diff --git a/hw/dmx/Makefile.am b/hw/dmx/Makefile.am index 0400c7a00..e8089d3e6 100644 --- a/hw/dmx/Makefile.am +++ b/hw/dmx/Makefile.am @@ -82,6 +82,8 @@ Xdmx_SOURCES = dmx.c \ dmxwindow.h \ dmxlaunch.c \ dmxlaunch.h \ + dmxcomp.c \ + dmxcomp.h \ $(top_srcdir)/mi/miinitext.c \ $(top_srcdir)/fb/fbcmap_mi.c \ $(GLX_SRCS) \ diff --git a/hw/dmx/dmxcomp.c b/hw/dmx/dmxcomp.c new file mode 100644 index 000000000..debd97dfc --- /dev/null +++ b/hw/dmx/dmxcomp.c @@ -0,0 +1,199 @@ +/* + * Copyright © 2008 Novell, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of + * Novell, Inc. not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior permission. + * Novell, Inc. makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: David Reveman + */ + +#ifdef HAVE_DMX_CONFIG_H +#include +#endif + +#include "dmx.h" +#include "dmxcomp.h" +#include "compint.h" + +extern int (*ProcCompositeVector[CompositeNumberRequests]) (ClientPtr); +static int (*dmxSaveCompositeVector[CompositeNumberRequests]) (ClientPtr); + +unsigned long DMX_CLIENTWINDOW; +unsigned long DMX_CLIENTSUBWINDOWS; + +static int +dmxProcCompositeRedirectWindow (ClientPtr client) +{ + WindowPtr pWin; + int rc; + REQUEST(xCompositeRedirectWindowReq); + + REQUEST_SIZE_MATCH(xCompositeRedirectWindowReq); + + rc = dixLookupResource((pointer *)&pWin, stuff->window, RT_WINDOW, client, + DixSetAttrAccess|DixManageAccess|DixBlendAccess); + if (rc != Success) + { + client->errorValue = stuff->window; + return (rc == BadValue) ? BadWindow : rc; + } + + /* Add implicit CompositeRedirectManual. This prevents clients + from using CompositeRedirectManual and composite extension from + handling window updates. Window updates are handled by + back-end servers. */ + if (!GetCompWindow (pWin)) + { + rc = compRedirectWindow (serverClient, pWin, CompositeRedirectManual); + if (rc != Success) + return rc; + } + + rc = compRedirectWindow (client, pWin, stuff->update); + if (rc == Success) + { + AddResource (GetCompWindow (pWin)->clients->id, + DMX_CLIENTWINDOW, + pWin); + } + else + { + if (!GetCompWindow (pWin)->clients->next) + compUnredirectWindow (serverClient, pWin, CompositeRedirectManual); + } + + return rc; +} + +static int +dmxProcCompositeRedirectSubwindows (ClientPtr client) +{ + WindowPtr pWin; + int rc; + REQUEST(xCompositeRedirectSubwindowsReq); + + REQUEST_SIZE_MATCH(xCompositeRedirectSubwindowsReq); + + rc = dixLookupResource((pointer *)&pWin, stuff->window, RT_WINDOW, client, + DixSetAttrAccess|DixManageAccess|DixBlendAccess); + if (rc != Success) + { + client->errorValue = stuff->window; + return (rc == BadValue) ? BadWindow : rc; + } + + if (!GetCompSubwindows (pWin)) + { + rc = compRedirectSubwindows (serverClient, pWin, + CompositeRedirectManual); + if (rc != Success) + return rc; + } + + rc = compRedirectSubwindows (client, pWin, stuff->update); + if (rc == Success) + { + AddResource (GetCompSubwindows (pWin)->clients->id, + DMX_CLIENTSUBWINDOWS, + pWin); + } + else + { + if (!GetCompSubwindows (pWin)->clients->next) + compUnredirectSubwindows (serverClient, pWin, + CompositeRedirectManual); + } + + return rc; +} + +static int +dmxFreeCompositeClientWindow (pointer value, XID ccwid) +{ + WindowPtr pWin = value; + CompWindowPtr cw = GetCompWindow (pWin); + CompClientWindowPtr ccw; + int count = 0; + + for (ccw = cw->clients; ccw; ccw = ccw->next) + if (ccw->update != CompositeRedirectManual) + count++; + + /* free our implicit manual redirect if that's the only one left */ + if (count <= 1) + compUnredirectWindow (serverClient, pWin, CompositeRedirectManual); + + return Success; +} + +static int +dmxFreeCompositeClientSubwindows (pointer value, XID ccwid) +{ + WindowPtr pWin = value; + CompSubwindowsPtr csw = GetCompSubwindows (pWin); + CompClientWindowPtr ccw; + int count = 0; + + for (ccw = csw->clients; ccw; ccw = ccw->next) + if (ccw->update != CompositeRedirectManual) + count++; + + /* free our implicit manual redirect if that's the only one left */ + if (count <= 1) + compUnredirectSubwindows (serverClient, pWin, + CompositeRedirectManual); + + return Success; +} + +/** Initialize the Proc Vector for the Composite extension. The functions + * here cannot be handled by the mi layer Composite hooks either because + * the required information is no longer available when it reaches the + * mi layer or no mi layer hooks exist. This function is called from + * InitOutput() since it should be initialized only once per server + * generation. */ +void +dmxInitComposite (void) +{ + int i; + + DMX_CLIENTWINDOW = CreateNewResourceType (dmxFreeCompositeClientWindow); + DMX_CLIENTSUBWINDOWS = + CreateNewResourceType (dmxFreeCompositeClientSubwindows); + + for (i = 0; i < CompositeNumberRequests; i++) + dmxSaveCompositeVector[i] = ProcCompositeVector[i]; + + ProcCompositeVector[X_CompositeRedirectWindow] + = dmxProcCompositeRedirectWindow; + ProcCompositeVector[X_CompositeRedirectSubwindows] + = dmxProcCompositeRedirectSubwindows; +} + +/** Reset the Proc Vector for the Composite extension back to the original + * functions. This function is called from dmxCloseScreen() during the + * server reset (only for screen #0). */ +void +dmxResetComposite (void) +{ + int i; + + for (i = 0; i < CompositeNumberRequests; i++) + ProcCompositeVector[i] = dmxSaveCompositeVector[i]; +} diff --git a/hw/dmx/dmxcomp.h b/hw/dmx/dmxcomp.h new file mode 100644 index 000000000..f9bffbfbd --- /dev/null +++ b/hw/dmx/dmxcomp.h @@ -0,0 +1,35 @@ +/* + * Copyright © 2008 Novell, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of + * Novell, Inc. not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior permission. + * Novell, Inc. makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: David Reveman + */ + +#ifndef DMXCOMP_H +#define DMXCOMP_H + +void +dmxInitComposite (void); + +void +dmxResetComposite (void); + +#endif /* DMXCOMP_H */ diff --git a/hw/dmx/dmxinit.c b/hw/dmx/dmxinit.c index 13cfd492c..fd14a30db 100644 --- a/hw/dmx/dmxinit.c +++ b/hw/dmx/dmxinit.c @@ -57,6 +57,9 @@ #ifdef RENDER #include "dmxpict.h" #endif +#ifdef COMPOSITE +#include "dmxcomp.h" +#endif #include "dmxextension.h" #include /* For gettimeofday */ @@ -933,6 +936,12 @@ void InitOutput(ScreenInfo *pScreenInfo, int argc, char *argv[]) dmxInitRender(); #endif +#ifdef COMPOSITE + /* Initialize the composite extension */ + if (!noCompositeExtension) + dmxInitComposite(); +#endif + /* Initialized things that need timer hooks */ dmxStatInit(); dmxSyncInit(); /* Calls RegisterBlockAndWakeupHandlers */ diff --git a/hw/dmx/dmxwindow.c b/hw/dmx/dmxwindow.c index 0b3cf8b43..941d31217 100644 --- a/hw/dmx/dmxwindow.c +++ b/hw/dmx/dmxwindow.c @@ -746,7 +746,7 @@ Bool dmxUnrealizeWindow(WindowPtr pWindow) { XCompositeUnredirectWindow (dmxScreen->beDisplay, pWinPriv->window, - CompositeRedirectManual); + CompositeRedirectAutomatic); pWinPriv->beRedirected = FALSE; } XLIB_EPILOGUE (dmxScreen); @@ -1152,7 +1152,7 @@ dmxDoRedirectWindow(WindowPtr pWindow) XLIB_PROLOGUE (dmxScreen); XCompositeRedirectWindow (dmxScreen->beDisplay, pWinPriv->window, - CompositeRedirectManual); + CompositeRedirectAutomatic); XLIB_EPILOGUE (dmxScreen); pWinPriv->beRedirected = TRUE; }