shadow.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. /*
  2. *
  3. * Copyright © 2000 Keith Packard
  4. *
  5. * Permission to use, copy, modify, distribute, and sell this software and its
  6. * documentation for any purpose is hereby granted without fee, provided that
  7. * the above copyright notice appear in all copies and that both that
  8. * copyright notice and this permission notice appear in supporting
  9. * documentation, and that the name of Keith Packard not be used in
  10. * advertising or publicity pertaining to distribution of the software without
  11. * specific, written prior permission. Keith Packard makes no
  12. * representations about the suitability of this software for any purpose. It
  13. * is provided "as is" without express or implied warranty.
  14. *
  15. * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  16. * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  17. * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  18. * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  19. * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  20. * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  21. * PERFORMANCE OF THIS SOFTWARE.
  22. */
  23. #ifdef HAVE_DIX_CONFIG_H
  24. #include <dix-config.h>
  25. #endif
  26. #include <stdlib.h>
  27. #include <X11/X.h>
  28. #include "scrnintstr.h"
  29. #include "windowstr.h"
  30. #include "dixfontstr.h"
  31. #include "mi.h"
  32. #include "regionstr.h"
  33. #include "globals.h"
  34. #include "gcstruct.h"
  35. #include "shadow.h"
  36. int shadowScrPrivateIndex;
  37. int shadowGeneration;
  38. #define wrap(priv, real, mem) {\
  39. priv->mem = real->mem; \
  40. real->mem = shadow##mem; \
  41. }
  42. #define unwrap(priv, real, mem) {\
  43. real->mem = priv->mem; \
  44. }
  45. static void
  46. shadowRedisplay(ScreenPtr pScreen)
  47. {
  48. shadowBuf(pScreen);
  49. RegionPtr pRegion;
  50. if (!pBuf || !pBuf->pDamage || !pBuf->update)
  51. return;
  52. pRegion = DamageRegion(pBuf->pDamage);
  53. if (REGION_NOTEMPTY(pRegion)) {
  54. (*pBuf->update) (pScreen, pBuf);
  55. DamageEmpty(pBuf->pDamage);
  56. }
  57. }
  58. static void
  59. shadowBlockHandler(pointer data, OSTimePtr pTimeout, pointer pRead)
  60. {
  61. ScreenPtr pScreen = (ScreenPtr) data;
  62. shadowRedisplay(pScreen);
  63. }
  64. static void
  65. shadowWakeupHandler(pointer data, int i, pointer LastSelectMask)
  66. {
  67. }
  68. static void
  69. shadowGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h,
  70. unsigned int format, unsigned long planeMask, char *pdstLine)
  71. {
  72. ScreenPtr pScreen = pDrawable->pScreen;
  73. shadowBuf(pScreen);
  74. /* Many apps use GetImage to sync with the visable frame buffer */
  75. if (pDrawable->type == DRAWABLE_WINDOW)
  76. shadowRedisplay(pScreen);
  77. unwrap(pBuf, pScreen, GetImage);
  78. pScreen->GetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine);
  79. wrap(pBuf, pScreen, GetImage);
  80. }
  81. #define BACKWARDS_COMPATIBILITY
  82. static Bool
  83. shadowCloseScreen(int i, ScreenPtr pScreen)
  84. {
  85. shadowBuf(pScreen);
  86. unwrap(pBuf, pScreen, GetImage);
  87. unwrap(pBuf, pScreen, CloseScreen);
  88. shadowRemove(pScreen, pBuf->pPixmap);
  89. DamageDestroy(pBuf->pDamage);
  90. #ifdef BACKWARDS_COMPATIBILITY
  91. REGION_UNINIT(&pBuf->damage); /* bc */
  92. #endif
  93. if (pBuf->pPixmap)
  94. pScreen->DestroyPixmap(pBuf->pPixmap);
  95. free(pBuf);
  96. return pScreen->CloseScreen(i, pScreen);
  97. }
  98. #ifdef BACKWARDS_COMPATIBILITY
  99. static void
  100. shadowReportFunc(DamagePtr pDamage, RegionPtr pRegion, void *closure)
  101. {
  102. ScreenPtr pScreen = closure;
  103. shadowBufPtr pBuf = pScreen->devPrivates[shadowScrPrivateIndex].ptr;
  104. /* Register the damaged region, use DamageReportNone below when we
  105. * want to break BC below... */
  106. REGION_UNION(&pDamage->damage, &pDamage->damage, pRegion);
  107. /*
  108. * BC hack. In 7.0 and earlier several drivers would inspect the
  109. * 'damage' member directly, so we have to keep it existing.
  110. */
  111. REGION_COPY(&pBuf->damage, pRegion);
  112. }
  113. #endif
  114. Bool
  115. shadowSetup(ScreenPtr pScreen)
  116. {
  117. shadowBufPtr pBuf;
  118. if (!DamageSetup(pScreen))
  119. return FALSE;
  120. if (shadowGeneration != serverGeneration) {
  121. shadowScrPrivateIndex = AllocateScreenPrivateIndex();
  122. if (shadowScrPrivateIndex == -1)
  123. return FALSE;
  124. shadowGeneration = serverGeneration;
  125. }
  126. pBuf = malloc(sizeof(shadowBufRec));
  127. if (!pBuf)
  128. return FALSE;
  129. #ifdef BACKWARDS_COMPATIBILITY
  130. pBuf->pDamage = DamageCreate((DamageReportFunc) shadowReportFunc,
  131. (DamageDestroyFunc) NULL,
  132. DamageReportRawRegion, TRUE, pScreen, pScreen);
  133. #else
  134. pBuf->pDamage = DamageCreate((DamageReportFunc) NULL,
  135. (DamageDestroyFunc) NULL,
  136. DamageReportNone, TRUE, pScreen, pScreen);
  137. #endif
  138. if (!pBuf->pDamage) {
  139. free(pBuf);
  140. return FALSE;
  141. }
  142. wrap(pBuf, pScreen, CloseScreen);
  143. wrap(pBuf, pScreen, GetImage);
  144. pBuf->update = 0;
  145. pBuf->window = 0;
  146. pBuf->pPixmap = 0;
  147. pBuf->closure = 0;
  148. pBuf->randr = 0;
  149. #ifdef BACKWARDS_COMPATIBILITY
  150. REGION_NULL(&pBuf->damage); /* bc */
  151. #endif
  152. pScreen->devPrivates[shadowScrPrivateIndex].ptr = (pointer) pBuf;
  153. return TRUE;
  154. }
  155. Bool
  156. shadowAdd(ScreenPtr pScreen, PixmapPtr pPixmap, ShadowUpdateProc update,
  157. ShadowWindowProc window, int randr, void *closure)
  158. {
  159. shadowBuf(pScreen);
  160. if (!RegisterBlockAndWakeupHandlers(shadowBlockHandler, shadowWakeupHandler,
  161. (pointer) pScreen))
  162. return FALSE;
  163. /*
  164. * Map simple rotation values to bitmasks; fortunately,
  165. * these are all unique
  166. */
  167. switch (randr) {
  168. case 0:
  169. randr = SHADOW_ROTATE_0;
  170. break;
  171. case 90:
  172. randr = SHADOW_ROTATE_90;
  173. break;
  174. case 180:
  175. randr = SHADOW_ROTATE_180;
  176. break;
  177. case 270:
  178. randr = SHADOW_ROTATE_270;
  179. break;
  180. }
  181. pBuf->update = update;
  182. pBuf->window = window;
  183. pBuf->randr = randr;
  184. pBuf->closure = 0;
  185. pBuf->pPixmap = pPixmap;
  186. DamageRegister(&pPixmap->drawable, pBuf->pDamage);
  187. return TRUE;
  188. }
  189. void
  190. shadowRemove(ScreenPtr pScreen, PixmapPtr pPixmap)
  191. {
  192. shadowBuf(pScreen);
  193. if (pBuf->pPixmap) {
  194. DamageUnregister(&pBuf->pPixmap->drawable, pBuf->pDamage);
  195. pBuf->update = 0;
  196. pBuf->window = 0;
  197. pBuf->randr = 0;
  198. pBuf->closure = 0;
  199. pBuf->pPixmap = 0;
  200. }
  201. RemoveBlockAndWakeupHandlers(shadowBlockHandler, shadowWakeupHandler,
  202. (pointer) pScreen);
  203. }
  204. Bool
  205. shadowInit(ScreenPtr pScreen, ShadowUpdateProc update, ShadowWindowProc window)
  206. {
  207. PixmapPtr pPixmap;
  208. pPixmap = pScreen->CreatePixmap(pScreen, pScreen->width, pScreen->height,
  209. pScreen->rootDepth);
  210. if (!pPixmap)
  211. return FALSE;
  212. if (!shadowSetup(pScreen)) {
  213. pScreen->DestroyPixmap(pPixmap);
  214. return FALSE;
  215. }
  216. shadowAdd(pScreen, pPixmap, update, window, SHADOW_ROTATE_0, 0);
  217. return TRUE;
  218. }