home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / x / xibm.zip / mpel / mpelStip.c < prev    next >
C/C++ Source or Header  |  1991-07-23  |  20KB  |  736 lines

  1. /* */
  2. #include "X.h"
  3. #include "Xproto.h"
  4. #include "Xmd.h"
  5. #include "servermd.h"
  6. #include "pixmapstr.h"
  7. #include "gcstruct.h"
  8. #include "colormap.h"    /* needed by ppc */
  9. #include "regionstr.h"
  10. #include "mi.h"
  11. #include "OScompiler.h"
  12.  
  13. #include "ibmTrace.h"
  14.  
  15. #include "mpel.h"
  16. #include "mpelHdwr.h"
  17. #include "mpelFifo.h"
  18.  
  19. #include "ppcGCstr.h"
  20.  
  21. extern PixmapPtr ppcCopyPixmap();
  22. extern void mpelStippleWindowFS();
  23. static void mpelStippleWindowFS2();
  24. static void make4x4();
  25. static BoxPtr mpel4x4rgn();
  26.  
  27. #ifdef PROFILE
  28. #undef MPELSendData
  29. #define MPELSendData(n, d) data_glue(d, n)
  30. void data_glue(d, n)
  31. register void *d;
  32. register unsigned int n;
  33. {
  34.   mfData(d, n);
  35. }
  36. #endif
  37.  
  38. /* If the operation is GXcopy and the data can fit into a megapel adapter
  39.    command (i.e. size can fit in a signed short), then use the 4x4 Immediate
  40.    Blit w/ color expansion.  Otherwise, copy it to the stage area.
  41.  
  42.    In any case, to make things simple the source width is rounded to a
  43.    multiple of 32 bits (note: check performance hit) for storage in the
  44.    stage area.
  45.  
  46.    What would be nice is a way to lock the pages into physical memory and
  47.    pass that to the adapter...
  48. */
  49.  
  50. #ifdef TRACE_X
  51. static char *gxnames[] = {
  52.   "GXcopy",
  53.   "GXand",
  54.   "GXandReverse",
  55.   "GXcopy",
  56.   "GXandInverted",
  57.   "GXnoop",
  58.   "GXxor",
  59.   "GXor",
  60.   "GXnor",
  61.   "GXequiv",
  62.   "GXinvert",
  63.   "GXorReverse",
  64.   "GXcopyInverted",
  65.   "GXorInverted",
  66.   "GXnand",
  67.   "GXset",
  68. };
  69. #endif
  70.  
  71. void
  72. mpelStipple(pStipple, fg, alu, planes, x, y, w, h, xSrc, ySrc)
  73. PixmapPtr pStipple;
  74. unsigned long int fg;
  75. int alu;
  76. unsigned long int planes;
  77. int x, y, w, h;
  78. int xSrc, ySrc;
  79. {
  80.   mpelStippleFillRegion(0, pStipple, fg, alu, planes, x, y, w, h, xSrc, ySrc);
  81.   return;
  82. }
  83.  
  84. void mpelOpStipple(pStipple, fg, bg, alu, planes, x, y, w, h, xSrc, ySrc)
  85. PixmapPtr pStipple;
  86. unsigned long int fg, bg;
  87. int alu;
  88. unsigned long int planes;
  89. int x, y, w, h;
  90. int xSrc, ySrc;
  91. {
  92.   switch(alu)
  93.     {
  94.     case GXnoop:
  95.       break;
  96.     case GXclear:
  97.     case GXset:
  98.       mpelFillSolid(fg, alu, planes, x, y, w, h);
  99.       break;
  100.     case GXcopy:
  101.     case GXcopyInverted:
  102.       mpelFillSolid(bg, alu, planes, x, y, w, h);
  103.       mpelStippleFillRegion(0, pStipple, fg, alu, planes, x, y, w, h, xSrc, ySrc);
  104.       break;
  105.     default:
  106.       {
  107.     register int i, j;
  108.     register PixmapPtr pInvStipple = ppcCopyPixmap(pStipple);
  109.     register unsigned char *data = pInvStipple->devPrivate.ptr;
  110.  
  111.     for (i = pInvStipple->drawable.height ; i-- ;)
  112.       for (j = pInvStipple->devKind ; j-- ; data++)
  113.         *data = ~*data;
  114.  
  115.     mpelStippleFillRegion(0, pInvStipple, bg, alu, 
  116.                   planes, x, y, w, h, xSrc, ySrc);
  117.     mfbDestroyPixmap(pInvStipple);
  118.     mpelStippleFillRegion(0, pStipple, fg, alu,
  119.                   planes, x, y, w, h, xSrc, ySrc);
  120.       }
  121.     } 
  122. }
  123.  
  124. #ifdef TRACE_X
  125. static int trace_FS;
  126. #endif
  127.  
  128. void
  129. mpelOpStippleWindowFS(pDrawable, pGC, nSpans, ppts, pwidth, fSorted)
  130. DrawablePtr pDrawable;
  131. GC    *pGC;
  132. int    nSpans;
  133. DDXPointPtr ppts;
  134. int *pwidth;
  135. int fSorted;
  136. {
  137.   int alu;
  138.   unsigned long fg, bg;
  139.   ppcPrivGC *pPriv = (ppcPrivGC *) pGC->devPrivates[mfbGCPrivateIndex].ptr;
  140.  
  141.   fg = pPriv->colorRrop.fgPixel;
  142.   bg = pPriv->colorRrop.bgPixel;
  143.   alu = pPriv->colorRrop.alu;
  144.  
  145. #ifdef TRACE_X
  146.   if(ibmTrace && trace_FS)
  147.     ErrorF("mpelOpStippleWindowFS(%#x, %#x, %d, %#x, %#x) alu %s fg %d bg %d\n",
  148.        pDrawable, pGC, nSpans, ppts, pwidth, gxnames[alu], fg, bg);
  149. #endif
  150.  
  151.   switch(alu)
  152.     {
  153.     case GXnoop:
  154.       break;
  155.       /* The following are degenerate */
  156.     case GXclear:
  157.     case GXset:
  158.       ppcSolidWindowFS(pDrawable, pGC, nSpans, ppts, pwidth, fSorted);
  159.       break;
  160.       /* These are easy */
  161.     case GXcopy:
  162.     case GXcopyInverted:
  163.       /* Hack alert! */
  164.       pPriv->colorRrop.fgPixel = bg;
  165.       ppcSolidWindowFS(pDrawable, pGC, nSpans, ppts, pwidth, fSorted);
  166.       pPriv->colorRrop.fgPixel = fg;
  167.       mpelStippleWindowFS2(pGC->stipple, 0, 
  168.                pDrawable->x + pGC->patOrg.x,
  169.                pDrawable->y + pGC->patOrg.y, pPriv,
  170.                nSpans, ppts, pwidth, fSorted);
  171.       break;
  172.       /* These are hard */
  173.     default:
  174.       {
  175.     /* Create an inverted stipple for the background */
  176.     register int i, j;
  177.     register PixmapPtr pInvStipple = ppcCopyPixmap(pGC->stipple);
  178.     register unsigned char *data = pInvStipple->devPrivate.ptr;
  179.  
  180.     for (i = pInvStipple->drawable.height ; i-- ;)
  181.       for (j = pInvStipple->devKind ; j-- ; data++)
  182.         *data = ~*data;
  183.  
  184.     mpelStippleWindowFS2(pGC->stipple, pInvStipple,
  185.                  pDrawable->x + pGC->patOrg.x,
  186.                  pDrawable->y + pGC->patOrg.y, pPriv,
  187.                  nSpans, ppts, pwidth, fSorted);
  188.     mfbDestroyPixmap(pInvStipple);
  189.       }
  190.       break;
  191.     }
  192. }
  193.  
  194. void
  195. mpelStippleWindowFS(pDrawable, pGC, nSpans, ppts, pwidth, fSorted)
  196. DrawablePtr pDrawable;
  197. GC    *pGC;
  198. int    nSpans;
  199. DDXPointPtr ppts;
  200. int *pwidth;
  201. int fSorted;
  202. {
  203.   ppcPrivGC *pPriv = (ppcPrivGC *) pGC->devPrivates[mfbGCPrivateIndex].ptr;
  204. #ifdef TRACE_X
  205.   if(ibmTrace && trace_FS)
  206.     ErrorF("mpelStippleWindowFS(%#x, %#x, %d, %#x, %#x, %d)\n",
  207.        pDrawable, pGC, nSpans, ppts, pwidth, fSorted);
  208. #endif
  209.   mpelStippleWindowFS2(pGC->stipple, 0, pDrawable->x + pGC->patOrg.x,
  210.                pDrawable->y + pGC->patOrg.y, pPriv,
  211.                nSpans, ppts, pwidth, fSorted);
  212. }
  213.  
  214. static void
  215. mpelStippleWindowFS2(pStippleF, pStippleB, xSrc, ySrc,
  216.              pPriv, nSpans, ppts, pwidth, fSorted)
  217. PixmapPtr pStippleF, pStippleB;
  218. int nSpans, xSrc, ySrc;
  219. DDXPointPtr ppts;
  220. int *pwidth;
  221. int fSorted;
  222. ppcPrivGC *pPriv;
  223. {
  224.   RegionPtr Rfill, pClip = pPriv->pCompositeClip;
  225.   int alu;
  226.   unsigned long fg, bg;
  227.  
  228.   fg = pPriv->colorRrop.fgPixel;
  229.   bg = pPriv->colorRrop.bgPixel;
  230.   alu = pPriv->colorRrop.alu;
  231.  
  232.   if(alu == GXnoop || REGION_NUM_RECTS(pClip) == 0)
  233.     return;
  234.  
  235.   {
  236.     Bool overlap;
  237.     register int i;
  238.     register xRectangle *rects;
  239.     xRectangle *rectsInit = 
  240.       (xRectangle *)ALLOCATE_LOCAL(nSpans * sizeof(xRectangle));
  241.     register DDXPointPtr p = ppts;
  242.     int *w = pwidth;
  243.  
  244.     rects = rectsInit;
  245.     
  246.     for(i = 0;i < nSpans;i++)
  247.       {
  248.     if(i && p->x == (p-1)->x && p->y == ((p-1)->y + 1) && *w == *(w-1))
  249.       {
  250.         (rects-1)->height++;
  251.       } else {
  252.         rects->x = p->x;
  253.         rects->y = p->y;
  254.         rects->width = *w;
  255.         rects->height = 1;
  256.         rects++;
  257.       }
  258.     p++;
  259.     w++;
  260.       }
  261.     Rfill = miRectsToRegion(rects - rectsInit, rectsInit,
  262.                 fSorted ? CT_YXBANDED : CT_UNSORTED);
  263.     DEALLOCATE_LOCAL(rectsInit);
  264.     miRegionValidate(Rfill, &overlap);
  265.     if(miIntersect(Rfill, Rfill, pClip) == FALSE)
  266.       { 
  267.     ErrorF("mpelStippleFillSpans: Error in clip intersect");
  268.     miRegionDestroy(Rfill);
  269.     return;
  270.       }
  271.   }
  272.   /* Now Rfill is a region to be entirely filled with stipple */
  273.   if(pStippleB)
  274.     mpelStippleFillRegion(Rfill, pStippleB, bg, alu,  pPriv->colorRrop.planemask,
  275.               -1, -1, -1, -1, xSrc, ySrc);
  276.   if(pStippleF)
  277.     mpelStippleFillRegion(Rfill, pStippleF, fg, alu, pPriv->colorRrop.planemask,
  278.               -1, -1, -1, -1, xSrc, ySrc);
  279.   miRegionDestroy(Rfill);
  280. }
  281.  
  282. void
  283. mpelStippleFillRect(pDrawable, pGC, nrect, prect)
  284.     DrawablePtr pDrawable;
  285.     GCPtr    pGC;
  286.     int        nrect;
  287.     xRectangle    *prect;
  288. {
  289.   RegionPtr fillRgn;
  290.   ppcPrivGC *pPriv = (ppcPrivGC *)pGC->devPrivates[mfbGCPrivateIndex].ptr;
  291.   Bool overlap;
  292.   TRACE(("mpelStippleFillRect(%#x, %#x, %d, %#x)\n",pDrawable,pGC,nrect,prect));
  293.   fillRgn = miRectsToRegion(nrect, prect, CT_UNSORTED);
  294.   miRegionValidate(fillRgn, &overlap);
  295.   miTranslateRegion(fillRgn, pDrawable->x, pDrawable->y);
  296.   miIntersect(fillRgn, fillRgn, pPriv->pCompositeClip);
  297.   miRegionValidate(fillRgn, &overlap);
  298.   mpelStippleFillRegion(fillRgn, pGC->stipple, pPriv->colorRrop.fgPixel,
  299.             pPriv->colorRrop.alu, pGC->planemask, 
  300.             -1, -1, -1, -1, pDrawable->x, pDrawable->y);
  301.   miRegionDestroy(fillRgn);
  302. }
  303.  
  304. #ifdef TRACE_X
  305. int __verbose_trace;
  306. #endif
  307.  
  308. static xPoint *stpts;
  309. static int stptcnt;
  310.  
  311. mpelStippleFillRegion(pRgn, pStipple, fg, alu, planes, x, y, w, h, xSrc, ySrc)
  312. RegionPtr pRgn;
  313. PixmapPtr pStipple;
  314. int xSrc, ySrc, alu, x, y;
  315. unsigned int w, h;
  316. unsigned long fg, planes;
  317. {
  318.   register unsigned char *bits;
  319.   int padded_h, nbytes, fast;
  320.   unsigned int src_al, dest_al;
  321.   RegionRec r;
  322.   int need_to_free = 0;    /* Need to unInit temp region ? */
  323.  
  324. #ifdef TRACE_X
  325.   if(pRgn)
  326.     {
  327.       TRACE(("mpelStippleFillRegion({%d, %d} {%d, %d}, {%dx%d}, fg %d %s)\n",
  328.          pRgn->extents.x1, pRgn->extents.y1, pRgn->extents.x2,
  329.          pRgn->extents.y2, pStipple->drawable.width,
  330.          pStipple->drawable.height,fg, gxnames[alu]));
  331.     } else {
  332.       TRACE(("mpelStippleFillRegion(%d, %d, %d, %d, {%dx%d}, fg %d %s)\n",
  333.          x, y, w, h, pStipple->drawable.width,
  334.          pStipple->drawable.height,fg, gxnames[alu]));
  335.     }
  336. #endif
  337.  
  338.   switch(alu)
  339.     {
  340.     case GXnoop:
  341.       return;
  342.     case GXclear:
  343.       alu = GXcopy;
  344.       fg  = 0;
  345.       break;
  346.     case GXset:
  347.       alu = GXcopy;
  348.       fg = ~0;
  349.       break;
  350.     case GXcopyInverted:
  351.       alu = GXcopy;
  352.       fg = ~fg;
  353.       break;
  354.     }
  355.   if(w != -1 && h != -1)
  356.     {
  357.       BoxRec b;
  358.       Bool overlap;
  359.       b.x1 = x;
  360.       b.x2 = x + w - 1;
  361.       b.y1 = y;
  362.       b.y2 = y + h - 1;
  363.       miRegionInit(&r, &b, 0);
  364.       if(pRgn)
  365.     miIntersect(&r, &r, pRgn);
  366.       pRgn = &r;
  367.       miRegionValidate(pRgn, &overlap);
  368.       need_to_free = 1;
  369.     }
  370.   /* At this point pRgn is a list of rectangles to be completely
  371.      filled with the stipple pattern.  x, y, w, and h can be
  372.      ignored. */
  373.  
  374.   src_al = pStipple->devKind;
  375.   /* dest_al is the number of 4-bit pieces that need to be read.
  376.      To simplify later calculations, make it be a multiple of 2. */
  377.   dest_al = ((pStipple->drawable.width + 7) >> 3) << 1;
  378.   padded_h = (pStipple->drawable.height + 3) & ~3;
  379.  
  380.   /* Can the output data fit into a megapel adapter command ? */
  381.   fast = ((nbytes = padded_h * dest_al / 2) < 0x7ff0) && (alu == GXcopy);
  382.  
  383.   if(!fast)
  384.     {
  385.       padded_h = pStipple->drawable.height;
  386.       if((nbytes = src_al * padded_h / 8) > MPEL_BLIT_STAGE_SIZE)
  387.     {
  388.       ErrorF("mpelStipple: stipple too big\n");
  389.       return;
  390.     }
  391.     }
  392.  
  393.   mpelSetPlaneMask(planes);
  394.  
  395.   ySrc %=  pStipple->drawable.height;
  396.   if(ySrc < 0)
  397.     ySrc += pStipple->drawable.height;
  398.   xSrc %= pStipple->drawable.width;
  399.   if(xSrc < 0)
  400.     xSrc += pStipple->drawable.width;
  401.  
  402.   bits = pStipple->devPrivate.ptr;
  403.  
  404.   if(fast)
  405.     {
  406.       mpelBLTImmed4x4WColorExpansion d;
  407.       mpelRectangle scissor;
  408.       BoxPtr rect4x4;
  409.       unsigned short *stage = (unsigned short *)ALLOCATE_LOCAL(nbytes);
  410.       register unsigned short *dst = stage;
  411.       register int xc, yc;
  412.       unsigned int i;
  413.       int pused = 0;
  414.       int sh = pStipple->drawable.height;
  415.       int sw = pStipple->drawable.width;
  416.       int nboxes;
  417.  
  418.       d.color = fg;
  419.  
  420.       make4x4(bits, dst, &sw, &sh, src_al, dest_al * 4, xSrc, ySrc);
  421.  
  422.       rect4x4 = mpel4x4rgn(pRgn, &nboxes);
  423.  
  424.       for(i = 0;i < nboxes; i++)
  425.     {
  426.       BoxPtr b = rect4x4 + i;
  427. #ifdef TRACE_X
  428.       if(__verbose_trace)
  429.         TRACE(("region {%d,%d}, {%d,%d} data [%x %x ...]\n",
  430.            b->x1, b->y1, b->x2, b->y2, stage[0], stage[1]));
  431. #endif
  432.       scissor.uright.x = b->x2;
  433.       scissor.lleft.x  = b->x1;
  434.       scissor.uright.y = MPEL_HEIGHT - 1 - b->y1;
  435.       scissor.lleft.y  = MPEL_HEIGHT - b->y2;
  436.       MPELSetScissor(&scissor);
  437.  
  438.       /* Optimize points.  A bit of the source is
  439.          bits + (src_al * y) + x / 8 :  x % 8 */
  440.  
  441.       if(b->x1 == b->x2 && b->y1 + 1 <= b->y2)
  442.         {
  443.           register int xoff, yoff;
  444.           xoff = (b->x1 - xSrc) % sw;
  445.           yoff = (b->y1 - ySrc) % sh;
  446.           if(xoff < 0)
  447.         xoff += sw;
  448.           if(yoff < 0)
  449.         yoff += sw;
  450.           if(bits[src_al * yoff + x / 8] & (0x80 >> (x & 7)))
  451.         {
  452.           if(pused >= stptcnt)
  453.             stpts = (xPoint *)Xrealloc(stpts, sizeof(xPoint) * (stptcnt = pused + 48));
  454.           stpts[pused].x = b->x1;
  455.           stpts[pused].y = MPEL_HEIGHT - 1 - b->y1;
  456.           pused++;
  457.         }
  458.           continue;
  459.         }
  460.  
  461.       /* The megapel scissor hardware requires that the low 2 bits
  462.          of the lower left corner of the scissor region be the same
  463.          as those of the box being filled, else the scissor boundary
  464.          may be off by up to 3 bits.  The following code needs to be
  465.          fixed to compensate for this.  */
  466.  
  467.       for(xc = (b->x1/sw)*sw;xc < b->x2; xc += sw)
  468.         for(yc = (b->y1/sh)*sh;yc < b->y2; yc += sh)
  469.           {
  470.         unsigned int tmpy = (b->y2 - yc + 2) & ~3;
  471.         unsigned int tmpnb;
  472.         if(tmpy > padded_h)
  473.           tmpy = padded_h;
  474.         tmpnb = dest_al / 2 * tmpy;
  475. #ifdef TRACE_X
  476.         if(__verbose_trace)
  477.           TRACE(("\tnbytes = %d, tmpy = %d\n", tmpnb, tmpy));
  478. #endif
  479.         d.dest.lleft.x  = xc;
  480.         d.dest.lleft.y = MPEL_HEIGHT - yc - tmpy;
  481.         d.dest.uright.x  = xc + dest_al * 4 - 1;
  482.         d.dest.uright.y = MPEL_HEIGHT - yc - 1;
  483.         MPELBLTImmed4x4WColorExpansion(tmpnb, &d);
  484.         MPELSendData(tmpnb, (char *)stage);
  485.           }
  486.     }
  487.       if(pused)
  488.     {
  489. #define MAXRQPTS    (32760 / sizeof(xPoint))
  490.       register int rem;
  491.       register xPoint *pts = stpts;
  492.       MPELResetScissor();
  493.       MPELSetMarkerType(1);
  494.       MPELSetPolymarkerColor(fg);
  495.       /* MPELPolymarker does not evaluate any of its arguments
  496.          more than once. */
  497.       for(rem = pused;rem > 0;rem -= MAXRQPTS, pts+=MAXRQPTS)
  498.         MPELPolymarker((rem>MAXRQPTS)?MAXRQPTS:rem, pts);
  499.       TRACE(("mpelStipple: %d extra points\n", pused));
  500.     }
  501.       DEALLOCATE_LOCAL((char *)stage);
  502.     } else { /* ! fast */
  503.       mpelSrcBLTVPMWColorExpansion block;
  504.       register unsigned int sh = pStipple->drawable.height;
  505.       register unsigned int sw = pStipple->drawable.width;
  506.       register int xc, yc;
  507.       int i;
  508.  
  509.       block.color   = fg;
  510.       block.alu     = alu + 1;
  511.       block.srcaddr = mpelAddr(MPEL_BLIT_STAGE);
  512.  
  513.       MPELWaitFifo();    /* Don't copy into stage area until sure
  514.                no one else is using it. */
  515.       MOVE(bits, MPEL_BLIT_STAGE, src_al * sh);
  516.       TRACE(("mpel slow stipple: org {%d, %d} source {%d, %d} src_al %d\n",
  517.          x, y, sw, sh, src_al));
  518.       for(i = 0;i < REGION_NUM_RECTS(pRgn); i++)
  519.     {
  520.       mpelRectangle scissor;
  521.       BoxPtr b = REGION_RECTS(pRgn)+i;
  522.  
  523.       scissor.uright.x = b->x2;
  524.       scissor.lleft.x  = b->x1;
  525.       scissor.uright.y = MPEL_HEIGHT - 1 - b->y1;
  526.       scissor.lleft.y  = MPEL_HEIGHT - b->y2;
  527.       MPELSetScissor(&scissor);
  528.  
  529.       for(xc = (b->x1 - xSrc)/sw + xSrc;xc < b->x2;xc += sw)
  530.         for(yc = (b->y1 - ySrc)/sh + ySrc;yc < b->y2;yc += sh)
  531.           {
  532.         block.dest.lleft.x  = xc;
  533.         block.dest.lleft.y  = MPEL_HEIGHT - yc - sh;
  534.         block.dest.uright.x = xc + (src_al << 3) - 1;
  535.         block.dest.uright.y = MPEL_HEIGHT - yc - 1;
  536.         MPELSrcBLTVPMWColorExpansionROP(&block);
  537.           }
  538.     }
  539.     }
  540.   MPELResetScissor();
  541.   if(need_to_free)
  542.     miRegionUninit(pRgn);
  543. }
  544.  
  545.  
  546. static void make4x4(bits, dst, sw, sh, src_al, dw, xOrg, yOrg)
  547. char *bits;
  548. short *dst;
  549. int *sw, *sh, dw, src_al;
  550. int xOrg, yOrg;
  551. {
  552.   int dh = (*sh + 3) & ~3;
  553.   int xc, yc;
  554.  
  555.   bzero((char *)dst, dh * dw >> 3);
  556.     if(*sh & 3)
  557.     {
  558.       register int off = 0;
  559.       yc = (*sh & ~3);
  560.       for(xc = 0; xc < (dw >> 3); xc++)
  561.     {
  562.       register unsigned int i;
  563.       union { unsigned int i;
  564.           unsigned char c[4];
  565.         } u;
  566.       u.i = 0;
  567.       switch(*sh & 3)
  568.         {
  569.         case 2:
  570.           u.c[3] = u.c[1] = *(bits + off + ((yc + yOrg + 1) % *sh) * src_al);
  571.           u.c[2] = u.c[0] = *(bits + off + ((yc + yOrg) % *sh) * src_al);
  572.           *sh = 4;
  573.           break;
  574.         case 3:
  575.           u.c[2] = *(bits + off + ((yc + yOrg + 2) % *sh) * src_al);
  576.           u.c[1] = *(bits + off + ((yc + yOrg + 1) % *sh) * src_al);
  577.           u.c[0] = *(bits + off + ((yc + yOrg) % *sh) * src_al);
  578.           break;
  579.         case 1:
  580.           u.c[0] = u.c[1] = u.c[2] = u.c[3] =
  581.         *(bits + off + ((yc + yOrg) % *sh) * src_al);
  582.           *sh = 4;
  583.         }
  584.       switch(*sw)
  585.         {
  586.         case 2:
  587.           u.i |= u.i >> 2;
  588.         case 4:
  589.           u.i |= u.i >> 4;
  590.         }
  591.       i = u.i;
  592.       *dst++ = ((i & 0xf0000000) >> 16) | ((i & 0x00f00000) >> 12) |
  593.         ((i & 0x0000f000) >> 8) | ((i & 0x000000f0) >> 4);
  594.       *dst++ = ((i & 0x0f000000) >> 12) | ((i & 0x000f0000) >> 8) |
  595.         ((i & 0x00000f00) >> 4) | (i & 0x0000000f);
  596.       off++;
  597.     }
  598.     }
  599.   for(yc = ((*sh-4)&~3); yc >= 0; yc -= 4)
  600.     {
  601.       register int off = 0;
  602.       for(xc = 0; xc < (dw>>3); xc++)
  603.     {
  604.       register unsigned int i;
  605.       union { unsigned int i;
  606.           unsigned char c[4];
  607.         } u;
  608.           
  609.       u.c[0] = *(bits + off + ((yc + yOrg) % *sh) * src_al);
  610.       u.c[1] = *(bits + off + ((yc + yOrg + 1) % *sh) * src_al);
  611.       u.c[2] = *(bits + off + ((yc + yOrg + 2) % *sh) * src_al);
  612.       u.c[3] = *(bits + off + ((yc + yOrg + 3) % *sh) * src_al);
  613.       switch(*sw)
  614.         {
  615.         case 2:
  616.           u.i |= u.i >> 2;
  617.         case 4:
  618.           u.i |= u.i >> 4;
  619.         }
  620.       i = u.i;
  621.       *dst++ = ((i & 0xf0000000) >> 16) | ((i & 0x00f00000) >> 12) |
  622.         ((i & 0x0000f000) >> 8) | ((i & 0x000000f0) >> 4);
  623.       *dst++ = ((i & 0x0f000000) >> 12) | ((i & 0x000f0000) >> 8) |
  624.         ((i & 0x00000f00) >> 4) | (i & 0x0000000f);
  625.       off++;
  626.     }
  627.     }
  628.   if(*sw == 2 || *sw == 4)
  629.     *sw = 8;
  630. }
  631.  
  632. /* mpel4x4rgn -- transform a validated region into a set of
  633.  * rectangles, creating as many rectangles with height a multiple
  634.  * of 4 as possible.
  635.  *
  636.  * xorg, yorg, sw and sh are hints: making a box bigger is not useful
  637.  * if it is made to cross a boundary s[wh] = 0 mod [xy]org.
  638.  *
  639.  * "4x4" is really a lie at this point...I'll settle for anything big.
  640.  */
  641.  
  642. static BoxPtr mpel4x4rgn(pRgn, ret, sw, sh, xorg, yorg)
  643. RegionPtr pRgn;
  644. int *ret, xorg, yorg;
  645. unsigned int sw, sh;
  646. {
  647. #if 1
  648.   *ret = REGION_NUM_RECTS(pRgn);
  649.   return REGION_RECTS(pRgn);
  650. #else
  651.   int i, nrect;
  652.   BoxPtr prect, prectl;
  653.   int dx1, dx2;
  654.  
  655.   prect = REGION_RECTS(pRgn);
  656.  
  657.   /* Assume it's not worth optimizing regions that have a small
  658.      number of rectangles. */
  659.   if((nrect = REGION_NUM_RECTS(pRgn)) < 8)
  660.     {
  661.       *ret = nrect;
  662.       return prect;
  663.     }
  664.  
  665.   if((i = nrect * 3) > n4x4boxes || n4x4boxes == 0)
  666.     if((mpel4x4boxes = (BoxPtr) Xrealloc(mpel4x4boxes, 
  667.                      sizeof(BoxRec) * (n4x4boxes = i))) == 0)
  668.       {
  669.     ErrorF("mpel4x4rgn: couldn't realloc %d boxes\n", i);
  670.     *ret = nrect;
  671.     n4x4boxes = 0;
  672.     return prect;
  673.       }
  674.  
  675.   i = 0;  
  676.   prectl = prect + nrect - 1;
  677.  
  678.   do
  679.     {
  680.       register BoxPtr prectn;
  681.       /* Check for: boxes adjacent vertically, sides within 2 pixels */
  682.       if(prect < prectl && (prectn = prect + 1)->y1 == prect->y2 && 
  683.      prect->y2 - prect->y1 < 3 && prectn->y2 - prectn->y1 < 3 &&
  684.      prect->x2 - prect->x1 > 7 &&
  685.      (dx1 = prectn->x1 - prect->x1) > -3 && dx1 < 3 && 
  686.      (dx2 = prectn->x2 - prect->x2) > -3 && dx2 < 3)
  687.     {
  688.       if(dx1 > 0)
  689.         {
  690.           mpel4x4boxes[i].x1 = prect->x1;
  691.           mpel4x4boxes[i].x2 = prectn->x1 - 1;
  692.           mpel4x4boxes[i].y1 = prect->y1;
  693.           mpel4x4boxes[i++].y2 = prect->y2;
  694.         } else if(dx1 < 0) {
  695.           mpel4x4boxes[i].x1 = prectn->x1;
  696.           mpel4x4boxes[i].x2 = prect->x1 - 1;
  697.           mpel4x4boxes[i].y1 = prectn->y1;
  698.           mpel4x4boxes[i++].y2 = prectn->y2;
  699.         }
  700.       if(dx2 < 0)
  701.         {
  702.           mpel4x4boxes[i].x1 = prectn->x2 + 1;
  703.           mpel4x4boxes[i].x2 = prect->x2;
  704.           mpel4x4boxes[i].y1 = prect->y1;
  705.           mpel4x4boxes[i++].y2 = prect->y2;
  706.         } else if(dx2 > 0) {
  707.           mpel4x4boxes[i].x1 = prect->x2 + 1;
  708.           mpel4x4boxes[i].x2 = prectn->x2;
  709.           mpel4x4boxes[i].y1 = prectn->y1;
  710.           mpel4x4boxes[i++].y2 = prectn->y2;
  711.         }
  712.       mpel4x4boxes[i].x1 = (dx1 < 0) ? prect->x1 : prectn->x1;
  713.       mpel4x4boxes[i].x2 = (dx2 > 0) ? prect->x2 : prectn->x2;
  714.       mpel4x4boxes[i].y1 = prect->y1;
  715.       mpel4x4boxes[i++].y2 = prectn->y2;
  716.       prect += 2;
  717.     } else {
  718.       mpel4x4boxes[i++] = *prect++;
  719.     }
  720.     } while(prect <= prectl);
  721.   *ret = i;
  722. #ifdef TRACE_X
  723.   if(ibmTrace && mpel4x4verbose)
  724.     ErrorF("mpel4x4rgn(%#x) returns %d\n", pRgn, i);
  725.   if(ibmTrace && mpel4x4verbose > 1)
  726.     while(i--)
  727.       ErrorF("mpel4x4boxes[%d] = %d x %d  {%d, %d}, {%d, %d}\n",
  728.          i, mpel4x4boxes[i].x2 - mpel4x4boxes[i].x1,
  729.          mpel4x4boxes[i].y2 - mpel4x4boxes[i].y1,
  730.          mpel4x4boxes[i].x1, mpel4x4boxes[i].y1,
  731.          mpel4x4boxes[i].x2, mpel4x4boxes[i].y2);
  732. #endif
  733.   return mpel4x4boxes;
  734. #endif
  735. }
  736.