First import
[xorg_rtime.git] / xorg-server-1.4 / hw / dmx / dmxgcops.c
blobeaabf16ddb7fde491ed8d9cfc9587afcb1bae3ad
1 /*
2 * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina.
4 * All Rights Reserved.
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:
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.
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.
29 * Authors:
30 * Kevin E. Martin <kem@redhat.com>
34 /** \file
35 * This file provides support for GC operations. */
37 #ifdef HAVE_DMX_CONFIG_H
38 #include <dmx-config.h>
39 #endif
41 #include "dmx.h"
42 #include "dmxsync.h"
43 #include "dmxgc.h"
44 #include "dmxgcops.h"
45 #include "dmxwindow.h"
46 #include "dmxpixmap.h"
48 #include "mi.h"
49 #include "gcstruct.h"
50 #include "pixmapstr.h"
51 #include "dixfontstr.h"
53 #include "panoramiXsrv.h"
55 #define DMX_GCOPS_SET_DRAWABLE(_pDraw, _draw) \
56 do { \
57 if ((_pDraw)->type == DRAWABLE_WINDOW) { \
58 dmxWinPrivPtr pWinPriv = \
59 DMX_GET_WINDOW_PRIV((WindowPtr)(_pDraw)); \
60 (_draw) = (Drawable)pWinPriv->window; \
61 } else { \
62 dmxPixPrivPtr pPixPriv = \
63 DMX_GET_PIXMAP_PRIV((PixmapPtr)(_pDraw)); \
64 (_draw) = (Drawable)pPixPriv->pixmap; \
65 } \
66 } while (0)
68 #define DMX_GCOPS_OFFSCREEN(_pDraw) \
69 (!dmxScreens[(_pDraw)->pScreen->myNum].beDisplay || \
70 (dmxOffScreenOpt && \
71 (_pDraw)->type == DRAWABLE_WINDOW && \
72 (DMX_GET_WINDOW_PRIV((WindowPtr)(_pDraw))->offscreen || \
73 !DMX_GET_WINDOW_PRIV((WindowPtr)(_pDraw))->window)))
75 /** Fill spans -- this function should never be called. */
76 void dmxFillSpans(DrawablePtr pDrawable, GCPtr pGC,
77 int nInit, DDXPointPtr pptInit, int *pwidthInit,
78 int fSorted)
80 /* Error -- this should never happen! */
83 /** Set spans -- this function should never be called. */
84 void dmxSetSpans(DrawablePtr pDrawable, GCPtr pGC,
85 char *psrc, DDXPointPtr ppt, int *pwidth, int nspans,
86 int fSorted)
88 /* Error -- this should never happen! */
91 /** Transfer \a pBits image to back-end server associated with \a
92 * pDrawable's screen. If primitive subdivision optimization is
93 * enabled, then only transfer the sections of \a pBits that are
94 * visible (i.e., not-clipped) to the back-end server. */
95 void dmxPutImage(DrawablePtr pDrawable, GCPtr pGC,
96 int depth, int x, int y, int w, int h,
97 int leftPad, int format, char *pBits)
99 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum];
100 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
101 XImage *img;
103 if (DMX_GCOPS_OFFSCREEN(pDrawable)) return;
105 img = XCreateImage(dmxScreen->beDisplay,
106 dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual,
107 depth, format, leftPad, pBits, w, h,
108 BitmapPad(dmxScreen->beDisplay),
109 (format == ZPixmap) ?
110 PixmapBytePad(w, depth) : BitmapBytePad(w+leftPad));
112 if (img) {
113 Drawable draw;
115 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
117 if (dmxSubdividePrimitives && pGC->pCompositeClip) {
118 RegionPtr pSubImages;
119 RegionPtr pClip;
120 BoxRec box;
121 BoxPtr pBox;
122 int nBox;
124 box.x1 = x;
125 box.y1 = y;
126 box.x2 = x + w;
127 box.y2 = y + h;
128 pSubImages = REGION_CREATE(pGC->pScreen, &box, 1);
130 pClip = REGION_CREATE(pGC->pScreen, NullBox, 1);
131 REGION_COPY(pGC->pScreen, pClip, pGC->pCompositeClip);
132 REGION_TRANSLATE(pGC->pScreen, pClip,
133 -pDrawable->x, -pDrawable->y);
134 REGION_INTERSECT(pGC->pScreen, pSubImages, pSubImages, pClip);
136 nBox = REGION_NUM_RECTS(pSubImages);
137 pBox = REGION_RECTS(pSubImages);
139 while (nBox--) {
140 XPutImage(dmxScreen->beDisplay, draw, pGCPriv->gc, img,
141 pBox->x1 - box.x1,
142 pBox->y1 - box.y1,
143 pBox->x1,
144 pBox->y1,
145 pBox->x2 - pBox->x1,
146 pBox->y2 - pBox->y1);
147 pBox++;
149 REGION_DESTROY(pGC->pScreen, pClip);
150 REGION_DESTROY(pGC->pScreen, pSubImages);
151 } else {
152 XPutImage(dmxScreen->beDisplay, draw, pGCPriv->gc,
153 img, 0, 0, x, y, w, h);
155 XFree(img); /* Use XFree instead of XDestroyImage
156 * because pBits is passed in from the
157 * caller. */
159 dmxSync(dmxScreen, FALSE);
160 } else {
161 /* Error -- this should not happen! */
165 /** Copy area from \a pSrc drawable to \a pDst drawable on the back-end
166 * server associated with \a pSrc drawable's screen. If the offscreen
167 * optimization is enabled, only copy when both \a pSrc and \a pDst are
168 * at least partially visible. */
169 RegionPtr dmxCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
170 int srcx, int srcy, int w, int h, int dstx, int dsty)
172 DMXScreenInfo *dmxScreen = &dmxScreens[pSrc->pScreen->myNum];
173 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
174 Drawable srcDraw, dstDraw;
176 if (DMX_GCOPS_OFFSCREEN(pSrc) || DMX_GCOPS_OFFSCREEN(pDst))
177 return miHandleExposures(pSrc, pDst, pGC, srcx, srcy, w, h,
178 dstx, dsty, 0L);
180 DMX_GCOPS_SET_DRAWABLE(pSrc, srcDraw);
181 DMX_GCOPS_SET_DRAWABLE(pDst, dstDraw);
183 XCopyArea(dmxScreen->beDisplay, srcDraw, dstDraw, pGCPriv->gc,
184 srcx, srcy, w, h, dstx, dsty);
185 dmxSync(dmxScreen, FALSE);
187 return miHandleExposures(pSrc, pDst, pGC, srcx, srcy, w, h,
188 dstx, dsty, 0L);
191 /** Copy plane number \a bitPlane from \a pSrc drawable to \a pDst
192 * drawable on the back-end server associated with \a pSrc drawable's
193 * screen. If the offscreen optimization is enabled, only copy when
194 * both \a pSrc and \a pDst are at least partially visible. */
195 RegionPtr dmxCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
196 int srcx, int srcy, int width, int height,
197 int dstx, int dsty, unsigned long bitPlane)
199 DMXScreenInfo *dmxScreen = &dmxScreens[pSrc->pScreen->myNum];
200 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
201 Drawable srcDraw, dstDraw;
203 if (DMX_GCOPS_OFFSCREEN(pSrc) || DMX_GCOPS_OFFSCREEN(pDst))
204 return miHandleExposures(pSrc, pDst, pGC, srcx, srcy, width, height,
205 dstx, dsty, bitPlane);
207 DMX_GCOPS_SET_DRAWABLE(pSrc, srcDraw);
208 DMX_GCOPS_SET_DRAWABLE(pDst, dstDraw);
210 XCopyPlane(dmxScreen->beDisplay, srcDraw, dstDraw, pGCPriv->gc,
211 srcx, srcy, width, height, dstx, dsty, bitPlane);
212 dmxSync(dmxScreen, FALSE);
214 return miHandleExposures(pSrc, pDst, pGC, srcx, srcy, width, height,
215 dstx, dsty, bitPlane);
218 /** Render list of points, \a pptInit in \a pDrawable on the back-end
219 * server associated with \a pDrawable's screen. If the offscreen
220 * optimization is enabled, only draw when \a pDrawable is at least
221 * partially visible. */
222 void dmxPolyPoint(DrawablePtr pDrawable, GCPtr pGC,
223 int mode, int npt, DDXPointPtr pptInit)
225 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum];
226 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
227 Drawable draw;
229 if (DMX_GCOPS_OFFSCREEN(pDrawable)) return;
231 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
233 XDrawPoints(dmxScreen->beDisplay, draw, pGCPriv->gc,
234 (XPoint *)pptInit, npt, mode);
235 dmxSync(dmxScreen, FALSE);
238 /** Render list of connected lines, \a pptInit in \a pDrawable on the
239 * back-end server associated with \a pDrawable's screen. If the
240 * offscreen optimization is enabled, only draw when \a pDrawable is at
241 * least partially visible. */
242 void dmxPolylines(DrawablePtr pDrawable, GCPtr pGC,
243 int mode, int npt, DDXPointPtr pptInit)
245 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum];
246 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
247 Drawable draw;
249 if (DMX_GCOPS_OFFSCREEN(pDrawable)) return;
251 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
253 XDrawLines(dmxScreen->beDisplay, draw, pGCPriv->gc,
254 (XPoint *)pptInit, npt, mode);
255 dmxSync(dmxScreen, FALSE);
258 /** Render list of disjoint segments, \a pSegs in \a pDrawable on the
259 * back-end server associated with \a pDrawable's screen. If the
260 * offscreen optimization is enabled, only draw when \a pDrawable is at
261 * least partially visible. */
262 void dmxPolySegment(DrawablePtr pDrawable, GCPtr pGC,
263 int nseg, xSegment *pSegs)
265 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum];
266 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
267 Drawable draw;
269 if (DMX_GCOPS_OFFSCREEN(pDrawable)) return;
271 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
273 XDrawSegments(dmxScreen->beDisplay, draw, pGCPriv->gc,
274 (XSegment *)pSegs, nseg);
275 dmxSync(dmxScreen, FALSE);
278 /** Render list of rectangle outlines, \a pRects in \a pDrawable on the
279 * back-end server associated with \a pDrawable's screen. If the
280 * offscreen optimization is enabled, only draw when \a pDrawable is at
281 * least partially visible. */
282 void dmxPolyRectangle(DrawablePtr pDrawable, GCPtr pGC,
283 int nrects, xRectangle *pRects)
285 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum];
286 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
287 Drawable draw;
289 if (DMX_GCOPS_OFFSCREEN(pDrawable)) return;
291 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
293 XDrawRectangles(dmxScreen->beDisplay, draw, pGCPriv->gc,
294 (XRectangle *)pRects, nrects);
296 dmxSync(dmxScreen, FALSE);
299 /** Render list of arc outlines, \a parcs in \a pDrawable on the
300 * back-end server associated with \a pDrawable's screen. If the
301 * offscreen optimization is enabled, only draw when \a pDrawable is at
302 * least partially visible. */
303 void dmxPolyArc(DrawablePtr pDrawable, GCPtr pGC,
304 int narcs, xArc *parcs)
306 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum];
307 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
308 Drawable draw;
310 if (DMX_GCOPS_OFFSCREEN(pDrawable)) return;
312 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
314 XDrawArcs(dmxScreen->beDisplay, draw, pGCPriv->gc,
315 (XArc *)parcs, narcs);
316 dmxSync(dmxScreen, FALSE);
319 /** Render a filled polygons in \a pDrawable on the back-end server
320 * associated with \a pDrawable's screen. If the offscreen
321 * optimization is enabled, only draw when \a pDrawable is at least
322 * partially visible. */
323 void dmxFillPolygon(DrawablePtr pDrawable, GCPtr pGC,
324 int shape, int mode, int count, DDXPointPtr pPts)
326 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum];
327 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
328 Drawable draw;
330 if (DMX_GCOPS_OFFSCREEN(pDrawable)) return;
332 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
334 XFillPolygon(dmxScreen->beDisplay, draw, pGCPriv->gc,
335 (XPoint *)pPts, count, shape, mode);
336 dmxSync(dmxScreen, FALSE);
339 /** Render list of filled rectangles, \a prectInit in \a pDrawable on
340 * the back-end server associated with \a pDrawable's screen. If the
341 * offscreen optimization is enabled, only draw when \a pDrawable is at
342 * least partially visible. */
343 void dmxPolyFillRect(DrawablePtr pDrawable, GCPtr pGC,
344 int nrectFill, xRectangle *prectInit)
346 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum];
347 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
348 Drawable draw;
350 if (DMX_GCOPS_OFFSCREEN(pDrawable)) return;
352 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
354 XFillRectangles(dmxScreen->beDisplay, draw, pGCPriv->gc,
355 (XRectangle *)prectInit, nrectFill);
356 dmxSync(dmxScreen, FALSE);
359 /** Render list of filled arcs, \a parcs in \a pDrawable on the back-end
360 * server associated with \a pDrawable's screen. If the offscreen
361 * optimization is enabled, only draw when \a pDrawable is at least
362 * partially visible. */
363 void dmxPolyFillArc(DrawablePtr pDrawable, GCPtr pGC,
364 int narcs, xArc *parcs)
366 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum];
367 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
368 Drawable draw;
370 if (DMX_GCOPS_OFFSCREEN(pDrawable)) return;
372 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
374 XFillArcs(dmxScreen->beDisplay, draw, pGCPriv->gc,
375 (XArc *)parcs, narcs);
376 dmxSync(dmxScreen, FALSE);
379 /** Render string of 8-bit \a chars (foreground only) in \a pDrawable on
380 * the back-end server associated with \a pDrawable's screen. If the
381 * offscreen optimization is enabled, only draw when \a pDrawable is at
382 * least partially visible. */
383 int dmxPolyText8(DrawablePtr pDrawable, GCPtr pGC,
384 int x, int y, int count, char *chars)
386 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum];
387 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
388 unsigned long n, i;
389 int w;
390 CharInfoPtr charinfo[255];
391 Drawable draw;
393 GetGlyphs(pGC->font, (unsigned long)count, (unsigned char *)chars,
394 Linear8Bit, &n, charinfo);
396 /* Calculate text width */
397 w = 0;
398 for (i = 0; i < n; i++) w += charinfo[i]->metrics.characterWidth;
400 if (n != 0 && !DMX_GCOPS_OFFSCREEN(pDrawable)) {
401 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
403 XDrawString(dmxScreen->beDisplay, draw, pGCPriv->gc,
404 x, y, chars, count);
405 dmxSync(dmxScreen, FALSE);
408 return x+w;
411 /** Render string of 16-bit \a chars (foreground only) in \a pDrawable
412 * on the back-end server associated with \a pDrawable's screen. If
413 * the offscreen optimization is enabled, only draw when \a pDrawable
414 * is at least partially visible. */
415 int dmxPolyText16(DrawablePtr pDrawable, GCPtr pGC,
416 int x, int y, int count, unsigned short *chars)
418 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum];
419 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
420 unsigned long n, i;
421 int w;
422 CharInfoPtr charinfo[255];
423 Drawable draw;
425 GetGlyphs(pGC->font, (unsigned long)count, (unsigned char *)chars,
426 (FONTLASTROW(pGC->font) == 0) ? Linear16Bit : TwoD16Bit,
427 &n, charinfo);
429 /* Calculate text width */
430 w = 0;
431 for (i = 0; i < n; i++) w += charinfo[i]->metrics.characterWidth;
433 if (n != 0 && !DMX_GCOPS_OFFSCREEN(pDrawable)) {
434 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
436 XDrawString16(dmxScreen->beDisplay, draw, pGCPriv->gc,
437 x, y, (XChar2b *)chars, count);
438 dmxSync(dmxScreen, FALSE);
441 return x+w;
444 /** Render string of 8-bit \a chars (both foreground and background) in
445 * \a pDrawable on the back-end server associated with \a pDrawable's
446 * screen. If the offscreen optimization is enabled, only draw when \a
447 * pDrawable is at least partially visible. */
448 void dmxImageText8(DrawablePtr pDrawable, GCPtr pGC,
449 int x, int y, int count, char *chars)
451 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum];
452 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
453 Drawable draw;
455 if (DMX_GCOPS_OFFSCREEN(pDrawable)) return;
457 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
459 XDrawImageString(dmxScreen->beDisplay, draw, pGCPriv->gc,
460 x, y, chars, count);
461 dmxSync(dmxScreen, FALSE);
464 /** Render string of 16-bit \a chars (both foreground and background) in
465 * \a pDrawable on the back-end server associated with \a pDrawable's
466 * screen. If the offscreen optimization is enabled, only draw when \a
467 * pDrawable is at least partially visible. */
468 void dmxImageText16(DrawablePtr pDrawable, GCPtr pGC,
469 int x, int y, int count, unsigned short *chars)
471 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum];
472 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
473 Drawable draw;
475 if (DMX_GCOPS_OFFSCREEN(pDrawable)) return;
477 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
479 XDrawImageString16(dmxScreen->beDisplay, draw, pGCPriv->gc,
480 x, y, (XChar2b *)chars, count);
481 dmxSync(dmxScreen, FALSE);
484 /** Image Glyph Blt -- this function should never be called. */
485 void dmxImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
486 int x, int y, unsigned int nglyph,
487 CharInfoPtr *ppci, pointer pglyphBase)
489 /* Error -- this should never happen! */
492 /** Poly Glyph Blt -- this function should never be called. */
493 void dmxPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
494 int x, int y, unsigned int nglyph,
495 CharInfoPtr *ppci, pointer pglyphBase)
497 /* Error -- this should never happen! */
500 /** Push Pixels -- this function should never be called. */
501 void dmxPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDst,
502 int w, int h, int x, int y)
504 /* Error -- this should never happen! */
507 /**********************************************************************
508 * Miscellaneous drawing commands
511 /** When Xinerama is active, the client pixmaps are always obtained from
512 * screen 0. When screen 0 is detached, the pixmaps must be obtained
513 * from any other screen that is not detached. Usually, this is screen
514 * 1. */
515 static DMXScreenInfo *dmxFindAlternatePixmap(DrawablePtr pDrawable, XID *draw)
517 #ifdef PANORAMIX
518 PanoramiXRes *pXinPix;
519 int i;
520 DMXScreenInfo *dmxScreen;
522 if (noPanoramiXExtension) return NULL;
523 if (pDrawable->type != DRAWABLE_PIXMAP) return NULL;
525 if (!(pXinPix = (PanoramiXRes *)LookupIDByType(pDrawable->id, XRT_PIXMAP)))
526 return NULL;
528 for (i = 1; i < PanoramiXNumScreens; i++) {
529 dmxScreen = &dmxScreens[i];
530 if (dmxScreen->beDisplay) {
531 PixmapPtr pSrc;
532 dmxPixPrivPtr pSrcPriv;
534 pSrc = (PixmapPtr)LookupIDByType(pXinPix->info[i].id,
535 RT_PIXMAP);
536 pSrcPriv = DMX_GET_PIXMAP_PRIV(pSrc);
537 if (pSrcPriv->pixmap) {
538 *draw = pSrcPriv->pixmap;
539 return dmxScreen;
543 #endif
544 return NULL;
547 /** Get an image from the back-end server associated with \a pDrawable's
548 * screen. If \a pDrawable is a window, it must be viewable to get an
549 * image from it. If it is not viewable, then get the image from the
550 * first ancestor of \a pDrawable that is viewable. If no viewable
551 * ancestor is found, then simply return without getting an image. */
552 void dmxGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h,
553 unsigned int format, unsigned long planeMask, char *pdstLine)
555 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum];
556 XImage *img;
557 Drawable draw;
559 /* Cannot get image from unviewable window */
560 if (pDrawable->type == DRAWABLE_WINDOW) {
561 WindowPtr pWindow = (WindowPtr)pDrawable;
562 if (!pWindow->viewable) {
563 while (!pWindow->viewable && pWindow->parent) {
564 sx += pWindow->origin.x - wBorderWidth(pWindow);
565 sx += pWindow->origin.y - wBorderWidth(pWindow);
566 pWindow = pWindow->parent;
568 if (!pWindow->viewable) {
569 return;
572 DMX_GCOPS_SET_DRAWABLE(&pWindow->drawable, draw);
573 if (DMX_GCOPS_OFFSCREEN(&pWindow->drawable))
574 return;
575 } else {
576 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
577 if (DMX_GCOPS_OFFSCREEN(pDrawable)) {
578 /* Try to find the pixmap on a non-detached Xinerama screen */
579 dmxScreen = dmxFindAlternatePixmap(pDrawable, &draw);
580 if (!dmxScreen) return;
584 img = XGetImage(dmxScreen->beDisplay, draw,
585 sx, sy, w, h, planeMask, format);
586 if (img) {
587 int len = img->bytes_per_line * img->height;
588 memmove(pdstLine, img->data, len);
589 XDestroyImage(img);
592 dmxSync(dmxScreen, FALSE);
595 /** Get Spans -- this function should never be called. */
596 void dmxGetSpans(DrawablePtr pDrawable, int wMax,
597 DDXPointPtr ppt, int *pwidth, int nspans,
598 char *pdstStart)
600 /* Error -- this should never happen! */