shadow.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /*
  2. Copyright (C) 1999. The XFree86 Project Inc.
  3. Copyright 2014 Red Hat, Inc.
  4. Written by Mark Vojkovich (mvojkovi@ucsd.edu)
  5. Pre-fb-write callbacks and RENDER support - Nolan Leake (nolan@vmware.com)
  6. */
  7. #ifdef HAVE_XORG_CONFIG_H
  8. #include <xorg-config.h>
  9. #endif
  10. #include <X11/X.h>
  11. #include <X11/Xproto.h>
  12. #include "misc.h"
  13. #include "pixmapstr.h"
  14. #include "input.h"
  15. #include <X11/fonts/font.h>
  16. #include "mi.h"
  17. #include "scrnintstr.h"
  18. #include "windowstr.h"
  19. #include "gcstruct.h"
  20. #include "dixfontstr.h"
  21. #include <X11/fonts/fontstruct.h>
  22. #include "xf86.h"
  23. #include "xf86str.h"
  24. #include "shadowfb.h"
  25. #include "picturestr.h"
  26. static Bool ShadowCloseScreen(ScreenPtr pScreen);
  27. static Bool ShadowCreateRootWindow(WindowPtr pWin);
  28. typedef struct {
  29. ScrnInfoPtr pScrn;
  30. RefreshAreaFuncPtr preRefresh;
  31. RefreshAreaFuncPtr postRefresh;
  32. CloseScreenProcPtr CloseScreen;
  33. CreateWindowProcPtr CreateWindow;
  34. } ShadowScreenRec, *ShadowScreenPtr;
  35. static DevPrivateKeyRec ShadowScreenKeyRec;
  36. static ShadowScreenPtr
  37. shadowfbGetScreenPrivate(ScreenPtr pScreen)
  38. {
  39. return dixLookupPrivate(&(pScreen)->devPrivates, &ShadowScreenKeyRec);
  40. }
  41. Bool
  42. ShadowFBInit2(ScreenPtr pScreen,
  43. RefreshAreaFuncPtr preRefreshArea,
  44. RefreshAreaFuncPtr postRefreshArea)
  45. {
  46. ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
  47. ShadowScreenPtr pPriv;
  48. if (!preRefreshArea && !postRefreshArea)
  49. return FALSE;
  50. if (!dixRegisterPrivateKey(&ShadowScreenKeyRec, PRIVATE_SCREEN, 0))
  51. return FALSE;
  52. if (!(pPriv = (ShadowScreenPtr) malloc(sizeof(ShadowScreenRec))))
  53. return FALSE;
  54. dixSetPrivate(&pScreen->devPrivates, &ShadowScreenKeyRec, pPriv);
  55. pPriv->pScrn = pScrn;
  56. pPriv->preRefresh = preRefreshArea;
  57. pPriv->postRefresh = postRefreshArea;
  58. pPriv->CloseScreen = pScreen->CloseScreen;
  59. pPriv->CreateWindow = pScreen->CreateWindow;
  60. pScreen->CloseScreen = ShadowCloseScreen;
  61. pScreen->CreateWindow = ShadowCreateRootWindow;
  62. return TRUE;
  63. }
  64. Bool
  65. ShadowFBInit(ScreenPtr pScreen, RefreshAreaFuncPtr refreshArea)
  66. {
  67. return ShadowFBInit2(pScreen, NULL, refreshArea);
  68. }
  69. /*
  70. * Note that we don't do DamageEmpty, or indeed look at the region inside the
  71. * DamagePtr at all. This is an optimization, believe it or not. The
  72. * incoming RegionPtr is the new damage, and if we were to empty the region
  73. * miext/damage would just have to waste time reallocating and re-unioning
  74. * it every time, whereas if we leave it around the union gets fast-pathed
  75. * away.
  76. */
  77. static void
  78. shadowfbReportPre(DamagePtr damage, RegionPtr reg, void *closure)
  79. {
  80. ShadowScreenPtr pPriv = closure;
  81. if (!pPriv->pScrn->vtSema)
  82. return;
  83. pPriv->preRefresh(pPriv->pScrn, RegionNumRects(reg), RegionRects(reg));
  84. }
  85. static void
  86. shadowfbReportPost(DamagePtr damage, RegionPtr reg, void *closure)
  87. {
  88. ShadowScreenPtr pPriv = closure;
  89. if (!pPriv->pScrn->vtSema)
  90. return;
  91. pPriv->postRefresh(pPriv->pScrn, RegionNumRects(reg), RegionRects(reg));
  92. }
  93. static Bool
  94. ShadowCreateRootWindow(WindowPtr pWin)
  95. {
  96. Bool ret;
  97. ScreenPtr pScreen = pWin->drawable.pScreen;
  98. ShadowScreenPtr pPriv = shadowfbGetScreenPrivate(pScreen);
  99. /* paranoia */
  100. if (pWin != pScreen->root)
  101. ErrorF("ShadowCreateRootWindow called unexpectedly\n");
  102. /* call down, but don't hook ourselves back in; we know the first time
  103. * we're called it's for the root window.
  104. */
  105. pScreen->CreateWindow = pPriv->CreateWindow;
  106. ret = pScreen->CreateWindow(pWin);
  107. /* this might look like it leaks, but the damage code reaps listeners
  108. * when their drawable disappears.
  109. */
  110. if (ret) {
  111. DamagePtr damage;
  112. if (pPriv->preRefresh) {
  113. damage = DamageCreate(shadowfbReportPre, NULL,
  114. DamageReportRawRegion,
  115. TRUE, pScreen, pPriv);
  116. DamageRegister(&pWin->drawable, damage);
  117. }
  118. if (pPriv->postRefresh) {
  119. damage = DamageCreate(shadowfbReportPost, NULL,
  120. DamageReportRawRegion,
  121. TRUE, pScreen, pPriv);
  122. DamageSetReportAfterOp(damage, TRUE);
  123. DamageRegister(&pWin->drawable, damage);
  124. }
  125. }
  126. return ret;
  127. }
  128. static Bool
  129. ShadowCloseScreen(ScreenPtr pScreen)
  130. {
  131. ShadowScreenPtr pPriv = shadowfbGetScreenPrivate(pScreen);
  132. pScreen->CloseScreen = pPriv->CloseScreen;
  133. free(pPriv);
  134. return (*pScreen->CloseScreen) (pScreen);
  135. }