Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / dmx / dmxgcops.c
1 /*
2 * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina.
3 *
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation on the rights to use, copy, modify, merge,
10 * publish, distribute, sublicense, and/or sell copies of the Software,
11 * and to permit persons to whom the Software is furnished to do so,
12 * subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial
16 * portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
22 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
26 */
27
28 /*
29 * Authors:
30 * Kevin E. Martin <kem@redhat.com>
31 *
32 */
33
34 /** \file
35 * This file provides support for GC operations. */
36
37 #ifdef HAVE_DMX_CONFIG_H
38 #include <dmx-config.h>
39 #endif
40
41 #include "dmx.h"
42 #include "dmxsync.h"
43 #include "dmxgc.h"
44 #include "dmxgcops.h"
45 #include "dmxwindow.h"
46 #include "dmxpixmap.h"
47
48 #include "mi.h"
49 #include "gcstruct.h"
50 #include "pixmapstr.h"
51 #include "dixfontstr.h"
52
53 #ifdef PANORAMIX
54 #include "panoramiXsrv.h"
55 #endif
56
57 #define DMX_GCOPS_SET_DRAWABLE(_pDraw, _draw) \
58 do { \
59 if ((_pDraw)->type == DRAWABLE_WINDOW) { \
60 dmxWinPrivPtr pWinPriv = \
61 DMX_GET_WINDOW_PRIV((WindowPtr)(_pDraw)); \
62 (_draw) = (Drawable)pWinPriv->window; \
63 } else { \
64 dmxPixPrivPtr pPixPriv = \
65 DMX_GET_PIXMAP_PRIV((PixmapPtr)(_pDraw)); \
66 (_draw) = (Drawable)pPixPriv->pixmap; \
67 } \
68 } while (0)
69
70 #define DMX_GCOPS_OFFSCREEN(_pDraw) \
71 (!dmxScreens[(_pDraw)->pScreen->myNum].beDisplay || \
72 (dmxOffScreenOpt && \
73 (_pDraw)->type == DRAWABLE_WINDOW && \
74 (DMX_GET_WINDOW_PRIV((WindowPtr)(_pDraw))->offscreen || \
75 !DMX_GET_WINDOW_PRIV((WindowPtr)(_pDraw))->window)))
76
77 /** Fill spans -- this function should never be called. */
78 void
79 dmxFillSpans(DrawablePtr pDrawable, GCPtr pGC,
80 int nInit, DDXPointPtr pptInit, int *pwidthInit, int fSorted)
81 {
82 /* Error -- this should never happen! */
83 }
84
85 /** Set spans -- this function should never be called. */
86 void
87 dmxSetSpans(DrawablePtr pDrawable, GCPtr pGC,
88 char *psrc, DDXPointPtr ppt, int *pwidth, int nspans, int fSorted)
89 {
90 /* Error -- this should never happen! */
91 }
92
93 /** Transfer \a pBits image to back-end server associated with \a
94 * pDrawable's screen. If primitive subdivision optimization is
95 * enabled, then only transfer the sections of \a pBits that are
96 * visible (i.e., not-clipped) to the back-end server. */
97 void
98 dmxPutImage(DrawablePtr pDrawable, GCPtr pGC,
99 int depth, int x, int y, int w, int h,
100 int leftPad, int format, char *pBits)
101 {
102 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum];
103 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
104 XImage *img;
105
106 if (DMX_GCOPS_OFFSCREEN(pDrawable))
107 return;
108
109 img = XCreateImage(dmxScreen->beDisplay,
110 dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual,
111 depth, format, leftPad, pBits, w, h,
112 BitmapPad(dmxScreen->beDisplay),
113 (format == ZPixmap) ?
114 PixmapBytePad(w, depth) : BitmapBytePad(w + leftPad));
115
116 if (img) {
117 Drawable draw;
118
119 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
120
121 if (dmxSubdividePrimitives && pGC->pCompositeClip) {
122 RegionPtr pSubImages;
123 RegionPtr pClip;
124 BoxRec box;
125 BoxPtr pBox;
126 int nBox;
127
128 box.x1 = x;
129 box.y1 = y;
130 box.x2 = x + w;
131 box.y2 = y + h;
132 pSubImages = RegionCreate(&box, 1);
133
134 pClip = RegionCreate(NullBox, 1);
135 RegionCopy(pClip, pGC->pCompositeClip);
136 RegionTranslate(pClip, -pDrawable->x, -pDrawable->y);
137 RegionIntersect(pSubImages, pSubImages, pClip);
138
139 nBox = RegionNumRects(pSubImages);
140 pBox = RegionRects(pSubImages);
141
142 while (nBox--) {
143 XPutImage(dmxScreen->beDisplay, draw, pGCPriv->gc, img,
144 pBox->x1 - box.x1,
145 pBox->y1 - box.y1,
146 pBox->x1,
147 pBox->y1, pBox->x2 - pBox->x1, pBox->y2 - pBox->y1);
148 pBox++;
149 }
150 RegionDestroy(pClip);
151 RegionDestroy(pSubImages);
152 }
153 else {
154 XPutImage(dmxScreen->beDisplay, draw, pGCPriv->gc,
155 img, 0, 0, x, y, w, h);
156 }
157 XFree(img); /* Use XFree instead of XDestroyImage
158 * because pBits is passed in from the
159 * caller. */
160
161 dmxSync(dmxScreen, FALSE);
162 }
163 else {
164 /* Error -- this should not happen! */
165 }
166 }
167
168 /** Copy area from \a pSrc drawable to \a pDst drawable on the back-end
169 * server associated with \a pSrc drawable's screen. If the offscreen
170 * optimization is enabled, only copy when both \a pSrc and \a pDst are
171 * at least partially visible. */
172 RegionPtr
173 dmxCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
174 int srcx, int srcy, int w, int h, int dstx, int dsty)
175 {
176 DMXScreenInfo *dmxScreen = &dmxScreens[pSrc->pScreen->myNum];
177 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
178 Drawable srcDraw, dstDraw;
179
180 if (DMX_GCOPS_OFFSCREEN(pSrc) || DMX_GCOPS_OFFSCREEN(pDst))
181 return miHandleExposures(pSrc, pDst, pGC, srcx, srcy, w, h,
182 dstx, dsty, 0L);
183
184 DMX_GCOPS_SET_DRAWABLE(pSrc, srcDraw);
185 DMX_GCOPS_SET_DRAWABLE(pDst, dstDraw);
186
187 XCopyArea(dmxScreen->beDisplay, srcDraw, dstDraw, pGCPriv->gc,
188 srcx, srcy, w, h, dstx, dsty);
189 dmxSync(dmxScreen, FALSE);
190
191 return miHandleExposures(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, 0L);
192 }
193
194 /** Copy plane number \a bitPlane from \a pSrc drawable to \a pDst
195 * drawable on the back-end server associated with \a pSrc drawable's
196 * screen. If the offscreen optimization is enabled, only copy when
197 * both \a pSrc and \a pDst are at least partially visible. */
198 RegionPtr
199 dmxCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
200 int srcx, int srcy, int width, int height,
201 int dstx, int dsty, unsigned long bitPlane)
202 {
203 DMXScreenInfo *dmxScreen = &dmxScreens[pSrc->pScreen->myNum];
204 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
205 Drawable srcDraw, dstDraw;
206
207 if (DMX_GCOPS_OFFSCREEN(pSrc) || DMX_GCOPS_OFFSCREEN(pDst))
208 return miHandleExposures(pSrc, pDst, pGC, srcx, srcy, width, height,
209 dstx, dsty, bitPlane);
210
211 DMX_GCOPS_SET_DRAWABLE(pSrc, srcDraw);
212 DMX_GCOPS_SET_DRAWABLE(pDst, dstDraw);
213
214 XCopyPlane(dmxScreen->beDisplay, srcDraw, dstDraw, pGCPriv->gc,
215 srcx, srcy, width, height, dstx, dsty, bitPlane);
216 dmxSync(dmxScreen, FALSE);
217
218 return miHandleExposures(pSrc, pDst, pGC, srcx, srcy, width, height,
219 dstx, dsty, bitPlane);
220 }
221
222 /** Render list of points, \a pptInit in \a pDrawable on the back-end
223 * server associated with \a pDrawable's screen. If the offscreen
224 * optimization is enabled, only draw when \a pDrawable is at least
225 * partially visible. */
226 void
227 dmxPolyPoint(DrawablePtr pDrawable, GCPtr pGC,
228 int mode, int npt, DDXPointPtr pptInit)
229 {
230 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum];
231 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
232 Drawable draw;
233
234 if (DMX_GCOPS_OFFSCREEN(pDrawable))
235 return;
236
237 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
238
239 XDrawPoints(dmxScreen->beDisplay, draw, pGCPriv->gc,
240 (XPoint *) pptInit, npt, mode);
241 dmxSync(dmxScreen, FALSE);
242 }
243
244 /** Render list of connected lines, \a pptInit in \a pDrawable on the
245 * back-end server associated with \a pDrawable's screen. If the
246 * offscreen optimization is enabled, only draw when \a pDrawable is at
247 * least partially visible. */
248 void
249 dmxPolylines(DrawablePtr pDrawable, GCPtr pGC,
250 int mode, int npt, DDXPointPtr pptInit)
251 {
252 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum];
253 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
254 Drawable draw;
255
256 if (DMX_GCOPS_OFFSCREEN(pDrawable))
257 return;
258
259 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
260
261 XDrawLines(dmxScreen->beDisplay, draw, pGCPriv->gc,
262 (XPoint *) pptInit, npt, mode);
263 dmxSync(dmxScreen, FALSE);
264 }
265
266 /** Render list of disjoint segments, \a pSegs in \a pDrawable on the
267 * back-end server associated with \a pDrawable's screen. If the
268 * offscreen optimization is enabled, only draw when \a pDrawable is at
269 * least partially visible. */
270 void
271 dmxPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment * pSegs)
272 {
273 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum];
274 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
275 Drawable draw;
276
277 if (DMX_GCOPS_OFFSCREEN(pDrawable))
278 return;
279
280 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
281
282 XDrawSegments(dmxScreen->beDisplay, draw, pGCPriv->gc,
283 (XSegment *) pSegs, nseg);
284 dmxSync(dmxScreen, FALSE);
285 }
286
287 /** Render list of rectangle outlines, \a pRects in \a pDrawable on the
288 * back-end server associated with \a pDrawable's screen. If the
289 * offscreen optimization is enabled, only draw when \a pDrawable is at
290 * least partially visible. */
291 void
292 dmxPolyRectangle(DrawablePtr pDrawable, GCPtr pGC,
293 int nrects, xRectangle *pRects)
294 {
295 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum];
296 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
297 Drawable draw;
298
299 if (DMX_GCOPS_OFFSCREEN(pDrawable))
300 return;
301
302 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
303
304 XDrawRectangles(dmxScreen->beDisplay, draw, pGCPriv->gc,
305 (XRectangle *) pRects, nrects);
306
307 dmxSync(dmxScreen, FALSE);
308 }
309
310 /** Render list of arc outlines, \a parcs in \a pDrawable on the
311 * back-end server associated with \a pDrawable's screen. If the
312 * offscreen optimization is enabled, only draw when \a pDrawable is at
313 * least partially visible. */
314 void
315 dmxPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc * parcs)
316 {
317 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum];
318 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
319 Drawable draw;
320
321 if (DMX_GCOPS_OFFSCREEN(pDrawable))
322 return;
323
324 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
325
326 XDrawArcs(dmxScreen->beDisplay, draw, pGCPriv->gc, (XArc *) parcs, narcs);
327 dmxSync(dmxScreen, FALSE);
328 }
329
330 /** Render a filled polygons in \a pDrawable on the back-end server
331 * associated with \a pDrawable's screen. If the offscreen
332 * optimization is enabled, only draw when \a pDrawable is at least
333 * partially visible. */
334 void
335 dmxFillPolygon(DrawablePtr pDrawable, GCPtr pGC,
336 int shape, int mode, int count, DDXPointPtr pPts)
337 {
338 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum];
339 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
340 Drawable draw;
341
342 if (DMX_GCOPS_OFFSCREEN(pDrawable))
343 return;
344
345 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
346
347 XFillPolygon(dmxScreen->beDisplay, draw, pGCPriv->gc,
348 (XPoint *) pPts, count, shape, mode);
349 dmxSync(dmxScreen, FALSE);
350 }
351
352 /** Render list of filled rectangles, \a prectInit in \a pDrawable on
353 * the back-end server associated with \a pDrawable's screen. If the
354 * offscreen optimization is enabled, only draw when \a pDrawable is at
355 * least partially visible. */
356 void
357 dmxPolyFillRect(DrawablePtr pDrawable, GCPtr pGC,
358 int nrectFill, xRectangle *prectInit)
359 {
360 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum];
361 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
362 Drawable draw;
363
364 if (DMX_GCOPS_OFFSCREEN(pDrawable))
365 return;
366
367 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
368
369 XFillRectangles(dmxScreen->beDisplay, draw, pGCPriv->gc,
370 (XRectangle *) prectInit, nrectFill);
371 dmxSync(dmxScreen, FALSE);
372 }
373
374 /** Render list of filled arcs, \a parcs in \a pDrawable on the back-end
375 * server associated with \a pDrawable's screen. If the offscreen
376 * optimization is enabled, only draw when \a pDrawable is at least
377 * partially visible. */
378 void
379 dmxPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc * parcs)
380 {
381 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum];
382 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
383 Drawable draw;
384
385 if (DMX_GCOPS_OFFSCREEN(pDrawable))
386 return;
387
388 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
389
390 XFillArcs(dmxScreen->beDisplay, draw, pGCPriv->gc, (XArc *) parcs, narcs);
391 dmxSync(dmxScreen, FALSE);
392 }
393
394 /** Render string of 8-bit \a chars (foreground only) in \a pDrawable on
395 * the back-end server associated with \a pDrawable's screen. If the
396 * offscreen optimization is enabled, only draw when \a pDrawable is at
397 * least partially visible. */
398 int
399 dmxPolyText8(DrawablePtr pDrawable, GCPtr pGC,
400 int x, int y, int count, char *chars)
401 {
402 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum];
403 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
404 unsigned long n, i;
405 int w;
406 CharInfoPtr charinfo[255];
407 Drawable draw;
408
409 GetGlyphs(pGC->font, (unsigned long) count, (unsigned char *) chars,
410 Linear8Bit, &n, charinfo);
411
412 /* Calculate text width */
413 w = 0;
414 for (i = 0; i < n; i++)
415 w += charinfo[i]->metrics.characterWidth;
416
417 if (n != 0 && !DMX_GCOPS_OFFSCREEN(pDrawable)) {
418 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
419
420 XDrawString(dmxScreen->beDisplay, draw, pGCPriv->gc,
421 x, y, chars, count);
422 dmxSync(dmxScreen, FALSE);
423 }
424
425 return x + w;
426 }
427
428 /** Render string of 16-bit \a chars (foreground only) in \a pDrawable
429 * on the back-end server associated with \a pDrawable's screen. If
430 * the offscreen optimization is enabled, only draw when \a pDrawable
431 * is at least partially visible. */
432 int
433 dmxPolyText16(DrawablePtr pDrawable, GCPtr pGC,
434 int x, int y, int count, unsigned short *chars)
435 {
436 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum];
437 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
438 unsigned long n, i;
439 int w;
440 CharInfoPtr charinfo[255];
441 Drawable draw;
442
443 GetGlyphs(pGC->font, (unsigned long) count, (unsigned char *) chars,
444 (FONTLASTROW(pGC->font) == 0) ? Linear16Bit : TwoD16Bit,
445 &n, charinfo);
446
447 /* Calculate text width */
448 w = 0;
449 for (i = 0; i < n; i++)
450 w += charinfo[i]->metrics.characterWidth;
451
452 if (n != 0 && !DMX_GCOPS_OFFSCREEN(pDrawable)) {
453 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
454
455 XDrawString16(dmxScreen->beDisplay, draw, pGCPriv->gc,
456 x, y, (XChar2b *) chars, count);
457 dmxSync(dmxScreen, FALSE);
458 }
459
460 return x + w;
461 }
462
463 /** Render string of 8-bit \a chars (both foreground and background) in
464 * \a pDrawable on the back-end server associated with \a pDrawable's
465 * screen. If the offscreen optimization is enabled, only draw when \a
466 * pDrawable is at least partially visible. */
467 void
468 dmxImageText8(DrawablePtr pDrawable, GCPtr pGC,
469 int x, int y, int count, char *chars)
470 {
471 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum];
472 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
473 Drawable draw;
474
475 if (DMX_GCOPS_OFFSCREEN(pDrawable))
476 return;
477
478 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
479
480 XDrawImageString(dmxScreen->beDisplay, draw, pGCPriv->gc,
481 x, y, chars, count);
482 dmxSync(dmxScreen, FALSE);
483 }
484
485 /** Render string of 16-bit \a chars (both foreground and background) in
486 * \a pDrawable on the back-end server associated with \a pDrawable's
487 * screen. If the offscreen optimization is enabled, only draw when \a
488 * pDrawable is at least partially visible. */
489 void
490 dmxImageText16(DrawablePtr pDrawable, GCPtr pGC,
491 int x, int y, int count, unsigned short *chars)
492 {
493 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum];
494 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
495 Drawable draw;
496
497 if (DMX_GCOPS_OFFSCREEN(pDrawable))
498 return;
499
500 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
501
502 XDrawImageString16(dmxScreen->beDisplay, draw, pGCPriv->gc,
503 x, y, (XChar2b *) chars, count);
504 dmxSync(dmxScreen, FALSE);
505 }
506
507 /** Image Glyph Blt -- this function should never be called. */
508 void
509 dmxImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
510 int x, int y, unsigned int nglyph,
511 CharInfoPtr * ppci, pointer pglyphBase)
512 {
513 /* Error -- this should never happen! */
514 }
515
516 /** Poly Glyph Blt -- this function should never be called. */
517 void
518 dmxPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
519 int x, int y, unsigned int nglyph,
520 CharInfoPtr * ppci, pointer pglyphBase)
521 {
522 /* Error -- this should never happen! */
523 }
524
525 /** Push Pixels -- this function should never be called. */
526 void
527 dmxPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDst,
528 int w, int h, int x, int y)
529 {
530 /* Error -- this should never happen! */
531 }
532
533 /**********************************************************************
534 * Miscellaneous drawing commands
535 */
536
537 /** When Xinerama is active, the client pixmaps are always obtained from
538 * screen 0. When screen 0 is detached, the pixmaps must be obtained
539 * from any other screen that is not detached. Usually, this is screen
540 * 1. */
541 static DMXScreenInfo *
542 dmxFindAlternatePixmap(DrawablePtr pDrawable, XID *draw)
543 {
544 #ifdef PANORAMIX
545 PanoramiXRes *pXinPix;
546 int i;
547 DMXScreenInfo *dmxScreen;
548
549 if (noPanoramiXExtension)
550 return NULL;
551 if (pDrawable->type != DRAWABLE_PIXMAP)
552 return NULL;
553
554 if (Success != dixLookupResourceByType((pointer *) &pXinPix,
555 pDrawable->id, XRT_PIXMAP,
556 NullClient, DixUnknownAccess))
557 return NULL;
558
559 FOR_NSCREENS_FORWARD_SKIP(i) {
560 dmxScreen = &dmxScreens[i];
561 if (dmxScreen->beDisplay) {
562 PixmapPtr pSrc;
563 dmxPixPrivPtr pSrcPriv;
564
565 dixLookupResourceByType((pointer *) &pSrc, pXinPix->info[i].id,
566 RT_PIXMAP, NullClient, DixUnknownAccess);
567 pSrcPriv = DMX_GET_PIXMAP_PRIV(pSrc);
568 if (pSrcPriv->pixmap) {
569 *draw = pSrcPriv->pixmap;
570 return dmxScreen;
571 }
572 }
573 }
574 #endif
575 return NULL;
576 }
577
578 /** Get an image from the back-end server associated with \a pDrawable's
579 * screen. If \a pDrawable is a window, it must be viewable to get an
580 * image from it. If it is not viewable, then get the image from the
581 * first ancestor of \a pDrawable that is viewable. If no viewable
582 * ancestor is found, then simply return without getting an image. */
583 void
584 dmxGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h,
585 unsigned int format, unsigned long planeMask, char *pdstLine)
586 {
587 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum];
588 XImage *img;
589 Drawable draw;
590
591 /* Cannot get image from unviewable window */
592 if (pDrawable->type == DRAWABLE_WINDOW) {
593 WindowPtr pWindow = (WindowPtr) pDrawable;
594
595 if (!pWindow->viewable) {
596 while (!pWindow->viewable && pWindow->parent) {
597 sx += pWindow->origin.x - wBorderWidth(pWindow);
598 sx += pWindow->origin.y - wBorderWidth(pWindow);
599 pWindow = pWindow->parent;
600 }
601 if (!pWindow->viewable) {
602 return;
603 }
604 }
605 DMX_GCOPS_SET_DRAWABLE(&pWindow->drawable, draw);
606 if (DMX_GCOPS_OFFSCREEN(&pWindow->drawable))
607 return;
608 }
609 else {
610 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
611 if (DMX_GCOPS_OFFSCREEN(pDrawable)) {
612 /* Try to find the pixmap on a non-detached Xinerama screen */
613 dmxScreen = dmxFindAlternatePixmap(pDrawable, &draw);
614 if (!dmxScreen)
615 return;
616 }
617 }
618
619 img = XGetImage(dmxScreen->beDisplay, draw,
620 sx, sy, w, h, planeMask, format);
621 if (img) {
622 int len = img->bytes_per_line * img->height;
623
624 memmove(pdstLine, img->data, len);
625 XDestroyImage(img);
626 }
627
628 dmxSync(dmxScreen, FALSE);
629 }
630
631 /** Get Spans -- this function should never be called. */
632 void
633 dmxGetSpans(DrawablePtr pDrawable, int wMax,
634 DDXPointPtr ppt, int *pwidth, int nspans, char *pdstStart)
635 {
636 /* Error -- this should never happen! */
637 }