Add patch that contain Mali fixes.
[deb_xorg-server.git] / fb / fboverlay.c
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
25 #ifdef HAVE_DIX_CONFIG_H
26 #include <dix-config.h>
27 #endif
28
29 #include <stdlib.h>
30
31 #include "fb.h"
32 #include "fboverlay.h"
33 #include "shmint.h"
34
35 static DevPrivateKeyRec fbOverlayScreenPrivateKeyRec;
36
37 #define fbOverlayScreenPrivateKey (&fbOverlayScreenPrivateKeyRec)
38
39 DevPrivateKey
40 fbOverlayGetScreenPrivateKey(void)
41 {
42 return fbOverlayScreenPrivateKey;
43 }
44
45 /*
46 * Replace this if you want something supporting
47 * multiple overlays with the same depth
48 */
49 Bool
50 fbOverlayCreateWindow(WindowPtr pWin)
51 {
52 FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pWin->drawable.pScreen);
53 int i;
54 PixmapPtr pPixmap;
55
56 if (pWin->drawable.class != InputOutput)
57 return TRUE;
58
59 if (pWin->drawable.bitsPerPixel == 32)
60 pWin->drawable.bitsPerPixel =
61 fbGetScreenPrivate(pWin->drawable.pScreen)->win32bpp;
62
63 for (i = 0; i < pScrPriv->nlayers; i++) {
64 pPixmap = pScrPriv->layer[i].u.run.pixmap;
65 if (pWin->drawable.depth == pPixmap->drawable.depth) {
66 dixSetPrivate(&pWin->devPrivates, fbGetWinPrivateKey(pWin), pPixmap);
67 /*
68 * Make sure layer keys are written correctly by
69 * having non-root layers set to full while the
70 * root layer is set to empty. This will cause
71 * all of the layers to get painted when the root
72 * is mapped
73 */
74 if (!pWin->parent) {
75 RegionEmpty(&pScrPriv->layer[i].u.run.region);
76 }
77 return TRUE;
78 }
79 }
80 return FALSE;
81 }
82
83 Bool
84 fbOverlayCloseScreen(ScreenPtr pScreen)
85 {
86 FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen);
87 int i;
88
89 for (i = 0; i < pScrPriv->nlayers; i++) {
90 (*pScreen->DestroyPixmap) (pScrPriv->layer[i].u.run.pixmap);
91 RegionUninit(&pScrPriv->layer[i].u.run.region);
92 }
93 return TRUE;
94 }
95
96 /*
97 * Return layer containing this window
98 */
99 int
100 fbOverlayWindowLayer(WindowPtr pWin)
101 {
102 FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pWin->drawable.pScreen);
103 int i;
104
105 for (i = 0; i < pScrPriv->nlayers; i++)
106 if (dixLookupPrivate(&pWin->devPrivates, fbGetWinPrivateKey(pWin)) ==
107 (pointer) pScrPriv->layer[i].u.run.pixmap)
108 return i;
109 return 0;
110 }
111
112 Bool
113 fbOverlayCreateScreenResources(ScreenPtr pScreen)
114 {
115 int i;
116 FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen);
117 PixmapPtr pPixmap;
118 pointer pbits;
119 int width;
120 int depth;
121 BoxRec box;
122
123 if (!miCreateScreenResources(pScreen))
124 return FALSE;
125
126 box.x1 = 0;
127 box.y1 = 0;
128 box.x2 = pScreen->width;
129 box.y2 = pScreen->height;
130 for (i = 0; i < pScrPriv->nlayers; i++) {
131 pbits = pScrPriv->layer[i].u.init.pbits;
132 width = pScrPriv->layer[i].u.init.width;
133 depth = pScrPriv->layer[i].u.init.depth;
134 pPixmap = (*pScreen->CreatePixmap) (pScreen, 0, 0, depth, 0);
135 if (!pPixmap)
136 return FALSE;
137 if (!(*pScreen->ModifyPixmapHeader) (pPixmap, pScreen->width,
138 pScreen->height, depth,
139 BitsPerPixel(depth),
140 PixmapBytePad(width, depth),
141 pbits))
142 return FALSE;
143 pScrPriv->layer[i].u.run.pixmap = pPixmap;
144 RegionInit(&pScrPriv->layer[i].u.run.region, &box, 0);
145 }
146 pScreen->devPrivate = pScrPriv->layer[0].u.run.pixmap;
147 return TRUE;
148 }
149
150 void
151 fbOverlayPaintKey(DrawablePtr pDrawable,
152 RegionPtr pRegion, CARD32 pixel, int layer)
153 {
154 fbFillRegionSolid(pDrawable, pRegion, 0,
155 fbReplicatePixel(pixel, pDrawable->bitsPerPixel));
156 }
157
158 /*
159 * Track visible region for each layer
160 */
161 void
162 fbOverlayUpdateLayerRegion(ScreenPtr pScreen, int layer, RegionPtr prgn)
163 {
164 FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen);
165 int i;
166 RegionRec rgnNew;
167
168 if (!prgn || !RegionNotEmpty(prgn))
169 return;
170 for (i = 0; i < pScrPriv->nlayers; i++) {
171 if (i == layer) {
172 /* add new piece to this fb */
173 RegionUnion(&pScrPriv->layer[i].u.run.region,
174 &pScrPriv->layer[i].u.run.region, prgn);
175 }
176 else if (RegionNotEmpty(&pScrPriv->layer[i].u.run.region)) {
177 /* paint new piece with chroma key */
178 RegionNull(&rgnNew);
179 RegionIntersect(&rgnNew, prgn, &pScrPriv->layer[i].u.run.region);
180 (*pScrPriv->PaintKey) (&pScrPriv->layer[i].u.run.pixmap->drawable,
181 &rgnNew, pScrPriv->layer[i].key, i);
182 RegionUninit(&rgnNew);
183 /* remove piece from other fbs */
184 RegionSubtract(&pScrPriv->layer[i].u.run.region,
185 &pScrPriv->layer[i].u.run.region, prgn);
186 }
187 }
188 }
189
190 /*
191 * Copy only areas in each layer containing real bits
192 */
193 void
194 fbOverlayCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
195 {
196 ScreenPtr pScreen = pWin->drawable.pScreen;
197 FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen);
198 RegionRec rgnDst;
199 int dx, dy;
200 int i;
201 RegionRec layerRgn[FB_OVERLAY_MAX];
202 PixmapPtr pPixmap;
203
204 dx = ptOldOrg.x - pWin->drawable.x;
205 dy = ptOldOrg.y - pWin->drawable.y;
206
207 /*
208 * Clip to existing bits
209 */
210 RegionTranslate(prgnSrc, -dx, -dy);
211 RegionNull(&rgnDst);
212 RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc);
213 RegionTranslate(&rgnDst, dx, dy);
214 /*
215 * Compute the portion of each fb affected by this copy
216 */
217 for (i = 0; i < pScrPriv->nlayers; i++) {
218 RegionNull(&layerRgn[i]);
219 RegionIntersect(&layerRgn[i], &rgnDst,
220 &pScrPriv->layer[i].u.run.region);
221 if (RegionNotEmpty(&layerRgn[i])) {
222 RegionTranslate(&layerRgn[i], -dx, -dy);
223 pPixmap = pScrPriv->layer[i].u.run.pixmap;
224 miCopyRegion(&pPixmap->drawable, &pPixmap->drawable,
225 0,
226 &layerRgn[i], dx, dy, pScrPriv->CopyWindow, 0,
227 (void *) (long) i);
228 }
229 }
230 /*
231 * Update regions
232 */
233 for (i = 0; i < pScrPriv->nlayers; i++) {
234 if (RegionNotEmpty(&layerRgn[i]))
235 fbOverlayUpdateLayerRegion(pScreen, i, &layerRgn[i]);
236
237 RegionUninit(&layerRgn[i]);
238 }
239 RegionUninit(&rgnDst);
240 }
241
242 void
243 fbOverlayWindowExposures(WindowPtr pWin,
244 RegionPtr prgn, RegionPtr other_exposed)
245 {
246 fbOverlayUpdateLayerRegion(pWin->drawable.pScreen,
247 fbOverlayWindowLayer(pWin), prgn);
248 miWindowExposures(pWin, prgn, other_exposed);
249 }
250
251 Bool
252 fbOverlaySetupScreen(ScreenPtr pScreen,
253 pointer pbits1,
254 pointer pbits2,
255 int xsize,
256 int ysize,
257 int dpix,
258 int dpiy, int width1, int width2, int bpp1, int bpp2)
259 {
260 return fbSetupScreen(pScreen,
261 pbits1, xsize, ysize, dpix, dpiy, width1, bpp1);
262 }
263
264 static Bool
265 fb24_32OverlayCreateScreenResources(ScreenPtr pScreen)
266 {
267 FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen);
268 int pitch;
269 Bool retval;
270 int i;
271
272 if ((retval = fbOverlayCreateScreenResources(pScreen))) {
273 for (i = 0; i < pScrPriv->nlayers; i++) {
274 /* fix the screen pixmap */
275 PixmapPtr pPix = (PixmapPtr) pScrPriv->layer[i].u.run.pixmap;
276
277 if (pPix->drawable.bitsPerPixel == 32) {
278 pPix->drawable.bitsPerPixel = 24;
279 pitch = BitmapBytePad(pPix->drawable.width * 24);
280 pPix->devKind = pitch;
281 }
282 }
283 }
284
285 return retval;
286 }
287
288 Bool
289 fbOverlayFinishScreenInit(ScreenPtr pScreen,
290 pointer pbits1,
291 pointer pbits2,
292 int xsize,
293 int ysize,
294 int dpix,
295 int dpiy,
296 int width1,
297 int width2,
298 int bpp1, int bpp2, int depth1, int depth2)
299 {
300 VisualPtr visuals;
301 DepthPtr depths;
302 int nvisuals;
303 int ndepths;
304 int bpp = 0, imagebpp = 32;
305 VisualID defaultVisual;
306 FbOverlayScrPrivPtr pScrPriv;
307
308 if (!dixRegisterPrivateKey
309 (&fbOverlayScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
310 return FALSE;
311
312 pScrPriv = malloc(sizeof(FbOverlayScrPrivRec));
313 if (!pScrPriv)
314 return FALSE;
315
316 if (bpp1 == 32 || bpp2 == 32)
317 bpp = 32;
318 else if (bpp1 == 24 || bpp2 == 24)
319 bpp = 24;
320
321 if (bpp == 24) {
322 int f;
323
324 imagebpp = 32;
325 /*
326 * Check to see if we're advertising a 24bpp image format,
327 * in which case windows will use it in preference to a 32 bit
328 * format.
329 */
330 for (f = 0; f < screenInfo.numPixmapFormats; f++) {
331 if (screenInfo.formats[f].bitsPerPixel == 24) {
332 imagebpp = 24;
333 break;
334 }
335 }
336 }
337 if (imagebpp == 32) {
338 fbGetScreenPrivate(pScreen)->win32bpp = bpp;
339 fbGetScreenPrivate(pScreen)->pix32bpp = bpp;
340 }
341 else {
342 fbGetScreenPrivate(pScreen)->win32bpp = 32;
343 fbGetScreenPrivate(pScreen)->pix32bpp = 32;
344 }
345
346 if (!fbInitVisuals(&visuals, &depths, &nvisuals, &ndepths, &depth1,
347 &defaultVisual, ((unsigned long) 1 << (bpp1 - 1)) |
348 ((unsigned long) 1 << (bpp2 - 1)), 8)) {
349 free(pScrPriv);
350 return FALSE;
351 }
352 if (!miScreenInit(pScreen, 0, xsize, ysize, dpix, dpiy, 0,
353 depth1, ndepths, depths,
354 defaultVisual, nvisuals, visuals)) {
355 free(pScrPriv);
356 return FALSE;
357 }
358 /* MI thinks there's no frame buffer */
359 #ifdef MITSHM
360 ShmRegisterFbFuncs(pScreen);
361 #endif
362 pScreen->minInstalledCmaps = 1;
363 pScreen->maxInstalledCmaps = 2;
364
365 pScrPriv->nlayers = 2;
366 pScrPriv->PaintKey = fbOverlayPaintKey;
367 pScrPriv->CopyWindow = fbCopyWindowProc;
368 pScrPriv->layer[0].u.init.pbits = pbits1;
369 pScrPriv->layer[0].u.init.width = width1;
370 pScrPriv->layer[0].u.init.depth = depth1;
371
372 pScrPriv->layer[1].u.init.pbits = pbits2;
373 pScrPriv->layer[1].u.init.width = width2;
374 pScrPriv->layer[1].u.init.depth = depth2;
375 dixSetPrivate(&pScreen->devPrivates, fbOverlayScreenPrivateKey, pScrPriv);
376
377 /* overwrite miCloseScreen with our own */
378 pScreen->CloseScreen = fbOverlayCloseScreen;
379 pScreen->CreateScreenResources = fbOverlayCreateScreenResources;
380 pScreen->CreateWindow = fbOverlayCreateWindow;
381 pScreen->WindowExposures = fbOverlayWindowExposures;
382 pScreen->CopyWindow = fbOverlayCopyWindow;
383 if (bpp == 24 && imagebpp == 32) {
384 pScreen->ModifyPixmapHeader = fb24_32ModifyPixmapHeader;
385 pScreen->CreateScreenResources = fb24_32OverlayCreateScreenResources;
386 }
387
388 return TRUE;
389 }