fboverlay.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. /*
  2. *
  3. * Copyright © 2000 SuSE, 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 SuSE not be used in advertising or
  10. * publicity pertaining to distribution of the software without specific,
  11. * written prior permission. SuSE makes no representations about the
  12. * suitability of this software for any purpose. It is provided "as is"
  13. * without express or implied warranty.
  14. *
  15. * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  16. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
  17. * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  18. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  19. * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  20. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  21. *
  22. * Author: Keith Packard, SuSE, Inc.
  23. */
  24. #ifdef HAVE_DIX_CONFIG_H
  25. #include <dix-config.h>
  26. #endif
  27. #include <stdlib.h>
  28. #include "fb.h"
  29. #include "fboverlay.h"
  30. #include "shmint.h"
  31. int fbOverlayGeneration;
  32. static int fbOverlayScreenPrivateIndex = -1;
  33. int
  34. fbOverlayGetScreenPrivateIndex(void)
  35. {
  36. return fbOverlayScreenPrivateIndex;
  37. }
  38. /*
  39. * Replace this if you want something supporting
  40. * multiple overlays with the same depth
  41. */
  42. Bool
  43. fbOverlayCreateWindow(WindowPtr pWin)
  44. {
  45. FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pWin->drawable.pScreen);
  46. int i;
  47. PixmapPtr pPixmap;
  48. if (pWin->drawable.class != InputOutput)
  49. return TRUE;
  50. if (pWin->drawable.bitsPerPixel == 32)
  51. pWin->drawable.bitsPerPixel =
  52. fbGetScreenPrivate(pWin->drawable.pScreen)->win32bpp;
  53. for (i = 0; i < pScrPriv->nlayers; i++) {
  54. pPixmap = pScrPriv->layer[i].u.run.pixmap;
  55. if (pWin->drawable.depth == pPixmap->drawable.depth) {
  56. pWin->devPrivates[fbWinPrivateIndex].ptr = (pointer) pPixmap;
  57. /*
  58. * Make sure layer keys are written correctly by
  59. * having non-root layers set to full while the
  60. * root layer is set to empty. This will cause
  61. * all of the layers to get painted when the root
  62. * is mapped
  63. */
  64. if (!pWin->parent) {
  65. REGION_EMPTY(
  66. &pScrPriv->layer[i].u.run.region);
  67. }
  68. return TRUE;
  69. }
  70. }
  71. return FALSE;
  72. }
  73. Bool
  74. fbOverlayCloseScreen(int iScreen, ScreenPtr pScreen)
  75. {
  76. FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen);
  77. int i;
  78. for (i = 0; i < pScrPriv->nlayers; i++) {
  79. (*pScreen->DestroyPixmap) (pScrPriv->layer[i].u.run.pixmap);
  80. REGION_UNINIT(&pScrPriv->layer[i].u.run.region);
  81. }
  82. return TRUE;
  83. }
  84. /*
  85. * Return layer containing this window
  86. */
  87. int
  88. fbOverlayWindowLayer(WindowPtr pWin)
  89. {
  90. FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pWin->drawable.pScreen);
  91. int i;
  92. for (i = 0; i < pScrPriv->nlayers; i++)
  93. if (pWin->devPrivates[fbWinPrivateIndex].ptr ==
  94. (pointer) pScrPriv->layer[i].u.run.pixmap)
  95. return i;
  96. return 0;
  97. }
  98. Bool
  99. fbOverlayCreateScreenResources(ScreenPtr pScreen)
  100. {
  101. int i;
  102. FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen);
  103. PixmapPtr pPixmap;
  104. pointer pbits;
  105. int width;
  106. int depth;
  107. BoxRec box;
  108. if (!miCreateScreenResources(pScreen))
  109. return FALSE;
  110. box.x1 = 0;
  111. box.y1 = 0;
  112. box.x2 = pScreen->width;
  113. box.y2 = pScreen->height;
  114. for (i = 0; i < pScrPriv->nlayers; i++) {
  115. pbits = pScrPriv->layer[i].u.init.pbits;
  116. width = pScrPriv->layer[i].u.init.width;
  117. depth = pScrPriv->layer[i].u.init.depth;
  118. pPixmap = (*pScreen->CreatePixmap) (pScreen, 0, 0, depth);
  119. if (!pPixmap)
  120. return FALSE;
  121. if (!(*pScreen->ModifyPixmapHeader) (pPixmap, pScreen->width,
  122. pScreen->height, depth,
  123. BitsPerPixel(depth),
  124. PixmapBytePad(width, depth),
  125. pbits))
  126. return FALSE;
  127. pScrPriv->layer[i].u.run.pixmap = pPixmap;
  128. REGION_INIT(&pScrPriv->layer[i].u.run.region, &box, 0);
  129. }
  130. pScreen->devPrivate = pScrPriv->layer[0].u.run.pixmap;
  131. return TRUE;
  132. }
  133. void
  134. fbOverlayPaintKey(DrawablePtr pDrawable,
  135. RegionPtr pRegion, CARD32 pixel, int layer)
  136. {
  137. fbFillRegionSolid(pDrawable, pRegion, 0,
  138. fbReplicatePixel(pixel, pDrawable->bitsPerPixel));
  139. }
  140. /*
  141. * Track visible region for each layer
  142. */
  143. void
  144. fbOverlayUpdateLayerRegion(ScreenPtr pScreen, int layer, RegionPtr prgn)
  145. {
  146. FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen);
  147. int i;
  148. RegionRec rgnNew;
  149. if (!prgn || !REGION_NOTEMPTY(prgn))
  150. return;
  151. for (i = 0; i < pScrPriv->nlayers; i++) {
  152. if (i == layer) {
  153. /* add new piece to this fb */
  154. REGION_UNION(&pScrPriv->layer[i].u.run.region,
  155. &pScrPriv->layer[i].u.run.region, prgn);
  156. }
  157. else if (REGION_NOTEMPTY(&pScrPriv->layer[i].u.run.region)) {
  158. /* paint new piece with chroma key */
  159. REGION_NULL(&rgnNew);
  160. REGION_INTERSECT(&rgnNew, prgn, &pScrPriv->layer[i].u.run.region);
  161. (*pScrPriv->PaintKey) (&pScrPriv->layer[i].u.run.pixmap->drawable,
  162. &rgnNew, pScrPriv->layer[i].key, i);
  163. REGION_UNINIT(&rgnNew);
  164. /* remove piece from other fbs */
  165. REGION_SUBTRACT(
  166. &pScrPriv->layer[i].u.run.region,
  167. &pScrPriv->layer[i].u.run.region, prgn);
  168. }
  169. }
  170. }
  171. /*
  172. * Copy only areas in each layer containing real bits
  173. */
  174. void
  175. fbOverlayCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
  176. {
  177. ScreenPtr pScreen = pWin->drawable.pScreen;
  178. FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pWin->drawable.pScreen);
  179. RegionRec rgnDst;
  180. int dx, dy;
  181. int i;
  182. RegionRec layerRgn[FB_OVERLAY_MAX];
  183. PixmapPtr pPixmap;
  184. dx = ptOldOrg.x - pWin->drawable.x;
  185. dy = ptOldOrg.y - pWin->drawable.y;
  186. /*
  187. * Clip to existing bits
  188. */
  189. REGION_TRANSLATE(prgnSrc, -dx, -dy);
  190. REGION_NULL(&rgnDst);
  191. REGION_INTERSECT(&rgnDst, &pWin->borderClip, prgnSrc);
  192. REGION_TRANSLATE(&rgnDst, dx, dy);
  193. /*
  194. * Compute the portion of each fb affected by this copy
  195. */
  196. for (i = 0; i < pScrPriv->nlayers; i++) {
  197. REGION_NULL(&layerRgn[i]);
  198. REGION_INTERSECT(&layerRgn[i], &rgnDst,
  199. &pScrPriv->layer[i].u.run.region);
  200. if (REGION_NOTEMPTY(&layerRgn[i])) {
  201. REGION_TRANSLATE(&layerRgn[i], -dx, -dy);
  202. pPixmap = pScrPriv->layer[i].u.run.pixmap;
  203. fbCopyRegion(&pPixmap->drawable, &pPixmap->drawable,
  204. 0,
  205. &layerRgn[i], dx, dy, pScrPriv->CopyWindow, 0,
  206. (void *) (long) i);
  207. }
  208. }
  209. /*
  210. * Update regions
  211. */
  212. for (i = 0; i < pScrPriv->nlayers; i++) {
  213. if (REGION_NOTEMPTY(&layerRgn[i]))
  214. fbOverlayUpdateLayerRegion(pScreen, i, &layerRgn[i]);
  215. REGION_UNINIT(&layerRgn[i]);
  216. }
  217. REGION_UNINIT(&rgnDst);
  218. }
  219. void
  220. fbOverlayWindowExposures(WindowPtr pWin,
  221. RegionPtr prgn, RegionPtr other_exposed)
  222. {
  223. fbOverlayUpdateLayerRegion(pWin->drawable.pScreen,
  224. fbOverlayWindowLayer(pWin), prgn);
  225. miWindowExposures(pWin, prgn, other_exposed);
  226. }
  227. void
  228. fbOverlayPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what)
  229. {
  230. if (what == PW_BORDER)
  231. fbOverlayUpdateLayerRegion(pWin->drawable.pScreen,
  232. fbOverlayWindowLayer(pWin), pRegion);
  233. fbPaintWindow(pWin, pRegion, what);
  234. }
  235. Bool
  236. fbOverlaySetupScreen(ScreenPtr pScreen,
  237. pointer pbits1,
  238. pointer pbits2,
  239. int xsize,
  240. int ysize,
  241. int dpix,
  242. int dpiy, int width1, int width2, int bpp1, int bpp2)
  243. {
  244. return fbSetupScreen(pScreen,
  245. pbits1, xsize, ysize, dpix, dpiy, width1, bpp1);
  246. }
  247. static Bool
  248. fb24_32OverlayCreateScreenResources(ScreenPtr pScreen)
  249. {
  250. FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen);
  251. int pitch;
  252. Bool retval;
  253. int i;
  254. if ((retval = fbOverlayCreateScreenResources(pScreen))) {
  255. for (i = 0; i < pScrPriv->nlayers; i++) {
  256. /* fix the screen pixmap */
  257. PixmapPtr pPix = (PixmapPtr) pScrPriv->layer[i].u.run.pixmap;
  258. if (pPix->drawable.bitsPerPixel == 32) {
  259. pPix->drawable.bitsPerPixel = 24;
  260. pitch = BitmapBytePad(pPix->drawable.width * 24);
  261. pPix->devKind = pitch;
  262. }
  263. }
  264. }
  265. return retval;
  266. }
  267. Bool
  268. fbOverlayFinishScreenInit(ScreenPtr pScreen,
  269. pointer pbits1,
  270. pointer pbits2,
  271. int xsize,
  272. int ysize,
  273. int dpix,
  274. int dpiy,
  275. int width1,
  276. int width2,
  277. int bpp1, int bpp2, int depth1, int depth2)
  278. {
  279. VisualPtr visuals;
  280. DepthPtr depths;
  281. int nvisuals;
  282. int ndepths;
  283. int bpp = 0, imagebpp = 32;
  284. VisualID defaultVisual;
  285. FbOverlayScrPrivPtr pScrPriv;
  286. if (fbOverlayGeneration != serverGeneration) {
  287. fbOverlayScreenPrivateIndex = AllocateScreenPrivateIndex();
  288. fbOverlayGeneration = serverGeneration;
  289. }
  290. pScrPriv = malloc(sizeof(FbOverlayScrPrivRec));
  291. if (!pScrPriv)
  292. return FALSE;
  293. if (bpp1 == 32 || bpp2 == 32)
  294. bpp = 32;
  295. else if (bpp1 == 24 || bpp2 == 24)
  296. bpp = 24;
  297. if (bpp == 24) {
  298. int f;
  299. imagebpp = 32;
  300. /*
  301. * Check to see if we're advertising a 24bpp image format,
  302. * in which case windows will use it in preference to a 32 bit
  303. * format.
  304. */
  305. for (f = 0; f < screenInfo.numPixmapFormats; f++) {
  306. if (screenInfo.formats[f].bitsPerPixel == 24) {
  307. imagebpp = 24;
  308. break;
  309. }
  310. }
  311. }
  312. if (imagebpp == 32) {
  313. fbGetScreenPrivate(pScreen)->win32bpp = bpp;
  314. fbGetScreenPrivate(pScreen)->pix32bpp = bpp;
  315. }
  316. else {
  317. fbGetScreenPrivate(pScreen)->win32bpp = 32;
  318. fbGetScreenPrivate(pScreen)->pix32bpp = 32;
  319. }
  320. if (!fbInitVisuals(&visuals, &depths, &nvisuals, &ndepths, &depth1,
  321. &defaultVisual, ((unsigned long) 1 << (bpp1 - 1)) |
  322. ((unsigned long) 1 << (bpp2 - 1)), 8))
  323. return FALSE;
  324. if (!miScreenInit(pScreen, 0, xsize, ysize, dpix, dpiy, 0,
  325. depth1, ndepths, depths, defaultVisual, nvisuals, visuals
  326. ))
  327. return FALSE;
  328. /* MI thinks there's no frame buffer */
  329. ShmRegisterFbFuncs(pScreen);
  330. pScreen->minInstalledCmaps = 1;
  331. pScreen->maxInstalledCmaps = 2;
  332. pScrPriv->nlayers = 2;
  333. pScrPriv->PaintKey = fbOverlayPaintKey;
  334. pScrPriv->CopyWindow = fbCopyWindowProc;
  335. pScrPriv->layer[0].u.init.pbits = pbits1;
  336. pScrPriv->layer[0].u.init.width = width1;
  337. pScrPriv->layer[0].u.init.depth = depth1;
  338. pScrPriv->layer[1].u.init.pbits = pbits2;
  339. pScrPriv->layer[1].u.init.width = width2;
  340. pScrPriv->layer[1].u.init.depth = depth2;
  341. pScreen->devPrivates[fbOverlayScreenPrivateIndex].ptr = (pointer) pScrPriv;
  342. /* overwrite miCloseScreen with our own */
  343. pScreen->CloseScreen = fbOverlayCloseScreen;
  344. pScreen->CreateScreenResources = fbOverlayCreateScreenResources;
  345. pScreen->CreateWindow = fbOverlayCreateWindow;
  346. pScreen->WindowExposures = fbOverlayWindowExposures;
  347. pScreen->CopyWindow = fbOverlayCopyWindow;
  348. pScreen->PaintWindowBorder = fbOverlayPaintWindow;
  349. if (bpp == 24 && imagebpp == 32) {
  350. pScreen->ModifyPixmapHeader = fb24_32ModifyPixmapHeader;
  351. pScreen->CreateScreenResources = fb24_32OverlayCreateScreenResources;
  352. }
  353. return TRUE;
  354. }