Commit | Line | Data |
---|---|---|
a09e091a JB |
1 | /* |
2 | * Copyright © 2000 SuSE, Inc. | |
3 | * | |
4 | * Permission to use, copy, modify, distribute, and sell this software and its | |
5 | * documentation for any purpose is hereby granted without fee, provided that | |
6 | * the above copyright notice appear in all copies and that both that | |
7 | * copyright notice and this permission notice appear in supporting | |
8 | * documentation, and that the name of SuSE not be used in advertising or | |
9 | * publicity pertaining to distribution of the software without specific, | |
10 | * written prior permission. SuSE makes no representations about the | |
11 | * suitability of this software for any purpose. It is provided "as is" | |
12 | * without express or implied warranty. | |
13 | * | |
14 | * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL | |
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE | |
16 | * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
17 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | |
18 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |
19 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
20 | * | |
21 | * Author: Keith Packard, SuSE, Inc. | |
22 | */ | |
23 | ||
24 | #ifdef HAVE_DIX_CONFIG_H | |
25 | #include <dix-config.h> | |
26 | #endif | |
27 | ||
28 | #include <string.h> | |
29 | ||
30 | #include "fb.h" | |
31 | ||
32 | /* X apps don't like 24bpp images, this code exposes 32bpp images */ | |
33 | ||
34 | /* | |
35 | * These two functions do a full CopyArea while reformatting | |
36 | * the data between 24 and 32bpp. They try to go a bit faster | |
37 | * by reading/writing aligned CARD32s where it's easy | |
38 | */ | |
39 | ||
40 | #define Get8(a) ((CARD32) READ(a)) | |
41 | ||
42 | #if BITMAP_BIT_ORDER == MSBFirst | |
43 | #define Get24(a) ((Get8(a) << 16) | (Get8((a)+1) << 8) | Get8((a)+2)) | |
44 | #define Put24(a,p) ((WRITE((a+0), (CARD8) ((p) >> 16))), \ | |
45 | (WRITE((a+1), (CARD8) ((p) >> 8))), \ | |
46 | (WRITE((a+2), (CARD8) (p)))) | |
47 | #else | |
48 | #define Get24(a) (Get8(a) | (Get8((a)+1) << 8) | (Get8((a)+2)<<16)) | |
49 | #define Put24(a,p) ((WRITE((a+0), (CARD8) (p))), \ | |
50 | (WRITE((a+1), (CARD8) ((p) >> 8))), \ | |
51 | (WRITE((a+2), (CARD8) ((p) >> 16)))) | |
52 | #endif | |
53 | ||
54 | typedef void (*fb24_32BltFunc) (CARD8 *srcLine, | |
55 | FbStride srcStride, | |
56 | int srcX, | |
57 | CARD8 *dstLine, | |
58 | FbStride dstStride, | |
59 | int dstX, | |
60 | int width, int height, int alu, FbBits pm); | |
61 | ||
62 | static void | |
63 | fb24_32BltDown(CARD8 *srcLine, | |
64 | FbStride srcStride, | |
65 | int srcX, | |
66 | CARD8 *dstLine, | |
67 | FbStride dstStride, | |
68 | int dstX, int width, int height, int alu, FbBits pm) | |
69 | { | |
70 | CARD32 *src; | |
71 | CARD8 *dst; | |
72 | int w; | |
73 | Bool destInvarient; | |
74 | CARD32 pixel, dpixel; | |
75 | ||
76 | FbDeclareMergeRop(); | |
77 | ||
78 | srcLine += srcX * 4; | |
79 | dstLine += dstX * 3; | |
80 | ||
81 | FbInitializeMergeRop(alu, (pm | ~(FbBits) 0xffffff)); | |
82 | destInvarient = FbDestInvarientMergeRop(); | |
83 | ||
84 | while (height--) { | |
85 | src = (CARD32 *) srcLine; | |
86 | dst = dstLine; | |
87 | srcLine += srcStride; | |
88 | dstLine += dstStride; | |
89 | w = width; | |
90 | if (destInvarient) { | |
91 | while (((long) dst & 3) && w) { | |
92 | w--; | |
93 | pixel = READ(src++); | |
94 | pixel = FbDoDestInvarientMergeRop(pixel); | |
95 | Put24(dst, pixel); | |
96 | dst += 3; | |
97 | } | |
98 | /* Do four aligned pixels at a time */ | |
99 | while (w >= 4) { | |
100 | CARD32 s0, s1; | |
101 | ||
102 | s0 = READ(src++); | |
103 | s0 = FbDoDestInvarientMergeRop(s0); | |
104 | s1 = READ(src++); | |
105 | s1 = FbDoDestInvarientMergeRop(s1); | |
106 | #if BITMAP_BIT_ORDER == LSBFirst | |
107 | WRITE((CARD32 *) dst, (s0 & 0xffffff) | (s1 << 24)); | |
108 | #else | |
109 | WRITE((CARD32 *) dst, (s0 << 8) | ((s1 & 0xffffff) >> 16)); | |
110 | #endif | |
111 | s0 = READ(src++); | |
112 | s0 = FbDoDestInvarientMergeRop(s0); | |
113 | #if BITMAP_BIT_ORDER == LSBFirst | |
114 | WRITE((CARD32 *) (dst + 4), | |
115 | ((s1 & 0xffffff) >> 8) | (s0 << 16)); | |
116 | #else | |
117 | WRITE((CARD32 *) (dst + 4), | |
118 | (s1 << 16) | ((s0 & 0xffffff) >> 8)); | |
119 | #endif | |
120 | s1 = READ(src++); | |
121 | s1 = FbDoDestInvarientMergeRop(s1); | |
122 | #if BITMAP_BIT_ORDER == LSBFirst | |
123 | WRITE((CARD32 *) (dst + 8), | |
124 | ((s0 & 0xffffff) >> 16) | (s1 << 8)); | |
125 | #else | |
126 | WRITE((CARD32 *) (dst + 8), (s0 << 24) | (s1 & 0xffffff)); | |
127 | #endif | |
128 | dst += 12; | |
129 | w -= 4; | |
130 | } | |
131 | while (w--) { | |
132 | pixel = READ(src++); | |
133 | pixel = FbDoDestInvarientMergeRop(pixel); | |
134 | Put24(dst, pixel); | |
135 | dst += 3; | |
136 | } | |
137 | } | |
138 | else { | |
139 | while (w--) { | |
140 | pixel = READ(src++); | |
141 | dpixel = Get24(dst); | |
142 | pixel = FbDoMergeRop(pixel, dpixel); | |
143 | Put24(dst, pixel); | |
144 | dst += 3; | |
145 | } | |
146 | } | |
147 | } | |
148 | } | |
149 | ||
150 | static void | |
151 | fb24_32BltUp(CARD8 *srcLine, | |
152 | FbStride srcStride, | |
153 | int srcX, | |
154 | CARD8 *dstLine, | |
155 | FbStride dstStride, | |
156 | int dstX, int width, int height, int alu, FbBits pm) | |
157 | { | |
158 | CARD8 *src; | |
159 | CARD32 *dst; | |
160 | int w; | |
161 | Bool destInvarient; | |
162 | CARD32 pixel; | |
163 | ||
164 | FbDeclareMergeRop(); | |
165 | ||
166 | FbInitializeMergeRop(alu, (pm | (~(FbBits) 0xffffff))); | |
167 | destInvarient = FbDestInvarientMergeRop(); | |
168 | ||
169 | srcLine += srcX * 3; | |
170 | dstLine += dstX * 4; | |
171 | ||
172 | while (height--) { | |
173 | w = width; | |
174 | src = srcLine; | |
175 | dst = (CARD32 *) dstLine; | |
176 | srcLine += srcStride; | |
177 | dstLine += dstStride; | |
178 | if (destInvarient) { | |
179 | while (((long) src & 3) && w) { | |
180 | w--; | |
181 | pixel = Get24(src); | |
182 | src += 3; | |
183 | WRITE(dst++, FbDoDestInvarientMergeRop(pixel)); | |
184 | } | |
185 | /* Do four aligned pixels at a time */ | |
186 | while (w >= 4) { | |
187 | CARD32 s0, s1; | |
188 | ||
189 | s0 = READ((CARD32 *) src); | |
190 | #if BITMAP_BIT_ORDER == LSBFirst | |
191 | pixel = s0 & 0xffffff; | |
192 | #else | |
193 | pixel = s0 >> 8; | |
194 | #endif | |
195 | WRITE(dst++, FbDoDestInvarientMergeRop(pixel)); | |
196 | s1 = READ((CARD32 *) (src + 4)); | |
197 | #if BITMAP_BIT_ORDER == LSBFirst | |
198 | pixel = (s0 >> 24) | ((s1 << 8) & 0xffffff); | |
199 | #else | |
200 | pixel = ((s0 << 16) & 0xffffff) | (s1 >> 16); | |
201 | #endif | |
202 | WRITE(dst++, FbDoDestInvarientMergeRop(pixel)); | |
203 | s0 = READ((CARD32 *) (src + 8)); | |
204 | #if BITMAP_BIT_ORDER == LSBFirst | |
205 | pixel = (s1 >> 16) | ((s0 << 16) & 0xffffff); | |
206 | #else | |
207 | pixel = ((s1 << 8) & 0xffffff) | (s0 >> 24); | |
208 | #endif | |
209 | WRITE(dst++, FbDoDestInvarientMergeRop(pixel)); | |
210 | #if BITMAP_BIT_ORDER == LSBFirst | |
211 | pixel = s0 >> 8; | |
212 | #else | |
213 | pixel = s0 & 0xffffff; | |
214 | #endif | |
215 | WRITE(dst++, FbDoDestInvarientMergeRop(pixel)); | |
216 | src += 12; | |
217 | w -= 4; | |
218 | } | |
219 | while (w) { | |
220 | w--; | |
221 | pixel = Get24(src); | |
222 | src += 3; | |
223 | WRITE(dst++, FbDoDestInvarientMergeRop(pixel)); | |
224 | } | |
225 | } | |
226 | else { | |
227 | while (w--) { | |
228 | pixel = Get24(src); | |
229 | src += 3; | |
230 | WRITE(dst, FbDoMergeRop(pixel, READ(dst))); | |
231 | dst++; | |
232 | } | |
233 | } | |
234 | } | |
235 | } | |
236 | ||
237 | /* | |
238 | * Spans functions; probably unused. | |
239 | */ | |
240 | void | |
241 | fb24_32GetSpans(DrawablePtr pDrawable, | |
242 | int wMax, | |
243 | DDXPointPtr ppt, int *pwidth, int nspans, char *pchardstStart) | |
244 | { | |
245 | FbBits *srcBits; | |
246 | CARD8 *src; | |
247 | FbStride srcStride; | |
248 | int srcBpp; | |
249 | int srcXoff, srcYoff; | |
250 | CARD8 *dst; | |
251 | ||
252 | fbGetDrawable(pDrawable, srcBits, srcStride, srcBpp, srcXoff, srcYoff); | |
253 | src = (CARD8 *) srcBits; | |
254 | srcStride *= sizeof(FbBits); | |
255 | ||
256 | while (nspans--) { | |
257 | dst = (CARD8 *) pchardstStart; | |
258 | fb24_32BltUp(src + (ppt->y + srcYoff) * srcStride, srcStride, | |
259 | ppt->x + srcXoff, | |
260 | dst, 1, 0, *pwidth, 1, GXcopy, FB_ALLONES); | |
261 | ||
262 | pchardstStart += PixmapBytePad(*pwidth, pDrawable->depth); | |
263 | ppt++; | |
264 | pwidth++; | |
265 | } | |
266 | ||
267 | fbFinishAccess(pDrawable); | |
268 | } | |
269 | ||
270 | void | |
271 | fb24_32SetSpans(DrawablePtr pDrawable, | |
272 | GCPtr pGC, | |
273 | char *src, | |
274 | DDXPointPtr ppt, int *pwidth, int nspans, int fSorted) | |
275 | { | |
276 | FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); | |
277 | RegionPtr pClip = fbGetCompositeClip(pGC); | |
278 | FbBits *dstBits; | |
279 | CARD8 *dst, *d, *s; | |
280 | FbStride dstStride; | |
281 | int dstBpp; | |
282 | int dstXoff, dstYoff; | |
283 | BoxPtr pbox; | |
284 | int n; | |
285 | int x1, x2; | |
286 | ||
287 | fbGetDrawable(pDrawable, dstBits, dstStride, dstBpp, dstXoff, dstYoff); | |
288 | dst = (CARD8 *) dstBits; | |
289 | dstStride *= sizeof(FbBits); | |
290 | while (nspans--) { | |
291 | d = dst + (ppt->y + dstYoff) * dstStride; | |
292 | s = (CARD8 *) src; | |
293 | n = RegionNumRects(pClip); | |
294 | pbox = RegionRects(pClip); | |
295 | while (n--) { | |
296 | if (pbox->y1 > ppt->y) | |
297 | break; | |
298 | if (pbox->y2 > ppt->y) { | |
299 | x1 = ppt->x; | |
300 | x2 = x1 + *pwidth; | |
301 | if (pbox->x1 > x1) | |
302 | x1 = pbox->x1; | |
303 | if (pbox->x2 < x2) | |
304 | x2 = pbox->x2; | |
305 | if (x1 < x2) | |
306 | fb24_32BltDown(s, | |
307 | 0, | |
308 | (x1 - ppt->x), | |
309 | d, | |
310 | dstStride, | |
311 | x1 + dstXoff, | |
312 | (x2 - x1), 1, pGC->alu, pPriv->pm); | |
313 | } | |
314 | } | |
315 | src += PixmapBytePad(*pwidth, pDrawable->depth); | |
316 | ppt++; | |
317 | pwidth++; | |
318 | } | |
319 | ||
320 | fbFinishAccess(pDrawable); | |
321 | } | |
322 | ||
323 | /* | |
324 | * Clip and put 32bpp Z-format images to a 24bpp drawable | |
325 | */ | |
326 | void | |
327 | fb24_32PutZImage(DrawablePtr pDrawable, | |
328 | RegionPtr pClip, | |
329 | int alu, | |
330 | FbBits pm, | |
331 | int x, | |
332 | int y, int width, int height, CARD8 *src, FbStride srcStride) | |
333 | { | |
334 | FbBits *dstBits; | |
335 | CARD8 *dst; | |
336 | FbStride dstStride; | |
337 | int dstBpp; | |
338 | int dstXoff, dstYoff; | |
339 | int nbox; | |
340 | BoxPtr pbox; | |
341 | int x1, y1, x2, y2; | |
342 | ||
343 | fbGetDrawable(pDrawable, dstBits, dstStride, dstBpp, dstXoff, dstYoff); | |
344 | dstStride *= sizeof(FbBits); | |
345 | dst = (CARD8 *) dstBits; | |
346 | ||
347 | for (nbox = RegionNumRects(pClip), | |
348 | pbox = RegionRects(pClip); nbox--; pbox++) { | |
349 | x1 = x; | |
350 | y1 = y; | |
351 | x2 = x + width; | |
352 | y2 = y + height; | |
353 | if (x1 < pbox->x1) | |
354 | x1 = pbox->x1; | |
355 | if (y1 < pbox->y1) | |
356 | y1 = pbox->y1; | |
357 | if (x2 > pbox->x2) | |
358 | x2 = pbox->x2; | |
359 | if (y2 > pbox->y2) | |
360 | y2 = pbox->y2; | |
361 | if (x1 >= x2 || y1 >= y2) | |
362 | continue; | |
363 | fb24_32BltDown(src + (y1 - y) * srcStride, | |
364 | srcStride, | |
365 | (x1 - x), | |
366 | dst + (y1 + dstYoff) * dstStride, | |
367 | dstStride, x1 + dstXoff, (x2 - x1), (y2 - y1), alu, pm); | |
368 | } | |
369 | ||
370 | fbFinishAccess(pDrawable); | |
371 | } | |
372 | ||
373 | void | |
374 | fb24_32GetImage(DrawablePtr pDrawable, | |
375 | int x, | |
376 | int y, | |
377 | int w, | |
378 | int h, unsigned int format, unsigned long planeMask, char *d) | |
379 | { | |
380 | FbBits *srcBits; | |
381 | CARD8 *src; | |
382 | FbStride srcStride; | |
383 | int srcBpp; | |
384 | int srcXoff, srcYoff; | |
385 | FbStride dstStride; | |
386 | FbBits pm; | |
387 | ||
388 | fbGetDrawable(pDrawable, srcBits, srcStride, srcBpp, srcXoff, srcYoff); | |
389 | src = (CARD8 *) srcBits; | |
390 | srcStride *= sizeof(FbBits); | |
391 | ||
392 | x += pDrawable->x; | |
393 | y += pDrawable->y; | |
394 | ||
395 | pm = fbReplicatePixel(planeMask, 32); | |
396 | dstStride = PixmapBytePad(w, pDrawable->depth); | |
397 | if (pm != FB_ALLONES) | |
398 | memset(d, 0, dstStride * h); | |
399 | fb24_32BltUp(src + (y + srcYoff) * srcStride, srcStride, x + srcXoff, | |
400 | (CARD8 *) d, dstStride, 0, w, h, GXcopy, pm); | |
401 | ||
402 | fbFinishAccess(pDrawable); | |
403 | } | |
404 | ||
405 | void | |
406 | fb24_32CopyMtoN(DrawablePtr pSrcDrawable, | |
407 | DrawablePtr pDstDrawable, | |
408 | GCPtr pGC, | |
409 | BoxPtr pbox, | |
410 | int nbox, | |
411 | int dx, | |
412 | int dy, | |
413 | Bool reverse, Bool upsidedown, Pixel bitplane, void *closure) | |
414 | { | |
415 | FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); | |
416 | FbBits *srcBits; | |
417 | CARD8 *src; | |
418 | FbStride srcStride; | |
419 | int srcBpp; | |
420 | FbBits *dstBits; | |
421 | CARD8 *dst; | |
422 | FbStride dstStride; | |
423 | int dstBpp; | |
424 | fb24_32BltFunc blt; | |
425 | int srcXoff, srcYoff; | |
426 | int dstXoff, dstYoff; | |
427 | ||
428 | fbGetDrawable(pSrcDrawable, srcBits, srcStride, srcBpp, srcXoff, srcYoff); | |
429 | src = (CARD8 *) srcBits; | |
430 | srcStride *= sizeof(FbBits); | |
431 | fbGetDrawable(pDstDrawable, dstBits, dstStride, dstBpp, dstXoff, dstYoff); | |
432 | dst = (CARD8 *) dstBits; | |
433 | dstStride *= sizeof(FbBits); | |
434 | if (srcBpp == 24) | |
435 | blt = fb24_32BltUp; | |
436 | else | |
437 | blt = fb24_32BltDown; | |
438 | ||
439 | while (nbox--) { | |
440 | (*blt) (src + (pbox->y1 + dy + srcYoff) * srcStride, | |
441 | srcStride, | |
442 | (pbox->x1 + dx + srcXoff), | |
443 | dst + (pbox->y1 + dstYoff) * dstStride, | |
444 | dstStride, | |
445 | (pbox->x1 + dstXoff), | |
446 | (pbox->x2 - pbox->x1), | |
447 | (pbox->y2 - pbox->y1), pGC->alu, pPriv->pm); | |
448 | pbox++; | |
449 | } | |
450 | ||
451 | fbFinishAccess(pSrcDrawable); | |
452 | fbFinishAccess(pDstDrawable); | |
453 | } | |
454 | ||
455 | PixmapPtr | |
456 | fb24_32ReformatTile(PixmapPtr pOldTile, int bitsPerPixel) | |
457 | { | |
458 | ScreenPtr pScreen = pOldTile->drawable.pScreen; | |
459 | PixmapPtr pNewTile; | |
460 | FbBits *old, *new; | |
461 | FbStride oldStride, newStride; | |
462 | int oldBpp, newBpp; | |
463 | fb24_32BltFunc blt; | |
464 | _X_UNUSED int oldXoff, oldYoff; | |
465 | _X_UNUSED int newXoff, newYoff; | |
466 | ||
467 | pNewTile = pScreen->CreatePixmap(pScreen, pOldTile->drawable.width, | |
468 | pOldTile->drawable.height, | |
469 | pOldTile->drawable.depth, | |
470 | pOldTile->usage_hint); | |
471 | if (!pNewTile) | |
472 | return 0; | |
473 | fbGetDrawable(&pOldTile->drawable, | |
474 | old, oldStride, oldBpp, oldXoff, oldYoff); | |
475 | fbGetDrawable(&pNewTile->drawable, | |
476 | new, newStride, newBpp, newXoff, newYoff); | |
477 | if (oldBpp == 24) | |
478 | blt = fb24_32BltUp; | |
479 | else | |
480 | blt = fb24_32BltDown; | |
481 | ||
482 | (*blt) ((CARD8 *) old, | |
483 | oldStride * sizeof(FbBits), | |
484 | 0, | |
485 | (CARD8 *) new, | |
486 | newStride * sizeof(FbBits), | |
487 | 0, | |
488 | pOldTile->drawable.width, | |
489 | pOldTile->drawable.height, GXcopy, FB_ALLONES); | |
490 | ||
491 | fbFinishAccess(&pOldTile->drawable); | |
492 | fbFinishAccess(&pNewTile->drawable); | |
493 | ||
494 | return pNewTile; | |
495 | } | |
496 | ||
497 | typedef struct { | |
498 | pointer pbits; | |
499 | int width; | |
500 | } miScreenInitParmsRec, *miScreenInitParmsPtr; | |
501 | ||
502 | Bool | |
503 | fb24_32CreateScreenResources(ScreenPtr pScreen) | |
504 | { | |
505 | miScreenInitParmsPtr pScrInitParms; | |
506 | int pitch; | |
507 | Bool retval; | |
508 | ||
509 | /* get the pitch before mi destroys it */ | |
510 | pScrInitParms = (miScreenInitParmsPtr) pScreen->devPrivate; | |
511 | pitch = BitmapBytePad(pScrInitParms->width * 24); | |
512 | ||
513 | if ((retval = miCreateScreenResources(pScreen))) { | |
514 | /* fix the screen pixmap */ | |
515 | PixmapPtr pPix = (PixmapPtr) pScreen->devPrivate; | |
516 | ||
517 | pPix->drawable.bitsPerPixel = 24; | |
518 | pPix->devKind = pitch; | |
519 | } | |
520 | ||
521 | return retval; | |
522 | } | |
523 | ||
524 | Bool | |
525 | fb24_32ModifyPixmapHeader(PixmapPtr pPixmap, | |
526 | int width, | |
527 | int height, | |
528 | int depth, | |
529 | int bitsPerPixel, int devKind, pointer pPixData) | |
530 | { | |
531 | int bpp, w; | |
532 | ||
533 | if (!pPixmap) | |
534 | return FALSE; | |
535 | bpp = bitsPerPixel; | |
536 | if (bpp <= 0) | |
537 | bpp = pPixmap->drawable.bitsPerPixel; | |
538 | if (bpp == 24) { | |
539 | if (devKind < 0) { | |
540 | w = width; | |
541 | if (w <= 0) | |
542 | w = pPixmap->drawable.width; | |
543 | devKind = BitmapBytePad(w * 24); | |
544 | } | |
545 | } | |
546 | return miModifyPixmapHeader(pPixmap, width, height, depth, bitsPerPixel, | |
547 | devKind, pPixData); | |
548 | } |