xref: /OK3568_Linux_fs/external/xserver/hw/dmx/dmxgcops.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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
dmxFillSpans(DrawablePtr pDrawable,GCPtr pGC,int nInit,DDXPointPtr pptInit,int * pwidthInit,int fSorted)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
dmxSetSpans(DrawablePtr pDrawable,GCPtr pGC,char * psrc,DDXPointPtr ppt,int * pwidth,int nspans,int fSorted)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
dmxPutImage(DrawablePtr pDrawable,GCPtr pGC,int depth,int x,int y,int w,int h,int leftPad,int format,char * pBits)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
dmxCopyArea(DrawablePtr pSrc,DrawablePtr pDst,GCPtr pGC,int srcx,int srcy,int w,int h,int dstx,int dsty)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);
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);
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
dmxCopyPlane(DrawablePtr pSrc,DrawablePtr pDst,GCPtr pGC,int srcx,int srcy,int width,int height,int dstx,int dsty,unsigned long bitPlane)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);
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);
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
dmxPolyPoint(DrawablePtr pDrawable,GCPtr pGC,int mode,int npt,DDXPointPtr pptInit)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
dmxPolylines(DrawablePtr pDrawable,GCPtr pGC,int mode,int npt,DDXPointPtr pptInit)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
dmxPolySegment(DrawablePtr pDrawable,GCPtr pGC,int nseg,xSegment * pSegs)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
dmxPolyRectangle(DrawablePtr pDrawable,GCPtr pGC,int nrects,xRectangle * pRects)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
dmxPolyArc(DrawablePtr pDrawable,GCPtr pGC,int narcs,xArc * parcs)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
dmxFillPolygon(DrawablePtr pDrawable,GCPtr pGC,int shape,int mode,int count,DDXPointPtr pPts)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
dmxPolyFillRect(DrawablePtr pDrawable,GCPtr pGC,int nrectFill,xRectangle * prectInit)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
dmxPolyFillArc(DrawablePtr pDrawable,GCPtr pGC,int narcs,xArc * parcs)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
dmxPolyText8(DrawablePtr pDrawable,GCPtr pGC,int x,int y,int count,char * chars)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
dmxPolyText16(DrawablePtr pDrawable,GCPtr pGC,int x,int y,int count,unsigned short * chars)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
dmxImageText8(DrawablePtr pDrawable,GCPtr pGC,int x,int y,int count,char * chars)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
dmxImageText16(DrawablePtr pDrawable,GCPtr pGC,int x,int y,int count,unsigned short * chars)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
dmxImageGlyphBlt(DrawablePtr pDrawable,GCPtr pGC,int x,int y,unsigned int nglyph,CharInfoPtr * ppci,void * pglyphBase)509 dmxImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
510                  int x, int y, unsigned int nglyph,
511                  CharInfoPtr * ppci, void *pglyphBase)
512 {
513     /* Error -- this should never happen! */
514 }
515 
516 /** Poly Glyph Blt -- this function should never be called. */
517 void
dmxPolyGlyphBlt(DrawablePtr pDrawable,GCPtr pGC,int x,int y,unsigned int nglyph,CharInfoPtr * ppci,void * pglyphBase)518 dmxPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
519                 int x, int y, unsigned int nglyph,
520                 CharInfoPtr * ppci, void *pglyphBase)
521 {
522     /* Error -- this should never happen! */
523 }
524 
525 /** Push Pixels -- this function should never be called. */
526 void
dmxPushPixels(GCPtr pGC,PixmapPtr pBitMap,DrawablePtr pDst,int w,int h,int x,int y)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 *
dmxFindAlternatePixmap(DrawablePtr pDrawable,XID * draw)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((void **) &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((void **) &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
dmxGetImage(DrawablePtr pDrawable,int sx,int sy,int w,int h,unsigned int format,unsigned long planeMask,char * pdstLine)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
dmxGetSpans(DrawablePtr pDrawable,int wMax,DDXPointPtr ppt,int * pwidth,int nspans,char * pdstStart)633 dmxGetSpans(DrawablePtr pDrawable, int wMax,
634             DDXPointPtr ppt, int *pwidth, int nspans, char *pdstStart)
635 {
636     /* Error -- this should never happen! */
637 }
638