From 95fadbd4022ec99f42ba78ec8a18a064903e8a7f Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Mon, 16 Jul 2007 17:37:21 +0200 Subject: [PATCH 01/44] Add basic Exa driver entry point validation. In exaDriverInit(), quickly check if the programmer forgot to set some mandadory driver hooks, in that case display a meaningful error message. --- exa/exa.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/exa/exa.c b/exa/exa.c index 3e8054da9..fc1f419bc 100644 --- a/exa/exa.c +++ b/exa/exa.c @@ -722,6 +722,48 @@ exaDriverAlloc(void) return xcalloc(1, sizeof(ExaDriverRec)); } +static Bool +exaDriverValidateEntryPoints (ExaDriverPtr pExaDriver) +{ + Bool res=TRUE ; + + if (!pExaDriver) + return FALSE ; + + if (!pExaDriver->memoryBase) { + LogMessage(X_ERROR, + "Exa: Exa::memoryBase member " + "must be assigned to a value different from zero\n") ; + res = FALSE ; + } + if (!pExaDriver->memorySize) { + LogMessage(X_ERROR, + "Exa: Exa::memorySize member must be different from zero\n") ; + res = FALSE ; + } + if (pExaDriver->offScreenBase > pExaDriver->memorySize) { + LogMessage(X_ERROR, + "Exa: Exa::ffscreenBase must be <= pExaDriver->memorySize member\n") ; + res = FALSE ; + } + if (!pExaDriver->PrepareSolid) { + LogMessage(X_ERROR, + "Exa: Exa::PrepareSolid member is required to be non NULL\n") ; + res = FALSE ; + } + if (!pExaDriver->PrepareCopy) { + LogMessage(X_ERROR, + "Exa: Exa::PrepareCopy member is required to be non NULL\n") ; + res = FALSE ; + } + if (!pExaDriver->WaitMarker) { + LogMessage(X_ERROR, + "Exa: Exa::WaitWarker member is required to be non NULL\n") ; + res = FALSE ; + } + return res ; +} + /** * @param pScreen screen being initialized * @param pScreenInfo EXA driver record @@ -806,6 +848,12 @@ exaDriverInit (ScreenPtr pScreen, { pScreenInfo->maxPitchPixels = pScreenInfo->maxX; } + if (!exaDriverValidateEntryPoints(pScreenInfo)) + { + LogMessage(X_ERROR, "Exa(%d): EXA driver entry points validation failed\n", + pScreen->myNum) ; + return FALSE ; + } #ifdef RENDER ps = GetPictureScreenIfSet(pScreen); From 50a64c84e1556ef7f8efcc7f8655e0c5e023ef4d Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Sat, 21 Jul 2007 12:08:39 +0200 Subject: [PATCH 02/44] initial commit of xv support work --- hw/kdrive/ephyr/Makefile.am | 27 +- hw/kdrive/ephyr/ephyr.h | 4 + hw/kdrive/ephyr/ephyrhostvideo.c | 234 ++++++++++++++++ hw/kdrive/ephyr/ephyrhostvideo.h | 139 ++++++++++ hw/kdrive/ephyr/ephyrlog.h | 67 +++++ hw/kdrive/ephyr/ephyrvideo.c | 448 +++++++++++++++++++++++++++++++ hw/kdrive/ephyr/hostx.c | 6 + hw/kdrive/ephyr/hostx.h | 3 + 8 files changed, 919 insertions(+), 9 deletions(-) create mode 100644 hw/kdrive/ephyr/ephyrhostvideo.c create mode 100644 hw/kdrive/ephyr/ephyrhostvideo.h create mode 100644 hw/kdrive/ephyr/ephyrlog.h create mode 100644 hw/kdrive/ephyr/ephyrvideo.c diff --git a/hw/kdrive/ephyr/Makefile.am b/hw/kdrive/ephyr/Makefile.am index cc3019fc7..193c26bd5 100644 --- a/hw/kdrive/ephyr/Makefile.am +++ b/hw/kdrive/ephyr/Makefile.am @@ -3,22 +3,29 @@ INCLUDES = \ @KDRIVE_CFLAGS@ \ -I$(srcdir)/../../../exa -noinst_LIBRARIES = libxephyr.a libxephyr-hostx.a +noinst_LIBRARIES = libxephyr-hostx.a libxephyr-hostxv.a libxephyr.a bin_PROGRAMS = Xephyr + +libxephyr_hostx_a_SOURCES = \ + hostx.c \ + hostx.h + +libxephyr_hostx_a_INCLUDES = @XEPHYR_INCS@ + +libxephyr_hostxv_a_SOURCES= \ + ephyrhostvideo.c \ + ephyrhostvideo.h + libxephyr_a_SOURCES = \ ephyr.c \ ephyr_draw.c \ + ephyrvideo.c \ os.c \ - hostx.h \ - ephyr.h - -libxephyr_hostx_a_SOURCES = \ - hostx.c \ - hostx.h - -libxephyr_hostx_a_INCLUDES = @XEPHYR_INCS@ + hostx.h \ + ephyr.h \ + ephyrlog.h Xephyr_SOURCES = \ ephyrinit.c @@ -26,6 +33,7 @@ Xephyr_SOURCES = \ Xephyr_LDADD = \ libxephyr.a \ libxephyr-hostx.a \ + libxephyr-hostxv.a \ ../../../exa/libexa.la \ @KDRIVE_LIBS@ \ @XEPHYR_LIBS@ @@ -33,6 +41,7 @@ Xephyr_LDADD = \ Xephyr_DEPENDENCIES = \ libxephyr.a \ libxephyr-hostx.a \ + libxephyr-hostxv.a \ @KDRIVE_LOCAL_LIBS@ relink: diff --git a/hw/kdrive/ephyr/ephyr.h b/hw/kdrive/ephyr/ephyr.h index 1c9b4f859..8ed7e23dd 100644 --- a/hw/kdrive/ephyr/ephyr.h +++ b/hw/kdrive/ephyr/ephyr.h @@ -194,4 +194,8 @@ ephyrDrawDisable(ScreenPtr pScreen); void ephyrDrawFini(ScreenPtr pScreen); +/*ephyvideo.c*/ + +Bool ephyrInitVideo(ScreenPtr pScreen) ; + #endif diff --git a/hw/kdrive/ephyr/ephyrhostvideo.c b/hw/kdrive/ephyr/ephyrhostvideo.c new file mode 100644 index 000000000..59a01bb20 --- /dev/null +++ b/hw/kdrive/ephyr/ephyrhostvideo.c @@ -0,0 +1,234 @@ +/* + * Xephyr - A kdrive X server thats runs in a host X window. + * Authored by Matthew Allum + * + * Copyright © 2007 OpenedHand Ltd + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of OpenedHand Ltd not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OpenedHand Ltd makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OpenedHand Ltd BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Authors: + * Dodji Seketeli + */ +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include + +#include "hostx.h" +#include "ephyrhostvideo.h" +#include "ephyrlog.h" + +#ifndef TRUE +#define TRUE 1 +#endif /*TRUE*/ + +#ifndef FALSE +#define FALSE 0 +#endif /*FALSE*/ + +struct _EphyrHostXVAdaptorArray { + XvAdaptorInfo *adaptors ; + unsigned int nb_adaptors ; +}; + +Bool +EphyrHostXVQueryAdaptors (EphyrHostXVAdaptorArray **a_adaptors) +{ + EphyrHostXVAdaptorArray *result=NULL ; + int ret=0 ; + Bool is_ok=FALSE ; + + EPHYR_RETURN_VAL_IF_FAIL (a_adaptors, FALSE) ; + + EPHYR_LOG ("enter\n") ; + + result = Xcalloc (sizeof (EphyrHostXVAdaptorArray)) ; + if (!result) + goto out ; + + ret = XvQueryAdaptors (hostx_get_display (), + DefaultRootWindow (hostx_get_display), + &result->nb_adaptors, + &result->adaptors) ; + if (ret != Success) { + EPHYR_LOG_ERROR ("failed to query host adaptors: %d\n", ret) ; + goto out ; + } + is_ok = TRUE ; + +out: + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +void +EphyrHostXVAdaptorArrayDelete (EphyrHostXVAdaptorArray *a_adaptors) +{ + if (!a_adaptors) + return ; + if (a_adaptors->adaptors) { + XvFreeAdaptorInfo (a_adaptors->adaptors) ; + a_adaptors->adaptors = NULL ; + a_adaptors->nb_adaptors = 0 ; + } + XFree (a_adaptors) ; +} + +int +EphyrHostXVAdaptorArrayGetSize (const EphyrHostXVAdaptorArray *a_this) +{ + EPHYR_RETURN_VAL_IF_FAIL (a_this, -1) ; + return a_this->nb_adaptors ; +} + +EphyrHostXVAdaptor* +EphyrHostXVAdaptorArrayAt (const EphyrHostXVAdaptorArray *a_this, + int a_index) +{ + EPHYR_RETURN_VAL_IF_FAIL (a_this, NULL) ; + + if (a_index >= a_this->nb_adaptors) + return NULL ; + return (EphyrHostXVAdaptor*)&a_this->adaptors[a_index] ; +} + +char +EphyrHostXVAdaptorGetType (const EphyrHostXVAdaptor *a_this) +{ + EPHYR_RETURN_VAL_IF_FAIL (a_this, -1) ; + return ((XvAdaptorInfo*)a_this)->type ; +} + +const char* +EphyrHostXVAdaptorGetName (const EphyrHostXVAdaptor *a_this) +{ + EPHYR_RETURN_VAL_IF_FAIL (a_this, NULL) ; + + return ((XvAdaptorInfo*)a_this)->name ; +} + +const EphyrHostVideoFormat* +EphyrHostXVAdaptorGetVideoFormats (const EphyrHostXVAdaptor *a_this, + int *a_nb_formats) +{ + EPHYR_RETURN_VAL_IF_FAIL (a_this, NULL) ; + + if (a_nb_formats) + *a_nb_formats = ((XvAdaptorInfo*)a_this)->num_formats ; + return (EphyrHostVideoFormat*) ((XvAdaptorInfo*)a_this)->formats ; +} + +int +EphyrHostXVAdaptorGetNbPorts (const EphyrHostXVAdaptor *a_this) +{ + EPHYR_RETURN_VAL_IF_FAIL (a_this, -1) ; + + return ((XvAdaptorInfo*)a_this)->num_ports ; +} + +int +EphyrHostXVAdaptorGetFirstPortID (const EphyrHostXVAdaptor *a_this) +{ + EPHYR_RETURN_VAL_IF_FAIL (a_this, -1) ; + + return ((XvAdaptorInfo*)a_this)->base_id ; +} + +Bool +EphyrHostXVQueryEncodings (int a_port_id, + EphyrHostEncoding **a_encodings, + unsigned int *a_num_encodings) +{ + int ret = 0 ; + EPHYR_RETURN_VAL_IF_FAIL (a_encodings && a_num_encodings, FALSE) ; + + ret = XvQueryEncodings (hostx_get_display (), + a_port_id, + a_num_encodings, + (XvEncodingInfo**)a_encodings) ; + if (ret == Success) + return TRUE ; + return FALSE ; +} + +void +EphyrHostEncodingsDelete (EphyrHostEncoding *a_encodings, + int a_num_encodings) +{ + int i=0 ; + + if (!a_encodings) + return ; + for (i=0; i < a_num_encodings; i++) { + if (a_encodings[i].name) { + xfree (a_encodings[i].name) ; + a_encodings[i].name = NULL ; + } + } + xfree (a_encodings) ; +} + +void +EphyrHostAttributesDelete (EphyrHostAttribute *a_attributes, + int a_num_attributes) +{ + int i=0 ; + + if (!a_attributes) + return ; + for (i=0; i < a_num_attributes; i++) { + if (a_attributes[i].name) { + xfree (a_attributes[i].name) ; + a_attributes[i].name = NULL ; + } + } + xfree (a_attributes) ; +} + +Bool +EphyrHostXVQueryPortAttributes (int a_port_id, + EphyrHostAttribute **a_attributes, + int *a_num_attributes) +{ + XvAttribute *attributes=NULL ; + int num_attributes=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_attributes && a_num_attributes, FALSE) ; + + attributes = XvQueryPortAttributes (hostx_get_display (), a_port_id, &num_attributes) ; + *a_attributes = (EphyrHostAttribute*)attributes ; + + return TRUE ; +} + +Bool +EphyrHostXVQueryImageFormats (int a_port_id, + EphyrHostImageFormat **a_formats, + int *a_num_format) +{ + XvImageFormatValues *result=NULL ; + + EPHYR_RETURN_VAL_IF_FAIL (a_formats && a_num_format, FALSE) ; + + result = XvListImageFormats (hostx_get_display (), a_port_id, a_num_format) ; + *a_formats = (EphyrHostImageFormat*) result ; + return TRUE ; + +} diff --git a/hw/kdrive/ephyr/ephyrhostvideo.h b/hw/kdrive/ephyr/ephyrhostvideo.h new file mode 100644 index 000000000..89c087c75 --- /dev/null +++ b/hw/kdrive/ephyr/ephyrhostvideo.h @@ -0,0 +1,139 @@ +/* + * Xephyr - A kdrive X server thats runs in a host X window. + * Authored by Matthew Allum + * + * Copyright © 2007 OpenedHand Ltd + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of OpenedHand Ltd not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OpenedHand Ltd makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OpenedHand Ltd BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Authors: + * Dodji Seketeli + */ +#ifndef __EPHYRHOSTVIDEO_H__ +#define __EPHYRHOSTVIDEO_H__ + + +typedef void* EphyrHostXVAdaptor ; +typedef struct _EphyrHostXVAdaptorArray EphyrHostXVAdaptorArray ; + +typedef struct _EphyrHostVideoFormat { + char depth ; + unsigned long visual_id; +} EphyrHostVideoFormat ; + +typedef struct _EphyrHostRational { + int numerator ; + int denominator ; +} EphyrHostRational; + +typedef struct _EphyrHostEncoding { + int id ; + char *name ; + unsigned short width, height ; + EphyrHostRational rate ; +} EphyrHostEncoding ; + +typedef struct _EphyrHostAttribute { + int flags; + int min_value; + int max_value; + char *name; +} EphyrHostAttribute ; + +typedef struct _EphyrHostImageFormat { + int id; /* Unique descriptor for the format */ + int type; /* XvRGB, XvYUV */ + int byte_order; /* LSBFirst, MSBFirst */ + char guid[16]; /* Globally Unique IDentifier */ + int bits_per_pixel; + int format; /* XvPacked, XvPlanar */ + int num_planes; + + /* for RGB formats only */ + int depth; + unsigned int red_mask; + unsigned int green_mask; + unsigned int blue_mask; + + /* for YUV formats only */ + unsigned int y_sample_bits; + unsigned int u_sample_bits; + unsigned int v_sample_bits; + unsigned int horz_y_period; + unsigned int horz_u_period; + unsigned int horz_v_period; + unsigned int vert_y_period; + unsigned int vert_u_period; + unsigned int vert_v_period; + char component_order[32]; /* eg. UYVY */ + int scanline_order; /* XvTopToBottom, XvBottomToTop */ +} EphyrHostImageFormat ; + +/* + * host adaptor array + */ +Bool EphyrHostXVQueryAdaptors (EphyrHostXVAdaptorArray **a_adaptors) ; +void EphyrHostXVAdaptorArrayDelete (EphyrHostXVAdaptorArray *a_adaptors) ; +int EphyrHostXVAdaptorArrayGetSize (const EphyrHostXVAdaptorArray *a_this) ; +EphyrHostXVAdaptor* EphyrHostXVAdaptorArrayAt (const EphyrHostXVAdaptorArray *a_this, + int a_index) ; + +/* + * host adaptor + */ + +char EphyrHostXVAdaptorGetType (const EphyrHostXVAdaptor *a_this) ; +const char* EphyrHostXVAdaptorGetName (const EphyrHostXVAdaptor *a_this) ; +const EphyrHostVideoFormat* EphyrHostXVAdaptorGetNbVideoFormats + (const EphyrHostXVAdaptor *a_this) ; +const EphyrHostVideoFormat* EphyrHostXVAdaptorGetVideoFormats + (const EphyrHostXVAdaptor *a_this, + int *a_nb_formats) ; +int EphyrHostXVAdaptorGetNbPorts (const EphyrHostXVAdaptor *a_this) ; +int EphyrHostXVAdaptorGetFirstPortID (const EphyrHostXVAdaptor *a_this) ; + +/* + * encoding + */ +Bool EphyrHostXVQueryEncodings (int a_port_id, + EphyrHostEncoding **a_encodings, + unsigned int *a_num_encodings) ; + +void EphyrHostEncodingsDelete (EphyrHostEncoding *a_encodings, + int a_num_encodings) ; + +/* + * attribute + */ +Bool EphyrHostXVQueryPortAttributes (int a_port_id, + EphyrHostAttribute **a_attributes, + int *a_num_attributes) ; + +void EphyrHostAttributesDelete (EphyrHostAttribute *a_attributes, + int a_num_attributes) ; +/* + * image format + */ + +Bool EphyrHostXVQueryImageFormats (int a_port_id, + EphyrHostImageFormat **a_formats, + int *a_num_format) ; + +#endif /*__EPHYRHOSTVIDEO_H__*/ + diff --git a/hw/kdrive/ephyr/ephyrlog.h b/hw/kdrive/ephyr/ephyrlog.h new file mode 100644 index 000000000..4c6435edd --- /dev/null +++ b/hw/kdrive/ephyr/ephyrlog.h @@ -0,0 +1,67 @@ +/* + * Xephyr - A kdrive X server thats runs in a host X window. + * Authored by Matthew Allum + * + * Copyright © 2007 OpenedHand Ltd + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of OpenedHand Ltd not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OpenedHand Ltd makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OpenedHand Ltd BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Authors: + * Dodji Seketeli + */ +#ifndef __EPHYRLOG_H__ +#define __EPHYRLOG_H__ + +#include +#include "os.h" + +#ifdef NDEBUG +/*we are not in debug mode*/ +#define EPHYR_LOG +#define EPHYR_LOG_ERROR +#endif /*NDEBUG*/ + +#define ERROR_LOG_LEVEL 3 +#define INFO_LOG_LEVEL 4 + +#ifndef EPHYR_LOG +#define EPHYR_LOG(...) \ +LogMessageVerb(X_NOTICE, INFO_LOG_LEVEL, "in %s:%d:%s: ",\ + __FILE__, __LINE__, __func__) ; \ +LogMessageVerb(X_NOTICE, INFO_LOG_LEVEL, __VA_ARGS__) +#endif /*nomadik_log*/ + +#ifndef EPHYR_LOG_ERROR +#define EPHYR_LOG_ERROR(...) \ +LogMessageVerb(X_NOTICE, ERROR_LOG_LEVEL, "Error:in %s:%d:%s: ",\ + __FILE__, __LINE__, __func__) ; \ +LogMessageVerb(X_NOTICE, ERROR_LOG_LEVEL, __VA_ARGS__) +#endif /*EPHYR_LOG_ERROR*/ + +#ifndef EPHYR_RETURN_IF_FAIL +#define EPHYR_RETURN_IF_FAIL(cond) \ +if (!(cond)) {EPHYR_LOG_ERROR("condition %s failed\n", #cond);return;} +#endif /*nomadik_return_if_fail*/ + +#ifndef EPHYR_RETURN_VAL_IF_FAIL +#define EPHYR_RETURN_VAL_IF_FAIL(cond,val) \ +if (!(cond)) {EPHYR_LOG_ERROR("condition %s failed\n", #cond);return val;} +#endif /*nomadik_return_val_if_fail*/ + +#endif /*__EPHYRLOG_H__*/ diff --git a/hw/kdrive/ephyr/ephyrvideo.c b/hw/kdrive/ephyr/ephyrvideo.c new file mode 100644 index 000000000..6be177b41 --- /dev/null +++ b/hw/kdrive/ephyr/ephyrvideo.c @@ -0,0 +1,448 @@ +/* + * Xephyr - A kdrive X server thats runs in a host X window. + * Authored by Matthew Allum + * + * Copyright © 2007 OpenedHand Ltd + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of OpenedHand Ltd not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OpenedHand Ltd makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OpenedHand Ltd BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Authors: + * Dodji Seketeli + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include "ephyrlog.h" +#include "kdrive.h" +#include "kxv.h" +#include "ephyr.h" +#include "hostx.h" +#include "ephyrhostvideo.h" + +struct _EphyrXVPriv { + EphyrHostXVAdaptorArray *host_adaptors ; + KdVideoAdaptorPtr adaptors ; + int num_adaptors ; +}; + +typedef struct _EphyrXVPriv EphyrXVPriv ; + +static EphyrXVPriv* EphyrXVPrivNew (void) ; +static void EphyrXVPrivDelete (EphyrXVPriv *a_this) ; +static Bool EphyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) ; +static Bool EphyrXVPrivSetAdaptorsHooks (EphyrXVPriv *a_this) ; + +static void EphyrStopVideo (KdScreenInfo *a_info, + pointer a_xv_priv, + Bool a_exit); + +static int EphyrSetPortAttribute (KdScreenInfo *a_info, + Atom a_attr_name, + int a_attr_value, + pointer a_xv_priv); + +static int EphyrGetPortAttribute (KdScreenInfo *a_screen_info, + Atom a_attr_name, + int *a_attr_value, + pointer a_xv_priv); + +static void EphyrQueryBestSize (KdScreenInfo *a_info, + Bool a_motion, + short a_src_w, + short a_src_h, + short a_drw_w, + short a_drw_h, + unsigned int *a_prefered_w, + unsigned int *a_prefered_h, + pointer a_xv_priv); + +static int EphyrPutImage (KdScreenInfo *a_info, + DrawablePtr a_drawable, + short a_src_x, + short a_src_y, + short a_drw_x, + short a_drw_y, + short a_src_w, + short a_src_h, + short a_drw_w, + short a_drw_h, + int a_id, + unsigned char *a_buf, + short a_width, + short a_height, + Bool a_sync, + RegionPtr a_clipping_region, + pointer a_xv_priv); + +static int EphyrQueryImageAttributes (KdScreenInfo *a_info, + int a_id, + unsigned short *a_w, + unsigned short *a_h, + int *a_pitches, + int *a_offsets); + +Bool +ephyrInitVideo (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + EphyrXVPriv *xv_priv = NULL ; + KdVideoAdaptorPtr *adaptors, *newAdaptors = NULL; + KdVideoAdaptorPtr newAdaptor = NULL; + int num_adaptors=0; + + EPHYR_LOG ("enter\n") ; + + if (screen->fb[0].bitsPerPixel == 8) { + EPHYR_LOG_ERROR ("8 bits depth not supported\n") ; + return FALSE ; + } + + xv_priv = EphyrXVPrivNew () ; + if (!xv_priv) { + EPHYR_LOG_ERROR ("failed to create xv_priv\n") ; + return FALSE ; + } + + /* + * TODO: + * queried host adaptors, now get xv_priv->adaptors and. + * add it to those already existing. + */ + num_adaptors = KdXVListGenericAdaptors (screen, &adaptors); + + if (newAdaptor) { + if (!num_adaptors) { + num_adaptors = 1; + adaptors = &newAdaptor; + } else { + newAdaptors = xalloc ((num_adaptors + 1) * sizeof(KdVideoAdaptorPtr*)); + if (newAdaptors) { + memcpy (newAdaptors, + adaptors, + num_adaptors * sizeof(KdVideoAdaptorPtr)); + newAdaptors[num_adaptors] = newAdaptor; + adaptors = newAdaptors; + num_adaptors++; + } + } + } + + if (num_adaptors) { + KdXVScreenInit (pScreen, adaptors, num_adaptors); + } else { + EPHYR_LOG_ERROR ("XVideo not initialised\n") ; + } + + if (newAdaptors) + xfree (newAdaptors); + return TRUE; +} + +static EphyrXVPriv* +EphyrXVPrivNew (void) +{ + EphyrXVPriv *xv_priv=NULL ; + + EPHYR_LOG ("enter\n") ; + + xv_priv = xcalloc (1, sizeof (EphyrXVPriv)) ; + if (!xv_priv) { + EPHYR_LOG_ERROR ("failed to create EphyrXVPriv\n") ; + goto error ; + } + if (!EphyrXVPrivQueryHostAdaptors (xv_priv)) { + EPHYR_LOG_ERROR ("failed to query the host x for xv properties\n") ; + goto error ; + } + if (EphyrXVPrivSetAdaptorsHooks (xv_priv)) { + EPHYR_LOG_ERROR ("failed to set xv_priv hooks\n") ; + goto error ; + } + + EPHYR_LOG ("leave\n") ; + return xv_priv ; + +error: + if (xv_priv) { + EphyrXVPrivDelete (xv_priv) ; + xv_priv = NULL ; + } + return NULL ; +} + +static void +EphyrXVPrivDelete (EphyrXVPriv *a_this) +{ + EPHYR_LOG ("enter\n") ; + + if (!a_this) + return ; + if (a_this->host_adaptors) { + EphyrHostXVAdaptorArrayDelete (a_this->host_adaptors) ; + a_this->host_adaptors = NULL ; + } + if (a_this->adaptors) { + xfree (a_this->adaptors) ; + a_this->adaptors = NULL ; + } + xfree (a_this) ; + EPHYR_LOG ("leave\n") ; +} + +static KdVideoEncodingPtr +videoEncodingDup (EphyrHostEncoding *a_encodings, + int a_num_encodings) +{ + KdVideoEncodingPtr result = NULL ; + int i=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_encodings && a_num_encodings, NULL) ; + + result = xcalloc (a_num_encodings, sizeof (KdVideoEncodingRec)) ; + for (i=0 ; i < a_num_encodings; i++) { + result[i].id = a_encodings[i].id ; + result[i].name = strdup (a_encodings[i].name) ; + result[i].width = a_encodings[i].width ; + result[i].height = a_encodings[i].height ; + result[i].rate.numerator = a_encodings[i].rate.numerator ; + result[i].rate.denominator = a_encodings[i].rate.denominator ; + } + return result ; +} + +static KdAttributePtr +portAttributesDup (EphyrHostAttribute *a_encodings, + int a_num_encodings) +{ + int i=0 ; + KdAttributePtr result=NULL ; + + EPHYR_RETURN_VAL_IF_FAIL (a_encodings && a_num_encodings, NULL) ; + + result = xcalloc (a_num_encodings, sizeof (KdAttributeRec)) ; + if (!result) { + EPHYR_LOG_ERROR ("failed to allocate attributes\n") ; + return NULL ; + } + for (i=0; i < a_num_encodings; i++) { + result[i].flags = a_encodings[i].flags ; + result[i].min_value = a_encodings[i].min_value ; + result[i].max_value = a_encodings[i].max_value ; + result[i].name = strdup (a_encodings[i].name) ; + } + return result ; +} + +static Bool +EphyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) +{ + EphyrHostXVAdaptor *cur_host_adaptor=NULL ; + EphyrHostVideoFormat *video_formats=NULL ; + EphyrHostEncoding *encodings=NULL ; + EphyrHostAttribute *attributes=NULL ; + EphyrHostImageFormat *image_formats=NULL ; + int num_video_formats=0, base_port_id=0, num_attributes=0, num_formats=0, res=0, i=0 ; + unsigned num_encodings=0 ; + Bool is_ok = FALSE ; + + EPHYR_RETURN_VAL_IF_FAIL (a_this, FALSE) ; + + if (!EphyrHostXVQueryAdaptors (&a_this->host_adaptors) || !a_this->host_adaptors) { + EPHYR_LOG_ERROR ("failed to query host adaptors: %d\n", res) ; + goto out ; + } + a_this->num_adaptors = EphyrHostXVAdaptorArrayGetSize (a_this->host_adaptors) ; + if (a_this->num_adaptors < 0) { + EPHYR_LOG_ERROR ("failed to get number of host adaptors\n") ; + goto out ; + } + /* + * copy what we can from adaptors into a_this->adaptors + */ + a_this->adaptors = xcalloc (a_this->num_adaptors, sizeof (KdVideoAdaptorRec)) ; + if (!a_this->host_adaptors) { + EPHYR_LOG_ERROR ("failed to create internal adaptors\n") ; + goto out ; + } + for (i=0; i < a_this->num_adaptors; i++) { + int j=0 ; + cur_host_adaptor = EphyrHostXVAdaptorArrayAt (a_this->host_adaptors, i) ; + if (!cur_host_adaptor) + continue ; + a_this->adaptors[i].type = EphyrHostXVAdaptorGetType (cur_host_adaptor) ; + a_this->adaptors[i].flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; + if (EphyrHostXVAdaptorGetName (cur_host_adaptor)) + a_this->adaptors[i].name = + strdup (EphyrHostXVAdaptorGetName (cur_host_adaptor)) ; + a_this->adaptors[i].name = "Xephyr Video Overlay"; + base_port_id = EphyrHostXVAdaptorGetFirstPortID (cur_host_adaptor) ; + if (base_port_id < 0) { + EPHYR_LOG_ERROR ("failed to get port id for adaptor %d\n", i) ; + continue ; + } + if (!EphyrHostXVQueryEncodings (base_port_id, &encodings, &num_encodings)) { + EPHYR_LOG_ERROR ("failed to get encodings for port port id %d, adaptors %d\n", + base_port_id, i) ; + continue ; + } + a_this->adaptors[i].nEncodings = num_encodings ; + a_this->adaptors[i].pEncodings = videoEncodingDup (encodings, num_encodings) ; + video_formats = (EphyrHostVideoFormat*) + EphyrHostXVAdaptorGetVideoFormats (cur_host_adaptor, &num_video_formats); + a_this->adaptors[i].pFormats = (KdVideoFormatPtr) video_formats ; + a_this->adaptors[i].nFormats = num_video_formats ; + a_this->adaptors[i].nPorts = EphyrHostXVAdaptorGetNbPorts (cur_host_adaptor) ; + a_this->adaptors[i].pPortPrivates = xcalloc (a_this->adaptors[i].nPorts, + sizeof (DevUnion)) ; + for (j=0; j < a_this->adaptors[i].nPorts; j++) { + a_this->adaptors[i].pPortPrivates[j].ptr = a_this ; + } + if (!EphyrHostXVQueryPortAttributes (base_port_id, + &attributes, + &num_attributes)) { + EPHYR_LOG_ERROR ("failed to get port attribute for adaptor %d\n", i) ; + continue ; + } + a_this->adaptors[i].pAttributes = portAttributesDup (attributes, num_attributes); + a_this->adaptors[i].nAttributes = num_attributes ; + if (!EphyrHostXVQueryImageFormats (base_port_id, &image_formats, &num_formats)) { + EPHYR_LOG_ERROR ("failed to get image formats for adaptor %d\n", i) ; + continue ; + } + a_this->adaptors[i].pImages = (KdImagePtr) image_formats ; + } + is_ok = TRUE ; + +out: + if (encodings) { + EphyrHostEncodingsDelete (encodings, num_encodings) ; + encodings = NULL ; + } + if (attributes) { + EphyrHostAttributesDelete (attributes, num_attributes) ; + attributes = NULL ; + } + if (image_formats) { + xfree (image_formats) ; + image_formats = NULL ; + } + return is_ok ; +} + +static Bool +EphyrXVPrivSetAdaptorsHooks (EphyrXVPriv *a_this) +{ + int i=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_this, FALSE) ; + + for (i=0; i < a_this->num_adaptors; i++) { + a_this->adaptors[i].StopVideo = EphyrStopVideo ; + a_this->adaptors[i].SetPortAttribute = EphyrSetPortAttribute ; + a_this->adaptors[i].GetPortAttribute = EphyrGetPortAttribute ; + a_this->adaptors[i].QueryBestSize = EphyrQueryBestSize ; + a_this->adaptors[i].PutImage = EphyrPutImage; + a_this->adaptors[i].QueryImageAttributes = EphyrQueryImageAttributes ; + } + return TRUE ; +} + +static void +EphyrStopVideo (KdScreenInfo *a_info, pointer a_xv_priv, Bool a_exit) +{ + EPHYR_LOG ("enter\n") ; + EPHYR_LOG ("leave\n") ; +} + +static int +EphyrSetPortAttribute (KdScreenInfo *a_info, + Atom a_attr_name, + int a_attr_value, + pointer a_xv_priv) +{ + EPHYR_LOG ("enter\n") ; + return 0 ; + EPHYR_LOG ("leave\n") ; +} + +static int +EphyrGetPortAttribute (KdScreenInfo *a_screen_info, + Atom a_attr_name, + int *a_attr_value, + pointer a_xv_priv) +{ + EPHYR_LOG ("enter\n") ; + return 0 ; + EPHYR_LOG ("leave\n") ; +} + +static void +EphyrQueryBestSize (KdScreenInfo *a_info, + Bool a_motion, + short a_src_w, + short a_src_h, + short a_drw_w, + short a_drw_h, + unsigned int *a_prefered_w, + unsigned int *a_prefered_h, + pointer a_xv_priv) +{ +} + +static int +EphyrPutImage (KdScreenInfo *a_info, + DrawablePtr a_drawable, + short a_src_x, + short a_src_y, + short a_drw_x, + short a_drw_y, + short a_src_w, + short a_src_h, + short a_drw_w, + short a_drw_h, + int a_id, + unsigned char *a_buf, + short a_width, + short a_height, + Bool a_sync, + RegionPtr a_clipping_region, + pointer a_xv_priv) +{ + EPHYR_LOG ("enter\n") ; + return 0 ; + EPHYR_LOG ("leave\n") ; +} + +static int +EphyrQueryImageAttributes (KdScreenInfo *a_info, + int a_id, + unsigned short *a_w, + unsigned short *a_h, + int *a_pitches, + int *a_offsets) +{ + EPHYR_LOG ("enter\n") ; + return 0 ; + EPHYR_LOG ("leave\n") ; +} + diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c index 81678d927..11cfe26fb 100644 --- a/hw/kdrive/ephyr/hostx.c +++ b/hw/kdrive/ephyr/hostx.c @@ -956,3 +956,9 @@ hostx_get_event(EphyrHostXEvent *ev) return 0; } +void* +hostx_get_display(void) +{ + return HostX.dpy ; +} + diff --git a/hw/kdrive/ephyr/hostx.h b/hw/kdrive/ephyr/hostx.h index 93765d096..dc8eb99e9 100644 --- a/hw/kdrive/ephyr/hostx.h +++ b/hw/kdrive/ephyr/hostx.h @@ -172,4 +172,7 @@ hostx_load_keymap(void); int hostx_get_event(EphyrHostXEvent *ev); +void* +hostx_get_display(void) ; + #endif From 8426eb2433f964ea19848f24dc99eb4588d10d1a Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Sat, 21 Jul 2007 17:55:12 +0200 Subject: [PATCH 03/44] link and init xv --- configure.ac | 5 +- hw/kdrive/ephyr/ephyr.c | 41 ++++++++-------- hw/kdrive/ephyr/ephyrvideo.c | 90 ++++++++++++++++++++++-------------- 3 files changed, 80 insertions(+), 56 deletions(-) diff --git a/configure.ac b/configure.ac index 5c5ff7d07..a7f1e8493 100644 --- a/configure.ac +++ b/configure.ac @@ -723,6 +723,7 @@ if test "x$XV" = xyes; then AC_DEFINE(XV, 1, [Support Xv extension]) AC_DEFINE(XvExtension, 1, [Build Xv extension]) REQUIRED_MODULES="$REQUIRED_MODULES videoproto" + PKG_CHECK_MODULES(XV, [xv >= 0.22]) else XVMC=no fi @@ -1860,9 +1861,9 @@ if test "$KDRIVE" = yes; then KDRIVE_OS_INC='-I$(top_srcdir)/hw/kdrive/linux' KDRIVE_INCS="$KDRIVE_PURE_INCS $KDRIVE_OS_INC" - KDRIVE_CFLAGS="$XSERVER_CFLAGS -DHAVE_KDRIVE_CONFIG_H $TSLIB_CFLAGS" + KDRIVE_CFLAGS="$XSERVER_CFLAGS -DHAVE_KDRIVE_CONFIG_H $TSLIB_CFLAGS $XV_CFLAGS" - KDRIVE_PURE_LIBS="$FIXES_LIB $XEXT_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_SHADOW_LIB $MIEXT_DAMAGE_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $XPSTUBS_LIB" + KDRIVE_PURE_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $XV_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $XPSTUBS_LIB $OS_LIB" KDRIVE_LIB='$(top_builddir)/hw/kdrive/src/libkdrive.a' case $host_os in *linux*) diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c index c5cb21a64..2cb7d0bd6 100644 --- a/hw/kdrive/ephyr/ephyr.c +++ b/hw/kdrive/ephyr/ephyr.c @@ -23,11 +23,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* TODO: - * - * o Support multiple screens, shouldn't be hard just alot of rejigging. - */ - #ifdef HAVE_CONFIG_H #include #endif @@ -35,6 +30,7 @@ #include "inputstr.h" #include "scrnintstr.h" +#include "ephyrlog.h" extern int KdTsPhyScreen; KdKeyboardInfo *ephyrKbd; @@ -209,7 +205,7 @@ ephyrMapFramebuffer (KdScreenInfo *screen) KdPointerMatrix m; int buffer_height; - EPHYR_DBG("screen->width: %d, screen->height: %d index=%d", + EPHYR_LOG("screen->width: %d, screen->height: %d index=%d", screen->width, screen->height, screen->mynum); KdComputePointerMatrix (&m, scrpriv->randr, screen->width, screen->height); @@ -245,7 +241,7 @@ ephyrMapFramebuffer (KdScreenInfo *screen) /* Rotated/Reflected so we need to use shadow fb */ scrpriv->shadow = TRUE; - EPHYR_DBG("allocing shadow"); + EPHYR_LOG("allocing shadow"); KdShadowFbAlloc (screen, 0, scrpriv->randr & (RR_Rotate_90|RR_Rotate_270)); @@ -296,7 +292,7 @@ ephyrShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf) KdScreenPriv(pScreen); KdScreenInfo *screen = pScreenPriv->screen; - EPHYR_DBG("slow paint"); + EPHYR_LOG("slow paint"); /* FIXME: Slow Rotated/Reflected updates could be much * much faster efficiently updating via tranforming @@ -410,7 +406,7 @@ ephyrRandRGetInfo (ScreenPtr pScreen, Rotation *rotations) Rotation randr; int n = 0; - EPHYR_DBG("mark"); + EPHYR_LOG("mark"); struct { int width, height; } sizes[] = { @@ -563,7 +559,7 @@ ephyrRandRSetConfig (ScreenPtr pScreen, return TRUE; bail4: - EPHYR_DBG("bailed"); + EPHYR_LOG("bailed"); ephyrUnmapFramebuffer (screen); *scrpriv = oldscr; @@ -606,10 +602,17 @@ ephyrInitScreen (ScreenPtr pScreen) KdScreenPriv(pScreen); KdScreenInfo *screen = pScreenPriv->screen; - EPHYR_DBG ("pScreen->myNum:%d\n", pScreen->myNum) ; + EPHYR_LOG ("pScreen->myNum:%d\n", pScreen->myNum) ; hostx_set_screen_number (screen, pScreen->myNum); hostx_set_win_title (screen, "(ctrl+shift grabs mouse and keyboard)") ; pScreen->CreateColormap = ephyrCreateColormap; +#ifdef XV + if (!ephyrInitVideo (pScreen)) { + EPHYR_LOG_ERROR ("failed to initialize xvideo\n") ; + } else { + EPHYR_LOG_ERROR ("initialized xvideo okay\n") ; + } +#endif /*XV*/ return TRUE; } @@ -637,7 +640,7 @@ ephyrCreateResources (ScreenPtr pScreen) KdScreenInfo *screen = pScreenPriv->screen; EphyrScrPriv *scrpriv = screen->driver; - EPHYR_DBG("mark pScreen=%p mynum=%d shadow=%d", + EPHYR_LOG("mark pScreen=%p mynum=%d shadow=%d", pScreen, pScreen->myNum, scrpriv->shadow); if (scrpriv->shadow) @@ -809,20 +812,20 @@ ephyrPoll(void) case EPHYR_EV_MOUSE_MOTION: if (!ephyrMouse || !((EphyrPointerPrivate *)ephyrMouse->driverPrivate)->enabled) { - EPHYR_DBG ("skipping mouse motion:%d\n", ephyrCurScreen) ; + EPHYR_LOG ("skipping mouse motion:%d\n", ephyrCurScreen) ; continue; } { if (ephyrCurScreen != ev.data.mouse_motion.screen) { - EPHYR_DBG ("warping mouse cursor:%d\n", ephyrCurScreen) ; + EPHYR_LOG ("warping mouse cursor:%d\n", ephyrCurScreen) ; ephyrWarpCursor(screenInfo.screens[ev.data.mouse_motion.screen], ev.data.mouse_motion.x, ev.data.mouse_motion.y ); } else { - EPHYR_DBG ("enqueuing mouse motion:%d\n", ephyrCurScreen) ; + EPHYR_LOG ("enqueuing mouse motion:%d\n", ephyrCurScreen) ; KdEnqueuePointerEvent(ephyrMouse, mouseState, ev.data.mouse_motion.x, ev.data.mouse_motion.y, @@ -834,10 +837,10 @@ ephyrPoll(void) case EPHYR_EV_MOUSE_PRESS: if (!ephyrMouse || !((EphyrPointerPrivate *)ephyrMouse->driverPrivate)->enabled) { - EPHYR_DBG ("skipping mouse press:%d\n", ephyrCurScreen) ; + EPHYR_LOG ("skipping mouse press:%d\n", ephyrCurScreen) ; continue; } - EPHYR_DBG ("enqueuing mouse press:%d\n", ephyrCurScreen) ; + EPHYR_LOG ("enqueuing mouse press:%d\n", ephyrCurScreen) ; ephyrUpdateModifierState(ev.key_state); mouseState |= ev.data.mouse_down.button_num; KdEnqueuePointerEvent(ephyrMouse, mouseState|KD_MOUSE_DELTA, 0, 0, 0); @@ -849,7 +852,7 @@ ephyrPoll(void) continue; ephyrUpdateModifierState(ev.key_state); mouseState &= ~ev.data.mouse_up.button_num; - EPHYR_DBG ("enqueuing mouse release:%d\n", ephyrCurScreen) ; + EPHYR_LOG ("enqueuing mouse release:%d\n", ephyrCurScreen) ; KdEnqueuePointerEvent(ephyrMouse, mouseState|KD_MOUSE_DELTA, 0, 0, 0); break; @@ -886,7 +889,7 @@ ephyrGetColors (ScreenPtr pScreen, int fb, int n, xColorItem *pdefs) { /* XXX Not sure if this is right */ - EPHYR_DBG("mark"); + EPHYR_LOG("mark"); while (n--) { diff --git a/hw/kdrive/ephyr/ephyrvideo.c b/hw/kdrive/ephyr/ephyrvideo.c index 6be177b41..d80dab320 100644 --- a/hw/kdrive/ephyr/ephyrvideo.c +++ b/hw/kdrive/ephyr/ephyrvideo.c @@ -50,6 +50,8 @@ static EphyrXVPriv* EphyrXVPrivNew (void) ; static void EphyrXVPrivDelete (EphyrXVPriv *a_this) ; static Bool EphyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) ; static Bool EphyrXVPrivSetAdaptorsHooks (EphyrXVPriv *a_this) ; +static Bool EphyrXVPrivRegisterAdaptors (EphyrXVPriv *a_this, + ScreenPtr a_screen) ; static void EphyrStopVideo (KdScreenInfo *a_info, pointer a_xv_priv, @@ -106,9 +108,6 @@ ephyrInitVideo (ScreenPtr pScreen) KdScreenPriv(pScreen); KdScreenInfo *screen = pScreenPriv->screen; EphyrXVPriv *xv_priv = NULL ; - KdVideoAdaptorPtr *adaptors, *newAdaptors = NULL; - KdVideoAdaptorPtr newAdaptor = NULL; - int num_adaptors=0; EPHYR_LOG ("enter\n") ; @@ -123,39 +122,11 @@ ephyrInitVideo (ScreenPtr pScreen) return FALSE ; } - /* - * TODO: - * queried host adaptors, now get xv_priv->adaptors and. - * add it to those already existing. - */ - num_adaptors = KdXVListGenericAdaptors (screen, &adaptors); - - if (newAdaptor) { - if (!num_adaptors) { - num_adaptors = 1; - adaptors = &newAdaptor; - } else { - newAdaptors = xalloc ((num_adaptors + 1) * sizeof(KdVideoAdaptorPtr*)); - if (newAdaptors) { - memcpy (newAdaptors, - adaptors, - num_adaptors * sizeof(KdVideoAdaptorPtr)); - newAdaptors[num_adaptors] = newAdaptor; - adaptors = newAdaptors; - num_adaptors++; - } - } + if (EphyrXVPrivRegisterAdaptors (xv_priv, pScreen)) { + EPHYR_LOG_ERROR ("failed to register adaptors\n") ; + return FALSE ; } - - if (num_adaptors) { - KdXVScreenInit (pScreen, adaptors, num_adaptors); - } else { - EPHYR_LOG_ERROR ("XVideo not initialised\n") ; - } - - if (newAdaptors) - xfree (newAdaptors); - return TRUE; + return TRUE ; } static EphyrXVPriv* @@ -267,6 +238,8 @@ EphyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) EPHYR_RETURN_VAL_IF_FAIL (a_this, FALSE) ; + EPHYR_LOG ("enter\n") ; + if (!EphyrHostXVQueryAdaptors (&a_this->host_adaptors) || !a_this->host_adaptors) { EPHYR_LOG_ERROR ("failed to query host adaptors: %d\n", res) ; goto out ; @@ -346,6 +319,7 @@ out: xfree (image_formats) ; image_formats = NULL ; } + EPHYR_LOG ("leave\n") ; return is_ok ; } @@ -356,6 +330,8 @@ EphyrXVPrivSetAdaptorsHooks (EphyrXVPriv *a_this) EPHYR_RETURN_VAL_IF_FAIL (a_this, FALSE) ; + EPHYR_LOG ("enter\n") ; + for (i=0; i < a_this->num_adaptors; i++) { a_this->adaptors[i].StopVideo = EphyrStopVideo ; a_this->adaptors[i].SetPortAttribute = EphyrSetPortAttribute ; @@ -364,9 +340,53 @@ EphyrXVPrivSetAdaptorsHooks (EphyrXVPriv *a_this) a_this->adaptors[i].PutImage = EphyrPutImage; a_this->adaptors[i].QueryImageAttributes = EphyrQueryImageAttributes ; } + EPHYR_LOG ("leave\n") ; return TRUE ; } +static Bool +EphyrXVPrivRegisterAdaptors (EphyrXVPriv *a_this, + ScreenPtr a_screen) +{ + KdScreenPriv(a_screen); + KdScreenInfo *screen = pScreenPriv->screen; + Bool is_ok = FALSE ; + KdVideoAdaptorPtr *adaptors=NULL, *registered_adaptors=NULL ; + int num_registered_adaptors=0, i=0, num_adaptors=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_this && a_screen, FALSE) ; + + EPHYR_LOG ("enter\n") ; + + if (!a_this->num_adaptors) + goto out ; + num_registered_adaptors = KdXVListGenericAdaptors (screen, ®istered_adaptors); + num_adaptors = num_registered_adaptors + a_this->num_adaptors ; + adaptors = xcalloc (num_adaptors, sizeof (KdVideoAdaptorPtr)) ; + if (!adaptors) { + EPHYR_LOG_ERROR ("failed to allocate adaptors tab\n") ; + goto out ; + } + memmove (adaptors, registered_adaptors, num_registered_adaptors) ; + for (i=0 ; i < a_this->num_adaptors; i++) { + *(adaptors + num_registered_adaptors + i) = &a_this->adaptors[i] ; + } + KdXVScreenInit (a_screen, adaptors, num_adaptors); + is_ok = TRUE ; + +out: + if (registered_adaptors) { + xfree (registered_adaptors) ; + registered_adaptors = NULL ; + } + if (adaptors) { + xfree (adaptors) ; + adaptors=NULL ; + } + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + static void EphyrStopVideo (KdScreenInfo *a_info, pointer a_xv_priv, Bool a_exit) { From 50ff2377cac50ae25218be5b30612fb8bf6046a6 Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Sat, 21 Jul 2007 18:20:59 +0200 Subject: [PATCH 04/44] add -verbosity option to command line --- hw/kdrive/ephyr/ephyrinit.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/hw/kdrive/ephyr/ephyrinit.c b/hw/kdrive/ephyr/ephyrinit.c index 687460952..c8fbdfff5 100644 --- a/hw/kdrive/ephyr/ephyrinit.c +++ b/hw/kdrive/ephyr/ephyrinit.c @@ -27,6 +27,7 @@ #include #endif #include "ephyr.h" +#include "ephyrlog.h" extern Window EphyrPreExistingHostWin; extern Bool EphyrWantGrayScale; @@ -92,11 +93,12 @@ ddxUseMsg (void) KdUseMsg(); ErrorF("\nXephyr Option Usage:\n"); - ErrorF("-parent XID Use existing window as Xephyr root win\n"); - ErrorF("-host-cursor Re-use exisiting X host server cursor\n"); - ErrorF("-fullscreen Attempt to run Xephyr fullscreen\n"); - ErrorF("-grayscale Simulate 8bit grayscale\n"); - ErrorF("-fakexa Simulate acceleration using software rendering\n"); + ErrorF("-parent Use existing window as Xephyr root win\n"); + ErrorF("-host-cursor Re-use exisiting X host server cursor\n"); + ErrorF("-fullscreen Attempt to run Xephyr fullscreen\n"); + ErrorF("-grayscale Simulate 8bit grayscale\n"); + ErrorF("-fakexa Simulate acceleration using software rendering\n"); + ErrorF("-verbosity Set log verbosity level\n"); ErrorF("\n"); exit(1); @@ -182,6 +184,21 @@ ddxProcessArgument (int argc, char **argv, int i) ephyrFuncs.finiAccel = ephyrDrawFini; return 1; } + else if (!strcmp (argv[i], "-verbosity")) + { + if(i+1 < argc && argv[i+1][0] != '-') + { + int verbosity=atoi (argv[i+1]) ; + LogSetParameter (XLOG_VERBOSITY, verbosity) ; + EPHYR_LOG ("set verbosiry to %d\n", verbosity) ; + return 2 ; + } + else + { + UseMsg() ; + exit(1) ; + } + } else if (argv[i][0] == ':') { hostx_set_display_name(argv[i]); From 1e8f8b36a56a884092ee01a0bb3f40436e30fa42 Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Sat, 21 Jul 2007 18:22:20 +0200 Subject: [PATCH 05/44] works with no adaptors Debug the early code to make work when the host has no video adaptors --- hw/kdrive/ephyr/ephyrhostvideo.c | 2 +- hw/kdrive/ephyr/ephyrvideo.c | 22 +++++++++++++--------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/hw/kdrive/ephyr/ephyrhostvideo.c b/hw/kdrive/ephyr/ephyrhostvideo.c index 59a01bb20..d86f9761c 100644 --- a/hw/kdrive/ephyr/ephyrhostvideo.c +++ b/hw/kdrive/ephyr/ephyrhostvideo.c @@ -64,7 +64,7 @@ EphyrHostXVQueryAdaptors (EphyrHostXVAdaptorArray **a_adaptors) goto out ; ret = XvQueryAdaptors (hostx_get_display (), - DefaultRootWindow (hostx_get_display), + DefaultRootWindow (hostx_get_display ()), &result->nb_adaptors, &result->adaptors) ; if (ret != Success) { diff --git a/hw/kdrive/ephyr/ephyrvideo.c b/hw/kdrive/ephyr/ephyrvideo.c index d80dab320..c87af19ba 100644 --- a/hw/kdrive/ephyr/ephyrvideo.c +++ b/hw/kdrive/ephyr/ephyrvideo.c @@ -145,7 +145,7 @@ EphyrXVPrivNew (void) EPHYR_LOG_ERROR ("failed to query the host x for xv properties\n") ; goto error ; } - if (EphyrXVPrivSetAdaptorsHooks (xv_priv)) { + if (!EphyrXVPrivSetAdaptorsHooks (xv_priv)) { EPHYR_LOG_ERROR ("failed to set xv_priv hooks\n") ; goto error ; } @@ -232,7 +232,7 @@ EphyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) EphyrHostEncoding *encodings=NULL ; EphyrHostAttribute *attributes=NULL ; EphyrHostImageFormat *image_formats=NULL ; - int num_video_formats=0, base_port_id=0, num_attributes=0, num_formats=0, res=0, i=0 ; + int num_video_formats=0, base_port_id=0, num_attributes=0, num_formats=0, i=0 ; unsigned num_encodings=0 ; Bool is_ok = FALSE ; @@ -240,22 +240,26 @@ EphyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) EPHYR_LOG ("enter\n") ; - if (!EphyrHostXVQueryAdaptors (&a_this->host_adaptors) || !a_this->host_adaptors) { - EPHYR_LOG_ERROR ("failed to query host adaptors: %d\n", res) ; + if (!EphyrHostXVQueryAdaptors (&a_this->host_adaptors)) { + EPHYR_LOG_ERROR ("failed to query host adaptors\n") ; goto out ; } - a_this->num_adaptors = EphyrHostXVAdaptorArrayGetSize (a_this->host_adaptors) ; + if (a_this->host_adaptors) + a_this->num_adaptors = EphyrHostXVAdaptorArrayGetSize (a_this->host_adaptors) ; if (a_this->num_adaptors < 0) { EPHYR_LOG_ERROR ("failed to get number of host adaptors\n") ; goto out ; } + EPHYR_LOG ("host has %d adaptors\n", a_this->num_adaptors) ; /* * copy what we can from adaptors into a_this->adaptors */ - a_this->adaptors = xcalloc (a_this->num_adaptors, sizeof (KdVideoAdaptorRec)) ; - if (!a_this->host_adaptors) { - EPHYR_LOG_ERROR ("failed to create internal adaptors\n") ; - goto out ; + if (a_this->num_adaptors) { + a_this->adaptors = xcalloc (a_this->num_adaptors, sizeof (KdVideoAdaptorRec)) ; + if (!a_this->adaptors) { + EPHYR_LOG_ERROR ("failed to create internal adaptors\n") ; + goto out ; + } } for (i=0; i < a_this->num_adaptors; i++) { int j=0 ; From 66b28532e533ff5688705c5286425e68d6403cee Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Sat, 21 Jul 2007 12:08:39 +0200 Subject: [PATCH 06/44] initial commit of xv support work --- hw/kdrive/ephyr/ephyrvideo.c | 1 - 1 file changed, 1 deletion(-) diff --git a/hw/kdrive/ephyr/ephyrvideo.c b/hw/kdrive/ephyr/ephyrvideo.c index c87af19ba..bd0dbde84 100644 --- a/hw/kdrive/ephyr/ephyrvideo.c +++ b/hw/kdrive/ephyr/ephyrvideo.c @@ -52,7 +52,6 @@ static Bool EphyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) ; static Bool EphyrXVPrivSetAdaptorsHooks (EphyrXVPriv *a_this) ; static Bool EphyrXVPrivRegisterAdaptors (EphyrXVPriv *a_this, ScreenPtr a_screen) ; - static void EphyrStopVideo (KdScreenInfo *a_info, pointer a_xv_priv, Bool a_exit); From 2bf7f3c223fd32cd4922f98eadda2e3f06d9e119 Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Sat, 21 Jul 2007 17:55:12 +0200 Subject: [PATCH 07/44] link and init xv --- hw/kdrive/ephyr/ephyrvideo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/kdrive/ephyr/ephyrvideo.c b/hw/kdrive/ephyr/ephyrvideo.c index bd0dbde84..4808685c6 100644 --- a/hw/kdrive/ephyr/ephyrvideo.c +++ b/hw/kdrive/ephyr/ephyrvideo.c @@ -1,4 +1,4 @@ -/* +/* * Xephyr - A kdrive X server thats runs in a host X window. * Authored by Matthew Allum * From aa2fae7b75f741e57bc4a9b754b5ea7518d78f47 Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Sat, 21 Jul 2007 23:56:13 +0200 Subject: [PATCH 08/44] misc fixes. *(EphyrHostXVQueryAdaptors): return the queried adaptors list * (EphyrHostXVQueryPortAttributes): return port attributes number --- hw/kdrive/ephyr/ephyrhostvideo.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/hw/kdrive/ephyr/ephyrhostvideo.c b/hw/kdrive/ephyr/ephyrhostvideo.c index d86f9761c..6c5891c9c 100644 --- a/hw/kdrive/ephyr/ephyrhostvideo.c +++ b/hw/kdrive/ephyr/ephyrhostvideo.c @@ -71,6 +71,7 @@ EphyrHostXVQueryAdaptors (EphyrHostXVAdaptorArray **a_adaptors) EPHYR_LOG_ERROR ("failed to query host adaptors: %d\n", ret) ; goto out ; } + *a_adaptors = result ; is_ok = TRUE ; out: @@ -207,13 +208,11 @@ EphyrHostXVQueryPortAttributes (int a_port_id, EphyrHostAttribute **a_attributes, int *a_num_attributes) { - XvAttribute *attributes=NULL ; - int num_attributes=0 ; - EPHYR_RETURN_VAL_IF_FAIL (a_attributes && a_num_attributes, FALSE) ; - attributes = XvQueryPortAttributes (hostx_get_display (), a_port_id, &num_attributes) ; - *a_attributes = (EphyrHostAttribute*)attributes ; + *a_attributes = (EphyrHostAttribute*)XvQueryPortAttributes (hostx_get_display (), + a_port_id, + a_num_attributes); return TRUE ; } From b8cd313be467fd14b8e5c9ba68e1a2029c1e888b Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Mon, 23 Jul 2007 12:43:43 +0200 Subject: [PATCH 09/44] make xvinfo work * hw/kdrive/ephyr/ephyrhostvideo.c: (EphyrHostXVAdaptorGetVideoFormats): properly get visual class instead of returning the visual id. (EphyrHostXVQueryEncodings): properly copy the fields because simple casting does truncate some fields. (EphyrHostAttributesDelete): XFree the whole array instead of trying to free invidial members. * hw/kdrive/ephyr/ephyrvideo.c: (ephyrInitVideo): fix a typo (EphyrXVPrivQueryHostAdaptors): set XvWindowMask mask to adaptors type. use host adaptor name. Don't forget to set nImages field. (EphyrXVPrivRegisterAdaptors): report an error when KdXVScreenInit() fails. --- hw/kdrive/ephyr/ephyrhostvideo.c | 74 +++++++++++++++++++++++--------- hw/kdrive/ephyr/ephyrhostvideo.h | 10 ++--- hw/kdrive/ephyr/ephyrvideo.c | 19 ++++---- 3 files changed, 67 insertions(+), 36 deletions(-) diff --git a/hw/kdrive/ephyr/ephyrhostvideo.c b/hw/kdrive/ephyr/ephyrhostvideo.c index 6c5891c9c..98b754947 100644 --- a/hw/kdrive/ephyr/ephyrhostvideo.c +++ b/hw/kdrive/ephyr/ephyrhostvideo.c @@ -28,7 +28,7 @@ #ifdef HAVE_CONFIG_H #include #endif -#include +#include #include #include "hostx.h" @@ -125,15 +125,34 @@ EphyrHostXVAdaptorGetName (const EphyrHostXVAdaptor *a_this) return ((XvAdaptorInfo*)a_this)->name ; } -const EphyrHostVideoFormat* +EphyrHostVideoFormat* EphyrHostXVAdaptorGetVideoFormats (const EphyrHostXVAdaptor *a_this, int *a_nb_formats) { + EphyrHostVideoFormat *formats=NULL ; + int nb_formats=0, i=0 ; + XVisualInfo *visual_info, visual_info_template ; + int nb_visual_info ; + EPHYR_RETURN_VAL_IF_FAIL (a_this, NULL) ; + nb_formats = ((XvAdaptorInfo*)a_this)->num_formats ; + formats = Xcalloc (nb_formats * sizeof (EphyrHostVideoFormat)) ; + for (i=0; i < nb_formats; i++) { + memset (&visual_info_template, 0, sizeof (visual_info_template)) ; + visual_info_template.visualid = + ((XvAdaptorInfo*)a_this)->formats[i].visual_id; + visual_info = XGetVisualInfo (hostx_get_display (), + VisualIDMask, + &visual_info_template, + &nb_visual_info) ; + formats[i].depth = ((XvAdaptorInfo*)a_this)->formats[i].depth ; + formats[i].visual_class = visual_info->class ; + XFree (visual_info) ; + } if (a_nb_formats) - *a_nb_formats = ((XvAdaptorInfo*)a_this)->num_formats ; - return (EphyrHostVideoFormat*) ((XvAdaptorInfo*)a_this)->formats ; + *a_nb_formats = nb_formats ; + return formats ; } int @@ -157,16 +176,38 @@ EphyrHostXVQueryEncodings (int a_port_id, EphyrHostEncoding **a_encodings, unsigned int *a_num_encodings) { - int ret = 0 ; + EphyrHostEncoding *encodings=NULL ; + XvEncodingInfo *encoding_info=NULL ; + unsigned int num_encodings=0, i; + int ret=0 ; + EPHYR_RETURN_VAL_IF_FAIL (a_encodings && a_num_encodings, FALSE) ; ret = XvQueryEncodings (hostx_get_display (), a_port_id, - a_num_encodings, - (XvEncodingInfo**)a_encodings) ; - if (ret == Success) - return TRUE ; - return FALSE ; + &num_encodings, + &encoding_info) ; + if (num_encodings && encoding_info) { + encodings = Xcalloc (num_encodings * sizeof (EphyrHostEncoding)) ; + for (i=0; iadaptors[i].type = EphyrHostXVAdaptorGetType (cur_host_adaptor) ; + a_this->adaptors[i].type |= XvWindowMask ; a_this->adaptors[i].flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; if (EphyrHostXVAdaptorGetName (cur_host_adaptor)) a_this->adaptors[i].name = strdup (EphyrHostXVAdaptorGetName (cur_host_adaptor)) ; - a_this->adaptors[i].name = "Xephyr Video Overlay"; + else + a_this->adaptors[i].name = strdup ("Xephyr Video Overlay"); base_port_id = EphyrHostXVAdaptorGetFirstPortID (cur_host_adaptor) ; if (base_port_id < 0) { EPHYR_LOG_ERROR ("failed to get port id for adaptor %d\n", i) ; @@ -306,6 +308,7 @@ EphyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) continue ; } a_this->adaptors[i].pImages = (KdImagePtr) image_formats ; + a_this->adaptors[i].nImages = num_formats ; } is_ok = TRUE ; @@ -315,13 +318,9 @@ out: encodings = NULL ; } if (attributes) { - EphyrHostAttributesDelete (attributes, num_attributes) ; + EphyrHostAttributesDelete (attributes) ; attributes = NULL ; } - if (image_formats) { - xfree (image_formats) ; - image_formats = NULL ; - } EPHYR_LOG ("leave\n") ; return is_ok ; } @@ -374,7 +373,11 @@ EphyrXVPrivRegisterAdaptors (EphyrXVPriv *a_this, for (i=0 ; i < a_this->num_adaptors; i++) { *(adaptors + num_registered_adaptors + i) = &a_this->adaptors[i] ; } - KdXVScreenInit (a_screen, adaptors, num_adaptors); + if (!KdXVScreenInit (a_screen, adaptors, num_adaptors)) { + EPHYR_LOG_ERROR ("failed to register adaptors\n"); + goto out ; + } + EPHYR_LOG ("registered %d adaptors\n", num_adaptors) ; is_ok = TRUE ; out: From 24c837c0be6f85a917582156ab61d6c9c69301f9 Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Tue, 31 Jul 2007 23:18:52 +0200 Subject: [PATCH 10/44] implement setportattribute and getportattribute calls --- hw/kdrive/ephyr/ephyrhostvideo.c | 38 +++++++++ hw/kdrive/ephyr/ephyrhostvideo.h | 10 ++- hw/kdrive/ephyr/ephyrvideo.c | 140 +++++++++++++++++++++++-------- 3 files changed, 152 insertions(+), 36 deletions(-) diff --git a/hw/kdrive/ephyr/ephyrhostvideo.c b/hw/kdrive/ephyr/ephyrhostvideo.c index 98b754947..ed6dbb0f3 100644 --- a/hw/kdrive/ephyr/ephyrhostvideo.c +++ b/hw/kdrive/ephyr/ephyrhostvideo.c @@ -263,3 +263,41 @@ EphyrHostXVQueryImageFormats (int a_port_id, return TRUE ; } + +Bool +EphyrHostXVSetPortAttribute (int a_port_id, + int a_atom, + int a_attr_value) +{ + int res=Success ; + + res = XvSetPortAttribute (hostx_get_display (), + a_port_id, + a_atom, + a_attr_value) ; + if (res != Success) { + EPHYR_LOG_ERROR ("XvSetPortAttribute() failed: %d\n", res) ; + return FALSE ; + } + return TRUE ; +} + +Bool +EphyrHostXVGetPortAttribute (int a_port_id, + int a_atom, + int *a_attr_value) +{ + int res=Success ; + + EPHYR_RETURN_VAL_IF_FAIL (a_attr_value, FALSE) ; + + res = XvGetPortAttribute (hostx_get_display (), + a_port_id, + a_atom, + a_attr_value) ; + if (res != Success) { + EPHYR_LOG_ERROR ("XvGetPortAttribute() failed: %d \n", res) ; + return FALSE ; + } + return TRUE ; +} diff --git a/hw/kdrive/ephyr/ephyrhostvideo.h b/hw/kdrive/ephyr/ephyrhostvideo.h index d9034fde7..af5456092 100644 --- a/hw/kdrive/ephyr/ephyrhostvideo.h +++ b/hw/kdrive/ephyr/ephyrhostvideo.h @@ -130,6 +130,14 @@ void EphyrHostAttributesDelete (EphyrHostAttribute *a_attributes) ; Bool EphyrHostXVQueryImageFormats (int a_port_id, EphyrHostImageFormat **a_formats, int *a_num_format) ; - +/* + * Port Attribute Get/Set + */ +Bool EphyrHostXVSetPortAttribute (int a_port_id, + int a_atom, + int a_attr_value) ; +Bool EphyrHostXVGetPortAttribute (int a_port_id, + int a_atom, + int *a_attr_value) ; #endif /*__EPHYRHOSTVIDEO_H__*/ diff --git a/hw/kdrive/ephyr/ephyrvideo.c b/hw/kdrive/ephyr/ephyrvideo.c index d08f111ba..eedbf1556 100644 --- a/hw/kdrive/ephyr/ephyrvideo.c +++ b/hw/kdrive/ephyr/ephyrvideo.c @@ -43,9 +43,14 @@ struct _EphyrXVPriv { KdVideoAdaptorPtr adaptors ; int num_adaptors ; }; - typedef struct _EphyrXVPriv EphyrXVPriv ; +struct _EphyrPortPriv { + int port_number ; + EphyrXVPriv *xv_priv; +}; +typedef struct _EphyrPortPriv EphyrPortPriv ; + static EphyrXVPriv* EphyrXVPrivNew (void) ; static void EphyrXVPrivDelete (EphyrXVPriv *a_this) ; static Bool EphyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) ; @@ -59,12 +64,12 @@ static void EphyrStopVideo (KdScreenInfo *a_info, static int EphyrSetPortAttribute (KdScreenInfo *a_info, Atom a_attr_name, int a_attr_value, - pointer a_xv_priv); + pointer a_port_priv); static int EphyrGetPortAttribute (KdScreenInfo *a_screen_info, Atom a_attr_name, int *a_attr_value, - pointer a_xv_priv); + pointer a_port_priv); static void EphyrQueryBestSize (KdScreenInfo *a_info, Bool a_motion, @@ -74,7 +79,7 @@ static void EphyrQueryBestSize (KdScreenInfo *a_info, short a_drw_h, unsigned int *a_prefered_w, unsigned int *a_prefered_h, - pointer a_xv_priv); + pointer a_port_priv); static int EphyrPutImage (KdScreenInfo *a_info, DrawablePtr a_drawable, @@ -92,7 +97,7 @@ static int EphyrPutImage (KdScreenInfo *a_info, short a_height, Bool a_sync, RegionPtr a_clipping_region, - pointer a_xv_priv); + pointer a_port_priv); static int EphyrQueryImageAttributes (KdScreenInfo *a_info, int a_id, @@ -231,7 +236,8 @@ EphyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) EphyrHostEncoding *encodings=NULL ; EphyrHostAttribute *attributes=NULL ; EphyrHostImageFormat *image_formats=NULL ; - int num_video_formats=0, base_port_id=0, num_attributes=0, num_formats=0, i=0 ; + int num_video_formats=0, base_port_id=0, + num_attributes=0, num_formats=0, i=0; unsigned num_encodings=0 ; Bool is_ok = FALSE ; @@ -244,7 +250,8 @@ EphyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) goto out ; } if (a_this->host_adaptors) - a_this->num_adaptors = EphyrHostXVAdaptorArrayGetSize (a_this->host_adaptors) ; + a_this->num_adaptors = + EphyrHostXVAdaptorArrayGetSize (a_this->host_adaptors) ; if (a_this->num_adaptors < 0) { EPHYR_LOG_ERROR ("failed to get number of host adaptors\n") ; goto out ; @@ -254,7 +261,8 @@ EphyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) * copy what we can from adaptors into a_this->adaptors */ if (a_this->num_adaptors) { - a_this->adaptors = xcalloc (a_this->num_adaptors, sizeof (KdVideoAdaptorRec)) ; + a_this->adaptors = xcalloc (a_this->num_adaptors, + sizeof (KdVideoAdaptorRec)) ; if (!a_this->adaptors) { EPHYR_LOG_ERROR ("failed to create internal adaptors\n") ; goto out ; @@ -262,15 +270,18 @@ EphyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) } for (i=0; i < a_this->num_adaptors; i++) { int j=0 ; - cur_host_adaptor = EphyrHostXVAdaptorArrayAt (a_this->host_adaptors, i) ; + cur_host_adaptor = + EphyrHostXVAdaptorArrayAt (a_this->host_adaptors, i) ; if (!cur_host_adaptor) continue ; - a_this->adaptors[i].type = EphyrHostXVAdaptorGetType (cur_host_adaptor) ; + a_this->adaptors[i].type = + EphyrHostXVAdaptorGetType (cur_host_adaptor) ; a_this->adaptors[i].type |= XvWindowMask ; - a_this->adaptors[i].flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; + a_this->adaptors[i].flags = + VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; if (EphyrHostXVAdaptorGetName (cur_host_adaptor)) a_this->adaptors[i].name = - strdup (EphyrHostXVAdaptorGetName (cur_host_adaptor)) ; + strdup (EphyrHostXVAdaptorGetName (cur_host_adaptor)) ; else a_this->adaptors[i].name = strdup ("Xephyr Video Overlay"); base_port_id = EphyrHostXVAdaptorGetFirstPortID (cur_host_adaptor) ; @@ -278,33 +289,51 @@ EphyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) EPHYR_LOG_ERROR ("failed to get port id for adaptor %d\n", i) ; continue ; } - if (!EphyrHostXVQueryEncodings (base_port_id, &encodings, &num_encodings)) { - EPHYR_LOG_ERROR ("failed to get encodings for port port id %d, adaptors %d\n", + if (!EphyrHostXVQueryEncodings (base_port_id, + &encodings, + &num_encodings)) { + EPHYR_LOG_ERROR ("failed to get encodings for port port id %d," + " adaptors %d\n", base_port_id, i) ; continue ; } a_this->adaptors[i].nEncodings = num_encodings ; - a_this->adaptors[i].pEncodings = videoEncodingDup (encodings, num_encodings) ; + a_this->adaptors[i].pEncodings = + videoEncodingDup (encodings, num_encodings) ; video_formats = (EphyrHostVideoFormat*) - EphyrHostXVAdaptorGetVideoFormats (cur_host_adaptor, &num_video_formats); + EphyrHostXVAdaptorGetVideoFormats (cur_host_adaptor, + &num_video_formats); a_this->adaptors[i].pFormats = (KdVideoFormatPtr) video_formats ; a_this->adaptors[i].nFormats = num_video_formats ; - a_this->adaptors[i].nPorts = EphyrHostXVAdaptorGetNbPorts (cur_host_adaptor) ; - a_this->adaptors[i].pPortPrivates = xcalloc (a_this->adaptors[i].nPorts, - sizeof (DevUnion)) ; + a_this->adaptors[i].nPorts = + EphyrHostXVAdaptorGetNbPorts (cur_host_adaptor) ; + a_this->adaptors[i].pPortPrivates = + xcalloc (a_this->adaptors[i].nPorts, + sizeof (DevUnion) + sizeof (EphyrPortPriv)) ; for (j=0; j < a_this->adaptors[i].nPorts; j++) { - a_this->adaptors[i].pPortPrivates[j].ptr = a_this ; + int port_priv_offset = a_this->adaptors[i].nPorts ; + EphyrPortPriv *port_priv = + (EphyrPortPriv*) + &a_this->adaptors[i].pPortPrivates[port_priv_offset + j]; + port_priv->port_number = base_port_id + j; + port_priv->xv_priv = a_this ; + a_this->adaptors[i].pPortPrivates[j].ptr = port_priv; } if (!EphyrHostXVQueryPortAttributes (base_port_id, &attributes, &num_attributes)) { - EPHYR_LOG_ERROR ("failed to get port attribute for adaptor %d\n", i) ; + EPHYR_LOG_ERROR ("failed to get port attribute " + "for adaptor %d\n", i) ; continue ; } - a_this->adaptors[i].pAttributes = portAttributesDup (attributes, num_attributes); + a_this->adaptors[i].pAttributes = + portAttributesDup (attributes, num_attributes); a_this->adaptors[i].nAttributes = num_attributes ; - if (!EphyrHostXVQueryImageFormats (base_port_id, &image_formats, &num_formats)) { - EPHYR_LOG_ERROR ("failed to get image formats for adaptor %d\n", i) ; + if (!EphyrHostXVQueryImageFormats (base_port_id, + &image_formats, + &num_formats)) { + EPHYR_LOG_ERROR ("failed to get image formats " + "for adaptor %d\n", i) ; continue ; } a_this->adaptors[i].pImages = (KdImagePtr) image_formats ; @@ -362,7 +391,8 @@ EphyrXVPrivRegisterAdaptors (EphyrXVPriv *a_this, if (!a_this->num_adaptors) goto out ; - num_registered_adaptors = KdXVListGenericAdaptors (screen, ®istered_adaptors); + num_registered_adaptors = + KdXVListGenericAdaptors (screen, ®istered_adaptors); num_adaptors = num_registered_adaptors + a_this->num_adaptors ; adaptors = xcalloc (num_adaptors, sizeof (KdVideoAdaptorPtr)) ; if (!adaptors) { @@ -394,7 +424,7 @@ out: } static void -EphyrStopVideo (KdScreenInfo *a_info, pointer a_xv_priv, Bool a_exit) +EphyrStopVideo (KdScreenInfo *a_info, pointer a_port_priv, Bool a_exit) { EPHYR_LOG ("enter\n") ; EPHYR_LOG ("leave\n") ; @@ -404,22 +434,62 @@ static int EphyrSetPortAttribute (KdScreenInfo *a_info, Atom a_attr_name, int a_attr_value, - pointer a_xv_priv) + pointer a_port_priv) { - EPHYR_LOG ("enter\n") ; - return 0 ; + int res=Success ; + EphyrPortPriv *port_priv = a_port_priv ; + + EPHYR_RETURN_VAL_IF_FAIL (port_priv, BadMatch) ; + EPHYR_RETURN_VAL_IF_FAIL (ValidAtom (a_attr_name), BadMatch) ; + + EPHYR_LOG ("enter, portnum:%d, atomid:%d, attr_name:%s, attr_val:%d\n", + port_priv->port_number, + (int)a_attr_name, + NameForAtom (a_attr_name), + a_attr_value) ; + + if (!EphyrHostXVSetPortAttribute (port_priv->port_number, + a_attr_name, + a_attr_value)) { + EPHYR_LOG_ERROR ("failed to set port attribute\n") ; + res = BadMatch ; + goto out ; + } + + res = Success ; +out: EPHYR_LOG ("leave\n") ; + return res ; } static int EphyrGetPortAttribute (KdScreenInfo *a_screen_info, Atom a_attr_name, int *a_attr_value, - pointer a_xv_priv) + pointer a_port_priv) { - EPHYR_LOG ("enter\n") ; - return 0 ; - EPHYR_LOG ("leave\n") ; + int res=Success ; + EphyrPortPriv *port_priv = a_port_priv ; + + EPHYR_RETURN_VAL_IF_FAIL (port_priv, BadMatch) ; + EPHYR_RETURN_VAL_IF_FAIL (ValidAtom (a_attr_name), BadMatch) ; + + EPHYR_LOG ("enter, portnum:%d, atomid:%d, attr_name:%s\n", + port_priv->port_number, + (int)a_attr_name, + NameForAtom (a_attr_name)) ; + + if (!EphyrHostXVGetPortAttribute (port_priv->port_number, + a_attr_name, + a_attr_value)) { + EPHYR_LOG_ERROR ("failed to get port attribute\n") ; + res = BadMatch ; + goto out ; + } + + res = Success ; +out: + return res ; } static void @@ -431,7 +501,7 @@ EphyrQueryBestSize (KdScreenInfo *a_info, short a_drw_h, unsigned int *a_prefered_w, unsigned int *a_prefered_h, - pointer a_xv_priv) + pointer a_port_priv) { } @@ -452,7 +522,7 @@ EphyrPutImage (KdScreenInfo *a_info, short a_height, Bool a_sync, RegionPtr a_clipping_region, - pointer a_xv_priv) + pointer a_port_priv) { EPHYR_LOG ("enter\n") ; return 0 ; From aa478e09e25a1cb19b808e7e52b2ee155e34f03b Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Thu, 2 Aug 2007 12:49:36 +0200 Subject: [PATCH 11/44] make properties setting/query code work and hopefully complete. * hw/kdrive/ephyr/ephyrhostvideo.c,h: (EphyrHostXVQueryImageAttributes): add this call. It calls XvQueryBestSize xserver entry point. It uses the protocol level machinery because Xvlib does not expose that entry point as a C function. (EphyrHostXVQueryBestSize): added this wrapper around XvQueryBestSize(). (EphyrHostGetAtom, EphyrHostGetAtomName): added this to get an atom or atom name from the host server * hw/kdrive/ephyr/ephyrvideo.c: (EphyrSetPortAttribute): convert the atom into an host server server atom before attacking the host server with it, because in in its current form, the input atom is only valid in xephyr. This fix makes this call work. (EphyrGetPortAttribute): ditto. (EphyrQueryBestSize): implement this. (EphyrQueryImageAttributes): implement this. --- hw/kdrive/ephyr/ephyrhostvideo.c | 257 ++++++++++++++++++++++++++++++- hw/kdrive/ephyr/ephyrhostvideo.h | 30 ++++ hw/kdrive/ephyr/ephyrvideo.c | 128 ++++++++++++++- 3 files changed, 400 insertions(+), 15 deletions(-) diff --git a/hw/kdrive/ephyr/ephyrhostvideo.c b/hw/kdrive/ephyr/ephyrhostvideo.c index ed6dbb0f3..fa1e15b70 100644 --- a/hw/kdrive/ephyr/ephyrhostvideo.c +++ b/hw/kdrive/ephyr/ephyrhostvideo.c @@ -29,7 +29,12 @@ #include #endif #include +#include #include +#include +#include +#include +#define _HAVE_XALLOC_DECLS #include "hostx.h" #include "ephyrhostvideo.h" @@ -43,6 +48,61 @@ #define FALSE 0 #endif /*FALSE*/ +static XExtensionInfo _xv_info_data; +static XExtensionInfo *xv_info = &_xv_info_data; +static char *xv_extension_name = XvName; +static char *xv_error_string(Display *dpy, int code, XExtCodes *codes, + char * buf, int n); +static int xv_close_display(Display *dpy, XExtCodes *codes); +static Bool xv_wire_to_event(Display *dpy, XEvent *host, xEvent *wire); + +static XExtensionHooks xv_extension_hooks = { + NULL, /* create_gc */ + NULL, /* copy_gc */ + NULL, /* flush_gc */ + NULL, /* free_gc */ + NULL, /* create_font */ + NULL, /* free_font */ + xv_close_display, /* close_display */ + xv_wire_to_event, /* wire_to_event */ + NULL, /* event_to_wire */ + NULL, /* error */ + xv_error_string /* error_string */ +}; + + +static char *xv_error_list[] = +{ + "BadPort", /* XvBadPort */ + "BadEncoding", /* XvBadEncoding */ + "BadControl" /* XvBadControl */ +}; + + +#define XvCheckExtension(dpy, i, val) \ + XextCheckExtension(dpy, i, xv_extension_name, val) +#define XvGetReq(name, req) \ + WORD64ALIGN\ + if ((dpy->bufptr + SIZEOF(xv##name##Req)) > dpy->bufmax)\ + _XFlush(dpy);\ + req = (xv##name##Req *)(dpy->last_req = dpy->bufptr);\ + req->reqType = info->codes->major_opcode;\ + req->xvReqType = xv_##name; \ + req->length = (SIZEOF(xv##name##Req))>>2;\ + dpy->bufptr += SIZEOF(xv##name##Req);\ + dpy->request++ + +static XEXT_GENERATE_CLOSE_DISPLAY (xv_close_display, xv_info) + + +static XEXT_GENERATE_FIND_DISPLAY (xv_find_display, xv_info, + xv_extension_name, + &xv_extension_hooks, + XvNumEvents, NULL) + +static XEXT_GENERATE_ERROR_STRING (xv_error_string, xv_extension_name, + XvNumErrors, xv_error_list) + struct _EphyrHostXVAdaptorArray { XvAdaptorInfo *adaptors ; unsigned int nb_adaptors ; @@ -59,7 +119,7 @@ EphyrHostXVQueryAdaptors (EphyrHostXVAdaptorArray **a_adaptors) EPHYR_LOG ("enter\n") ; - result = Xcalloc (sizeof (EphyrHostXVAdaptorArray)) ; + result = Xcalloc (1, sizeof (EphyrHostXVAdaptorArray)) ; if (!result) goto out ; @@ -137,7 +197,7 @@ EphyrHostXVAdaptorGetVideoFormats (const EphyrHostXVAdaptor *a_this, EPHYR_RETURN_VAL_IF_FAIL (a_this, NULL) ; nb_formats = ((XvAdaptorInfo*)a_this)->num_formats ; - formats = Xcalloc (nb_formats * sizeof (EphyrHostVideoFormat)) ; + formats = Xcalloc (nb_formats, sizeof (EphyrHostVideoFormat)) ; for (i=0; i < nb_formats; i++) { memset (&visual_info_template, 0, sizeof (visual_info_template)) ; visual_info_template.visualid = @@ -188,7 +248,7 @@ EphyrHostXVQueryEncodings (int a_port_id, &num_encodings, &encoding_info) ; if (num_encodings && encoding_info) { - encodings = Xcalloc (num_encodings * sizeof (EphyrHostEncoding)) ; + encodings = Xcalloc (num_encodings, sizeof (EphyrHostEncoding)) ; for (i=0; iu.u.type & 0x7F) - info->codes->first_event) { + case XvVideoNotify: + re->xvvideo.type = event->u.u.type & 0x7f; + re->xvvideo.serial = + _XSetLastRequestRead(dpy, (xGenericReply *)event); + re->xvvideo.send_event = ((event->u.u.type & 0x80) != 0); + re->xvvideo.display = dpy; + re->xvvideo.time = event->u.videoNotify.time; + re->xvvideo.reason = event->u.videoNotify.reason; + re->xvvideo.drawable = event->u.videoNotify.drawable; + re->xvvideo.port_id = event->u.videoNotify.port; + break; + case XvPortNotify: + re->xvport.type = event->u.u.type & 0x7f; + re->xvport.serial = + _XSetLastRequestRead(dpy, (xGenericReply *)event); + re->xvport.send_event = ((event->u.u.type & 0x80) != 0); + re->xvport.display = dpy; + re->xvport.time = event->u.portNotify.time; + re->xvport.port_id = event->u.portNotify.port; + re->xvport.attribute = event->u.portNotify.attribute; + re->xvport.value = event->u.portNotify.value; + break; + default: + return False; + } + + return True ; +} + +Bool +EphyrHostXVQueryImageAttributes (int a_port_id, + int a_image_id /*image fourcc code*/, + unsigned short *a_width, + unsigned short *a_height, + int *a_image_size, + int *a_pitches, + int *a_offsets) +{ + Display *dpy = hostx_get_display () ; + Bool ret=FALSE ; + XExtDisplayInfo *info = xv_find_display (dpy); + xvQueryImageAttributesReq *req=NULL; + xvQueryImageAttributesReply rep; + + EPHYR_RETURN_VAL_IF_FAIL (a_width, FALSE) ; + EPHYR_RETURN_VAL_IF_FAIL (a_height, FALSE) ; + EPHYR_RETURN_VAL_IF_FAIL (a_image_size, FALSE) ; + + XvCheckExtension (dpy, info, FALSE); + + LockDisplay (dpy); + + XvGetReq (QueryImageAttributes, req); + req->id = a_image_id; + req->port = a_port_id; + req->width = *a_width; + req->height = *a_height; + /* + * read the reply + */ + if (!_XReply (dpy, (xReply *)&rep, 0, xFalse)) { + EPHYR_LOG_ERROR ("QeryImageAttribute req failed\n") ; + goto out ; + } + if (a_pitches && a_offsets) { + _XRead (dpy, + (char*)a_pitches, + rep.num_planes << 2); + _XRead (dpy, + (char*)a_offsets, + rep.num_planes << 2); + } else { + _XEatData(dpy, rep.length << 2); + } + *a_width = rep.width ; + *a_height = rep.height ; + *a_image_size = rep.data_size ; + + ret = TRUE ; + +out: + UnlockDisplay (dpy) ; + SyncHandle (); + return ret ; +} + +Bool +EphyrHostGetAtom (const char* a_name, + Bool a_create_if_not_exists, + int *a_atom) +{ + int atom=None ; + + EPHYR_RETURN_VAL_IF_FAIL (a_atom, FALSE) ; + + atom = XInternAtom (hostx_get_display (), a_name, a_create_if_not_exists); + if (atom == None) { return FALSE ; } + *a_atom = atom ; return TRUE ; } + +char* +EphyrHostGetAtomName (int a_atom) +{ + return XGetAtomName (hostx_get_display (), a_atom) ; +} + +void +EphyrHostFree (void *a_pointer) +{ + if (a_pointer) + XFree (a_pointer) ; +} + diff --git a/hw/kdrive/ephyr/ephyrhostvideo.h b/hw/kdrive/ephyr/ephyrhostvideo.h index af5456092..fa3eba0bd 100644 --- a/hw/kdrive/ephyr/ephyrhostvideo.h +++ b/hw/kdrive/ephyr/ephyrhostvideo.h @@ -84,6 +84,8 @@ typedef struct _EphyrHostImageFormat { int scanline_order; /* XvTopToBottom, XvBottomToTop */ } EphyrHostImageFormat ; +void EphyrHostFree (void *a_pointer) ; + /* * host adaptor array */ @@ -139,5 +141,33 @@ Bool EphyrHostXVSetPortAttribute (int a_port_id, Bool EphyrHostXVGetPortAttribute (int a_port_id, int a_atom, int *a_attr_value) ; +/* + *size query + */ +Bool EphyrHostXVQueryBestSize (int a_port_id, + Bool a_motion, + unsigned int a_frame_w, + unsigned int a_frame_h, + unsigned int a_drw_w, + unsigned int a_drw_h, + unsigned int *a_actual_w, + unsigned int *a_actual_h) ; + +Bool EphyrHostXVQueryImageAttributes (int a_port_id, + int a_image_id /*image fourcc code*/, + unsigned short *a_width, + unsigned short *a_height, + int *a_image_size, + int *a_pitches, + int *a_offsets) ; +/* + * atom + */ +Bool EphyrHostGetAtom (const char* a_name, + Bool a_create_if_not_exists, + int *a_atom) ; +char* EphyrHostGetAtomName (int a_atom) ; + + #endif /*__EPHYRHOSTVIDEO_H__*/ diff --git a/hw/kdrive/ephyr/ephyrvideo.c b/hw/kdrive/ephyr/ephyrvideo.c index eedbf1556..6f0bc8f41 100644 --- a/hw/kdrive/ephyr/ephyrvideo.c +++ b/hw/kdrive/ephyr/ephyrvideo.c @@ -51,6 +51,10 @@ struct _EphyrPortPriv { }; typedef struct _EphyrPortPriv EphyrPortPriv ; +static Bool EphyrLocalAtomToHost (int a_local_atom, int *a_host_atom) ; + +static Bool EphyrHostAtomToLocal (int a_host_atom, int *a_local_atom) ; + static EphyrXVPriv* EphyrXVPrivNew (void) ; static void EphyrXVPrivDelete (EphyrXVPriv *a_this) ; static Bool EphyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) ; @@ -105,6 +109,67 @@ static int EphyrQueryImageAttributes (KdScreenInfo *a_info, unsigned short *a_h, int *a_pitches, int *a_offsets); +static int s_base_port_id ; + +/************** + * + * ************/ + +static Bool +EphyrLocalAtomToHost (int a_local_atom, int *a_host_atom) +{ + char *atom_name=NULL; + int host_atom=None ; + + EPHYR_RETURN_VAL_IF_FAIL (a_host_atom, FALSE) ; + + if (!ValidAtom (a_local_atom)) + return FALSE ; + + atom_name = NameForAtom (a_local_atom) ; + + if (!atom_name) + return FALSE ; + + if (!EphyrHostGetAtom (atom_name, FALSE, &host_atom) || host_atom == None) { + EPHYR_LOG_ERROR ("no atom for string %s defined in host X\n", + atom_name) ; + return FALSE ; + } + *a_host_atom = host_atom ; + return TRUE ; +} + +static Bool +EphyrHostAtomToLocal (int a_host_atom, int *a_local_atom) +{ + Bool is_ok=FALSE ; + char *atom_name=NULL ; + int atom=None ; + + EPHYR_RETURN_VAL_IF_FAIL (a_local_atom, FALSE) ; + + atom_name = EphyrHostGetAtomName (a_host_atom) ; + if (!atom_name) + goto out ; + + atom = MakeAtom (atom_name, strlen (atom_name), TRUE) ; + if (atom == None) + goto out ; + + *a_local_atom = atom ; + is_ok = TRUE ; + +out: + if (atom_name) { + EphyrHostFree (atom_name) ; + } + return is_ok ; +} + +/************** + * + * ************/ Bool ephyrInitVideo (ScreenPtr pScreen) @@ -289,6 +354,9 @@ EphyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) EPHYR_LOG_ERROR ("failed to get port id for adaptor %d\n", i) ; continue ; } + if (!s_base_port_id) + s_base_port_id = base_port_id ; + if (!EphyrHostXVQueryEncodings (base_port_id, &encodings, &num_encodings)) { @@ -436,7 +504,7 @@ EphyrSetPortAttribute (KdScreenInfo *a_info, int a_attr_value, pointer a_port_priv) { - int res=Success ; + int res=Success, host_atom=0 ; EphyrPortPriv *port_priv = a_port_priv ; EPHYR_RETURN_VAL_IF_FAIL (port_priv, BadMatch) ; @@ -448,8 +516,14 @@ EphyrSetPortAttribute (KdScreenInfo *a_info, NameForAtom (a_attr_name), a_attr_value) ; + if (!EphyrLocalAtomToHost (a_attr_name, &host_atom)) { + EPHYR_LOG_ERROR ("failed to convert local atom to host atom\n") ; + res = BadMatch ; + goto out ; + } + if (!EphyrHostXVSetPortAttribute (port_priv->port_number, - a_attr_name, + host_atom, a_attr_value)) { EPHYR_LOG_ERROR ("failed to set port attribute\n") ; res = BadMatch ; @@ -468,7 +542,7 @@ EphyrGetPortAttribute (KdScreenInfo *a_screen_info, int *a_attr_value, pointer a_port_priv) { - int res=Success ; + int res=Success, host_atom=0 ; EphyrPortPriv *port_priv = a_port_priv ; EPHYR_RETURN_VAL_IF_FAIL (port_priv, BadMatch) ; @@ -479,8 +553,14 @@ EphyrGetPortAttribute (KdScreenInfo *a_screen_info, (int)a_attr_name, NameForAtom (a_attr_name)) ; + if (!EphyrLocalAtomToHost (a_attr_name, &host_atom)) { + EPHYR_LOG_ERROR ("failed to convert local atom to host atom\n") ; + res = BadMatch ; + goto out ; + } + if (!EphyrHostXVGetPortAttribute (port_priv->port_number, - a_attr_name, + host_atom, a_attr_value)) { EPHYR_LOG_ERROR ("failed to get port attribute\n") ; res = BadMatch ; @@ -489,6 +569,7 @@ EphyrGetPortAttribute (KdScreenInfo *a_screen_info, res = Success ; out: + EPHYR_LOG ("leave\n") ; return res ; } @@ -503,6 +584,21 @@ EphyrQueryBestSize (KdScreenInfo *a_info, unsigned int *a_prefered_h, pointer a_port_priv) { + int res=0 ; + EphyrPortPriv *port_priv = a_port_priv ; + + EPHYR_RETURN_IF_FAIL (port_priv) ; + + EPHYR_LOG ("enter\n") ; + res = EphyrHostXVQueryBestSize (port_priv->port_number, + a_motion, + a_src_w, a_src_h, + a_drw_w, a_drw_h, + a_prefered_w, a_prefered_h) ; + if (!res) { + EPHYR_LOG_ERROR ("Failed to query best size\n") ; + } + EPHYR_LOG ("leave\n") ; } static int @@ -537,8 +633,24 @@ EphyrQueryImageAttributes (KdScreenInfo *a_info, int *a_pitches, int *a_offsets) { - EPHYR_LOG ("enter\n") ; - return 0 ; - EPHYR_LOG ("leave\n") ; -} + int image_size=0 ; + EPHYR_RETURN_VAL_IF_FAIL (a_w && a_h, FALSE) ; + + EPHYR_LOG ("enter: dim (%dx%d), pitches: %#x, offsets: %#x\n", + *a_w, *a_h, (unsigned int)a_pitches, (unsigned int)a_offsets) ; + + if (!EphyrHostXVQueryImageAttributes (s_base_port_id, + a_id, + a_w, a_h, + &image_size, + a_pitches, a_offsets)) { + EPHYR_LOG_ERROR ("EphyrHostXVQueryImageAttributes() failed\n") ; + goto out ; + } + EPHYR_LOG ("image size: %d, dim (%dx%d)", image_size, *a_w, *a_h) ; + +out: + EPHYR_LOG ("leave\n") ; + return image_size ; +} From 207714b60d18e94bbe2d755a431dbb29fe5677f7 Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Fri, 3 Aug 2007 01:10:39 +0200 Subject: [PATCH 12/44] first implementation of putimage * hw/kdrive/ephyr/ephyrhostvideo.c,h: (EphyrHostXVPutImage): first implementation. does not support clipping regions yet. * hw/kdrive/ephyr/ephyrvideo.c: (DoSimpleClip): clip using a clipping box. Does not support regions yet. (EphyrPutImage): first implementation. Uses a simple clipping rectangle, no region yet. * hw/kdrive/ephyr/hostx.c: (hostx_get_window): added this to get the main window of the host x. --- hw/kdrive/ephyr/ephyrhostvideo.c | 53 +++++++++++++++++++ hw/kdrive/ephyr/ephyrhostvideo.h | 17 ++++++ hw/kdrive/ephyr/ephyrvideo.c | 89 +++++++++++++++++++++++++++++++- hw/kdrive/ephyr/hostx.c | 5 ++ hw/kdrive/ephyr/hostx.h | 3 ++ 5 files changed, 166 insertions(+), 1 deletion(-) diff --git a/hw/kdrive/ephyr/ephyrhostvideo.c b/hw/kdrive/ephyr/ephyrhostvideo.c index fa1e15b70..c15a90429 100644 --- a/hw/kdrive/ephyr/ephyrhostvideo.c +++ b/hw/kdrive/ephyr/ephyrhostvideo.c @@ -544,3 +544,56 @@ EphyrHostFree (void *a_pointer) XFree (a_pointer) ; } +Bool +EphyrHostXVPutImage (int a_port_id, + int a_image_id, + int a_drw_x, + int a_drw_y, + int a_drw_w, + int a_drw_h, + int a_src_x, + int a_src_y, + int a_src_w, + int a_src_h, + int a_image_width, + int a_image_height, + unsigned char *a_buf) +{ + Bool is_ok=TRUE ; + XvImage *xv_image=NULL ; + GC gc=0 ; + XGCValues gc_values; + + EPHYR_RETURN_VAL_IF_FAIL (a_buf, FALSE) ; + + EPHYR_LOG ("enter\n") ; + + gc = XCreateGC (hostx_get_display (), hostx_get_window (), 0L, &gc_values); + if (!gc) { + EPHYR_LOG_ERROR ("failed to create gc \n") ; + goto out ; + } + xv_image = (XvImage*) XvCreateImage (hostx_get_display (), + a_port_id, a_image_id, + NULL, a_image_width, a_image_height) ; + if (!xv_image) { + EPHYR_LOG_ERROR ("failed to create image\n") ; + goto out ; + } + xv_image->data = (char*)a_buf ; + XvPutImage (hostx_get_display (), a_port_id, hostx_get_window (), + gc, xv_image, + a_src_x, a_src_y, a_src_w, a_src_h, + a_drw_x, a_drw_y, a_drw_w, a_drw_h) ; + XFlush (hostx_get_display ()) ; + is_ok = TRUE ; + +out: + + EPHYR_LOG ("leave\n") ; + if (xv_image) { + XFree (xv_image) ; + xv_image = NULL ; + } + return is_ok ; +} diff --git a/hw/kdrive/ephyr/ephyrhostvideo.h b/hw/kdrive/ephyr/ephyrhostvideo.h index fa3eba0bd..0e97bdee8 100644 --- a/hw/kdrive/ephyr/ephyrhostvideo.h +++ b/hw/kdrive/ephyr/ephyrhostvideo.h @@ -168,6 +168,23 @@ Bool EphyrHostGetAtom (const char* a_name, int *a_atom) ; char* EphyrHostGetAtomName (int a_atom) ; +/* + *PutImage + * (ignore clipping for now) + */ +Bool EphyrHostXVPutImage (int a_port_id, + int a_image_id, + int a_drw_x, + int a_drw_y, + int a_drw_w, + int a_drw_h, + int a_src_x, + int a_src_y, + int a_src_w, + int a_src_h, + int a_image_width, + int a_image_height, + unsigned char *a_buf) ; #endif /*__EPHYRHOSTVIDEO_H__*/ diff --git a/hw/kdrive/ephyr/ephyrvideo.c b/hw/kdrive/ephyr/ephyrvideo.c index 6f0bc8f41..9cd479bcc 100644 --- a/hw/kdrive/ephyr/ephyrvideo.c +++ b/hw/kdrive/ephyr/ephyrvideo.c @@ -51,6 +51,10 @@ struct _EphyrPortPriv { }; typedef struct _EphyrPortPriv EphyrPortPriv ; +static Bool DoSimpleClip (BoxPtr a_dst_drw, + BoxPtr a_clipper, + BoxPtr a_result) ; + static Bool EphyrLocalAtomToHost (int a_local_atom, int *a_host_atom) ; static Bool EphyrHostAtomToLocal (int a_host_atom, int *a_local_atom) ; @@ -115,6 +119,51 @@ static int s_base_port_id ; * * ************/ +static Bool +DoSimpleClip (BoxPtr a_dst_box, + BoxPtr a_clipper, + BoxPtr a_result) +{ + BoxRec dstClippedBox ; + + EPHYR_RETURN_VAL_IF_FAIL (a_dst_box && a_clipper && a_result, FALSE) ; + + /* + * setup the clipbox inside the destination. + */ + dstClippedBox.x1 = a_dst_box->x1 ; + dstClippedBox.x2 = a_dst_box->x2 ; + dstClippedBox.y1 = a_dst_box->y1 ; + dstClippedBox.y2 = a_dst_box->y2 ; + + /* + * if the cliper leftmost edge is inside + * the destination area then the leftmost edge of the resulting + * clipped box is the leftmost edge of the cliper. + */ + if (a_clipper->x1 > dstClippedBox.x1) + dstClippedBox.x1 = a_clipper->x1 ; + + /* + * if the cliper top edge is inside the destination area + * then the bottom horizontal edge of the resulting clipped box + * is the bottom edge of the cliper + */ + if (a_clipper->y1 > dstClippedBox.y1) + dstClippedBox.y1 = a_clipper->y1 ; + + /*ditto for right edge*/ + if (a_clipper->x2 < dstClippedBox.x2) + dstClippedBox.x2 = a_clipper->x2 ; + + /*ditto for bottom edge*/ + if (a_clipper->y2 < dstClippedBox.y2) + dstClippedBox.y2 = a_clipper->y2 ; + + memcpy (a_result, &dstClippedBox, sizeof (dstClippedBox)) ; + return TRUE ; +} + static Bool EphyrLocalAtomToHost (int a_local_atom, int *a_host_atom) { @@ -601,6 +650,7 @@ EphyrQueryBestSize (KdScreenInfo *a_info, EPHYR_LOG ("leave\n") ; } + static int EphyrPutImage (KdScreenInfo *a_info, DrawablePtr a_drawable, @@ -620,9 +670,46 @@ EphyrPutImage (KdScreenInfo *a_info, RegionPtr a_clipping_region, pointer a_port_priv) { + EphyrPortPriv *port_priv = a_port_priv ; + BoxRec clipped_area, dst_box ; + int result=BadImplementation ; + int drw_x=0, drw_y=0, drw_w=0, drw_h=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_drawable, BadValue) ; + EPHYR_LOG ("enter\n") ; - return 0 ; + + dst_box.x1 = a_drw_x ; + dst_box.x2 = a_drw_x + a_drw_w; + dst_box.y1 = a_drw_y ; + dst_box.y2 = a_drw_y + a_drw_h; + + if (!DoSimpleClip (&dst_box, + REGION_EXTENTS (pScreen->pScreen, a_clipping_region), + &clipped_area)) { + EPHYR_LOG_ERROR ("failed to simple clip\n") ; + goto out ; + } + + drw_x = clipped_area.x1 ; + drw_y = clipped_area.y1 ; + drw_w = clipped_area.x2 - clipped_area.x1 ; + drw_h = clipped_area.y2 - clipped_area.y1 ; + + if (!EphyrHostXVPutImage (port_priv->port_number, + a_id, + drw_x, drw_y, drw_w, drw_h, + a_src_x, a_src_y, a_src_w, a_src_h, + a_width, a_height, a_buf)) { + EPHYR_LOG_ERROR ("EphyrHostXVPutImage() failed\n") ; + goto out ; + } + + result = Success ; + +out: EPHYR_LOG ("leave\n") ; + return result ; } static int diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c index 11cfe26fb..8a2762ff8 100644 --- a/hw/kdrive/ephyr/hostx.c +++ b/hw/kdrive/ephyr/hostx.c @@ -962,3 +962,8 @@ hostx_get_display(void) return HostX.dpy ; } +int +hostx_get_window(void) +{ + return HostX.win ; +} diff --git a/hw/kdrive/ephyr/hostx.h b/hw/kdrive/ephyr/hostx.h index dc8eb99e9..1d8cd70db 100644 --- a/hw/kdrive/ephyr/hostx.h +++ b/hw/kdrive/ephyr/hostx.h @@ -175,4 +175,7 @@ hostx_get_event(EphyrHostXEvent *ev); void* hostx_get_display(void) ; +int +hostx_get_window(void) ; + #endif From 1de89239bdfa68ded2ef25fbb7d08369f527f7a9 Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Sat, 4 Aug 2007 01:13:38 +0200 Subject: [PATCH 13/44] don't crash when hostX reports an error. * hw/kdrive/ephyr/ephyrhostvideo.c,h: (ephyrHostXVLogXErrorEvent): add this to log X error events. Heavily copied from libx11 (ephyrHostXVErrorHandler): new x error handler that logs the error but does not exits. (ephyrHostXVInit): add this to be called at the beginning of xvideo lifetime. It sets an xerror handler that does not exit. * hw/kdrive/ephyr/ephyrvideo.c: (ephyrXVPrivIsAttrValueValid): this validates an attribute value. (ephyrSetPortAttribute): before setting an attribute, validate the new value so that we don't send a buggy request to host X. * hw/kdrive/ephyr/*.c: fix case in ephyrvideo code. * hw/kdrive/ephyr/ephyr.c: fix a typo --- hw/kdrive/ephyr/ephyr.c | 2 +- hw/kdrive/ephyr/ephyrhostvideo.c | 183 ++++++++++++++++++++++++++---- hw/kdrive/ephyr/ephyrhostvideo.h | 46 ++++---- hw/kdrive/ephyr/ephyrvideo.c | 185 ++++++++++++++++++++----------- 4 files changed, 308 insertions(+), 108 deletions(-) diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c index 2cb7d0bd6..2febb655d 100644 --- a/hw/kdrive/ephyr/ephyr.c +++ b/hw/kdrive/ephyr/ephyr.c @@ -610,7 +610,7 @@ ephyrInitScreen (ScreenPtr pScreen) if (!ephyrInitVideo (pScreen)) { EPHYR_LOG_ERROR ("failed to initialize xvideo\n") ; } else { - EPHYR_LOG_ERROR ("initialized xvideo okay\n") ; + EPHYR_LOG ("initialized xvideo okay\n") ; } #endif /*XV*/ return TRUE; diff --git a/hw/kdrive/ephyr/ephyrhostvideo.c b/hw/kdrive/ephyr/ephyrhostvideo.c index c15a90429..1ccd994c0 100644 --- a/hw/kdrive/ephyr/ephyrhostvideo.c +++ b/hw/kdrive/ephyr/ephyrhostvideo.c @@ -108,8 +108,141 @@ struct _EphyrHostXVAdaptorArray { unsigned int nb_adaptors ; }; +/*heavily copied from libx11*/ +#define BUFSIZE 2048 +static void +ephyrHostXVLogXErrorEvent (Display *a_display, + XErrorEvent *a_err_event, + FILE *a_fp) +{ + char buffer[BUFSIZ]; + char mesg[BUFSIZ]; + char number[32]; + const char *mtype = "XlibMessage"; + register _XExtension *ext = (_XExtension *)NULL; + _XExtension *bext = (_XExtension *)NULL; + Display *dpy = a_display ; + + XGetErrorText(dpy, a_err_event->error_code, buffer, BUFSIZ); + XGetErrorDatabaseText(dpy, mtype, "XError", "X Error", mesg, BUFSIZ); + (void) fprintf(a_fp, "%s: %s\n ", mesg, buffer); + XGetErrorDatabaseText(dpy, mtype, "MajorCode", "Request Major code %d", + mesg, BUFSIZ); + (void) fprintf(a_fp, mesg, a_err_event->request_code); + if (a_err_event->request_code < 128) { + sprintf(number, "%d", a_err_event->request_code); + XGetErrorDatabaseText(dpy, "XRequest", number, "", buffer, BUFSIZ); + } else { + for (ext = dpy->ext_procs; + ext && (ext->codes.major_opcode != a_err_event->request_code); + ext = ext->next) + ; + if (ext) + strcpy(buffer, ext->name); + else + buffer[0] = '\0'; + } + (void) fprintf(a_fp, " (%s)\n", buffer); + if (a_err_event->request_code >= 128) { + XGetErrorDatabaseText(dpy, mtype, "MinorCode", "Request Minor code %d", + mesg, BUFSIZ); + fputs(" ", a_fp); + (void) fprintf(a_fp, mesg, a_err_event->minor_code); + if (ext) { + sprintf(mesg, "%s.%d", ext->name, a_err_event->minor_code); + XGetErrorDatabaseText(dpy, "XRequest", mesg, "", buffer, BUFSIZ); + (void) fprintf(a_fp, " (%s)", buffer); + } + fputs("\n", a_fp); + } + if (a_err_event->error_code >= 128) { + /* kludge, try to find the extension that caused it */ + buffer[0] = '\0'; + for (ext = dpy->ext_procs; ext; ext = ext->next) { + if (ext->error_string) + (*ext->error_string)(dpy, a_err_event->error_code, &ext->codes, + buffer, BUFSIZ); + if (buffer[0]) { + bext = ext; + break; + } + if (ext->codes.first_error && + ext->codes.first_error < (int)a_err_event->error_code && + (!bext || ext->codes.first_error > bext->codes.first_error)) + bext = ext; + } + if (bext) + sprintf(buffer, "%s.%d", bext->name, + a_err_event->error_code - bext->codes.first_error); + else + strcpy(buffer, "Value"); + XGetErrorDatabaseText(dpy, mtype, buffer, "", mesg, BUFSIZ); + if (mesg[0]) { + fputs(" ", a_fp); + (void) fprintf(a_fp, mesg, a_err_event->resourceid); + fputs("\n", a_fp); + } + /* let extensions try to print the values */ + for (ext = dpy->ext_procs; ext; ext = ext->next) { + if (ext->error_values) + (*ext->error_values)(dpy, a_err_event, a_fp); + } + } else if ((a_err_event->error_code == BadWindow) || + (a_err_event->error_code == BadPixmap) || + (a_err_event->error_code == BadCursor) || + (a_err_event->error_code == BadFont) || + (a_err_event->error_code == BadDrawable) || + (a_err_event->error_code == BadColor) || + (a_err_event->error_code == BadGC) || + (a_err_event->error_code == BadIDChoice) || + (a_err_event->error_code == BadValue) || + (a_err_event->error_code == BadAtom)) { + if (a_err_event->error_code == BadValue) + XGetErrorDatabaseText(dpy, mtype, "Value", "Value 0x%x", + mesg, BUFSIZ); + else if (a_err_event->error_code == BadAtom) + XGetErrorDatabaseText(dpy, mtype, "AtomID", "AtomID 0x%x", + mesg, BUFSIZ); + else + XGetErrorDatabaseText(dpy, mtype, "ResourceID", "ResourceID 0x%x", + mesg, BUFSIZ); + fputs(" ", a_fp); + (void) fprintf(a_fp, mesg, a_err_event->resourceid); + fputs("\n", a_fp); + } + XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d", + mesg, BUFSIZ); + fputs(" ", a_fp); + (void) fprintf(a_fp, mesg, a_err_event->serial); + XGetErrorDatabaseText(dpy, mtype, "CurrentSerial", "Current Serial #%d", + mesg, BUFSIZ); + fputs("\n ", a_fp); + (void) fprintf(a_fp, mesg, dpy->request); + fputs("\n", a_fp); +} + +static int +ephyrHostXVErrorHandler (Display *a_display, + XErrorEvent *a_error_event) +{ + EPHYR_LOG_ERROR ("got an error from the host xserver:\n") ; + ephyrHostXVLogXErrorEvent (a_display, a_error_event, stderr) ; + return Success ; +} + +void +ephyrHostXVInit (void) +{ + static Bool s_initialized ; + + if (s_initialized) + return ; + XSetErrorHandler (ephyrHostXVErrorHandler) ; + s_initialized = TRUE ; +} + Bool -EphyrHostXVQueryAdaptors (EphyrHostXVAdaptorArray **a_adaptors) +ephyrHostXVQueryAdaptors (EphyrHostXVAdaptorArray **a_adaptors) { EphyrHostXVAdaptorArray *result=NULL ; int ret=0 ; @@ -140,7 +273,7 @@ out: } void -EphyrHostXVAdaptorArrayDelete (EphyrHostXVAdaptorArray *a_adaptors) +ephyrHostXVAdaptorArrayDelete (EphyrHostXVAdaptorArray *a_adaptors) { if (!a_adaptors) return ; @@ -153,14 +286,14 @@ EphyrHostXVAdaptorArrayDelete (EphyrHostXVAdaptorArray *a_adaptors) } int -EphyrHostXVAdaptorArrayGetSize (const EphyrHostXVAdaptorArray *a_this) +ephyrHostXVAdaptorArrayGetSize (const EphyrHostXVAdaptorArray *a_this) { EPHYR_RETURN_VAL_IF_FAIL (a_this, -1) ; return a_this->nb_adaptors ; } EphyrHostXVAdaptor* -EphyrHostXVAdaptorArrayAt (const EphyrHostXVAdaptorArray *a_this, +ephyrHostXVAdaptorArrayAt (const EphyrHostXVAdaptorArray *a_this, int a_index) { EPHYR_RETURN_VAL_IF_FAIL (a_this, NULL) ; @@ -171,14 +304,14 @@ EphyrHostXVAdaptorArrayAt (const EphyrHostXVAdaptorArray *a_this, } char -EphyrHostXVAdaptorGetType (const EphyrHostXVAdaptor *a_this) +ephyrHostXVAdaptorGetType (const EphyrHostXVAdaptor *a_this) { EPHYR_RETURN_VAL_IF_FAIL (a_this, -1) ; return ((XvAdaptorInfo*)a_this)->type ; } const char* -EphyrHostXVAdaptorGetName (const EphyrHostXVAdaptor *a_this) +ephyrHostXVAdaptorGetName (const EphyrHostXVAdaptor *a_this) { EPHYR_RETURN_VAL_IF_FAIL (a_this, NULL) ; @@ -186,7 +319,7 @@ EphyrHostXVAdaptorGetName (const EphyrHostXVAdaptor *a_this) } EphyrHostVideoFormat* -EphyrHostXVAdaptorGetVideoFormats (const EphyrHostXVAdaptor *a_this, +ephyrHostXVAdaptorGetVideoFormats (const EphyrHostXVAdaptor *a_this, int *a_nb_formats) { EphyrHostVideoFormat *formats=NULL ; @@ -216,7 +349,7 @@ EphyrHostXVAdaptorGetVideoFormats (const EphyrHostXVAdaptor *a_this, } int -EphyrHostXVAdaptorGetNbPorts (const EphyrHostXVAdaptor *a_this) +ephyrHostXVAdaptorGetNbPorts (const EphyrHostXVAdaptor *a_this) { EPHYR_RETURN_VAL_IF_FAIL (a_this, -1) ; @@ -224,7 +357,7 @@ EphyrHostXVAdaptorGetNbPorts (const EphyrHostXVAdaptor *a_this) } int -EphyrHostXVAdaptorGetFirstPortID (const EphyrHostXVAdaptor *a_this) +ephyrHostXVAdaptorGetFirstPortID (const EphyrHostXVAdaptor *a_this) { EPHYR_RETURN_VAL_IF_FAIL (a_this, -1) ; @@ -232,7 +365,7 @@ EphyrHostXVAdaptorGetFirstPortID (const EphyrHostXVAdaptor *a_this) } Bool -EphyrHostXVQueryEncodings (int a_port_id, +ephyrHostXVQueryEncodings (int a_port_id, EphyrHostEncoding **a_encodings, unsigned int *a_num_encodings) { @@ -271,7 +404,7 @@ EphyrHostXVQueryEncodings (int a_port_id, } void -EphyrHostEncodingsDelete (EphyrHostEncoding *a_encodings, +ephyrHostEncodingsDelete (EphyrHostEncoding *a_encodings, int a_num_encodings) { int i=0 ; @@ -288,7 +421,7 @@ EphyrHostEncodingsDelete (EphyrHostEncoding *a_encodings, } void -EphyrHostAttributesDelete (EphyrHostAttribute *a_attributes) +ephyrHostAttributesDelete (EphyrHostAttribute *a_attributes) { if (!a_attributes) return ; @@ -296,7 +429,7 @@ EphyrHostAttributesDelete (EphyrHostAttribute *a_attributes) } Bool -EphyrHostXVQueryPortAttributes (int a_port_id, +ephyrHostXVQueryPortAttributes (int a_port_id, EphyrHostAttribute **a_attributes, int *a_num_attributes) { @@ -311,7 +444,7 @@ EphyrHostXVQueryPortAttributes (int a_port_id, } Bool -EphyrHostXVQueryImageFormats (int a_port_id, +ephyrHostXVQueryImageFormats (int a_port_id, EphyrHostImageFormat **a_formats, int *a_num_format) { @@ -328,13 +461,16 @@ EphyrHostXVQueryImageFormats (int a_port_id, } Bool -EphyrHostXVSetPortAttribute (int a_port_id, +ephyrHostXVSetPortAttribute (int a_port_id, int a_atom, int a_attr_value) { int res=Success ; - EPHYR_LOG ("atom,value: (%d, %d)\n", a_atom, a_attr_value) ; + EPHYR_LOG ("atom,name,value: (%d,%s,%d)\n", + a_atom, + XGetAtomName (hostx_get_display (), a_atom), + a_attr_value) ; res = XvSetPortAttribute (hostx_get_display (), a_port_id, @@ -344,13 +480,14 @@ EphyrHostXVSetPortAttribute (int a_port_id, EPHYR_LOG_ERROR ("XvSetPortAttribute() failed: %d\n", res) ; return FALSE ; } + XFlush (hostx_get_display ()) ; EPHYR_LOG ("leave\n") ; return TRUE ; } Bool -EphyrHostXVGetPortAttribute (int a_port_id, +ephyrHostXVGetPortAttribute (int a_port_id, int a_atom, int *a_attr_value) { @@ -380,7 +517,7 @@ out: } Bool -EphyrHostXVQueryBestSize (int a_port_id, +ephyrHostXVQueryBestSize (int a_port_id, Bool a_motion, unsigned int a_frame_w, unsigned int a_frame_h, @@ -458,7 +595,7 @@ xv_wire_to_event(Display *dpy, XEvent *host, xEvent *wire) } Bool -EphyrHostXVQueryImageAttributes (int a_port_id, +ephyrHostXVQueryImageAttributes (int a_port_id, int a_image_id /*image fourcc code*/, unsigned short *a_width, unsigned short *a_height, @@ -515,7 +652,7 @@ out: } Bool -EphyrHostGetAtom (const char* a_name, +ephyrHostGetAtom (const char* a_name, Bool a_create_if_not_exists, int *a_atom) { @@ -532,20 +669,20 @@ EphyrHostGetAtom (const char* a_name, } char* -EphyrHostGetAtomName (int a_atom) +ephyrHostGetAtomName (int a_atom) { return XGetAtomName (hostx_get_display (), a_atom) ; } void -EphyrHostFree (void *a_pointer) +ephyrHostFree (void *a_pointer) { if (a_pointer) XFree (a_pointer) ; } Bool -EphyrHostXVPutImage (int a_port_id, +ephyrHostXVPutImage (int a_port_id, int a_image_id, int a_drw_x, int a_drw_y, diff --git a/hw/kdrive/ephyr/ephyrhostvideo.h b/hw/kdrive/ephyr/ephyrhostvideo.h index 0e97bdee8..86154bcef 100644 --- a/hw/kdrive/ephyr/ephyrhostvideo.h +++ b/hw/kdrive/ephyr/ephyrhostvideo.h @@ -84,67 +84,69 @@ typedef struct _EphyrHostImageFormat { int scanline_order; /* XvTopToBottom, XvBottomToTop */ } EphyrHostImageFormat ; -void EphyrHostFree (void *a_pointer) ; +void ephyrHostXVInit (void) ; + +void ephyrHostFree (void *a_pointer) ; /* * host adaptor array */ -Bool EphyrHostXVQueryAdaptors (EphyrHostXVAdaptorArray **a_adaptors) ; -void EphyrHostXVAdaptorArrayDelete (EphyrHostXVAdaptorArray *a_adaptors) ; -int EphyrHostXVAdaptorArrayGetSize (const EphyrHostXVAdaptorArray *a_this) ; -EphyrHostXVAdaptor* EphyrHostXVAdaptorArrayAt (const EphyrHostXVAdaptorArray *a_this, +Bool ephyrHostXVQueryAdaptors (EphyrHostXVAdaptorArray **a_adaptors) ; +void ephyrHostXVAdaptorArrayDelete (EphyrHostXVAdaptorArray *a_adaptors) ; +int ephyrHostXVAdaptorArrayGetSize (const EphyrHostXVAdaptorArray *a_this) ; +EphyrHostXVAdaptor* ephyrHostXVAdaptorArrayAt (const EphyrHostXVAdaptorArray *a_this, int a_index) ; /* * host adaptor */ -char EphyrHostXVAdaptorGetType (const EphyrHostXVAdaptor *a_this) ; -const char* EphyrHostXVAdaptorGetName (const EphyrHostXVAdaptor *a_this) ; -EphyrHostVideoFormat* EphyrHostXVAdaptorGetVideoFormats +char ephyrHostXVAdaptorGetType (const EphyrHostXVAdaptor *a_this) ; +const char* ephyrHostXVAdaptorGetName (const EphyrHostXVAdaptor *a_this) ; +EphyrHostVideoFormat* ephyrHostXVAdaptorGetVideoFormats (const EphyrHostXVAdaptor *a_this, int *a_nb_formats) ; -int EphyrHostXVAdaptorGetNbPorts (const EphyrHostXVAdaptor *a_this) ; -int EphyrHostXVAdaptorGetFirstPortID (const EphyrHostXVAdaptor *a_this) ; +int ephyrHostXVAdaptorGetNbPorts (const EphyrHostXVAdaptor *a_this) ; +int ephyrHostXVAdaptorGetFirstPortID (const EphyrHostXVAdaptor *a_this) ; /* * encoding */ -Bool EphyrHostXVQueryEncodings (int a_port_id, +Bool ephyrHostXVQueryEncodings (int a_port_id, EphyrHostEncoding **a_encodings, unsigned int *a_num_encodings) ; -void EphyrHostEncodingsDelete (EphyrHostEncoding *a_encodings, +void ephyrHostEncodingsDelete (EphyrHostEncoding *a_encodings, int a_num_encodings) ; /* * attribute */ -Bool EphyrHostXVQueryPortAttributes (int a_port_id, +Bool ephyrHostXVQueryPortAttributes (int a_port_id, EphyrHostAttribute **a_attributes, int *a_num_attributes) ; -void EphyrHostAttributesDelete (EphyrHostAttribute *a_attributes) ; +void ephyrHostAttributesDelete (EphyrHostAttribute *a_attributes) ; /* * image format */ -Bool EphyrHostXVQueryImageFormats (int a_port_id, +Bool ephyrHostXVQueryImageFormats (int a_port_id, EphyrHostImageFormat **a_formats, int *a_num_format) ; /* * Port Attribute Get/Set */ -Bool EphyrHostXVSetPortAttribute (int a_port_id, +Bool ephyrHostXVSetPortAttribute (int a_port_id, int a_atom, int a_attr_value) ; -Bool EphyrHostXVGetPortAttribute (int a_port_id, +Bool ephyrHostXVGetPortAttribute (int a_port_id, int a_atom, int *a_attr_value) ; /* *size query */ -Bool EphyrHostXVQueryBestSize (int a_port_id, +Bool ephyrHostXVQueryBestSize (int a_port_id, Bool a_motion, unsigned int a_frame_w, unsigned int a_frame_h, @@ -153,7 +155,7 @@ Bool EphyrHostXVQueryBestSize (int a_port_id, unsigned int *a_actual_w, unsigned int *a_actual_h) ; -Bool EphyrHostXVQueryImageAttributes (int a_port_id, +Bool ephyrHostXVQueryImageAttributes (int a_port_id, int a_image_id /*image fourcc code*/, unsigned short *a_width, unsigned short *a_height, @@ -163,16 +165,16 @@ Bool EphyrHostXVQueryImageAttributes (int a_port_id, /* * atom */ -Bool EphyrHostGetAtom (const char* a_name, +Bool ephyrHostGetAtom (const char* a_name, Bool a_create_if_not_exists, int *a_atom) ; -char* EphyrHostGetAtomName (int a_atom) ; +char* ephyrHostGetAtomName (int a_atom) ; /* *PutImage * (ignore clipping for now) */ -Bool EphyrHostXVPutImage (int a_port_id, +Bool ephyrHostXVPutImage (int a_port_id, int a_image_id, int a_drw_x, int a_drw_y, diff --git a/hw/kdrive/ephyr/ephyrvideo.c b/hw/kdrive/ephyr/ephyrvideo.c index 9cd479bcc..5cd9d178b 100644 --- a/hw/kdrive/ephyr/ephyrvideo.c +++ b/hw/kdrive/ephyr/ephyrvideo.c @@ -47,6 +47,7 @@ typedef struct _EphyrXVPriv EphyrXVPriv ; struct _EphyrPortPriv { int port_number ; + KdVideoAdaptorPtr current_adaptor ; EphyrXVPriv *xv_priv; }; typedef struct _EphyrPortPriv EphyrPortPriv ; @@ -55,31 +56,38 @@ static Bool DoSimpleClip (BoxPtr a_dst_drw, BoxPtr a_clipper, BoxPtr a_result) ; -static Bool EphyrLocalAtomToHost (int a_local_atom, int *a_host_atom) ; +static Bool ephyrLocalAtomToHost (int a_local_atom, int *a_host_atom) ; -static Bool EphyrHostAtomToLocal (int a_host_atom, int *a_local_atom) ; +static Bool ephyrHostAtomToLocal (int a_host_atom, int *a_local_atom) ; -static EphyrXVPriv* EphyrXVPrivNew (void) ; -static void EphyrXVPrivDelete (EphyrXVPriv *a_this) ; -static Bool EphyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) ; -static Bool EphyrXVPrivSetAdaptorsHooks (EphyrXVPriv *a_this) ; -static Bool EphyrXVPrivRegisterAdaptors (EphyrXVPriv *a_this, +static EphyrXVPriv* ephyrXVPrivNew (void) ; +static void ephyrXVPrivDelete (EphyrXVPriv *a_this) ; +static Bool ephyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) ; +static Bool ephyrXVPrivSetAdaptorsHooks (EphyrXVPriv *a_this) ; +static Bool ephyrXVPrivRegisterAdaptors (EphyrXVPriv *a_this, ScreenPtr a_screen) ; -static void EphyrStopVideo (KdScreenInfo *a_info, + +static Bool ephyrXVPrivIsAttrValueValid (KdAttributePtr a_attrs, + int a_attrs_len, + const char *a_attr_name, + int a_attr_value, + Bool *a_is_valid) ; + +static void ephyrStopVideo (KdScreenInfo *a_info, pointer a_xv_priv, Bool a_exit); -static int EphyrSetPortAttribute (KdScreenInfo *a_info, +static int ephyrSetPortAttribute (KdScreenInfo *a_info, Atom a_attr_name, int a_attr_value, pointer a_port_priv); -static int EphyrGetPortAttribute (KdScreenInfo *a_screen_info, +static int ephyrGetPortAttribute (KdScreenInfo *a_screen_info, Atom a_attr_name, int *a_attr_value, pointer a_port_priv); -static void EphyrQueryBestSize (KdScreenInfo *a_info, +static void ephyrQueryBestSize (KdScreenInfo *a_info, Bool a_motion, short a_src_w, short a_src_h, @@ -89,7 +97,7 @@ static void EphyrQueryBestSize (KdScreenInfo *a_info, unsigned int *a_prefered_h, pointer a_port_priv); -static int EphyrPutImage (KdScreenInfo *a_info, +static int ephyrPutImage (KdScreenInfo *a_info, DrawablePtr a_drawable, short a_src_x, short a_src_y, @@ -107,7 +115,7 @@ static int EphyrPutImage (KdScreenInfo *a_info, RegionPtr a_clipping_region, pointer a_port_priv); -static int EphyrQueryImageAttributes (KdScreenInfo *a_info, +static int ephyrQueryImageAttributes (KdScreenInfo *a_info, int a_id, unsigned short *a_w, unsigned short *a_h, @@ -165,7 +173,7 @@ DoSimpleClip (BoxPtr a_dst_box, } static Bool -EphyrLocalAtomToHost (int a_local_atom, int *a_host_atom) +ephyrLocalAtomToHost (int a_local_atom, int *a_host_atom) { char *atom_name=NULL; int host_atom=None ; @@ -180,7 +188,7 @@ EphyrLocalAtomToHost (int a_local_atom, int *a_host_atom) if (!atom_name) return FALSE ; - if (!EphyrHostGetAtom (atom_name, FALSE, &host_atom) || host_atom == None) { + if (!ephyrHostGetAtom (atom_name, FALSE, &host_atom) || host_atom == None) { EPHYR_LOG_ERROR ("no atom for string %s defined in host X\n", atom_name) ; return FALSE ; @@ -190,7 +198,7 @@ EphyrLocalAtomToHost (int a_local_atom, int *a_host_atom) } static Bool -EphyrHostAtomToLocal (int a_host_atom, int *a_local_atom) +ephyrHostAtomToLocal (int a_host_atom, int *a_local_atom) { Bool is_ok=FALSE ; char *atom_name=NULL ; @@ -198,7 +206,7 @@ EphyrHostAtomToLocal (int a_host_atom, int *a_local_atom) EPHYR_RETURN_VAL_IF_FAIL (a_local_atom, FALSE) ; - atom_name = EphyrHostGetAtomName (a_host_atom) ; + atom_name = ephyrHostGetAtomName (a_host_atom) ; if (!atom_name) goto out ; @@ -211,7 +219,7 @@ EphyrHostAtomToLocal (int a_host_atom, int *a_local_atom) out: if (atom_name) { - EphyrHostFree (atom_name) ; + ephyrHostFree (atom_name) ; } return is_ok ; } @@ -234,13 +242,13 @@ ephyrInitVideo (ScreenPtr pScreen) return FALSE ; } - xv_priv = EphyrXVPrivNew () ; + xv_priv = ephyrXVPrivNew () ; if (!xv_priv) { EPHYR_LOG_ERROR ("failed to create xv_priv\n") ; return FALSE ; } - if (!EphyrXVPrivRegisterAdaptors (xv_priv, pScreen)) { + if (!ephyrXVPrivRegisterAdaptors (xv_priv, pScreen)) { EPHYR_LOG_ERROR ("failed to register adaptors\n") ; return FALSE ; } @@ -248,7 +256,7 @@ ephyrInitVideo (ScreenPtr pScreen) } static EphyrXVPriv* -EphyrXVPrivNew (void) +ephyrXVPrivNew (void) { EphyrXVPriv *xv_priv=NULL ; @@ -259,11 +267,14 @@ EphyrXVPrivNew (void) EPHYR_LOG_ERROR ("failed to create EphyrXVPriv\n") ; goto error ; } - if (!EphyrXVPrivQueryHostAdaptors (xv_priv)) { + + ephyrHostXVInit () ; + + if (!ephyrXVPrivQueryHostAdaptors (xv_priv)) { EPHYR_LOG_ERROR ("failed to query the host x for xv properties\n") ; goto error ; } - if (!EphyrXVPrivSetAdaptorsHooks (xv_priv)) { + if (!ephyrXVPrivSetAdaptorsHooks (xv_priv)) { EPHYR_LOG_ERROR ("failed to set xv_priv hooks\n") ; goto error ; } @@ -273,21 +284,21 @@ EphyrXVPrivNew (void) error: if (xv_priv) { - EphyrXVPrivDelete (xv_priv) ; + ephyrXVPrivDelete (xv_priv) ; xv_priv = NULL ; } return NULL ; } static void -EphyrXVPrivDelete (EphyrXVPriv *a_this) +ephyrXVPrivDelete (EphyrXVPriv *a_this) { EPHYR_LOG ("enter\n") ; if (!a_this) return ; if (a_this->host_adaptors) { - EphyrHostXVAdaptorArrayDelete (a_this->host_adaptors) ; + ephyrHostXVAdaptorArrayDelete (a_this->host_adaptors) ; a_this->host_adaptors = NULL ; } if (a_this->adaptors) { @@ -343,7 +354,7 @@ portAttributesDup (EphyrHostAttribute *a_encodings, } static Bool -EphyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) +ephyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) { EphyrHostXVAdaptor *cur_host_adaptor=NULL ; EphyrHostVideoFormat *video_formats=NULL ; @@ -359,13 +370,13 @@ EphyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) EPHYR_LOG ("enter\n") ; - if (!EphyrHostXVQueryAdaptors (&a_this->host_adaptors)) { + if (!ephyrHostXVQueryAdaptors (&a_this->host_adaptors)) { EPHYR_LOG_ERROR ("failed to query host adaptors\n") ; goto out ; } if (a_this->host_adaptors) a_this->num_adaptors = - EphyrHostXVAdaptorArrayGetSize (a_this->host_adaptors) ; + ephyrHostXVAdaptorArrayGetSize (a_this->host_adaptors) ; if (a_this->num_adaptors < 0) { EPHYR_LOG_ERROR ("failed to get number of host adaptors\n") ; goto out ; @@ -385,20 +396,20 @@ EphyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) for (i=0; i < a_this->num_adaptors; i++) { int j=0 ; cur_host_adaptor = - EphyrHostXVAdaptorArrayAt (a_this->host_adaptors, i) ; + ephyrHostXVAdaptorArrayAt (a_this->host_adaptors, i) ; if (!cur_host_adaptor) continue ; a_this->adaptors[i].type = - EphyrHostXVAdaptorGetType (cur_host_adaptor) ; + ephyrHostXVAdaptorGetType (cur_host_adaptor) ; a_this->adaptors[i].type |= XvWindowMask ; a_this->adaptors[i].flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; - if (EphyrHostXVAdaptorGetName (cur_host_adaptor)) + if (ephyrHostXVAdaptorGetName (cur_host_adaptor)) a_this->adaptors[i].name = - strdup (EphyrHostXVAdaptorGetName (cur_host_adaptor)) ; + strdup (ephyrHostXVAdaptorGetName (cur_host_adaptor)) ; else a_this->adaptors[i].name = strdup ("Xephyr Video Overlay"); - base_port_id = EphyrHostXVAdaptorGetFirstPortID (cur_host_adaptor) ; + base_port_id = ephyrHostXVAdaptorGetFirstPortID (cur_host_adaptor) ; if (base_port_id < 0) { EPHYR_LOG_ERROR ("failed to get port id for adaptor %d\n", i) ; continue ; @@ -406,7 +417,7 @@ EphyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) if (!s_base_port_id) s_base_port_id = base_port_id ; - if (!EphyrHostXVQueryEncodings (base_port_id, + if (!ephyrHostXVQueryEncodings (base_port_id, &encodings, &num_encodings)) { EPHYR_LOG_ERROR ("failed to get encodings for port port id %d," @@ -418,12 +429,12 @@ EphyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) a_this->adaptors[i].pEncodings = videoEncodingDup (encodings, num_encodings) ; video_formats = (EphyrHostVideoFormat*) - EphyrHostXVAdaptorGetVideoFormats (cur_host_adaptor, + ephyrHostXVAdaptorGetVideoFormats (cur_host_adaptor, &num_video_formats); a_this->adaptors[i].pFormats = (KdVideoFormatPtr) video_formats ; a_this->adaptors[i].nFormats = num_video_formats ; a_this->adaptors[i].nPorts = - EphyrHostXVAdaptorGetNbPorts (cur_host_adaptor) ; + ephyrHostXVAdaptorGetNbPorts (cur_host_adaptor) ; a_this->adaptors[i].pPortPrivates = xcalloc (a_this->adaptors[i].nPorts, sizeof (DevUnion) + sizeof (EphyrPortPriv)) ; @@ -433,10 +444,11 @@ EphyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) (EphyrPortPriv*) &a_this->adaptors[i].pPortPrivates[port_priv_offset + j]; port_priv->port_number = base_port_id + j; + port_priv->current_adaptor = &a_this->adaptors[i] ; port_priv->xv_priv = a_this ; a_this->adaptors[i].pPortPrivates[j].ptr = port_priv; } - if (!EphyrHostXVQueryPortAttributes (base_port_id, + if (!ephyrHostXVQueryPortAttributes (base_port_id, &attributes, &num_attributes)) { EPHYR_LOG_ERROR ("failed to get port attribute " @@ -446,7 +458,7 @@ EphyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) a_this->adaptors[i].pAttributes = portAttributesDup (attributes, num_attributes); a_this->adaptors[i].nAttributes = num_attributes ; - if (!EphyrHostXVQueryImageFormats (base_port_id, + if (!ephyrHostXVQueryImageFormats (base_port_id, &image_formats, &num_formats)) { EPHYR_LOG_ERROR ("failed to get image formats " @@ -460,11 +472,11 @@ EphyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) out: if (encodings) { - EphyrHostEncodingsDelete (encodings, num_encodings) ; + ephyrHostEncodingsDelete (encodings, num_encodings) ; encodings = NULL ; } if (attributes) { - EphyrHostAttributesDelete (attributes) ; + ephyrHostAttributesDelete (attributes) ; attributes = NULL ; } EPHYR_LOG ("leave\n") ; @@ -472,7 +484,7 @@ out: } static Bool -EphyrXVPrivSetAdaptorsHooks (EphyrXVPriv *a_this) +ephyrXVPrivSetAdaptorsHooks (EphyrXVPriv *a_this) { int i=0 ; @@ -481,19 +493,19 @@ EphyrXVPrivSetAdaptorsHooks (EphyrXVPriv *a_this) EPHYR_LOG ("enter\n") ; for (i=0; i < a_this->num_adaptors; i++) { - a_this->adaptors[i].StopVideo = EphyrStopVideo ; - a_this->adaptors[i].SetPortAttribute = EphyrSetPortAttribute ; - a_this->adaptors[i].GetPortAttribute = EphyrGetPortAttribute ; - a_this->adaptors[i].QueryBestSize = EphyrQueryBestSize ; - a_this->adaptors[i].PutImage = EphyrPutImage; - a_this->adaptors[i].QueryImageAttributes = EphyrQueryImageAttributes ; + a_this->adaptors[i].StopVideo = ephyrStopVideo ; + a_this->adaptors[i].SetPortAttribute = ephyrSetPortAttribute ; + a_this->adaptors[i].GetPortAttribute = ephyrGetPortAttribute ; + a_this->adaptors[i].QueryBestSize = ephyrQueryBestSize ; + a_this->adaptors[i].PutImage = ephyrPutImage; + a_this->adaptors[i].QueryImageAttributes = ephyrQueryImageAttributes ; } EPHYR_LOG ("leave\n") ; return TRUE ; } static Bool -EphyrXVPrivRegisterAdaptors (EphyrXVPriv *a_this, +ephyrXVPrivRegisterAdaptors (EphyrXVPriv *a_this, ScreenPtr a_screen) { KdScreenPriv(a_screen); @@ -540,23 +552,55 @@ out: return is_ok ; } +static Bool +ephyrXVPrivIsAttrValueValid (KdAttributePtr a_attrs, + int a_attrs_len, + const char *a_attr_name, + int a_attr_value, + Bool *a_is_valid) +{ + int i=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_attrs && a_attr_name && a_is_valid, + FALSE) ; + + for (i=0; i < a_attrs_len; i++) { + if (a_attrs[i].name && strcmp (a_attrs[i].name, a_attr_name)) + continue ; + if (a_attrs[i].min_value > a_attr_value || + a_attrs[i].max_value < a_attr_value) { + *a_is_valid = FALSE ; + } else { + *a_is_valid = TRUE ; + } + return TRUE ; + } + return FALSE ; +} + static void -EphyrStopVideo (KdScreenInfo *a_info, pointer a_port_priv, Bool a_exit) +ephyrStopVideo (KdScreenInfo *a_info, pointer a_port_priv, Bool a_exit) { EPHYR_LOG ("enter\n") ; EPHYR_LOG ("leave\n") ; } static int -EphyrSetPortAttribute (KdScreenInfo *a_info, +ephyrSetPortAttribute (KdScreenInfo *a_info, Atom a_attr_name, int a_attr_value, pointer a_port_priv) { int res=Success, host_atom=0 ; EphyrPortPriv *port_priv = a_port_priv ; + Bool is_attr_valid=FALSE ; EPHYR_RETURN_VAL_IF_FAIL (port_priv, BadMatch) ; + EPHYR_RETURN_VAL_IF_FAIL (port_priv->current_adaptor, BadMatch) ; + EPHYR_RETURN_VAL_IF_FAIL (port_priv->current_adaptor->pAttributes, + BadMatch) ; + EPHYR_RETURN_VAL_IF_FAIL (port_priv->current_adaptor->nAttributes, + BadMatch) ; EPHYR_RETURN_VAL_IF_FAIL (ValidAtom (a_attr_name), BadMatch) ; EPHYR_LOG ("enter, portnum:%d, atomid:%d, attr_name:%s, attr_val:%d\n", @@ -565,13 +609,30 @@ EphyrSetPortAttribute (KdScreenInfo *a_info, NameForAtom (a_attr_name), a_attr_value) ; - if (!EphyrLocalAtomToHost (a_attr_name, &host_atom)) { + if (!ephyrLocalAtomToHost (a_attr_name, &host_atom)) { EPHYR_LOG_ERROR ("failed to convert local atom to host atom\n") ; res = BadMatch ; goto out ; } - if (!EphyrHostXVSetPortAttribute (port_priv->port_number, + if (!ephyrXVPrivIsAttrValueValid (port_priv->current_adaptor->pAttributes, + port_priv->current_adaptor->nAttributes, + NameForAtom (a_attr_name), + a_attr_value, + &is_attr_valid)) { + EPHYR_LOG_ERROR ("failed to validate attribute %s\n", + NameForAtom (a_attr_name)) ; + res = BadMatch ; + goto out ; + } + if (!is_attr_valid) { + EPHYR_LOG_ERROR ("attribute %s is not valid\n", + NameForAtom (a_attr_name)) ; + res = BadMatch ; + goto out ; + } + + if (!ephyrHostXVSetPortAttribute (port_priv->port_number, host_atom, a_attr_value)) { EPHYR_LOG_ERROR ("failed to set port attribute\n") ; @@ -586,7 +647,7 @@ out: } static int -EphyrGetPortAttribute (KdScreenInfo *a_screen_info, +ephyrGetPortAttribute (KdScreenInfo *a_screen_info, Atom a_attr_name, int *a_attr_value, pointer a_port_priv) @@ -602,13 +663,13 @@ EphyrGetPortAttribute (KdScreenInfo *a_screen_info, (int)a_attr_name, NameForAtom (a_attr_name)) ; - if (!EphyrLocalAtomToHost (a_attr_name, &host_atom)) { + if (!ephyrLocalAtomToHost (a_attr_name, &host_atom)) { EPHYR_LOG_ERROR ("failed to convert local atom to host atom\n") ; res = BadMatch ; goto out ; } - if (!EphyrHostXVGetPortAttribute (port_priv->port_number, + if (!ephyrHostXVGetPortAttribute (port_priv->port_number, host_atom, a_attr_value)) { EPHYR_LOG_ERROR ("failed to get port attribute\n") ; @@ -623,7 +684,7 @@ out: } static void -EphyrQueryBestSize (KdScreenInfo *a_info, +ephyrQueryBestSize (KdScreenInfo *a_info, Bool a_motion, short a_src_w, short a_src_h, @@ -639,7 +700,7 @@ EphyrQueryBestSize (KdScreenInfo *a_info, EPHYR_RETURN_IF_FAIL (port_priv) ; EPHYR_LOG ("enter\n") ; - res = EphyrHostXVQueryBestSize (port_priv->port_number, + res = ephyrHostXVQueryBestSize (port_priv->port_number, a_motion, a_src_w, a_src_h, a_drw_w, a_drw_h, @@ -652,7 +713,7 @@ EphyrQueryBestSize (KdScreenInfo *a_info, static int -EphyrPutImage (KdScreenInfo *a_info, +ephyrPutImage (KdScreenInfo *a_info, DrawablePtr a_drawable, short a_src_x, short a_src_y, @@ -696,7 +757,7 @@ EphyrPutImage (KdScreenInfo *a_info, drw_w = clipped_area.x2 - clipped_area.x1 ; drw_h = clipped_area.y2 - clipped_area.y1 ; - if (!EphyrHostXVPutImage (port_priv->port_number, + if (!ephyrHostXVPutImage (port_priv->port_number, a_id, drw_x, drw_y, drw_w, drw_h, a_src_x, a_src_y, a_src_w, a_src_h, @@ -713,7 +774,7 @@ out: } static int -EphyrQueryImageAttributes (KdScreenInfo *a_info, +ephyrQueryImageAttributes (KdScreenInfo *a_info, int a_id, unsigned short *a_w, unsigned short *a_h, @@ -727,7 +788,7 @@ EphyrQueryImageAttributes (KdScreenInfo *a_info, EPHYR_LOG ("enter: dim (%dx%d), pitches: %#x, offsets: %#x\n", *a_w, *a_h, (unsigned int)a_pitches, (unsigned int)a_offsets) ; - if (!EphyrHostXVQueryImageAttributes (s_base_port_id, + if (!ephyrHostXVQueryImageAttributes (s_base_port_id, a_id, a_w, a_h, &image_size, From 6f7961bc218169aaa0d10cfad0952adb7fac2f00 Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Mon, 6 Aug 2007 18:38:54 +0200 Subject: [PATCH 14/44] advertise only the hooks implemented by host X * hw/kdrive/ephyr/ephyrhostvideo.c,h: (ephyrHostXVAdaptorHasPutVideo): detect if host X has the PutVideo call. (ephyrHostXVAdaptorHasPutStill): detect if host X has the PutStill call (ephyrHostXVAdaptorHasPutImage): detect if host X has the PutImage call * hw/kdrive/ephyr/ephyrvideo.c: (ephyrXVPrivQueryHostAdaptors): make sure to create atoms for attribute names otherwise subsequent calls to get/set attribute from clients won't work. (ephyrXVPrivSetAdaptorsHooks): don't hardwire advertising of the PutImage call. Instead, advertise the calls advertised by the host. --- hw/kdrive/ephyr/ephyrhostvideo.c | 41 +++++++++++++++- hw/kdrive/ephyr/ephyrhostvideo.h | 7 +++ hw/kdrive/ephyr/ephyrvideo.c | 84 +++++++++++++++++++++++++++++++- 3 files changed, 130 insertions(+), 2 deletions(-) diff --git a/hw/kdrive/ephyr/ephyrhostvideo.c b/hw/kdrive/ephyr/ephyrhostvideo.c index 1ccd994c0..33109933a 100644 --- a/hw/kdrive/ephyr/ephyrhostvideo.c +++ b/hw/kdrive/ephyr/ephyrhostvideo.c @@ -364,6 +364,45 @@ ephyrHostXVAdaptorGetFirstPortID (const EphyrHostXVAdaptor *a_this) return ((XvAdaptorInfo*)a_this)->base_id ; } +Bool +ephyrHostXVAdaptorHasPutVideo (const EphyrHostXVAdaptor *a_this, + Bool *a_result) +{ + EPHYR_RETURN_VAL_IF_FAIL (a_this && a_result, FALSE) ; + + if (((XvAdaptorInfo*)a_this)->type & XvVideoMask) + *a_result = TRUE ; + else + *a_result = FALSE ; + return TRUE ; +} + +Bool +ephyrHostXVAdaptorHasPutStill (const EphyrHostXVAdaptor *a_this, + Bool *a_result) +{ + EPHYR_RETURN_VAL_IF_FAIL (a_this && a_result, FALSE) ; + + if (((XvAdaptorInfo*)a_this)->type & XvStillMask) + *a_result = TRUE ; + else + *a_result = FALSE ; + return TRUE ; +} + +Bool +ephyrHostXVAdaptorHasPutImage (const EphyrHostXVAdaptor *a_this, + Bool *a_result) +{ + EPHYR_RETURN_VAL_IF_FAIL (a_this && a_result, FALSE) ; + + if (((XvAdaptorInfo*)a_this)->type & XvImageMask) + *a_result = TRUE ; + else + *a_result = FALSE ; + return TRUE ; +} + Bool ephyrHostXVQueryEncodings (int a_port_id, EphyrHostEncoding **a_encodings, @@ -545,9 +584,9 @@ ephyrHostXVQueryBestSize (int a_port_id, EPHYR_LOG_ERROR ("XvQueryBestSize() failed: %d\n", res) ; goto out ; } + XSync (hostx_get_display (), FALSE) ; EPHYR_LOG ("actual (%dx%d)\n", *a_actual_w, *a_actual_h) ; - is_ok = TRUE ; out: diff --git a/hw/kdrive/ephyr/ephyrhostvideo.h b/hw/kdrive/ephyr/ephyrhostvideo.h index 86154bcef..94994463a 100644 --- a/hw/kdrive/ephyr/ephyrhostvideo.h +++ b/hw/kdrive/ephyr/ephyrhostvideo.h @@ -109,6 +109,13 @@ EphyrHostVideoFormat* ephyrHostXVAdaptorGetVideoFormats int ephyrHostXVAdaptorGetNbPorts (const EphyrHostXVAdaptor *a_this) ; int ephyrHostXVAdaptorGetFirstPortID (const EphyrHostXVAdaptor *a_this) ; +Bool ephyrHostXVAdaptorHasPutVideo (const EphyrHostXVAdaptor *a_this, + Bool *a_result) ; +Bool ephyrHostXVAdaptorHasPutStill (const EphyrHostXVAdaptor *a_this, + Bool *a_result) ; +Bool ephyrHostXVAdaptorHasPutImage (const EphyrHostXVAdaptor *a_this, + Bool *a_result) ; + /* * encoding */ diff --git a/hw/kdrive/ephyr/ephyrvideo.c b/hw/kdrive/ephyr/ephyrvideo.c index 5cd9d178b..8ac220476 100644 --- a/hw/kdrive/ephyr/ephyrvideo.c +++ b/hw/kdrive/ephyr/ephyrvideo.c @@ -97,6 +97,24 @@ static void ephyrQueryBestSize (KdScreenInfo *a_info, unsigned int *a_prefered_h, pointer a_port_priv); +static int ephyrPutVideo (KdScreenInfo *a_screen, + DrawablePtr a_drw, + short a_vid_x, short a_vid_y, + short a_drw_x, short a_drw_y, + short a_vid_w, short a_vid_h, + short a_drw_w, short a_drw_h, + RegionPtr a_clip_region, + pointer a_port_priv) ; + +static int ephyrPutStill (KdScreenInfo *a_screen, + DrawablePtr a_drw, + short a_vid_x, short a_vid_y, + short a_drw_x, short a_drw_y, + short a_vid_w, short a_vid_h, + short a_drw_w, short a_drw_h, + RegionPtr a_clip_region, + pointer a_port_priv) ; + static int ephyrPutImage (KdScreenInfo *a_info, DrawablePtr a_drawable, short a_src_x, @@ -458,6 +476,13 @@ ephyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) a_this->adaptors[i].pAttributes = portAttributesDup (attributes, num_attributes); a_this->adaptors[i].nAttributes = num_attributes ; + /*make sure atoms of attrs names are created in xephyr*/ + for (j=0; j < a_this->adaptors[i].nAttributes; j++) { + if (a_this->adaptors[i].pAttributes[j].name) + MakeAtom (a_this->adaptors[i].pAttributes[j].name, + strlen (a_this->adaptors[i].pAttributes[j].name), + TRUE) ; + } if (!ephyrHostXVQueryImageFormats (base_port_id, &image_formats, &num_formats)) { @@ -487,6 +512,8 @@ static Bool ephyrXVPrivSetAdaptorsHooks (EphyrXVPriv *a_this) { int i=0 ; + Bool has_it=FALSE ; + EphyrHostXVAdaptor *cur_host_adaptor=NULL ; EPHYR_RETURN_VAL_IF_FAIL (a_this, FALSE) ; @@ -497,8 +524,34 @@ ephyrXVPrivSetAdaptorsHooks (EphyrXVPriv *a_this) a_this->adaptors[i].SetPortAttribute = ephyrSetPortAttribute ; a_this->adaptors[i].GetPortAttribute = ephyrGetPortAttribute ; a_this->adaptors[i].QueryBestSize = ephyrQueryBestSize ; - a_this->adaptors[i].PutImage = ephyrPutImage; a_this->adaptors[i].QueryImageAttributes = ephyrQueryImageAttributes ; + + cur_host_adaptor = + ephyrHostXVAdaptorArrayAt (a_this->host_adaptors, i) ; + if (!cur_host_adaptor) { + EPHYR_LOG_ERROR ("failed to get host adaptor at index %d\n", i) ; + continue ; + } + has_it = FALSE ; + if (!ephyrHostXVAdaptorHasPutImage (cur_host_adaptor, &has_it)) { + EPHYR_LOG_ERROR ("error\n") ; + } + if (has_it) + a_this->adaptors[i].PutImage = ephyrPutImage; + + has_it = FALSE ; + if (!ephyrHostXVAdaptorHasPutVideo (cur_host_adaptor, &has_it)) { + EPHYR_LOG_ERROR ("error\n") ; + } + if (has_it) + a_this->adaptors[i].PutVideo = ephyrPutVideo; + + has_it = FALSE ; + if (!ephyrHostXVAdaptorHasPutStill (cur_host_adaptor, &has_it)) { + EPHYR_LOG_ERROR ("error\n") ; + } + if (has_it) + a_this->adaptors[i].PutStill = ephyrPutStill; } EPHYR_LOG ("leave\n") ; return TRUE ; @@ -711,6 +764,35 @@ ephyrQueryBestSize (KdScreenInfo *a_info, EPHYR_LOG ("leave\n") ; } +static int +ephyrPutVideo (KdScreenInfo *a_screen, + DrawablePtr a_drw, + short a_vid_x, short a_vid_y, + short a_drw_x, short a_drw_y, + short a_vid_w, short a_vid_h, + short a_drw_w, short a_drw_h, + RegionPtr a_clip_region, + pointer a_port_priv) +{ + EPHYR_LOG ("enter\n") ; + return Success ; + EPHYR_LOG ("leave\n") ; +} + +static int +ephyrPutStill (KdScreenInfo *a_screen, + DrawablePtr a_drw, + short a_vid_x, short a_vid_y, + short a_drw_x, short a_drw_y, + short a_vid_w, short a_vid_h, + short a_drw_w, short a_drw_h, + RegionPtr a_clip_region, + pointer a_port_priv) +{ + EPHYR_LOG ("enter\n") ; + return Success ; + EPHYR_LOG ("leave\n") ; +} static int ephyrPutImage (KdScreenInfo *a_info, From 4ed083095a13ec92bb4c8e705f26500f8312c138 Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Tue, 7 Aug 2007 14:16:13 +0200 Subject: [PATCH 15/44] add [Get/Put]Video and [Get/Put]Still support * hw/kdrive/ephyr/ephyrhostvideo.c,h: (ephyrHostXVAdaptorHasXXX): fix these. (ephyrHostXVAdaptorHasGetVideo): added this (ephyrHostXVAdaptorHasGetStill): ditto (ephyrHostXVPutVideo): added this (ephyrHostXVGetVideo): ditto (ephyrHostXVPutStill): ditto (ephyrHostXVGetStill): ditto * hw/kdrive/ephyr/ephyrvideo.c: (ephyrPutVideo): implement this (ephyrGetVideo): ditto (ephyrPutStill): ditto (ephyrGetStill): ditto (ephyrXVPrivSetAdaptorsHooks): advertise GetVideo and GetStill when the host X supports it. --- hw/kdrive/ephyr/ephyrhostvideo.c | 190 +++++++++++++++++++- hw/kdrive/ephyr/ephyrhostvideo.h | 22 +++ hw/kdrive/ephyr/ephyrvideo.c | 294 ++++++++++++++++++++++++++----- 3 files changed, 452 insertions(+), 54 deletions(-) diff --git a/hw/kdrive/ephyr/ephyrhostvideo.c b/hw/kdrive/ephyr/ephyrhostvideo.c index 33109933a..b1b926a45 100644 --- a/hw/kdrive/ephyr/ephyrhostvideo.c +++ b/hw/kdrive/ephyr/ephyrhostvideo.c @@ -370,7 +370,18 @@ ephyrHostXVAdaptorHasPutVideo (const EphyrHostXVAdaptor *a_this, { EPHYR_RETURN_VAL_IF_FAIL (a_this && a_result, FALSE) ; - if (((XvAdaptorInfo*)a_this)->type & XvVideoMask) + if (((XvAdaptorInfo*)a_this)->type & XvVideoMask & XvInputMask) + *a_result = TRUE ; + else + *a_result = FALSE ; + return TRUE ; +} + +Bool +ephyrHostXVAdaptorHasGetVideo (const EphyrHostXVAdaptor *a_this, + Bool *a_result) +{ + if (((XvAdaptorInfo*)a_this)->type & XvVideoMask & XvOutputMask) *a_result = TRUE ; else *a_result = FALSE ; @@ -383,7 +394,20 @@ ephyrHostXVAdaptorHasPutStill (const EphyrHostXVAdaptor *a_this, { EPHYR_RETURN_VAL_IF_FAIL (a_this && a_result, FALSE) ; - if (((XvAdaptorInfo*)a_this)->type & XvStillMask) + if (((XvAdaptorInfo*)a_this)->type & XvStillMask && XvInputMask) + *a_result = TRUE ; + else + *a_result = FALSE ; + return TRUE ; +} + +Bool +ephyrHostXVAdaptorHasGetStill (const EphyrHostXVAdaptor *a_this, + Bool *a_result) +{ + EPHYR_RETURN_VAL_IF_FAIL (a_this && a_result, FALSE) ; + + if (((XvAdaptorInfo*)a_this)->type & XvStillMask && XvOutputMask) *a_result = TRUE ; else *a_result = FALSE ; @@ -396,7 +420,7 @@ ephyrHostXVAdaptorHasPutImage (const EphyrHostXVAdaptor *a_this, { EPHYR_RETURN_VAL_IF_FAIL (a_this && a_result, FALSE) ; - if (((XvAdaptorInfo*)a_this)->type & XvImageMask) + if (((XvAdaptorInfo*)a_this)->type & XvImageMask && XvInputMask) *a_result = TRUE ; else *a_result = FALSE ; @@ -739,12 +763,13 @@ ephyrHostXVPutImage (int a_port_id, XvImage *xv_image=NULL ; GC gc=0 ; XGCValues gc_values; + Display *dpy = hostx_get_display () ; EPHYR_RETURN_VAL_IF_FAIL (a_buf, FALSE) ; EPHYR_LOG ("enter\n") ; - gc = XCreateGC (hostx_get_display (), hostx_get_window (), 0L, &gc_values); + gc = XCreateGC (dpy, hostx_get_window (), 0L, &gc_values); if (!gc) { EPHYR_LOG_ERROR ("failed to create gc \n") ; goto out ; @@ -757,11 +782,11 @@ ephyrHostXVPutImage (int a_port_id, goto out ; } xv_image->data = (char*)a_buf ; - XvPutImage (hostx_get_display (), a_port_id, hostx_get_window (), + XvPutImage (dpy, a_port_id, hostx_get_window (), gc, xv_image, a_src_x, a_src_y, a_src_w, a_src_h, a_drw_x, a_drw_y, a_drw_w, a_drw_h) ; - XFlush (hostx_get_display ()) ; + XFlush (dpy) ; is_ok = TRUE ; out: @@ -771,5 +796,158 @@ out: XFree (xv_image) ; xv_image = NULL ; } + if (gc) { + XFreeGC (dpy, gc) ; + gc = NULL ; + } return is_ok ; } + +Bool +ephyrHostXVPutVideo (int a_port_id, + int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, + int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) +{ + Bool is_ok=FALSE ; + int res=FALSE ; + GC gc=0 ; + XGCValues gc_values; + Display *dpy=hostx_get_display () ; + + EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; + + gc = XCreateGC (dpy, hostx_get_window (), 0L, &gc_values); + if (!gc) { + EPHYR_LOG_ERROR ("failed to create gc \n") ; + goto out ; + } + res = XvPutVideo (dpy, a_port_id, hostx_get_window (), gc, + a_vid_x, a_vid_y, a_vid_w, a_vid_h, + a_drw_x, a_drw_y, a_drw_w, a_drw_h) ; + + if (res != Success) { + EPHYR_LOG_ERROR ("XvPutVideo() failed: %d\n", res) ; + goto out ; + } + + is_ok = TRUE ; + +out: + if (gc) { + XFreeGC (dpy, gc) ; + gc = NULL ; + } + return is_ok ; +} + +Bool +ephyrHostXVGetVideo (int a_port_id, + int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, + int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) +{ + Bool is_ok=FALSE ; + int res=FALSE ; + GC gc=0 ; + XGCValues gc_values; + Display *dpy=hostx_get_display () ; + + EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; + + gc = XCreateGC (dpy, hostx_get_window (), 0L, &gc_values); + if (!gc) { + EPHYR_LOG_ERROR ("failed to create gc \n") ; + goto out ; + } + res = XvGetVideo (dpy, a_port_id, hostx_get_window (), gc, + a_vid_x, a_vid_y, a_vid_w, a_vid_h, + a_drw_x, a_drw_y, a_drw_w, a_drw_h) ; + + if (res != Success) { + EPHYR_LOG_ERROR ("XvGetVideo() failed: %d\n", res) ; + goto out ; + } + + is_ok = TRUE ; + +out: + if (gc) { + XFreeGC (dpy, gc) ; + gc = NULL ; + } + return is_ok ; +} + +Bool +ephyrHostXVPutStill (int a_port_id, + int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, + int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) +{ + Bool is_ok=FALSE ; + int res=FALSE ; + GC gc=0 ; + XGCValues gc_values; + Display *dpy=hostx_get_display () ; + + EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; + + gc = XCreateGC (dpy, hostx_get_window (), 0L, &gc_values); + if (!gc) { + EPHYR_LOG_ERROR ("failed to create gc \n") ; + goto out ; + } + res = XvPutStill (dpy, a_port_id, hostx_get_window (), gc, + a_vid_x, a_vid_y, a_vid_w, a_vid_h, + a_drw_x, a_drw_y, a_drw_w, a_drw_h) ; + + if (res != Success) { + EPHYR_LOG_ERROR ("XvPutStill() failed: %d\n", res) ; + goto out ; + } + + is_ok = TRUE ; + +out: + if (gc) { + XFreeGC (dpy, gc) ; + gc = NULL ; + } + return is_ok ; +} + +Bool +ephyrHostXVGetStill (int a_port_id, + int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, + int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) +{ + Bool is_ok=FALSE ; + int res=FALSE ; + GC gc=0 ; + XGCValues gc_values; + Display *dpy=hostx_get_display () ; + + EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; + + gc = XCreateGC (dpy, hostx_get_window (), 0L, &gc_values); + if (!gc) { + EPHYR_LOG_ERROR ("failed to create gc \n") ; + goto out ; + } + res = XvGetStill (dpy, a_port_id, hostx_get_window (), gc, + a_vid_x, a_vid_y, a_vid_w, a_vid_h, + a_drw_x, a_drw_y, a_drw_w, a_drw_h) ; + + if (res != Success) { + EPHYR_LOG_ERROR ("XvGetStill() failed: %d\n", res) ; + goto out ; + } + + is_ok = TRUE ; + +out: + if (gc) { + XFreeGC (dpy, gc) ; + gc = NULL ; + } + return is_ok ; +} + diff --git a/hw/kdrive/ephyr/ephyrhostvideo.h b/hw/kdrive/ephyr/ephyrhostvideo.h index 94994463a..9c97c6a96 100644 --- a/hw/kdrive/ephyr/ephyrhostvideo.h +++ b/hw/kdrive/ephyr/ephyrhostvideo.h @@ -111,8 +111,12 @@ int ephyrHostXVAdaptorGetFirstPortID (const EphyrHostXVAdaptor *a_this) ; Bool ephyrHostXVAdaptorHasPutVideo (const EphyrHostXVAdaptor *a_this, Bool *a_result) ; +Bool ephyrHostXVAdaptorHasGetVideo (const EphyrHostXVAdaptor *a_this, + Bool *a_result) ; Bool ephyrHostXVAdaptorHasPutStill (const EphyrHostXVAdaptor *a_this, Bool *a_result) ; +Bool ephyrHostXVAdaptorHasGetStill (const EphyrHostXVAdaptor *a_this, + Bool *a_result) ; Bool ephyrHostXVAdaptorHasPutImage (const EphyrHostXVAdaptor *a_this, Bool *a_result) ; @@ -195,5 +199,23 @@ Bool ephyrHostXVPutImage (int a_port_id, int a_image_height, unsigned char *a_buf) ; +/* + * Putvideo/PutStill/GetVideo + */ +Bool ephyrHostXVPutVideo (int a_port_id, + int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, + int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) ; + +Bool ephyrHostXVGetVideo (int a_port_id, + int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, + int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) ; + +Bool ephyrHostXVPutStill (int a_port_id, + int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, + int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) ; + +Bool ephyrHostXVGetStill (int a_port_id, + int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, + int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) ; #endif /*__EPHYRHOSTVIDEO_H__*/ diff --git a/hw/kdrive/ephyr/ephyrvideo.c b/hw/kdrive/ephyr/ephyrvideo.c index 8ac220476..1cc45ff08 100644 --- a/hw/kdrive/ephyr/ephyrvideo.c +++ b/hw/kdrive/ephyr/ephyrvideo.c @@ -97,24 +97,6 @@ static void ephyrQueryBestSize (KdScreenInfo *a_info, unsigned int *a_prefered_h, pointer a_port_priv); -static int ephyrPutVideo (KdScreenInfo *a_screen, - DrawablePtr a_drw, - short a_vid_x, short a_vid_y, - short a_drw_x, short a_drw_y, - short a_vid_w, short a_vid_h, - short a_drw_w, short a_drw_h, - RegionPtr a_clip_region, - pointer a_port_priv) ; - -static int ephyrPutStill (KdScreenInfo *a_screen, - DrawablePtr a_drw, - short a_vid_x, short a_vid_y, - short a_drw_x, short a_drw_y, - short a_vid_w, short a_vid_h, - short a_drw_w, short a_drw_h, - RegionPtr a_clip_region, - pointer a_port_priv) ; - static int ephyrPutImage (KdScreenInfo *a_info, DrawablePtr a_drawable, short a_src_x, @@ -133,6 +115,42 @@ static int ephyrPutImage (KdScreenInfo *a_info, RegionPtr a_clipping_region, pointer a_port_priv); +static int ephyrPutVideo (KdScreenInfo *a_info, + DrawablePtr a_drawable, + short a_vid_x, short a_vid_y, + short a_drw_x, short a_drw_y, + short a_vid_w, short a_vid_h, + short a_drw_w, short a_drw_h, + RegionPtr a_clip_region, + pointer a_port_priv) ; + +static int ephyrGetVideo (KdScreenInfo *a_info, + DrawablePtr a_drawable, + short a_vid_x, short a_vid_y, + short a_drw_x, short a_drw_y, + short a_vid_w, short a_vid_h, + short a_drw_w, short a_drw_h, + RegionPtr a_clip_region, + pointer a_port_priv) ; + +static int ephyrPutStill (KdScreenInfo *a_info, + DrawablePtr a_drawable, + short a_vid_x, short a_vid_y, + short a_drw_x, short a_drw_y, + short a_vid_w, short a_vid_h, + short a_drw_w, short a_drw_h, + RegionPtr a_clip_region, + pointer a_port_priv) ; + +static int ephyrGetStill (KdScreenInfo *a_info, + DrawablePtr a_drawable, + short a_vid_x, short a_vid_y, + short a_drw_x, short a_drw_y, + short a_vid_w, short a_vid_h, + short a_drw_w, short a_drw_h, + RegionPtr a_clip_region, + pointer a_port_priv) ; + static int ephyrQueryImageAttributes (KdScreenInfo *a_info, int a_id, unsigned short *a_w, @@ -546,12 +564,26 @@ ephyrXVPrivSetAdaptorsHooks (EphyrXVPriv *a_this) if (has_it) a_this->adaptors[i].PutVideo = ephyrPutVideo; + has_it = FALSE ; + if (!ephyrHostXVAdaptorHasGetVideo (cur_host_adaptor, &has_it)) { + EPHYR_LOG_ERROR ("error\n") ; + } + if (has_it) + a_this->adaptors[i].GetVideo = ephyrGetVideo; + has_it = FALSE ; if (!ephyrHostXVAdaptorHasPutStill (cur_host_adaptor, &has_it)) { EPHYR_LOG_ERROR ("error\n") ; } if (has_it) a_this->adaptors[i].PutStill = ephyrPutStill; + + has_it = FALSE ; + if (!ephyrHostXVAdaptorHasGetStill (cur_host_adaptor, &has_it)) { + EPHYR_LOG_ERROR ("error\n") ; + } + if (has_it) + a_this->adaptors[i].GetStill = ephyrGetStill; } EPHYR_LOG ("leave\n") ; return TRUE ; @@ -764,36 +796,6 @@ ephyrQueryBestSize (KdScreenInfo *a_info, EPHYR_LOG ("leave\n") ; } -static int -ephyrPutVideo (KdScreenInfo *a_screen, - DrawablePtr a_drw, - short a_vid_x, short a_vid_y, - short a_drw_x, short a_drw_y, - short a_vid_w, short a_vid_h, - short a_drw_w, short a_drw_h, - RegionPtr a_clip_region, - pointer a_port_priv) -{ - EPHYR_LOG ("enter\n") ; - return Success ; - EPHYR_LOG ("leave\n") ; -} - -static int -ephyrPutStill (KdScreenInfo *a_screen, - DrawablePtr a_drw, - short a_vid_x, short a_vid_y, - short a_drw_x, short a_drw_y, - short a_vid_w, short a_vid_h, - short a_drw_w, short a_drw_h, - RegionPtr a_clip_region, - pointer a_port_priv) -{ - EPHYR_LOG ("enter\n") ; - return Success ; - EPHYR_LOG ("leave\n") ; -} - static int ephyrPutImage (KdScreenInfo *a_info, DrawablePtr a_drawable, @@ -855,6 +857,202 @@ out: return result ; } +static int +ephyrPutVideo (KdScreenInfo *a_info, + DrawablePtr a_drawable, + short a_vid_x, short a_vid_y, + short a_drw_x, short a_drw_y, + short a_vid_w, short a_vid_h, + short a_drw_w, short a_drw_h, + RegionPtr a_clipping_region, + pointer a_port_priv) +{ + EphyrPortPriv *port_priv = a_port_priv ; + BoxRec clipped_area, dst_box ; + int result=BadImplementation ; + int drw_x=0, drw_y=0, drw_w=0, drw_h=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_drawable && port_priv, BadValue) ; + + EPHYR_LOG ("enter\n") ; + + dst_box.x1 = a_drw_x ; + dst_box.x2 = a_drw_x + a_drw_w; + dst_box.y1 = a_drw_y ; + dst_box.y2 = a_drw_y + a_drw_h; + + if (!DoSimpleClip (&dst_box, + REGION_EXTENTS (pScreen->pScreen, a_clipping_region), + &clipped_area)) { + EPHYR_LOG_ERROR ("failed to simple clip\n") ; + goto out ; + } + + drw_x = clipped_area.x1 ; + drw_y = clipped_area.y1 ; + drw_w = clipped_area.x2 - clipped_area.x1 ; + drw_h = clipped_area.y2 - clipped_area.y1 ; + + if (!ephyrHostXVPutVideo (port_priv->port_number, + a_vid_x, a_vid_y, a_vid_w, a_vid_h, + a_drw_x, a_drw_y, a_drw_w, a_drw_h)) { + EPHYR_LOG_ERROR ("ephyrHostXVPutVideo() failed\n") ; + goto out ; + } + result = Success ; + +out: + EPHYR_LOG ("leave\n") ; + return result ; +} + +static int +ephyrGetVideo (KdScreenInfo *a_info, + DrawablePtr a_drawable, + short a_vid_x, short a_vid_y, + short a_drw_x, short a_drw_y, + short a_vid_w, short a_vid_h, + short a_drw_w, short a_drw_h, + RegionPtr a_clipping_region, + pointer a_port_priv) +{ + EphyrPortPriv *port_priv = a_port_priv ; + BoxRec clipped_area, dst_box ; + int result=BadImplementation ; + int drw_x=0, drw_y=0, drw_w=0, drw_h=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_drawable && port_priv, BadValue) ; + + EPHYR_LOG ("enter\n") ; + + dst_box.x1 = a_drw_x ; + dst_box.x2 = a_drw_x + a_drw_w; + dst_box.y1 = a_drw_y ; + dst_box.y2 = a_drw_y + a_drw_h; + + if (!DoSimpleClip (&dst_box, + REGION_EXTENTS (pScreen->pScreen, a_clipping_region), + &clipped_area)) { + EPHYR_LOG_ERROR ("failed to simple clip\n") ; + goto out ; + } + + drw_x = clipped_area.x1 ; + drw_y = clipped_area.y1 ; + drw_w = clipped_area.x2 - clipped_area.x1 ; + drw_h = clipped_area.y2 - clipped_area.y1 ; + + if (!ephyrHostXVGetVideo (port_priv->port_number, + a_vid_x, a_vid_y, a_vid_w, a_vid_h, + a_drw_x, a_drw_y, a_drw_w, a_drw_h)) { + EPHYR_LOG_ERROR ("ephyrHostXVGetVideo() failed\n") ; + goto out ; + } + result = Success ; + +out: + EPHYR_LOG ("leave\n") ; + return result ; +} + +static int +ephyrPutStill (KdScreenInfo *a_info, + DrawablePtr a_drawable, + short a_vid_x, short a_vid_y, + short a_drw_x, short a_drw_y, + short a_vid_w, short a_vid_h, + short a_drw_w, short a_drw_h, + RegionPtr a_clipping_region, + pointer a_port_priv) +{ + EphyrPortPriv *port_priv = a_port_priv ; + BoxRec clipped_area, dst_box ; + int result=BadImplementation ; + int drw_x=0, drw_y=0, drw_w=0, drw_h=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_drawable && port_priv, BadValue) ; + + EPHYR_LOG ("enter\n") ; + + dst_box.x1 = a_drw_x ; + dst_box.x2 = a_drw_x + a_drw_w; + dst_box.y1 = a_drw_y ; + dst_box.y2 = a_drw_y + a_drw_h; + + if (!DoSimpleClip (&dst_box, + REGION_EXTENTS (pScreen->pScreen, a_clipping_region), + &clipped_area)) { + EPHYR_LOG_ERROR ("failed to simple clip\n") ; + goto out ; + } + + drw_x = clipped_area.x1 ; + drw_y = clipped_area.y1 ; + drw_w = clipped_area.x2 - clipped_area.x1 ; + drw_h = clipped_area.y2 - clipped_area.y1 ; + + if (!ephyrHostXVPutStill (port_priv->port_number, + a_vid_x, a_vid_y, a_vid_w, a_vid_h, + a_drw_x, a_drw_y, a_drw_w, a_drw_h)) { + EPHYR_LOG_ERROR ("ephyrHostXVPutStill() failed\n") ; + goto out ; + } + result = Success ; + +out: + EPHYR_LOG ("leave\n") ; + return result ; +} + +static int +ephyrGetStill (KdScreenInfo *a_info, + DrawablePtr a_drawable, + short a_vid_x, short a_vid_y, + short a_drw_x, short a_drw_y, + short a_vid_w, short a_vid_h, + short a_drw_w, short a_drw_h, + RegionPtr a_clipping_region, + pointer a_port_priv) +{ + EphyrPortPriv *port_priv = a_port_priv ; + BoxRec clipped_area, dst_box ; + int result=BadImplementation ; + int drw_x=0, drw_y=0, drw_w=0, drw_h=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_drawable && port_priv, BadValue) ; + + EPHYR_LOG ("enter\n") ; + + dst_box.x1 = a_drw_x ; + dst_box.x2 = a_drw_x + a_drw_w; + dst_box.y1 = a_drw_y ; + dst_box.y2 = a_drw_y + a_drw_h; + + if (!DoSimpleClip (&dst_box, + REGION_EXTENTS (pScreen->pScreen, a_clipping_region), + &clipped_area)) { + EPHYR_LOG_ERROR ("failed to simple clip\n") ; + goto out ; + } + + drw_x = clipped_area.x1 ; + drw_y = clipped_area.y1 ; + drw_w = clipped_area.x2 - clipped_area.x1 ; + drw_h = clipped_area.y2 - clipped_area.y1 ; + + if (!ephyrHostXVGetStill (port_priv->port_number, + a_vid_x, a_vid_y, a_vid_w, a_vid_h, + a_drw_x, a_drw_y, a_drw_w, a_drw_h)) { + EPHYR_LOG_ERROR ("ephyrHostXVGetStill() failed\n") ; + goto out ; + } + result = Success ; + +out: + EPHYR_LOG ("leave\n") ; + return result ; +} + static int ephyrQueryImageAttributes (KdScreenInfo *a_info, int a_id, From 39d3895469f07304d72800d8dcef6c7732f13d5f Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Wed, 8 Aug 2007 14:27:32 +0200 Subject: [PATCH 16/44] make EphyrXVPriv be a singleton * hw/kdrive/ephyr/ephyrvideo.c: (ephyrInitVideo) make the EphyrXVPriv object be a singleton instance, otherwise a new object is created at each generation. --- hw/kdrive/ephyr/ephyrvideo.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/hw/kdrive/ephyr/ephyrvideo.c b/hw/kdrive/ephyr/ephyrvideo.c index 1cc45ff08..90c7535da 100644 --- a/hw/kdrive/ephyr/ephyrvideo.c +++ b/hw/kdrive/ephyr/ephyrvideo.c @@ -1,4 +1,4 @@ -/* +/* * Xephyr - A kdrive X server thats runs in a host X window. * Authored by Matthew Allum * @@ -267,9 +267,10 @@ out: Bool ephyrInitVideo (ScreenPtr pScreen) { + Bool is_ok = FALSE ; KdScreenPriv(pScreen); KdScreenInfo *screen = pScreenPriv->screen; - EphyrXVPriv *xv_priv = NULL ; + static EphyrXVPriv *xv_priv; EPHYR_LOG ("enter\n") ; @@ -278,17 +279,22 @@ ephyrInitVideo (ScreenPtr pScreen) return FALSE ; } - xv_priv = ephyrXVPrivNew () ; + if (!xv_priv) { + xv_priv = ephyrXVPrivNew () ; + } if (!xv_priv) { EPHYR_LOG_ERROR ("failed to create xv_priv\n") ; - return FALSE ; + goto out ; } if (!ephyrXVPrivRegisterAdaptors (xv_priv, pScreen)) { EPHYR_LOG_ERROR ("failed to register adaptors\n") ; - return FALSE ; + goto out ; } - return TRUE ; + is_ok = TRUE ; + +out: + return is_ok ; } static EphyrXVPriv* @@ -607,6 +613,8 @@ ephyrXVPrivRegisterAdaptors (EphyrXVPriv *a_this, goto out ; num_registered_adaptors = KdXVListGenericAdaptors (screen, ®istered_adaptors); + EPHYR_LOG ("") ; + num_adaptors = num_registered_adaptors + a_this->num_adaptors ; adaptors = xcalloc (num_adaptors, sizeof (KdVideoAdaptorPtr)) ; if (!adaptors) { @@ -621,7 +629,7 @@ ephyrXVPrivRegisterAdaptors (EphyrXVPriv *a_this, EPHYR_LOG_ERROR ("failed to register adaptors\n"); goto out ; } - EPHYR_LOG ("registered %d adaptors\n", num_adaptors) ; + EPHYR_LOG ("there are %d registered adaptors\n", num_adaptors) ; is_ok = TRUE ; out: From e01d3dd98d1b596e75d25f94dd89c7d41223011d Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Thu, 9 Aug 2007 10:55:10 +0200 Subject: [PATCH 17/44] Support clipping region in PutImage. * hw/kdrive/ephyr/ephyrhostvideo.c,h: (ephyrHostXVPutImage): make this support clipping region. The clipping region is propagated to host using XSetClipRectangles. This changes the API of ephyrHostXVPutImage. * hw/kdrive/ephyr/ephyrvideo.c: (ephyrPutImage): propagate the clipping region to the new ephyrHostXVPutImage() entry point. --- hw/kdrive/ephyr/ephyrhostvideo.c | 43 +++++++++++++++++++++++++------- hw/kdrive/ephyr/ephyrhostvideo.h | 8 +++++- hw/kdrive/ephyr/ephyrvideo.c | 26 +++---------------- 3 files changed, 45 insertions(+), 32 deletions(-) diff --git a/hw/kdrive/ephyr/ephyrhostvideo.c b/hw/kdrive/ephyr/ephyrhostvideo.c index b1b926a45..85fc7bd8e 100644 --- a/hw/kdrive/ephyr/ephyrhostvideo.c +++ b/hw/kdrive/ephyr/ephyrhostvideo.c @@ -757,17 +757,21 @@ ephyrHostXVPutImage (int a_port_id, int a_src_h, int a_image_width, int a_image_height, - unsigned char *a_buf) + unsigned char *a_buf, + EphyrHostBox *a_clip_rects, + int a_clip_rect_nums ) { Bool is_ok=TRUE ; XvImage *xv_image=NULL ; GC gc=0 ; XGCValues gc_values; Display *dpy = hostx_get_display () ; + XRectangle *rects=NULL ; + int res = 0 ; EPHYR_RETURN_VAL_IF_FAIL (a_buf, FALSE) ; - EPHYR_LOG ("enter\n") ; + EPHYR_LOG ("enter, num_clip_rects: %d\n", a_clip_rect_nums) ; gc = XCreateGC (dpy, hostx_get_window (), 0L, &gc_values); if (!gc) { @@ -782,16 +786,32 @@ ephyrHostXVPutImage (int a_port_id, goto out ; } xv_image->data = (char*)a_buf ; - XvPutImage (dpy, a_port_id, hostx_get_window (), - gc, xv_image, - a_src_x, a_src_y, a_src_w, a_src_h, - a_drw_x, a_drw_y, a_drw_w, a_drw_h) ; - XFlush (dpy) ; + if (a_clip_rect_nums) { + int i=0 ; + rects = calloc (a_clip_rect_nums, sizeof (XRectangle)) ; + for (i=0; i < a_clip_rect_nums; i++) { + rects[i].x = a_clip_rects[i].x1 ; + rects[i].y = a_clip_rects[i].y1 ; + rects[i].width = a_clip_rects[i].x2 - a_clip_rects[i].x1; + rects[i].height = a_clip_rects[i].y2 - a_clip_rects[i].y1; + EPHYR_LOG ("(x,y,w,h): (%d,%d,%d,%d)\n", + rects[i].x, rects[i].y, + rects[i].width, rects[i].height) ; + } + XSetClipRectangles (dpy, gc, 0, 0, rects, a_clip_rect_nums, YXBanded) ; + /*this always returns 1*/ + } + res = XvPutImage (dpy, a_port_id, hostx_get_window (), + gc, xv_image, + a_src_x, a_src_y, a_src_w, a_src_h, + a_drw_x, a_drw_y, a_drw_w, a_drw_h) ; + if (res != Success) { + EPHYR_LOG_ERROR ("XvPutImage() failed: %d\n", res) ; + goto out ; + } is_ok = TRUE ; out: - - EPHYR_LOG ("leave\n") ; if (xv_image) { XFree (xv_image) ; xv_image = NULL ; @@ -800,6 +820,11 @@ out: XFreeGC (dpy, gc) ; gc = NULL ; } + if (rects) { + free (rects) ; + rects = NULL ; + } + EPHYR_LOG ("leave\n") ; return is_ok ; } diff --git a/hw/kdrive/ephyr/ephyrhostvideo.h b/hw/kdrive/ephyr/ephyrhostvideo.h index 9c97c6a96..661792bab 100644 --- a/hw/kdrive/ephyr/ephyrhostvideo.h +++ b/hw/kdrive/ephyr/ephyrhostvideo.h @@ -84,6 +84,10 @@ typedef struct _EphyrHostImageFormat { int scanline_order; /* XvTopToBottom, XvBottomToTop */ } EphyrHostImageFormat ; +typedef struct { + unsigned short x1, y1, x2, y2 ; +} EphyrHostBox ; + void ephyrHostXVInit (void) ; void ephyrHostFree (void *a_pointer) ; @@ -197,7 +201,9 @@ Bool ephyrHostXVPutImage (int a_port_id, int a_src_h, int a_image_width, int a_image_height, - unsigned char *a_buf) ; + unsigned char *a_buf, + EphyrHostBox *a_clip_rects, + int a_clip_rect_nums) ; /* * Putvideo/PutStill/GetVideo diff --git a/hw/kdrive/ephyr/ephyrvideo.c b/hw/kdrive/ephyr/ephyrvideo.c index 90c7535da..e2f00c8a1 100644 --- a/hw/kdrive/ephyr/ephyrvideo.c +++ b/hw/kdrive/ephyr/ephyrvideo.c @@ -613,7 +613,6 @@ ephyrXVPrivRegisterAdaptors (EphyrXVPriv *a_this, goto out ; num_registered_adaptors = KdXVListGenericAdaptors (screen, ®istered_adaptors); - EPHYR_LOG ("") ; num_adaptors = num_registered_adaptors + a_this->num_adaptors ; adaptors = xcalloc (num_adaptors, sizeof (KdVideoAdaptorPtr)) ; @@ -824,36 +823,19 @@ ephyrPutImage (KdScreenInfo *a_info, pointer a_port_priv) { EphyrPortPriv *port_priv = a_port_priv ; - BoxRec clipped_area, dst_box ; int result=BadImplementation ; - int drw_x=0, drw_y=0, drw_w=0, drw_h=0 ; EPHYR_RETURN_VAL_IF_FAIL (a_drawable, BadValue) ; EPHYR_LOG ("enter\n") ; - dst_box.x1 = a_drw_x ; - dst_box.x2 = a_drw_x + a_drw_w; - dst_box.y1 = a_drw_y ; - dst_box.y2 = a_drw_y + a_drw_h; - - if (!DoSimpleClip (&dst_box, - REGION_EXTENTS (pScreen->pScreen, a_clipping_region), - &clipped_area)) { - EPHYR_LOG_ERROR ("failed to simple clip\n") ; - goto out ; - } - - drw_x = clipped_area.x1 ; - drw_y = clipped_area.y1 ; - drw_w = clipped_area.x2 - clipped_area.x1 ; - drw_h = clipped_area.y2 - clipped_area.y1 ; - if (!ephyrHostXVPutImage (port_priv->port_number, a_id, - drw_x, drw_y, drw_w, drw_h, + a_drw_x, a_drw_y, a_drw_w, a_drw_h, a_src_x, a_src_y, a_src_w, a_src_h, - a_width, a_height, a_buf)) { + a_width, a_height, a_buf, + (EphyrHostBox*)REGION_RECTS (a_clipping_region), + REGION_NUM_RECTS (a_clipping_region))) { EPHYR_LOG_ERROR ("EphyrHostXVPutImage() failed\n") ; goto out ; } From e4239a48075c77e6a8d2d5cb21f58dd67687482f Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Tue, 14 Aug 2007 22:48:41 +0200 Subject: [PATCH 18/44] Initial dri forwarding big bricks. * hw/kdrive/ephyr/ephyrdriext.c: added this to implement a DRI extension into Xephyr. Normally the DRI extension is only present in the xfree86 server, but I have ported it to Xephyr. The extension calls functions that declared/defined in ephyrdri.h ephyrdri.c that forwards the DRI calls to the host X. It does not work yet, as this entry is just to put the big bricks in place. * hw/kdrive/ephyr/ephyrdri.c,h: declaration & definition of the DRI client API that would hit the hostX server. * hw/kdrive/ephyr/GL/internal/dri_interface.h: added this, otherwise inclusion of /usr/include/X11/dri/xf86dri.h won't compile --- hw/kdrive/ephyr/GL/internal/dri_interface.h | 517 +++++++++++++++ hw/kdrive/ephyr/Makefile.am | 10 +- hw/kdrive/ephyr/ephyrdri.c | 206 ++++++ hw/kdrive/ephyr/ephyrdri.h | 75 +++ hw/kdrive/ephyr/ephyrdriext.c | 691 ++++++++++++++++++++ 5 files changed, 1497 insertions(+), 2 deletions(-) create mode 100644 hw/kdrive/ephyr/GL/internal/dri_interface.h create mode 100644 hw/kdrive/ephyr/ephyrdri.c create mode 100644 hw/kdrive/ephyr/ephyrdri.h create mode 100644 hw/kdrive/ephyr/ephyrdriext.c diff --git a/hw/kdrive/ephyr/GL/internal/dri_interface.h b/hw/kdrive/ephyr/GL/internal/dri_interface.h new file mode 100644 index 000000000..8d24e311f --- /dev/null +++ b/hw/kdrive/ephyr/GL/internal/dri_interface.h @@ -0,0 +1,517 @@ +/* + * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. + * (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 dri_interface.h + * + * This file contains all the types and functions that define the interface + * between a DRI driver and driver loader. Currently, the most common driver + * loader is the XFree86 libGL.so. However, other loaders do exist, and in + * the future the server-side libglx.a will also be a loader. + * + * \author Kevin E. Martin + * \author Ian Romanick + */ + +#ifndef DRI_INTERFACE_H +#define DRI_INTERFACE_H + +#include +#include + +/** + * \name DRI interface structures + * + * The following structures define the interface between the GLX client + * side library and the DRI (direct rendering infrastructure). + */ +/*@{*/ +typedef struct __DRIdisplayRec __DRIdisplay; +typedef struct __DRIscreenRec __DRIscreen; +typedef struct __DRIcontextRec __DRIcontext; +typedef struct __DRIdrawableRec __DRIdrawable; +typedef struct __DRIdriverRec __DRIdriver; +typedef struct __DRIframebufferRec __DRIframebuffer; +typedef struct __DRIversionRec __DRIversion; +typedef struct __DRIinterfaceMethodsRec __DRIinterfaceMethods; +typedef unsigned long __DRIid; +typedef void __DRInativeDisplay; +/*@}*/ + + +/** + * \name Functions provided by the driver loader. + */ +/*@{*/ +/** + * Type of a pointer to \c glXGetScreenDriver, as returned by + * \c glXGetProcAddress. This function is used to get the name of the DRI + * driver for the specified screen of the specified display. The driver + * name is typically used with \c glXGetDriverConfig. + * + * \sa glXGetScreenDriver, glXGetProcAddress, glXGetDriverConfig + */ +typedef const char * (* PFNGLXGETSCREENDRIVERPROC) (__DRInativeDisplay *dpy, int scrNum); + +/** + * Type of a pointer to \c glXGetDriverConfig, as returned by + * \c glXGetProcAddress. This function is used to get the XML document + * describing the configuration options available for the specified driver. + * + * \sa glXGetDriverConfig, glXGetProcAddress, glXGetScreenDriver + */ +typedef const char * (* PFNGLXGETDRIVERCONFIGPROC) (const char *driverName); + +/** + * Type of a pointer to \c glxEnableExtension, as returned by + * \c __DRIinterfaceMethods::getProcAddress. This function is used to enable + * a GLX extension on the specified screen. + */ +typedef void (* PFNGLXSCRENABLEEXTENSIONPROC) ( void *psc, const char * name ); +/*@}*/ + + +/** + * \name Functions and data provided by the driver. + */ +/*@{*/ + +typedef void *(CREATENEWSCREENFUNC)(__DRInativeDisplay *dpy, int scrn, + __DRIscreen *psc, const __GLcontextModes * modes, + const __DRIversion * ddx_version, const __DRIversion * dri_version, + const __DRIversion * drm_version, const __DRIframebuffer * frame_buffer, + void * pSAREA, int fd, int internal_api_version, + const __DRIinterfaceMethods * interface, + __GLcontextModes ** driver_modes); +typedef CREATENEWSCREENFUNC* PFNCREATENEWSCREENFUNC; +extern CREATENEWSCREENFUNC __driCreateNewScreen_20050727; + + +/** + * XML document describing the configuration options supported by the + * driver. + */ +extern const char __driConfigOptions[]; + +/*@}*/ + + +/** + * Stored version of some component (i.e., server-side DRI module, kernel-side + * DRM, etc.). + * + * \todo + * There are several data structures that explicitly store a major version, + * minor version, and patch level. These structures should be modified to + * have a \c __DRIversionRec instead. + */ +struct __DRIversionRec { + int major; /**< Major version number. */ + int minor; /**< Minor version number. */ + int patch; /**< Patch-level. */ +}; + + +typedef void (*__DRIfuncPtr)(void); + +struct __DRIinterfaceMethodsRec { + /** + * Get pointer to named function. + */ + __DRIfuncPtr (*getProcAddress)( const char * proc_name ); + + /** + * Create a list of \c __GLcontextModes structures. + */ + __GLcontextModes * (*createContextModes)(unsigned count, + size_t minimum_bytes_per_struct); + + /** + * Destroy a list of \c __GLcontextModes structures. + * + * \todo + * Determine if the drivers actually need to call this. + */ + void (*destroyContextModes)( __GLcontextModes * modes ); + + /** + * Get the \c __DRIscreen for a given display and screen number. + */ + __DRIscreen *(*getScreen)(__DRInativeDisplay *dpy, int screenNum); + + + /** + * \name Client/server protocol functions. + * + * These functions implement the DRI client/server protocol for + * context and drawable operations. Platforms that do not implement + * the wire protocol (e.g., EGL) will implement glorified no-op functions. + */ + /*@{*/ + /** + * Determine if the specified window ID still exists. + * + * \note + * Implementations may assume that the driver will only pass an ID into + * this function that actually corresponds to a window. On + * implementations where windows can only be destroyed by the DRI driver + * (e.g., EGL), this function is allowed to always return \c GL_TRUE. + */ + GLboolean (*windowExists)(__DRInativeDisplay *dpy, __DRIid draw); + + /** + * Create the server-side portion of the GL context. + */ + GLboolean (* createContext)( __DRInativeDisplay *dpy, int screenNum, + int configID, void * contextID, drm_context_t * hw_context ); + + /** + * Destroy the server-side portion of the GL context. + */ + GLboolean (* destroyContext)( __DRInativeDisplay *dpy, int screenNum, + __DRIid context ); + + /** + * Create the server-side portion of the drawable. + */ + GLboolean (*createDrawable)( __DRInativeDisplay * ndpy, int screen, + __DRIid drawable, drm_drawable_t * hHWDrawable ); + + /** + * Destroy the server-side portion of the drawable. + */ + GLboolean (*destroyDrawable)( __DRInativeDisplay * ndpy, int screen, + __DRIid drawable ); + + /** + * This function is used to get information about the position, size, and + * clip rects of a drawable. + */ + GLboolean (* getDrawableInfo) ( __DRInativeDisplay *dpy, int scrn, + __DRIid draw, unsigned int * index, unsigned int * stamp, + int * x, int * y, int * width, int * height, + int * numClipRects, drm_clip_rect_t ** pClipRects, + int * backX, int * backY, + int * numBackClipRects, drm_clip_rect_t ** pBackClipRects ); + /*@}*/ + + + /** + * \name Timing related functions. + */ + /*@{*/ + /** + * Get the 64-bit unadjusted system time (UST). + */ + int (*getUST)(int64_t * ust); + + /** + * Get the media stream counter (MSC) rate. + * + * Matching the definition in GLX_OML_sync_control, this function returns + * the rate of the "media stream counter". In practical terms, this is + * the frame refresh rate of the display. + */ + GLboolean (*getMSCRate)(__DRInativeDisplay * dpy, __DRIid drawable, + int32_t * numerator, int32_t * denominator); + /*@}*/ + + /** + * Reports areas of the given drawable which have been modified by the + * driver. + * + * \param drawable which the drawing was done to. + * \param rects rectangles affected, with the drawable origin as the + * origin. + * \param x X offset of the drawable within the screen (used in the + * front_buffer case) + * \param y Y offset of the drawable within the screen. + * \param front_buffer boolean flag for whether the drawing to the + * drawable was actually done directly to the front buffer (instead + * of backing storage, for example) + */ + void (*reportDamage)(__DRInativeDisplay * dpy, int screen, + __DRIid drawable, + int x, int y, + drm_clip_rect_t *rects, int num_rects, + int front_buffer); +}; + + +/** + * Framebuffer information record. Used by libGL to communicate information + * about the framebuffer to the driver's \c __driCreateNewScreen function. + * + * In XFree86, most of this information is derrived from data returned by + * calling \c XF86DRIGetDeviceInfo. + * + * \sa XF86DRIGetDeviceInfo __DRIdisplayRec::createNewScreen + * __driUtilCreateNewScreen CallCreateNewScreen + * + * \bug This structure could be better named. + */ +struct __DRIframebufferRec { + unsigned char *base; /**< Framebuffer base address in the CPU's + * address space. This value is calculated by + * calling \c drmMap on the framebuffer handle + * returned by \c XF86DRIGetDeviceInfo (or a + * similar function). + */ + int size; /**< Framebuffer size, in bytes. */ + int stride; /**< Number of bytes from one line to the next. */ + int width; /**< Pixel width of the framebuffer. */ + int height; /**< Pixel height of the framebuffer. */ + int dev_priv_size; /**< Size of the driver's dev-priv structure. */ + void *dev_priv; /**< Pointer to the driver's dev-priv structure. */ +}; + + +/** + * Screen dependent methods. This structure is initialized during the + * \c __DRIdisplayRec::createScreen call. + */ +struct __DRIscreenRec { + /** + * Method to destroy the private DRI screen data. + */ + void (*destroyScreen)(__DRInativeDisplay *dpy, int scrn, void *screenPrivate); + + /** + * Method to create the private DRI drawable data and initialize the + * drawable dependent methods. + */ + void *(*createNewDrawable)(__DRInativeDisplay *dpy, const __GLcontextModes *modes, + __DRIid draw, __DRIdrawable *pdraw, + int renderType, const int *attrs); + + /** + * Method to return a pointer to the DRI drawable data. + */ + __DRIdrawable *(*getDrawable)(__DRInativeDisplay *dpy, __DRIid draw, + void *drawablePrivate); + + /** + * Opaque pointer to private per screen direct rendering data. \c NULL + * if direct rendering is not supported on this screen. Never + * dereferenced in libGL. + */ + void *private; + + /** + * Get the number of vertical refreshes since some point in time before + * this function was first called (i.e., system start up). + * + * \since Internal API version 20030317. + */ + int (*getMSC)( void *screenPrivate, int64_t *msc ); + + /** + * Opaque pointer that points back to the containing + * \c __GLXscreenConfigs. This data structure is shared with DRI drivers + * but \c __GLXscreenConfigs is not. However, they are needed by some GLX + * functions called by DRI drivers. + * + * \since Internal API version 20030813. + */ + void *screenConfigs; + + /** + * Functions associated with MESA_allocate_memory. + * + * \since Internal API version 20030815. + */ + /*@{*/ + void *(*allocateMemory)(__DRInativeDisplay *dpy, int scrn, GLsizei size, + GLfloat readfreq, GLfloat writefreq, + GLfloat priority); + + void (*freeMemory)(__DRInativeDisplay *dpy, int scrn, GLvoid *pointer); + + GLuint (*memoryOffset)(__DRInativeDisplay *dpy, int scrn, const GLvoid *pointer); + /*@}*/ + + /** + * Method to create the private DRI context data and initialize the + * context dependent methods. + * + * \since Internal API version 20031201. + */ + void * (*createNewContext)(__DRInativeDisplay *dpy, const __GLcontextModes *modes, + int render_type, + void *sharedPrivate, __DRIcontext *pctx); + + /** + * Method to override base texture image with a driver specific 'offset'. + * The depth passed in allows e.g. to ignore the alpha channel of texture + * images where the non-alpha components don't occupy a whole texel. + * + * For GLX_EXT_texture_from_pixmap with AIGLX. + * + * \since Internal API version 20070121. + */ + void (*setTexOffset)(__DRIcontext *pDRICtx, GLint texname, + unsigned long long offset, GLint depth, GLuint pitch); +}; + +/** + * Context dependent methods. This structure is initialized during the + * \c __DRIscreenRec::createContext call. + */ +struct __DRIcontextRec { + /** + * Method to destroy the private DRI context data. + */ + void (*destroyContext)(__DRInativeDisplay *dpy, int scrn, void *contextPrivate); + + /** + * Opaque pointer to private per context direct rendering data. + * \c NULL if direct rendering is not supported on the display or + * screen used to create this context. Never dereferenced in libGL. + */ + void *private; + + /** + * Pointer to the mode used to create this context. + * + * \since Internal API version 20040317. + */ + const __GLcontextModes * mode; + + /** + * Method to bind a DRI drawable to a DRI graphics context. + * + * \since Internal API version 20050727. + */ + GLboolean (*bindContext)(__DRInativeDisplay *dpy, int scrn, __DRIid draw, + __DRIid read, __DRIcontext *ctx); + + /** + * Method to unbind a DRI drawable from a DRI graphics context. + * + * \since Internal API version 20050727. + */ + GLboolean (*unbindContext)(__DRInativeDisplay *dpy, int scrn, __DRIid draw, + __DRIid read, __DRIcontext *ctx); +}; + +/** + * Drawable dependent methods. This structure is initialized during the + * \c __DRIscreenRec::createDrawable call. \c createDrawable is not called + * by libGL at this time. It's currently used via the dri_util.c utility code + * instead. + */ +struct __DRIdrawableRec { + /** + * Method to destroy the private DRI drawable data. + */ + void (*destroyDrawable)(__DRInativeDisplay *dpy, void *drawablePrivate); + + /** + * Method to swap the front and back buffers. + */ + void (*swapBuffers)(__DRInativeDisplay *dpy, void *drawablePrivate); + + /** + * Opaque pointer to private per drawable direct rendering data. + * \c NULL if direct rendering is not supported on the display or + * screen used to create this drawable. Never dereferenced in libGL. + */ + void *private; + + /** + * Get the number of completed swap buffers for this drawable. + * + * \since Internal API version 20030317. + */ + int (*getSBC)(__DRInativeDisplay *dpy, void *drawablePrivate, int64_t *sbc ); + + /** + * Wait for the SBC to be greater than or equal target_sbc. + * + * \since Internal API version 20030317. + */ + int (*waitForSBC)( __DRInativeDisplay * dpy, void *drawablePriv, + int64_t target_sbc, + int64_t * msc, int64_t * sbc ); + + /** + * Wait for the MSC to equal target_msc, or, if that has already passed, + * the next time (MSC % divisor) is equal to remainder. If divisor is + * zero, the function will return as soon as MSC is greater than or equal + * to target_msc. + * + * \since Internal API version 20030317. + */ + int (*waitForMSC)( __DRInativeDisplay * dpy, void *drawablePriv, + int64_t target_msc, int64_t divisor, int64_t remainder, + int64_t * msc, int64_t * sbc ); + + /** + * Like \c swapBuffers, but does NOT have an implicit \c glFlush. Once + * rendering is complete, waits until MSC is equal to target_msc, or + * if that has already passed, waits until (MSC % divisor) is equal + * to remainder. If divisor is zero, the swap will happen as soon as + * MSC is greater than or equal to target_msc. + * + * \since Internal API version 20030317. + */ + int64_t (*swapBuffersMSC)(__DRInativeDisplay *dpy, void *drawablePrivate, + int64_t target_msc, + int64_t divisor, int64_t remainder); + + /** + * Enable or disable frame usage tracking. + * + * \since Internal API version 20030317. + */ + int (*frameTracking)(__DRInativeDisplay *dpy, void *drawablePrivate, GLboolean enable); + + /** + * Retrieve frame usage information. + * + * \since Internal API version 20030317. + */ + int (*queryFrameTracking)(__DRInativeDisplay *dpy, void *drawablePrivate, + int64_t * sbc, int64_t * missedFrames, + float * lastMissedUsage, float * usage ); + + /** + * Used by drivers that implement the GLX_SGI_swap_control or + * GLX_MESA_swap_control extension. + * + * \since Internal API version 20030317. + */ + unsigned swap_interval; + + /** + * Used by drivers that implement the GLX_MESA_copy_sub_buffer extension. + * + * \since Internal API version 20060314. + */ + void (*copySubBuffer)(__DRInativeDisplay *dpy, void *drawablePrivate, + int x, int y, int w, int h); +}; + +#endif diff --git a/hw/kdrive/ephyr/Makefile.am b/hw/kdrive/ephyr/Makefile.am index 193c26bd5..290aa3409 100644 --- a/hw/kdrive/ephyr/Makefile.am +++ b/hw/kdrive/ephyr/Makefile.am @@ -3,7 +3,7 @@ INCLUDES = \ @KDRIVE_CFLAGS@ \ -I$(srcdir)/../../../exa -noinst_LIBRARIES = libxephyr-hostx.a libxephyr-hostxv.a libxephyr.a +noinst_LIBRARIES = libxephyr-hostx.a libxephyr-hostxv.a libxephyr.a bin_PROGRAMS = Xephyr @@ -22,11 +22,16 @@ libxephyr_a_SOURCES = \ ephyr.c \ ephyr_draw.c \ ephyrvideo.c \ + ephyrdriext.c \ + ephyrdri.c \ + ephyrdri.h \ os.c \ hostx.h \ ephyr.h \ ephyrlog.h +libxephyr_a_CFLAGS = @LIBDRM_CFLAGS@ @DRIPROTO_CFLAGS@ + Xephyr_SOURCES = \ ephyrinit.c @@ -36,7 +41,8 @@ Xephyr_LDADD = \ libxephyr-hostxv.a \ ../../../exa/libexa.la \ @KDRIVE_LIBS@ \ - @XEPHYR_LIBS@ + @XEPHYR_LIBS@ \ + @LIBDRM_LIBS@ Xephyr_DEPENDENCIES = \ libxephyr.a \ diff --git a/hw/kdrive/ephyr/ephyrdri.c b/hw/kdrive/ephyr/ephyrdri.c new file mode 100644 index 000000000..c54e876dc --- /dev/null +++ b/hw/kdrive/ephyr/ephyrdri.c @@ -0,0 +1,206 @@ +/* + * Xephyr - A kdrive X server thats runs in a host X window. + * Authored by Matthew Allum + * + * Copyright © 2007 OpenedHand Ltd + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of OpenedHand Ltd not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OpenedHand Ltd makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OpenedHand Ltd BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Authors: + * Dodji Seketeli + */ +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include +/*#define _XF86DRI_SERVER_*/ +#include +#include +#include "hostx.h" +#include "ephyrdri.h" +#define _HAVE_XALLOC_DECLS +#include "ephyrlog.h" + +#ifndef TRUE +#define TRUE 1 +#endif /*TRUE*/ + +#ifndef FALSE +#define FALSE 0 +#endif /*FALSE*/ + +Bool +ephyrDRIQueryDirectRenderingCapable (int a_screen, Bool *a_is_capable) +{ + Display *dpy=hostx_get_display () ; + Bool is_ok=FALSE ; + + EPHYR_LOG ("enter\n") ; + is_ok = XF86DRIQueryDirectRenderingCapable (dpy, a_screen, a_is_capable) ; + EPHYR_LOG ("leave\n") ; + + return is_ok ; +} + +Bool +ephyrDRIOpenConnection (int a_screen, drm_handle_t *a_sarea, char **a_bus_id_string) +{ + Display *dpy = hostx_get_display () ; + Bool is_ok=FALSE ; + + EPHYR_LOG ("enter\n") ; + is_ok = XF86DRIOpenConnection (dpy, a_screen, a_sarea, a_bus_id_string) ; + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +Bool +ephyrDRIAuthConnection (int a_screen, drm_magic_t a_magic) +{ + Display *dpy = hostx_get_display () ; + Bool is_ok=FALSE ; + + EPHYR_LOG ("enter\n") ; + is_ok = XF86DRIAuthConnection (dpy, a_screen, a_magic) ; + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +Bool +ephyrDRICloseConnection (int a_screen) +{ + Display *dpy = hostx_get_display () ; + Bool is_ok=FALSE ; + + EPHYR_LOG ("enter\n") ; + is_ok = XF86DRICloseConnection (dpy, a_screen) ; + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +Bool +ephyrDRIGetClientDriverName (int a_screen, + int *a_ddx_driver_major_version, + int *a_ddx_driver_minor_version, + int *a_ddx_driver_patch_version, + char ** a_client_driver_name) +{ + Display *dpy = hostx_get_display () ; + Bool is_ok=FALSE ; + + EPHYR_LOG ("enter\n") ; + is_ok = XF86DRIGetClientDriverName (dpy, a_screen, + a_ddx_driver_major_version, + a_ddx_driver_minor_version, + a_ddx_driver_patch_version, + a_client_driver_name) ; + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +Bool +ephyrDRICreateContext (int a_screen, + int a_visual_id, + unsigned long int *a_returned_ctxt_id, + drm_context_t *a_hw_ctxt) +{ + Display *dpy = hostx_get_display () ; + Bool is_ok=FALSE ; + Visual v; + + EPHYR_LOG ("enter\n") ; + memset (&v, 0, sizeof (v)) ; + v.visualid = a_visual_id ; + is_ok = XF86DRICreateContext (dpy, + a_screen, + &v, + a_returned_ctxt_id, + a_hw_ctxt) ; + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +Bool +ephyrDRIDestroyContext (int a_screen, + int a_context_id) +{ + Display *dpy = hostx_get_display () ; + Bool is_ok=FALSE ; + + EPHYR_LOG ("enter\n") ; + is_ok = XF86DRIDestroyContext (dpy, a_screen, a_context_id) ; + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +Bool +ephyrDRICreateDrawable (int a_screen, + int a_drawable, + drm_drawable_t *a_hw_drawable) +{ + EPHYR_LOG ("enter\n") ; + return FALSE ; + EPHYR_LOG ("leave\n") ; +} + +Bool +ephyrDRIDestroyDrawable (int a_screen, int a_drawable) +{ + EPHYR_LOG ("enter\n") ; + return FALSE ; + EPHYR_LOG ("leave\n") ; +} + +Bool +ephyrDRIGetDrawableInfo (int a_screen, + int a_drawable, + unsigned int *a_index, + unsigned int *a_stamp, + int *a_x, + int *a_y, + int *a_w, + int *a_h, + int *a_num_clip_rects, + drm_clip_rect_t **a_clip_rects, + int *a_back_x, + int *a_back_y, + int *num_back_clip_rects, + drm_clip_rect_t **a_back_clip_rects) +{ + EPHYR_LOG ("enter\n") ; + return FALSE ; + EPHYR_LOG ("leave\n") ; +} + +Bool +ephyrDRIGetDeviceInfo (int a_screen, + drm_handle_t *a_frame_buffer, + int *a_fb_origin, + int *a_fb_size, + int *a_fb_stride, + int *a_dev_private_size, + void **a_dev_private) +{ + EPHYR_LOG ("enter\n") ; + return FALSE ; + EPHYR_LOG ("leave\n") ; +} + diff --git a/hw/kdrive/ephyr/ephyrdri.h b/hw/kdrive/ephyr/ephyrdri.h new file mode 100644 index 000000000..d77467f99 --- /dev/null +++ b/hw/kdrive/ephyr/ephyrdri.h @@ -0,0 +1,75 @@ +/* + * Xephyr - A kdrive X server thats runs in a host X window. + * Authored by Matthew Allum + * + * Copyright © 2007 OpenedHand Ltd + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of OpenedHand Ltd not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OpenedHand Ltd makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OpenedHand Ltd BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Authors: + * Dodji Seketeli + */ + +#ifndef __EPHYRDRI_H__ +#define __EPHYRDRI_H__ + +#include + +Bool ephyrDRIQueryDirectRenderingCapable (int a_screen, Bool *a_is_capable) ; +Bool ephyrDRIOpenConnection (int screen, drm_handle_t *a_sarea, char **a_bus_id_string) ; +Bool ephyrDRIAuthConnection (int a_screen, drm_magic_t a_magic) ; +Bool ephyrDRICloseConnection (int a_screen) ; +Bool ephyrDRIGetClientDriverName (int a_screen, + int *a_ddx_driver_major_version, + int *a_ddx_driver_minor_version, + int *a_ddx_driver_patch_version, + char ** a_client_driver_name) ; +Bool ephyrDRICreateContext (int a_screen, + int a_visual_id, + unsigned long int *a_returned_ctx_id, + drm_context_t *a_hw_ctx) ; +Bool ephyrDRIDestroyContext (int a_screen, + int a_context_id) ; +Bool ephyrDRICreateDrawable (int a_screen, + int a_drawable, + drm_drawable_t *a_hw_drawable) ; +Bool ephyrDRIDestroyDrawable (int a_screen, int a_drawable) ; +Bool ephyrDRIGetDrawableInfo (int a_screen, + int a_drawable, + unsigned int *a_index, + unsigned int *a_stamp, + int *a_x, + int *a_y, + int *a_w, + int *a_h, + int *a_num_clip_rects, + drm_clip_rect_t **a_clip_rects, + int *a_back_x, + int *a_back_y, + int *num_back_clip_rects, + drm_clip_rect_t **a_back_clip_rects) ; +Bool ephyrDRIGetDeviceInfo (int a_screen, + drm_handle_t *a_frame_buffer, + int *a_fb_origin, + int *a_fb_size, + int *a_fb_stride, + int *a_dev_private_size, + void **a_dev_private) ; +#endif /*__EPHYRDRI_H__*/ + diff --git a/hw/kdrive/ephyr/ephyrdriext.c b/hw/kdrive/ephyr/ephyrdriext.c new file mode 100644 index 000000000..926fa4cfe --- /dev/null +++ b/hw/kdrive/ephyr/ephyrdriext.c @@ -0,0 +1,691 @@ +/* + * Xephyr - A kdrive X server thats runs in a host X window. + * Authored by Matthew Allum + * + * Copyright © 2007 OpenedHand Ltd + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of OpenedHand Ltd not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OpenedHand Ltd makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OpenedHand Ltd BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * This file is heavily copied from hw/xfree86/dri/xf86dri.c + * + * Authors: + * Dodji Seketeli + */ +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include + +#define NEED_REPLIES +#define NEED_EVENTS +#include +#include +#define _XF86DRI_SERVER_ +#include +#include +#include "misc.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "scrnintstr.h" +#include "servermd.h" +#include "swaprep.h" +#include "ephyrdri.h" +#define _HAVE_XALLOC_DECLS +#include "ephyrlog.h" + +static int DRIErrorBase; + +static DISPATCH_PROC(ProcXF86DRIQueryVersion); +static DISPATCH_PROC(ProcXF86DRIQueryDirectRenderingCapable); +static DISPATCH_PROC(ProcXF86DRIOpenConnection); +static DISPATCH_PROC(ProcXF86DRICloseConnection); +static DISPATCH_PROC(ProcXF86DRIGetClientDriverName); +static DISPATCH_PROC(ProcXF86DRICreateContext); +static DISPATCH_PROC(ProcXF86DRIDestroyContext); +static DISPATCH_PROC(ProcXF86DRICreateDrawable); +static DISPATCH_PROC(ProcXF86DRIDestroyDrawable); +static DISPATCH_PROC(ProcXF86DRIGetDrawableInfo); +static DISPATCH_PROC(ProcXF86DRIGetDeviceInfo); +static DISPATCH_PROC(ProcXF86DRIDispatch); +static DISPATCH_PROC(ProcXF86DRIAuthConnection); + +static DISPATCH_PROC(SProcXF86DRIQueryVersion); +static DISPATCH_PROC(SProcXF86DRIQueryDirectRenderingCapable); +static DISPATCH_PROC(SProcXF86DRIDispatch); + +static void XF86DRIResetProc(ExtensionEntry* extEntry); + +static unsigned char DRIReqCode = 0; + +extern void XFree86DRIExtensionInit(void); + +void +XFree86DRIExtensionInit(void) +{ + ExtensionEntry* extEntry; + EPHYR_LOG ("enter\n") ; + +#ifdef XF86DRI_EVENTS + EventType = CreateNewResourceType(XF86DRIFreeEvents); +#endif + + if ((extEntry = AddExtension(XF86DRINAME, + XF86DRINumberEvents, + XF86DRINumberErrors, + ProcXF86DRIDispatch, + SProcXF86DRIDispatch, + XF86DRIResetProc, + StandardMinorOpcode))) { + DRIReqCode = (unsigned char)extEntry->base; + DRIErrorBase = extEntry->errorBase; + } + EPHYR_LOG ("leave\n") ; +} + +/*ARGSUSED*/ +static void +XF86DRIResetProc ( + ExtensionEntry* extEntry +) +{ +} + +static int +ProcXF86DRIQueryVersion( + register ClientPtr client +) +{ + xXF86DRIQueryVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH(xXF86DRIQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = XF86DRI_MAJOR_VERSION; + rep.minorVersion = XF86DRI_MINOR_VERSION; + rep.patchVersion = XF86DRI_PATCH_VERSION; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + swapl(&rep.patchVersion, n); + } + WriteToClient(client, sizeof(xXF86DRIQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + +static int +ProcXF86DRIQueryDirectRenderingCapable( + register ClientPtr client +) +{ + xXF86DRIQueryDirectRenderingCapableReply rep; + Bool isCapable; + register int n; + + REQUEST(xXF86DRIQueryDirectRenderingCapableReq); + REQUEST_SIZE_MATCH(xXF86DRIQueryDirectRenderingCapableReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + if (!ephyrDRIQueryDirectRenderingCapable (stuff->screen, &isCapable)) { + return BadValue; + } + rep.isCapable = isCapable; + + if (!LocalClient(client) || client->swapped) + rep.isCapable = 0; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + } + + WriteToClient(client, + sizeof(xXF86DRIQueryDirectRenderingCapableReply), (char *)&rep); + return (client->noClientException); +} + +static int +ProcXF86DRIOpenConnection( + register ClientPtr client +) +{ + xXF86DRIOpenConnectionReply rep; + drm_handle_t hSAREA; + char* busIdString; + + REQUEST(xXF86DRIOpenConnectionReq); + REQUEST_SIZE_MATCH(xXF86DRIOpenConnectionReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + if (!ephyrDRIOpenConnection(stuff->screen, + &hSAREA, + &busIdString)) { + return BadValue; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.busIdStringLength = 0; + if (busIdString) + rep.busIdStringLength = strlen(busIdString); + rep.length = (SIZEOF(xXF86DRIOpenConnectionReply) - SIZEOF(xGenericReply) + + ((rep.busIdStringLength + 3) & ~3)) >> 2; + + rep.hSAREALow = (CARD32)(hSAREA & 0xffffffff); +#if defined(LONG64) && !defined(__linux__) + rep.hSAREAHigh = (CARD32)(hSAREA >> 32); +#else + rep.hSAREAHigh = 0; +#endif + + WriteToClient(client, sizeof(xXF86DRIOpenConnectionReply), (char *)&rep); + if (rep.busIdStringLength) + WriteToClient(client, rep.busIdStringLength, busIdString); + return (client->noClientException); +} + +static int +ProcXF86DRIAuthConnection( + register ClientPtr client +) +{ + xXF86DRIAuthConnectionReply rep; + + REQUEST(xXF86DRIAuthConnectionReq); + REQUEST_SIZE_MATCH(xXF86DRIAuthConnectionReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.authenticated = 1; + + if (!ephyrDRIAuthConnection (stuff->screen, stuff->magic)) { + ErrorF("Failed to authenticate %lu\n", (unsigned long)stuff->magic); + rep.authenticated = 0; + } + WriteToClient(client, sizeof(xXF86DRIAuthConnectionReply), (char *)&rep); + return (client->noClientException); +} + +static int +ProcXF86DRICloseConnection( + register ClientPtr client +) +{ + REQUEST(xXF86DRICloseConnectionReq); + REQUEST_SIZE_MATCH(xXF86DRICloseConnectionReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + /* + DRICloseConnection( screenInfo.screens[stuff->screen]); + */ + + return (client->noClientException); +} + +static int +ProcXF86DRIGetClientDriverName( + register ClientPtr client +) +{ + xXF86DRIGetClientDriverNameReply rep; + char* clientDriverName; + + REQUEST(xXF86DRIGetClientDriverNameReq); + REQUEST_SIZE_MATCH(xXF86DRIGetClientDriverNameReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + ephyrDRIGetClientDriverName (stuff->screen, + (int *)&rep.ddxDriverMajorVersion, + (int *)&rep.ddxDriverMinorVersion, + (int *)&rep.ddxDriverPatchVersion, + &clientDriverName); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.clientDriverNameLength = 0; + if (clientDriverName) + rep.clientDriverNameLength = strlen(clientDriverName); + rep.length = (SIZEOF(xXF86DRIGetClientDriverNameReply) - + SIZEOF(xGenericReply) + + ((rep.clientDriverNameLength + 3) & ~3)) >> 2; + + WriteToClient(client, + sizeof(xXF86DRIGetClientDriverNameReply), (char *)&rep); + if (rep.clientDriverNameLength) + WriteToClient(client, + rep.clientDriverNameLength, + clientDriverName); + return (client->noClientException); +} + +static int +ProcXF86DRICreateContext( + register ClientPtr client +) +{ + xXF86DRICreateContextReply rep; + ScreenPtr pScreen; + VisualPtr visual; + int i; + + REQUEST(xXF86DRICreateContextReq); + REQUEST_SIZE_MATCH(xXF86DRICreateContextReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + pScreen = screenInfo.screens[stuff->screen]; + visual = pScreen->visuals; + + /* Find the requested X visual */ + for (i = 0; i < pScreen->numVisuals; i++, visual++) + if (visual->vid == stuff->visual) + break; + if (i == pScreen->numVisuals) { + /* No visual found */ + return BadValue; + } + + /* + if (!DRICreateContext( pScreen, + visual, + stuff->context, + (drm_context_t *)&rep.hHWContext)) { + return BadValue; + } + */ + + WriteToClient(client, sizeof(xXF86DRICreateContextReply), (char *)&rep); + return (client->noClientException); +} + +static int +ProcXF86DRIDestroyContext( + register ClientPtr client +) +{ + REQUEST(xXF86DRIDestroyContextReq); + REQUEST_SIZE_MATCH(xXF86DRIDestroyContextReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + /* + if (!DRIDestroyContext( screenInfo.screens[stuff->screen], + stuff->context)) { + return BadValue; + } + */ + + return (client->noClientException); +} + +static int +ProcXF86DRICreateDrawable( + ClientPtr client +) +{ + xXF86DRICreateDrawableReply rep; + DrawablePtr pDrawable; + int rc; + + REQUEST(xXF86DRICreateDrawableReq); + REQUEST_SIZE_MATCH(xXF86DRICreateDrawableReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, + DixReadAccess); + if (rc != Success) + return rc; + + /*TODO: this cannot work. We must properly + * do the mapping between the xephyr drawable and + * the host drawable + */ + if (!ephyrDRICreateDrawable (stuff->screen, + 0/*should be host drawableID*/, + (drm_drawable_t *)&rep.hHWDrawable)) { + return BadValue; + } + + WriteToClient(client, sizeof(xXF86DRICreateDrawableReply), (char *)&rep); + return (client->noClientException); +} + +static int +ProcXF86DRIDestroyDrawable( + register ClientPtr client +) +{ + REQUEST(xXF86DRIDestroyDrawableReq); + DrawablePtr pDrawable; + REQUEST_SIZE_MATCH(xXF86DRIDestroyDrawableReq); + int rc; + + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, + DixReadAccess); + if (rc != Success) + return rc; + + if (!ephyrDRIDestroyDrawable(stuff->screen, + 0/*should be drawable in host x*/)) { + return BadValue; + } + return (client->noClientException); +} + +static int +ProcXF86DRIGetDrawableInfo( + register ClientPtr client +) +{ + xXF86DRIGetDrawableInfoReply rep; + DrawablePtr pDrawable; + int X, Y, W, H; + drm_clip_rect_t * pClipRects, *pClippedRects; + drm_clip_rect_t * pBackClipRects; + int backX, backY, rc; + + REQUEST(xXF86DRIGetDrawableInfoReq); + REQUEST_SIZE_MATCH(xXF86DRIGetDrawableInfoReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + /*TODO: this cannot work. + * We must properly do the mapping + * between xephyr drawable and the host drawable + */ + rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, + DixReadAccess); + if (rc != Success) + return rc; + + if (!ephyrDRIGetDrawableInfo (stuff->screen, + 0 /*should be the drawable in hostx*/, + (unsigned int*)&rep.drawableTableIndex, + (unsigned int*)&rep.drawableTableStamp, + (int*)&X, + (int*)&Y, + (int*)&W, + (int*)&H, + (int*)&rep.numClipRects, + &pClipRects, + &backX, + &backY, + (int*)&rep.numBackClipRects, + &pBackClipRects)) { + return BadValue; + } + + rep.drawableX = X; + rep.drawableY = Y; + rep.drawableWidth = W; + rep.drawableHeight = H; + rep.length = (SIZEOF(xXF86DRIGetDrawableInfoReply) - + SIZEOF(xGenericReply)); + + rep.backX = backX; + rep.backY = backY; + + if (rep.numBackClipRects) + rep.length += sizeof(drm_clip_rect_t) * rep.numBackClipRects; + + pClippedRects = pClipRects; + + if (rep.numClipRects) { + /* Clip cliprects to screen dimensions (redirected windows) */ + pClippedRects = xalloc(rep.numClipRects * sizeof(drm_clip_rect_t)); + + if (pClippedRects) { + ScreenPtr pScreen = screenInfo.screens[stuff->screen]; + int i, j; + + for (i = 0, j = 0; i < rep.numClipRects; i++) { + pClippedRects[j].x1 = max(pClipRects[i].x1, 0); + pClippedRects[j].y1 = max(pClipRects[i].y1, 0); + pClippedRects[j].x2 = min(pClipRects[i].x2, pScreen->width); + pClippedRects[j].y2 = min(pClipRects[i].y2, pScreen->height); + + if (pClippedRects[j].x1 < pClippedRects[j].x2 && + pClippedRects[j].y1 < pClippedRects[j].y2) { + j++; + } + } + + rep.numClipRects = j; + } else { + rep.numClipRects = 0; + } + + rep.length += sizeof(drm_clip_rect_t) * rep.numClipRects; + } + + rep.length = ((rep.length + 3) & ~3) >> 2; + + WriteToClient(client, sizeof(xXF86DRIGetDrawableInfoReply), (char *)&rep); + + if (rep.numClipRects) { + WriteToClient(client, + sizeof(drm_clip_rect_t) * rep.numClipRects, + (char *)pClippedRects); + xfree(pClippedRects); + } + + if (rep.numBackClipRects) { + WriteToClient(client, + sizeof(drm_clip_rect_t) * rep.numBackClipRects, + (char *)pBackClipRects); + } + + return (client->noClientException); +} + +static int +ProcXF86DRIGetDeviceInfo( + register ClientPtr client +) +{ + xXF86DRIGetDeviceInfoReply rep; + drm_handle_t hFrameBuffer; + void *pDevPrivate; + + REQUEST(xXF86DRIGetDeviceInfoReq); + REQUEST_SIZE_MATCH(xXF86DRIGetDeviceInfoReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + if (!ephyrDRIGetDeviceInfo (stuff->screen, + &hFrameBuffer, + (int*)&rep.framebufferOrigin, + (int*)&rep.framebufferSize, + (int*)&rep.framebufferStride, + (int*)&rep.devPrivateSize, + &pDevPrivate)) { + return BadValue; + } + + rep.hFrameBufferLow = (CARD32)(hFrameBuffer & 0xffffffff); +#if defined(LONG64) && !defined(__linux__) + rep.hFrameBufferHigh = (CARD32)(hFrameBuffer >> 32); +#else + rep.hFrameBufferHigh = 0; +#endif + + rep.length = 0; + if (rep.devPrivateSize) { + rep.length = (SIZEOF(xXF86DRIGetDeviceInfoReply) - + SIZEOF(xGenericReply) + + ((rep.devPrivateSize + 3) & ~3)) >> 2; + } + + WriteToClient(client, sizeof(xXF86DRIGetDeviceInfoReply), (char *)&rep); + if (rep.length) { + WriteToClient(client, rep.devPrivateSize, (char *)pDevPrivate); + } + return (client->noClientException); +} + +static int +ProcXF86DRIDispatch ( + register ClientPtr client +) +{ + REQUEST(xReq); + + switch (stuff->data) + { + case X_XF86DRIQueryVersion: + return ProcXF86DRIQueryVersion(client); + case X_XF86DRIQueryDirectRenderingCapable: + return ProcXF86DRIQueryDirectRenderingCapable(client); + } + + if (!LocalClient(client)) + return DRIErrorBase + XF86DRIClientNotLocal; + + switch (stuff->data) + { + case X_XF86DRIOpenConnection: + return ProcXF86DRIOpenConnection(client); + case X_XF86DRICloseConnection: + return ProcXF86DRICloseConnection(client); + case X_XF86DRIGetClientDriverName: + return ProcXF86DRIGetClientDriverName(client); + case X_XF86DRICreateContext: + return ProcXF86DRICreateContext(client); + case X_XF86DRIDestroyContext: + return ProcXF86DRIDestroyContext(client); + case X_XF86DRICreateDrawable: + return ProcXF86DRICreateDrawable(client); + case X_XF86DRIDestroyDrawable: + return ProcXF86DRIDestroyDrawable(client); + case X_XF86DRIGetDrawableInfo: + return ProcXF86DRIGetDrawableInfo(client); + case X_XF86DRIGetDeviceInfo: + return ProcXF86DRIGetDeviceInfo(client); + case X_XF86DRIAuthConnection: + return ProcXF86DRIAuthConnection(client); + /* {Open,Close}FullScreen are deprecated now */ + default: + return BadRequest; + } +} + +static int +SProcXF86DRIQueryVersion( + register ClientPtr client +) +{ + register int n; + REQUEST(xXF86DRIQueryVersionReq); + swaps(&stuff->length, n); + return ProcXF86DRIQueryVersion(client); +} + +static int +SProcXF86DRIQueryDirectRenderingCapable( + register ClientPtr client +) +{ + register int n; + REQUEST(xXF86DRIQueryDirectRenderingCapableReq); + swaps(&stuff->length, n); + swapl(&stuff->screen, n); + return ProcXF86DRIQueryDirectRenderingCapable(client); +} + +static int +SProcXF86DRIDispatch ( + register ClientPtr client +) +{ + REQUEST(xReq); + + /* + * Only local clients are allowed DRI access, but remote clients still need + * these requests to find out cleanly. + */ + switch (stuff->data) + { + case X_XF86DRIQueryVersion: + return SProcXF86DRIQueryVersion(client); + case X_XF86DRIQueryDirectRenderingCapable: + return SProcXF86DRIQueryDirectRenderingCapable(client); + default: + return DRIErrorBase + XF86DRIClientNotLocal; + } +} + From a38ad562a6f50e9d76a37917b936035215ea460e Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Wed, 15 Aug 2007 19:40:10 +0200 Subject: [PATCH 19/44] make xephyr talk DRI protocol with hostX * configure.ac,include/dix-config.h.in: define the XEPHYR_DRI macro. define it when --enable-xephyr and --enable-dri are both turned on. * hw/kdrive/ephyr/XF86dri.c: copy this from mesa source to enable Xephyr to talk DRI protocol the host X. In mesa, this is used by libGL.so to talk DRI protocol with the server. * hw/kdrive/ephyr/ephyr.c: finally initialise the DRI extension in the ephyrInitScreen() function. * hw/kdrive/ephyr/ephyrdri.c,ephyrdriext.c: safeguard the compilation using the XEPHYR_DRI macro. --- configure.ac | 7 + hw/kdrive/ephyr/Makefile.am | 8 +- hw/kdrive/ephyr/XF86dri.c | 635 ++++++++++++++++++++++++++++++++++ hw/kdrive/ephyr/ephyr.c | 5 + hw/kdrive/ephyr/ephyrdri.c | 7 +- hw/kdrive/ephyr/ephyrdriext.c | 10 +- include/dix-config.h.in | 2 + 7 files changed, 666 insertions(+), 8 deletions(-) create mode 100644 hw/kdrive/ephyr/XF86dri.c diff --git a/configure.ac b/configure.ac index a7f1e8493..125ee47ff 100644 --- a/configure.ac +++ b/configure.ac @@ -1842,6 +1842,13 @@ if test "$KDRIVE" = yes; then if test "x$XEPHYR" = xauto; then XEPHYR=$xephyr fi + XEPHYR_DRI=no + if test x$XEPHYR = xyes -a x$DRI = xyes; then + XEPHYR_DRI=yes + fi + if test x$XEPHYR_DRI = xyes ; then + AC_DEFINE(XEPHYR_DRI,1,[enable DRI extension in xephyr]) + fi # Xephyr needs nanosleep() which is in librt on Solaris AC_CHECK_FUNC([nanosleep], [], diff --git a/hw/kdrive/ephyr/Makefile.am b/hw/kdrive/ephyr/Makefile.am index 290aa3409..cc9c9109a 100644 --- a/hw/kdrive/ephyr/Makefile.am +++ b/hw/kdrive/ephyr/Makefile.am @@ -22,7 +22,8 @@ libxephyr_a_SOURCES = \ ephyr.c \ ephyr_draw.c \ ephyrvideo.c \ - ephyrdriext.c \ + XF86dri.c \ + ephyrdriext.c \ ephyrdri.c \ ephyrdri.h \ os.c \ @@ -41,8 +42,9 @@ Xephyr_LDADD = \ libxephyr-hostxv.a \ ../../../exa/libexa.la \ @KDRIVE_LIBS@ \ - @XEPHYR_LIBS@ \ - @LIBDRM_LIBS@ + @XEPHYR_LIBS@ \ + @LIBDRM_LIBS@ \ + -lGL Xephyr_DEPENDENCIES = \ libxephyr.a \ diff --git a/hw/kdrive/ephyr/XF86dri.c b/hw/kdrive/ephyr/XF86dri.c new file mode 100644 index 000000000..bed65e5a4 --- /dev/null +++ b/hw/kdrive/ephyr/XF86dri.c @@ -0,0 +1,635 @@ +/* $XFree86: xc/lib/GL/dri/XF86dri.c,v 1.13 2002/10/30 12:51:25 alanh Exp $ */ +/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +Copyright 2000 VA Linux Systems, 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 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 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: + * Kevin E. Martin + * Jens Owen + * Rickard E. (Rik) Faith + * + */ + +/* + * This file has been copied from the mesa source tree and a little bit + * modified by: + * + * Dodji Seketeli + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef XEPHYR_DRI + +/* THIS IS NOT AN X CONSORTIUM STANDARD */ + +#define NEED_REPLIES +#include +#include +#include +#include +#include +#include + +static XExtensionInfo _xf86dri_info_data; +static XExtensionInfo *xf86dri_info = &_xf86dri_info_data; +static char xf86dri_extension_name[] = XF86DRINAME; + +#define XF86DRICheckExtension(dpy,i,val) \ + XextCheckExtension (dpy, i, xf86dri_extension_name, val) + +/***************************************************************************** + * * + * private utility routines * + * * + *****************************************************************************/ + +static int close_display(Display *dpy, XExtCodes *extCodes); +static /* const */ XExtensionHooks xf86dri_extension_hooks = { + NULL, /* create_gc */ + NULL, /* copy_gc */ + NULL, /* flush_gc */ + NULL, /* free_gc */ + NULL, /* create_font */ + NULL, /* free_font */ + close_display, /* close_display */ + NULL, /* wire_to_event */ + NULL, /* event_to_wire */ + NULL, /* error */ + NULL, /* error_string */ +}; + +static XEXT_GENERATE_FIND_DISPLAY (find_display, xf86dri_info, + xf86dri_extension_name, + &xf86dri_extension_hooks, + 0, NULL) + +static XEXT_GENERATE_CLOSE_DISPLAY (close_display, xf86dri_info) + + +/***************************************************************************** + * * + * public XFree86-DRI Extension routines * + * * + *****************************************************************************/ + +#if 0 +#include +#define TRACE(msg) fprintf(stderr,"XF86DRI%s\n", msg); +#else +#define TRACE(msg) +#endif + + +Bool XF86DRIQueryExtension (dpy, event_basep, error_basep) + Display *dpy; + int *event_basep, *error_basep; +{ + XExtDisplayInfo *info = find_display (dpy); + + TRACE("QueryExtension..."); + if (XextHasExtension(info)) { + *event_basep = info->codes->first_event; + *error_basep = info->codes->first_error; + TRACE("QueryExtension... return True"); + return True; + } else { + TRACE("QueryExtension... return False"); + return False; + } +} + +Bool XF86DRIQueryVersion(dpy, majorVersion, minorVersion, patchVersion) + Display* dpy; + int* majorVersion; + int* minorVersion; + int* patchVersion; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86DRIQueryVersionReply rep; + xXF86DRIQueryVersionReq *req; + + TRACE("QueryVersion..."); + XF86DRICheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DRIQueryVersion, req); + req->reqType = info->codes->major_opcode; + req->driReqType = X_XF86DRIQueryVersion; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + TRACE("QueryVersion... return False"); + return False; + } + *majorVersion = rep.majorVersion; + *minorVersion = rep.minorVersion; + *patchVersion = rep.patchVersion; + UnlockDisplay(dpy); + SyncHandle(); + TRACE("QueryVersion... return True"); + return True; +} + +Bool XF86DRIQueryDirectRenderingCapable(dpy, screen, isCapable) + Display* dpy; + int screen; + Bool* isCapable; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86DRIQueryDirectRenderingCapableReply rep; + xXF86DRIQueryDirectRenderingCapableReq *req; + + TRACE("QueryDirectRenderingCapable..."); + XF86DRICheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DRIQueryDirectRenderingCapable, req); + req->reqType = info->codes->major_opcode; + req->driReqType = X_XF86DRIQueryDirectRenderingCapable; + req->screen = screen; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + TRACE("QueryDirectRenderingCapable... return False"); + return False; + } + *isCapable = rep.isCapable; + UnlockDisplay(dpy); + SyncHandle(); + TRACE("QueryDirectRenderingCapable... return True"); + return True; +} + +Bool XF86DRIOpenConnection(dpy, screen, hSAREA, busIdString) + Display* dpy; + int screen; + drm_handle_t * hSAREA; + char **busIdString; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86DRIOpenConnectionReply rep; + xXF86DRIOpenConnectionReq *req; + + TRACE("OpenConnection..."); + XF86DRICheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DRIOpenConnection, req); + req->reqType = info->codes->major_opcode; + req->driReqType = X_XF86DRIOpenConnection; + req->screen = screen; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + TRACE("OpenConnection... return False"); + return False; + } + + *hSAREA = rep.hSAREALow; + if (sizeof(drm_handle_t) == 8) { + int shift = 32; /* var to prevent warning on next line */ + *hSAREA |= ((drm_handle_t) rep.hSAREAHigh) << shift; + } + + if (rep.length) { + if (!(*busIdString = (char *)Xcalloc(rep.busIdStringLength + 1, 1))) { + _XEatData(dpy, ((rep.busIdStringLength+3) & ~3)); + UnlockDisplay(dpy); + SyncHandle(); + TRACE("OpenConnection... return False"); + return False; + } + _XReadPad(dpy, *busIdString, rep.busIdStringLength); + } else { + *busIdString = NULL; + } + UnlockDisplay(dpy); + SyncHandle(); + TRACE("OpenConnection... return True"); + return True; +} + +Bool XF86DRIAuthConnection(dpy, screen, magic) + Display* dpy; + int screen; + drm_magic_t magic; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86DRIAuthConnectionReq *req; + xXF86DRIAuthConnectionReply rep; + + TRACE("AuthConnection..."); + XF86DRICheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DRIAuthConnection, req); + req->reqType = info->codes->major_opcode; + req->driReqType = X_XF86DRIAuthConnection; + req->screen = screen; + req->magic = magic; + rep.authenticated = 0; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse) || !rep.authenticated) { + UnlockDisplay(dpy); + SyncHandle(); + TRACE("AuthConnection... return False"); + return False; + } + UnlockDisplay(dpy); + SyncHandle(); + TRACE("AuthConnection... return True"); + return True; +} + +Bool XF86DRICloseConnection(dpy, screen) + Display* dpy; + int screen; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86DRICloseConnectionReq *req; + + TRACE("CloseConnection..."); + + XF86DRICheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DRICloseConnection, req); + req->reqType = info->codes->major_opcode; + req->driReqType = X_XF86DRICloseConnection; + req->screen = screen; + UnlockDisplay(dpy); + SyncHandle(); + TRACE("CloseConnection... return True"); + return True; +} + +Bool XF86DRIGetClientDriverName(dpy, screen, ddxDriverMajorVersion, + ddxDriverMinorVersion, ddxDriverPatchVersion, clientDriverName) + Display* dpy; + int screen; + int* ddxDriverMajorVersion; + int* ddxDriverMinorVersion; + int* ddxDriverPatchVersion; + char** clientDriverName; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86DRIGetClientDriverNameReply rep; + xXF86DRIGetClientDriverNameReq *req; + + TRACE("GetClientDriverName..."); + XF86DRICheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DRIGetClientDriverName, req); + req->reqType = info->codes->major_opcode; + req->driReqType = X_XF86DRIGetClientDriverName; + req->screen = screen; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + TRACE("GetClientDriverName... return False"); + return False; + } + + *ddxDriverMajorVersion = rep.ddxDriverMajorVersion; + *ddxDriverMinorVersion = rep.ddxDriverMinorVersion; + *ddxDriverPatchVersion = rep.ddxDriverPatchVersion; + + if (rep.length) { + if (!(*clientDriverName = (char *)Xcalloc(rep.clientDriverNameLength + 1, 1))) { + _XEatData(dpy, ((rep.clientDriverNameLength+3) & ~3)); + UnlockDisplay(dpy); + SyncHandle(); + TRACE("GetClientDriverName... return False"); + return False; + } + _XReadPad(dpy, *clientDriverName, rep.clientDriverNameLength); + } else { + *clientDriverName = NULL; + } + UnlockDisplay(dpy); + SyncHandle(); + TRACE("GetClientDriverName... return True"); + return True; +} + +Bool XF86DRICreateContextWithConfig(dpy, screen, configID, context, + hHWContext) + Display* dpy; + int screen; + int configID; + XID* context; + drm_context_t * hHWContext; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86DRICreateContextReply rep; + xXF86DRICreateContextReq *req; + + TRACE("CreateContext..."); + XF86DRICheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DRICreateContext, req); + req->reqType = info->codes->major_opcode; + req->driReqType = X_XF86DRICreateContext; + req->visual = configID; + req->screen = screen; + *context = XAllocID(dpy); + req->context = *context; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + TRACE("CreateContext... return False"); + return False; + } + *hHWContext = rep.hHWContext; + UnlockDisplay(dpy); + SyncHandle(); + TRACE("CreateContext... return True"); + return True; +} + +Bool XF86DRICreateContext(dpy, screen, visual, context, hHWContext) + Display* dpy; + int screen; + Visual* visual; + XID* context; + drm_context_t * hHWContext; +{ + return XF86DRICreateContextWithConfig( dpy, screen, visual->visualid, + context, hHWContext ); +} + +GLboolean XF86DRIDestroyContext( __DRInativeDisplay * ndpy, int screen, + __DRIid context ) +{ + Display * const dpy = (Display *) ndpy; + XExtDisplayInfo *info = find_display (dpy); + xXF86DRIDestroyContextReq *req; + + TRACE("DestroyContext..."); + XF86DRICheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DRIDestroyContext, req); + req->reqType = info->codes->major_opcode; + req->driReqType = X_XF86DRIDestroyContext; + req->screen = screen; + req->context = context; + UnlockDisplay(dpy); + SyncHandle(); + TRACE("DestroyContext... return True"); + return True; +} + +GLboolean XF86DRICreateDrawable( __DRInativeDisplay * ndpy, int screen, + __DRIid drawable, drm_drawable_t * hHWDrawable ) +{ + Display * const dpy = (Display *) ndpy; + XExtDisplayInfo *info = find_display (dpy); + xXF86DRICreateDrawableReply rep; + xXF86DRICreateDrawableReq *req; + + TRACE("CreateDrawable..."); + XF86DRICheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DRICreateDrawable, req); + req->reqType = info->codes->major_opcode; + req->driReqType = X_XF86DRICreateDrawable; + req->screen = screen; + req->drawable = drawable; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + TRACE("CreateDrawable... return False"); + return False; + } + *hHWDrawable = rep.hHWDrawable; + UnlockDisplay(dpy); + SyncHandle(); + TRACE("CreateDrawable... return True"); + return True; +} + +GLboolean XF86DRIDestroyDrawable( __DRInativeDisplay * ndpy, int screen, + __DRIid drawable ) +{ + Display * const dpy = (Display *) ndpy; + XExtDisplayInfo *info = find_display (dpy); + xXF86DRIDestroyDrawableReq *req; + + TRACE("DestroyDrawable..."); + XF86DRICheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DRIDestroyDrawable, req); + req->reqType = info->codes->major_opcode; + req->driReqType = X_XF86DRIDestroyDrawable; + req->screen = screen; + req->drawable = drawable; + UnlockDisplay(dpy); + SyncHandle(); + TRACE("DestroyDrawable... return True"); + return True; +} + +Bool XF86DRIGetDrawableInfo(Display* dpy, int screen, Drawable drawable, + unsigned int* index, unsigned int* stamp, + int* X, int* Y, int* W, int* H, + int* numClipRects, drm_clip_rect_t ** pClipRects, + int* backX, int* backY, + int* numBackClipRects, drm_clip_rect_t ** pBackClipRects ) +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86DRIGetDrawableInfoReply rep; + xXF86DRIGetDrawableInfoReq *req; + int total_rects; + + TRACE("GetDrawableInfo..."); + XF86DRICheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DRIGetDrawableInfo, req); + req->reqType = info->codes->major_opcode; + req->driReqType = X_XF86DRIGetDrawableInfo; + req->screen = screen; + req->drawable = drawable; + + if (!_XReply(dpy, (xReply *)&rep, 1, xFalse)) + { + UnlockDisplay(dpy); + SyncHandle(); + TRACE("GetDrawableInfo... return False"); + return False; + } + *index = rep.drawableTableIndex; + *stamp = rep.drawableTableStamp; + *X = (int)rep.drawableX; + *Y = (int)rep.drawableY; + *W = (int)rep.drawableWidth; + *H = (int)rep.drawableHeight; + *numClipRects = rep.numClipRects; + total_rects = *numClipRects; + + *backX = rep.backX; + *backY = rep.backY; + *numBackClipRects = rep.numBackClipRects; + total_rects += *numBackClipRects; + +#if 0 + /* Because of the fix in Xserver/GL/dri/xf86dri.c, this check breaks + * backwards compatibility (Because of the >> 2 shift) but the fix + * enables multi-threaded apps to work. + */ + if (rep.length != ((((SIZEOF(xXF86DRIGetDrawableInfoReply) - + SIZEOF(xGenericReply) + + total_rects * sizeof(drm_clip_rect_t)) + 3) & ~3) >> 2)) { + _XEatData(dpy, rep.length); + UnlockDisplay(dpy); + SyncHandle(); + TRACE("GetDrawableInfo... return False"); + return False; + } +#endif + + if (*numClipRects) { + int len = sizeof(drm_clip_rect_t) * (*numClipRects); + + *pClipRects = (drm_clip_rect_t *)Xcalloc(len, 1); + if (*pClipRects) + _XRead(dpy, (char*)*pClipRects, len); + } else { + *pClipRects = NULL; + } + + if (*numBackClipRects) { + int len = sizeof(drm_clip_rect_t) * (*numBackClipRects); + + *pBackClipRects = (drm_clip_rect_t *)Xcalloc(len, 1); + if (*pBackClipRects) + _XRead(dpy, (char*)*pBackClipRects, len); + } else { + *pBackClipRects = NULL; + } + + UnlockDisplay(dpy); + SyncHandle(); + TRACE("GetDrawableInfo... return True"); + return True; +} + +Bool XF86DRIGetDeviceInfo(dpy, screen, hFrameBuffer, + fbOrigin, fbSize, fbStride, devPrivateSize, pDevPrivate) + Display* dpy; + int screen; + drm_handle_t * hFrameBuffer; + int* fbOrigin; + int* fbSize; + int* fbStride; + int* devPrivateSize; + void** pDevPrivate; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86DRIGetDeviceInfoReply rep; + xXF86DRIGetDeviceInfoReq *req; + + TRACE("GetDeviceInfo..."); + XF86DRICheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DRIGetDeviceInfo, req); + req->reqType = info->codes->major_opcode; + req->driReqType = X_XF86DRIGetDeviceInfo; + req->screen = screen; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + TRACE("GetDeviceInfo... return False"); + return False; + } + + *hFrameBuffer = rep.hFrameBufferLow; + if (sizeof(drm_handle_t) == 8) { + int shift = 32; /* var to prevent warning on next line */ + *hFrameBuffer |= ((drm_handle_t) rep.hFrameBufferHigh) << shift; + } + + *fbOrigin = rep.framebufferOrigin; + *fbSize = rep.framebufferSize; + *fbStride = rep.framebufferStride; + *devPrivateSize = rep.devPrivateSize; + + if (rep.length) { + if (!(*pDevPrivate = (void *)Xcalloc(rep.devPrivateSize, 1))) { + _XEatData(dpy, ((rep.devPrivateSize+3) & ~3)); + UnlockDisplay(dpy); + SyncHandle(); + TRACE("GetDeviceInfo... return False"); + return False; + } + _XRead(dpy, (char*)*pDevPrivate, rep.devPrivateSize); + } else { + *pDevPrivate = NULL; + } + + UnlockDisplay(dpy); + SyncHandle(); + TRACE("GetDeviceInfo... return True"); + return True; +} + +Bool XF86DRIOpenFullScreen(dpy, screen, drawable) + Display* dpy; + int screen; + Drawable drawable; +{ + /* This function and the underlying X protocol are deprecated. + */ + (void) dpy; + (void) screen; + (void) drawable; + return False; +} + +Bool XF86DRICloseFullScreen(dpy, screen, drawable) + Display* dpy; + int screen; + Drawable drawable; +{ + /* This function and the underlying X protocol are deprecated. + */ + (void) dpy; + (void) screen; + (void) drawable; + return True; +} +#endif /*EPHYR_DRI*/ + diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c index 2febb655d..330158a7d 100644 --- a/hw/kdrive/ephyr/ephyr.c +++ b/hw/kdrive/ephyr/ephyr.c @@ -606,6 +606,7 @@ ephyrInitScreen (ScreenPtr pScreen) hostx_set_screen_number (screen, pScreen->myNum); hostx_set_win_title (screen, "(ctrl+shift grabs mouse and keyboard)") ; pScreen->CreateColormap = ephyrCreateColormap; + #ifdef XV if (!ephyrInitVideo (pScreen)) { EPHYR_LOG_ERROR ("failed to initialize xvideo\n") ; @@ -613,6 +614,10 @@ ephyrInitScreen (ScreenPtr pScreen) EPHYR_LOG ("initialized xvideo okay\n") ; } #endif /*XV*/ + +#ifdef XEPHYR_DRI + ephyrDRIExtensionInit () ; +#endif return TRUE; } diff --git a/hw/kdrive/ephyr/ephyrdri.c b/hw/kdrive/ephyr/ephyrdri.c index c54e876dc..5201082d8 100644 --- a/hw/kdrive/ephyr/ephyrdri.c +++ b/hw/kdrive/ephyr/ephyrdri.c @@ -25,10 +25,12 @@ * Authors: * Dodji Seketeli */ -#ifdef HAVE_XORG_CONFIG_H -#include +#ifdef HAVE_CONFIG_H +#include #endif +#ifdef XEPHYR_DRI + #include #include /*#define _XF86DRI_SERVER_*/ @@ -203,4 +205,5 @@ ephyrDRIGetDeviceInfo (int a_screen, return FALSE ; EPHYR_LOG ("leave\n") ; } +#endif /*EPHYR_DRI*/ diff --git a/hw/kdrive/ephyr/ephyrdriext.c b/hw/kdrive/ephyr/ephyrdriext.c index 926fa4cfe..437d8c4da 100644 --- a/hw/kdrive/ephyr/ephyrdriext.c +++ b/hw/kdrive/ephyr/ephyrdriext.c @@ -27,10 +27,13 @@ * Authors: * Dodji Seketeli */ -#ifdef HAVE_XORG_CONFIG_H -#include + +#ifdef HAVE_CONFIG_H +#include #endif +#ifdef XEPHYR_DRI + #include #define NEED_REPLIES @@ -79,7 +82,7 @@ static unsigned char DRIReqCode = 0; extern void XFree86DRIExtensionInit(void); void -XFree86DRIExtensionInit(void) +ephyrDRIExtensionInit(void) { ExtensionEntry* extEntry; EPHYR_LOG ("enter\n") ; @@ -689,3 +692,4 @@ SProcXF86DRIDispatch ( } } +#endif /*XEPHYR_DRI*/ diff --git a/include/dix-config.h.in b/include/dix-config.h.in index 563d3439f..3b9f15c28 100644 --- a/include/dix-config.h.in +++ b/include/dix-config.h.in @@ -425,6 +425,8 @@ /* Support DRI extension */ #undef XF86DRI +#undef XEPHYR_DRI + /* Build DBE support */ #undef DBE From 47e6dff89e48249828e828502e98951eee7f85bc Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Thu, 16 Aug 2007 17:07:36 +0200 Subject: [PATCH 20/44] Xephyr-Xv: fix a crash when host X support several ports * hw/kdrive/ephyr/ephyrvideo.c: (ephyrXVPrivQueryHostAdaptors): properly set port private luke. This fixes a crash when the host Xv supports multiple ports. Make sure number of ports cannot be zero. --- hw/kdrive/ephyr/ephyrvideo.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/hw/kdrive/ephyr/ephyrvideo.c b/hw/kdrive/ephyr/ephyrvideo.c index e2f00c8a1..0c003519d 100644 --- a/hw/kdrive/ephyr/ephyrvideo.c +++ b/hw/kdrive/ephyr/ephyrvideo.c @@ -404,7 +404,8 @@ ephyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) EphyrHostAttribute *attributes=NULL ; EphyrHostImageFormat *image_formats=NULL ; int num_video_formats=0, base_port_id=0, - num_attributes=0, num_formats=0, i=0; + num_attributes=0, num_formats=0, i=0, + port_priv_offset=0; unsigned num_encodings=0 ; Bool is_ok = FALSE ; @@ -441,6 +442,12 @@ ephyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) ephyrHostXVAdaptorArrayAt (a_this->host_adaptors, i) ; if (!cur_host_adaptor) continue ; + a_this->adaptors[i].nPorts = + ephyrHostXVAdaptorGetNbPorts (cur_host_adaptor) ; + if (a_this->adaptors[i].nPorts <=0) { + EPHYR_LOG_ERROR ("Could not find any port of adaptor %d\n", i) ; + continue ; + } a_this->adaptors[i].type = ephyrHostXVAdaptorGetType (cur_host_adaptor) ; a_this->adaptors[i].type |= XvWindowMask ; @@ -475,16 +482,18 @@ ephyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) &num_video_formats); a_this->adaptors[i].pFormats = (KdVideoFormatPtr) video_formats ; a_this->adaptors[i].nFormats = num_video_formats ; + /* got a_this->adaptors[i].nPorts already a_this->adaptors[i].nPorts = ephyrHostXVAdaptorGetNbPorts (cur_host_adaptor) ; + */ a_this->adaptors[i].pPortPrivates = xcalloc (a_this->adaptors[i].nPorts, sizeof (DevUnion) + sizeof (EphyrPortPriv)) ; + port_priv_offset = a_this->adaptors[i].nPorts; for (j=0; j < a_this->adaptors[i].nPorts; j++) { - int port_priv_offset = a_this->adaptors[i].nPorts ; - EphyrPortPriv *port_priv = - (EphyrPortPriv*) - &a_this->adaptors[i].pPortPrivates[port_priv_offset + j]; + EphyrPortPriv *port_privs_base = + (EphyrPortPriv*)&a_this->adaptors[i].pPortPrivates[port_priv_offset]; + EphyrPortPriv *port_priv = &port_privs_base[j] ; port_priv->port_number = base_port_id + j; port_priv->current_adaptor = &a_this->adaptors[i] ; port_priv->xv_priv = a_this ; From 810dc55866d1c2343512354646c7ab309ea1fad2 Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Thu, 16 Aug 2007 17:11:22 +0200 Subject: [PATCH 21/44] Ephyr-Xv: add a new line to a log * hw/kdrive/ephyr/ephyrvideo.c: (ephyrQueryImageAttributes): add newline to log. --- hw/kdrive/ephyr/ephyrvideo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/kdrive/ephyr/ephyrvideo.c b/hw/kdrive/ephyr/ephyrvideo.c index 0c003519d..3c28f0d38 100644 --- a/hw/kdrive/ephyr/ephyrvideo.c +++ b/hw/kdrive/ephyr/ephyrvideo.c @@ -1075,7 +1075,7 @@ ephyrQueryImageAttributes (KdScreenInfo *a_info, EPHYR_LOG_ERROR ("EphyrHostXVQueryImageAttributes() failed\n") ; goto out ; } - EPHYR_LOG ("image size: %d, dim (%dx%d)", image_size, *a_w, *a_h) ; + EPHYR_LOG ("image size: %d, dim (%dx%d)\n", image_size, *a_w, *a_h) ; out: EPHYR_LOG ("leave\n") ; From 0b8545144975bf7ed43c2564d01c697144eb1244 Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Thu, 16 Aug 2007 17:30:13 +0200 Subject: [PATCH 22/44] Implement ReputImage and StopVideo * hw/kdrive/ephyr/ephyrhostvideo.c/h: (ephyrHostXVStopVideo): add this entry point. * hw/kdrive/ephyr/ephyrvideo.c: Basically add ReputImage and StopVideo implementations. Now, when other windows obscur the video window, the reclipping seems to be well handled using StopVideo and ReputImage. To do this, I was obliged to save the frame in PutImage, so that I could resend it un ReputImage. --- hw/kdrive/ephyr/ephyrhostvideo.c | 23 ++++ hw/kdrive/ephyr/ephyrhostvideo.h | 6 + hw/kdrive/ephyr/ephyrvideo.c | 181 ++++++++++++++++++++++++++++++- 3 files changed, 204 insertions(+), 6 deletions(-) diff --git a/hw/kdrive/ephyr/ephyrhostvideo.c b/hw/kdrive/ephyr/ephyrhostvideo.c index 85fc7bd8e..6509274ec 100644 --- a/hw/kdrive/ephyr/ephyrhostvideo.c +++ b/hw/kdrive/ephyr/ephyrhostvideo.c @@ -976,3 +976,26 @@ out: return is_ok ; } +Bool +ephyrHostXVStopVideo (int a_port_id) +{ + int ret=0 ; + Bool is_ok=FALSE ; + Display *dpy = hostx_get_display () ; + + EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; + + EPHYR_LOG ("enter\n") ; + + ret = XvStopVideo (dpy, a_port_id, hostx_get_window ()) ; + if (ret != Success) { + EPHYR_LOG_ERROR ("XvStopVideo() failed: %d \n", ret) ; + goto out ; + } + is_ok = TRUE ; + +out: + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + diff --git a/hw/kdrive/ephyr/ephyrhostvideo.h b/hw/kdrive/ephyr/ephyrhostvideo.h index 661792bab..64b224f1c 100644 --- a/hw/kdrive/ephyr/ephyrhostvideo.h +++ b/hw/kdrive/ephyr/ephyrhostvideo.h @@ -223,5 +223,11 @@ Bool ephyrHostXVPutStill (int a_port_id, Bool ephyrHostXVGetStill (int a_port_id, int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) ; + +/* + * StopVideo + */ +Bool ephyrHostXVStopVideo (int a_port_id) ; + #endif /*__EPHYRHOSTVIDEO_H__*/ diff --git a/hw/kdrive/ephyr/ephyrvideo.c b/hw/kdrive/ephyr/ephyrvideo.c index 3c28f0d38..eea426af3 100644 --- a/hw/kdrive/ephyr/ephyrvideo.c +++ b/hw/kdrive/ephyr/ephyrvideo.c @@ -49,6 +49,12 @@ struct _EphyrPortPriv { int port_number ; KdVideoAdaptorPtr current_adaptor ; EphyrXVPriv *xv_priv; + unsigned char *image_buf ; + int image_buf_size ; + int image_id ; + int drw_x, drw_y, drw_w, drw_h ; + int src_x, src_y, src_w, src_h ; + int image_width, image_height ; }; typedef struct _EphyrPortPriv EphyrPortPriv ; @@ -73,6 +79,16 @@ static Bool ephyrXVPrivIsAttrValueValid (KdAttributePtr a_attrs, int a_attr_value, Bool *a_is_valid) ; +static Bool ephyrXVPrivGetImageBufSize (int a_port_id, + int a_image_id, + unsigned short a_width, + unsigned short a_height, + int *a_size) ; + +static Bool ephyrXVPrivSaveImageToPortPriv (EphyrPortPriv *a_port_priv, + const unsigned char *a_image, + int a_image_len) ; + static void ephyrStopVideo (KdScreenInfo *a_info, pointer a_xv_priv, Bool a_exit); @@ -115,6 +131,13 @@ static int ephyrPutImage (KdScreenInfo *a_info, RegionPtr a_clipping_region, pointer a_port_priv); +static int ephyrReputImage (KdScreenInfo *a_info, + DrawablePtr a_drawable, + short a_drw_x, + short a_drw_y, + RegionPtr a_clipping_region, + pointer a_port_priv) ; + static int ephyrPutVideo (KdScreenInfo *a_info, DrawablePtr a_drawable, short a_vid_x, short a_vid_y, @@ -233,6 +256,8 @@ ephyrLocalAtomToHost (int a_local_atom, int *a_host_atom) return TRUE ; } +/* + Not used yed. static Bool ephyrHostAtomToLocal (int a_host_atom, int *a_local_atom) { @@ -259,6 +284,7 @@ out: } return is_ok ; } +*/ /************** * @@ -553,6 +579,7 @@ ephyrXVPrivSetAdaptorsHooks (EphyrXVPriv *a_this) EPHYR_LOG ("enter\n") ; for (i=0; i < a_this->num_adaptors; i++) { + a_this->adaptors[i].ReputImage = ephyrReputImage ; a_this->adaptors[i].StopVideo = ephyrStopVideo ; a_this->adaptors[i].SetPortAttribute = ephyrSetPortAttribute ; a_this->adaptors[i].GetPortAttribute = ephyrGetPortAttribute ; @@ -569,36 +596,41 @@ ephyrXVPrivSetAdaptorsHooks (EphyrXVPriv *a_this) if (!ephyrHostXVAdaptorHasPutImage (cur_host_adaptor, &has_it)) { EPHYR_LOG_ERROR ("error\n") ; } - if (has_it) + if (has_it) { a_this->adaptors[i].PutImage = ephyrPutImage; + } has_it = FALSE ; if (!ephyrHostXVAdaptorHasPutVideo (cur_host_adaptor, &has_it)) { EPHYR_LOG_ERROR ("error\n") ; } - if (has_it) + if (has_it) { a_this->adaptors[i].PutVideo = ephyrPutVideo; + } has_it = FALSE ; if (!ephyrHostXVAdaptorHasGetVideo (cur_host_adaptor, &has_it)) { EPHYR_LOG_ERROR ("error\n") ; } - if (has_it) + if (has_it) { a_this->adaptors[i].GetVideo = ephyrGetVideo; + } has_it = FALSE ; if (!ephyrHostXVAdaptorHasPutStill (cur_host_adaptor, &has_it)) { EPHYR_LOG_ERROR ("error\n") ; } - if (has_it) + if (has_it) { a_this->adaptors[i].PutStill = ephyrPutStill; + } has_it = FALSE ; if (!ephyrHostXVAdaptorHasGetStill (cur_host_adaptor, &has_it)) { EPHYR_LOG_ERROR ("error\n") ; } - if (has_it) + if (has_it) { a_this->adaptors[i].GetStill = ephyrGetStill; + } } EPHYR_LOG ("leave\n") ; return TRUE ; @@ -679,10 +711,70 @@ ephyrXVPrivIsAttrValueValid (KdAttributePtr a_attrs, return FALSE ; } +static Bool +ephyrXVPrivGetImageBufSize (int a_port_id, + int a_image_id, + unsigned short a_width, + unsigned short a_height, + int *a_size) +{ + Bool is_ok=FALSE ; + unsigned short width=a_width, height=a_height ; + + EPHYR_RETURN_VAL_IF_FAIL (a_size, FALSE) ; + + EPHYR_LOG ("enter\n") ; + + if (!ephyrHostXVQueryImageAttributes (a_port_id, a_image_id, + &width, &height, a_size, NULL, NULL)) { + EPHYR_LOG_ERROR ("failed to get image attributes\n") ; + goto out ; + } + is_ok = TRUE ; + +out: + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +static Bool +ephyrXVPrivSaveImageToPortPriv (EphyrPortPriv *a_port_priv, + const unsigned char *a_image_buf, + int a_image_len) +{ + Bool is_ok=FALSE ; + + EPHYR_LOG ("enter\n") ; + + if (a_port_priv->image_buf_size < a_image_len) { + unsigned char *buf=NULL ; + buf = realloc (a_port_priv->image_buf, a_image_len) ; + if (!buf) { + EPHYR_LOG_ERROR ("failed to realloc image buffer\n") ; + goto out ; + } + a_port_priv->image_buf = buf ; + a_port_priv->image_buf_size = a_image_len; + } + memmove (a_port_priv->image_buf, a_image_buf, a_image_len) ; + is_ok = TRUE ; + +out: + return is_ok ; + EPHYR_LOG ("leave\n") ; +} + static void ephyrStopVideo (KdScreenInfo *a_info, pointer a_port_priv, Bool a_exit) { + EphyrPortPriv *port_priv = a_port_priv ; + + EPHYR_RETURN_IF_FAIL (port_priv) ; + EPHYR_LOG ("enter\n") ; + if (!ephyrHostXVStopVideo (port_priv->port_number)) { + EPHYR_LOG_ERROR ("XvStopVideo() failed\n") ; + } EPHYR_LOG ("leave\n") ; } @@ -832,7 +924,8 @@ ephyrPutImage (KdScreenInfo *a_info, pointer a_port_priv) { EphyrPortPriv *port_priv = a_port_priv ; - int result=BadImplementation ; + Bool is_ok=FALSE ; + int result=BadImplementation, image_size=0 ; EPHYR_RETURN_VAL_IF_FAIL (a_drawable, BadValue) ; @@ -849,6 +942,82 @@ ephyrPutImage (KdScreenInfo *a_info, goto out ; } + /* + * Now save the image so that we can resend it to host it + * later, in ReputImage. + */ + if (!ephyrXVPrivGetImageBufSize (port_priv->port_number, + a_id, a_width, a_height, &image_size)) { + EPHYR_LOG_ERROR ("failed to get image size\n") ; + /*this is a minor error so we won't get bail out abruptly*/ + is_ok = FALSE ; + } else { + is_ok = TRUE ; + } + if (is_ok) { + if (!ephyrXVPrivSaveImageToPortPriv (port_priv, a_buf, image_size)) { + is_ok=FALSE ; + } else { + port_priv->image_id = a_id; + port_priv->drw_x = a_drw_x; + port_priv->drw_y = a_drw_y; + port_priv->drw_w = a_drw_w ; + port_priv->drw_h = a_drw_h ; + port_priv->src_x = a_src_x; + port_priv->src_y = a_src_y ; + port_priv->src_w = a_src_w ; + port_priv->src_h = a_src_h ; + port_priv->image_width = a_width ; + port_priv->image_height = a_height ; + } + } + if (!is_ok) { + if (port_priv->image_buf) { + free (port_priv->image_buf) ; + port_priv->image_buf = NULL ; + port_priv->image_buf_size = 0 ; + } + } + + result = Success ; + +out: + EPHYR_LOG ("leave\n") ; + return result ; +} + +static int +ephyrReputImage (KdScreenInfo *a_info, + DrawablePtr a_drawable, + short a_drw_x, + short a_drw_y, + RegionPtr a_clipping_region, + pointer a_port_priv) +{ + EphyrPortPriv *port_priv = a_port_priv ; + int result=BadImplementation ; + + EPHYR_RETURN_VAL_IF_FAIL (a_drawable && port_priv, BadValue) ; + + EPHYR_LOG ("enter\n") ; + + if (!port_priv->image_buf_size || !port_priv->image_buf) { + EPHYR_LOG_ERROR ("has null image buf in cache\n") ; + goto out ; + } + if (!ephyrHostXVPutImage (port_priv->port_number, port_priv->image_id, + a_drw_x, a_drw_y, + port_priv->drw_w, port_priv->drw_h, + port_priv->src_x, port_priv->src_y, + port_priv->src_w, port_priv->src_h, + port_priv->image_width, port_priv->image_height, + port_priv->image_buf, + (EphyrHostBox*)REGION_RECTS (a_clipping_region), + REGION_NUM_RECTS (a_clipping_region))) { + EPHYR_LOG_ERROR ("ephyrHostXVPutImage() failed\n") ; + goto out ; + } + result = Success ; out: From c06fa924b4781a35b86e4a78d95ff3e9d95b02d1 Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Thu, 23 Aug 2007 11:53:02 +0200 Subject: [PATCH 23/44] XEPHYR: more GLX/DRI proxying work. * hw/kdrive/ephyr/XF86dri.c: re format this correctly. Make function decls honour the Ansi-C standard. * hw/kdrive/ephyr/ephyr.c: protect glx/dri related extension initialisation with the XEPHYR_DRI macro. Initialize the GLX ext hijacking at startup. * hw/kdrive/ephyr/ephyrdri.c: add more logging to ease debugging * hw/kdrive/ephyr/ephyrdriext.c: ditto. reformat. * hw/kdrive/ephyr/ephyrglxext.c,h: add this extension to proxy GLX requests to the host X. started to proxy those nedded to make glxinfo work with fglrx. Not yet finished. * hw/kdrive/ephyr/ephyrhostglx.c,h: put here the actual Xlib code used to hit the host X server because Xlib stuff cannot be mixed with xserver internal code, otherwise compilation erros due to type clashes happen. So no Xlib type should be exported by the entrypoints defined here. --- hw/kdrive/ephyr/Makefile.am | 9 +- hw/kdrive/ephyr/XF86dri.c | 59 +++--- hw/kdrive/ephyr/ephyr.c | 8 + hw/kdrive/ephyr/ephyrdri.c | 18 +- hw/kdrive/ephyr/ephyrdriext.c | 365 ++++++++++++++++++--------------- hw/kdrive/ephyr/ephyrglxext.c | 291 ++++++++++++++++++++++++++ hw/kdrive/ephyr/ephyrglxext.h | 35 ++++ hw/kdrive/ephyr/ephyrhostglx.c | 350 +++++++++++++++++++++++++++++++ hw/kdrive/ephyr/ephyrhostglx.h | 47 +++++ 9 files changed, 974 insertions(+), 208 deletions(-) create mode 100644 hw/kdrive/ephyr/ephyrglxext.c create mode 100644 hw/kdrive/ephyr/ephyrglxext.h create mode 100644 hw/kdrive/ephyr/ephyrhostglx.c create mode 100644 hw/kdrive/ephyr/ephyrhostglx.h diff --git a/hw/kdrive/ephyr/Makefile.am b/hw/kdrive/ephyr/Makefile.am index cc9c9109a..5e3316324 100644 --- a/hw/kdrive/ephyr/Makefile.am +++ b/hw/kdrive/ephyr/Makefile.am @@ -26,12 +26,19 @@ libxephyr_a_SOURCES = \ ephyrdriext.c \ ephyrdri.c \ ephyrdri.h \ + ephyrglxext.c \ + ephyrglxext.h \ + ephyrhostglx.c \ + ephyrhostglx.h \ os.c \ hostx.h \ ephyr.h \ ephyrlog.h -libxephyr_a_CFLAGS = @LIBDRM_CFLAGS@ @DRIPROTO_CFLAGS@ +libxephyr_a_CFLAGS = \ +@LIBDRM_CFLAGS@ \ +-I$(top_srcdir) \ +@DRIPROTO_CFLAGS@ Xephyr_SOURCES = \ ephyrinit.c diff --git a/hw/kdrive/ephyr/XF86dri.c b/hw/kdrive/ephyr/XF86dri.c index bed65e5a4..fc35ce267 100644 --- a/hw/kdrive/ephyr/XF86dri.c +++ b/hw/kdrive/ephyr/XF86dri.c @@ -158,10 +158,8 @@ Bool XF86DRIQueryVersion(dpy, majorVersion, minorVersion, patchVersion) return True; } -Bool XF86DRIQueryDirectRenderingCapable(dpy, screen, isCapable) - Display* dpy; - int screen; - Bool* isCapable; +Bool +XF86DRIQueryDirectRenderingCapable (Display *dpy, int screen, Bool *isCapable) { XExtDisplayInfo *info = find_display (dpy); xXF86DRIQueryDirectRenderingCapableReply rep; @@ -176,10 +174,10 @@ Bool XF86DRIQueryDirectRenderingCapable(dpy, screen, isCapable) req->driReqType = X_XF86DRIQueryDirectRenderingCapable; req->screen = screen; if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { - UnlockDisplay(dpy); - SyncHandle(); + UnlockDisplay(dpy); + SyncHandle(); TRACE("QueryDirectRenderingCapable... return False"); - return False; + return False; } *isCapable = rep.isCapable; UnlockDisplay(dpy); @@ -188,11 +186,10 @@ Bool XF86DRIQueryDirectRenderingCapable(dpy, screen, isCapable) return True; } -Bool XF86DRIOpenConnection(dpy, screen, hSAREA, busIdString) - Display* dpy; - int screen; - drm_handle_t * hSAREA; - char **busIdString; +Bool +XF86DRIOpenConnection (Display *dpy, int screen, + drm_handle_t *hSAREA, + char **busIdString) { XExtDisplayInfo *info = find_display (dpy); xXF86DRIOpenConnectionReply rep; @@ -207,16 +204,16 @@ Bool XF86DRIOpenConnection(dpy, screen, hSAREA, busIdString) req->driReqType = X_XF86DRIOpenConnection; req->screen = screen; if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { - UnlockDisplay(dpy); - SyncHandle(); + UnlockDisplay(dpy); + SyncHandle(); TRACE("OpenConnection... return False"); - return False; + return False; } *hSAREA = rep.hSAREALow; if (sizeof(drm_handle_t) == 8) { - int shift = 32; /* var to prevent warning on next line */ - *hSAREA |= ((drm_handle_t) rep.hSAREAHigh) << shift; + int shift = 32; /* var to prevent warning on next line */ + *hSAREA |= ((drm_handle_t) rep.hSAREAHigh) << shift; } if (rep.length) { @@ -227,7 +224,7 @@ Bool XF86DRIOpenConnection(dpy, screen, hSAREA, busIdString) TRACE("OpenConnection... return False"); return False; } - _XReadPad(dpy, *busIdString, rep.busIdStringLength); + _XReadPad(dpy, *busIdString, rep.busIdStringLength); } else { *busIdString = NULL; } @@ -546,16 +543,10 @@ Bool XF86DRIGetDrawableInfo(Display* dpy, int screen, Drawable drawable, return True; } -Bool XF86DRIGetDeviceInfo(dpy, screen, hFrameBuffer, - fbOrigin, fbSize, fbStride, devPrivateSize, pDevPrivate) - Display* dpy; - int screen; - drm_handle_t * hFrameBuffer; - int* fbOrigin; - int* fbSize; - int* fbStride; - int* devPrivateSize; - void** pDevPrivate; +Bool +XF86DRIGetDeviceInfo (Display *dpy, int screen, drm_handle_t *hFrameBuffer, + int *fbOrigin, int *fbSize, int *fbStride, + int *devPrivateSize, void **pDevPrivate) { XExtDisplayInfo *info = find_display (dpy); xXF86DRIGetDeviceInfoReply rep; @@ -606,10 +597,8 @@ Bool XF86DRIGetDeviceInfo(dpy, screen, hFrameBuffer, return True; } -Bool XF86DRIOpenFullScreen(dpy, screen, drawable) - Display* dpy; - int screen; - Drawable drawable; +Bool +XF86DRIOpenFullScreen(Display *dpy, int screen, Drawable drawable) { /* This function and the underlying X protocol are deprecated. */ @@ -619,10 +608,8 @@ Bool XF86DRIOpenFullScreen(dpy, screen, drawable) return False; } -Bool XF86DRICloseFullScreen(dpy, screen, drawable) - Display* dpy; - int screen; - Drawable drawable; +Bool +XF86DRICloseFullScreen(Display *dpy, int screen, Drawable drawable) { /* This function and the underlying X protocol are deprecated. */ diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c index 330158a7d..b460b9630 100644 --- a/hw/kdrive/ephyr/ephyr.c +++ b/hw/kdrive/ephyr/ephyr.c @@ -31,6 +31,8 @@ #include "inputstr.h" #include "scrnintstr.h" #include "ephyrlog.h" +#include "ephyrdri.h" +#include "ephyrglxext.h" extern int KdTsPhyScreen; KdKeyboardInfo *ephyrKbd; @@ -45,6 +47,11 @@ typedef struct _EphyrInputPrivate { Bool EphyrWantGrayScale = 0; + +#ifdef XEPHYR_DRI +extern void ephyrDRIExtensionInit(void) ; +#endif + Bool ephyrInitialize (KdCardInfo *card, EphyrPriv *priv) { @@ -617,6 +624,7 @@ ephyrInitScreen (ScreenPtr pScreen) #ifdef XEPHYR_DRI ephyrDRIExtensionInit () ; + ephyrHijackGLXExtension () ; #endif return TRUE; } diff --git a/hw/kdrive/ephyr/ephyrdri.c b/hw/kdrive/ephyr/ephyrdri.c index 5201082d8..89d9ae7b5 100644 --- a/hw/kdrive/ephyr/ephyrdri.c +++ b/hw/kdrive/ephyr/ephyrdri.c @@ -159,16 +159,18 @@ ephyrDRICreateDrawable (int a_screen, drm_drawable_t *a_hw_drawable) { EPHYR_LOG ("enter\n") ; - return FALSE ; + EPHYR_LOG_ERROR ("not implemented yet\n") ; EPHYR_LOG ("leave\n") ; + return FALSE ; } Bool ephyrDRIDestroyDrawable (int a_screen, int a_drawable) { EPHYR_LOG ("enter\n") ; - return FALSE ; + EPHYR_LOG_ERROR ("not implemented yet\n") ; EPHYR_LOG ("leave\n") ; + return FALSE ; } Bool @@ -188,8 +190,9 @@ ephyrDRIGetDrawableInfo (int a_screen, drm_clip_rect_t **a_back_clip_rects) { EPHYR_LOG ("enter\n") ; - return FALSE ; + EPHYR_LOG_ERROR ("not implemented yet\n") ; EPHYR_LOG ("leave\n") ; + return FALSE ; } Bool @@ -201,9 +204,16 @@ ephyrDRIGetDeviceInfo (int a_screen, int *a_dev_private_size, void **a_dev_private) { + Bool is_ok = FALSE ; + Display *dpy = hostx_get_display () ; + + EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; EPHYR_LOG ("enter\n") ; - return FALSE ; + is_ok = XF86DRIGetDeviceInfo (dpy, a_screen, a_frame_buffer, + a_fb_origin, a_fb_size, a_fb_stride, + a_dev_private_size, a_dev_private) ; EPHYR_LOG ("leave\n") ; + return is_ok ; } #endif /*EPHYR_DRI*/ diff --git a/hw/kdrive/ephyr/ephyrdriext.c b/hw/kdrive/ephyr/ephyrdriext.c index 437d8c4da..ac68054a3 100644 --- a/hw/kdrive/ephyr/ephyrdriext.c +++ b/hw/kdrive/ephyr/ephyrdriext.c @@ -79,7 +79,7 @@ static void XF86DRIResetProc(ExtensionEntry* extEntry); static unsigned char DRIReqCode = 0; -extern void XFree86DRIExtensionInit(void); +extern void ephyrDRIExtensionInit(void); void ephyrDRIExtensionInit(void) @@ -113,13 +113,13 @@ XF86DRIResetProc ( } static int -ProcXF86DRIQueryVersion( - register ClientPtr client -) +ProcXF86DRIQueryVersion (register ClientPtr client) { xXF86DRIQueryVersionReply rep; register int n; + EPHYR_LOG ("enter\n") ; + REQUEST_SIZE_MATCH(xXF86DRIQueryVersionReq); rep.type = X_Reply; rep.length = 0; @@ -135,18 +135,18 @@ ProcXF86DRIQueryVersion( swapl(&rep.patchVersion, n); } WriteToClient(client, sizeof(xXF86DRIQueryVersionReply), (char *)&rep); + EPHYR_LOG ("leave\n") ; return (client->noClientException); } static int -ProcXF86DRIQueryDirectRenderingCapable( - register ClientPtr client -) +ProcXF86DRIQueryDirectRenderingCapable (register ClientPtr client) { xXF86DRIQueryDirectRenderingCapableReply rep; Bool isCapable; register int n; + EPHYR_LOG ("enter\n") ; REQUEST(xXF86DRIQueryDirectRenderingCapableReq); REQUEST_SIZE_MATCH(xXF86DRIQueryDirectRenderingCapableReq); if (stuff->screen >= screenInfo.numScreens) { @@ -171,20 +171,20 @@ ProcXF86DRIQueryDirectRenderingCapable( swapl(&rep.length, n); } - WriteToClient(client, - sizeof(xXF86DRIQueryDirectRenderingCapableReply), (char *)&rep); + WriteToClient(client, sizeof(xXF86DRIQueryDirectRenderingCapableReply), (char *)&rep); + EPHYR_LOG ("leave\n") ; + return (client->noClientException); } static int -ProcXF86DRIOpenConnection( - register ClientPtr client -) +ProcXF86DRIOpenConnection (register ClientPtr client) { xXF86DRIOpenConnectionReply rep; drm_handle_t hSAREA; char* busIdString; + EPHYR_LOG ("enter\n") ; REQUEST(xXF86DRIOpenConnectionReq); REQUEST_SIZE_MATCH(xXF86DRIOpenConnectionReq); if (stuff->screen >= screenInfo.numScreens) { @@ -215,17 +215,17 @@ ProcXF86DRIOpenConnection( WriteToClient(client, sizeof(xXF86DRIOpenConnectionReply), (char *)&rep); if (rep.busIdStringLength) - WriteToClient(client, rep.busIdStringLength, busIdString); + WriteToClient(client, rep.busIdStringLength, busIdString); + EPHYR_LOG ("leave\n") ; return (client->noClientException); } static int -ProcXF86DRIAuthConnection( - register ClientPtr client -) +ProcXF86DRIAuthConnection (register ClientPtr client) { xXF86DRIAuthConnectionReply rep; - + + EPHYR_LOG ("enter\n") ; REQUEST(xXF86DRIAuthConnectionReq); REQUEST_SIZE_MATCH(xXF86DRIAuthConnectionReq); if (stuff->screen >= screenInfo.numScreens) { @@ -243,36 +243,36 @@ ProcXF86DRIAuthConnection( rep.authenticated = 0; } WriteToClient(client, sizeof(xXF86DRIAuthConnectionReply), (char *)&rep); + EPHYR_LOG ("leave\n") ; return (client->noClientException); } static int -ProcXF86DRICloseConnection( - register ClientPtr client -) +ProcXF86DRICloseConnection (register ClientPtr client) { + EPHYR_LOG ("enter\n") ; REQUEST(xXF86DRICloseConnectionReq); REQUEST_SIZE_MATCH(xXF86DRICloseConnectionReq); if (stuff->screen >= screenInfo.numScreens) { - client->errorValue = stuff->screen; - return BadValue; + client->errorValue = stuff->screen; + return BadValue; } /* DRICloseConnection( screenInfo.screens[stuff->screen]); */ + EPHYR_LOG ("leave\n") ; return (client->noClientException); } static int -ProcXF86DRIGetClientDriverName( - register ClientPtr client -) +ProcXF86DRIGetClientDriverName (register ClientPtr client) { xXF86DRIGetClientDriverNameReply rep; char* clientDriverName; + EPHYR_LOG ("enter\n") ; REQUEST(xXF86DRIGetClientDriverNameReq); REQUEST_SIZE_MATCH(xXF86DRIGetClientDriverNameReq); if (stuff->screen >= screenInfo.numScreens) { @@ -301,19 +301,19 @@ ProcXF86DRIGetClientDriverName( WriteToClient(client, rep.clientDriverNameLength, clientDriverName); + EPHYR_LOG ("leave\n") ; return (client->noClientException); } static int -ProcXF86DRICreateContext( - register ClientPtr client -) +ProcXF86DRICreateContext (register ClientPtr client) { xXF86DRICreateContextReply rep; ScreenPtr pScreen; VisualPtr visual; int i; + EPHYR_LOG ("enter\n") ; REQUEST(xXF86DRICreateContextReq); REQUEST_SIZE_MATCH(xXF86DRICreateContextReq); if (stuff->screen >= screenInfo.numScreens) { @@ -347,101 +347,104 @@ ProcXF86DRICreateContext( */ WriteToClient(client, sizeof(xXF86DRICreateContextReply), (char *)&rep); + EPHYR_LOG ("leave\n") ; return (client->noClientException); } static int -ProcXF86DRIDestroyContext( - register ClientPtr client -) +ProcXF86DRIDestroyContext (register ClientPtr client) { + EPHYR_LOG ("enter\n") ; + REQUEST(xXF86DRIDestroyContextReq); REQUEST_SIZE_MATCH(xXF86DRIDestroyContextReq); if (stuff->screen >= screenInfo.numScreens) { - client->errorValue = stuff->screen; - return BadValue; + client->errorValue = stuff->screen; + return BadValue; } /* - if (!DRIDestroyContext( screenInfo.screens[stuff->screen], - stuff->context)) { - return BadValue; - } - */ + if (!DRIDestroyContext( screenInfo.screens[stuff->screen], + stuff->context)) { + return BadValue; + } + */ + EPHYR_LOG ("leave\n") ; return (client->noClientException); } static int -ProcXF86DRICreateDrawable( - ClientPtr client -) +ProcXF86DRICreateDrawable (ClientPtr client) { xXF86DRICreateDrawableReply rep; DrawablePtr pDrawable; int rc; + EPHYR_LOG ("enter\n") ; REQUEST(xXF86DRICreateDrawableReq); REQUEST_SIZE_MATCH(xXF86DRICreateDrawableReq); if (stuff->screen >= screenInfo.numScreens) { - client->errorValue = stuff->screen; - return BadValue; + client->errorValue = stuff->screen; + return BadValue; } rep.type = X_Reply; rep.length = 0; rep.sequenceNumber = client->sequence; - rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, - DixReadAccess); + rc = dixLookupDrawable (&pDrawable, stuff->drawable, client, 0, + DixReadAccess); if (rc != Success) - return rc; + return rc; /*TODO: this cannot work. We must properly * do the mapping between the xephyr drawable and * the host drawable */ if (!ephyrDRICreateDrawable (stuff->screen, - 0/*should be host drawableID*/, - (drm_drawable_t *)&rep.hHWDrawable)) { + 0/*should be host drawableID*/, + (drm_drawable_t *)&rep.hHWDrawable)) { return BadValue; } WriteToClient(client, sizeof(xXF86DRICreateDrawableReply), (char *)&rep); + EPHYR_LOG ("leave\n") ; return (client->noClientException); } static int -ProcXF86DRIDestroyDrawable( - register ClientPtr client -) +ProcXF86DRIDestroyDrawable (register ClientPtr client) { REQUEST(xXF86DRIDestroyDrawableReq); DrawablePtr pDrawable; REQUEST_SIZE_MATCH(xXF86DRIDestroyDrawableReq); int rc; + EPHYR_LOG ("enter\n") ; if (stuff->screen >= screenInfo.numScreens) { - client->errorValue = stuff->screen; - return BadValue; + client->errorValue = stuff->screen; + return BadValue; } - rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, - DixReadAccess); + rc = dixLookupDrawable(&pDrawable, + stuff->drawable, + client, + 0, + DixReadAccess); if (rc != Success) - return rc; + return rc; if (!ephyrDRIDestroyDrawable(stuff->screen, 0/*should be drawable in host x*/)) { - return BadValue; + return BadValue; } + EPHYR_LOG ("leave\n") ; return (client->noClientException); } static int -ProcXF86DRIGetDrawableInfo( - register ClientPtr client -) +ProcXF86DRIGetDrawableInfo (register ClientPtr client) { xXF86DRIGetDrawableInfoReply rep; DrawablePtr pDrawable; @@ -450,11 +453,12 @@ ProcXF86DRIGetDrawableInfo( drm_clip_rect_t * pBackClipRects; int backX, backY, rc; + EPHYR_LOG ("enter\n") ; REQUEST(xXF86DRIGetDrawableInfoReq); REQUEST_SIZE_MATCH(xXF86DRIGetDrawableInfoReq); if (stuff->screen >= screenInfo.numScreens) { - client->errorValue = stuff->screen; - return BadValue; + client->errorValue = stuff->screen; + return BadValue; } rep.type = X_Reply; @@ -466,25 +470,25 @@ ProcXF86DRIGetDrawableInfo( * between xephyr drawable and the host drawable */ rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, - DixReadAccess); + DixReadAccess); if (rc != Success) - return rc; + return rc; if (!ephyrDRIGetDrawableInfo (stuff->screen, - 0 /*should be the drawable in hostx*/, - (unsigned int*)&rep.drawableTableIndex, - (unsigned int*)&rep.drawableTableStamp, - (int*)&X, - (int*)&Y, - (int*)&W, - (int*)&H, - (int*)&rep.numClipRects, - &pClipRects, - &backX, - &backY, - (int*)&rep.numBackClipRects, - &pBackClipRects)) { - return BadValue; + 0 /*should be the drawable in hostx*/, + (unsigned int*)&rep.drawableTableIndex, + (unsigned int*)&rep.drawableTableStamp, + (int*)&X, + (int*)&Y, + (int*)&W, + (int*)&H, + (int*)&rep.numClipRects, + &pClipRects, + &backX, + &backY, + (int*)&rep.numBackClipRects, + &pBackClipRects)) { + return BadValue; } rep.drawableX = X; @@ -492,78 +496,78 @@ ProcXF86DRIGetDrawableInfo( rep.drawableWidth = W; rep.drawableHeight = H; rep.length = (SIZEOF(xXF86DRIGetDrawableInfoReply) - - SIZEOF(xGenericReply)); + SIZEOF(xGenericReply)); rep.backX = backX; rep.backY = backY; - + if (rep.numBackClipRects) - rep.length += sizeof(drm_clip_rect_t) * rep.numBackClipRects; + rep.length += sizeof(drm_clip_rect_t) * rep.numBackClipRects; pClippedRects = pClipRects; if (rep.numClipRects) { - /* Clip cliprects to screen dimensions (redirected windows) */ - pClippedRects = xalloc(rep.numClipRects * sizeof(drm_clip_rect_t)); + /* Clip cliprects to screen dimensions (redirected windows) */ + pClippedRects = xalloc(rep.numClipRects * sizeof(drm_clip_rect_t)); - if (pClippedRects) { - ScreenPtr pScreen = screenInfo.screens[stuff->screen]; - int i, j; + if (pClippedRects) { + ScreenPtr pScreen = screenInfo.screens[stuff->screen]; + int i, j; - for (i = 0, j = 0; i < rep.numClipRects; i++) { - pClippedRects[j].x1 = max(pClipRects[i].x1, 0); - pClippedRects[j].y1 = max(pClipRects[i].y1, 0); - pClippedRects[j].x2 = min(pClipRects[i].x2, pScreen->width); - pClippedRects[j].y2 = min(pClipRects[i].y2, pScreen->height); + for (i = 0, j = 0; i < rep.numClipRects; i++) { + pClippedRects[j].x1 = max(pClipRects[i].x1, 0); + pClippedRects[j].y1 = max(pClipRects[i].y1, 0); + pClippedRects[j].x2 = min(pClipRects[i].x2, pScreen->width); + pClippedRects[j].y2 = min(pClipRects[i].y2, pScreen->height); - if (pClippedRects[j].x1 < pClippedRects[j].x2 && - pClippedRects[j].y1 < pClippedRects[j].y2) { - j++; - } - } + if (pClippedRects[j].x1 < pClippedRects[j].x2 && + pClippedRects[j].y1 < pClippedRects[j].y2) { + j++; + } + } - rep.numClipRects = j; - } else { - rep.numClipRects = 0; - } + rep.numClipRects = j; + } else { + rep.numClipRects = 0; + } - rep.length += sizeof(drm_clip_rect_t) * rep.numClipRects; + rep.length += sizeof(drm_clip_rect_t) * rep.numClipRects; } - + rep.length = ((rep.length + 3) & ~3) >> 2; WriteToClient(client, sizeof(xXF86DRIGetDrawableInfoReply), (char *)&rep); if (rep.numClipRects) { - WriteToClient(client, - sizeof(drm_clip_rect_t) * rep.numClipRects, - (char *)pClippedRects); - xfree(pClippedRects); + WriteToClient(client, + sizeof(drm_clip_rect_t) * rep.numClipRects, + (char *)pClippedRects); + xfree(pClippedRects); } if (rep.numBackClipRects) { - WriteToClient(client, - sizeof(drm_clip_rect_t) * rep.numBackClipRects, - (char *)pBackClipRects); + WriteToClient(client, + sizeof(drm_clip_rect_t) * rep.numBackClipRects, + (char *)pBackClipRects); } + EPHYR_LOG ("leave\n") ; return (client->noClientException); } static int -ProcXF86DRIGetDeviceInfo( - register ClientPtr client -) +ProcXF86DRIGetDeviceInfo (register ClientPtr client) { xXF86DRIGetDeviceInfoReply rep; drm_handle_t hFrameBuffer; void *pDevPrivate; + EPHYR_LOG ("enter\n") ; REQUEST(xXF86DRIGetDeviceInfoReq); REQUEST_SIZE_MATCH(xXF86DRIGetDeviceInfoReq); if (stuff->screen >= screenInfo.numScreens) { - client->errorValue = stuff->screen; - return BadValue; + client->errorValue = stuff->screen; + return BadValue; } rep.type = X_Reply; @@ -571,12 +575,12 @@ ProcXF86DRIGetDeviceInfo( rep.sequenceNumber = client->sequence; if (!ephyrDRIGetDeviceInfo (stuff->screen, - &hFrameBuffer, - (int*)&rep.framebufferOrigin, - (int*)&rep.framebufferSize, - (int*)&rep.framebufferStride, - (int*)&rep.devPrivateSize, - &pDevPrivate)) { + &hFrameBuffer, + (int*)&rep.framebufferOrigin, + (int*)&rep.framebufferSize, + (int*)&rep.framebufferStride, + (int*)&rep.devPrivateSize, + &pDevPrivate)) { return BadValue; } @@ -590,30 +594,34 @@ ProcXF86DRIGetDeviceInfo( rep.length = 0; if (rep.devPrivateSize) { rep.length = (SIZEOF(xXF86DRIGetDeviceInfoReply) - - SIZEOF(xGenericReply) + - ((rep.devPrivateSize + 3) & ~3)) >> 2; + SIZEOF(xGenericReply) + + ((rep.devPrivateSize + 3) & ~3)) >> 2; } WriteToClient(client, sizeof(xXF86DRIGetDeviceInfoReply), (char *)&rep); if (rep.length) { WriteToClient(client, rep.devPrivateSize, (char *)pDevPrivate); } + EPHYR_LOG ("leave\n") ; return (client->noClientException); } static int -ProcXF86DRIDispatch ( - register ClientPtr client -) +ProcXF86DRIDispatch (register ClientPtr client) { REQUEST(xReq); + EPHYR_LOG ("enter\n") ; switch (stuff->data) { - case X_XF86DRIQueryVersion: - return ProcXF86DRIQueryVersion(client); - case X_XF86DRIQueryDirectRenderingCapable: - return ProcXF86DRIQueryDirectRenderingCapable(client); + case X_XF86DRIQueryVersion: { + EPHYR_LOG ("leave\n") ; + return ProcXF86DRIQueryVersion(client); + } + case X_XF86DRIQueryDirectRenderingCapable: { + EPHYR_LOG ("leave\n") ; + return ProcXF86DRIQueryDirectRenderingCapable(client); + } } if (!LocalClient(client)) @@ -621,36 +629,56 @@ ProcXF86DRIDispatch ( switch (stuff->data) { - case X_XF86DRIOpenConnection: - return ProcXF86DRIOpenConnection(client); - case X_XF86DRICloseConnection: - return ProcXF86DRICloseConnection(client); - case X_XF86DRIGetClientDriverName: - return ProcXF86DRIGetClientDriverName(client); - case X_XF86DRICreateContext: - return ProcXF86DRICreateContext(client); - case X_XF86DRIDestroyContext: - return ProcXF86DRIDestroyContext(client); - case X_XF86DRICreateDrawable: - return ProcXF86DRICreateDrawable(client); - case X_XF86DRIDestroyDrawable: - return ProcXF86DRIDestroyDrawable(client); - case X_XF86DRIGetDrawableInfo: - return ProcXF86DRIGetDrawableInfo(client); - case X_XF86DRIGetDeviceInfo: - return ProcXF86DRIGetDeviceInfo(client); - case X_XF86DRIAuthConnection: - return ProcXF86DRIAuthConnection(client); - /* {Open,Close}FullScreen are deprecated now */ - default: - return BadRequest; + case X_XF86DRIOpenConnection: { + EPHYR_LOG ("leave\n") ; + return ProcXF86DRIOpenConnection(client); + } + case X_XF86DRICloseConnection: { + EPHYR_LOG ("leave\n") ; + return ProcXF86DRICloseConnection(client); + } + case X_XF86DRIGetClientDriverName: { + EPHYR_LOG ("leave\n") ; + return ProcXF86DRIGetClientDriverName(client); + } + case X_XF86DRICreateContext: { + EPHYR_LOG ("leave\n") ; + return ProcXF86DRICreateContext(client); + } + case X_XF86DRIDestroyContext: { + EPHYR_LOG ("leave\n") ; + return ProcXF86DRIDestroyContext(client); + } + case X_XF86DRICreateDrawable: { + EPHYR_LOG ("leave\n") ; + return ProcXF86DRICreateDrawable(client); + } + case X_XF86DRIDestroyDrawable: { + EPHYR_LOG ("leave\n") ; + return ProcXF86DRIDestroyDrawable(client); + } + case X_XF86DRIGetDrawableInfo: { + EPHYR_LOG ("leave\n") ; + return ProcXF86DRIGetDrawableInfo(client); + } + case X_XF86DRIGetDeviceInfo: { + EPHYR_LOG ("leave\n") ; + return ProcXF86DRIGetDeviceInfo(client); + } + case X_XF86DRIAuthConnection: { + EPHYR_LOG ("leave\n") ; + return ProcXF86DRIAuthConnection(client); + } + /* {Open,Close}FullScreen are deprecated now */ + default: { + EPHYR_LOG ("leave\n") ; + return BadRequest; + } } } static int -SProcXF86DRIQueryVersion( - register ClientPtr client -) +SProcXF86DRIQueryVersion (register ClientPtr client) { register int n; REQUEST(xXF86DRIQueryVersionReq); @@ -659,9 +687,7 @@ SProcXF86DRIQueryVersion( } static int -SProcXF86DRIQueryDirectRenderingCapable( - register ClientPtr client -) +SProcXF86DRIQueryDirectRenderingCapable (register ClientPtr client) { register int n; REQUEST(xXF86DRIQueryDirectRenderingCapableReq); @@ -671,24 +697,29 @@ SProcXF86DRIQueryDirectRenderingCapable( } static int -SProcXF86DRIDispatch ( - register ClientPtr client -) +SProcXF86DRIDispatch (register ClientPtr client) { REQUEST(xReq); + EPHYR_LOG ("enter\n") ; /* * Only local clients are allowed DRI access, but remote clients still need * these requests to find out cleanly. */ switch (stuff->data) { - case X_XF86DRIQueryVersion: - return SProcXF86DRIQueryVersion(client); - case X_XF86DRIQueryDirectRenderingCapable: - return SProcXF86DRIQueryDirectRenderingCapable(client); - default: - return DRIErrorBase + XF86DRIClientNotLocal; + case X_XF86DRIQueryVersion: { + EPHYR_LOG ("leave\n") ; + return SProcXF86DRIQueryVersion(client); + } + case X_XF86DRIQueryDirectRenderingCapable: { + EPHYR_LOG ("leave\n") ; + return SProcXF86DRIQueryDirectRenderingCapable(client); + } + default: { + EPHYR_LOG ("leave\n") ; + return DRIErrorBase + XF86DRIClientNotLocal; + } } } diff --git a/hw/kdrive/ephyr/ephyrglxext.c b/hw/kdrive/ephyr/ephyrglxext.c new file mode 100644 index 000000000..d0380f105 --- /dev/null +++ b/hw/kdrive/ephyr/ephyrglxext.c @@ -0,0 +1,291 @@ +/* + * Xephyr - A kdrive X server thats runs in a host X window. + * Authored by Matthew Allum + * + * Copyright © 2007 OpenedHand Ltd + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of OpenedHand Ltd not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OpenedHand Ltd makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OpenedHand Ltd BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Authors: + * Dodji Seketeli + */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "extnsionst.h" +#include "ephyrglxext.h" +#include "ephyrhostglx.h" +#define _HAVE_XALLOC_DECLS +#include "ephyrlog.h" +#include +#include "GL/glx/glxserver.h" +#include "GL/glx/indirect_table.h" +#include "GL/glx/unpack.h" + + +#ifdef XEPHYR_DRI + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + + +int ephyrGLXQueryVersion (__GLXclientState *cl, GLbyte *pc) ; +int ephyrGLXQueryVersionSwap (__GLXclientState *cl, GLbyte *pc) ; +int ephyrGLXGetVisualConfigs (__GLXclientState *cl, GLbyte *pc) ; +int ephyrGLXGetVisualConfigsSwap (__GLXclientState *cl, GLbyte *pc) ; +int ephyrGLXClientInfo(__GLXclientState *cl, GLbyte *pc) ; +int ephyrGLXClientInfoSwap(__GLXclientState *cl, GLbyte *pc) ; +int ephyrGLXQueryServerString(__GLXclientState *a_cl, GLbyte *a_pc) ; +int ephyrGLXQueryServerStringSwap(__GLXclientState *a_cl, GLbyte *a_pc) ; + +Bool +ephyrHijackGLXExtension (void) +{ + const void *(*dispatch_functions)[2]; + + EPHYR_LOG ("Got GLX extension\n") ; + if (!Single_dispatch_info.dispatch_functions) { + EPHYR_LOG_ERROR ("could not get dispatch functions table\n") ; + return FALSE ; + } + dispatch_functions = Single_dispatch_info.dispatch_functions ; + EPHYR_RETURN_VAL_IF_FAIL (dispatch_functions, FALSE) ; + + dispatch_functions[X_GLXQueryVersion][0] = ephyrGLXQueryVersion ; + dispatch_functions[X_GLXQueryVersion][1] = ephyrGLXQueryVersionSwap ; + + dispatch_functions[X_GLXGetVisualConfigs][0] = ephyrGLXGetVisualConfigs ; + dispatch_functions[X_GLXGetVisualConfigs][1] = ephyrGLXGetVisualConfigsSwap ; + + dispatch_functions[X_GLXClientInfo][0] = ephyrGLXClientInfo ; + dispatch_functions[X_GLXClientInfo][1] = ephyrGLXClientInfoSwap ; + + dispatch_functions[X_GLXQueryServerString][0] = ephyrGLXQueryServerString ; + dispatch_functions[X_GLXQueryServerString][1] = ephyrGLXQueryServerStringSwap ; + + EPHYR_LOG ("hijacked mesa GL to forward requests to host X\n") ; + + return TRUE ; +} + +/********************* + * implementation of + * hijacked GLX entry + * points + ********************/ + +int +ephyrGLXQueryVersion(__GLXclientState *a_cl, GLbyte *a_pc) +{ + ClientPtr client = a_cl->client; + xGLXQueryVersionReq *req = (xGLXQueryVersionReq *) a_pc; + xGLXQueryVersionReply reply; + int major, minor; + int res = BadImplementation ; + + EPHYR_LOG ("enter\n") ; + + major = req->majorVersion ; + minor = req->minorVersion ; + + if (!ephyrHostGLXQueryVersion (&major, &minor)) { + EPHYR_LOG_ERROR ("ephyrHostGLXQueryVersion() failed\n") ; + goto out ; + } + reply.majorVersion = major ; + reply.minorVersion = minor ; + reply.length = 0 ; + reply.type = X_Reply ; + reply.sequenceNumber = client->sequence ; + + if (client->swapped) { + __glXSwapQueryVersionReply(client, &reply); + } else { + WriteToClient(client, sz_xGLXQueryVersionReply, (char *)&reply); + } + + res = Success ; +out: + EPHYR_LOG ("leave\n") ; + return res; +} + +int +ephyrGLXQueryVersionSwap (__GLXclientState *a_cl, GLbyte *a_pc) +{ + xGLXQueryVersionReq *req = (xGLXQueryVersionReq *) a_pc; + __GLX_DECLARE_SWAP_VARIABLES; + + __GLX_SWAP_SHORT (&req->length); + __GLX_SWAP_INT (&req->majorVersion); + __GLX_SWAP_INT (&req->minorVersion); + return ephyrGLXQueryVersion (a_cl, a_pc) ; +} + +static int +ephyrGLXGetVisualConfigsReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap) +{ + xGLXGetVisualConfigsReq *req = (xGLXGetVisualConfigsReq *) a_pc; + ClientPtr client = a_cl->client; + xGLXGetVisualConfigsReply reply; + int32_t *props_buf=NULL, num_visuals=0, + num_props=0, res=BadImplementation, i=0, + props_per_visual_size=0, + props_buf_size=0; + __GLX_DECLARE_SWAP_VARIABLES; + __GLX_DECLARE_SWAP_ARRAY_VARIABLES; + + EPHYR_LOG ("enter\n") ; + + if (!ephyrHostGLXGetVisualConfigs (req->screen, + &num_visuals, + &num_props, + &props_buf_size, + &props_buf)) { + EPHYR_LOG_ERROR ("ephyrHostGLXGetVisualConfigs() failed\n") ; + goto out ; + } + EPHYR_LOG ("num_visuals:%d, num_props:%d\n", num_visuals, num_props) ; + + reply.numVisuals = num_visuals; + reply.numProps = num_props; + reply.length = (num_visuals *__GLX_SIZE_CARD32 * num_props) >> 2; + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + + if (a_do_swap) { + __GLX_SWAP_SHORT(&reply.sequenceNumber); + __GLX_SWAP_INT(&reply.length); + __GLX_SWAP_INT(&reply.numVisuals); + __GLX_SWAP_INT(&reply.numProps); + __GLX_SWAP_INT_ARRAY (props_buf, num_props) ; + } + WriteToClient(client, sz_xGLXGetVisualConfigsReply, (char*)&reply); + props_per_visual_size = props_buf_size/num_visuals ; + for (i=0; i < num_visuals; i++) { + WriteToClient (client, + props_per_visual_size, + (char*)props_buf +i*props_per_visual_size); + } + res = Success ; + +out: + EPHYR_LOG ("leave\n") ; + if (props_buf) { + xfree (props_buf) ; + props_buf = NULL ; + } + return res ; +} + +int +ephyrGLXGetVisualConfigs (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXGetVisualConfigsReal (a_cl, a_pc, FALSE) ; +} + +int +ephyrGLXGetVisualConfigsSwap (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXGetVisualConfigsReal (a_cl, a_pc, TRUE) ; +} + + +int +ephyrGLXClientInfo(__GLXclientState *a_cl, GLbyte *a_pc) +{ + int res=BadImplementation ; + xGLXClientInfoReq *req = (xGLXClientInfoReq *) a_pc; + + EPHYR_LOG ("enter\n") ; + if (!ephyrHostGLXSendClientInfo (req->major, req->minor, (char*)req+1)) { + EPHYR_LOG_ERROR ("failed to send client info to host\n") ; + goto out ; + } + res = Success ; + +out: + EPHYR_LOG ("leave\n") ; + return res ; +} + +int +ephyrGLXClientInfoSwap (__GLXclientState *a_cl, GLbyte *a_pc) +{ + xGLXClientInfoReq *req = (xGLXClientInfoReq *)a_pc; + __GLX_DECLARE_SWAP_VARIABLES; + + __GLX_SWAP_SHORT (&req->length); + __GLX_SWAP_INT (&req->major); + __GLX_SWAP_INT (&req->minor); + __GLX_SWAP_INT (&req->numbytes); + + return ephyrGLXClientInfo (a_cl, a_pc) ; +} + +int +ephyrGLXQueryServerString(__GLXclientState *a_cl, GLbyte *a_pc) +{ + int res = BadImplementation ; + ClientPtr client = a_cl->client; + xGLXQueryServerStringReq *req = (xGLXQueryServerStringReq *) a_pc; + xGLXQueryServerStringReply reply; + char *server_string=NULL ; + int length=0 ; + + EPHYR_LOG ("enter\n") ; + if (!ephyrHostGLXGetStringFromServer (req->screen, req->name, &server_string)) { + EPHYR_LOG_ERROR ("failed to query string from host\n") ; + goto out ; + } + length= strlen (server_string) + 1; + reply.type = X_Reply ; + reply.sequenceNumber = client->sequence ; + reply.length = __GLX_PAD (length) >> 2 ; + reply.n = length ; + + WriteToClient(client, sz_xGLXQueryServerStringReply, (char*)&reply); + WriteToClient(client, (int)length, server_string); + + res = Success ; + +out: + EPHYR_LOG ("leave\n") ; + if (server_string) { + xfree (server_string) ; + server_string = NULL; + } + return res ; +} + +int +ephyrGLXQueryServerStringSwap(__GLXclientState *a_cl, GLbyte *a_pc) +{ + EPHYR_LOG_ERROR ("not yet implemented\n") ; + return BadImplementation ; +} + +#endif /*XEPHYR_DRI*/ + diff --git a/hw/kdrive/ephyr/ephyrglxext.h b/hw/kdrive/ephyr/ephyrglxext.h new file mode 100644 index 000000000..22ea605d7 --- /dev/null +++ b/hw/kdrive/ephyr/ephyrglxext.h @@ -0,0 +1,35 @@ +/* + * Xephyr - A kdrive X server thats runs in a host X window. + * Authored by Matthew Allum + * + * Copyright © 2007 OpenedHand Ltd + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of OpenedHand Ltd not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OpenedHand Ltd makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OpenedHand Ltd BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Authors: + * Dodji Seketeli + */ +#ifndef __EPHYR_GLXEXT_H__ +#define __EPHYR_GLXEXT_H__ + +#include +Bool ephyrHijackGLXExtension (void) ; + +#endif /*__EPHYR_GLXEXT_H__*/ + diff --git a/hw/kdrive/ephyr/ephyrhostglx.c b/hw/kdrive/ephyr/ephyrhostglx.c new file mode 100644 index 000000000..693fbc1a9 --- /dev/null +++ b/hw/kdrive/ephyr/ephyrhostglx.c @@ -0,0 +1,350 @@ +/* + * Xephyr - A kdrive X server thats runs in a host X window. + * Authored by Matthew Allum + * + * Copyright © 2007 OpenedHand Ltd + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of OpenedHand Ltd not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OpenedHand Ltd makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OpenedHand Ltd BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * a lots of the content of this file has been adapted from the mesa source + * code. + * Authors: + * Dodji Seketeli + */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include "hostx.h" +#include "ephyrhostglx.h" +#define _HAVE_XALLOC_DECLS +#include "ephyrlog.h" + +#ifdef XEPHYR_DRI + +Bool +ephyrHostGLXGetMajorOpcode (int *a_opcode) +{ + Bool is_ok=FALSE ; + Display *dpy=hostx_get_display () ; + static int opcode ; + int first_event_return=0, first_error_return=0; + + EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; + EPHYR_LOG ("enter\n") ; + if (!opcode) { + if (!XQueryExtension (dpy, GLX_EXTENSION_NAME, &opcode, + &first_event_return, &first_error_return)) { + EPHYR_LOG_ERROR ("XQueryExtension() failed\n") ; + goto out ; + } + } + *a_opcode = opcode ; + is_ok = TRUE ; +out: + EPHYR_LOG ("release\n") ; + return is_ok ; +} + +Bool +ephyrHostGLXQueryVersion (int *a_major, int *a_minor) +{ + Bool is_ok = FALSE ; + Display *dpy = hostx_get_display () ; + + EPHYR_RETURN_VAL_IF_FAIL (a_major && a_minor, FALSE) ; + EPHYR_LOG ("enter\n") ; + + if (!glXQueryVersion (dpy, a_major, a_minor)) { + EPHYR_LOG_ERROR ("glxQueryVersion() failed\n") ; + goto out ; + } + + is_ok = TRUE ; +out: + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +/** + * GLX protocol structure for the ficticious "GXLGenericGetString" request. + * + * This is a non-existant protocol packet. It just so happens that all of + * the real protocol packets used to request a string from the server have + * an identical binary layout. The only difference between them is the + * meaning of the \c for_whom field and the value of the \c glxCode. + */ +typedef struct GLXGenericGetString { + CARD8 reqType; + CARD8 glxCode; + CARD16 length B16; + CARD32 for_whom B32; + CARD32 name B32; +} xGLXGenericGetStringReq; + +/* These defines are only needed to make the GetReq macro happy. + */ +#define sz_xGLXGenericGetStringReq 12 +#define X_GLXGenericGetString 0 + +Bool +ephyrHostGLXGetStringFromServer (int a_screen_number, + int a_string_name, + char **a_string) +{ + Display *dpy = hostx_get_display () ; + xGLXGenericGetStringReq *req=NULL; + xGLXSingleReply reply; + int length=0, numbytes=0, major_opcode=0; + + EPHYR_RETURN_VAL_IF_FAIL (dpy && a_string, FALSE) ; + + EPHYR_LOG ("enter\n") ; + + if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) { + EPHYR_LOG_ERROR ("failed to get major opcode\n") ; + return FALSE ; + } + EPHYR_LOG ("major opcode: %d\n", major_opcode) ; + + LockDisplay (dpy); + + /* All of the GLX protocol requests for getting a string from the server + * look the same. The exact meaning of the a_for_whom field is usually + * either the screen number (for glXQueryServerString) or the context tag + * (for GLXSingle). + */ + GetReq (GLXGenericGetString, req); + req->reqType = major_opcode; + req->glxCode = X_GLXQueryServerString; + req->for_whom = a_screen_number; + req->name = a_string_name; + + _XReply (dpy, (xReply *)&reply, 0, False); + + length = reply.length * 4; + numbytes = reply.size; + + *a_string = (char *) Xmalloc( numbytes ); + if (*a_string != NULL) { + if (_XRead (dpy, *a_string, numbytes)) { + EPHYR_LOG_ERROR ("read failed\n") ; + } + length -= numbytes; + } + + _XEatData (dpy, length) ; + + UnlockDisplay (dpy); + SyncHandle (); + + EPHYR_LOG ("leave\n") ; + return TRUE ; +} + +Bool +ephyrHostGLXGetVisualConfigs (int32_t a_screen, + int32_t *a_num_visuals, + int32_t *a_num_props, + int32_t *a_props_buf_size, + int32_t **a_props_buf) +{ + Bool is_ok = FALSE ; + Display *dpy = hostx_get_display () ; + xGLXGetVisualConfigsReq *req; + xGLXGetFBConfigsReq *fb_req; + xGLXVendorPrivateWithReplyReq *vpreq; + xGLXGetFBConfigsSGIXReq *sgi_req; + xGLXGetVisualConfigsReply reply; + unsigned supported_request=0; + char *server_glx_version=NULL, + *server_glx_extensions=NULL ; + int j=0, + screens=0, + major_opcode=0, + num_props=0, + num_visuals=0, + props_buf_size=0, + props_per_visual_size=0; + int32_t *props_buf=NULL; + + EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; + + screens = ScreenCount (dpy); + if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) { + EPHYR_LOG_ERROR ("failed to get opcode\n") ; + goto out ; + } + if (!ephyrHostGLXGetStringFromServer (0, GLX_VERSION, + &server_glx_version) + || !server_glx_version) { + EPHYR_LOG_ERROR ("failed to get glx version from server\n") ; + goto out ; + } + + if (atof (server_glx_version) >= 1.3 ) { + supported_request = 1; + } + + if (!ephyrHostGLXGetStringFromServer (a_screen, GLX_EXTENSIONS, + &server_glx_extensions)) { + EPHYR_LOG_ERROR ("failed to get glx extensions from server for screen: %d\n", + a_screen) ; + goto out ; + } + if (supported_request != 1) { + if (server_glx_extensions + && strstr (server_glx_extensions, "GLX_SGIX_fbconfig" ) != NULL ) { + supported_request = 2; + } else { + supported_request = 3; + } + } + + LockDisplay(dpy); + switch (supported_request) { + case 1: + GetReq(GLXGetFBConfigs,fb_req); + fb_req->reqType = major_opcode; + fb_req->glxCode = X_GLXGetFBConfigs; + fb_req->screen = a_screen; + break; + + case 2: + GetReqExtra(GLXVendorPrivateWithReply, + sz_xGLXGetFBConfigsSGIXReq-sz_xGLXVendorPrivateWithReplyReq,vpreq); + sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq; + sgi_req->reqType = major_opcode; + sgi_req->glxCode = X_GLXVendorPrivateWithReply; + sgi_req->vendorCode = X_GLXvop_GetFBConfigsSGIX; + sgi_req->screen = a_screen; + break; + + case 3: + GetReq(GLXGetVisualConfigs,req); + req->reqType = major_opcode; + req->glxCode = X_GLXGetVisualConfigs; + req->screen = a_screen; + break; + } + + if (!_XReply(dpy, (xReply*) &reply, 0, False)) { + EPHYR_LOG_ERROR ("unknown error\n") ; + UnlockDisplay(dpy); + goto out ; + } + if (!reply.numVisuals) { + EPHYR_LOG_ERROR ("screen does not support GL rendering\n") ; + UnlockDisplay(dpy); + goto out ; + } + num_visuals = reply.numVisuals ; + + /* FIXME: Is the __GLX_MIN_CONFIG_PROPS test correct for + * FIXME: FBconfigs? + */ + /* Check number of properties */ + num_props = reply.numProps; + if ((num_props < __GLX_MIN_CONFIG_PROPS) || + (num_props > __GLX_MAX_CONFIG_PROPS)) { + /* Huh? Not in protocol defined limits. Punt */ + EPHYR_LOG_ERROR ("got a bad reply to request\n") ; + UnlockDisplay(dpy); + goto out ; + } + + if (supported_request != 3) { + num_props *= 2; + } + props_per_visual_size = num_props * __GLX_SIZE_INT32; + props_buf_size = props_per_visual_size * reply.numVisuals; + props_buf = malloc (props_buf_size) ; + for (j = 0; j < reply.numVisuals; j++) { + if (_XRead (dpy, + (char*)props_buf + j*props_per_visual_size, + props_per_visual_size) != Success) { + EPHYR_LOG_ERROR ("read failed\n") ; + } + } + UnlockDisplay(dpy); + + *a_num_visuals = num_visuals ; + *a_num_props = num_props ; + *a_props_buf_size = props_buf_size ; + *a_props_buf = props_buf ; + is_ok = TRUE ; + +out: + if (server_glx_version) { + XFree (server_glx_version) ; + server_glx_version = NULL ; + } + if (server_glx_extensions) { + XFree (server_glx_extensions) ; + server_glx_extensions = NULL ; + } + SyncHandle () ; + return is_ok; +} + +Bool +ephyrHostGLXSendClientInfo (int32_t a_major, int32_t a_minor, + const char* a_extension_list) +{ + Bool is_ok = FALSE ; + Display *dpy = hostx_get_display () ; + xGLXClientInfoReq *req; + int size; + int32_t major_opcode=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (dpy && a_extension_list, FALSE) ; + + if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) { + EPHYR_LOG_ERROR ("failed to get major opcode\n") ; + goto out ; + } + + LockDisplay (dpy); + + GetReq (GLXClientInfo,req); + req->reqType = major_opcode; + req->glxCode = X_GLXClientInfo; + req->major = a_major; + req->minor = a_minor; + + size = strlen (a_extension_list) + 1; + req->length += (size + 3) >> 2; + req->numbytes = size; + Data (dpy, a_extension_list, size); + + is_ok=TRUE ; + +out: + UnlockDisplay(dpy); + SyncHandle(); + return is_ok ; +} + +#endif /*XEPHYR_DRI*/ + diff --git a/hw/kdrive/ephyr/ephyrhostglx.h b/hw/kdrive/ephyr/ephyrhostglx.h new file mode 100644 index 000000000..7a158f3d0 --- /dev/null +++ b/hw/kdrive/ephyr/ephyrhostglx.h @@ -0,0 +1,47 @@ +/* + * Xephyr - A kdrive X server thats runs in a host X window. + * Authored by Matthew Allum + * + * Copyright © 2007 OpenedHand Ltd + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of OpenedHand Ltd not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OpenedHand Ltd makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OpenedHand Ltd BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Authors: + * Dodji Seketeli + */ +#ifndef __EPHYRHOSTGLX_H__ +#define __EPHYRHOSTGLX_H__ + +Bool ephyrHostGLXQueryVersion (int *a_maj, int *a_min) ; +Bool ephyrHostGLXGetStringFromServer (int a_screen_number, + int a_string_name, + char **a_string) ; +Bool ephyrHostGLXGetVisualConfigs (int a_screen, + int32_t *a_num_visuals, + int32_t *a_num_props, + int32_t *a_props_buf_size, + int32_t **a_props_buf) ; + +Bool ephyrHostGLXGetMajorOpcode (int32_t *a_opcode) ; + +Bool ephyrHostGLXSendClientInfo (int32_t a_major, int32_t a_minor, + const char* a_extension_list) ; + +#endif /*__EPHYRHOSTGLX_H__*/ + From 5af73f98c46dfe5640185ca90feb20c39c6e06fa Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Fri, 24 Aug 2007 16:30:50 +0200 Subject: [PATCH 24/44] EPHYR: Add an experiment proto proxy extension. * hw/kdrive/ephyr/Makefile.am: add the proxy extension to ephyr. The proxy extension is an experimental extension that forwards protocol packets targeted at a given extension to the host X. * hw/kdrive/ephyr/ephyr.c: init proxy ext. * hw/kdrive/ephyr/ephyrhostproxy.c,h: added this new file as part of the proxy extension. * hw/kdrive/ephyr/ephyrproxyext.c,h: ditto * hw/kdrive/ephyr/hostx.c: add the hostx_get_get_extension_info() entry point. --- hw/kdrive/ephyr/Makefile.am | 5 ++ hw/kdrive/ephyr/ephyr.c | 5 ++ hw/kdrive/ephyr/ephyrhostproxy.c | 94 ++++++++++++++++++++++++ hw/kdrive/ephyr/ephyrhostproxy.h | 51 +++++++++++++ hw/kdrive/ephyr/ephyrproxyext.c | 119 +++++++++++++++++++++++++++++++ hw/kdrive/ephyr/ephyrproxyext.h | 34 +++++++++ hw/kdrive/ephyr/hostx.c | 20 ++++++ hw/kdrive/ephyr/hostx.h | 6 ++ 8 files changed, 334 insertions(+) create mode 100644 hw/kdrive/ephyr/ephyrhostproxy.c create mode 100644 hw/kdrive/ephyr/ephyrhostproxy.h create mode 100644 hw/kdrive/ephyr/ephyrproxyext.c create mode 100644 hw/kdrive/ephyr/ephyrproxyext.h diff --git a/hw/kdrive/ephyr/Makefile.am b/hw/kdrive/ephyr/Makefile.am index 5e3316324..604e22eaa 100644 --- a/hw/kdrive/ephyr/Makefile.am +++ b/hw/kdrive/ephyr/Makefile.am @@ -30,6 +30,11 @@ libxephyr_a_SOURCES = \ ephyrglxext.h \ ephyrhostglx.c \ ephyrhostglx.h \ + ephyrhostproxy.c \ + ephyrhostproxy.h \ + ephyrhostproxy.c \ + ephyrproxyext.c \ + ephyrproxyext.h \ os.c \ hostx.h \ ephyr.h \ diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c index b460b9630..8e12bbbed 100644 --- a/hw/kdrive/ephyr/ephyr.c +++ b/hw/kdrive/ephyr/ephyr.c @@ -31,8 +31,12 @@ #include "inputstr.h" #include "scrnintstr.h" #include "ephyrlog.h" + +#ifdef XEPHYR_DRI #include "ephyrdri.h" #include "ephyrglxext.h" +#include "ephyrproxyext.h" +#endif /*XEPHYR_DRI*/ extern int KdTsPhyScreen; KdKeyboardInfo *ephyrKbd; @@ -625,6 +629,7 @@ ephyrInitScreen (ScreenPtr pScreen) #ifdef XEPHYR_DRI ephyrDRIExtensionInit () ; ephyrHijackGLXExtension () ; + ephyrProxyExtensionInit ("ATIFGLRXDRI") ; #endif return TRUE; } diff --git a/hw/kdrive/ephyr/ephyrhostproxy.c b/hw/kdrive/ephyr/ephyrhostproxy.c new file mode 100644 index 000000000..ce3f01852 --- /dev/null +++ b/hw/kdrive/ephyr/ephyrhostproxy.c @@ -0,0 +1,94 @@ +/* + * Xephyr - A kdrive X server thats runs in a host X window. + * Authored by Matthew Allum + * + * Copyright © 2007 OpenedHand Ltd + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of OpenedHand Ltd not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OpenedHand Ltd makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OpenedHand Ltd BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Authors: + * Dodji Seketeli + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#define _HAVE_XALLOC_DECLS +#include "ephyrlog.h" +#include "ephyrhostproxy.h" +#include "hostx.h" + +/* byte swap a short */ +#define swaps(x, n) { \ + n = ((char *) (x))[0];\ + ((char *) (x))[0] = ((char *) (x))[1];\ + ((char *) (x))[1] = n; } + +#define GetXReq(req) \ + WORD64ALIGN ;\ + if ((dpy->bufptr + SIZEOF(xReq)) > dpy->bufmax)\ + _XFlush(dpy);\ + req = (xReq *)(dpy->last_req = dpy->bufptr);\ + dpy->bufptr += SIZEOF(xReq);\ + dpy->request++ + + +Bool +ephyrHostProxyDoForward (pointer a_request_buffer, + struct XReply *a_reply, + Bool a_do_swap) +{ + Bool is_ok = FALSE ; + int n=0 ; + Display *dpy=hostx_get_display () ; + xReq *in_req = (xReq*) a_request_buffer ; + xReq *forward_req=NULL ; + struct XReply reply ; + + EPHYR_RETURN_VAL_IF_FAIL (in_req && dpy, FALSE) ; + + EPHYR_LOG ("enter\n") ; + + if (a_do_swap) { + swaps (&in_req->length, n) ; + } + EPHYR_LOG ("Req {type:%d, data:%d, length:%d}\n", + in_req->reqType, in_req->data, in_req->length) ; + GetXReq (forward_req) ; + memmove (forward_req, in_req, 4) ; + + if (!_XReply (dpy, (xReply*) &reply, 0, FALSE)) { + EPHYR_LOG_ERROR ("failed to get reply\n") ; + goto out; + } + EPHYR_LOG ("XReply{type:%d, foo:%d, seqnum:%d, length:%d}\n", + reply.type, reply.foo, reply.sequence_number, reply.length) ; + + if (a_reply) { + memmove (a_reply, &reply, sizeof (reply)) ; + } + is_ok = TRUE ; + +out: + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + diff --git a/hw/kdrive/ephyr/ephyrhostproxy.h b/hw/kdrive/ephyr/ephyrhostproxy.h new file mode 100644 index 000000000..720c986ff --- /dev/null +++ b/hw/kdrive/ephyr/ephyrhostproxy.h @@ -0,0 +1,51 @@ +/* + * Xephyr - A kdrive X server thats runs in a host X window. + * Authored by Matthew Allum + * + * Copyright © 2007 OpenedHand Ltd + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of OpenedHand Ltd not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OpenedHand Ltd makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OpenedHand Ltd BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Authors: + * Dodji Seketeli + */ + +#ifndef __EPHYRHOSTPROXY_H__ +#define __EPHYRHOSTPROXY_H__ + +struct XReply { + int8_t type ;/*X_Reply*/ + int8_t foo; + int16_t sequence_number ; + int32_t length ; + /*following is some data up to 32 bytes lenght*/ + int32_t pad0 ; + int32_t pad1 ; + int32_t pad2 ; + int32_t pad3 ; + int32_t pad4 ; + int32_t pad5 ; +}; + +Bool +ephyrHostProxyDoForward (pointer a_request_buffer, + struct XReply *a_reply, + Bool a_do_swap) ; + +#endif /*__EPHYRHOSTPROXY_H__*/ diff --git a/hw/kdrive/ephyr/ephyrproxyext.c b/hw/kdrive/ephyr/ephyrproxyext.c new file mode 100644 index 000000000..0c070f4c7 --- /dev/null +++ b/hw/kdrive/ephyr/ephyrproxyext.c @@ -0,0 +1,119 @@ +/* + * Xephyr - A kdrive X server thats runs in a host X window. + * Authored by Matthew Allum + * + * Copyright © 2007 OpenedHand Ltd + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of OpenedHand Ltd not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OpenedHand Ltd makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OpenedHand Ltd BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Authors: + * Dodji Seketeli + */ + +/* + * \file + * This file defines a proxy extension that forwards requests. + * When a request to extension FOO is sent to Xephyr, that request is forwared + * to the host X, without even trying to know what the request means. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "misc.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "ephyrproxyext.h" +#define _HAVE_XALLOC_DECLS +#include "ephyrlog.h" +#include "ephyrhostproxy.h" +#include "hostx.h" + +static Bool ephyrProxyGetHostExtensionInfo (const char *a_ext_name, + int *a_major_opcode, + int *a_first_event, + int *a_first_error) ; + +static int ephyrProxyProcDispatch (ClientPtr client) ; + +static Bool +ephyrProxyGetHostExtensionInfo (const char *a_ext_name, + int *a_major_opcode, + int *a_first_event, + int *a_first_error) +{ + return hostx_get_extension_info (a_ext_name, a_major_opcode, + a_first_event, a_first_error) ; +} + +static int +ephyrProxyProcDispatch (ClientPtr a_client) +{ + int res=BadImplementation ; + struct XReply reply ; + + if (!ephyrHostProxyDoForward (a_client->requestBuffer, &reply, FALSE)) { + EPHYR_LOG_ERROR ("forwarding failed\n") ; + goto out ; + } + reply.sequence_number = a_client->sequence; + res = Success ; + + WriteToClient(a_client, 32, (char *)&reply); + +out: + return res ; +} + +static void +ephyrProxyProcReset (ExtensionEntry *a_entry) +{ +} + +Bool +ephyrProxyExtensionInit (const char *a_extension_name) +{ + Bool is_ok = FALSE ; + int major_opcode=0, first_event=0, first_error=0; + ExtensionEntry *ext=NULL ; + + if (!ephyrProxyGetHostExtensionInfo (a_extension_name, + &major_opcode, + &first_event, + &first_error)) { + EPHYR_LOG ("failed to query extension %s from host\n", a_extension_name) ; + goto out; + } + ext = AddExtension ((char*)a_extension_name, 0, 0, + ephyrProxyProcDispatch, + ephyrProxyProcDispatch, + ephyrProxyProcReset, + StandardMinorOpcode) ; + if (!ext) { + EPHYR_LOG_ERROR ("failed to add the extension\n") ; + goto out ; + } + is_ok = TRUE ; + +out: + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + diff --git a/hw/kdrive/ephyr/ephyrproxyext.h b/hw/kdrive/ephyr/ephyrproxyext.h new file mode 100644 index 000000000..e52f8d887 --- /dev/null +++ b/hw/kdrive/ephyr/ephyrproxyext.h @@ -0,0 +1,34 @@ +/* + * Xephyr - A kdrive X server thats runs in a host X window. + * Authored by Matthew Allum + * + * Copyright © 2007 OpenedHand Ltd + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of OpenedHand Ltd not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OpenedHand Ltd makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OpenedHand Ltd BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Authors: + * Dodji Seketeli + */ +#ifndef __EPHYRPROXYEXT_H__ +#define __EPHYRPROXYEXT_H__ + +Bool ephyrProxyExtensionInit (const char *a_extension_name) ; + +#endif /*__EPHYRPROXYEXT_H__*/ + diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c index 8a2762ff8..8323c2824 100644 --- a/hw/kdrive/ephyr/hostx.c +++ b/hw/kdrive/ephyr/hostx.c @@ -967,3 +967,23 @@ hostx_get_window(void) { return HostX.win ; } + +int +hostx_get_extension_info (const char *a_ext_name, + int *a_major_opcode, + int *a_first_event, + int *a_first_error) +{ + if (!a_ext_name || !a_major_opcode || !a_first_event || !a_first_error) + return 0 ; + if (!XQueryExtension (HostX.dpy, + a_ext_name, + a_major_opcode, + a_first_event, + a_first_error)) + { + return 0 ; + } + return 1 ; +} + diff --git a/hw/kdrive/ephyr/hostx.h b/hw/kdrive/ephyr/hostx.h index 1d8cd70db..7babd340d 100644 --- a/hw/kdrive/ephyr/hostx.h +++ b/hw/kdrive/ephyr/hostx.h @@ -178,4 +178,10 @@ hostx_get_display(void) ; int hostx_get_window(void) ; +int +hostx_get_extension_info (const char *a_ext_name, + int *a_major_opcode, + int *a_first_even, + int *a_first_error) ; + #endif From 26da625055a3876c93a7a005520657b971748c4e Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Tue, 28 Aug 2007 15:55:05 +0200 Subject: [PATCH 25/44] proxy the glXGetFBConfigSGIX call * hw/kdrive/ephyr/ephyrglxext.c: (ephyrGLXGetFBConfigsSGIX): proxy the GLXGetFBConfigsSGIX call. It is a vendor extension to get the visual configs as a list of name/value pairs. (ephyrHijackGLXExtension): hijack the VendorPriv_dispatch_info dispatch table to register our implementation of GLXGetFBConfigsSGIX (ephyrGLXGetFBConfigsSGIXReal): added this where the real implementation of GLXGetFBConfigsSGIX is. It support bytes swapping. (ephyrGLXGetFBConfigsSGIX,ephyrGLXGetFBConfigsSGIXSwap): these are the dispatch entry points. They just call ephyrGLXGetFBConfigsSGIXReal. * hw/kdrive/ephyr/ephyrhostglx.c,h: reorganize the proxies to get visual params from the host so that they clearly support the different methods of doing so. --- hw/kdrive/ephyr/ephyrglxext.c | 100 +++++++++++++++++++++++++++-- hw/kdrive/ephyr/ephyrhostglx.c | 112 +++++++++++++++++++++------------ hw/kdrive/ephyr/ephyrhostglx.h | 8 ++- 3 files changed, 173 insertions(+), 47 deletions(-) diff --git a/hw/kdrive/ephyr/ephyrglxext.c b/hw/kdrive/ephyr/ephyrglxext.c index d0380f105..c4e5ba4d4 100644 --- a/hw/kdrive/ephyr/ephyrglxext.c +++ b/hw/kdrive/ephyr/ephyrglxext.c @@ -59,17 +59,22 @@ int ephyrGLXClientInfo(__GLXclientState *cl, GLbyte *pc) ; int ephyrGLXClientInfoSwap(__GLXclientState *cl, GLbyte *pc) ; int ephyrGLXQueryServerString(__GLXclientState *a_cl, GLbyte *a_pc) ; int ephyrGLXQueryServerStringSwap(__GLXclientState *a_cl, GLbyte *a_pc) ; +int ephyrGLXGetFBConfigsSGIX (__GLXclientState *a_cl, GLbyte *a_pc); +int ephyrGLXGetFBConfigsSGIXSwap (__GLXclientState *a_cl, GLbyte *a_pc); Bool ephyrHijackGLXExtension (void) { const void *(*dispatch_functions)[2]; - EPHYR_LOG ("Got GLX extension\n") ; + EPHYR_LOG ("going to hijack some glx entry points ...\n") ; if (!Single_dispatch_info.dispatch_functions) { EPHYR_LOG_ERROR ("could not get dispatch functions table\n") ; return FALSE ; } + /* + * hijack some single entry point dispatch functions + */ dispatch_functions = Single_dispatch_info.dispatch_functions ; EPHYR_RETURN_VAL_IF_FAIL (dispatch_functions, FALSE) ; @@ -83,9 +88,16 @@ ephyrHijackGLXExtension (void) dispatch_functions[X_GLXClientInfo][1] = ephyrGLXClientInfoSwap ; dispatch_functions[X_GLXQueryServerString][0] = ephyrGLXQueryServerString ; - dispatch_functions[X_GLXQueryServerString][1] = ephyrGLXQueryServerStringSwap ; + dispatch_functions[X_GLXQueryServerString][1] = + ephyrGLXQueryServerStringSwap ; - EPHYR_LOG ("hijacked mesa GL to forward requests to host X\n") ; + /* + * hijack some vendor priv entry point dispatch functions + */ + dispatch_functions = VendorPriv_dispatch_info.dispatch_functions ; + dispatch_functions[92][0] = ephyrGLXGetFBConfigsSGIX; + dispatch_functions[92][1] = ephyrGLXGetFBConfigsSGIXSwap; + EPHYR_LOG ("hijacked glx entry points to forward requests to host X\n") ; return TRUE ; } @@ -114,6 +126,8 @@ ephyrGLXQueryVersion(__GLXclientState *a_cl, GLbyte *a_pc) EPHYR_LOG_ERROR ("ephyrHostGLXQueryVersion() failed\n") ; goto out ; } + EPHYR_LOG ("major:%d, minor:%d\n", + major, minor); reply.majorVersion = major ; reply.minorVersion = minor ; reply.length = 0 ; @@ -145,7 +159,9 @@ ephyrGLXQueryVersionSwap (__GLXclientState *a_cl, GLbyte *a_pc) } static int -ephyrGLXGetVisualConfigsReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap) +ephyrGLXGetVisualConfigsReal (__GLXclientState *a_cl, + GLbyte *a_pc, + Bool a_do_swap) { xGLXGetVisualConfigsReq *req = (xGLXGetVisualConfigsReq *) a_pc; ClientPtr client = a_cl->client; @@ -200,6 +216,64 @@ out: return res ; } +static int +ephyrGLXGetFBConfigsSGIXReal (__GLXclientState *a_cl, + GLbyte *a_pc, + Bool a_do_swap) +{ + xGLXGetFBConfigsSGIXReq *req = (xGLXGetFBConfigsSGIXReq *)a_pc; + ClientPtr client = a_cl->client; + xGLXGetVisualConfigsReply reply; + int32_t *props_buf=NULL, num_visuals=0, + num_props=0, res=BadImplementation, i=0, + props_per_visual_size=0, + props_buf_size=0; + __GLX_DECLARE_SWAP_VARIABLES; + __GLX_DECLARE_SWAP_ARRAY_VARIABLES; + + EPHYR_LOG ("enter\n") ; + + if (!ephyrHostGLXVendorPrivGetFBConfigsSGIX (req->screen, + &num_visuals, + &num_props, + &props_buf_size, + &props_buf)) { + EPHYR_LOG_ERROR ("ephyrHostGLXGetVisualConfigs() failed\n") ; + goto out ; + } + EPHYR_LOG ("num_visuals:%d, num_props:%d\n", num_visuals, num_props) ; + + reply.numVisuals = num_visuals; + reply.numProps = num_props; + reply.length = props_buf_size >> 2; + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + + if (a_do_swap) { + __GLX_SWAP_SHORT(&reply.sequenceNumber); + __GLX_SWAP_INT(&reply.length); + __GLX_SWAP_INT(&reply.numVisuals); + __GLX_SWAP_INT(&reply.numProps); + __GLX_SWAP_INT_ARRAY (props_buf, num_props) ; + } + WriteToClient(client, sz_xGLXGetVisualConfigsReply, (char*)&reply); + props_per_visual_size = props_buf_size/num_visuals ; + for (i=0; i < num_visuals; i++) { + WriteToClient (client, + props_per_visual_size, + &((char*)props_buf)[i*props_per_visual_size]); + } + res = Success ; + +out: + EPHYR_LOG ("leave\n") ; + if (props_buf) { + xfree (props_buf) ; + props_buf = NULL ; + } + return res ; +} + int ephyrGLXGetVisualConfigs (__GLXclientState *a_cl, GLbyte *a_pc) { @@ -256,10 +330,13 @@ ephyrGLXQueryServerString(__GLXclientState *a_cl, GLbyte *a_pc) int length=0 ; EPHYR_LOG ("enter\n") ; - if (!ephyrHostGLXGetStringFromServer (req->screen, req->name, &server_string)) { + if (!ephyrHostGLXGetStringFromServer (req->screen, + req->name, + &server_string)) { EPHYR_LOG_ERROR ("failed to query string from host\n") ; goto out ; } + EPHYR_LOG ("string: %s", server_string) ; length= strlen (server_string) + 1; reply.type = X_Reply ; reply.sequenceNumber = client->sequence ; @@ -287,5 +364,18 @@ ephyrGLXQueryServerStringSwap(__GLXclientState *a_cl, GLbyte *a_pc) return BadImplementation ; } + +int +ephyrGLXGetFBConfigsSGIX (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXGetFBConfigsSGIXReal (a_cl, a_pc, FALSE) ; +} + +int +ephyrGLXGetFBConfigsSGIXSwap (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXGetFBConfigsSGIXReal (a_cl, a_pc, TRUE) ; +} + #endif /*XEPHYR_DRI*/ diff --git a/hw/kdrive/ephyr/ephyrhostglx.c b/hw/kdrive/ephyr/ephyrhostglx.c index 693fbc1a9..83e06a85b 100644 --- a/hw/kdrive/ephyr/ephyrhostglx.c +++ b/hw/kdrive/ephyr/ephyrhostglx.c @@ -42,7 +42,20 @@ #include "ephyrlog.h" #ifdef XEPHYR_DRI +enum VisualConfRequestType { + EPHYR_GET_FB_CONFIG, + EPHYR_VENDOR_PRIV_GET_FB_CONFIG_SGIX, + EPHYR_GET_VISUAL_CONFIGS +}; + +static Bool ephyrHostGLXGetVisualConfigsInternal + (enum VisualConfRequestType a_type, + int32_t a_screen, + int32_t *a_num_visuals, + int32_t *a_num_props, + int32_t *a_props_buf_size, + int32_t **a_props_buf); Bool ephyrHostGLXGetMajorOpcode (int *a_opcode) { @@ -163,12 +176,13 @@ ephyrHostGLXGetStringFromServer (int a_screen_number, return TRUE ; } -Bool -ephyrHostGLXGetVisualConfigs (int32_t a_screen, - int32_t *a_num_visuals, - int32_t *a_num_props, - int32_t *a_props_buf_size, - int32_t **a_props_buf) +static Bool +ephyrHostGLXGetVisualConfigsInternal (enum VisualConfRequestType a_type, + int32_t a_screen, + int32_t *a_num_visuals, + int32_t *a_num_props, + int32_t *a_props_buf_size, + int32_t **a_props_buf) { Bool is_ok = FALSE ; Display *dpy = hostx_get_display () ; @@ -177,7 +191,6 @@ ephyrHostGLXGetVisualConfigs (int32_t a_screen, xGLXVendorPrivateWithReplyReq *vpreq; xGLXGetFBConfigsSGIXReq *sgi_req; xGLXGetVisualConfigsReply reply; - unsigned supported_request=0; char *server_glx_version=NULL, *server_glx_extensions=NULL ; int j=0, @@ -196,44 +209,22 @@ ephyrHostGLXGetVisualConfigs (int32_t a_screen, EPHYR_LOG_ERROR ("failed to get opcode\n") ; goto out ; } - if (!ephyrHostGLXGetStringFromServer (0, GLX_VERSION, - &server_glx_version) - || !server_glx_version) { - EPHYR_LOG_ERROR ("failed to get glx version from server\n") ; - goto out ; - } - - if (atof (server_glx_version) >= 1.3 ) { - supported_request = 1; - } - - if (!ephyrHostGLXGetStringFromServer (a_screen, GLX_EXTENSIONS, - &server_glx_extensions)) { - EPHYR_LOG_ERROR ("failed to get glx extensions from server for screen: %d\n", - a_screen) ; - goto out ; - } - if (supported_request != 1) { - if (server_glx_extensions - && strstr (server_glx_extensions, "GLX_SGIX_fbconfig" ) != NULL ) { - supported_request = 2; - } else { - supported_request = 3; - } - } LockDisplay(dpy); - switch (supported_request) { - case 1: + switch (a_type) { + case EPHYR_GET_FB_CONFIG: GetReq(GLXGetFBConfigs,fb_req); fb_req->reqType = major_opcode; fb_req->glxCode = X_GLXGetFBConfigs; fb_req->screen = a_screen; break; - case 2: + case EPHYR_VENDOR_PRIV_GET_FB_CONFIG_SGIX: GetReqExtra(GLXVendorPrivateWithReply, - sz_xGLXGetFBConfigsSGIXReq-sz_xGLXVendorPrivateWithReplyReq,vpreq); + sz_xGLXGetFBConfigsSGIXReq + - + sz_xGLXVendorPrivateWithReplyReq, + vpreq); sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq; sgi_req->reqType = major_opcode; sgi_req->glxCode = X_GLXVendorPrivateWithReply; @@ -241,7 +232,7 @@ ephyrHostGLXGetVisualConfigs (int32_t a_screen, sgi_req->screen = a_screen; break; - case 3: + case EPHYR_GET_VISUAL_CONFIGS: GetReq(GLXGetVisualConfigs,req); req->reqType = major_opcode; req->glxCode = X_GLXGetVisualConfigs; @@ -274,7 +265,7 @@ ephyrHostGLXGetVisualConfigs (int32_t a_screen, goto out ; } - if (supported_request != 3) { + if (a_type != EPHYR_GET_VISUAL_CONFIGS) { num_props *= 2; } props_per_visual_size = num_props * __GLX_SIZE_INT32; @@ -282,7 +273,7 @@ ephyrHostGLXGetVisualConfigs (int32_t a_screen, props_buf = malloc (props_buf_size) ; for (j = 0; j < reply.numVisuals; j++) { if (_XRead (dpy, - (char*)props_buf + j*props_per_visual_size, + &((char*)props_buf)[j*props_per_visual_size], props_per_visual_size) != Success) { EPHYR_LOG_ERROR ("read failed\n") ; } @@ -290,7 +281,7 @@ ephyrHostGLXGetVisualConfigs (int32_t a_screen, UnlockDisplay(dpy); *a_num_visuals = num_visuals ; - *a_num_props = num_props ; + *a_num_props = reply.numProps ; *a_props_buf_size = props_buf_size ; *a_props_buf = props_buf ; is_ok = TRUE ; @@ -308,6 +299,47 @@ out: return is_ok; } +Bool +ephyrHostGLXGetVisualConfigs (int32_t a_screen, + int32_t *a_num_visuals, + int32_t *a_num_props, + int32_t *a_props_buf_size, + int32_t **a_props_buf) +{ + Bool is_ok = FALSE; + + EPHYR_LOG ("enter\n") ; + is_ok = ephyrHostGLXGetVisualConfigsInternal (EPHYR_GET_VISUAL_CONFIGS, + a_screen, + a_num_visuals, + a_num_props, + a_props_buf_size, + a_props_buf) ; + + EPHYR_LOG ("leave:%d\n", is_ok) ; + return is_ok; +} + +Bool +ephyrHostGLXVendorPrivGetFBConfigsSGIX (int a_screen, + int32_t *a_num_visuals, + int32_t *a_num_props, + int32_t *a_props_buf_size, + int32_t **a_props_buf) +{ + Bool is_ok=FALSE ; + EPHYR_LOG ("enter\n") ; + is_ok = ephyrHostGLXGetVisualConfigsInternal + (EPHYR_VENDOR_PRIV_GET_FB_CONFIG_SGIX, + a_screen, + a_num_visuals, + a_num_props, + a_props_buf_size, + a_props_buf) ; + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + Bool ephyrHostGLXSendClientInfo (int32_t a_major, int32_t a_minor, const char* a_extension_list) diff --git a/hw/kdrive/ephyr/ephyrhostglx.h b/hw/kdrive/ephyr/ephyrhostglx.h index 7a158f3d0..1040f6c61 100644 --- a/hw/kdrive/ephyr/ephyrhostglx.h +++ b/hw/kdrive/ephyr/ephyrhostglx.h @@ -37,9 +37,13 @@ Bool ephyrHostGLXGetVisualConfigs (int a_screen, int32_t *a_num_props, int32_t *a_props_buf_size, int32_t **a_props_buf) ; - +Bool +ephyrHostGLXVendorPrivGetFBConfigsSGIX (int a_screen, + int32_t *a_num_visuals, + int32_t *a_num_props, + int32_t *a_props_buf_size, + int32_t **a_props_buf); Bool ephyrHostGLXGetMajorOpcode (int32_t *a_opcode) ; - Bool ephyrHostGLXSendClientInfo (int32_t a_major, int32_t a_minor, const char* a_extension_list) ; From 1dd589410c6c5e8b62b4d15ec681b01452ec68c6 Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Tue, 28 Aug 2007 15:58:55 +0200 Subject: [PATCH 26/44] mirror the visuals of the host X at startup. * hw/kdrive/ephyr/ephyr.c: make Xephyr mirror the visuals of the host X upon startup. This is important for GLX client apps. * hw/kdrive/ephyr/hostx.c,h: add a hostx_get_visuals_info() to get the visuals of the host X. --- hw/kdrive/ephyr/ephyr.c | 164 ++++++++++++++++++++++++++++++++++++++++ hw/kdrive/ephyr/hostx.c | 52 +++++++++++++ hw/kdrive/ephyr/hostx.h | 16 +++- 3 files changed, 231 insertions(+), 1 deletion(-) diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c index 8e12bbbed..df91f83fb 100644 --- a/hw/kdrive/ephyr/ephyr.c +++ b/hw/kdrive/ephyr/ephyr.c @@ -54,6 +54,7 @@ Bool EphyrWantGrayScale = 0; #ifdef XEPHYR_DRI extern void ephyrDRIExtensionInit(void) ; +static Bool EphyrMirrorHostVisuals (void) ; #endif Bool @@ -630,6 +631,7 @@ ephyrInitScreen (ScreenPtr pScreen) ephyrDRIExtensionInit () ; ephyrHijackGLXExtension () ; ephyrProxyExtensionInit ("ATIFGLRXDRI") ; + EphyrMirrorHostVisuals () ; #endif return TRUE; } @@ -1046,6 +1048,168 @@ EphyrKeyboardBell (KdKeyboardInfo *ki, int volume, int frequency, int duration) { } +/** + * Duplicates a visual of a_screen + * In screen a_screen, for depth a_depth, find a visual which + * bitsPerRGBValue and colormap size equal + * a_bits_per_rgb_values and a_colormap_entries. + * The ID of that duplicated visual is set to a_new_id. + * That duplicated visual is then added to the list of visuals + * of the screen. + */ +static Bool +EphyrDuplicateVisual (unsigned int a_screen, + short a_depth, + short a_class, + short a_bits_per_rgb_values, + short a_colormap_entries, + unsigned int a_red_mask, + unsigned int a_green_mask, + unsigned int a_blue_mask, + unsigned int a_new_id) +{ + Bool is_ok = FALSE, found_visual=FALSE, found_depth=FALSE ; + ScreenPtr screen=NULL ; + VisualRec new_visual, *new_visuals=NULL ; + int i=0 ; + + EPHYR_LOG ("enter\n") ; + if (a_screen > screenInfo.numScreens) { + EPHYR_LOG_ERROR ("bad screen number\n") ; + goto out; + } + memset (&new_visual, 0, sizeof (VisualRec)) ; + + /*get the screen pointed to by a_screen*/ + screen = screenInfo.screens[a_screen] ; + EPHYR_RETURN_VAL_IF_FAIL (screen, FALSE) ; + + /* + * In that screen, first look for an existing visual that has the + * same characteristics as those passed in parameter + * to this function and copy it. + */ + for (i=0; i < screen->numVisuals; i++) { + if (screen->visuals[i].bitsPerRGBValue == a_bits_per_rgb_values && + screen->visuals[i].ColormapEntries == a_colormap_entries ) { + /*copy the visual found*/ + memcpy (&new_visual, &screen->visuals[i], sizeof (new_visual)) ; + new_visual.vid = a_new_id ; + found_visual = TRUE ; + EPHYR_LOG ("found a visual that matches visual id: %d\n", + a_new_id) ; + break; + } + } + if (!found_visual) { + EPHYR_LOG ("did not find any visual matching %d\n", a_new_id) ; + goto out ; + } + /* + * be prepare to extend screen->visuals to add new_visual to it + */ + new_visuals = xcalloc (screen->numVisuals+1, sizeof (VisualRec)) ; + memmove (new_visuals, + screen->visuals, + screen->numVisuals*sizeof (VisualRec)) ; + memmove (&new_visuals[screen->numVisuals], + &new_visual, + sizeof (VisualRec)) ; + /* + * Now, in that same screen, update the screen->allowedDepths member. + * In that array, each element represents the visuals applicable to + * a given depth. So we need to add an entry matching the new visual + * that we are going to add to screen->visuals + */ + for (i=0; inumDepths; i++) { + VisualID *vids=NULL; + DepthPtr cur_depth=NULL ; + /*find the entry matching a_depth*/ + if (screen->allowedDepths[i].depth != a_depth) + continue ; + cur_depth = &screen->allowedDepths[i]; + /* + * extend the list of visual IDs in that entry, + * so to add a_new_id in there. + */ + vids = xrealloc (cur_depth->vids, + (cur_depth->numVids+1)*sizeof (VisualID)); + if (!vids) { + EPHYR_LOG_ERROR ("failed to realloc numids\n") ; + goto out ; + } + vids[cur_depth->numVids] = a_new_id ; + /* + * Okay now commit our change. + * Do really update screen->allowedDepths[i] + */ + cur_depth->numVids++ ; + cur_depth->vids = vids ; + found_depth=TRUE; + } + if (!found_depth) { + EPHYR_LOG_ERROR ("failed to update screen[%d]->allowedDepth\n", + a_screen) ; + goto out ; + } + /* + * Commit our change to screen->visuals + */ + xfree (screen->visuals) ; + screen->visuals = new_visuals ; + screen->numVisuals++ ; + new_visuals = NULL ; + + is_ok = TRUE ; +out: + if (new_visuals) { + xfree (new_visuals) ; + new_visuals = NULL ; + } + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +/** + * Duplicates the visuals of the host X server. + * This is necessary to have visuals that have the same + * ID as those of the host X. It is important to have that for + * GLX. + */ +static Bool +EphyrMirrorHostVisuals (void) +{ + Bool is_ok=FALSE; + EphyrHostVisualInfo *visuals=NULL; + int nb_visuals=0, i=0; + + EPHYR_LOG ("enter\n") ; + if (!hostx_get_visuals_info (&visuals, &nb_visuals)) { + EPHYR_LOG_ERROR ("failed to get host visuals\n") ; + goto out ; + } + for (i=0; i #include #include +#include "ephyrlog.h" /* * All xlib calls go here, which gets built as its own .a . @@ -987,3 +988,54 @@ hostx_get_extension_info (const char *a_ext_name, return 1 ; } +int +hostx_get_visuals_info (EphyrHostVisualInfo **a_visuals, + int *a_num_entries) +{ + Display *dpy=hostx_get_display () ; + Bool is_ok=False ; + XVisualInfo templ, *visuals=NULL; + EphyrHostVisualInfo *host_visuals=NULL ; + int nb_items=0, i=0; + + EPHYR_RETURN_VAL_IF_FAIL (a_visuals && a_num_entries && dpy, + False) ; + EPHYR_LOG ("enter\n") ; + memset (&templ, 0, sizeof (templ)) ; + visuals = XGetVisualInfo (dpy, VisualNoMask, &templ, &nb_items) ; + if (!visuals) { + EPHYR_LOG_ERROR ("host does not advertise any visual\n") ; + goto out ; + } + EPHYR_LOG ("host advertises %d visuals\n", nb_items) ; + host_visuals = calloc (nb_items, sizeof (EphyrHostVisualInfo)) ; + for (i=0; i Date: Tue, 28 Aug 2007 15:59:45 +0200 Subject: [PATCH 27/44] Xephyr: add logging in the DRI extension --- hw/kdrive/ephyr/ephyrdri.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/hw/kdrive/ephyr/ephyrdri.c b/hw/kdrive/ephyr/ephyrdri.c index 89d9ae7b5..54ad2c0b6 100644 --- a/hw/kdrive/ephyr/ephyrdri.c +++ b/hw/kdrive/ephyr/ephyrdri.c @@ -63,7 +63,9 @@ ephyrDRIQueryDirectRenderingCapable (int a_screen, Bool *a_is_capable) } Bool -ephyrDRIOpenConnection (int a_screen, drm_handle_t *a_sarea, char **a_bus_id_string) +ephyrDRIOpenConnection (int a_screen, + drm_handle_t *a_sarea, + char **a_bus_id_string) { Display *dpy = hostx_get_display () ; Bool is_ok=FALSE ; @@ -108,13 +110,23 @@ ephyrDRIGetClientDriverName (int a_screen, Display *dpy = hostx_get_display () ; Bool is_ok=FALSE ; + EPHYR_RETURN_VAL_IF_FAIL (a_ddx_driver_major_version + && a_ddx_driver_minor_version + && a_ddx_driver_patch_version + && a_client_driver_name, + FALSE); EPHYR_LOG ("enter\n") ; is_ok = XF86DRIGetClientDriverName (dpy, a_screen, a_ddx_driver_major_version, a_ddx_driver_minor_version, a_ddx_driver_patch_version, a_client_driver_name) ; - EPHYR_LOG ("leave\n") ; + EPHYR_LOG ("major:%d, minor:%d, patch:%d, name:%s\n", + *a_ddx_driver_major_version, + *a_ddx_driver_minor_version, + *a_ddx_driver_patch_version, + *a_client_driver_name) ; + EPHYR_LOG ("leave:%d\n", is_ok) ; return is_ok ; } @@ -136,7 +148,7 @@ ephyrDRICreateContext (int a_screen, &v, a_returned_ctxt_id, a_hw_ctxt) ; - EPHYR_LOG ("leave\n") ; + EPHYR_LOG ("leave:%d\n", is_ok) ; return is_ok ; } @@ -149,7 +161,7 @@ ephyrDRIDestroyContext (int a_screen, EPHYR_LOG ("enter\n") ; is_ok = XF86DRIDestroyContext (dpy, a_screen, a_context_id) ; - EPHYR_LOG ("leave\n") ; + EPHYR_LOG ("leave:%d\n", is_ok) ; return is_ok ; } @@ -212,7 +224,7 @@ ephyrDRIGetDeviceInfo (int a_screen, is_ok = XF86DRIGetDeviceInfo (dpy, a_screen, a_frame_buffer, a_fb_origin, a_fb_size, a_fb_stride, a_dev_private_size, a_dev_private) ; - EPHYR_LOG ("leave\n") ; + EPHYR_LOG ("leave:%d\n", is_ok) ; return is_ok ; } #endif /*EPHYR_DRI*/ From 8c78df0ea36abc7d46c4f59670289f4280f75507 Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Thu, 30 Aug 2007 22:31:47 +0200 Subject: [PATCH 28/44] Xserver: fix potential crash * dix/extension.c: (AddExtensionAlias): don't crash when failed to add extension alias. --- dix/extension.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dix/extension.c b/dix/extension.c index 186574d76..4c0c3d236 100644 --- a/dix/extension.c +++ b/dix/extension.c @@ -184,6 +184,8 @@ _X_EXPORT Bool AddExtensionAlias(char *alias, ExtensionEntry *ext) char *name; char **aliases; + if (!ext) + return FALSE ; aliases = (char **)xrealloc(ext->aliases, (ext->num_aliases + 1) * sizeof(char *)); if (!aliases) From 4dd4be99df38b70d43b02d9cb19e09e0ed94462b Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Thu, 30 Aug 2007 23:54:49 +0200 Subject: [PATCH 29/44] Xephyr: Make glxinfo work on the ATI R200 free driver. * hw/kdrive/ephyr/ephyr.c: (EphyrDuplicateVisual): when duplicating the visual, copy the color component masks and the class from the hostX (EphyrMirrorHostVisuals): don't mix blue and green mask. * hw/kdrive/ephyr/ephyrdri.c: add more logs. (ephyrDRICreateDrawable): actually implement this. for the moment it creates a DRI drawable for the hostX window, no matter what drawable this call was issued for. (ephyrDRIGetDrawableInfo): actually implemented this. for the moment the drawable info queried for its attrs is the Xephyr main main window. * hw/kdrive/ephyr/ephyrdriext.c: (ProcXF86DRIGetDrawableInfo): properly hook this dispatch function to the ephyrDRIGetDrawableInfo() function. * hw/kdrive/ephyr/ephyrglxext.c: add a bunch of GLX implementation hooks here. Hijack some of the xserver GLX hooks with them. Still need to properly support byteswapped clients though. * hw/kdrive/ephyr/ephyrhostglx.c,h: actually implemented the protocol level forwarding functions used by the GLX entr points in ephyrglxext.c. Here as well, there are a bunch of them, but we are far from having implemented all the GLX calls. * hw/kdrive/ephyr/hostx.c,h: (hostx_get_window_attributes): added this new entry point (hostx_allocate_resource_id_peer): added this to keep track of resource IDs peers: one member of the peer is in Xephyr, the other is in host X. (hostx_get_resource_id_peer): ditto. --- hw/kdrive/ephyr/ephyr.c | 6 +- hw/kdrive/ephyr/ephyrdri.c | 63 +++++-- hw/kdrive/ephyr/ephyrdri.h | 2 +- hw/kdrive/ephyr/ephyrdriext.c | 35 ++-- hw/kdrive/ephyr/ephyrglxext.c | 317 ++++++++++++++++++++++++++++++++- hw/kdrive/ephyr/ephyrhostglx.c | 284 ++++++++++++++++++++++++++++- hw/kdrive/ephyr/ephyrhostglx.h | 25 +++ hw/kdrive/ephyr/hostx.c | 93 ++++++++++ hw/kdrive/ephyr/hostx.h | 16 ++ 9 files changed, 801 insertions(+), 40 deletions(-) diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c index df91f83fb..97eac51d9 100644 --- a/hw/kdrive/ephyr/ephyr.c +++ b/hw/kdrive/ephyr/ephyr.c @@ -1095,6 +1095,10 @@ EphyrDuplicateVisual (unsigned int a_screen, /*copy the visual found*/ memcpy (&new_visual, &screen->visuals[i], sizeof (new_visual)) ; new_visual.vid = a_new_id ; + new_visual.class = a_class ; + new_visual.redMask = a_red_mask ; + new_visual.greenMask = a_green_mask ; + new_visual.blueMask = a_blue_mask ; found_visual = TRUE ; EPHYR_LOG ("found a visual that matches visual id: %d\n", a_new_id) ; @@ -1195,8 +1199,8 @@ EphyrMirrorHostVisuals (void) visuals[i].bits_per_rgb, visuals[i].colormap_size, visuals[i].red_mask, - visuals[i].blue_mask, visuals[i].green_mask, + visuals[i].blue_mask, visuals[i].visualid)) { EPHYR_LOG_ERROR ("failed to duplicate host visual %d\n", (int)visuals[i].visualid) ; diff --git a/hw/kdrive/ephyr/ephyrdri.c b/hw/kdrive/ephyr/ephyrdri.c index 54ad2c0b6..95ace7c25 100644 --- a/hw/kdrive/ephyr/ephyrdri.c +++ b/hw/kdrive/ephyr/ephyrdri.c @@ -40,6 +40,8 @@ #include "ephyrdri.h" #define _HAVE_XALLOC_DECLS #include "ephyrlog.h" +#include "dixstruct.h" +#include "pixmapstr.h" #ifndef TRUE #define TRUE 1 @@ -55,9 +57,10 @@ ephyrDRIQueryDirectRenderingCapable (int a_screen, Bool *a_is_capable) Display *dpy=hostx_get_display () ; Bool is_ok=FALSE ; + EPHYR_RETURN_VAL_IF_FAIL (a_is_capable, FALSE) ; EPHYR_LOG ("enter\n") ; is_ok = XF86DRIQueryDirectRenderingCapable (dpy, a_screen, a_is_capable) ; - EPHYR_LOG ("leave\n") ; + EPHYR_LOG ("leave. is_capable:%d, is_ok=%d\n", *a_is_capable, is_ok) ; return is_ok ; } @@ -70,9 +73,16 @@ ephyrDRIOpenConnection (int a_screen, Display *dpy = hostx_get_display () ; Bool is_ok=FALSE ; - EPHYR_LOG ("enter\n") ; + EPHYR_RETURN_VAL_IF_FAIL (a_bus_id_string, FALSE) ; + EPHYR_LOG ("enter. screen:%d\n", a_screen) ; is_ok = XF86DRIOpenConnection (dpy, a_screen, a_sarea, a_bus_id_string) ; - EPHYR_LOG ("leave\n") ; + if (*a_bus_id_string) { + EPHYR_LOG ("leave. bus_id_string:%s, is_ok:%d\n", + *a_bus_id_string, is_ok) ; + } else { + EPHYR_LOG ("leave. bus_id_string:null, is_ok:%d\n", + is_ok) ; + } return is_ok ; } @@ -84,7 +94,7 @@ ephyrDRIAuthConnection (int a_screen, drm_magic_t a_magic) EPHYR_LOG ("enter\n") ; is_ok = XF86DRIAuthConnection (dpy, a_screen, a_magic) ; - EPHYR_LOG ("leave\n") ; + EPHYR_LOG ("leave. is_ok:%d\n", is_ok) ; return is_ok ; } @@ -140,7 +150,7 @@ ephyrDRICreateContext (int a_screen, Bool is_ok=FALSE ; Visual v; - EPHYR_LOG ("enter\n") ; + EPHYR_LOG ("enter. screen:%d, visual:%d\n", a_screen, a_visual_id) ; memset (&v, 0, sizeof (v)) ; v.visualid = a_visual_id ; is_ok = XF86DRICreateContext (dpy, @@ -170,10 +180,14 @@ ephyrDRICreateDrawable (int a_screen, int a_drawable, drm_drawable_t *a_hw_drawable) { + Bool is_ok=FALSE; + Display *dpy=hostx_get_display () ; + int host_win=hostx_get_window () ; + EPHYR_LOG ("enter\n") ; - EPHYR_LOG_ERROR ("not implemented yet\n") ; - EPHYR_LOG ("leave\n") ; - return FALSE ; + is_ok = XF86DRICreateDrawable (dpy, a_screen, host_win, a_hw_drawable) ; + EPHYR_LOG ("leave. is_ok:%d\n", is_ok) ; + return is_ok ; } Bool @@ -187,7 +201,7 @@ ephyrDRIDestroyDrawable (int a_screen, int a_drawable) Bool ephyrDRIGetDrawableInfo (int a_screen, - int a_drawable, + void *a_drawable, unsigned int *a_index, unsigned int *a_stamp, int *a_x, @@ -198,13 +212,38 @@ ephyrDRIGetDrawableInfo (int a_screen, drm_clip_rect_t **a_clip_rects, int *a_back_x, int *a_back_y, - int *num_back_clip_rects, + int *a_num_back_clip_rects, drm_clip_rect_t **a_back_clip_rects) { + Bool is_ok=FALSE; + DrawablePtr drawable = a_drawable ; + EphyrHostWindowAttributes attrs ; + + EPHYR_RETURN_VAL_IF_FAIL (drawable && a_x && a_y && a_w && a_h + && a_num_clip_rects, + FALSE) ; + EPHYR_LOG ("enter\n") ; - EPHYR_LOG_ERROR ("not implemented yet\n") ; + memset (&attrs, 0, sizeof (attrs)) ; + if (!hostx_get_window_attributes (hostx_get_window (), &attrs)) { + EPHYR_LOG_ERROR ("failed to query host window attributes\n") ; + goto out; + } + *a_x = drawable->x + attrs.x; + *a_y = drawable->y + attrs.y; + *a_w = drawable->width + attrs.width ; + *a_h = drawable->height + attrs.height ; + *a_num_clip_rects = 0 ; + *a_clip_rects = NULL ; + *a_back_x = 0; + *a_back_y = 0 ; + *a_num_back_clip_rects = 0 ; + *a_back_clip_rects = NULL ; + + is_ok = TRUE ; +out: EPHYR_LOG ("leave\n") ; - return FALSE ; + return is_ok ; } Bool diff --git a/hw/kdrive/ephyr/ephyrdri.h b/hw/kdrive/ephyr/ephyrdri.h index d77467f99..ffbbb8e83 100644 --- a/hw/kdrive/ephyr/ephyrdri.h +++ b/hw/kdrive/ephyr/ephyrdri.h @@ -51,7 +51,7 @@ Bool ephyrDRICreateDrawable (int a_screen, drm_drawable_t *a_hw_drawable) ; Bool ephyrDRIDestroyDrawable (int a_screen, int a_drawable) ; Bool ephyrDRIGetDrawableInfo (int a_screen, - int a_drawable, + void* /*DrawablePtr*/ a_drawable, unsigned int *a_index, unsigned int *a_stamp, int *a_x, diff --git a/hw/kdrive/ephyr/ephyrdriext.c b/hw/kdrive/ephyr/ephyrdriext.c index ac68054a3..d54da2164 100644 --- a/hw/kdrive/ephyr/ephyrdriext.c +++ b/hw/kdrive/ephyr/ephyrdriext.c @@ -447,11 +447,10 @@ static int ProcXF86DRIGetDrawableInfo (register ClientPtr client) { xXF86DRIGetDrawableInfoReply rep; - DrawablePtr pDrawable; - int X, Y, W, H; + DrawablePtr drawable; + int X, Y, W, H, backX, backY, rc; drm_clip_rect_t * pClipRects, *pClippedRects; drm_clip_rect_t * pBackClipRects; - int backX, backY, rc; EPHYR_LOG ("enter\n") ; REQUEST(xXF86DRIGetDrawableInfoReq); @@ -469,25 +468,25 @@ ProcXF86DRIGetDrawableInfo (register ClientPtr client) * We must properly do the mapping * between xephyr drawable and the host drawable */ - rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, - DixReadAccess); + rc = dixLookupDrawable(&drawable, stuff->drawable, client, 0, + DixReadAccess); if (rc != Success) return rc; if (!ephyrDRIGetDrawableInfo (stuff->screen, - 0 /*should be the drawable in hostx*/, - (unsigned int*)&rep.drawableTableIndex, - (unsigned int*)&rep.drawableTableStamp, - (int*)&X, - (int*)&Y, - (int*)&W, - (int*)&H, - (int*)&rep.numClipRects, - &pClipRects, - &backX, - &backY, - (int*)&rep.numBackClipRects, - &pBackClipRects)) { + drawable/*should be the drawable in hostx*/, + (unsigned int*)&rep.drawableTableIndex, + (unsigned int*)&rep.drawableTableStamp, + (int*)&X, + (int*)&Y, + (int*)&W, + (int*)&H, + (int*)&rep.numClipRects, + &pClipRects, + &backX, + &backY, + (int*)&rep.numBackClipRects, + &pBackClipRects)) { return BadValue; } diff --git a/hw/kdrive/ephyr/ephyrglxext.c b/hw/kdrive/ephyr/ephyrglxext.c index c4e5ba4d4..fbac6aa9a 100644 --- a/hw/kdrive/ephyr/ephyrglxext.c +++ b/hw/kdrive/ephyr/ephyrglxext.c @@ -37,7 +37,9 @@ #include #include "GL/glx/glxserver.h" #include "GL/glx/indirect_table.h" +#include "GL/glx/indirect_util.h" #include "GL/glx/unpack.h" +#include "hostx.h" #ifdef XEPHYR_DRI @@ -61,6 +63,18 @@ int ephyrGLXQueryServerString(__GLXclientState *a_cl, GLbyte *a_pc) ; int ephyrGLXQueryServerStringSwap(__GLXclientState *a_cl, GLbyte *a_pc) ; int ephyrGLXGetFBConfigsSGIX (__GLXclientState *a_cl, GLbyte *a_pc); int ephyrGLXGetFBConfigsSGIXSwap (__GLXclientState *a_cl, GLbyte *a_pc); +int ephyrGLXCreateContext (__GLXclientState *a_cl, GLbyte *a_pc); +int ephyrGLXCreateContextSwap (__GLXclientState *a_cl, GLbyte *a_pc); +int ephyrGLXDestroyContext (__GLXclientState *a_cl, GLbyte *a_pc) ; +int ephyrGLXDestroyContextSwap (__GLXclientState *a_cl, GLbyte *a_pc) ; +int ephyrGLXMakeCurrent (__GLXclientState *a_cl, GLbyte *a_pc) ; +int ephyrGLXMakeCurrentSwap (__GLXclientState *a_cl, GLbyte *a_pc) ; +int ephyrGLXGetString (__GLXclientState *a_cl, GLbyte *a_pc) ; +int ephyrGLXGetStringSwap (__GLXclientState *a_cl, GLbyte *a_pc) ; +int ephyrGLXGetIntegerv (__GLXclientState *a_cl, GLbyte *a_pc) ; +int ephyrGLXGetIntegervSwap (__GLXclientState *a_cl, GLbyte *a_pc) ; +int ephyrGLXIsDirect (__GLXclientState *a_cl, GLbyte *a_pc) ; +int ephyrGLXIsDirectSwap (__GLXclientState *a_cl, GLbyte *a_pc) ; Bool ephyrHijackGLXExtension (void) @@ -83,7 +97,6 @@ ephyrHijackGLXExtension (void) dispatch_functions[X_GLXGetVisualConfigs][0] = ephyrGLXGetVisualConfigs ; dispatch_functions[X_GLXGetVisualConfigs][1] = ephyrGLXGetVisualConfigsSwap ; - dispatch_functions[X_GLXClientInfo][0] = ephyrGLXClientInfo ; dispatch_functions[X_GLXClientInfo][1] = ephyrGLXClientInfoSwap ; @@ -91,6 +104,24 @@ ephyrHijackGLXExtension (void) dispatch_functions[X_GLXQueryServerString][1] = ephyrGLXQueryServerStringSwap ; + dispatch_functions[X_GLXCreateContext][0] = ephyrGLXCreateContext ; + dispatch_functions[X_GLXCreateContext][1] = ephyrGLXCreateContextSwap ; + + dispatch_functions[X_GLXDestroyContext][0] = ephyrGLXDestroyContext ; + dispatch_functions[X_GLXDestroyContext][1] = ephyrGLXDestroyContextSwap ; + + dispatch_functions[X_GLXMakeCurrent][0] = ephyrGLXMakeCurrent ; + dispatch_functions[X_GLXMakeCurrent][1] = ephyrGLXMakeCurrentSwap ; + + dispatch_functions[X_GLXIsDirect][0] = ephyrGLXIsDirect ; + dispatch_functions[X_GLXIsDirect][1] = ephyrGLXIsDirectSwap ; + + dispatch_functions[73][0] = ephyrGLXGetString ; + dispatch_functions[73][1] = ephyrGLXGetStringSwap ; + + dispatch_functions[61][0] = ephyrGLXGetIntegerv ; + dispatch_functions[61][1] = ephyrGLXGetIntegervSwap ; + /* * hijack some vendor priv entry point dispatch functions */ @@ -332,6 +363,7 @@ ephyrGLXQueryServerString(__GLXclientState *a_cl, GLbyte *a_pc) EPHYR_LOG ("enter\n") ; if (!ephyrHostGLXGetStringFromServer (req->screen, req->name, + EPHYR_HOST_GLX_QueryServerString, &server_string)) { EPHYR_LOG_ERROR ("failed to query string from host\n") ; goto out ; @@ -377,5 +409,288 @@ ephyrGLXGetFBConfigsSGIXSwap (__GLXclientState *a_cl, GLbyte *a_pc) return ephyrGLXGetFBConfigsSGIXReal (a_cl, a_pc, TRUE) ; } +static int +ephyrGLXCreateContextReal (xGLXCreateContextReq *a_req, Bool a_do_swap) +{ + int res=BadImplementation; + EphyrHostWindowAttributes host_w_attrs ; + __GLX_DECLARE_SWAP_VARIABLES; + + EPHYR_RETURN_VAL_IF_FAIL (a_req, BadValue) ; + EPHYR_LOG ("enter\n") ; + + if (a_do_swap) { + __GLX_SWAP_SHORT(&a_req->length); + __GLX_SWAP_INT(&a_req->context); + __GLX_SWAP_INT(&a_req->visual); + __GLX_SWAP_INT(&a_req->screen); + __GLX_SWAP_INT(&a_req->shareList); + } + + EPHYR_LOG ("context creation requested. localid:%d, " + "screen:%d, visual:%d, direct:%d\n", + (int)a_req->context, (int)a_req->screen, + (int)a_req->visual, (int)a_req->isDirect) ; + + memset (&host_w_attrs, 0, sizeof (host_w_attrs)) ; + if (!hostx_get_window_attributes (hostx_get_window (), &host_w_attrs)) { + EPHYR_LOG_ERROR ("failed to get host window attrs\n") ; + goto out ; + } + + EPHYR_LOG ("host window visual id: %d\n", host_w_attrs.visualid) ; + + if (!ephyrHostGLXCreateContext (a_req->screen, + host_w_attrs.visualid, + a_req->context, + a_req->shareList, + a_req->isDirect)) { + EPHYR_LOG_ERROR ("ephyrHostGLXCreateContext() failed\n") ; + goto out ; + } + res = Success; +out: + EPHYR_LOG ("leave\n") ; + return res ; +} + +int +ephyrGLXCreateContext (__GLXclientState *cl, GLbyte *pc) +{ + xGLXCreateContextReq *req = (xGLXCreateContextReq *) pc; + + return ephyrGLXCreateContextReal (req, FALSE) ; +} + +int ephyrGLXCreateContextSwap (__GLXclientState *cl, GLbyte *pc) +{ + xGLXCreateContextReq *req = (xGLXCreateContextReq *) pc; + return ephyrGLXCreateContextReal (req, TRUE) ; +} + +static int +ephyrGLXDestroyContextReal (__GLXclientState *a_cl, + GLbyte *a_pc, + Bool a_do_swap) +{ + int res=BadImplementation; + ClientPtr client = a_cl->client; + xGLXDestroyContextReq *req = (xGLXDestroyContextReq *) a_pc; + + EPHYR_LOG ("enter. id:%d\n", (int)req->context) ; + if (!ephyrHostDestroyContext (req->context)) { + EPHYR_LOG_ERROR ("ephyrHostDestroyContext() failed\n") ; + client->errorValue = req->context ; + goto out ; + } + res = Success ; + +out: + EPHYR_LOG ("leave\n") ; + return res ; +} + +int +ephyrGLXDestroyContext (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXDestroyContextReal (a_cl, a_pc, FALSE) ; +} + +int +ephyrGLXDestroyContextSwap (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXDestroyContextReal (a_cl, a_pc, TRUE) ; +} + +static int +ephyrGLXMakeCurrentReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap) +{ + int res=BadImplementation; + xGLXMakeCurrentReq *req = (xGLXMakeCurrentReq *) a_pc; + xGLXMakeCurrentReply reply ; + + EPHYR_LOG ("enter\n") ; + memset (&reply, 0, sizeof (reply)) ; + if (!ephyrHostGLXMakeCurrent (hostx_get_window (), + req->context, + req->oldContextTag, + (int*)&reply.contextTag)) { + EPHYR_LOG_ERROR ("ephyrHostGLXMakeCurrent() failed\n") ; + goto out; + } + reply.length = 0; + reply.type = X_Reply; + reply.sequenceNumber = a_cl->client->sequence; + if (a_do_swap) { + __GLX_DECLARE_SWAP_VARIABLES; + __GLX_SWAP_SHORT(&reply.sequenceNumber); + __GLX_SWAP_INT(&reply.length); + __GLX_SWAP_INT(&reply.contextTag); + } + WriteToClient(a_cl->client, sz_xGLXMakeCurrentReply, (char *)&reply); + + res = Success ; +out: + EPHYR_LOG ("leave\n") ; + return res ; +} + +int +ephyrGLXMakeCurrent (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXMakeCurrentReal (a_cl, a_pc, FALSE) ; +} + +int +ephyrGLXMakeCurrentSwap (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXMakeCurrentReal (a_cl, a_pc, TRUE) ; +} + +static int +ephyrGLXGetStringReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap) +{ + ClientPtr client=NULL ; + int context_tag=0, name=0, res=BadImplementation, length=0 ; + char *string=NULL; + __GLX_DECLARE_SWAP_VARIABLES; + + EPHYR_RETURN_VAL_IF_FAIL (a_cl && a_pc, BadValue) ; + + EPHYR_LOG ("enter\n") ; + + client = a_cl->client ; + + if (a_do_swap) { + __GLX_SWAP_INT (a_pc + 4); + __GLX_SWAP_INT (a_pc + __GLX_SINGLE_HDR_SIZE); + } + context_tag = __GLX_GET_SINGLE_CONTEXT_TAG (a_pc) ; + a_pc += __GLX_SINGLE_HDR_SIZE; + name = *(GLenum*)(a_pc + 0); + EPHYR_LOG ("context_tag:%d, name:%d\n", context_tag, name) ; + if (!ephyrHostGLXGetStringFromServer (context_tag, + name, + EPHYR_HOST_GLX_GetString, + &string)) { + EPHYR_LOG_ERROR ("failed to get string from server\n") ; + goto out ; + } + if (string) { + length = strlen (string) ; + EPHYR_LOG ("got string: string:%s\n", string) ; + } else { + EPHYR_LOG ("got string: string (null)\n") ; + } + __GLX_BEGIN_REPLY (length); + __GLX_PUT_SIZE (length); + __GLX_SEND_HEADER (); + if (a_do_swap) { + __GLX_SWAP_REPLY_SIZE (); + __GLX_SWAP_REPLY_HEADER (); + } + WriteToClient (client, length, (char *)string); + + res = Success ; +out: + EPHYR_LOG ("enter\n") ; + return res ; +} + +int +ephyrGLXGetString (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXGetStringReal (a_cl, a_pc, FALSE) ; +} + +int +ephyrGLXGetStringSwap (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXGetStringReal (a_cl, a_pc, TRUE) ; +} + +static int +ephyrGLXGetIntegervReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap) +{ + int res=BadImplementation; + xGLXSingleReq * const req = (xGLXSingleReq *) a_pc; + GLenum int_name ; + int value=0 ; + GLint answer_buf_room[200]; + GLint *buf=NULL ; + + a_pc += __GLX_SINGLE_HDR_SIZE; + + int_name = *(GLenum*) (a_pc+0) ; + if (!ephyrHostGetIntegerValue (req->contextTag, int_name, &value)) { + EPHYR_LOG_ERROR ("ephyrHostGetIntegerValue() failed\n") ; + goto out ; + } + buf = __glXGetAnswerBuffer (a_cl, sizeof (value), + answer_buf_room, + sizeof (answer_buf_room), + 4) ; + + if (!buf) { + EPHYR_LOG_ERROR ("failed to allocate reply buffer\n") ; + res = BadAlloc ; + goto out ; + } + __glXSendReply (a_cl->client, buf, 1, sizeof (value), GL_FALSE, 0) ; + res = Success ; +out: + return res ; +} + +int +ephyrGLXGetIntegerv (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXGetIntegervReal (a_cl, a_pc, FALSE) ; +} + +int +ephyrGLXGetIntegervSwap (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXGetIntegervReal (a_cl, a_pc, TRUE) ; +} + +static int +ephyrGLXIsDirectReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap) +{ + int res=BadImplementation; + ClientPtr client = a_cl->client; + xGLXIsDirectReq *req = (xGLXIsDirectReq *) a_pc; + xGLXIsDirectReply reply; + int is_direct=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_cl && a_pc, FALSE) ; + + memset (&reply, 0, sizeof (reply)) ; + if (!ephyrHostIsContextDirect (req->context, (int*)&is_direct)) { + EPHYR_LOG_ERROR ("ephyrHostIsContextDirect() failed\n") ; + goto out ; + } + reply.isDirect = is_direct ; + reply.length = 0; + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + WriteToClient(client, sz_xGLXIsDirectReply, (char *)&reply); + res = Success ; +out: + return res ; +} + +int +ephyrGLXIsDirect (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXIsDirectReal (a_cl, a_pc, FALSE) ; +} + +int +ephyrGLXIsDirectSwap (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXIsDirectReal (a_cl, a_pc, TRUE) ; +} + #endif /*XEPHYR_DRI*/ diff --git a/hw/kdrive/ephyr/ephyrhostglx.c b/hw/kdrive/ephyr/ephyrhostglx.c index 83e06a85b..843a0e523 100644 --- a/hw/kdrive/ephyr/ephyrhostglx.c +++ b/hw/kdrive/ephyr/ephyrhostglx.c @@ -36,10 +36,10 @@ #include #include #include -#include "hostx.h" #include "ephyrhostglx.h" #define _HAVE_XALLOC_DECLS #include "ephyrlog.h" +#include "hostx.h" #ifdef XEPHYR_DRI enum VisualConfRequestType { @@ -107,6 +107,7 @@ out: * the real protocol packets used to request a string from the server have * an identical binary layout. The only difference between them is the * meaning of the \c for_whom field and the value of the \c glxCode. + * (this has been copied from the mesa source code) */ typedef struct GLXGenericGetString { CARD8 reqType; @@ -124,20 +125,33 @@ typedef struct GLXGenericGetString { Bool ephyrHostGLXGetStringFromServer (int a_screen_number, int a_string_name, + enum EphyrHostGLXGetStringOps a_op, char **a_string) { + Bool is_ok=FALSE ; Display *dpy = hostx_get_display () ; xGLXGenericGetStringReq *req=NULL; xGLXSingleReply reply; - int length=0, numbytes=0, major_opcode=0; + int length=0, numbytes=0, major_opcode=0, get_string_op=0; EPHYR_RETURN_VAL_IF_FAIL (dpy && a_string, FALSE) ; EPHYR_LOG ("enter\n") ; + switch (a_op) { + case EPHYR_HOST_GLX_QueryServerString: + get_string_op = X_GLXQueryServerString; + break ; + case EPHYR_HOST_GLX_GetString: + get_string_op = X_GLsop_GetString; + break ; + default: + EPHYR_LOG_ERROR ("unknown EphyrHostGLXGetStringOp:%d\n", a_op) ; + goto out ; + } if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) { EPHYR_LOG_ERROR ("failed to get major opcode\n") ; - return FALSE ; + goto out ; } EPHYR_LOG ("major opcode: %d\n", major_opcode) ; @@ -150,7 +164,7 @@ ephyrHostGLXGetStringFromServer (int a_screen_number, */ GetReq (GLXGenericGetString, req); req->reqType = major_opcode; - req->glxCode = X_GLXQueryServerString; + req->glxCode = get_string_op; req->for_whom = a_screen_number; req->name = a_string_name; @@ -162,18 +176,21 @@ ephyrHostGLXGetStringFromServer (int a_screen_number, *a_string = (char *) Xmalloc( numbytes ); if (*a_string != NULL) { if (_XRead (dpy, *a_string, numbytes)) { + UnlockDisplay (dpy); + SyncHandle (); EPHYR_LOG_ERROR ("read failed\n") ; + goto out ; } length -= numbytes; } - _XEatData (dpy, length) ; - UnlockDisplay (dpy); SyncHandle (); + is_ok = TRUE ; +out: EPHYR_LOG ("leave\n") ; - return TRUE ; + return is_ok ; } static Bool @@ -378,5 +395,258 @@ out: return is_ok ; } +Bool +ephyrHostGLXCreateContext (int a_screen, + int a_visual_id, + int a_context_id, + int a_share_list_ctxt_id, + Bool a_direct) +{ + Bool is_ok = FALSE; + Display *dpy = hostx_get_display (); + int major_opcode=0, remote_context_id=0; + xGLXCreateContextReq *req; + + EPHYR_LOG ("enter. screen:%d, visual:%d, contextid:%d, direct:%d\n", + a_screen, a_visual_id, a_context_id, a_direct) ; + + if (!hostx_allocate_resource_id_peer (a_context_id, &remote_context_id)) { + EPHYR_LOG_ERROR ("failed to peer the context id %d host X", + remote_context_id) ; + goto out ; + } + + if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) { + EPHYR_LOG_ERROR ("failed to get major opcode\n") ; + goto out ; + } + + LockDisplay (dpy) ; + + /* Send the glXCreateContext request */ + GetReq(GLXCreateContext,req); + req->reqType = major_opcode; + req->glxCode = X_GLXCreateContext; + req->context = remote_context_id; + req->visual = a_visual_id; + req->screen = a_screen; + req->shareList = a_share_list_ctxt_id; + req->isDirect = a_direct; + + is_ok = TRUE ; + +out: + UnlockDisplay (dpy); + SyncHandle (); + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +Bool +ephyrHostDestroyContext (int a_ctxt_id) +{ + Bool is_ok=FALSE; + Display *dpy=hostx_get_display (); + int major_opcode=0, remote_ctxt_id=0 ; + xGLXDestroyContextReq *req=NULL; + + EPHYR_LOG ("enter:%d\n", a_ctxt_id) ; + + if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) { + EPHYR_LOG_ERROR ("failed to get major opcode\n") ; + goto out ; + } + if (!hostx_get_resource_id_peer (a_ctxt_id, &remote_ctxt_id)) { + EPHYR_LOG_ERROR ("failed to get remote glx ctxt id\n") ; + goto out ; + } + EPHYR_LOG ("host context id:%d\n", remote_ctxt_id) ; + + LockDisplay (dpy); + GetReq (GLXDestroyContext,req); + req->reqType = major_opcode; + req->glxCode = X_GLXDestroyContext; + req->context = remote_ctxt_id; + UnlockDisplay (dpy); + SyncHandle (); + + is_ok = TRUE ; + +out: + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +Bool +ephyrHostGLXMakeCurrent (int a_drawable, + int a_glx_ctxt_id, + int a_old_ctxt_tag, + int *a_ctxt_tag) +{ + Bool is_ok=FALSE ; + Display *dpy = hostx_get_display () ; + int32_t major_opcode=0 ; + int remote_glx_ctxt_id=0 ; + xGLXMakeCurrentReq *req; + xGLXMakeCurrentReply reply; + + EPHYR_RETURN_VAL_IF_FAIL (a_ctxt_tag, FALSE) ; + + EPHYR_LOG ("enter. drawable:%d, context:%d, oldtag:%d\n", + a_drawable, a_glx_ctxt_id, a_old_ctxt_tag) ; + + if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) { + EPHYR_LOG_ERROR ("failed to get major opcode\n") ; + goto out ; + } + if (!hostx_get_resource_id_peer (a_glx_ctxt_id, &remote_glx_ctxt_id)) { + EPHYR_LOG_ERROR ("failed to get remote glx ctxt id\n") ; + goto out ; + } + + LockDisplay (dpy); + + GetReq (GLXMakeCurrent,req); + req->reqType = major_opcode; + req->glxCode = X_GLXMakeCurrent; + req->drawable = a_drawable; + req->context = remote_glx_ctxt_id; + req->oldContextTag = a_old_ctxt_tag; + + memset (&reply, 0, sizeof (reply)) ; + if (!_XReply (dpy, (xReply*)&reply, 0, False)) { + EPHYR_LOG_ERROR ("failed to get reply from host\n") ; + goto out ; + } + *a_ctxt_tag = reply.contextTag ; + is_ok = TRUE ; + +out: + UnlockDisplay (dpy); + SyncHandle (); + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +#define X_GLXSingle 0 + +#define __EPHYR_GLX_SINGLE_PUT_CHAR(offset,a) \ + *((INT8 *) (pc + offset)) = a + +#define EPHYR_GLX_SINGLE_PUT_SHORT(offset,a) \ + *((INT16 *) (pc + offset)) = a + +#define EPHYR_GLX_SINGLE_PUT_LONG(offset,a) \ + *((INT32 *) (pc + offset)) = a + +#define EPHYR_GLX_SINGLE_PUT_FLOAT(offset,a) \ + *((FLOAT32 *) (pc + offset)) = a + +#define EPHYR_GLX_SINGLE_READ_XREPLY() \ + (void) _XReply(dpy, (xReply*) &reply, 0, False) + +#define EPHYR_GLX_SINGLE_GET_RETVAL(a,cast) \ + a = (cast) reply.retval + +#define EPHYR_GLX_SINGLE_GET_SIZE(a) \ + a = (GLint) reply.size + +#define EPHYR_GLX_SINGLE_GET_CHAR(p) \ + *p = *(GLbyte *)&reply.pad3; + +#define EPHYR_GLX_SINGLE_GET_SHORT(p) \ + *p = *(GLshort *)&reply.pad3; + +#define EPHYR_GLX_SINGLE_GET_LONG(p) \ + *p = *(GLint *)&reply.pad3; + +#define EPHYR_GLX_SINGLE_GET_FLOAT(p) \ + *p = *(GLfloat *)&reply.pad3; + +Bool +ephyrHostGetIntegerValue (int a_current_context_tag, int a_int, int *a_val) +{ + Bool is_ok=FALSE; + Display *dpy = hostx_get_display () ; + int major_opcode=0, size=0; + xGLXSingleReq *req=NULL; + xGLXSingleReply reply; + unsigned char* pc=NULL ; + + EPHYR_RETURN_VAL_IF_FAIL (a_val, FALSE) ; + + EPHYR_LOG ("enter\n") ; + if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) { + EPHYR_LOG_ERROR ("failed to get major opcode\n") ; + goto out ; + } + LockDisplay (dpy) ; + GetReqExtra (GLXSingle, 4, req) ; + req->reqType = major_opcode ; + req->glxCode = X_GLsop_GetIntegerv ; + req->contextTag = a_current_context_tag; + pc = ((unsigned char *)(req) + sz_xGLXSingleReq) ; + EPHYR_GLX_SINGLE_PUT_LONG (0, a_int) ; + EPHYR_GLX_SINGLE_READ_XREPLY () ; + EPHYR_GLX_SINGLE_GET_SIZE (size) ; + if (!size) { + UnlockDisplay (dpy) ; + SyncHandle () ; + EPHYR_LOG_ERROR ("X_GLsop_GetIngerv failed\n") ; + goto out ; + } + EPHYR_GLX_SINGLE_GET_LONG (a_val) ; + UnlockDisplay (dpy) ; + SyncHandle () ; + is_ok = TRUE ; + +out: + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +Bool +ephyrHostIsContextDirect (int a_ctxt_id, + int *a_is_direct) +{ + Bool is_ok=FALSE; + Display *dpy = hostx_get_display () ; + xGLXIsDirectReq *req=NULL; + xGLXIsDirectReply reply; + int major_opcode=0, remote_glx_ctxt_id=0; + + EPHYR_LOG ("enter\n") ; + if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) { + EPHYR_LOG_ERROR ("failed to get major opcode\n") ; + goto out ; + } + if (!hostx_get_resource_id_peer (a_ctxt_id, &remote_glx_ctxt_id)) { + EPHYR_LOG_ERROR ("failed to get remote glx ctxt id\n") ; + goto out ; + } + memset (&reply, 0, sizeof (reply)) ; + + /* Send the glXIsDirect request */ + LockDisplay (dpy); + GetReq (GLXIsDirect,req); + req->reqType = major_opcode; + req->glxCode = X_GLXIsDirect; + req->context = remote_glx_ctxt_id; + if (!_XReply (dpy, (xReply*) &reply, 0, False)) { + EPHYR_LOG_ERROR ("fail in reading reply from host\n") ; + UnlockDisplay (dpy); + SyncHandle (); + goto out ; + } + UnlockDisplay (dpy); + SyncHandle (); + *a_is_direct = reply.isDirect ; + is_ok = TRUE ; + +out: + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + #endif /*XEPHYR_DRI*/ diff --git a/hw/kdrive/ephyr/ephyrhostglx.h b/hw/kdrive/ephyr/ephyrhostglx.h index 1040f6c61..6db362f30 100644 --- a/hw/kdrive/ephyr/ephyrhostglx.h +++ b/hw/kdrive/ephyr/ephyrhostglx.h @@ -28,9 +28,16 @@ #ifndef __EPHYRHOSTGLX_H__ #define __EPHYRHOSTGLX_H__ +enum EphyrHostGLXGetStringOps { + EPHYR_HOST_GLX_UNDEF, + EPHYR_HOST_GLX_QueryServerString, + EPHYR_HOST_GLX_GetString, +}; + Bool ephyrHostGLXQueryVersion (int *a_maj, int *a_min) ; Bool ephyrHostGLXGetStringFromServer (int a_screen_number, int a_string_name, + enum EphyrHostGLXGetStringOps a_op, char **a_string) ; Bool ephyrHostGLXGetVisualConfigs (int a_screen, int32_t *a_num_visuals, @@ -46,6 +53,24 @@ ephyrHostGLXVendorPrivGetFBConfigsSGIX (int a_screen, Bool ephyrHostGLXGetMajorOpcode (int32_t *a_opcode) ; Bool ephyrHostGLXSendClientInfo (int32_t a_major, int32_t a_minor, const char* a_extension_list) ; +Bool ephyrHostGLXCreateContext (int a_screen, + int a_visual_id, + int a_context_id, + int a_shared_list_ctx_id, + Bool a_direct) ; + +Bool ephyrHostDestroyContext (int a_ctxt_id) ; + +Bool ephyrHostGLXMakeCurrent (int a_drawable, int a_glx_ctxt_id, + int a_olg_ctxt_tag, int *a_ctxt_tag) ; + +Bool ephyrHostGetIntegerValue (int a_current_context_tag, + int a_int, + int *a_val) ; + +Bool ephyrHostIsContextDirect (int a_ctxt_id, + int *a_is_direct) ; + #endif /*__EPHYRHOSTGLX_H__*/ diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c index 17712cd5b..51fda478f 100644 --- a/hw/kdrive/ephyr/hostx.c +++ b/hw/kdrive/ephyr/hostx.c @@ -969,6 +969,27 @@ hostx_get_window(void) return HostX.win ; } +int +hostx_get_window_attributes (int a_window, EphyrHostWindowAttributes *a_attrs) +{ + XWindowAttributes attrs ; + + memset (&attrs, 0, sizeof (attrs)) ; + + if (!XGetWindowAttributes (hostx_get_display (), + a_window, + &attrs)) { + return FALSE ; + } + a_attrs->x = attrs.x ; + a_attrs->y = attrs.y ; + a_attrs->width = attrs.width ; + a_attrs->height = attrs.height ; + if (attrs.visual) + a_attrs->visualid = attrs.visual->visualid ; + return TRUE ; +} + int hostx_get_extension_info (const char *a_ext_name, int *a_major_opcode, @@ -1039,3 +1060,75 @@ out: } +typedef struct { + int is_valid ; + int local_id ; + int remote_id ; +} ResourcePair ; + +#define RESOURCE_PEERS_SIZE 1024*10 +static ResourcePair resource_peers[RESOURCE_PEERS_SIZE] ; + +int +hostx_allocate_resource_id_peer (int a_local_resource_id, + int *a_remote_resource_id) +{ + int i=0 ; + ResourcePair *peer=NULL ; + Display *dpy=hostx_get_display (); + + /* + * first make sure a resource peer + * does not exist already for + * a_local_resource_id + */ + for (i=0; iremote_id = XAllocID (dpy); + peer->local_id = a_local_resource_id ; + peer->is_valid = TRUE ; + } + } + if (peer) { + *a_remote_resource_id = peer->remote_id ; + return TRUE ; + } + return FALSE ; +} + +int +hostx_get_resource_id_peer (int a_local_resource_id, + int *a_remote_resource_id) +{ + int i=0 ; + ResourcePair *peer=NULL ; + for (i=0; iremote_id ; + return TRUE ; + } + return FALSE ; +} + diff --git a/hw/kdrive/ephyr/hostx.h b/hw/kdrive/ephyr/hostx.h index a44b52030..51a5f6832 100644 --- a/hw/kdrive/ephyr/hostx.h +++ b/hw/kdrive/ephyr/hostx.h @@ -104,6 +104,12 @@ typedef struct { int bits_per_rgb; } EphyrHostVisualInfo; +typedef struct { + int x, y; + int width, height ; + int visualid ; +} EphyrHostWindowAttributes; + int hostx_want_screen_size(EphyrScreenInfo screen, int *width, int *height); @@ -190,6 +196,9 @@ hostx_get_display(void) ; int hostx_get_window(void) ; +int +hostx_get_window_attributes (int a_window, EphyrHostWindowAttributes *a_attr) ; + int hostx_get_extension_info (const char *a_ext_name, int *a_major_opcode, @@ -198,4 +207,11 @@ hostx_get_extension_info (const char *a_ext_name, int hostx_get_visuals_info (EphyrHostVisualInfo **a_visuals, int *a_num_entries) ; +int +hostx_allocate_resource_id_peer (int a_local_resource_id, + int *a_remote_resource_id) ; +int +hostx_get_resource_id_peer (int a_local_resource_id, + int *a_remote_resource_id) ; + #endif From 9e192d2118246ad715e23cf5626a038274eb1eaa Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Fri, 31 Aug 2007 14:43:39 +0200 Subject: [PATCH 30/44] Xephyr: better error handling in GLX forwarding * hw/kdrive/ephyr/ephyrglxext.c: fixed various logging functions (ephyrGLXGetStringReal): make sure all the string is sent to clients including the ending zero. * hw/kdrive/ephyr/ephyrhostglx.c: (ephyrHostGLXGetStringFromServer): better error handling. (ephyrHostGLXSendClientInfo): ditto. (ephyrHostGLXMakeCurrent): ditto --- hw/kdrive/ephyr/ephyrglxext.c | 16 ++++++++++---- hw/kdrive/ephyr/ephyrhostglx.c | 40 +++++++++++++++++++++------------- 2 files changed, 37 insertions(+), 19 deletions(-) diff --git a/hw/kdrive/ephyr/ephyrglxext.c b/hw/kdrive/ephyr/ephyrglxext.c index fbac6aa9a..27b2a2dc3 100644 --- a/hw/kdrive/ephyr/ephyrglxext.c +++ b/hw/kdrive/ephyr/ephyrglxext.c @@ -368,7 +368,7 @@ ephyrGLXQueryServerString(__GLXclientState *a_cl, GLbyte *a_pc) EPHYR_LOG_ERROR ("failed to query string from host\n") ; goto out ; } - EPHYR_LOG ("string: %s", server_string) ; + EPHYR_LOG ("string: %s\n", server_string) ; length= strlen (server_string) + 1; reply.type = X_Reply ; reply.sequenceNumber = client->sequence ; @@ -577,8 +577,8 @@ ephyrGLXGetStringReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap) goto out ; } if (string) { - length = strlen (string) ; - EPHYR_LOG ("got string: string:%s\n", string) ; + length = strlen (string) + 1; + EPHYR_LOG ("got string:'%s', size:%d\n", string, length) ; } else { EPHYR_LOG ("got string: string (null)\n") ; } @@ -593,7 +593,7 @@ ephyrGLXGetStringReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap) res = Success ; out: - EPHYR_LOG ("enter\n") ; + EPHYR_LOG ("leave\n") ; return res ; } @@ -619,6 +619,8 @@ ephyrGLXGetIntegervReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap) GLint answer_buf_room[200]; GLint *buf=NULL ; + EPHYR_LOG ("enter\n") ; + a_pc += __GLX_SINGLE_HDR_SIZE; int_name = *(GLenum*) (a_pc+0) ; @@ -638,7 +640,9 @@ ephyrGLXGetIntegervReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap) } __glXSendReply (a_cl->client, buf, 1, sizeof (value), GL_FALSE, 0) ; res = Success ; + out: + EPHYR_LOG ("leave\n") ; return res ; } @@ -665,6 +669,8 @@ ephyrGLXIsDirectReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap) EPHYR_RETURN_VAL_IF_FAIL (a_cl && a_pc, FALSE) ; + EPHYR_LOG ("enter\n") ; + memset (&reply, 0, sizeof (reply)) ; if (!ephyrHostIsContextDirect (req->context, (int*)&is_direct)) { EPHYR_LOG_ERROR ("ephyrHostIsContextDirect() failed\n") ; @@ -676,7 +682,9 @@ ephyrGLXIsDirectReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap) reply.sequenceNumber = client->sequence; WriteToClient(client, sz_xGLXIsDirectReply, (char *)&reply); res = Success ; + out: + EPHYR_LOG ("leave\n") ; return res ; } diff --git a/hw/kdrive/ephyr/ephyrhostglx.c b/hw/kdrive/ephyr/ephyrhostglx.c index 843a0e523..2bebfdf62 100644 --- a/hw/kdrive/ephyr/ephyrhostglx.c +++ b/hw/kdrive/ephyr/ephyrhostglx.c @@ -172,20 +172,26 @@ ephyrHostGLXGetStringFromServer (int a_screen_number, length = reply.length * 4; numbytes = reply.size; + EPHYR_LOG ("got a string of size:%d\n", numbytes) ; - *a_string = (char *) Xmalloc( numbytes ); - if (*a_string != NULL) { - if (_XRead (dpy, *a_string, numbytes)) { - UnlockDisplay (dpy); - SyncHandle (); - EPHYR_LOG_ERROR ("read failed\n") ; - goto out ; - } - length -= numbytes; + *a_string = (char *) Xmalloc (numbytes +1); + if (!a_string) { + EPHYR_LOG_ERROR ("allocation failed\n") ; + goto out; } + + memset (*a_string, 0, numbytes+1) ; + if (_XRead (dpy, *a_string, numbytes)) { + UnlockDisplay (dpy); + SyncHandle (); + EPHYR_LOG_ERROR ("read failed\n") ; + goto out ; + } + length -= numbytes; _XEatData (dpy, length) ; UnlockDisplay (dpy); SyncHandle (); + EPHYR_LOG ("string:'%s'\n", *a_string) ; is_ok = TRUE ; out: @@ -387,11 +393,12 @@ ephyrHostGLXSendClientInfo (int32_t a_major, int32_t a_minor, req->numbytes = size; Data (dpy, a_extension_list, size); + UnlockDisplay(dpy); + SyncHandle(); + is_ok=TRUE ; out: - UnlockDisplay(dpy); - SyncHandle(); return is_ok ; } @@ -433,11 +440,12 @@ ephyrHostGLXCreateContext (int a_screen, req->shareList = a_share_list_ctxt_id; req->isDirect = a_direct; + UnlockDisplay (dpy); + SyncHandle (); + is_ok = TRUE ; out: - UnlockDisplay (dpy); - SyncHandle (); EPHYR_LOG ("leave\n") ; return is_ok ; } @@ -516,14 +524,16 @@ ephyrHostGLXMakeCurrent (int a_drawable, memset (&reply, 0, sizeof (reply)) ; if (!_XReply (dpy, (xReply*)&reply, 0, False)) { EPHYR_LOG_ERROR ("failed to get reply from host\n") ; + UnlockDisplay (dpy); + SyncHandle (); goto out ; } + UnlockDisplay (dpy); + SyncHandle (); *a_ctxt_tag = reply.contextTag ; is_ok = TRUE ; out: - UnlockDisplay (dpy); - SyncHandle (); EPHYR_LOG ("leave\n") ; return is_ok ; } From a39b57d2f784f14e3198c8506f5eb865bacc2440 Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Fri, 31 Aug 2007 16:53:18 +0200 Subject: [PATCH 31/44] Xephyr: add more logging to GLX forwarding * hw/kdrive/ephyr/ephyrhostglx.c: added more logging. --- hw/kdrive/ephyr/ephyrhostglx.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/hw/kdrive/ephyr/ephyrhostglx.c b/hw/kdrive/ephyr/ephyrhostglx.c index 2bebfdf62..071a58154 100644 --- a/hw/kdrive/ephyr/ephyrhostglx.c +++ b/hw/kdrive/ephyr/ephyrhostglx.c @@ -143,6 +143,8 @@ ephyrHostGLXGetStringFromServer (int a_screen_number, break ; case EPHYR_HOST_GLX_GetString: get_string_op = X_GLsop_GetString; + EPHYR_LOG ("Going to glXGetString. strname:%#x, ctxttag:%d\n", + a_string_name, a_screen_number) ; break ; default: EPHYR_LOG_ERROR ("unknown EphyrHostGLXGetStringOp:%d\n", a_op) ; @@ -172,7 +174,7 @@ ephyrHostGLXGetStringFromServer (int a_screen_number, length = reply.length * 4; numbytes = reply.size; - EPHYR_LOG ("got a string of size:%d\n", numbytes) ; + EPHYR_LOG ("going to get a string of size:%d\n", numbytes) ; *a_string = (char *) Xmalloc (numbytes +1); if (!a_string) { @@ -191,7 +193,8 @@ ephyrHostGLXGetStringFromServer (int a_screen_number, _XEatData (dpy, length) ; UnlockDisplay (dpy); SyncHandle (); - EPHYR_LOG ("string:'%s'\n", *a_string) ; + EPHYR_LOG ("strname:%#x, strvalue:'%s', strlen:%d\n", + a_string_name, *a_string, numbytes) ; is_ok = TRUE ; out: @@ -531,6 +534,7 @@ ephyrHostGLXMakeCurrent (int a_drawable, UnlockDisplay (dpy); SyncHandle (); *a_ctxt_tag = reply.contextTag ; + EPHYR_LOG ("context tag:%d\n", *a_ctxt_tag) ; is_ok = TRUE ; out: From 6d1e44d3d53b451d466d43197be589d0ecc4b9f6 Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Tue, 4 Sep 2007 18:28:16 +0200 Subject: [PATCH 32/44] Xephyr: fix a host X hang. * hw/kdrive/ephyr/ephyrdri.c: (ephyrDRIGetDrawableInfo): quickly hook this into getting the drawable info from the host X server. For the time being, this only gets the drawable info of the Xephyr main window in the host. It should really get the info of a the peer drawable in the host X. So there should be a peer drawable to begin with. * hw/kdrive/ephyr/ephyrdriext.c: (ProcXF86DRIGetDrawableInfo): some cleanups. Properly get the the drawable info otherwise there is a host X hang. * hw/kdrive/ephyr/ephyrhostglx.c: do not (ephyrHostGLXQueryVersion): do not use C bindings of the glx protocol calls. Some of those actually access DRI context directly, resulting in the context having three clients. Instead all XF86DRI proto fowarding request should be coded by hand and only forward the protocol requests --- hw/kdrive/ephyr/ephyrdri.c | 32 +++++++++++++++++++++----------- hw/kdrive/ephyr/ephyrdriext.c | 9 +++++---- hw/kdrive/ephyr/ephyrhostglx.c | 4 ++++ 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/hw/kdrive/ephyr/ephyrdri.c b/hw/kdrive/ephyr/ephyrdri.c index 95ace7c25..3f470f8b0 100644 --- a/hw/kdrive/ephyr/ephyrdri.c +++ b/hw/kdrive/ephyr/ephyrdri.c @@ -216,6 +216,7 @@ ephyrDRIGetDrawableInfo (int a_screen, drm_clip_rect_t **a_back_clip_rects) { Bool is_ok=FALSE; + Display *dpy=hostx_get_display () ; DrawablePtr drawable = a_drawable ; EphyrHostWindowAttributes attrs ; @@ -229,20 +230,29 @@ ephyrDRIGetDrawableInfo (int a_screen, EPHYR_LOG_ERROR ("failed to query host window attributes\n") ; goto out; } - *a_x = drawable->x + attrs.x; - *a_y = drawable->y + attrs.y; - *a_w = drawable->width + attrs.width ; - *a_h = drawable->height + attrs.height ; - *a_num_clip_rects = 0 ; - *a_clip_rects = NULL ; - *a_back_x = 0; - *a_back_y = 0 ; - *a_num_back_clip_rects = 0 ; - *a_back_clip_rects = NULL ; + if (!XF86DRIGetDrawableInfo (dpy, a_screen, hostx_get_window (), + a_index, a_stamp, + a_x, a_y, + a_w, a_h, + a_num_clip_rects, a_clip_rects, + a_back_x, a_back_y, + a_num_back_clip_rects, + a_back_clip_rects)) { + EPHYR_LOG_ERROR ("XF86DRIGetDrawableInfo ()\n") ; + goto out ; + } + EPHYR_LOG ("host x,y,w,h: (%d,%d,%d,%d)\n", *a_x, *a_y, *a_w, *a_h) ; + *a_x += drawable->x ; + *a_y += drawable->y ; + *a_back_x = *a_x ; + *a_back_y = *a_y ; + *a_w = drawable->width; + *a_h = drawable->height; is_ok = TRUE ; out: - EPHYR_LOG ("leave\n") ; + EPHYR_LOG ("leave. index:%d, stamp:%d, x,y:(%d,%d), w,y:(%d,%d)\n", + *a_index, *a_stamp, *a_x, *a_y, *a_w, *a_h) ; return is_ok ; } diff --git a/hw/kdrive/ephyr/ephyrdriext.c b/hw/kdrive/ephyr/ephyrdriext.c index d54da2164..443fe9d57 100644 --- a/hw/kdrive/ephyr/ephyrdriext.c +++ b/hw/kdrive/ephyr/ephyrdriext.c @@ -446,13 +446,14 @@ ProcXF86DRIDestroyDrawable (register ClientPtr client) static int ProcXF86DRIGetDrawableInfo (register ClientPtr client) { - xXF86DRIGetDrawableInfoReply rep; + xXF86DRIGetDrawableInfoReply rep; DrawablePtr drawable; - int X, Y, W, H, backX, backY, rc; - drm_clip_rect_t * pClipRects, *pClippedRects; - drm_clip_rect_t * pBackClipRects; + int X=0, Y=0, W=0, H=0, backX=0, backY=0, rc=0; + drm_clip_rect_t *pClipRects=NULL, *pClippedRects=NULL; + drm_clip_rect_t *pBackClipRects=NULL; EPHYR_LOG ("enter\n") ; + memset (&rep, 0, sizeof (rep)) ; REQUEST(xXF86DRIGetDrawableInfoReq); REQUEST_SIZE_MATCH(xXF86DRIGetDrawableInfoReq); if (stuff->screen >= screenInfo.numScreens) { diff --git a/hw/kdrive/ephyr/ephyrhostglx.c b/hw/kdrive/ephyr/ephyrhostglx.c index 071a58154..21a109e64 100644 --- a/hw/kdrive/ephyr/ephyrhostglx.c +++ b/hw/kdrive/ephyr/ephyrhostglx.c @@ -89,10 +89,14 @@ ephyrHostGLXQueryVersion (int *a_major, int *a_minor) EPHYR_RETURN_VAL_IF_FAIL (a_major && a_minor, FALSE) ; EPHYR_LOG ("enter\n") ; + *a_major = 1 ; + *a_minor = 2 ; + /* if (!glXQueryVersion (dpy, a_major, a_minor)) { EPHYR_LOG_ERROR ("glxQueryVersion() failed\n") ; goto out ; } + */ is_ok = TRUE ; out: From cf58781eee7d91a3bbca701a2c4523a36f8e0abb Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Sat, 8 Sep 2007 00:33:59 +0200 Subject: [PATCH 33/44] Xephyr: make accelerated glxgears work in Xephyr * hw/kdrive/ephyr/ephyr.c: (ephyrInitialize): cleanup ephyrDRI extension init. remove functions that belongs in ephyrdriext.c . * hw/kdrive/ephyr/ephyrdri.c: (ephyrDRICreateDrawable): create the drawable on the host X peer window, not on the host xephyr main window. (ephyrDRIGetDrawableInfo): get drawable info of the host X peer window. * hw/kdrive/ephyr/ephyrdriext.c: make ephyr DRI extention wrap a bunch of screen ops so that it can update the host X peer window whenever DRI bound drawable are moved in Xephyr. Also code the building blocks of the management of the host X window peer. * hw/kdrive/ephyr/hostx.c,h: (hostx_create_window): added this new entry point (hostx_destroy_window): ditto ()hostx_set_window_geometry): ditto --- hw/kdrive/ephyr/ephyr.c | 174 +-------- hw/kdrive/ephyr/ephyrdri.c | 18 +- hw/kdrive/ephyr/ephyrdri.h | 2 +- hw/kdrive/ephyr/ephyrdriext.c | 697 ++++++++++++++++++++++++++++++++-- hw/kdrive/ephyr/ephyrvideo.c | 2 + hw/kdrive/ephyr/hostx.c | 83 ++++ hw/kdrive/ephyr/hostx.h | 15 + 7 files changed, 767 insertions(+), 224 deletions(-) diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c index 97eac51d9..63e0cb166 100644 --- a/hw/kdrive/ephyr/ephyr.c +++ b/hw/kdrive/ephyr/ephyr.c @@ -34,6 +34,7 @@ #ifdef XEPHYR_DRI #include "ephyrdri.h" +#include "ephyrdriext.h" #include "ephyrglxext.h" #include "ephyrproxyext.h" #endif /*XEPHYR_DRI*/ @@ -52,11 +53,6 @@ typedef struct _EphyrInputPrivate { Bool EphyrWantGrayScale = 0; -#ifdef XEPHYR_DRI -extern void ephyrDRIExtensionInit(void) ; -static Bool EphyrMirrorHostVisuals (void) ; -#endif - Bool ephyrInitialize (KdCardInfo *card, EphyrPriv *priv) { @@ -628,10 +624,9 @@ ephyrInitScreen (ScreenPtr pScreen) #endif /*XV*/ #ifdef XEPHYR_DRI - ephyrDRIExtensionInit () ; + ephyrDRIExtensionInit (pScreen) ; ephyrHijackGLXExtension () ; ephyrProxyExtensionInit ("ATIFGLRXDRI") ; - EphyrMirrorHostVisuals () ; #endif return TRUE; } @@ -1048,171 +1043,6 @@ EphyrKeyboardBell (KdKeyboardInfo *ki, int volume, int frequency, int duration) { } -/** - * Duplicates a visual of a_screen - * In screen a_screen, for depth a_depth, find a visual which - * bitsPerRGBValue and colormap size equal - * a_bits_per_rgb_values and a_colormap_entries. - * The ID of that duplicated visual is set to a_new_id. - * That duplicated visual is then added to the list of visuals - * of the screen. - */ -static Bool -EphyrDuplicateVisual (unsigned int a_screen, - short a_depth, - short a_class, - short a_bits_per_rgb_values, - short a_colormap_entries, - unsigned int a_red_mask, - unsigned int a_green_mask, - unsigned int a_blue_mask, - unsigned int a_new_id) -{ - Bool is_ok = FALSE, found_visual=FALSE, found_depth=FALSE ; - ScreenPtr screen=NULL ; - VisualRec new_visual, *new_visuals=NULL ; - int i=0 ; - - EPHYR_LOG ("enter\n") ; - if (a_screen > screenInfo.numScreens) { - EPHYR_LOG_ERROR ("bad screen number\n") ; - goto out; - } - memset (&new_visual, 0, sizeof (VisualRec)) ; - - /*get the screen pointed to by a_screen*/ - screen = screenInfo.screens[a_screen] ; - EPHYR_RETURN_VAL_IF_FAIL (screen, FALSE) ; - - /* - * In that screen, first look for an existing visual that has the - * same characteristics as those passed in parameter - * to this function and copy it. - */ - for (i=0; i < screen->numVisuals; i++) { - if (screen->visuals[i].bitsPerRGBValue == a_bits_per_rgb_values && - screen->visuals[i].ColormapEntries == a_colormap_entries ) { - /*copy the visual found*/ - memcpy (&new_visual, &screen->visuals[i], sizeof (new_visual)) ; - new_visual.vid = a_new_id ; - new_visual.class = a_class ; - new_visual.redMask = a_red_mask ; - new_visual.greenMask = a_green_mask ; - new_visual.blueMask = a_blue_mask ; - found_visual = TRUE ; - EPHYR_LOG ("found a visual that matches visual id: %d\n", - a_new_id) ; - break; - } - } - if (!found_visual) { - EPHYR_LOG ("did not find any visual matching %d\n", a_new_id) ; - goto out ; - } - /* - * be prepare to extend screen->visuals to add new_visual to it - */ - new_visuals = xcalloc (screen->numVisuals+1, sizeof (VisualRec)) ; - memmove (new_visuals, - screen->visuals, - screen->numVisuals*sizeof (VisualRec)) ; - memmove (&new_visuals[screen->numVisuals], - &new_visual, - sizeof (VisualRec)) ; - /* - * Now, in that same screen, update the screen->allowedDepths member. - * In that array, each element represents the visuals applicable to - * a given depth. So we need to add an entry matching the new visual - * that we are going to add to screen->visuals - */ - for (i=0; inumDepths; i++) { - VisualID *vids=NULL; - DepthPtr cur_depth=NULL ; - /*find the entry matching a_depth*/ - if (screen->allowedDepths[i].depth != a_depth) - continue ; - cur_depth = &screen->allowedDepths[i]; - /* - * extend the list of visual IDs in that entry, - * so to add a_new_id in there. - */ - vids = xrealloc (cur_depth->vids, - (cur_depth->numVids+1)*sizeof (VisualID)); - if (!vids) { - EPHYR_LOG_ERROR ("failed to realloc numids\n") ; - goto out ; - } - vids[cur_depth->numVids] = a_new_id ; - /* - * Okay now commit our change. - * Do really update screen->allowedDepths[i] - */ - cur_depth->numVids++ ; - cur_depth->vids = vids ; - found_depth=TRUE; - } - if (!found_depth) { - EPHYR_LOG_ERROR ("failed to update screen[%d]->allowedDepth\n", - a_screen) ; - goto out ; - } - /* - * Commit our change to screen->visuals - */ - xfree (screen->visuals) ; - screen->visuals = new_visuals ; - screen->numVisuals++ ; - new_visuals = NULL ; - - is_ok = TRUE ; -out: - if (new_visuals) { - xfree (new_visuals) ; - new_visuals = NULL ; - } - EPHYR_LOG ("leave\n") ; - return is_ok ; -} - -/** - * Duplicates the visuals of the host X server. - * This is necessary to have visuals that have the same - * ID as those of the host X. It is important to have that for - * GLX. - */ -static Bool -EphyrMirrorHostVisuals (void) -{ - Bool is_ok=FALSE; - EphyrHostVisualInfo *visuals=NULL; - int nb_visuals=0, i=0; - - EPHYR_LOG ("enter\n") ; - if (!hostx_get_visuals_info (&visuals, &nb_visuals)) { - EPHYR_LOG_ERROR ("failed to get host visuals\n") ; - goto out ; - } - for (i=0; ix ; - *a_y += drawable->y ; *a_back_x = *a_x ; *a_back_y = *a_y ; - *a_w = drawable->width; - *a_h = drawable->height; + *a_w = attrs.width; + *a_h = attrs.height; is_ok = TRUE ; out: diff --git a/hw/kdrive/ephyr/ephyrdri.h b/hw/kdrive/ephyr/ephyrdri.h index ffbbb8e83..af8bb11fd 100644 --- a/hw/kdrive/ephyr/ephyrdri.h +++ b/hw/kdrive/ephyr/ephyrdri.h @@ -51,7 +51,7 @@ Bool ephyrDRICreateDrawable (int a_screen, drm_drawable_t *a_hw_drawable) ; Bool ephyrDRIDestroyDrawable (int a_screen, int a_drawable) ; Bool ephyrDRIGetDrawableInfo (int a_screen, - void* /*DrawablePtr*/ a_drawable, + int /*Drawable*/a_drawable, unsigned int *a_index, unsigned int *a_stamp, int *a_x, diff --git a/hw/kdrive/ephyr/ephyrdriext.c b/hw/kdrive/ephyr/ephyrdriext.c index 443fe9d57..04f3b39e5 100644 --- a/hw/kdrive/ephyr/ephyrdriext.c +++ b/hw/kdrive/ephyr/ephyrdriext.c @@ -49,12 +49,33 @@ #include "colormapst.h" #include "cursorstr.h" #include "scrnintstr.h" +#include "windowstr.h" #include "servermd.h" #include "swaprep.h" #include "ephyrdri.h" +#include "ephyrdriext.h" +#include "hostx.h" #define _HAVE_XALLOC_DECLS #include "ephyrlog.h" +typedef struct { + WindowPtr local ; + int remote ; +} EphyrWindowPair; + +typedef struct { + int foo; +} EphyrDRIWindowPrivRec; +typedef EphyrDRIWindowPrivRec* EphyrDRIWindowPrivPtr; + +typedef struct { + CreateWindowProcPtr CreateWindow ; + DestroyWindowProcPtr DestroyWindow ; + MoveWindowProcPtr MoveWindow ; + PositionWindowProcPtr PositionWindow ; +} EphyrDRIScreenPrivRec; +typedef EphyrDRIScreenPrivRec* EphyrDRIScreenPrivPtr; + static int DRIErrorBase; static DISPATCH_PROC(ProcXF86DRIQueryVersion); @@ -77,18 +98,43 @@ static DISPATCH_PROC(SProcXF86DRIDispatch); static void XF86DRIResetProc(ExtensionEntry* extEntry); +static Bool ephyrDRIScreenInit (ScreenPtr a_screen) ; +static Bool ephyrDRICreateWindow (WindowPtr a_win) ; +static Bool ephyrDRIDestroyWindow (WindowPtr a_win) ; +static void ephyrDRIMoveWindow (WindowPtr a_win, + int a_x, int a_y, + WindowPtr a_siblings, + VTKind a_kind); +static Bool ephyrDRIPositionWindow (WindowPtr a_win, + int x, int y) ; +static Bool EphyrMirrorHostVisuals (void) ; +static Bool destroyHostPeerWindow (const WindowPtr a_win) ; +static Bool findWindowPairFromLocal (WindowPtr a_local, + EphyrWindowPair **a_pair); + static unsigned char DRIReqCode = 0; -extern void ephyrDRIExtensionInit(void); +static int ephyrDRIGeneration=-1 ; +static int ephyrDRIWindowIndex=-1 ; +static int ephyrDRIScreenIndex=-1 ; -void -ephyrDRIExtensionInit(void) +#define GET_EPHYR_DRI_WINDOW_PRIV(win) \ + ((EphyrDRIWindowPrivPtr)((win)->devPrivates[ephyrDRIWindowIndex].ptr)) +#define GET_EPHYR_DRI_SCREEN_PRIV(screen) \ + ((EphyrDRIScreenPrivPtr)((screen)->devPrivates[ephyrDRIScreenIndex].ptr)) + + +Bool +ephyrDRIExtensionInit (ScreenPtr a_screen) { - ExtensionEntry* extEntry; + Bool is_ok=FALSE ; + ExtensionEntry* extEntry=NULL; + EphyrDRIScreenPrivPtr screen_priv=NULL ; + EPHYR_LOG ("enter\n") ; #ifdef XF86DRI_EVENTS - EventType = CreateNewResourceType(XF86DRIFreeEvents); + EventType = CreateNewResourceType (XF86DRIFreeEvents); #endif if ((extEntry = AddExtension(XF86DRINAME, @@ -100,10 +146,411 @@ ephyrDRIExtensionInit(void) StandardMinorOpcode))) { DRIReqCode = (unsigned char)extEntry->base; DRIErrorBase = extEntry->errorBase; + } else { + EPHYR_LOG_ERROR ("failed to register DRI extension\n") ; + goto out ; } + if (ephyrDRIGeneration != serverGeneration) { + ephyrDRIScreenIndex = AllocateScreenPrivateIndex () ; + if (ephyrDRIScreenIndex < 0) { + EPHYR_LOG_ERROR ("failed to allocate screen priv index\n") ; + goto out ; + } + } + screen_priv = xcalloc (1, sizeof (EphyrDRIScreenPrivRec)) ; + if (!screen_priv) { + EPHYR_LOG_ERROR ("failed to allocate screen_priv\n") ; + goto out ; + } + a_screen->devPrivates[ephyrDRIScreenIndex].ptr = screen_priv; + + if (!ephyrDRIScreenInit (a_screen)) { + EPHYR_LOG_ERROR ("ephyrDRIScreenInit() failed\n") ; + goto out ; + } + EphyrMirrorHostVisuals () ; + if (ephyrDRIGeneration != serverGeneration) { + ephyrDRIGeneration = serverGeneration ; + } + is_ok=TRUE ; +out: EPHYR_LOG ("leave\n") ; + return is_ok ; } +static Bool +ephyrDRIScreenInit (ScreenPtr a_screen) +{ + Bool is_ok=FALSE ; + EphyrDRIScreenPrivPtr screen_priv=NULL ; + + EPHYR_RETURN_VAL_IF_FAIL (a_screen, FALSE) ; + + screen_priv=GET_EPHYR_DRI_SCREEN_PRIV (a_screen) ; + EPHYR_RETURN_VAL_IF_FAIL (screen_priv, FALSE) ; + + if (ephyrDRIGeneration != serverGeneration) { + ephyrDRIWindowIndex = AllocateWindowPrivateIndex () ; + if (ephyrDRIWindowIndex < 0) { + EPHYR_LOG_ERROR ("failed to allocate window priv index\n") ; + goto out ; + } + } + if (!AllocateWindowPrivate (a_screen, ephyrDRIWindowIndex, 0)) { + EPHYR_LOG_ERROR ("failed to allocate window privates\n") ; + goto out ; + } + screen_priv->CreateWindow = a_screen->CreateWindow ; + screen_priv->DestroyWindow = a_screen->DestroyWindow ; + screen_priv->MoveWindow = a_screen->MoveWindow ; + screen_priv->PositionWindow = a_screen->PositionWindow ; + + a_screen->CreateWindow = ephyrDRICreateWindow ; + a_screen->DestroyWindow = ephyrDRIDestroyWindow ; + a_screen->MoveWindow = ephyrDRIMoveWindow ; + a_screen->PositionWindow = ephyrDRIPositionWindow ; + + is_ok = TRUE ; +out: + return is_ok ; +} + +static Bool +ephyrDRICreateWindow (WindowPtr a_win) +{ + Bool is_ok=FALSE ; + ScreenPtr screen=NULL ; + EphyrDRIScreenPrivPtr screen_priv =NULL; + + EPHYR_RETURN_VAL_IF_FAIL (a_win, FALSE) ; + screen = a_win->drawable.pScreen ; + EPHYR_RETURN_VAL_IF_FAIL (screen, FALSE) ; + screen_priv = GET_EPHYR_DRI_SCREEN_PRIV (screen) ; + EPHYR_RETURN_VAL_IF_FAIL (screen_priv + && screen_priv->CreateWindow, + FALSE) ; + + EPHYR_LOG ("enter. win:%#x\n", + (unsigned int)a_win) ; + + screen->CreateWindow = screen_priv->CreateWindow ; + is_ok = (*screen->CreateWindow) (a_win) ; + screen->CreateWindow = ephyrDRICreateWindow ; + + if (is_ok) { + a_win->devPrivates[ephyrDRIWindowIndex].ptr = NULL ; + } + return is_ok ; +} + +static Bool +ephyrDRIDestroyWindow (WindowPtr a_win) +{ + Bool is_ok=FALSE ; + ScreenPtr screen=NULL ; + EphyrDRIScreenPrivPtr screen_priv =NULL; + + EPHYR_RETURN_VAL_IF_FAIL (a_win, FALSE) ; + screen = a_win->drawable.pScreen ; + EPHYR_RETURN_VAL_IF_FAIL (screen, FALSE) ; + screen_priv = GET_EPHYR_DRI_SCREEN_PRIV (screen) ; + EPHYR_RETURN_VAL_IF_FAIL (screen_priv + && screen_priv->DestroyWindow, + FALSE) ; + + screen->DestroyWindow = screen_priv->DestroyWindow ; + is_ok = (*screen->DestroyWindow) (a_win) ; + screen->DestroyWindow = ephyrDRIDestroyWindow ; + + if (is_ok) { + EphyrDRIWindowPrivPtr win_priv=GET_EPHYR_DRI_WINDOW_PRIV (a_win) ; + if (win_priv) { + destroyHostPeerWindow (a_win) ; + xfree (win_priv) ; + a_win->devPrivates[ephyrDRIWindowIndex].ptr = NULL ; + EPHYR_LOG ("destroyed the remote peer window\n") ; + } + } + return is_ok ; +} + +static void +ephyrDRIMoveWindow (WindowPtr a_win, + int a_x, int a_y, + WindowPtr a_siblings, + VTKind a_kind) +{ + Bool is_ok=FALSE ; + ScreenPtr screen=NULL ; + EphyrDRIScreenPrivPtr screen_priv =NULL; + EphyrDRIWindowPrivPtr win_priv=NULL ; + EphyrWindowPair *pair=NULL ; + EphyrBox geo; + int x=0,y=0;/*coords relative to parent window*/ + + EPHYR_RETURN_IF_FAIL (a_win) ; + + EPHYR_LOG ("enter\n") ; + screen = a_win->drawable.pScreen ; + EPHYR_RETURN_IF_FAIL (screen) ; + screen_priv = GET_EPHYR_DRI_SCREEN_PRIV (screen) ; + EPHYR_RETURN_IF_FAIL (screen_priv + && screen_priv->MoveWindow) ; + + screen->MoveWindow = screen_priv->MoveWindow ; + (*screen->MoveWindow) (a_win, a_x, a_y, a_siblings, a_kind) ; + screen->MoveWindow = ephyrDRIMoveWindow ; + + EPHYR_LOG ("window: %#x\n", (unsigned int)a_win) ; + if (!a_win->parent) { + EPHYR_LOG ("cannot move root window\n") ; + is_ok = TRUE ; + goto out ; + } + win_priv = GET_EPHYR_DRI_WINDOW_PRIV (a_win) ; + if (!win_priv) { + EPHYR_LOG ("not a DRI peered window\n") ; + is_ok = TRUE ; + goto out ; + } + if (!findWindowPairFromLocal (a_win, &pair) || !pair) { + EPHYR_LOG_ERROR ("failed to get window pair\n") ; + goto out ; + } + /*compute position relative to parent window*/ + x = a_win->drawable.x - a_win->parent->drawable.x ; + y = a_win->drawable.y - a_win->parent->drawable.y ; + /*set the geometry to pass to hostx_set_window_geometry*/ + memset (&geo, 0, sizeof (geo)) ; + geo.x = x ; + geo.y = y ; + geo.width = a_win->drawable.width ; + geo.height = a_win->drawable.height ; + hostx_set_window_geometry (pair->remote, &geo) ; + is_ok = TRUE ; + +out: + EPHYR_LOG ("leave. is_ok:%d\n", is_ok) ; + /*do cleanup here*/ +} + +static Bool +ephyrDRIPositionWindow (WindowPtr a_win, + int a_x, int a_y) +{ + Bool is_ok=FALSE ; + ScreenPtr screen=NULL ; + EphyrDRIScreenPrivPtr screen_priv =NULL; + EphyrDRIWindowPrivPtr win_priv=NULL ; + EphyrWindowPair *pair=NULL ; + EphyrBox geo; + + EPHYR_RETURN_VAL_IF_FAIL (a_win, FALSE) ; + + EPHYR_LOG ("enter\n") ; + screen = a_win->drawable.pScreen ; + EPHYR_RETURN_VAL_IF_FAIL (screen, FALSE) ; + screen_priv = GET_EPHYR_DRI_SCREEN_PRIV (screen) ; + EPHYR_RETURN_VAL_IF_FAIL (screen_priv + && screen_priv->PositionWindow, + FALSE) ; + + screen->PositionWindow = screen_priv->PositionWindow ; + (*screen->PositionWindow) (a_win, a_x, a_y) ; + screen->PositionWindow = ephyrDRIPositionWindow ; + + EPHYR_LOG ("window: %#x\n", (unsigned int)a_win) ; + win_priv = GET_EPHYR_DRI_WINDOW_PRIV (a_win) ; + if (!win_priv) { + EPHYR_LOG ("not a DRI peered window\n") ; + is_ok = TRUE ; + goto out ; + } + if (!findWindowPairFromLocal (a_win, &pair) || !pair) { + EPHYR_LOG_ERROR ("failed to get window pair\n") ; + goto out ; + } + /*set the geometry to pass to hostx_set_window_geometry*/ + memset (&geo, 0, sizeof (geo)) ; + geo.x = a_x ; + geo.y = a_y ; + geo.width = a_win->drawable.width ; + geo.height = a_win->drawable.height ; + hostx_set_window_geometry (pair->remote, &geo) ; + is_ok = TRUE ; + +out: + EPHYR_LOG ("leave. is_ok:%d\n", is_ok) ; + /*do cleanup here*/ + return is_ok ; +} + +/** + * Duplicates a visual of a_screen + * In screen a_screen, for depth a_depth, find a visual which + * bitsPerRGBValue and colormap size equal + * a_bits_per_rgb_values and a_colormap_entries. + * The ID of that duplicated visual is set to a_new_id. + * That duplicated visual is then added to the list of visuals + * of the screen. + */ +static Bool +EphyrDuplicateVisual (unsigned int a_screen, + short a_depth, + short a_class, + short a_bits_per_rgb_values, + short a_colormap_entries, + unsigned int a_red_mask, + unsigned int a_green_mask, + unsigned int a_blue_mask, + unsigned int a_new_id) +{ + Bool is_ok = FALSE, found_visual=FALSE, found_depth=FALSE ; + ScreenPtr screen=NULL ; + VisualRec new_visual, *new_visuals=NULL ; + int i=0 ; + + EPHYR_LOG ("enter\n") ; + if (a_screen > screenInfo.numScreens) { + EPHYR_LOG_ERROR ("bad screen number\n") ; + goto out; + } + memset (&new_visual, 0, sizeof (VisualRec)) ; + + /*get the screen pointed to by a_screen*/ + screen = screenInfo.screens[a_screen] ; + EPHYR_RETURN_VAL_IF_FAIL (screen, FALSE) ; + + /* + * In that screen, first look for an existing visual that has the + * same characteristics as those passed in parameter + * to this function and copy it. + */ + for (i=0; i < screen->numVisuals; i++) { + if (screen->visuals[i].bitsPerRGBValue == a_bits_per_rgb_values && + screen->visuals[i].ColormapEntries == a_colormap_entries ) { + /*copy the visual found*/ + memcpy (&new_visual, &screen->visuals[i], sizeof (new_visual)) ; + new_visual.vid = a_new_id ; + new_visual.class = a_class ; + new_visual.redMask = a_red_mask ; + new_visual.greenMask = a_green_mask ; + new_visual.blueMask = a_blue_mask ; + found_visual = TRUE ; + EPHYR_LOG ("found a visual that matches visual id: %d\n", + a_new_id) ; + break; + } + } + if (!found_visual) { + EPHYR_LOG ("did not find any visual matching %d\n", a_new_id) ; + goto out ; + } + /* + * be prepare to extend screen->visuals to add new_visual to it + */ + new_visuals = xcalloc (screen->numVisuals+1, sizeof (VisualRec)) ; + memmove (new_visuals, + screen->visuals, + screen->numVisuals*sizeof (VisualRec)) ; + memmove (&new_visuals[screen->numVisuals], + &new_visual, + sizeof (VisualRec)) ; + /* + * Now, in that same screen, update the screen->allowedDepths member. + * In that array, each element represents the visuals applicable to + * a given depth. So we need to add an entry matching the new visual + * that we are going to add to screen->visuals + */ + for (i=0; inumDepths; i++) { + VisualID *vids=NULL; + DepthPtr cur_depth=NULL ; + /*find the entry matching a_depth*/ + if (screen->allowedDepths[i].depth != a_depth) + continue ; + cur_depth = &screen->allowedDepths[i]; + /* + * extend the list of visual IDs in that entry, + * so to add a_new_id in there. + */ + vids = xrealloc (cur_depth->vids, + (cur_depth->numVids+1)*sizeof (VisualID)); + if (!vids) { + EPHYR_LOG_ERROR ("failed to realloc numids\n") ; + goto out ; + } + vids[cur_depth->numVids] = a_new_id ; + /* + * Okay now commit our change. + * Do really update screen->allowedDepths[i] + */ + cur_depth->numVids++ ; + cur_depth->vids = vids ; + found_depth=TRUE; + } + if (!found_depth) { + EPHYR_LOG_ERROR ("failed to update screen[%d]->allowedDepth\n", + a_screen) ; + goto out ; + } + /* + * Commit our change to screen->visuals + */ + xfree (screen->visuals) ; + screen->visuals = new_visuals ; + screen->numVisuals++ ; + new_visuals = NULL ; + + is_ok = TRUE ; +out: + if (new_visuals) { + xfree (new_visuals) ; + new_visuals = NULL ; + } + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +/** + * Duplicates the visuals of the host X server. + * This is necessary to have visuals that have the same + * ID as those of the host X. It is important to have that for + * GLX. + */ +static Bool +EphyrMirrorHostVisuals (void) +{ + Bool is_ok=FALSE; + EphyrHostVisualInfo *visuals=NULL; + int nb_visuals=0, i=0; + + EPHYR_LOG ("enter\n") ; + if (!hostx_get_visuals_info (&visuals, &nb_visuals)) { + EPHYR_LOG_ERROR ("failed to get host visuals\n") ; + goto out ; + } + for (i=0; icontext, - (drm_context_t *)&rep.hHWContext)) { - return BadValue; + context_id = stuff->context ; + if (!ephyrDRICreateContext (stuff->screen, + stuff->visual, + &context_id, + (drm_context_t *)&rep.hHWContext)) { + return BadValue; } - */ WriteToClient(client, sizeof(xXF86DRICreateContextReply), (char *)&rep); EPHYR_LOG ("leave\n") ; @@ -363,23 +810,146 @@ ProcXF86DRIDestroyContext (register ClientPtr client) return BadValue; } - /* - if (!DRIDestroyContext( screenInfo.screens[stuff->screen], - stuff->context)) { + if (!ephyrDRIDestroyContext (stuff->screen, stuff->context)) { return BadValue; - } - */ + } EPHYR_LOG ("leave\n") ; return (client->noClientException); } +static Bool +getWindowVisual (const WindowPtr a_win, + VisualPtr *a_visual) +{ + int i=0, visual_id=0 ; + EPHYR_RETURN_VAL_IF_FAIL (a_win + && a_win->drawable.pScreen + && a_win->drawable.pScreen->visuals, + FALSE) ; + + visual_id = wVisual (a_win) ; + for (i=0; i < a_win->drawable.pScreen->numVisuals; i++) { + if (a_win->drawable.pScreen->visuals[i].vid == visual_id) { + *a_visual = &a_win->drawable.pScreen->visuals[i] ; + return TRUE ; + } + } + return FALSE ; +} + + +#define NUM_WINDOW_PAIRS 256 +static EphyrWindowPair window_pairs[NUM_WINDOW_PAIRS] ; + +static Bool +appendWindowPairToList (WindowPtr a_local, + int a_remote) +{ + int i=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_local, FALSE) ; + + EPHYR_LOG ("(local,remote):(%#x, %d)\n", (unsigned int)a_local, a_remote) ; + + for (i=0; i < NUM_WINDOW_PAIRS; i++) { + if (window_pairs[i].local == NULL) { + window_pairs[i].local = a_local ; + window_pairs[i].remote = a_remote ; + return TRUE ; + } + } + return FALSE ; +} + +static Bool +findWindowPairFromLocal (WindowPtr a_local, + EphyrWindowPair **a_pair) +{ + int i=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_pair && a_local, FALSE) ; + + for (i=0; i < NUM_WINDOW_PAIRS; i++) { + if (window_pairs[i].local == a_local) { + *a_pair = &window_pairs[i] ; + EPHYR_LOG ("found (%#x, %d)\n", + (unsigned int)(*a_pair)->local, + (*a_pair)->remote) ; + return TRUE ; + } + } + return FALSE ; +} + +static Bool +createHostPeerWindow (const WindowPtr a_win, + int *a_peer_win) +{ + Bool is_ok=FALSE ; + VisualPtr visual=NULL; + EphyrBox geo ; + + EPHYR_RETURN_VAL_IF_FAIL (a_win && a_peer_win, FALSE) ; + + EPHYR_LOG ("enter. a_win '%#x'\n", (unsigned int)a_win) ; + if (!getWindowVisual (a_win, &visual)) { + EPHYR_LOG_ERROR ("failed to get window visual\n") ; + goto out ; + } + if (!visual) { + EPHYR_LOG_ERROR ("failed to create visual\n") ; + goto out ; + } + memset (&geo, 0, sizeof (geo)) ; + geo.x = a_win->drawable.x ; + geo.y = a_win->drawable.y ; + geo.width = a_win->drawable.width ; + geo.height = a_win->drawable.height ; + if (!hostx_create_window (&geo, visual->vid, a_peer_win)) { + EPHYR_LOG_ERROR ("failed to create host peer window\n") ; + goto out ; + } + if (!appendWindowPairToList (a_win, *a_peer_win)) { + EPHYR_LOG_ERROR ("failed to append window to pair list\n") ; + goto out ; + } + is_ok = TRUE ; +out: + EPHYR_LOG ("leave:remote win%d\n", *a_peer_win) ; + return is_ok ; +} + +static Bool +destroyHostPeerWindow (const WindowPtr a_win) +{ + Bool is_ok = FALSE ; + EphyrWindowPair *pair=NULL ; + EPHYR_RETURN_VAL_IF_FAIL (a_win, FALSE) ; + + EPHYR_LOG ("enter\n") ; + + if (!findWindowPairFromLocal (a_win, &pair) || !pair) { + EPHYR_LOG_ERROR ("failed to find peer to local window\n") ; + goto out; + } + hostx_destroy_window (pair->remote) ; + is_ok = TRUE ; + +out: + EPHYR_LOG ("leave\n") ; + return is_ok; +} + static int ProcXF86DRICreateDrawable (ClientPtr client) { xXF86DRICreateDrawableReply rep; - DrawablePtr pDrawable; - int rc; + DrawablePtr drawable=NULL; + WindowPtr window=NULL ; + EphyrWindowPair *pair=NULL ; + EphyrDRIWindowPrivPtr win_priv=NULL; + int rc=0, remote_win=0; EPHYR_LOG ("enter\n") ; REQUEST(xXF86DRICreateDrawableReq); @@ -393,21 +963,44 @@ ProcXF86DRICreateDrawable (ClientPtr client) rep.length = 0; rep.sequenceNumber = client->sequence; - rc = dixLookupDrawable (&pDrawable, stuff->drawable, client, 0, + rc = dixLookupDrawable (&drawable, stuff->drawable, client, 0, DixReadAccess); if (rc != Success) return rc; + if (drawable->type != DRAWABLE_WINDOW) { + EPHYR_LOG_ERROR ("non drawable windows are not yet supported\n") ; + return BadImplementation ; + } + EPHYR_LOG ("lookedup drawable %#x\n", (unsigned int)drawable) ; + window = (WindowPtr)drawable; + if (findWindowPairFromLocal (window, &pair) && pair) { + remote_win = pair->remote ; + EPHYR_LOG ("found window '%#x' paire with remote '%d'\n", + (unsigned int)window, remote_win) ; + } else if (!createHostPeerWindow (window, &remote_win)) { + EPHYR_LOG_ERROR ("failed to create host peer window\n") ; + return BadAlloc ; + } - /*TODO: this cannot work. We must properly - * do the mapping between the xephyr drawable and - * the host drawable - */ if (!ephyrDRICreateDrawable (stuff->screen, - 0/*should be host drawableID*/, - (drm_drawable_t *)&rep.hHWDrawable)) { + remote_win, + (drm_drawable_t *)&rep.hHWDrawable)) { + EPHYR_LOG_ERROR ("failed to create dri drawable\n") ; return BadValue; } + win_priv = GET_EPHYR_DRI_WINDOW_PRIV (window) ; + if (!win_priv) { + win_priv = xcalloc (1, sizeof (EphyrDRIWindowPrivRec)) ; + if (!win_priv) { + EPHYR_LOG_ERROR ("failed to allocate window private\n") ; + return BadAlloc ; + } + window->devPrivates[ephyrDRIWindowIndex].ptr = win_priv ; + EPHYR_LOG ("paired window '%#x' with remote '%d'\n", + (unsigned int)window, remote_win) ; + } + WriteToClient(client, sizeof(xXF86DRICreateDrawableReply), (char *)&rep); EPHYR_LOG ("leave\n") ; return (client->noClientException); @@ -417,9 +1010,11 @@ static int ProcXF86DRIDestroyDrawable (register ClientPtr client) { REQUEST(xXF86DRIDestroyDrawableReq); - DrawablePtr pDrawable; + DrawablePtr drawable=NULL; + WindowPtr window=NULL; + EphyrWindowPair *pair=NULL; REQUEST_SIZE_MATCH(xXF86DRIDestroyDrawableReq); - int rc; + int rc=0; EPHYR_LOG ("enter\n") ; if (stuff->screen >= screenInfo.numScreens) { @@ -427,18 +1022,30 @@ ProcXF86DRIDestroyDrawable (register ClientPtr client) return BadValue; } - rc = dixLookupDrawable(&pDrawable, + rc = dixLookupDrawable(&drawable, stuff->drawable, client, 0, DixReadAccess); if (rc != Success) return rc; - - if (!ephyrDRIDestroyDrawable(stuff->screen, - 0/*should be drawable in host x*/)) { - return BadValue; + if (drawable->type != DRAWABLE_WINDOW) { + EPHYR_LOG_ERROR ("non drawable windows are not yet supported\n") ; + return BadImplementation ; } + window = (WindowPtr)drawable; + if (!findWindowPairFromLocal (window, &pair) && pair) { + EPHYR_LOG_ERROR ("failed to find pair window\n") ; + return BadImplementation; + } + if (!ephyrDRIDestroyDrawable(stuff->screen, + pair->remote/*drawable in host x*/)) { + EPHYR_LOG_ERROR ("failed to destroy dri drawable\n") ; + return BadImplementation; + } + pair->local=NULL ; + pair->remote=0; + EPHYR_LOG ("leave\n") ; return (client->noClientException); } @@ -448,6 +1055,8 @@ ProcXF86DRIGetDrawableInfo (register ClientPtr client) { xXF86DRIGetDrawableInfoReply rep; DrawablePtr drawable; + WindowPtr window=NULL; + EphyrWindowPair *pair=NULL; int X=0, Y=0, W=0, H=0, backX=0, backY=0, rc=0; drm_clip_rect_t *pClipRects=NULL, *pClippedRects=NULL; drm_clip_rect_t *pBackClipRects=NULL; @@ -465,17 +1074,25 @@ ProcXF86DRIGetDrawableInfo (register ClientPtr client) rep.length = 0; rep.sequenceNumber = client->sequence; - /*TODO: this cannot work. - * We must properly do the mapping - * between xephyr drawable and the host drawable - */ rc = dixLookupDrawable(&drawable, stuff->drawable, client, 0, DixReadAccess); - if (rc != Success) + if (rc != Success || !drawable) { + EPHYR_LOG_ERROR ("could not get drawable\n") ; return rc; + } + if (drawable->type != DRAWABLE_WINDOW) { + EPHYR_LOG_ERROR ("non windows type drawables are not yes supported\n") ; + return BadImplementation ; + } + window = (WindowPtr)drawable ; + memset (&pair, 0, sizeof (pair)) ; + if (!findWindowPairFromLocal (window, &pair) || !pair) { + EPHYR_LOG_ERROR ("failed to find remote peer drawable\n") ; + return BadMatch ; + } if (!ephyrDRIGetDrawableInfo (stuff->screen, - drawable/*should be the drawable in hostx*/, + pair->remote/*the drawable in hostx*/, (unsigned int*)&rep.drawableTableIndex, (unsigned int*)&rep.drawableTableStamp, (int*)&X, diff --git a/hw/kdrive/ephyr/ephyrvideo.c b/hw/kdrive/ephyr/ephyrvideo.c index eea426af3..521f3a6b5 100644 --- a/hw/kdrive/ephyr/ephyrvideo.c +++ b/hw/kdrive/ephyr/ephyrvideo.c @@ -64,7 +64,9 @@ static Bool DoSimpleClip (BoxPtr a_dst_drw, static Bool ephyrLocalAtomToHost (int a_local_atom, int *a_host_atom) ; +/* static Bool ephyrHostAtomToLocal (int a_host_atom, int *a_local_atom) ; +*/ static EphyrXVPriv* ephyrXVPrivNew (void) ; static void ephyrXVPrivDelete (EphyrXVPriv *a_this) ; diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c index 51fda478f..7636e250e 100644 --- a/hw/kdrive/ephyr/hostx.c +++ b/hw/kdrive/ephyr/hostx.c @@ -1132,3 +1132,86 @@ hostx_get_resource_id_peer (int a_local_resource_id, return FALSE ; } +int +hostx_create_window (EphyrBox *a_geometry, + int a_visual_id, + int *a_host_peer /*out parameter*/) +{ + Bool is_ok=FALSE ; + Display *dpy=hostx_get_display () ; + XVisualInfo *visual_info=NULL, visual_info_templ; + int visual_mask=VisualIDMask ; + Window win=None ; + int nb_visuals=0, winmask=0; + XSetWindowAttributes attrs; + + EPHYR_RETURN_VAL_IF_FAIL (dpy && a_geometry, FALSE) ; + + EPHYR_LOG ("enter\n") ; + + /*get visual*/ + memset (&visual_info, 0, sizeof (visual_info)) ; + visual_info_templ.visualid = a_visual_id ; + visual_info = XGetVisualInfo (dpy, visual_mask, + &visual_info_templ, + &nb_visuals) ; + if (!visual_info) { + EPHYR_LOG_ERROR ("argh, could not find a remote visual with id:%d\n", + a_visual_id) ; + goto out ; + } + memset (&attrs, 0, sizeof (attrs)) ; + attrs.colormap = XCreateColormap (dpy, + RootWindow (dpy, + visual_info->screen), + visual_info->visual, + AllocNone) ; + winmask = CWColormap; + + win = XCreateWindow (dpy, hostx_get_window (), + a_geometry->x, a_geometry->y, + a_geometry->width, a_geometry->height, 0, + visual_info->depth, InputOutput, + visual_info->visual, winmask, &attrs) ; + if (win == None) { + EPHYR_LOG_ERROR ("failed to create peer window\n") ; + goto out ; + } + XFlush (dpy) ; + XMapWindow (dpy, win) ; + *a_host_peer = win ; + is_ok = TRUE ; +out: + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +int +hostx_destroy_window (int a_win) +{ + Display *dpy=hostx_get_display () ; + + EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; + XDestroyWindow (dpy, a_win) ; + XFlush (dpy) ; + return TRUE ; +} + +int +hostx_set_window_geometry (int a_win, EphyrBox *a_geo) +{ + Display *dpy=hostx_get_display (); + + EPHYR_RETURN_VAL_IF_FAIL (dpy && a_geo, FALSE) ; + + EPHYR_LOG ("enter. x,y,w,h:(%d,%d,%d,%d)\n", + a_geo->x, a_geo->y, + a_geo->width, a_geo->height) ; + + XMoveWindow (dpy, a_win, a_geo->x, a_geo->y) ; + XResizeWindow (dpy, a_win, a_geo->width, a_geo->height) ; + XFlush (dpy) ; + EPHYR_LOG ("leave\n") ; + return TRUE; +} + diff --git a/hw/kdrive/ephyr/hostx.h b/hw/kdrive/ephyr/hostx.h index 51a5f6832..3cd27ff0a 100644 --- a/hw/kdrive/ephyr/hostx.h +++ b/hw/kdrive/ephyr/hostx.h @@ -110,6 +110,10 @@ typedef struct { int visualid ; } EphyrHostWindowAttributes; +typedef struct { + int x,y,width,height; +} EphyrBox; + int hostx_want_screen_size(EphyrScreenInfo screen, int *width, int *height); @@ -214,4 +218,15 @@ int hostx_get_resource_id_peer (int a_local_resource_id, int *a_remote_resource_id) ; +int hostx_create_window (EphyrBox *a_geometry, + int a_visual_id, + int *a_host_win /*out parameter*/) ; + +int hostx_destroy_window (int a_win) ; + +int hostx_set_window_geometry (int a_win, EphyrBox *a_geo) ; + +int hostx_lookup_peer_window (void *a_local_window, + int *a_host_peer /*out parameter*/) ; + #endif From 3816d64e50a59e0ef276ddd6cb250cab98a49392 Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Sun, 9 Sep 2007 15:20:51 +0200 Subject: [PATCH 34/44] Xephyr: oops, forgot to add ephyrdriext.h --- hw/kdrive/ephyr/ephyrdriext.h | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 hw/kdrive/ephyr/ephyrdriext.h diff --git a/hw/kdrive/ephyr/ephyrdriext.h b/hw/kdrive/ephyr/ephyrdriext.h new file mode 100644 index 000000000..66af833b9 --- /dev/null +++ b/hw/kdrive/ephyr/ephyrdriext.h @@ -0,0 +1,32 @@ +/* + * Xephyr - A kdrive X server thats runs in a host X window. + * Authored by Matthew Allum + * + * Copyright © 2007 OpenedHand Ltd + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of OpenedHand Ltd not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OpenedHand Ltd makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OpenedHand Ltd BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Authors: + * Dodji Seketeli + */ +#ifndef __EPHYRDRIEXT_H__ +#define __EPHYRDRIEXT_H__ +Bool ephyrDRIExtensionInit (ScreenPtr a_screen) ; +#endif /*__EPHYRDRIEXT_H__*/ + From 79782726617d4b5a4f9b376f21936d035fc870e1 Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Mon, 17 Sep 2007 18:15:03 +0200 Subject: [PATCH 35/44] Xephyr: properly clip GL drawables in Xephyr --- hw/kdrive/ephyr/XF86dri.c | 4 +- hw/kdrive/ephyr/ephyrdri.c | 11 +++ hw/kdrive/ephyr/ephyrdriext.c | 158 ++++++++++++++++++++++++------- hw/kdrive/ephyr/ephyrhostvideo.c | 1 + hw/kdrive/ephyr/hostx.c | 75 +++++++++++++++ hw/kdrive/ephyr/hostx.h | 10 ++ 6 files changed, 223 insertions(+), 36 deletions(-) diff --git a/hw/kdrive/ephyr/XF86dri.c b/hw/kdrive/ephyr/XF86dri.c index fc35ce267..bf6c54f97 100644 --- a/hw/kdrive/ephyr/XF86dri.c +++ b/hw/kdrive/ephyr/XF86dri.c @@ -467,7 +467,7 @@ Bool XF86DRIGetDrawableInfo(Display* dpy, int screen, Drawable drawable, { XExtDisplayInfo *info = find_display (dpy); xXF86DRIGetDrawableInfoReply rep; - xXF86DRIGetDrawableInfoReq *req; + xXF86DRIGetDrawableInfoReq *req=NULL; int total_rects; TRACE("GetDrawableInfo..."); @@ -521,7 +521,7 @@ Bool XF86DRIGetDrawableInfo(Display* dpy, int screen, Drawable drawable, int len = sizeof(drm_clip_rect_t) * (*numClipRects); *pClipRects = (drm_clip_rect_t *)Xcalloc(len, 1); - if (*pClipRects) + if (*pClipRects) _XRead(dpy, (char*)*pClipRects, len); } else { *pClipRects = NULL; diff --git a/hw/kdrive/ephyr/ephyrdri.c b/hw/kdrive/ephyr/ephyrdri.c index 17ea7120d..c4637d022 100644 --- a/hw/kdrive/ephyr/ephyrdri.c +++ b/hw/kdrive/ephyr/ephyrdri.c @@ -240,6 +240,17 @@ ephyrDRIGetDrawableInfo (int a_screen, goto out ; } EPHYR_LOG ("host x,y,w,h: (%d,%d,%d,%d)\n", *a_x, *a_y, *a_w, *a_h) ; + if (*a_num_back_clip_rects != *a_num_clip_rects) { + free (*a_back_clip_rects) ; + *a_back_clip_rects = calloc (*a_num_clip_rects, + sizeof (drm_clip_rect_t)) ; + memmove (*a_back_clip_rects, + *a_clip_rects, + *a_num_clip_rects * sizeof (drm_clip_rect_t)) ; + *a_num_back_clip_rects = *a_num_clip_rects; + } + EPHYR_LOG ("num back clip rects:%d, num clip rects:%d\n", + *a_num_clip_rects, *a_num_back_clip_rects) ; *a_back_x = *a_x ; *a_back_y = *a_y ; *a_w = attrs.width; diff --git a/hw/kdrive/ephyr/ephyrdriext.c b/hw/kdrive/ephyr/ephyrdriext.c index 04f3b39e5..be07e6475 100644 --- a/hw/kdrive/ephyr/ephyrdriext.c +++ b/hw/kdrive/ephyr/ephyrdriext.c @@ -73,6 +73,7 @@ typedef struct { DestroyWindowProcPtr DestroyWindow ; MoveWindowProcPtr MoveWindow ; PositionWindowProcPtr PositionWindow ; + ClipNotifyProcPtr ClipNotify ; } EphyrDRIScreenPrivRec; typedef EphyrDRIScreenPrivRec* EphyrDRIScreenPrivPtr; @@ -107,6 +108,9 @@ static void ephyrDRIMoveWindow (WindowPtr a_win, VTKind a_kind); static Bool ephyrDRIPositionWindow (WindowPtr a_win, int x, int y) ; +static void ephyrDRIClipNotify (WindowPtr a_win, + int a_x, int a_y) ; + static Bool EphyrMirrorHostVisuals (void) ; static Bool destroyHostPeerWindow (const WindowPtr a_win) ; static Bool findWindowPairFromLocal (WindowPtr a_local, @@ -204,11 +208,13 @@ ephyrDRIScreenInit (ScreenPtr a_screen) screen_priv->DestroyWindow = a_screen->DestroyWindow ; screen_priv->MoveWindow = a_screen->MoveWindow ; screen_priv->PositionWindow = a_screen->PositionWindow ; + screen_priv->ClipNotify = a_screen->ClipNotify ; a_screen->CreateWindow = ephyrDRICreateWindow ; a_screen->DestroyWindow = ephyrDRIDestroyWindow ; a_screen->MoveWindow = ephyrDRIMoveWindow ; a_screen->PositionWindow = ephyrDRIPositionWindow ; + a_screen->ClipNotify = ephyrDRIClipNotify ; is_ok = TRUE ; out: @@ -259,7 +265,9 @@ ephyrDRIDestroyWindow (WindowPtr a_win) FALSE) ; screen->DestroyWindow = screen_priv->DestroyWindow ; - is_ok = (*screen->DestroyWindow) (a_win) ; + if (screen->DestroyWindow) { + is_ok = (*screen->DestroyWindow) (a_win) ; + } screen->DestroyWindow = ephyrDRIDestroyWindow ; if (is_ok) { @@ -298,7 +306,9 @@ ephyrDRIMoveWindow (WindowPtr a_win, && screen_priv->MoveWindow) ; screen->MoveWindow = screen_priv->MoveWindow ; - (*screen->MoveWindow) (a_win, a_x, a_y, a_siblings, a_kind) ; + if (screen->MoveWindow) { + (*screen->MoveWindow) (a_win, a_x, a_y, a_siblings, a_kind) ; + } screen->MoveWindow = ephyrDRIMoveWindow ; EPHYR_LOG ("window: %#x\n", (unsigned int)a_win) ; @@ -356,7 +366,9 @@ ephyrDRIPositionWindow (WindowPtr a_win, FALSE) ; screen->PositionWindow = screen_priv->PositionWindow ; - (*screen->PositionWindow) (a_win, a_x, a_y) ; + if (screen->PositionWindow) { + (*screen->PositionWindow) (a_win, a_x, a_y) ; + } screen->PositionWindow = ephyrDRIPositionWindow ; EPHYR_LOG ("window: %#x\n", (unsigned int)a_win) ; @@ -385,6 +397,73 @@ out: return is_ok ; } +static void +ephyrDRIClipNotify (WindowPtr a_win, + int a_x, int a_y) +{ + Bool is_ok=FALSE ; + ScreenPtr screen=NULL ; + EphyrDRIScreenPrivPtr screen_priv =NULL; + EphyrDRIWindowPrivPtr win_priv=NULL ; + EphyrWindowPair *pair=NULL ; + EphyrRect *rects=NULL; + int i=0 ; + + EPHYR_RETURN_IF_FAIL (a_win) ; + + EPHYR_LOG ("enter\n") ; + screen = a_win->drawable.pScreen ; + EPHYR_RETURN_IF_FAIL (screen) ; + screen_priv = GET_EPHYR_DRI_SCREEN_PRIV (screen) ; + EPHYR_RETURN_IF_FAIL (screen_priv && screen_priv->ClipNotify) ; + + screen->ClipNotify = screen_priv->ClipNotify ; + if (screen->ClipNotify) { + (*screen->ClipNotify) (a_win, a_x, a_y) ; + } + screen->ClipNotify = ephyrDRIClipNotify ; + + EPHYR_LOG ("window: %#x\n", (unsigned int)a_win) ; + win_priv = GET_EPHYR_DRI_WINDOW_PRIV (a_win) ; + if (!win_priv) { + EPHYR_LOG ("not a DRI peered window\n") ; + is_ok = TRUE ; + goto out ; + } + if (!findWindowPairFromLocal (a_win, &pair) || !pair) { + EPHYR_LOG_ERROR ("failed to get window pair\n") ; + goto out ; + } + rects = xcalloc (REGION_NUM_RECTS (&a_win->clipList), + sizeof (EphyrRect)) ; + for (i=0; i < REGION_NUM_RECTS (&a_win->clipList); i++) { + memmove (&rects[i], + ®ION_RECTS (&a_win->clipList)[i], + sizeof (EphyrRect)) ; + rects[i].x1 -= a_win->drawable.x; + rects[i].x2 -= a_win->drawable.x; + rects[i].y1 -= a_win->drawable.y; + rects[i].y2 -= a_win->drawable.y; + } + /* + * push the clipping region of this window + * to the peer window in the host + */ + is_ok = hostx_set_window_bounding_rectangles + (pair->remote, + rects, + REGION_NUM_RECTS (&a_win->clipList)) ; + is_ok = TRUE ; + +out: + if (rects) { + xfree (rects) ; + rects = NULL ; + } + EPHYR_LOG ("leave. is_ok:%d\n", is_ok) ; + /*do cleanup here*/ +} + /** * Duplicates a visual of a_screen * In screen a_screen, for depth a_depth, find a visual which @@ -1057,9 +1136,9 @@ ProcXF86DRIGetDrawableInfo (register ClientPtr client) DrawablePtr drawable; WindowPtr window=NULL; EphyrWindowPair *pair=NULL; - int X=0, Y=0, W=0, H=0, backX=0, backY=0, rc=0; - drm_clip_rect_t *pClipRects=NULL, *pClippedRects=NULL; - drm_clip_rect_t *pBackClipRects=NULL; + int X=0, Y=0, W=0, H=0, backX=0, backY=0, rc=0, i=0; + drm_clip_rect_t *clipRects=NULL, *clippedRects=NULL; + drm_clip_rect_t *backClipRects=NULL; EPHYR_LOG ("enter\n") ; memset (&rep, 0, sizeof (rep)) ; @@ -1091,6 +1170,15 @@ ProcXF86DRIGetDrawableInfo (register ClientPtr client) EPHYR_LOG_ERROR ("failed to find remote peer drawable\n") ; return BadMatch ; } + EPHYR_LOG ("clip list of xephyr gl drawable:\n") ; + for (i=0; i < REGION_NUM_RECTS (&window->clipList); i++) { + EPHYR_LOG ("x1:%d, y1:%d, x2:%d, y2:%d\n", + REGION_RECTS (&window->clipList)[i].x1, + REGION_RECTS (&window->clipList)[i].y1, + REGION_RECTS (&window->clipList)[i].x2, + REGION_RECTS (&window->clipList)[i].y2) ; + } + if (!ephyrDRIGetDrawableInfo (stuff->screen, pair->remote/*the drawable in hostx*/, (unsigned int*)&rep.drawableTableIndex, @@ -1100,54 +1188,56 @@ ProcXF86DRIGetDrawableInfo (register ClientPtr client) (int*)&W, (int*)&H, (int*)&rep.numClipRects, - &pClipRects, + &clipRects, &backX, &backY, (int*)&rep.numBackClipRects, - &pBackClipRects)) { + &backClipRects)) { return BadValue; } + EPHYR_LOG ("num clip rects:%d, num back clip rects:%d\n", + (int)rep.numClipRects, (int)rep.numBackClipRects) ; + backClipRects = clipRects ; rep.drawableX = X; rep.drawableY = Y; rep.drawableWidth = W; rep.drawableHeight = H; - rep.length = (SIZEOF(xXF86DRIGetDrawableInfoReply) - + rep.length = (SIZEOF(xXF86DRIGetDrawableInfoReply) - SIZEOF(xGenericReply)); rep.backX = backX; rep.backY = backY; - if (rep.numBackClipRects) - rep.length += sizeof(drm_clip_rect_t) * rep.numBackClipRects; + if (rep.numBackClipRects) + rep.length += sizeof(drm_clip_rect_t) * rep.numBackClipRects; - pClippedRects = pClipRects; + clippedRects = clipRects; if (rep.numClipRects) { /* Clip cliprects to screen dimensions (redirected windows) */ - pClippedRects = xalloc(rep.numClipRects * sizeof(drm_clip_rect_t)); + clippedRects = xalloc(rep.numClipRects * sizeof(drm_clip_rect_t)); - if (pClippedRects) { + if (clippedRects) { ScreenPtr pScreen = screenInfo.screens[stuff->screen]; - int i, j; + int i=0; - for (i = 0, j = 0; i < rep.numClipRects; i++) { - pClippedRects[j].x1 = max(pClipRects[i].x1, 0); - pClippedRects[j].y1 = max(pClipRects[i].y1, 0); - pClippedRects[j].x2 = min(pClipRects[i].x2, pScreen->width); - pClippedRects[j].y2 = min(pClipRects[i].y2, pScreen->height); - - if (pClippedRects[j].x1 < pClippedRects[j].x2 && - pClippedRects[j].y1 < pClippedRects[j].y2) { - j++; - } + EPHYR_LOG ("clip list of host gl drawable:\n") ; + for (i = 0; i < rep.numClipRects; i++) { + clippedRects[i].x1 = max(clipRects[i].x1, 0); + clippedRects[i].y1 = max(clipRects[i].y1, 0); + clippedRects[i].x2 = min(clipRects[i].x2, pScreen->width); + clippedRects[i].y2 = min(clipRects[i].y2, pScreen->height); + EPHYR_LOG ("x1:%d, y1:%d, x2:%d, y2:%d\n", + clippedRects[i].x1, clippedRects[i].y1, + clippedRects[i].x2, clippedRects[i].y2) ; } - rep.numClipRects = j; + /*rep.numClipRects = j*/; + EPHYR_LOG ("num host clip rects:%d\n", (int)rep.numClipRects) ; } else { rep.numClipRects = 0; } - rep.length += sizeof(drm_clip_rect_t) * rep.numClipRects; } @@ -1156,16 +1246,16 @@ ProcXF86DRIGetDrawableInfo (register ClientPtr client) WriteToClient(client, sizeof(xXF86DRIGetDrawableInfoReply), (char *)&rep); if (rep.numClipRects) { - WriteToClient(client, - sizeof(drm_clip_rect_t) * rep.numClipRects, - (char *)pClippedRects); - xfree(pClippedRects); + WriteToClient(client, + sizeof(drm_clip_rect_t) * rep.numClipRects, + (char *)clippedRects); + xfree(clippedRects); } if (rep.numBackClipRects) { - WriteToClient(client, - sizeof(drm_clip_rect_t) * rep.numBackClipRects, - (char *)pBackClipRects); + WriteToClient(client, + sizeof(drm_clip_rect_t) * rep.numBackClipRects, + (char *)backClipRects); } EPHYR_LOG ("leave\n") ; diff --git a/hw/kdrive/ephyr/ephyrhostvideo.c b/hw/kdrive/ephyr/ephyrhostvideo.c index 6509274ec..a0ca76bb4 100644 --- a/hw/kdrive/ephyr/ephyrhostvideo.c +++ b/hw/kdrive/ephyr/ephyrhostvideo.c @@ -773,6 +773,7 @@ ephyrHostXVPutImage (int a_port_id, EPHYR_LOG ("enter, num_clip_rects: %d\n", a_clip_rect_nums) ; + memset (&gc_values, 0, sizeof (gc_values)) ; gc = XCreateGC (dpy, hostx_get_window (), 0L, &gc_values); if (!gc) { EPHYR_LOG_ERROR ("failed to create gc \n") ; diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c index 7636e250e..d50c6b1e5 100644 --- a/hw/kdrive/ephyr/hostx.c +++ b/hw/kdrive/ephyr/hostx.c @@ -40,6 +40,7 @@ #include #include #include +#include #include "ephyrlog.h" /* @@ -1215,3 +1216,77 @@ hostx_set_window_geometry (int a_win, EphyrBox *a_geo) return TRUE; } +int +hostx_set_window_bounding_rectangles (int a_window, + EphyrRect *a_rects, + int a_num_rects) +{ + Bool is_ok=FALSE; + Display *dpy=hostx_get_display () ; + int i=0 ; + XRectangle *rects=NULL ; + + EPHYR_RETURN_VAL_IF_FAIL (dpy && a_rects, FALSE) ; + + EPHYR_LOG ("enter. num rects:%d\n", a_num_rects) ; + + rects = calloc (a_num_rects, sizeof (XRectangle)) ; + for (i=0; i Date: Mon, 17 Sep 2007 22:13:51 +0200 Subject: [PATCH 36/44] Xephyr: fix a clipping issue xephyr-dri * hw/kdrive/ephyr/ephyrdri.c: (ephyrDRIGetDrawableInfo): force the back clipping rects to equal the front clipping rects. * hw/kdrive/ephyr/ephyrdriext.c: (ProcXF86DRIGetDrawableInfo): properly overclip the clipping rects we got from the client. This bug fixes a clipping rect that was too small in height, basically. Also fix a possible mem corruption. * hw/kdrive/ephyr/hostx.c: (hostx_set_window_geometry): remove a useless XSync --- hw/kdrive/ephyr/ephyrdri.c | 2 +- hw/kdrive/ephyr/ephyrdriext.c | 50 ++++++++++++++++++----------------- hw/kdrive/ephyr/hostx.c | 1 - 3 files changed, 27 insertions(+), 26 deletions(-) diff --git a/hw/kdrive/ephyr/ephyrdri.c b/hw/kdrive/ephyr/ephyrdri.c index c4637d022..e7d412881 100644 --- a/hw/kdrive/ephyr/ephyrdri.c +++ b/hw/kdrive/ephyr/ephyrdri.c @@ -240,7 +240,7 @@ ephyrDRIGetDrawableInfo (int a_screen, goto out ; } EPHYR_LOG ("host x,y,w,h: (%d,%d,%d,%d)\n", *a_x, *a_y, *a_w, *a_h) ; - if (*a_num_back_clip_rects != *a_num_clip_rects) { + if (*a_num_clip_rects) { free (*a_back_clip_rects) ; *a_back_clip_rects = calloc (*a_num_clip_rects, sizeof (drm_clip_rect_t)) ; diff --git a/hw/kdrive/ephyr/ephyrdriext.c b/hw/kdrive/ephyr/ephyrdriext.c index be07e6475..41a1f4b85 100644 --- a/hw/kdrive/ephyr/ephyrdriext.c +++ b/hw/kdrive/ephyr/ephyrdriext.c @@ -1137,7 +1137,7 @@ ProcXF86DRIGetDrawableInfo (register ClientPtr client) WindowPtr window=NULL; EphyrWindowPair *pair=NULL; int X=0, Y=0, W=0, H=0, backX=0, backY=0, rc=0, i=0; - drm_clip_rect_t *clipRects=NULL, *clippedRects=NULL; + drm_clip_rect_t *clipRects=NULL; drm_clip_rect_t *backClipRects=NULL; EPHYR_LOG ("enter\n") ; @@ -1197,7 +1197,6 @@ ProcXF86DRIGetDrawableInfo (register ClientPtr client) } EPHYR_LOG ("num clip rects:%d, num back clip rects:%d\n", (int)rep.numClipRects, (int)rep.numBackClipRects) ; - backClipRects = clipRects ; rep.drawableX = X; rep.drawableY = Y; @@ -1209,37 +1208,37 @@ ProcXF86DRIGetDrawableInfo (register ClientPtr client) rep.backX = backX; rep.backY = backY; - if (rep.numBackClipRects) - rep.length += sizeof(drm_clip_rect_t) * rep.numBackClipRects; - - clippedRects = clipRects; if (rep.numClipRects) { - /* Clip cliprects to screen dimensions (redirected windows) */ - clippedRects = xalloc(rep.numClipRects * sizeof(drm_clip_rect_t)); - - if (clippedRects) { + if (clipRects) { ScreenPtr pScreen = screenInfo.screens[stuff->screen]; int i=0; - EPHYR_LOG ("clip list of host gl drawable:\n") ; for (i = 0; i < rep.numClipRects; i++) { - clippedRects[i].x1 = max(clipRects[i].x1, 0); - clippedRects[i].y1 = max(clipRects[i].y1, 0); - clippedRects[i].x2 = min(clipRects[i].x2, pScreen->width); - clippedRects[i].y2 = min(clipRects[i].y2, pScreen->height); - EPHYR_LOG ("x1:%d, y1:%d, x2:%d, y2:%d\n", - clippedRects[i].x1, clippedRects[i].y1, - clippedRects[i].x2, clippedRects[i].y2) ; - } + clipRects[i].x1 = max (clipRects[i].x1, 0); + clipRects[i].y1 = max (clipRects[i].y1, 0); + clipRects[i].x2 = min (clipRects[i].x2, + pScreen->width + clipRects[i].x1) ; + clipRects[i].y2 = min (clipRects[i].y2, + pScreen->width + clipRects[i].y1) ; - /*rep.numClipRects = j*/; - EPHYR_LOG ("num host clip rects:%d\n", (int)rep.numClipRects) ; + EPHYR_LOG ("x1:%d, y1:%d, x2:%d, y2:%d\n", + clipRects[i].x1, clipRects[i].y1, + clipRects[i].x2, clipRects[i].y2) ; + } } else { rep.numClipRects = 0; } - rep.length += sizeof(drm_clip_rect_t) * rep.numClipRects; + } else { + EPHYR_LOG ("got zero host gl drawable clipping rects\n") ; } + rep.length += sizeof(drm_clip_rect_t) * rep.numClipRects; + backClipRects = clipRects ; + rep.numBackClipRects = rep.numClipRects ; + if (rep.numBackClipRects) + rep.length += sizeof(drm_clip_rect_t) * rep.numBackClipRects; + EPHYR_LOG ("num host clip rects:%d\n", (int)rep.numClipRects) ; + EPHYR_LOG ("num host back clip rects:%d\n", (int)rep.numBackClipRects) ; rep.length = ((rep.length + 3) & ~3) >> 2; @@ -1248,8 +1247,7 @@ ProcXF86DRIGetDrawableInfo (register ClientPtr client) if (rep.numClipRects) { WriteToClient(client, sizeof(drm_clip_rect_t) * rep.numClipRects, - (char *)clippedRects); - xfree(clippedRects); + (char *)clipRects); } if (rep.numBackClipRects) { @@ -1257,6 +1255,10 @@ ProcXF86DRIGetDrawableInfo (register ClientPtr client) sizeof(drm_clip_rect_t) * rep.numBackClipRects, (char *)backClipRects); } + if (clipRects) { + xfree(clipRects); + clipRects = NULL ; + } EPHYR_LOG ("leave\n") ; return (client->noClientException); diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c index d50c6b1e5..dd988dc69 100644 --- a/hw/kdrive/ephyr/hostx.c +++ b/hw/kdrive/ephyr/hostx.c @@ -1211,7 +1211,6 @@ hostx_set_window_geometry (int a_win, EphyrBox *a_geo) XMoveWindow (dpy, a_win, a_geo->x, a_geo->y) ; XResizeWindow (dpy, a_win, a_geo->width, a_geo->height) ; - XFlush (dpy) ; EPHYR_LOG ("leave\n") ; return TRUE; } From 6307ee77091041af2d34e93bc164352d4438a808 Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Tue, 18 Sep 2007 18:22:44 +0200 Subject: [PATCH 37/44] GLX: allow skipping of visual init wrapping * GL/glx/glxvisuals.c: added boolean to disable calling init_visuals(). This gives a chance to Xephyr to take over visuals manipulation and avoid a crash at server shutdown in __glXMesaScreenDestroy(), due to the fact that mesa might sees more visual than what it has actually created in init_visuals(). It might see more visuals because Xephyr can augment the number of visuals, dynamically. * os/utils.c: the boolean is actually defined here. --- GL/glx/glxvisuals.c | 8 +++++--- os/utils.c | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/GL/glx/glxvisuals.c b/GL/glx/glxvisuals.c index 0e9bdedec..46b380b3d 100644 --- a/GL/glx/glxvisuals.c +++ b/GL/glx/glxvisuals.c @@ -55,6 +55,7 @@ void GlxWrapInitVisuals(miInitVisualsProcPtr *); +extern Bool noGlxVisualInit; #include "glcontextmodes.h" struct ScreenVisualsRec { @@ -452,14 +453,15 @@ Bool GlxInitVisuals(VisualPtr *visualp, DepthPtr *depthp, /* * Setup the visuals supported by this particular screen. */ - init_visuals(nvisualp, visualp, defaultVisp, - *ndepthp, *depthp, *rootDepthp); + if (!noGlxVisualInit) { + init_visuals(nvisualp, visualp, defaultVisp, + *ndepthp, *depthp, *rootDepthp); + } return True; } - /************************************************************************/ diff --git a/os/utils.c b/os/utils.c index 36c8dfeb3..31cb0af92 100644 --- a/os/utils.c +++ b/os/utils.c @@ -160,6 +160,7 @@ _X_EXPORT Bool noFontCacheExtension = FALSE; #endif #ifdef GLXEXT _X_EXPORT Bool noGlxExtension = FALSE; +_X_EXPORT Bool noGlxVisualInit = FALSE; #endif #ifdef SCREENSAVER _X_EXPORT Bool noScreenSaverExtension = FALSE; From a5bd536869f646e4024befa84f6e677b990310bc Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Tue, 18 Sep 2007 18:28:25 +0200 Subject: [PATCH 38/44] fbcmap_mi.c: add a missing api * fb/fbcmap_mi.c: (fbSetVisualTypesAndMasks): added this entry point that was missing. This is useful so that servers using this entry point can use fbcmap_mi.c, and be obliged to stick to fbcmap.c. Note that fbcmap.c does implement this entry point. Up to now, kdrive based server could not use fbcmap_mi.c because this entry point was missing. The will allow Xephyr to properly use GL. --- fb/fbcmap_mi.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/fb/fbcmap_mi.c b/fb/fbcmap_mi.c index 58bcae3aa..188decd4c 100644 --- a/fb/fbcmap_mi.c +++ b/fb/fbcmap_mi.c @@ -103,6 +103,14 @@ fbSetVisualTypes (int depth, int visuals, int bitsPerRGB) return miSetVisualTypes(depth, visuals, bitsPerRGB, -1); } +Bool +fbSetVisualTypesAndMasks (int depth, int visuals, int bitsPerRGB, + Pixel redMask, Pixel greenMask, Pixel blueMask) +{ + return miSetVisualTypesAndMasks(depth, visuals, bitsPerRGB, -1, + redMask, greenMask, blueMask); +} + /* * Given a list of formats for a screen, create a list * of visuals and depths for the screen which coorespond to From 50674391388b3cfe987782a3ad81b4f240f3db67 Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Tue, 18 Sep 2007 18:37:49 +0200 Subject: [PATCH 39/44] Kdrive: use fbcmap_mi.c instead of fbcmap.c * hw/kdrive/src/Makefile.am: use fb/fbcmap_mi.c and not fb/fbcmap.c. This allows kdrive to take advantage of extensions redefining the entry points of micmap.c stuff. For instance it allows Xephyr to have a working GL, which is not possible otherwise, because GL redefines mInitVisualsProc to initialise its visuals. --- hw/kdrive/src/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/kdrive/src/Makefile.am b/hw/kdrive/src/Makefile.am index 20fae554a..07ab8c859 100644 --- a/hw/kdrive/src/Makefile.am +++ b/hw/kdrive/src/Makefile.am @@ -37,4 +37,4 @@ libkdrive_a_SOURCES = \ $(top_srcdir)/mi/miinitext.c libkdrivestubs_a_SOURCES = \ - $(top_srcdir)/fb/fbcmap.c + $(top_srcdir)/fb/fbcmap_mi.c From f731b9da7dbafad50dd5a1e8da28ce86ffab19b7 Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Tue, 18 Sep 2007 18:41:18 +0200 Subject: [PATCH 40/44] Xephyr: add -nodri and -noxv switches. * hw/kdrive/ephyr/ephyr.c,ephyrinit.c:: add -nodri and -noxv to disable either DRI or XV. When -nodri, mesa GL (non acceleretated) works. --- hw/kdrive/ephyr/ephyr.c | 19 +++++++++++++------ hw/kdrive/ephyr/ephyrinit.c | 20 ++++++++++++++++++++ 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c index 63e0cb166..85aab280f 100644 --- a/hw/kdrive/ephyr/ephyr.c +++ b/hw/kdrive/ephyr/ephyr.c @@ -43,6 +43,8 @@ extern int KdTsPhyScreen; KdKeyboardInfo *ephyrKbd; KdPointerInfo *ephyrMouse; EphyrKeySyms ephyrKeySyms; +Bool ephyrNoDRI=FALSE ; +Bool ephyrNoXV=FALSE ; static int mouseState = 0; @@ -616,18 +618,23 @@ ephyrInitScreen (ScreenPtr pScreen) pScreen->CreateColormap = ephyrCreateColormap; #ifdef XV - if (!ephyrInitVideo (pScreen)) { - EPHYR_LOG_ERROR ("failed to initialize xvideo\n") ; - } else { - EPHYR_LOG ("initialized xvideo okay\n") ; + if (!ephyrNoXV) { + if (!ephyrInitVideo (pScreen)) { + EPHYR_LOG_ERROR ("failed to initialize xvideo\n") ; + } else { + EPHYR_LOG ("initialized xvideo okay\n") ; + } } #endif /*XV*/ #ifdef XEPHYR_DRI + if (!ephyrNoDRI) { ephyrDRIExtensionInit (pScreen) ; ephyrHijackGLXExtension () ; ephyrProxyExtensionInit ("ATIFGLRXDRI") ; + } #endif + return TRUE; } @@ -639,12 +646,12 @@ ephyrFinishInitScreen (ScreenPtr pScreen) */ if (!shadowSetup (pScreen)) return FALSE; - + #ifdef RANDR if (!ephyrRandRInit (pScreen)) return FALSE; #endif - + return TRUE; } diff --git a/hw/kdrive/ephyr/ephyrinit.c b/hw/kdrive/ephyr/ephyrinit.c index c8fbdfff5..cc7a36700 100644 --- a/hw/kdrive/ephyr/ephyrinit.c +++ b/hw/kdrive/ephyr/ephyrinit.c @@ -33,6 +33,9 @@ extern Window EphyrPreExistingHostWin; extern Bool EphyrWantGrayScale; extern Bool kdHasPointer; extern Bool kdHasKbd; +extern Bool ephyrNoDRI; +extern Bool ephyrNoXV; +extern Bool noGlxVisualInit; void processScreenArg (char *screen_size, char *parent_id) ; @@ -99,6 +102,8 @@ ddxUseMsg (void) ErrorF("-grayscale Simulate 8bit grayscale\n"); ErrorF("-fakexa Simulate acceleration using software rendering\n"); ErrorF("-verbosity Set log verbosity level\n"); + ErrorF("-nodri do not use DRI\n"); + ErrorF("-noxv do not use XV\n"); ErrorF("\n"); exit(1); @@ -139,6 +144,8 @@ ddxProcessArgument (int argc, char **argv, int i) { EPHYR_DBG("mark argv[%d]='%s'", i, argv[i] ); + noGlxVisualInit = TRUE ; + if (!strcmp (argv[i], "-parent")) { if(i+1 < argc) @@ -199,6 +206,19 @@ ddxProcessArgument (int argc, char **argv, int i) exit(1) ; } } + else if (!strcmp (argv[i], "-nodri")) + { + noGlxVisualInit = FALSE ; + ephyrNoDRI = TRUE ; + EPHYR_LOG ("no direct rendering enabled\n") ; + return 1 ; + } + else if (!strcmp (argv[i], "-noxv")) + { + ephyrNoXV = TRUE ; + EPHYR_LOG ("no XVideo enabled\n") ; + return 1 ; + } else if (argv[i][0] == ':') { hostx_set_display_name(argv[i]); From 2b217fc055300d4c709dd27c4e8ec8166183993b Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Wed, 19 Sep 2007 15:00:43 +0200 Subject: [PATCH 41/44] Xephyr: cleanup XF86dri.c a bit --- hw/kdrive/ephyr/XF86dri.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/hw/kdrive/ephyr/XF86dri.c b/hw/kdrive/ephyr/XF86dri.c index bf6c54f97..f3f317907 100644 --- a/hw/kdrive/ephyr/XF86dri.c +++ b/hw/kdrive/ephyr/XF86dri.c @@ -108,9 +108,7 @@ static XEXT_GENERATE_CLOSE_DISPLAY (close_display, xf86dri_info) #endif -Bool XF86DRIQueryExtension (dpy, event_basep, error_basep) - Display *dpy; - int *event_basep, *error_basep; +Bool XF86DRIQueryExtension (Display *dpy, int *event_basep, int *error_basep) { XExtDisplayInfo *info = find_display (dpy); From 6a435b00003fb00930299a0e0810c93afc23a72e Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Wed, 19 Sep 2007 15:35:51 +0200 Subject: [PATCH 42/44] Xephyr: check presence of extensions in host X * hw/kdrive/ephyr/hostx.c,h: (hostx_has_xshape), (hostx_has_glx), (hostx_has_dri): added these new entry points * hw/kdrive/ephyr/ephyrdriext.c: (ephyrDRIExtensionInit): check presence of DRI and XShape extensions before trying to use them. * hw/kdrive/ephyr/ephyrglxext.c: (ephyrHijackGLXExtension): check presence of glx extension before we use it. --- hw/kdrive/ephyr/ephyrdriext.c | 10 ++ hw/kdrive/ephyr/ephyrglxext.c | 7 +- hw/kdrive/ephyr/hostx.c | 180 ++++++++++++++++++++++------------ hw/kdrive/ephyr/hostx.h | 26 +++-- 4 files changed, 151 insertions(+), 72 deletions(-) diff --git a/hw/kdrive/ephyr/ephyrdriext.c b/hw/kdrive/ephyr/ephyrdriext.c index 41a1f4b85..26c792d52 100644 --- a/hw/kdrive/ephyr/ephyrdriext.c +++ b/hw/kdrive/ephyr/ephyrdriext.c @@ -136,6 +136,16 @@ ephyrDRIExtensionInit (ScreenPtr a_screen) EphyrDRIScreenPrivPtr screen_priv=NULL ; EPHYR_LOG ("enter\n") ; + if (!hostx_has_dri ()) { + EPHYR_LOG ("host does not have DRI extension\n") ; + goto out ; + } + EPHYR_LOG ("host X does have DRI extension\n") ; + if (!hostx_has_xshape ()) { + EPHYR_LOG ("host does not have XShape extension\n") ; + goto out ; + } + EPHYR_LOG ("host X does have XShape extension\n") ; #ifdef XF86DRI_EVENTS EventType = CreateNewResourceType (XF86DRIFreeEvents); diff --git a/hw/kdrive/ephyr/ephyrglxext.c b/hw/kdrive/ephyr/ephyrglxext.c index 27b2a2dc3..47c4fb1c8 100644 --- a/hw/kdrive/ephyr/ephyrglxext.c +++ b/hw/kdrive/ephyr/ephyrglxext.c @@ -81,7 +81,12 @@ ephyrHijackGLXExtension (void) { const void *(*dispatch_functions)[2]; - EPHYR_LOG ("going to hijack some glx entry points ...\n") ; + if (!hostx_has_glx ()) { + EPHYR_LOG ("host X does not have GLX\n") ; + return FALSE ; + } + EPHYR_LOG ("host X does have GLX\n") ; + if (!Single_dispatch_info.dispatch_functions) { EPHYR_LOG_ERROR ("could not get dispatch functions table\n") ; return FALSE ; diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c index dd988dc69..0ef1a6283 100644 --- a/hw/kdrive/ephyr/hostx.c +++ b/hw/kdrive/ephyr/hostx.c @@ -23,6 +23,10 @@ * PERFORMANCE OF THIS SOFTWARE. */ +#ifdef HAVE_CONFIG_H +#include +#endif + #include "hostx.h" #include @@ -41,8 +45,17 @@ #include #include #include +#ifdef XEPHYR_DRI +#include +#endif /*XEPHYR_DRI*/ #include "ephyrlog.h" +#ifdef XEPHYR_DRI +extern Bool XF86DRIQueryExtension (Display *dpy, + int *event_basep, + int *error_basep); +#endif + /* * All xlib calls go here, which gets built as its own .a . * Mixing kdrive and xlib headers causes all sorts of types @@ -1070,68 +1083,6 @@ typedef struct { #define RESOURCE_PEERS_SIZE 1024*10 static ResourcePair resource_peers[RESOURCE_PEERS_SIZE] ; -int -hostx_allocate_resource_id_peer (int a_local_resource_id, - int *a_remote_resource_id) -{ - int i=0 ; - ResourcePair *peer=NULL ; - Display *dpy=hostx_get_display (); - - /* - * first make sure a resource peer - * does not exist already for - * a_local_resource_id - */ - for (i=0; iremote_id = XAllocID (dpy); - peer->local_id = a_local_resource_id ; - peer->is_valid = TRUE ; - } - } - if (peer) { - *a_remote_resource_id = peer->remote_id ; - return TRUE ; - } - return FALSE ; -} - -int -hostx_get_resource_id_peer (int a_local_resource_id, - int *a_remote_resource_id) -{ - int i=0 ; - ResourcePair *peer=NULL ; - for (i=0; iremote_id ; - return TRUE ; - } - return FALSE ; -} int hostx_create_window (EphyrBox *a_geometry, @@ -1289,3 +1240,108 @@ hostx_set_window_clipping_rectangles (int a_window, return is_ok; } +int +hostx_has_xshape (void) +{ + int event_base=0, error_base=0 ; + Display *dpy=hostx_get_display () ; + if (!XShapeQueryExtension (dpy, + &event_base, + &error_base)) { + return FALSE ; + } + return TRUE; +} + +#ifdef XEPHYR_DRI +int +hostx_allocate_resource_id_peer (int a_local_resource_id, + int *a_remote_resource_id) +{ + int i=0 ; + ResourcePair *peer=NULL ; + Display *dpy=hostx_get_display (); + + /* + * first make sure a resource peer + * does not exist already for + * a_local_resource_id + */ + for (i=0; iremote_id = XAllocID (dpy); + peer->local_id = a_local_resource_id ; + peer->is_valid = TRUE ; + } + } + if (peer) { + *a_remote_resource_id = peer->remote_id ; + return TRUE ; + } + return FALSE ; +} + +int +hostx_get_resource_id_peer (int a_local_resource_id, + int *a_remote_resource_id) +{ + int i=0 ; + ResourcePair *peer=NULL ; + for (i=0; iremote_id ; + return TRUE ; + } + return FALSE ; +} + +int +hostx_has_dri (void) +{ + int event_base=0, error_base=0 ; + Display *dpy=hostx_get_display () ; + + if (!XF86DRIQueryExtension (dpy, + &event_base, + &error_base)) { + return FALSE ; + } + return TRUE ; +} + +int +hostx_has_glx (void) +{ + Display *dpy=hostx_get_display () ; + int event_base=0, error_base=0 ; + + if (!glXQueryExtension (dpy, &event_base, &error_base)) { + return FALSE ; + } + return TRUE ; +} + +#endif /*XEPHYR_DRI*/ + diff --git a/hw/kdrive/ephyr/hostx.h b/hw/kdrive/ephyr/hostx.h index 70255a1b7..941eeceb5 100644 --- a/hw/kdrive/ephyr/hostx.h +++ b/hw/kdrive/ephyr/hostx.h @@ -215,12 +215,6 @@ hostx_get_extension_info (const char *a_ext_name, int hostx_get_visuals_info (EphyrHostVisualInfo **a_visuals, int *a_num_entries) ; -int -hostx_allocate_resource_id_peer (int a_local_resource_id, - int *a_remote_resource_id) ; -int -hostx_get_resource_id_peer (int a_local_resource_id, - int *a_remote_resource_id) ; int hostx_create_window (EphyrBox *a_geometry, int a_visual_id, @@ -230,8 +224,6 @@ int hostx_destroy_window (int a_win) ; int hostx_set_window_geometry (int a_win, EphyrBox *a_geo) ; -int hostx_lookup_peer_window (void *a_local_window, - int *a_host_peer /*out parameter*/) ; int hostx_set_window_bounding_rectangles (int a_window, EphyrRect *a_rects, @@ -239,4 +231,20 @@ int hostx_set_window_bounding_rectangles (int a_window, int hostx_set_window_clipping_rectangles (int a_window, EphyrRect *a_rects, int a_num_rects) ; -#endif +int hostx_has_xshape (void) ; + +#ifdef XEPHYR_DRI +int hostx_lookup_peer_window (void *a_local_window, + int *a_host_peer /*out parameter*/) ; +int +hostx_allocate_resource_id_peer (int a_local_resource_id, + int *a_remote_resource_id) ; +int +hostx_get_resource_id_peer (int a_local_resource_id, + int *a_remote_resource_id) ; +int hostx_has_dri (void) ; + +int hostx_has_glx (void) ; +#endif /*XEPHYR_DRI*/ + +#endif /*_XLIBS_STUFF_H_*/ From dcb4db1bf5b6fcfaed4e7162eb6c7a3a509e14bd Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Wed, 19 Sep 2007 15:46:09 +0200 Subject: [PATCH 43/44] Xephyr: glx fixlet * hw/kdrive/ephyr/ephyrhostglx.c: (ephyrHostGLXQueryVersion): properly query the host for its gxl version. --- hw/kdrive/ephyr/ephyrhostglx.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/hw/kdrive/ephyr/ephyrhostglx.c b/hw/kdrive/ephyr/ephyrhostglx.c index 21a109e64..ad86d3009 100644 --- a/hw/kdrive/ephyr/ephyrhostglx.c +++ b/hw/kdrive/ephyr/ephyrhostglx.c @@ -85,18 +85,35 @@ ephyrHostGLXQueryVersion (int *a_major, int *a_minor) { Bool is_ok = FALSE ; Display *dpy = hostx_get_display () ; + int major_opcode=0; + xGLXQueryVersionReq *req=NULL; + xGLXQueryVersionReply reply; EPHYR_RETURN_VAL_IF_FAIL (a_major && a_minor, FALSE) ; EPHYR_LOG ("enter\n") ; - *a_major = 1 ; - *a_minor = 2 ; - /* - if (!glXQueryVersion (dpy, a_major, a_minor)) { - EPHYR_LOG_ERROR ("glxQueryVersion() failed\n") ; + if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) { + EPHYR_LOG_ERROR ("failed to get major opcode\n") ; goto out ; } - */ + EPHYR_LOG ("major opcode: %d\n", major_opcode) ; + + /* Send the glXQueryVersion request */ + memset (&reply, 0, sizeof (reply)) ; + LockDisplay (dpy); + GetReq (GLXQueryVersion, req); + req->reqType = major_opcode; + req->glxCode = X_GLXQueryVersion; + req->majorVersion = 2; + req->minorVersion = 1; + _XReply(dpy, (xReply*) &reply, 0, False); + UnlockDisplay (dpy); + SyncHandle (); + + *a_major = reply.majorVersion ; + *a_minor = reply.minorVersion ; + + EPHYR_LOG ("major:%d, minor:%d\n", *a_major, *a_minor) ; is_ok = TRUE ; out: From 4ba76a7e2b62d26f43c0e670de571afb75ec92f4 Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Wed, 3 Oct 2007 13:03:34 +0200 Subject: [PATCH 44/44] Xephyr: port XV/GL stuff of the new multiscreen architecture We can now launch GL or XV apps in any of the Xephyr screens we want. * hw/kdrive/ephyr/hostx.c,h: (hostx_get_window): (hostx_create_window): make these functions be screen number aware. * hw/kdrive/ephyr/XF86dri.c : fix some compiler warnings. * hw/kdrive/ephyr/ephyrdri.c: (ephyrDRIQueryDirectRenderingCapable), (ephyrDRIOpenConnection), (ephyrDRIAuthConnection), (ephyrDRICloseConnection), (ephyrDRIGetClientDriverName), (ephyrDRICreateContext), (ephyrDRIDestroyContext), (ephyrDRICreateDrawable), (ephyrDRIGetDrawableInfo), (ephyrDRIGetDeviceInfo): in all those functions, don't forward the screen number we receive - from the client - to the host X. We (Xephyr) are always targetting the same X display screen, which is the one Xephyr got launched against. So we enforce that in the code. * hw/kdrive/ephyr/ephyrdriext.c: (EphyrMirrorHostVisuals): make this duplicate the visuals of the host X default screen into a given Xephyr screen. This way we have a chance to update the visuals of all Xephyr screen to make them mirror those of the host X. (many other places): specify screen number where required by the api change in hostx.h. * hw/kdrive/ephyr/ephyrglxext.c: specify screen number where required by the api change in hostx.h * hw/kdrive/ephyr/ephyrhostglx.c: don't forward the screen number we receive - from the client - to the host X. We (Xephyr) are always targetting the same X display screen, which is the one Xephyr got launched against. So we enforce that in the code. * hw/kdrive/ephyr/ephyrhostvideo.c,h: take in account the screen number received from the client app. This is useful to know on which Xephyr screen we need to display video stuff. * hw/kdrive/ephyr/ephyrvideo.c: update this to reflect the API change in hw/kdrive/ephyr/ephyrhostvideo.h. (ephyrSetPortAttribute): when parameters are not valid - they exceed their validity range - send them to the host anyway and do not return an error to clients. Some host expose buggy validity range, so rejecting client for that is too harsh. --- hw/kdrive/ephyr/XF86dri.c | 2 ++ hw/kdrive/ephyr/ephyrdri.c | 24 ++++++++++-------- hw/kdrive/ephyr/ephyrdriext.c | 13 ++++++---- hw/kdrive/ephyr/ephyrglxext.c | 17 +++++++++++-- hw/kdrive/ephyr/ephyrhostglx.c | 10 ++++---- hw/kdrive/ephyr/ephyrhostvideo.c | 36 ++++++++++++++------------- hw/kdrive/ephyr/ephyrhostvideo.h | 17 ++++++++----- hw/kdrive/ephyr/ephyrvideo.c | 42 +++++++++++++++++++++++++------- hw/kdrive/ephyr/hostx.c | 13 +++++++--- hw/kdrive/ephyr/hostx.h | 12 +++++---- 10 files changed, 123 insertions(+), 63 deletions(-) diff --git a/hw/kdrive/ephyr/XF86dri.c b/hw/kdrive/ephyr/XF86dri.c index f3f317907..ae2ec890f 100644 --- a/hw/kdrive/ephyr/XF86dri.c +++ b/hw/kdrive/ephyr/XF86dri.c @@ -107,6 +107,8 @@ static XEXT_GENERATE_CLOSE_DISPLAY (close_display, xf86dri_info) #define TRACE(msg) #endif +Bool XF86DRIOpenFullScreen(Display *dpy, int screen, Drawable drawable); +Bool XF86DRICloseFullScreen(Display *dpy, int screen, Drawable drawable); Bool XF86DRIQueryExtension (Display *dpy, int *event_basep, int *error_basep) { diff --git a/hw/kdrive/ephyr/ephyrdri.c b/hw/kdrive/ephyr/ephyrdri.c index e7d412881..53a96ba11 100644 --- a/hw/kdrive/ephyr/ephyrdri.c +++ b/hw/kdrive/ephyr/ephyrdri.c @@ -59,7 +59,8 @@ ephyrDRIQueryDirectRenderingCapable (int a_screen, Bool *a_is_capable) EPHYR_RETURN_VAL_IF_FAIL (a_is_capable, FALSE) ; EPHYR_LOG ("enter\n") ; - is_ok = XF86DRIQueryDirectRenderingCapable (dpy, a_screen, a_is_capable) ; + is_ok = XF86DRIQueryDirectRenderingCapable (dpy, DefaultScreen (dpy), + a_is_capable) ; EPHYR_LOG ("leave. is_capable:%d, is_ok=%d\n", *a_is_capable, is_ok) ; return is_ok ; @@ -75,7 +76,9 @@ ephyrDRIOpenConnection (int a_screen, EPHYR_RETURN_VAL_IF_FAIL (a_bus_id_string, FALSE) ; EPHYR_LOG ("enter. screen:%d\n", a_screen) ; - is_ok = XF86DRIOpenConnection (dpy, a_screen, a_sarea, a_bus_id_string) ; + is_ok = XF86DRIOpenConnection (dpy, DefaultScreen (dpy), + a_sarea, + a_bus_id_string) ; if (*a_bus_id_string) { EPHYR_LOG ("leave. bus_id_string:%s, is_ok:%d\n", *a_bus_id_string, is_ok) ; @@ -93,7 +96,7 @@ ephyrDRIAuthConnection (int a_screen, drm_magic_t a_magic) Bool is_ok=FALSE ; EPHYR_LOG ("enter\n") ; - is_ok = XF86DRIAuthConnection (dpy, a_screen, a_magic) ; + is_ok = XF86DRIAuthConnection (dpy, DefaultScreen (dpy), a_magic) ; EPHYR_LOG ("leave. is_ok:%d\n", is_ok) ; return is_ok ; } @@ -105,7 +108,7 @@ ephyrDRICloseConnection (int a_screen) Bool is_ok=FALSE ; EPHYR_LOG ("enter\n") ; - is_ok = XF86DRICloseConnection (dpy, a_screen) ; + is_ok = XF86DRICloseConnection (dpy, DefaultScreen (dpy)) ; EPHYR_LOG ("leave\n") ; return is_ok ; } @@ -126,7 +129,7 @@ ephyrDRIGetClientDriverName (int a_screen, && a_client_driver_name, FALSE); EPHYR_LOG ("enter\n") ; - is_ok = XF86DRIGetClientDriverName (dpy, a_screen, + is_ok = XF86DRIGetClientDriverName (dpy, DefaultScreen (dpy), a_ddx_driver_major_version, a_ddx_driver_minor_version, a_ddx_driver_patch_version, @@ -154,7 +157,7 @@ ephyrDRICreateContext (int a_screen, memset (&v, 0, sizeof (v)) ; v.visualid = a_visual_id ; is_ok = XF86DRICreateContext (dpy, - a_screen, + DefaultScreen (dpy), &v, a_returned_ctxt_id, a_hw_ctxt) ; @@ -170,7 +173,7 @@ ephyrDRIDestroyContext (int a_screen, Bool is_ok=FALSE ; EPHYR_LOG ("enter\n") ; - is_ok = XF86DRIDestroyContext (dpy, a_screen, a_context_id) ; + is_ok = XF86DRIDestroyContext (dpy, DefaultScreen (dpy), a_context_id) ; EPHYR_LOG ("leave:%d\n", is_ok) ; return is_ok ; } @@ -184,7 +187,8 @@ ephyrDRICreateDrawable (int a_screen, Display *dpy=hostx_get_display () ; EPHYR_LOG ("enter\n") ; - is_ok = XF86DRICreateDrawable (dpy, a_screen, a_drawable, a_hw_drawable) ; + is_ok = XF86DRICreateDrawable (dpy, DefaultScreen (dpy), + a_drawable, a_hw_drawable) ; EPHYR_LOG ("leave. is_ok:%d\n", is_ok) ; return is_ok ; } @@ -228,7 +232,7 @@ ephyrDRIGetDrawableInfo (int a_screen, EPHYR_LOG_ERROR ("failed to query host window attributes\n") ; goto out; } - if (!XF86DRIGetDrawableInfo (dpy, a_screen, a_drawable, + if (!XF86DRIGetDrawableInfo (dpy, DefaultScreen (dpy), a_drawable, a_index, a_stamp, a_x, a_y, a_w, a_h, @@ -277,7 +281,7 @@ ephyrDRIGetDeviceInfo (int a_screen, EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; EPHYR_LOG ("enter\n") ; - is_ok = XF86DRIGetDeviceInfo (dpy, a_screen, a_frame_buffer, + is_ok = XF86DRIGetDeviceInfo (dpy, DefaultScreen (dpy), a_frame_buffer, a_fb_origin, a_fb_size, a_fb_stride, a_dev_private_size, a_dev_private) ; EPHYR_LOG ("leave:%d\n", is_ok) ; diff --git a/hw/kdrive/ephyr/ephyrdriext.c b/hw/kdrive/ephyr/ephyrdriext.c index 26c792d52..e3d0cfbb4 100644 --- a/hw/kdrive/ephyr/ephyrdriext.c +++ b/hw/kdrive/ephyr/ephyrdriext.c @@ -111,7 +111,7 @@ static Bool ephyrDRIPositionWindow (WindowPtr a_win, static void ephyrDRIClipNotify (WindowPtr a_win, int a_x, int a_y) ; -static Bool EphyrMirrorHostVisuals (void) ; +static Bool EphyrMirrorHostVisuals (ScreenPtr a_screen) ; static Bool destroyHostPeerWindow (const WindowPtr a_win) ; static Bool findWindowPairFromLocal (WindowPtr a_local, EphyrWindowPair **a_pair); @@ -182,7 +182,7 @@ ephyrDRIExtensionInit (ScreenPtr a_screen) EPHYR_LOG_ERROR ("ephyrDRIScreenInit() failed\n") ; goto out ; } - EphyrMirrorHostVisuals () ; + EphyrMirrorHostVisuals (a_screen) ; if (ephyrDRIGeneration != serverGeneration) { ephyrDRIGeneration = serverGeneration ; } @@ -607,7 +607,7 @@ out: * GLX. */ static Bool -EphyrMirrorHostVisuals (void) +EphyrMirrorHostVisuals (ScreenPtr a_screen) { Bool is_ok=FALSE; EphyrHostVisualInfo *visuals=NULL; @@ -619,7 +619,7 @@ EphyrMirrorHostVisuals (void) goto out ; } for (i=0; imyNum, visuals[i].depth, visuals[i].class, visuals[i].bits_per_rgb, @@ -980,6 +980,8 @@ createHostPeerWindow (const WindowPtr a_win, EphyrBox geo ; EPHYR_RETURN_VAL_IF_FAIL (a_win && a_peer_win, FALSE) ; + EPHYR_RETURN_VAL_IF_FAIL (a_win->drawable.pScreen, + FALSE) ; EPHYR_LOG ("enter. a_win '%#x'\n", (unsigned int)a_win) ; if (!getWindowVisual (a_win, &visual)) { @@ -995,7 +997,8 @@ createHostPeerWindow (const WindowPtr a_win, geo.y = a_win->drawable.y ; geo.width = a_win->drawable.width ; geo.height = a_win->drawable.height ; - if (!hostx_create_window (&geo, visual->vid, a_peer_win)) { + if (!hostx_create_window (a_win->drawable.pScreen->myNum, + &geo, visual->vid, a_peer_win)) { EPHYR_LOG_ERROR ("failed to create host peer window\n") ; goto out ; } diff --git a/hw/kdrive/ephyr/ephyrglxext.c b/hw/kdrive/ephyr/ephyrglxext.c index 47c4fb1c8..381c9d7ed 100644 --- a/hw/kdrive/ephyr/ephyrglxext.c +++ b/hw/kdrive/ephyr/ephyrglxext.c @@ -438,7 +438,8 @@ ephyrGLXCreateContextReal (xGLXCreateContextReq *a_req, Bool a_do_swap) (int)a_req->visual, (int)a_req->isDirect) ; memset (&host_w_attrs, 0, sizeof (host_w_attrs)) ; - if (!hostx_get_window_attributes (hostx_get_window (), &host_w_attrs)) { + if (!hostx_get_window_attributes (hostx_get_window (a_req->screen), + &host_w_attrs)) { EPHYR_LOG_ERROR ("failed to get host window attrs\n") ; goto out ; } @@ -513,10 +514,22 @@ ephyrGLXMakeCurrentReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap) int res=BadImplementation; xGLXMakeCurrentReq *req = (xGLXMakeCurrentReq *) a_pc; xGLXMakeCurrentReply reply ; + DrawablePtr drawable=NULL; + int rc=0; EPHYR_LOG ("enter\n") ; + rc = dixLookupDrawable (&drawable, + req->drawable, + a_cl->client, + 0, + DixReadAccess); + EPHYR_RETURN_VAL_IF_FAIL (drawable, BadValue) ; + EPHYR_RETURN_VAL_IF_FAIL (drawable->pScreen, BadValue) ; + EPHYR_LOG ("screen nummber requested:%d\n", + drawable->pScreen->myNum) ; + memset (&reply, 0, sizeof (reply)) ; - if (!ephyrHostGLXMakeCurrent (hostx_get_window (), + if (!ephyrHostGLXMakeCurrent (hostx_get_window (drawable->pScreen->myNum), req->context, req->oldContextTag, (int*)&reply.contextTag)) { diff --git a/hw/kdrive/ephyr/ephyrhostglx.c b/hw/kdrive/ephyr/ephyrhostglx.c index ad86d3009..5d9a482e8 100644 --- a/hw/kdrive/ephyr/ephyrhostglx.c +++ b/hw/kdrive/ephyr/ephyrhostglx.c @@ -188,7 +188,7 @@ ephyrHostGLXGetStringFromServer (int a_screen_number, GetReq (GLXGenericGetString, req); req->reqType = major_opcode; req->glxCode = get_string_op; - req->for_whom = a_screen_number; + req->for_whom = DefaultScreen (dpy); req->name = a_string_name; _XReply (dpy, (xReply *)&reply, 0, False); @@ -263,7 +263,7 @@ ephyrHostGLXGetVisualConfigsInternal (enum VisualConfRequestType a_type, GetReq(GLXGetFBConfigs,fb_req); fb_req->reqType = major_opcode; fb_req->glxCode = X_GLXGetFBConfigs; - fb_req->screen = a_screen; + fb_req->screen = DefaultScreen (dpy); break; case EPHYR_VENDOR_PRIV_GET_FB_CONFIG_SGIX: @@ -276,14 +276,14 @@ ephyrHostGLXGetVisualConfigsInternal (enum VisualConfRequestType a_type, sgi_req->reqType = major_opcode; sgi_req->glxCode = X_GLXVendorPrivateWithReply; sgi_req->vendorCode = X_GLXvop_GetFBConfigsSGIX; - sgi_req->screen = a_screen; + sgi_req->screen = DefaultScreen (dpy); break; case EPHYR_GET_VISUAL_CONFIGS: GetReq(GLXGetVisualConfigs,req); req->reqType = major_opcode; req->glxCode = X_GLXGetVisualConfigs; - req->screen = a_screen; + req->screen = DefaultScreen (dpy); break; } @@ -460,7 +460,7 @@ ephyrHostGLXCreateContext (int a_screen, req->glxCode = X_GLXCreateContext; req->context = remote_context_id; req->visual = a_visual_id; - req->screen = a_screen; + req->screen = DefaultScreen (dpy); req->shareList = a_share_list_ctxt_id; req->isDirect = a_direct; diff --git a/hw/kdrive/ephyr/ephyrhostvideo.c b/hw/kdrive/ephyr/ephyrhostvideo.c index a0ca76bb4..562c2a4e8 100644 --- a/hw/kdrive/ephyr/ephyrhostvideo.c +++ b/hw/kdrive/ephyr/ephyrhostvideo.c @@ -745,7 +745,8 @@ ephyrHostFree (void *a_pointer) } Bool -ephyrHostXVPutImage (int a_port_id, +ephyrHostXVPutImage (int a_screen_num, + int a_port_id, int a_image_id, int a_drw_x, int a_drw_y, @@ -774,7 +775,7 @@ ephyrHostXVPutImage (int a_port_id, EPHYR_LOG ("enter, num_clip_rects: %d\n", a_clip_rect_nums) ; memset (&gc_values, 0, sizeof (gc_values)) ; - gc = XCreateGC (dpy, hostx_get_window (), 0L, &gc_values); + gc = XCreateGC (dpy, hostx_get_window (a_screen_num), 0L, &gc_values); if (!gc) { EPHYR_LOG_ERROR ("failed to create gc \n") ; goto out ; @@ -802,7 +803,8 @@ ephyrHostXVPutImage (int a_port_id, XSetClipRectangles (dpy, gc, 0, 0, rects, a_clip_rect_nums, YXBanded) ; /*this always returns 1*/ } - res = XvPutImage (dpy, a_port_id, hostx_get_window (), + res = XvPutImage (dpy, a_port_id, + hostx_get_window (a_screen_num), gc, xv_image, a_src_x, a_src_y, a_src_w, a_src_h, a_drw_x, a_drw_y, a_drw_w, a_drw_h) ; @@ -830,7 +832,7 @@ out: } Bool -ephyrHostXVPutVideo (int a_port_id, +ephyrHostXVPutVideo (int a_screen_num, int a_port_id, int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) { @@ -842,12 +844,12 @@ ephyrHostXVPutVideo (int a_port_id, EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; - gc = XCreateGC (dpy, hostx_get_window (), 0L, &gc_values); + gc = XCreateGC (dpy, hostx_get_window (a_screen_num), 0L, &gc_values); if (!gc) { EPHYR_LOG_ERROR ("failed to create gc \n") ; goto out ; } - res = XvPutVideo (dpy, a_port_id, hostx_get_window (), gc, + res = XvPutVideo (dpy, a_port_id, hostx_get_window (a_screen_num), gc, a_vid_x, a_vid_y, a_vid_w, a_vid_h, a_drw_x, a_drw_y, a_drw_w, a_drw_h) ; @@ -867,7 +869,7 @@ out: } Bool -ephyrHostXVGetVideo (int a_port_id, +ephyrHostXVGetVideo (int a_screen_num, int a_port_id, int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) { @@ -879,12 +881,12 @@ ephyrHostXVGetVideo (int a_port_id, EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; - gc = XCreateGC (dpy, hostx_get_window (), 0L, &gc_values); + gc = XCreateGC (dpy, hostx_get_window (a_screen_num), 0L, &gc_values); if (!gc) { EPHYR_LOG_ERROR ("failed to create gc \n") ; goto out ; } - res = XvGetVideo (dpy, a_port_id, hostx_get_window (), gc, + res = XvGetVideo (dpy, a_port_id, hostx_get_window (a_screen_num), gc, a_vid_x, a_vid_y, a_vid_w, a_vid_h, a_drw_x, a_drw_y, a_drw_w, a_drw_h) ; @@ -904,7 +906,7 @@ out: } Bool -ephyrHostXVPutStill (int a_port_id, +ephyrHostXVPutStill (int a_screen_num, int a_port_id, int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) { @@ -916,12 +918,12 @@ ephyrHostXVPutStill (int a_port_id, EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; - gc = XCreateGC (dpy, hostx_get_window (), 0L, &gc_values); + gc = XCreateGC (dpy, hostx_get_window (a_screen_num), 0L, &gc_values); if (!gc) { EPHYR_LOG_ERROR ("failed to create gc \n") ; goto out ; } - res = XvPutStill (dpy, a_port_id, hostx_get_window (), gc, + res = XvPutStill (dpy, a_port_id, hostx_get_window (a_screen_num), gc, a_vid_x, a_vid_y, a_vid_w, a_vid_h, a_drw_x, a_drw_y, a_drw_w, a_drw_h) ; @@ -941,7 +943,7 @@ out: } Bool -ephyrHostXVGetStill (int a_port_id, +ephyrHostXVGetStill (int a_screen_num, int a_port_id, int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) { @@ -953,12 +955,12 @@ ephyrHostXVGetStill (int a_port_id, EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; - gc = XCreateGC (dpy, hostx_get_window (), 0L, &gc_values); + gc = XCreateGC (dpy, hostx_get_window (a_screen_num), 0L, &gc_values); if (!gc) { EPHYR_LOG_ERROR ("failed to create gc \n") ; goto out ; } - res = XvGetStill (dpy, a_port_id, hostx_get_window (), gc, + res = XvGetStill (dpy, a_port_id, hostx_get_window (a_screen_num), gc, a_vid_x, a_vid_y, a_vid_w, a_vid_h, a_drw_x, a_drw_y, a_drw_w, a_drw_h) ; @@ -978,7 +980,7 @@ out: } Bool -ephyrHostXVStopVideo (int a_port_id) +ephyrHostXVStopVideo (int a_screen_num, int a_port_id) { int ret=0 ; Bool is_ok=FALSE ; @@ -988,7 +990,7 @@ ephyrHostXVStopVideo (int a_port_id) EPHYR_LOG ("enter\n") ; - ret = XvStopVideo (dpy, a_port_id, hostx_get_window ()) ; + ret = XvStopVideo (dpy, a_port_id, hostx_get_window (a_screen_num)) ; if (ret != Success) { EPHYR_LOG_ERROR ("XvStopVideo() failed: %d \n", ret) ; goto out ; diff --git a/hw/kdrive/ephyr/ephyrhostvideo.h b/hw/kdrive/ephyr/ephyrhostvideo.h index 64b224f1c..05ee38a03 100644 --- a/hw/kdrive/ephyr/ephyrhostvideo.h +++ b/hw/kdrive/ephyr/ephyrhostvideo.h @@ -189,7 +189,8 @@ char* ephyrHostGetAtomName (int a_atom) ; *PutImage * (ignore clipping for now) */ -Bool ephyrHostXVPutImage (int a_port_id, +Bool ephyrHostXVPutImage (int a_screen_num, + int a_port_id, int a_image_id, int a_drw_x, int a_drw_y, @@ -208,26 +209,30 @@ Bool ephyrHostXVPutImage (int a_port_id, /* * Putvideo/PutStill/GetVideo */ -Bool ephyrHostXVPutVideo (int a_port_id, +Bool ephyrHostXVPutVideo (int a_screen_num, + int a_port_id, int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) ; -Bool ephyrHostXVGetVideo (int a_port_id, +Bool ephyrHostXVGetVideo (int a_screen_num, + int a_port_id, int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) ; -Bool ephyrHostXVPutStill (int a_port_id, +Bool ephyrHostXVPutStill (int a_screen_num, + int a_port_id, int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) ; -Bool ephyrHostXVGetStill (int a_port_id, +Bool ephyrHostXVGetStill (int a_screen_num, + int a_port_id, int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) ; /* * StopVideo */ -Bool ephyrHostXVStopVideo (int a_port_id) ; +Bool ephyrHostXVStopVideo (int a_screen_num, int a_port_id) ; #endif /*__EPHYRHOSTVIDEO_H__*/ diff --git a/hw/kdrive/ephyr/ephyrvideo.c b/hw/kdrive/ephyr/ephyrvideo.c index 521f3a6b5..bfe4d7223 100644 --- a/hw/kdrive/ephyr/ephyrvideo.c +++ b/hw/kdrive/ephyr/ephyrvideo.c @@ -705,6 +705,11 @@ ephyrXVPrivIsAttrValueValid (KdAttributePtr a_attrs, if (a_attrs[i].min_value > a_attr_value || a_attrs[i].max_value < a_attr_value) { *a_is_valid = FALSE ; + EPHYR_LOG_ERROR ("attribute was not valid\n" + "value:%d. min:%d. max:%d\n", + a_attr_value, + a_attrs[i].min_value, + a_attrs[i].max_value) ; } else { *a_is_valid = TRUE ; } @@ -771,10 +776,12 @@ ephyrStopVideo (KdScreenInfo *a_info, pointer a_port_priv, Bool a_exit) { EphyrPortPriv *port_priv = a_port_priv ; + EPHYR_RETURN_IF_FAIL (a_info && a_info->pScreen) ; EPHYR_RETURN_IF_FAIL (port_priv) ; EPHYR_LOG ("enter\n") ; - if (!ephyrHostXVStopVideo (port_priv->port_number)) { + if (!ephyrHostXVStopVideo (a_info->pScreen->myNum, + port_priv->port_number)) { EPHYR_LOG_ERROR ("XvStopVideo() failed\n") ; } EPHYR_LOG ("leave\n") ; @@ -817,14 +824,18 @@ ephyrSetPortAttribute (KdScreenInfo *a_info, &is_attr_valid)) { EPHYR_LOG_ERROR ("failed to validate attribute %s\n", NameForAtom (a_attr_name)) ; - res = BadMatch ; - goto out ; + /* + res = BadMatch ; + goto out ; + */ } if (!is_attr_valid) { EPHYR_LOG_ERROR ("attribute %s is not valid\n", NameForAtom (a_attr_name)) ; + /* res = BadMatch ; goto out ; + */ } if (!ephyrHostXVSetPortAttribute (port_priv->port_number, @@ -929,11 +940,13 @@ ephyrPutImage (KdScreenInfo *a_info, Bool is_ok=FALSE ; int result=BadImplementation, image_size=0 ; + EPHYR_RETURN_VAL_IF_FAIL (a_info && a_info->pScreen, BadValue) ; EPHYR_RETURN_VAL_IF_FAIL (a_drawable, BadValue) ; EPHYR_LOG ("enter\n") ; - if (!ephyrHostXVPutImage (port_priv->port_number, + if (!ephyrHostXVPutImage (a_info->pScreen->myNum, + port_priv->port_number, a_id, a_drw_x, a_drw_y, a_drw_w, a_drw_h, a_src_x, a_src_y, a_src_w, a_src_h, @@ -999,6 +1012,7 @@ ephyrReputImage (KdScreenInfo *a_info, EphyrPortPriv *port_priv = a_port_priv ; int result=BadImplementation ; + EPHYR_RETURN_VAL_IF_FAIL (a_info->pScreen, FALSE) ; EPHYR_RETURN_VAL_IF_FAIL (a_drawable && port_priv, BadValue) ; EPHYR_LOG ("enter\n") ; @@ -1007,7 +1021,9 @@ ephyrReputImage (KdScreenInfo *a_info, EPHYR_LOG_ERROR ("has null image buf in cache\n") ; goto out ; } - if (!ephyrHostXVPutImage (port_priv->port_number, port_priv->image_id, + if (!ephyrHostXVPutImage (a_info->pScreen->myNum, + port_priv->port_number, + port_priv->image_id, a_drw_x, a_drw_y, port_priv->drw_w, port_priv->drw_h, port_priv->src_x, port_priv->src_y, @@ -1042,6 +1058,7 @@ ephyrPutVideo (KdScreenInfo *a_info, int result=BadImplementation ; int drw_x=0, drw_y=0, drw_w=0, drw_h=0 ; + EPHYR_RETURN_VAL_IF_FAIL (a_info->pScreen, BadValue) ; EPHYR_RETURN_VAL_IF_FAIL (a_drawable && port_priv, BadValue) ; EPHYR_LOG ("enter\n") ; @@ -1063,7 +1080,8 @@ ephyrPutVideo (KdScreenInfo *a_info, drw_w = clipped_area.x2 - clipped_area.x1 ; drw_h = clipped_area.y2 - clipped_area.y1 ; - if (!ephyrHostXVPutVideo (port_priv->port_number, + if (!ephyrHostXVPutVideo (a_info->pScreen->myNum, + port_priv->port_number, a_vid_x, a_vid_y, a_vid_w, a_vid_h, a_drw_x, a_drw_y, a_drw_w, a_drw_h)) { EPHYR_LOG_ERROR ("ephyrHostXVPutVideo() failed\n") ; @@ -1091,6 +1109,7 @@ ephyrGetVideo (KdScreenInfo *a_info, int result=BadImplementation ; int drw_x=0, drw_y=0, drw_w=0, drw_h=0 ; + EPHYR_RETURN_VAL_IF_FAIL (a_info && a_info->pScreen, BadValue) ; EPHYR_RETURN_VAL_IF_FAIL (a_drawable && port_priv, BadValue) ; EPHYR_LOG ("enter\n") ; @@ -1112,7 +1131,8 @@ ephyrGetVideo (KdScreenInfo *a_info, drw_w = clipped_area.x2 - clipped_area.x1 ; drw_h = clipped_area.y2 - clipped_area.y1 ; - if (!ephyrHostXVGetVideo (port_priv->port_number, + if (!ephyrHostXVGetVideo (a_info->pScreen->myNum, + port_priv->port_number, a_vid_x, a_vid_y, a_vid_w, a_vid_h, a_drw_x, a_drw_y, a_drw_w, a_drw_h)) { EPHYR_LOG_ERROR ("ephyrHostXVGetVideo() failed\n") ; @@ -1140,6 +1160,7 @@ ephyrPutStill (KdScreenInfo *a_info, int result=BadImplementation ; int drw_x=0, drw_y=0, drw_w=0, drw_h=0 ; + EPHYR_RETURN_VAL_IF_FAIL (a_info && a_info->pScreen, BadValue) ; EPHYR_RETURN_VAL_IF_FAIL (a_drawable && port_priv, BadValue) ; EPHYR_LOG ("enter\n") ; @@ -1161,7 +1182,8 @@ ephyrPutStill (KdScreenInfo *a_info, drw_w = clipped_area.x2 - clipped_area.x1 ; drw_h = clipped_area.y2 - clipped_area.y1 ; - if (!ephyrHostXVPutStill (port_priv->port_number, + if (!ephyrHostXVPutStill (a_info->pScreen->myNum, + port_priv->port_number, a_vid_x, a_vid_y, a_vid_w, a_vid_h, a_drw_x, a_drw_y, a_drw_w, a_drw_h)) { EPHYR_LOG_ERROR ("ephyrHostXVPutStill() failed\n") ; @@ -1189,6 +1211,7 @@ ephyrGetStill (KdScreenInfo *a_info, int result=BadImplementation ; int drw_x=0, drw_y=0, drw_w=0, drw_h=0 ; + EPHYR_RETURN_VAL_IF_FAIL (a_info && a_info->pScreen, BadValue) ; EPHYR_RETURN_VAL_IF_FAIL (a_drawable && port_priv, BadValue) ; EPHYR_LOG ("enter\n") ; @@ -1210,7 +1233,8 @@ ephyrGetStill (KdScreenInfo *a_info, drw_w = clipped_area.x2 - clipped_area.x1 ; drw_h = clipped_area.y2 - clipped_area.y1 ; - if (!ephyrHostXVGetStill (port_priv->port_number, + if (!ephyrHostXVGetStill (a_info->pScreen->myNum, + port_priv->port_number, a_vid_x, a_vid_y, a_vid_w, a_vid_h, a_drw_x, a_drw_y, a_drw_w, a_drw_h)) { EPHYR_LOG_ERROR ("ephyrHostXVGetStill() failed\n") ; diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c index 0ef1a6283..181edd226 100644 --- a/hw/kdrive/ephyr/hostx.c +++ b/hw/kdrive/ephyr/hostx.c @@ -978,9 +978,13 @@ hostx_get_display(void) } int -hostx_get_window(void) +hostx_get_window (int a_screen_number) { - return HostX.win ; + if (a_screen_number < 0 || a_screen_number >= HostX.n_screens) { + EPHYR_LOG_ERROR ("bad screen number:%d\n", a_screen_number) ; + return 0; + } + return HostX.screens[a_screen_number].win ; } int @@ -1085,7 +1089,8 @@ static ResourcePair resource_peers[RESOURCE_PEERS_SIZE] ; int -hostx_create_window (EphyrBox *a_geometry, +hostx_create_window (int a_screen_number, + EphyrBox *a_geometry, int a_visual_id, int *a_host_peer /*out parameter*/) { @@ -1120,7 +1125,7 @@ hostx_create_window (EphyrBox *a_geometry, AllocNone) ; winmask = CWColormap; - win = XCreateWindow (dpy, hostx_get_window (), + win = XCreateWindow (dpy, hostx_get_window (a_screen_number), a_geometry->x, a_geometry->y, a_geometry->width, a_geometry->height, 0, visual_info->depth, InputOutput, diff --git a/hw/kdrive/ephyr/hostx.h b/hw/kdrive/ephyr/hostx.h index 941eeceb5..3caa466a7 100644 --- a/hw/kdrive/ephyr/hostx.h +++ b/hw/kdrive/ephyr/hostx.h @@ -193,16 +193,16 @@ hostx_paint_rect(EphyrScreenInfo screen, void -hostx_load_keymap(void); +hostx_load_keymap (void); int -hostx_get_event(EphyrHostXEvent *ev); +hostx_get_event (EphyrHostXEvent *ev); void* -hostx_get_display(void) ; +hostx_get_display (void) ; int -hostx_get_window(void) ; +hostx_get_window (int a_screen_number) ; int hostx_get_window_attributes (int a_window, EphyrHostWindowAttributes *a_attr) ; @@ -216,7 +216,8 @@ int hostx_get_visuals_info (EphyrHostVisualInfo **a_visuals, int *a_num_entries) ; -int hostx_create_window (EphyrBox *a_geometry, +int hostx_create_window (int a_screen_number, + EphyrBox *a_geometry, int a_visual_id, int *a_host_win /*out parameter*/) ; @@ -228,6 +229,7 @@ int hostx_set_window_geometry (int a_win, EphyrBox *a_geo) ; int hostx_set_window_bounding_rectangles (int a_window, EphyrRect *a_rects, int a_num_rects) ; + int hostx_set_window_clipping_rectangles (int a_window, EphyrRect *a_rects, int a_num_rects) ;