shrotate.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. /*
  2. *
  3. * Copyright © 2001 Keith Packard, member of The XFree86 Project, Inc.
  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 <X11/X.h>
  27. #include "scrnintstr.h"
  28. #include "windowstr.h"
  29. #include <X11/fonts/font.h>
  30. #include "dixfontstr.h"
  31. #include <X11/fonts/fontstruct.h>
  32. #include "mi.h"
  33. #include "regionstr.h"
  34. #include "globals.h"
  35. #include "gcstruct.h"
  36. #include "shadow.h"
  37. #include "fb.h"
  38. /*
  39. * These indicate which way the source (shadow) is scanned when
  40. * walking the screen in a particular direction
  41. */
  42. #define LEFT_TO_RIGHT 1
  43. #define RIGHT_TO_LEFT -1
  44. #define TOP_TO_BOTTOM 2
  45. #define BOTTOM_TO_TOP -2
  46. void
  47. shadowUpdateRotatePacked(ScreenPtr pScreen, shadowBufPtr pBuf)
  48. {
  49. RegionPtr damage = shadowDamage(pBuf);
  50. PixmapPtr pShadow = pBuf->pPixmap;
  51. int nbox = REGION_NUM_RECTS(damage);
  52. BoxPtr pbox = REGION_RECTS(damage);
  53. FbBits *shaBits;
  54. FbStride shaStride;
  55. int shaBpp;
  56. int shaXoff _X_UNUSED, shaYoff _X_UNUSED;
  57. int box_x1, box_x2, box_y1, box_y2;
  58. int sha_x1 = 0, sha_y1 = 0;
  59. int scr_x1 = 0, scr_x2 = 0, scr_y1 = 0, scr_y2 = 0, scr_w, scr_h;
  60. int scr_x, scr_y;
  61. int w;
  62. int pixelsPerBits;
  63. int pixelsMask;
  64. FbStride shaStepOverY = 0, shaStepDownY = 0;
  65. FbStride shaStepOverX = 0, shaStepDownX = 0;
  66. FbBits *shaLine, *sha;
  67. int shaHeight = pShadow->drawable.height;
  68. int shaWidth = pShadow->drawable.width;
  69. FbBits shaMask;
  70. int shaFirstShift, shaShift;
  71. int o_x_dir;
  72. int o_y_dir;
  73. int x_dir;
  74. int y_dir;
  75. fbGetDrawable(&pShadow->drawable, shaBits, shaStride, shaBpp, shaXoff,
  76. shaYoff);
  77. pixelsPerBits = (sizeof(FbBits) * 8) / shaBpp;
  78. pixelsMask = ~(pixelsPerBits - 1);
  79. shaMask = FbBitsMask(FB_UNIT - shaBpp, shaBpp);
  80. /*
  81. * Compute rotation related constants to walk the shadow
  82. */
  83. o_x_dir = LEFT_TO_RIGHT;
  84. o_y_dir = TOP_TO_BOTTOM;
  85. if (pBuf->randr & SHADOW_REFLECT_X)
  86. o_x_dir = -o_x_dir;
  87. if (pBuf->randr & SHADOW_REFLECT_Y)
  88. o_y_dir = -o_y_dir;
  89. switch (pBuf->randr & (SHADOW_ROTATE_ALL)) {
  90. case SHADOW_ROTATE_0: /* upper left shadow -> upper left screen */
  91. default:
  92. x_dir = o_x_dir;
  93. y_dir = o_y_dir;
  94. break;
  95. case SHADOW_ROTATE_90: /* upper right shadow -> upper left screen */
  96. x_dir = o_y_dir;
  97. y_dir = -o_x_dir;
  98. break;
  99. case SHADOW_ROTATE_180: /* lower right shadow -> upper left screen */
  100. x_dir = -o_x_dir;
  101. y_dir = -o_y_dir;
  102. break;
  103. case SHADOW_ROTATE_270: /* lower left shadow -> upper left screen */
  104. x_dir = -o_y_dir;
  105. y_dir = o_x_dir;
  106. break;
  107. }
  108. switch (x_dir) {
  109. case LEFT_TO_RIGHT:
  110. shaStepOverX = shaBpp;
  111. shaStepOverY = 0;
  112. break;
  113. case TOP_TO_BOTTOM:
  114. shaStepOverX = 0;
  115. shaStepOverY = shaStride;
  116. break;
  117. case RIGHT_TO_LEFT:
  118. shaStepOverX = -shaBpp;
  119. shaStepOverY = 0;
  120. break;
  121. case BOTTOM_TO_TOP:
  122. shaStepOverX = 0;
  123. shaStepOverY = -shaStride;
  124. break;
  125. }
  126. switch (y_dir) {
  127. case TOP_TO_BOTTOM:
  128. shaStepDownX = 0;
  129. shaStepDownY = shaStride;
  130. break;
  131. case RIGHT_TO_LEFT:
  132. shaStepDownX = -shaBpp;
  133. shaStepDownY = 0;
  134. break;
  135. case BOTTOM_TO_TOP:
  136. shaStepDownX = 0;
  137. shaStepDownY = -shaStride;
  138. break;
  139. case LEFT_TO_RIGHT:
  140. shaStepDownX = shaBpp;
  141. shaStepDownY = 0;
  142. break;
  143. }
  144. while (nbox--) {
  145. box_x1 = pbox->x1;
  146. box_y1 = pbox->y1;
  147. box_x2 = pbox->x2;
  148. box_y2 = pbox->y2;
  149. pbox++;
  150. /*
  151. * Compute screen and shadow locations for this box
  152. */
  153. switch (x_dir) {
  154. case LEFT_TO_RIGHT:
  155. scr_x1 = box_x1 & pixelsMask;
  156. scr_x2 = (box_x2 + pixelsPerBits - 1) & pixelsMask;
  157. sha_x1 = scr_x1;
  158. break;
  159. case TOP_TO_BOTTOM:
  160. scr_x1 = box_y1 & pixelsMask;
  161. scr_x2 = (box_y2 + pixelsPerBits - 1) & pixelsMask;
  162. sha_y1 = scr_x1;
  163. break;
  164. case RIGHT_TO_LEFT:
  165. scr_x1 = (shaWidth - box_x2) & pixelsMask;
  166. scr_x2 = (shaWidth - box_x1 + pixelsPerBits - 1) & pixelsMask;
  167. sha_x1 = (shaWidth - scr_x1 - 1);
  168. break;
  169. case BOTTOM_TO_TOP:
  170. scr_x1 = (shaHeight - box_y2) & pixelsMask;
  171. scr_x2 = (shaHeight - box_y1 + pixelsPerBits - 1) & pixelsMask;
  172. sha_y1 = (shaHeight - scr_x1 - 1);
  173. break;
  174. }
  175. switch (y_dir) {
  176. case TOP_TO_BOTTOM:
  177. scr_y1 = box_y1;
  178. scr_y2 = box_y2;
  179. sha_y1 = scr_y1;
  180. break;
  181. case RIGHT_TO_LEFT:
  182. scr_y1 = (shaWidth - box_x2);
  183. scr_y2 = (shaWidth - box_x1);
  184. sha_x1 = box_x2 - 1;
  185. break;
  186. case BOTTOM_TO_TOP:
  187. scr_y1 = shaHeight - box_y2;
  188. scr_y2 = shaHeight - box_y1;
  189. sha_y1 = box_y2 - 1;
  190. break;
  191. case LEFT_TO_RIGHT:
  192. scr_y1 = box_x1;
  193. scr_y2 = box_x2;
  194. sha_x1 = box_x1;
  195. break;
  196. }
  197. scr_w = ((scr_x2 - scr_x1) * shaBpp) >> FB_SHIFT;
  198. scr_h = scr_y2 - scr_y1;
  199. scr_y = scr_y1;
  200. /* shift amount for first pixel on screen */
  201. shaFirstShift = FB_UNIT - ((sha_x1 * shaBpp) & FB_MASK) - shaBpp;
  202. /* pointer to shadow data first placed on screen */
  203. shaLine = (shaBits +
  204. sha_y1 * shaStride + ((sha_x1 * shaBpp) >> FB_SHIFT));
  205. /*
  206. * Copy the bits, always write across the physical frame buffer
  207. * to take advantage of write combining.
  208. */
  209. while (scr_h--) {
  210. int p;
  211. FbBits bits;
  212. FbBits *win;
  213. int i;
  214. CARD32 winSize;
  215. sha = shaLine;
  216. shaShift = shaFirstShift;
  217. w = scr_w;
  218. scr_x = scr_x1 * shaBpp >> FB_SHIFT;
  219. while (w) {
  220. /*
  221. * Map some of this line
  222. */
  223. win = (FbBits *) (*pBuf->window) (pScreen,
  224. scr_y,
  225. scr_x << 2,
  226. SHADOW_WINDOW_WRITE,
  227. &winSize, pBuf->closure);
  228. i = (winSize >> 2);
  229. if (i > w)
  230. i = w;
  231. w -= i;
  232. scr_x += i;
  233. /*
  234. * Copy the portion of the line mapped
  235. */
  236. while (i--) {
  237. bits = 0;
  238. p = pixelsPerBits;
  239. /*
  240. * Build one word of output from multiple inputs
  241. *
  242. * Note that for 90/270 rotations, this will walk
  243. * down the shadow hitting each scanline once.
  244. * This is probably not very efficient.
  245. */
  246. while (p--) {
  247. bits = FbScrLeft(bits, shaBpp);
  248. bits |= FbScrRight(*sha, shaShift) & shaMask;
  249. shaShift -= shaStepOverX;
  250. if (shaShift >= FB_UNIT) {
  251. shaShift -= FB_UNIT;
  252. sha--;
  253. }
  254. else if (shaShift < 0) {
  255. shaShift += FB_UNIT;
  256. sha++;
  257. }
  258. sha += shaStepOverY;
  259. }
  260. *win++ = bits;
  261. }
  262. }
  263. scr_y++;
  264. shaFirstShift -= shaStepDownX;
  265. if (shaFirstShift >= FB_UNIT) {
  266. shaFirstShift -= FB_UNIT;
  267. shaLine--;
  268. }
  269. else if (shaFirstShift < 0) {
  270. shaFirstShift += FB_UNIT;
  271. shaLine++;
  272. }
  273. shaLine += shaStepDownY;
  274. }
  275. }
  276. }
  277. shadowUpdateProc
  278. shadowUpdateRotatePackedWeak(void)
  279. {
  280. return shadowUpdateRotatePacked;
  281. }