home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 275 / DPCS0111DVD.ISO / Toolkit / Audio-Visual / VirtualDub / Source / VirtualDub-1.9.10-src.7z / src / Kasumi / source / triblt.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2009-09-14  |  46.7 KB  |  1,718 lines

  1. //    VirtualDub - Video processing and capture application
  2. //    Graphics support library
  3. //    Copyright (C) 1998-2008 Avery Lee
  4. //
  5. //    This program is free software; you can redistribute it and/or modify
  6. //    it under the terms of the GNU General Public License as published by
  7. //    the Free Software Foundation; either version 2 of the License, or
  8. //    (at your option) any later version.
  9. //
  10. //    This program is distributed in the hope that it will be useful,
  11. //    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. //    GNU General Public License for more details.
  14. //
  15. //    You should have received a copy of the GNU General Public License
  16. //    along with this program; if not, write to the Free Software
  17. //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  
  19. #include <math.h>
  20. #include <vector>
  21. #include <vd2/system/math.h>
  22. #include <vd2/system/cpuaccel.h>
  23. #include <vd2/system/vdalloc.h>
  24. #include <vd2/Kasumi/pixmap.h>
  25. #include <vd2/Kasumi/pixmaputils.h>
  26. #include <vd2/Kasumi/pixmapops.h>
  27. #include <vd2/Kasumi/resample.h>
  28. #include <vd2/Kasumi/tables.h>
  29. #include <vd2/Kasumi/triblt.h>
  30.  
  31. namespace {
  32.     uint32 lerp_RGB888(sint32 a, sint32 b, sint32 x) {
  33.         sint32 a_rb    = a & 0xff00ff;
  34.         sint32 a_g    = a & 0x00ff00;
  35.         sint32 b_rb    = b & 0xff00ff;
  36.         sint32 b_g    = b & 0x00ff00;
  37.  
  38.         const uint32 top_rb = (a_rb + (((b_rb - a_rb)*x + 0x00800080) >> 8)) & 0xff00ff;
  39.         const uint32 top_g  = (a_g  + (((b_g  - a_g )*x + 0x00008000) >> 8)) & 0x00ff00;
  40.  
  41.         return top_rb + top_g;
  42.     }
  43.  
  44.     uint32 bilerp_RGB888(sint32 a, sint32 b, sint32 c, sint32 d, sint32 x, sint32 y) {
  45.         sint32 a_rb    = a & 0xff00ff;
  46.         sint32 a_g    = a & 0x00ff00;
  47.         sint32 b_rb    = b & 0xff00ff;
  48.         sint32 b_g    = b & 0x00ff00;
  49.         sint32 c_rb    = c & 0xff00ff;
  50.         sint32 c_g    = c & 0x00ff00;
  51.         sint32 d_rb    = d & 0xff00ff;
  52.         sint32 d_g    = d & 0x00ff00;
  53.  
  54.         const uint32 top_rb = (a_rb + (((b_rb - a_rb)*x + 0x00800080) >> 8)) & 0xff00ff;
  55.         const uint32 top_g  = (a_g  + (((b_g  - a_g )*x + 0x00008000) >> 8)) & 0x00ff00;
  56.         const uint32 bot_rb = (c_rb + (((d_rb - c_rb)*x + 0x00800080) >> 8)) & 0xff00ff;
  57.         const uint32 bot_g  = (c_g  + (((d_g  - c_g )*x + 0x00008000) >> 8)) & 0x00ff00;
  58.  
  59.         const uint32 final_rb = (top_rb + (((bot_rb - top_rb)*y) >> 8)) & 0xff00ff;
  60.         const uint32 final_g  = (top_g  + (((bot_g  - top_g )*y) >> 8)) & 0x00ff00;
  61.  
  62.         return final_rb + final_g;
  63.     }
  64.  
  65.     uint32 bicubic_RGB888(const uint32 *src0, const uint32 *src1, const uint32 *src2, const uint32 *src3, sint32 x, sint32 y) {
  66.         const uint32 p00 = src0[0];
  67.         const uint32 p01 = src0[1];
  68.         const uint32 p02 = src0[2];
  69.         const uint32 p03 = src0[3];
  70.         const uint32 p10 = src1[0];
  71.         const uint32 p11 = src1[1];
  72.         const uint32 p12 = src1[2];
  73.         const uint32 p13 = src1[3];
  74.         const uint32 p20 = src2[0];
  75.         const uint32 p21 = src2[1];
  76.         const uint32 p22 = src2[2];
  77.         const uint32 p23 = src2[3];
  78.         const uint32 p30 = src3[0];
  79.         const uint32 p31 = src3[1];
  80.         const uint32 p32 = src3[2];
  81.         const uint32 p33 = src3[3];
  82.  
  83.         const sint32 *htab = kVDCubicInterpTableFX14_075[x];
  84.         const sint32 *vtab = kVDCubicInterpTableFX14_075[y];
  85.  
  86.         const int ch0 = htab[0];
  87.         const int ch1 = htab[1];
  88.         const int ch2 = htab[2];
  89.         const int ch3 = htab[3];
  90.         const int cv0 = vtab[0];
  91.         const int cv1 = vtab[1];
  92.         const int cv2 = vtab[2];
  93.         const int cv3 = vtab[3];
  94.  
  95.         int r0 = ((int)((p00>>16)&0xff) * ch0 + (int)((p01>>16)&0xff) * ch1 + (int)((p02>>16)&0xff) * ch2 + (int)((p03>>16)&0xff) * ch3 + 128) >> 8;
  96.         int g0 = ((int)((p00>> 8)&0xff) * ch0 + (int)((p01>> 8)&0xff) * ch1 + (int)((p02>> 8)&0xff) * ch2 + (int)((p03>> 8)&0xff) * ch3 + 128) >> 8;
  97.         int b0 = ((int)((p00    )&0xff) * ch0 + (int)((p01    )&0xff) * ch1 + (int)((p02    )&0xff) * ch2 + (int)((p03    )&0xff) * ch3 + 128) >> 8;
  98.         int r1 = ((int)((p10>>16)&0xff) * ch0 + (int)((p11>>16)&0xff) * ch1 + (int)((p12>>16)&0xff) * ch2 + (int)((p13>>16)&0xff) * ch3 + 128) >> 8;
  99.         int g1 = ((int)((p10>> 8)&0xff) * ch0 + (int)((p11>> 8)&0xff) * ch1 + (int)((p12>> 8)&0xff) * ch2 + (int)((p13>> 8)&0xff) * ch3 + 128) >> 8;
  100.         int b1 = ((int)((p10    )&0xff) * ch0 + (int)((p11    )&0xff) * ch1 + (int)((p12    )&0xff) * ch2 + (int)((p13    )&0xff) * ch3 + 128) >> 8;
  101.         int r2 = ((int)((p20>>16)&0xff) * ch0 + (int)((p21>>16)&0xff) * ch1 + (int)((p22>>16)&0xff) * ch2 + (int)((p23>>16)&0xff) * ch3 + 128) >> 8;
  102.         int g2 = ((int)((p20>> 8)&0xff) * ch0 + (int)((p21>> 8)&0xff) * ch1 + (int)((p22>> 8)&0xff) * ch2 + (int)((p23>> 8)&0xff) * ch3 + 128) >> 8;
  103.         int b2 = ((int)((p20    )&0xff) * ch0 + (int)((p21    )&0xff) * ch1 + (int)((p22    )&0xff) * ch2 + (int)((p23    )&0xff) * ch3 + 128) >> 8;
  104.         int r3 = ((int)((p30>>16)&0xff) * ch0 + (int)((p31>>16)&0xff) * ch1 + (int)((p32>>16)&0xff) * ch2 + (int)((p33>>16)&0xff) * ch3 + 128) >> 8;
  105.         int g3 = ((int)((p30>> 8)&0xff) * ch0 + (int)((p31>> 8)&0xff) * ch1 + (int)((p32>> 8)&0xff) * ch2 + (int)((p33>> 8)&0xff) * ch3 + 128) >> 8;
  106.         int b3 = ((int)((p30    )&0xff) * ch0 + (int)((p31    )&0xff) * ch1 + (int)((p32    )&0xff) * ch2 + (int)((p33    )&0xff) * ch3 + 128) >> 8;
  107.  
  108.         int r = (r0 * cv0 + r1 * cv1 + r2 * cv2 + r3 * cv3 + (1<<19)) >> 20;
  109.         int g = (g0 * cv0 + g1 * cv1 + g2 * cv2 + g3 * cv3 + (1<<19)) >> 20;
  110.         int b = (b0 * cv0 + b1 * cv1 + b2 * cv2 + b3 * cv3 + (1<<19)) >> 20;
  111.  
  112.         if (r<0) r=0; else if (r>255) r=255;
  113.         if (g<0) g=0; else if (g>255) g=255;
  114.         if (b<0) b=0; else if (b>255) b=255;
  115.  
  116.         return (r<<16) + (g<<8) + b;
  117.     }
  118. }
  119.  
  120. namespace {
  121.     enum {
  122.         kTop = 1,
  123.         kBottom = 2,
  124.         kLeft = 4,
  125.         kRight = 8,
  126.         kNear = 16,
  127.         kFar = 32
  128.     };
  129.  
  130.     struct VDTriBltMipInfo {
  131.         const uint32 *mip;
  132.         ptrdiff_t pitch;
  133.         uint32 uvmul, _pad;
  134.     };
  135.  
  136.     struct VDTriBltInfo {
  137.         VDTriBltMipInfo mips[16];
  138.         uint32 *dst;
  139.         const uint32 *src;
  140.         sint32 width;
  141.         const int *cubictab;
  142.     };
  143.  
  144.     struct VDTriBltGenInfo {
  145.         float    u;
  146.         float    v;
  147.         float    rhw;
  148.         float    dudx;
  149.         float    dvdx;
  150.         float    drhwdx;
  151.     };
  152.  
  153.     typedef void (*VDTriBltSpanFunction)(const VDTriBltInfo *);
  154.     typedef void (*VDTriBltGenFunction)(const VDTriBltGenInfo *);
  155.  
  156.     void vd_triblt_span_point(const VDTriBltInfo *pInfo) {
  157.         sint32 w = -pInfo->width;
  158.         uint32 *dst = pInfo->dst + pInfo->width;
  159.         const uint32 *src = pInfo->src;
  160.         const uint32 *texture = pInfo->mips[0].mip;
  161.         const ptrdiff_t texpitch = pInfo->mips[0].pitch;
  162.  
  163.         do {
  164.             dst[w] = vdptroffset(texture, texpitch * src[1])[src[0]];
  165.             src += 2;
  166.         } while(++w);
  167.     }
  168.  
  169.     void vd_triblt_span_bilinear(const VDTriBltInfo *pInfo) {
  170.         sint32 w = -pInfo->width;
  171.         uint32 *dst = pInfo->dst + pInfo->width;
  172.         const uint32 *src = pInfo->src;
  173.         const uint32 *texture = pInfo->mips[0].mip;
  174.         const ptrdiff_t texpitch = pInfo->mips[0].pitch;
  175.  
  176.         do {
  177.             const sint32 u = src[0];
  178.             const sint32 v = src[1];
  179.             src += 2;
  180.             const uint32 *src1 = vdptroffset(texture, texpitch * (v>>8)) + (u>>8);
  181.             const uint32 *src2 = vdptroffset(src1, texpitch);
  182.  
  183.             dst[w] = bilerp_RGB888(src1[0], src1[1], src2[0], src2[1], u&255, v&255);
  184.         } while(++w);
  185.     }
  186.  
  187.     void vd_triblt_span_trilinear(const VDTriBltInfo *pInfo) {
  188.         sint32 w = -pInfo->width;
  189.         uint32 *dst = pInfo->dst + pInfo->width;
  190.         const uint32 *src = pInfo->src;
  191.  
  192.         do {
  193.             sint32 u = src[0];
  194.             sint32 v = src[1];
  195.             const sint32 lambda = src[2];
  196.             src += 3;
  197.  
  198.             const sint32 lod = lambda >> 8;
  199.  
  200.             const uint32 *texture1 = pInfo->mips[lod].mip;
  201.             const ptrdiff_t texpitch1 = pInfo->mips[lod].pitch;
  202.             const uint32 *texture2 = pInfo->mips[lod+1].mip;
  203.             const ptrdiff_t texpitch2 = pInfo->mips[lod+1].pitch;
  204.  
  205.             u >>= lod;
  206.             v >>= lod;
  207.  
  208.             u += 128;
  209.             v += 128;
  210.  
  211.             const uint32 *src1 = vdptroffset(texture1, texpitch1 * (v>>8)) + (u>>8);
  212.             const uint32 *src2 = vdptroffset(src1, texpitch1);
  213.             const uint32 p1 = bilerp_RGB888(src1[0], src1[1], src2[0], src2[1], u&255, v&255);
  214.  
  215.             u += 128;
  216.             v += 128;
  217.  
  218.             const uint32 *src3 = vdptroffset(texture2, texpitch2 * (v>>9)) + (u>>9);
  219.             const uint32 *src4 = vdptroffset(src3, texpitch2);
  220.             const uint32 p2 = bilerp_RGB888(src3[0], src3[1], src4[0], src4[1], (u>>1)&255, (v>>1)&255);
  221.  
  222.             dst[w] = lerp_RGB888(p1, p2, lambda & 255);
  223.         } while(++w);
  224.     }
  225.  
  226.     void vd_triblt_span_bicubic_mip_linear(const VDTriBltInfo *pInfo) {
  227.         sint32 w = -pInfo->width;
  228.         uint32 *dst = pInfo->dst + pInfo->width;
  229.         const uint32 *src = pInfo->src;
  230.  
  231.         do {
  232.             sint32 u = src[0];
  233.             sint32 v = src[1];
  234.             const sint32 lambda = src[2];
  235.             src += 3;
  236.  
  237.             const sint32 lod = lambda >> 8;
  238.  
  239.             const uint32 *texture1 = pInfo->mips[lod].mip;
  240.             const ptrdiff_t texpitch1 = pInfo->mips[lod].pitch;
  241.             const uint32 *texture2 = pInfo->mips[lod+1].mip;
  242.             const ptrdiff_t texpitch2 = pInfo->mips[lod+1].pitch;
  243.  
  244.             u >>= lod;
  245.             v >>= lod;
  246.  
  247.             u += 128;
  248.             v += 128;
  249.  
  250.             const uint32 *src1 = vdptroffset(texture1, texpitch1 * (v>>8)) + (u>>8);
  251.             const uint32 *src2 = vdptroffset(src1, texpitch1);
  252.             const uint32 *src3 = vdptroffset(src2, texpitch1);
  253.             const uint32 *src4 = vdptroffset(src3, texpitch1);
  254.             const uint32 p1 = bicubic_RGB888(src1, src2, src3, src4, u&255, v&255);
  255.  
  256.             u += 128;
  257.             v += 128;
  258.  
  259.             const uint32 *src5 = vdptroffset(texture2, texpitch2 * (v>>9)) + (u>>9);
  260.             const uint32 *src6 = vdptroffset(src5, texpitch2);
  261.             const uint32 *src7 = vdptroffset(src6, texpitch2);
  262.             const uint32 *src8 = vdptroffset(src7, texpitch2);
  263.             const uint32 p2 = bicubic_RGB888(src5, src6, src7, src8, (u>>1)&255, (v>>1)&255);
  264.  
  265.             dst[w] = lerp_RGB888(p1, p2, lambda & 255);
  266.         } while(++w);
  267.     }
  268.  
  269. #ifdef _M_IX86
  270.     extern "C" void vdasm_triblt_span_bilinear_mmx(const VDTriBltInfo *pInfo);
  271.     extern "C" void vdasm_triblt_span_trilinear_mmx(const VDTriBltInfo *pInfo);
  272.     extern "C" void vdasm_triblt_span_bicubic_mip_linear_mmx(const VDTriBltInfo *pInfo);
  273.     extern "C" void vdasm_triblt_span_bicubic_mip_linear_sse2(const VDTriBltInfo *pInfo);
  274.     extern "C" void vdasm_triblt_span_point(const VDTriBltInfo *pInfo);
  275. #endif
  276.  
  277.     struct VDTriBltTransformedVertex {
  278.         float x, y, z;
  279.         union {
  280.             float w;
  281.             float rhw;
  282.         };
  283.         float r, g, b, a;
  284.         float u, v;
  285.         int outcode;
  286.  
  287.         void interp(const VDTriBltTransformedVertex *v1, const VDTriBltTransformedVertex *v2, float alpha) {
  288.             x = v1->x + alpha * (v2->x - v1->x);
  289.             y = v1->y + alpha * (v2->y - v1->y);
  290.             z = v1->z + alpha * (v2->z - v1->z);
  291.             w = v1->w + alpha * (v2->w - v1->w);
  292.  
  293.             r = v1->r + alpha * (v2->r - v1->r);
  294.             g = v1->g + alpha * (v2->g - v1->g);
  295.             b = v1->b + alpha * (v2->b - v1->b);
  296.             a = v1->a + alpha * (v2->a - v1->a);
  297.  
  298.             u = v1->u + alpha * (v2->u - v1->u);
  299.             v = v1->v + alpha * (v2->v - v1->v);
  300.  
  301.             outcode    = (x < -w ? kLeft : 0)
  302.                     + (x > +w ? kRight : 0)
  303.                     + (y < -w ? kTop : 0)
  304.                     + (y > +w ? kBottom : 0)
  305.                     + (z < -w ? kNear : 0)
  306.                     + (z > +w ? kFar : 0);
  307.         }
  308.     };
  309.  
  310.     void TransformVerts(VDTriBltTransformedVertex *dst, const VDTriBltVertex *src, int nVerts, const float xform[16]) {
  311.         const float xflocal[16]={
  312.             xform[ 0],    xform[ 1],    xform[ 2],    xform[ 3],
  313.             xform[ 4],    xform[ 5],    xform[ 6],    xform[ 7],
  314.             xform[ 8],    xform[ 9],    xform[10],    xform[11],
  315.             xform[12],    xform[13],    xform[14],    xform[15],
  316.         };
  317.  
  318.         if (nVerts <= 0)
  319.             return;
  320.  
  321.         do {
  322.             const float x0 = src->x;
  323.             const float y0 = src->y;
  324.             const float z0 = src->z;
  325.  
  326.             const float w    = x0*xflocal[12] + y0*xflocal[13] + z0*xflocal[14] + xflocal[15];
  327.             const float x   = x0*xflocal[ 0] + y0*xflocal[ 1] + z0*xflocal[ 2] + xflocal[ 3];
  328.             const float y   = x0*xflocal[ 4] + y0*xflocal[ 5] + z0*xflocal[ 6] + xflocal[ 7];
  329.             const float z   = x0*xflocal[ 8] + y0*xflocal[ 9] + z0*xflocal[10] + xflocal[11];
  330.  
  331.             int outcode = 0;
  332.  
  333.             if (x < -w)        outcode += kLeft;
  334.             if (x > w)        outcode += kRight;
  335.             if (y < -w)        outcode += kTop;
  336.             if (y > w)        outcode += kBottom;
  337.             if (z < -w)        outcode += kNear;
  338.             if (z > w)        outcode += kFar;
  339.  
  340.             dst->x = x;
  341.             dst->y = y;
  342.             dst->z = z;
  343.             dst->w = w;
  344.             dst->u = src->u;
  345.             dst->v = src->v;
  346.             dst->r = 1.0f;
  347.             dst->g = 1.0f;
  348.             dst->b = 1.0f;
  349.             dst->a = 1.0f;
  350.             dst->outcode = outcode;
  351.  
  352.             ++src;
  353.             ++dst;
  354.         } while(--nVerts);
  355.     }
  356.  
  357.     void TransformVerts(VDTriBltTransformedVertex *dst, const VDTriColorVertex *src, int nVerts, const float xform[16]) {
  358.         const float xflocal[16]={
  359.             xform[ 0],    xform[ 1],    xform[ 2],    xform[ 3],
  360.             xform[ 4],    xform[ 5],    xform[ 6],    xform[ 7],
  361.             xform[ 8],    xform[ 9],    xform[10],    xform[11],
  362.             xform[12],    xform[13],    xform[14],    xform[15],
  363.         };
  364.  
  365.         if (nVerts <= 0)
  366.             return;
  367.  
  368.         do {
  369.             const float x0 = src->x;
  370.             const float y0 = src->y;
  371.             const float z0 = src->z;
  372.  
  373.             const float w    = x0*xflocal[12] + y0*xflocal[13] + z0*xflocal[14] + xflocal[15];
  374.             const float x   = x0*xflocal[ 0] + y0*xflocal[ 1] + z0*xflocal[ 2] + xflocal[ 3];
  375.             const float y   = x0*xflocal[ 4] + y0*xflocal[ 5] + z0*xflocal[ 6] + xflocal[ 7];
  376.             const float z   = x0*xflocal[ 8] + y0*xflocal[ 9] + z0*xflocal[10] + xflocal[11];
  377.  
  378.             int outcode = 0;
  379.  
  380.             if (x < -w)        outcode += kLeft;
  381.             if (x > w)        outcode += kRight;
  382.             if (y < -w)        outcode += kTop;
  383.             if (y > w)        outcode += kBottom;
  384.             if (z < -w)        outcode += kNear;
  385.             if (z > w)        outcode += kFar;
  386.  
  387.             dst->x = x;
  388.             dst->y = y;
  389.             dst->z = z;
  390.             dst->w = w;
  391.             dst->u = 0.0f;
  392.             dst->v = 0.0f;
  393.             dst->r = src->r;
  394.             dst->g = src->g;
  395.             dst->b = src->b;
  396.             dst->a = src->a;
  397.             dst->outcode = outcode;
  398.  
  399.             ++src;
  400.             ++dst;
  401.         } while(--nVerts);
  402.     }
  403.  
  404.     struct VDTriangleSetupInfo {
  405.         const VDTriBltTransformedVertex *pt, *pr, *pl;
  406.         VDTriBltTransformedVertex tmp0, tmp1, tmp2;
  407.     };
  408.  
  409.     void SetupTri(
  410.             VDTriangleSetupInfo& setup,
  411.             VDPixmap& dst,
  412.             const VDTriBltTransformedVertex *vx0,
  413.             const VDTriBltTransformedVertex *vx1,
  414.             const VDTriBltTransformedVertex *vx2,
  415.             const VDTriBltFilterMode *filterMode
  416.             )
  417.     {
  418.         setup.tmp0 = *vx0;
  419.         setup.tmp1 = *vx1;
  420.         setup.tmp2 = *vx2;
  421.  
  422.         // adjust UVs for filter mode
  423.         if (filterMode) {
  424.             switch(*filterMode) {
  425.             case kTriBltFilterBilinear:
  426.                 setup.tmp0.u += 0.5f;
  427.                 setup.tmp0.v += 0.5f;
  428.                 setup.tmp1.u += 0.5f;
  429.                 setup.tmp1.v += 0.5f;
  430.                 setup.tmp2.u += 0.5f;
  431.                 setup.tmp2.v += 0.5f;
  432.             case kTriBltFilterTrilinear:
  433.             case kTriBltFilterBicubicMipLinear:
  434.                 setup.tmp0.u *= 256.0f;
  435.                 setup.tmp0.v *= 256.0f;
  436.                 setup.tmp1.u *= 256.0f;
  437.                 setup.tmp1.v *= 256.0f;
  438.                 setup.tmp2.u *= 256.0f;
  439.                 setup.tmp2.v *= 256.0f;
  440.                 break;
  441.             case kTriBltFilterPoint:
  442.                 setup.tmp0.u += 1.0f;
  443.                 setup.tmp0.v += 1.0f;
  444.                 setup.tmp1.u += 1.0f;
  445.                 setup.tmp1.v += 1.0f;
  446.                 setup.tmp2.u += 1.0f;
  447.                 setup.tmp2.v += 1.0f;
  448.                 break;
  449.             }
  450.         }
  451.  
  452.         // do perspective divide and NDC space conversion
  453.         const float xscale = dst.w * 0.5f;
  454.         const float yscale = dst.h * 0.5f;
  455.  
  456.         setup.tmp0.rhw = 1.0f / setup.tmp0.w;
  457.         setup.tmp0.x = (1.0f+setup.tmp0.x*setup.tmp0.rhw)*xscale;
  458.         setup.tmp0.y = (1.0f+setup.tmp0.y*setup.tmp0.rhw)*yscale;
  459.         setup.tmp0.u *= setup.tmp0.rhw;
  460.         setup.tmp0.v *= setup.tmp0.rhw;
  461.         setup.tmp0.r *= setup.tmp0.rhw;
  462.         setup.tmp0.g *= setup.tmp0.rhw;
  463.         setup.tmp0.b *= setup.tmp0.rhw;
  464.         setup.tmp0.a *= setup.tmp0.rhw;
  465.         setup.tmp1.rhw = 1.0f / setup.tmp1.w;
  466.         setup.tmp1.x = (1.0f+setup.tmp1.x*setup.tmp1.rhw)*xscale;
  467.         setup.tmp1.y = (1.0f+setup.tmp1.y*setup.tmp1.rhw)*yscale;
  468.         setup.tmp1.u *= setup.tmp1.rhw;
  469.         setup.tmp1.v *= setup.tmp1.rhw;
  470.         setup.tmp1.r *= setup.tmp1.rhw;
  471.         setup.tmp1.g *= setup.tmp1.rhw;
  472.         setup.tmp1.b *= setup.tmp1.rhw;
  473.         setup.tmp1.a *= setup.tmp1.rhw;
  474.         setup.tmp2.rhw = 1.0f / setup.tmp2.w;
  475.         setup.tmp2.x = (1.0f+setup.tmp2.x*setup.tmp2.rhw)*xscale;
  476.         setup.tmp2.y = (1.0f+setup.tmp2.y*setup.tmp2.rhw)*yscale;
  477.         setup.tmp2.u *= setup.tmp2.rhw;
  478.         setup.tmp2.v *= setup.tmp2.rhw;
  479.         setup.tmp2.r *= setup.tmp2.rhw;
  480.         setup.tmp2.g *= setup.tmp2.rhw;
  481.         setup.tmp2.b *= setup.tmp2.rhw;
  482.         setup.tmp2.a *= setup.tmp2.rhw;
  483.  
  484.         // verify clipping
  485.         VDASSERT(setup.tmp0.x >= 0 && setup.tmp0.x <= dst.w);
  486.         VDASSERT(setup.tmp1.x >= 0 && setup.tmp1.x <= dst.w);
  487.         VDASSERT(setup.tmp2.x >= 0 && setup.tmp2.x <= dst.w);
  488.         VDASSERT(setup.tmp0.y >= 0 && setup.tmp0.y <= dst.h);
  489.         VDASSERT(setup.tmp1.y >= 0 && setup.tmp1.y <= dst.h);
  490.         VDASSERT(setup.tmp2.y >= 0 && setup.tmp2.y <= dst.h);
  491.  
  492.         vx0 = &setup.tmp0;
  493.         vx1 = &setup.tmp1;
  494.         vx2 = &setup.tmp2;
  495.  
  496.         const VDTriBltTransformedVertex *pt, *pl, *pr;
  497.  
  498.         // sort points
  499.         if (vx0->y < vx1->y)        // 1 < 2
  500.             if (vx0->y < vx2->y) {    // 1 < 2,3
  501.                 pt = vx0;
  502.                 pr = vx1;
  503.                 pl = vx2;
  504.             } else {                // 3 < 1 < 2
  505.                 pt = vx2;
  506.                 pr = vx0;
  507.                 pl = vx1;
  508.             }
  509.         else                        // 2 < 1
  510.             if (vx1->y < vx2->y) {    // 2 < 1,3
  511.                 pt = vx1;
  512.                 pr = vx2;
  513.                 pl = vx0;
  514.             } else {                // 3 < 2 < 1
  515.                 pt = vx2;
  516.                 pr = vx0;
  517.                 pl = vx1;
  518.             }
  519.  
  520.         setup.pl = pl;
  521.         setup.pt = pt;
  522.         setup.pr = pr;
  523.     }
  524.  
  525.     void RenderTri(VDPixmap& dst, const VDPixmap *const *pSources, int nMipmaps,
  526.                             const VDTriBltTransformedVertex *vx0,
  527.                             const VDTriBltTransformedVertex *vx1,
  528.                             const VDTriBltTransformedVertex *vx2,
  529.                             VDTriBltFilterMode filterMode,
  530.                             float mipMapLODBias)
  531.     {
  532.         VDTriangleSetupInfo setup;
  533.  
  534.         SetupTri(setup, dst, vx0, vx1, vx2, &filterMode);
  535.  
  536.         const VDTriBltTransformedVertex *pt = setup.pt, *pl = setup.pl, *pr = setup.pr;
  537.  
  538.         const float x10 = pl->x - pt->x;
  539.         const float x20 = pr->x - pt->x;
  540.         const float y10 = pl->y - pt->y;
  541.         const float y20 = pr->y - pt->y;
  542.         const float A = x20*y10 - x10*y20;
  543.  
  544.         if (A <= 0.f)
  545.             return;
  546.  
  547.         float invA = 0.f;
  548.         if (A >= 1e-5f)
  549.             invA = 1.0f / A;
  550.  
  551.         float x10_A = x10 * invA;
  552.         float x20_A = x20 * invA;
  553.         float y10_A = y10 * invA;
  554.         float y20_A = y20 * invA;
  555.  
  556.         float u10 = pl->u - pt->u;
  557.         float u20 = pr->u - pt->u;
  558.         float v10 = pl->v - pt->v;
  559.         float v20 = pr->v - pt->v;
  560.         float rhw10 = pl->rhw - pt->rhw;
  561.         float rhw20 = pr->rhw - pt->rhw;
  562.  
  563.         float dudx = u20*y10_A - u10*y20_A;
  564.         float dudy = u10*x20_A - u20*x10_A;
  565.         float dvdx = v20*y10_A - v10*y20_A;
  566.         float dvdy = v10*x20_A - v20*x10_A;
  567.         float drhwdx = rhw20*y10_A - rhw10*y20_A;
  568.         float drhwdy = rhw10*x20_A - rhw20*x10_A;
  569.  
  570.         // Compute edge walking parameters
  571.  
  572.         float dxl1=0, dxr1=0, dul1=0, dvl1=0, drhwl1=0;
  573.         float dxl2=0, dxr2=0, dul2=0, dvl2=0, drhwl2=0;
  574.  
  575.         // Compute left-edge interpolation parameters for first half.
  576.  
  577.         if (pl->y != pt->y) {
  578.             dxl1 = (pl->x - pt->x) / (pl->y - pt->y);
  579.  
  580.             dul1 = dudy + dxl1 * dudx;
  581.             dvl1 = dvdy + dxl1 * dvdx;
  582.             drhwl1 = drhwdy + dxl1 * drhwdx;
  583.         }
  584.  
  585.         // Compute right-edge interpolation parameters for first half.
  586.  
  587.         if (pr->y != pt->y) {
  588.             dxr1 = (pr->x - pt->x) / (pr->y - pt->y);
  589.         }
  590.  
  591.         // Compute third-edge interpolation parameters.
  592.  
  593.         if (pr->y != pl->y) {
  594.             dxl2 = (pr->x - pl->x) / (pr->y - pl->y);
  595.  
  596.             dul2 = dudy + dxl2 * dudx;
  597.             dvl2 = dvdy + dxl2 * dvdx;
  598.             drhwl2 = drhwdy + dxl2 * drhwdx;
  599.  
  600.             dxr2 = dxl2;
  601.         }
  602.  
  603.         // Initialize parameters for first half.
  604.         //
  605.         // We place pixel centers at (x+0.5, y+0.5).
  606.  
  607.         double xl, xr, ul, vl, rhwl, yf;
  608.         int y, y1, y2;
  609.  
  610.         // y_start < y+0.5 to include pixel y.
  611.  
  612.         y = (int)floor(pt->y + 0.5);
  613.         yf = (y+0.5) - pt->y;
  614.  
  615.         xl = pt->x + dxl1 * yf;
  616.         xr = pt->x + dxr1 * yf;
  617.         ul = pt->u + dul1 * yf;
  618.         vl = pt->v + dvl1 * yf;
  619.         rhwl = pt->rhw + drhwl1 * yf;
  620.  
  621.         // Initialize parameters for second half.
  622.  
  623.         double xl2, xr2, ul2, vl2, rhwl2;
  624.  
  625.         if (pl->y > pr->y) {        // Left edge is long side
  626.             dxl2 = dxl1;
  627.             dul2 = dul1;
  628.             dvl2 = dvl1;
  629.             drhwl2 = drhwl1;
  630.  
  631.             y1 = (int)floor(pr->y + 0.5);
  632.             y2 = (int)floor(pl->y + 0.5);
  633.  
  634.             yf = (y1+0.5) - pr->y;
  635.  
  636.             // Step left edge.
  637.  
  638.             xl2 = xl + dxl1 * (y1 - y);
  639.             ul2 = ul + dul1 * (y1 - y);
  640.             vl2 = vl + dvl1 * (y1 - y);
  641.             rhwl2 = rhwl + drhwl1 * (y1 - y);
  642.  
  643.             // Prestep right edge.
  644.  
  645.             xr2 = pr->x + dxr2 * yf;
  646.         } else {                    // Right edge is long side
  647.             dxr2 = dxr1;
  648.  
  649.             y1 = (int)floor(pl->y + 0.5);
  650.             y2 = (int)floor(pr->y + 0.5);
  651.  
  652.             yf = (y1+0.5) - pl->y;
  653.  
  654.             // Prestep left edge.
  655.  
  656.             xl2 = pl->x + dxl2 * yf;
  657.             ul2 = pl->u + dul2 * yf;
  658.             vl2 = pl->v + dvl2 * yf;
  659.             rhwl2 = pl->rhw + drhwl2 * yf;
  660.  
  661.             // Step right edge.
  662.  
  663.             xr2 = xr + dxr1 * (y1 - y);
  664.         }
  665.  
  666.         // rasterize
  667.         const ptrdiff_t dstpitch = dst.pitch;
  668.         uint32 *dstp = (uint32 *)((char *)dst.data + dstpitch * y);
  669.  
  670.         VDTriBltInfo texinfo;
  671.         VDTriBltSpanFunction drawSpan;
  672.         uint32 cpuflags = CPUGetEnabledExtensions();
  673.  
  674.         bool triBlt16 = false;
  675.  
  676.         switch(filterMode) {
  677.         case kTriBltFilterBicubicMipLinear:
  678. #ifdef _M_IX86
  679.             if (cpuflags & CPUF_SUPPORTS_SSE2) {
  680.                 drawSpan = vdasm_triblt_span_bicubic_mip_linear_sse2;
  681.                 triBlt16 = true;
  682.             } else if (cpuflags & CPUF_SUPPORTS_MMX) {
  683.                 drawSpan = vdasm_triblt_span_bicubic_mip_linear_mmx;
  684.                 triBlt16 = true;
  685.             } else
  686. #endif
  687.                 drawSpan = vd_triblt_span_bicubic_mip_linear;
  688.             break;
  689.         case kTriBltFilterTrilinear:
  690. #ifdef _M_IX86
  691.             if (cpuflags & CPUF_SUPPORTS_MMX) {
  692.                 drawSpan = vdasm_triblt_span_trilinear_mmx;
  693.                 triBlt16 = true;
  694.             } else
  695. #endif
  696.                 drawSpan = vd_triblt_span_trilinear;
  697.             break;
  698.         case kTriBltFilterBilinear:
  699. #ifdef _M_IX86
  700.             if (cpuflags & CPUF_SUPPORTS_MMX) {
  701.                 drawSpan = vdasm_triblt_span_bilinear_mmx;
  702.                 triBlt16 = true;
  703.             } else
  704. #endif
  705.                 drawSpan = vd_triblt_span_bilinear;
  706.             break;
  707.         case kTriBltFilterPoint:
  708.             drawSpan = vd_triblt_span_point;
  709.             break;
  710.         }
  711.  
  712.         float rhobase = sqrtf(std::max<float>(dudx*dudx + dvdx*dvdx, dudy*dudy + dvdy*dvdy) * (1.0f / 65536.0f)) * powf(2.0f, mipMapLODBias);
  713.  
  714.         if (triBlt16) {
  715.             ul *= 256.0f;
  716.             vl *= 256.0f;
  717.             ul2 *= 256.0f;
  718.             vl2 *= 256.0f;
  719.             dul1 *= 256.0f;
  720.             dvl1 *= 256.0f;
  721.             dul2 *= 256.0f;
  722.             dvl2 *= 256.0f;
  723.             dudx *= 256.0f;
  724.             dvdx *= 256.0f;
  725.             dudy *= 256.0f;
  726.             dvdy *= 256.0f;
  727.         }
  728.  
  729.         int minx1 = (int)floor(std::min<float>(std::min<float>(pl->x, pr->x), pt->x) + 0.5);
  730.         int maxx2 = (int)floor(std::max<float>(std::max<float>(pl->x, pr->x), pt->x) + 0.5);
  731.  
  732.         uint32 *const spanptr = new uint32[3 * (maxx2 - minx1)];
  733.  
  734.         while(y < y2) {
  735.             if (y == y1) {
  736.                 xl = xl2;
  737.                 xr = xr2;
  738.                 ul = ul2;
  739.                 vl = vl2;
  740.                 rhwl = rhwl2;
  741.                 dxl1 = dxl2;
  742.                 dxr1 = dxr2;
  743.                 dul1 = dul2;
  744.                 dvl1 = dvl2;
  745.                 drhwl1 = drhwl2;
  746.             }
  747.  
  748.             int x1, x2;
  749.             double xf;
  750.             double u, v, rhw;
  751.  
  752.             // x_left must be less than (x+0.5) to include pixel x.
  753.  
  754.             x1        = (int)floor(xl + 0.5);
  755.             x2        = (int)floor(xr + 0.5);
  756.             xf        = (x1+0.5) - xl;
  757.             
  758.             u        = ul + xf * dudx;
  759.             v        = vl + xf * dvdx;
  760.             rhw        = rhwl + xf * drhwdx;
  761.  
  762.             int x = x1;
  763.             uint32 *spanp = spanptr;
  764.  
  765.             float w = 1.0f / (float)rhw;
  766.  
  767.             if (x < x2) {
  768.                 if (filterMode >= kTriBltFilterTrilinear) {
  769.                     do {
  770.                         int utexel = VDRoundToIntFastFullRange(u * w);
  771.                         int vtexel = VDRoundToIntFastFullRange(v * w);
  772.                         union{ float f; sint32 i; } rho = {rhobase * w};
  773.  
  774.                         int lambda = ((rho.i - 0x3F800000) >> (23-8));
  775.                         if (lambda < 0)
  776.                             lambda = 0;
  777.                         if (lambda >= (nMipmaps<<8)-256)
  778.                             lambda = (nMipmaps<<8)-257;
  779.  
  780.                         spanp[0] = utexel;
  781.                         spanp[1] = vtexel;
  782.                         spanp[2] = lambda;
  783.                         spanp += 3;
  784.  
  785.                         u += dudx;
  786.                         v += dvdx;
  787.                         rhw += drhwdx;
  788.  
  789.                         w *= (2.0f - w*(float)rhw);
  790.                     } while(++x < x2);
  791.                 } else {
  792.                     do {
  793.                         int utexel = VDFloorToInt(u * w);
  794.                         int vtexel = VDFloorToInt(v * w);
  795.  
  796.                         spanp[0] = utexel;
  797.                         spanp[1] = vtexel;
  798.                         spanp += 2;
  799.  
  800.                         u += dudx;
  801.                         v += dvdx;
  802.                         rhw += drhwdx;
  803.  
  804.                         w *= (2.0f - w*(float)rhw);
  805.                     } while(++x < x2);
  806.                 }
  807.             }
  808.  
  809.             for(int i=0; i<nMipmaps; ++i) {
  810.                 texinfo.mips[i].mip        = (const uint32 *)pSources[i]->data;
  811.                 texinfo.mips[i].pitch    = pSources[i]->pitch;
  812.                 texinfo.mips[i].uvmul    = (pSources[i]->pitch << 16) + 4;
  813.             }
  814.             texinfo.dst = dstp+x1;
  815.             texinfo.src = spanptr;
  816.             texinfo.width = x2-x1;
  817.  
  818.             if (texinfo.width>0)
  819.                 drawSpan(&texinfo);
  820.  
  821.             dstp = vdptroffset(dstp, dstpitch);
  822.             xl += dxl1;
  823.             xr += dxr1;
  824.             ul += dul1;
  825.             vl += dvl1;
  826.             rhwl += drhwl1;
  827.  
  828.             ++y;
  829.         }
  830.  
  831.         delete[] spanptr;
  832.     }
  833.  
  834.     void FillTri(VDPixmap& dst, uint32 c,
  835.                     const VDTriBltTransformedVertex *vx0,
  836.                     const VDTriBltTransformedVertex *vx1,
  837.                     const VDTriBltTransformedVertex *vx2
  838.                     )
  839.     {
  840.  
  841.         VDTriangleSetupInfo setup;
  842.  
  843.         SetupTri(setup, dst, vx0, vx1, vx2, NULL);
  844.  
  845.         const VDTriBltTransformedVertex *pt = setup.pt, *pl = setup.pl, *pr = setup.pr;
  846.  
  847.         // Compute edge walking parameters
  848.         float dxl1=0, dxr1=0;
  849.         float dxl2=0, dxr2=0;
  850.  
  851.         float x_lt = pl->x - pt->x;
  852.         float x_rt = pr->x - pt->x;
  853.         float x_rl = pr->x - pl->x;
  854.         float y_lt = pl->y - pt->y;
  855.         float y_rt = pr->y - pt->y;
  856.         float y_rl = pr->y - pl->y;
  857.  
  858.         // reject backfaces
  859.         if (x_lt*y_rt >= x_rt*y_lt)
  860.             return;
  861.  
  862.         // Compute left-edge interpolation parameters for first half.
  863.         if (pl->y != pt->y)
  864.             dxl1 = x_lt / y_lt;
  865.  
  866.         // Compute right-edge interpolation parameters for first half.
  867.         if (pr->y != pt->y)
  868.             dxr1 = x_rt / y_rt;
  869.  
  870.         // Compute third-edge interpolation parameters.
  871.         if (pr->y != pl->y) {
  872.             dxl2 = x_rl / y_rl;
  873.  
  874.             dxr2 = dxl2;
  875.         }
  876.  
  877.         // Initialize parameters for first half.
  878.         //
  879.         // We place pixel centers at (x+0.5, y+0.5).
  880.  
  881.         double xl, xr, yf;
  882.         int y, y1, y2;
  883.  
  884.         // y_start < y+0.5 to include pixel y.
  885.  
  886.         y = (int)floor(pt->y + 0.5);
  887.         yf = (y+0.5) - pt->y;
  888.  
  889.         xl = pt->x + dxl1 * yf;
  890.         xr = pt->x + dxr1 * yf;
  891.  
  892.         // Initialize parameters for second half.
  893.         double xl2, xr2;
  894.  
  895.         if (pl->y > pr->y) {        // Left edge is long side
  896.             dxl2 = dxl1;
  897.  
  898.             y1 = (int)floor(pr->y + 0.5);
  899.             y2 = (int)floor(pl->y + 0.5);
  900.  
  901.             yf = (y1+0.5) - pr->y;
  902.  
  903.             // Prestep right edge.
  904.             xr2 = pr->x + dxr2 * yf;
  905.  
  906.             // Step left edge.
  907.             xl2 = xl + dxl1 * (y1 - y);
  908.         } else {                    // Right edge is long side
  909.             dxr2 = dxr1;
  910.  
  911.             y1 = (int)floor(pl->y + 0.5);
  912.             y2 = (int)floor(pr->y + 0.5);
  913.  
  914.             yf = (y1+0.5) - pl->y;
  915.  
  916.             // Prestep left edge.
  917.             xl2 = pl->x + dxl2 * yf;
  918.  
  919.             // Step right edge.
  920.             xr2 = xr + dxr1 * (y1 - y);
  921.         }
  922.  
  923.         // rasterize
  924.         const ptrdiff_t dstpitch = dst.pitch;
  925.         uint32 *dstp = (uint32 *)((char *)dst.data + dstpitch * y);
  926.  
  927.         while(y < y2) {
  928.             if (y == y1) {
  929.                 xl = xl2;
  930.                 xr = xr2;
  931.                 dxl1 = dxl2;
  932.                 dxr1 = dxr2;
  933.             }
  934.  
  935.             int x1, x2;
  936.             double xf;
  937.  
  938.             // x_left must be less than (x+0.5) to include pixel x.
  939.  
  940.             x1        = (int)floor(xl + 0.5);
  941.             x2        = (int)floor(xr + 0.5);
  942.             xf        = (x1+0.5) - xl;
  943.             
  944.             while(x1 < x2)
  945.                 dstp[x1++] = c;
  946.  
  947.             dstp = vdptroffset(dstp, dstpitch);
  948.             xl += dxl1;
  949.             xr += dxr1;
  950.             ++y;
  951.         }
  952.     }
  953.  
  954.     void FillTriGrad(VDPixmap& dst,
  955.                     const VDTriBltTransformedVertex *vx0,
  956.                     const VDTriBltTransformedVertex *vx1,
  957.                     const VDTriBltTransformedVertex *vx2
  958.                     )
  959.     {
  960.  
  961.         VDTriangleSetupInfo setup;
  962.  
  963.         SetupTri(setup, dst, vx0, vx1, vx2, NULL);
  964.  
  965.         const VDTriBltTransformedVertex *pt = setup.pt, *pl = setup.pl, *pr = setup.pr;
  966.         const float x10 = pl->x - pt->x;
  967.         const float x20 = pr->x - pt->x;
  968.         const float y10 = pl->y - pt->y;
  969.         const float y20 = pr->y - pt->y;
  970.         const float A = x20*y10 - x10*y20;
  971.  
  972.         if (A <= 0.f)
  973.             return;
  974.  
  975.         float invA = 0.f;
  976.         if (A >= 1e-5f)
  977.             invA = 1.0f / A;
  978.  
  979.         float x10_A = x10 * invA;
  980.         float x20_A = x20 * invA;
  981.         float y10_A = y10 * invA;
  982.         float y20_A = y20 * invA;
  983.  
  984.         float r10 = pl->r - pt->r;
  985.         float r20 = pr->r - pt->r;
  986.         float g10 = pl->g - pt->g;
  987.         float g20 = pr->g - pt->g;
  988.         float b10 = pl->b - pt->b;
  989.         float b20 = pr->b - pt->b;
  990.         float a10 = pl->a - pt->a;
  991.         float a20 = pr->a - pt->a;
  992.         float rhw10 = pl->rhw - pt->rhw;
  993.         float rhw20 = pr->rhw - pt->rhw;
  994.  
  995.         float drdx = r20*y10_A - r10*y20_A;
  996.         float drdy = r10*x20_A - r20*x10_A;
  997.         float dgdx = g20*y10_A - g10*y20_A;
  998.         float dgdy = g10*x20_A - g20*x10_A;
  999.         float dbdx = b20*y10_A - b10*y20_A;
  1000.         float dbdy = b10*x20_A - b20*x10_A;
  1001.         float dadx = a20*y10_A - a10*y20_A;
  1002.         float dady = a10*x20_A - a20*x10_A;
  1003.         float drhwdx = rhw20*y10_A - rhw10*y20_A;
  1004.         float drhwdy = rhw10*x20_A - rhw20*x10_A;
  1005.  
  1006.         // Compute edge walking parameters
  1007.         float dxl1=0;
  1008.         float drl1=0;
  1009.         float dgl1=0;
  1010.         float dbl1=0;
  1011.         float dal1=0;
  1012.         float drhwl1=0;
  1013.         float dxr1=0;
  1014.         float dxl2=0;
  1015.         float drl2=0;
  1016.         float dgl2=0;
  1017.         float dbl2=0;
  1018.         float dal2=0;
  1019.         float drhwl2=0;
  1020.         float dxr2=0;
  1021.  
  1022.         float x_lt = pl->x - pt->x;
  1023.         float x_rt = pr->x - pt->x;
  1024.         float x_rl = pr->x - pl->x;
  1025.         float y_lt = pl->y - pt->y;
  1026.         float y_rt = pr->y - pt->y;
  1027.         float y_rl = pr->y - pl->y;
  1028.  
  1029.         // Compute left-edge interpolation parameters for first half.
  1030.         if (pl->y != pt->y) {
  1031.             dxl1 = x_lt / y_lt;
  1032.             drl1 = drdy + dxl1 * drdx;
  1033.             dgl1 = dgdy + dxl1 * dgdx;
  1034.             dbl1 = dbdy + dxl1 * dbdx;
  1035.             dal1 = dady + dxl1 * dadx;
  1036.             drhwl1 = drhwdy + dxl1 * drhwdx;
  1037.         }
  1038.  
  1039.         // Compute right-edge interpolation parameters for first half.
  1040.         if (pr->y != pt->y)
  1041.             dxr1 = x_rt / y_rt;
  1042.  
  1043.         // Compute third-edge interpolation parameters.
  1044.         if (pr->y != pl->y) {
  1045.             dxl2 = x_rl / y_rl;
  1046.  
  1047.             drl2 = drdy + dxl2 * drdx;
  1048.             dgl2 = dgdy + dxl2 * dgdx;
  1049.             dbl2 = dbdy + dxl2 * dbdx;
  1050.             dal2 = dady + dxl2 * dadx;
  1051.             drhwl2 = drhwdy + dxl2 * drhwdx;
  1052.  
  1053.             dxr2 = dxl2;
  1054.         }
  1055.  
  1056.         // Initialize parameters for first half.
  1057.         //
  1058.         // We place pixel centers at (x+0.5, y+0.5).
  1059.  
  1060.         double xl, xr, yf;
  1061.         double rl, gl, bl, al, rhwl;
  1062.         double rl2, gl2, bl2, al2, rhwl2;
  1063.         int y, y1, y2;
  1064.  
  1065.         // y_start < y+0.5 to include pixel y.
  1066.  
  1067.         y = (int)floor(pt->y + 0.5);
  1068.         yf = (y+0.5) - pt->y;
  1069.  
  1070.         xl = pt->x + dxl1 * yf;
  1071.         xr = pt->x + dxr1 * yf;
  1072.         rl = pt->r + drl1 * yf;
  1073.         gl = pt->g + dgl1 * yf;
  1074.         bl = pt->b + dbl1 * yf;
  1075.         al = pt->a + dal1 * yf;
  1076.         rhwl = pt->rhw + drhwl1 * yf;
  1077.  
  1078.         // Initialize parameters for second half.
  1079.         double xl2, xr2;
  1080.  
  1081.         if (pl->y > pr->y) {        // Left edge is long side
  1082.             dxl2 = dxl1;
  1083.             drl2 = drl1;
  1084.             dgl2 = dgl1;
  1085.             dbl2 = dbl1;
  1086.             dal2 = dal1;
  1087.             drhwl2 = drhwl1;
  1088.  
  1089.             y1 = (int)floor(pr->y + 0.5);
  1090.             y2 = (int)floor(pl->y + 0.5);
  1091.  
  1092.             yf = (y1+0.5) - pr->y;
  1093.  
  1094.             // Step left edge.
  1095.             xl2 = xl + dxl1 * (y1 - y);
  1096.             rl2 = rl + drl1 * (y1 - y);
  1097.             gl2 = gl + dgl1 * (y1 - y);
  1098.             bl2 = bl + dbl1 * (y1 - y);
  1099.             al2 = al + dal1 * (y1 - y);
  1100.             rhwl2 = rhwl + drhwl1 * (y1 - y);
  1101.  
  1102.             // Prestep right edge.
  1103.             xr2 = pr->x + dxr2 * yf;
  1104.         } else {                    // Right edge is long side
  1105.             dxr2 = dxr1;
  1106.  
  1107.             y1 = (int)floor(pl->y + 0.5);
  1108.             y2 = (int)floor(pr->y + 0.5);
  1109.  
  1110.             yf = (y1+0.5) - pl->y;
  1111.  
  1112.             // Prestep left edge.
  1113.             xl2 = pl->x + dxl2 * yf;
  1114.             rl2 = pl->r + drl2 * yf;
  1115.             gl2 = pl->g + dgl2 * yf;
  1116.             bl2 = pl->b + dbl2 * yf;
  1117.             al2 = pl->a + dal2 * yf;
  1118.             rhwl2 = pl->rhw + drhwl2 * yf;
  1119.  
  1120.             // Step right edge.
  1121.             xr2 = xr + dxr2 * (y1 - y);
  1122.         }
  1123.  
  1124.         // rasterize
  1125.         const ptrdiff_t dstpitch = dst.pitch;
  1126.         char *dstp0 = (char *)dst.data + dstpitch * y;
  1127.  
  1128.         while(y < y2) {
  1129.             if (y == y1) {
  1130.                 xl = xl2;
  1131.                 xr = xr2;
  1132.                 rl = rl2;
  1133.                 gl = gl2;
  1134.                 bl = bl2;
  1135.                 al = al2;
  1136.                 rhwl = rhwl2;
  1137.                 dxl1 = dxl2;
  1138.                 drl1 = drl2;
  1139.                 dgl1 = dgl2;
  1140.                 dbl1 = dbl2;
  1141.                 dal1 = dal2;
  1142.                 drhwl1 = drhwl2;
  1143.                 dxr1 = dxr2;
  1144.             }
  1145.  
  1146.             int x1, x2;
  1147.             double xf;
  1148.             double r, g, b, a, rhw;
  1149.  
  1150.             // x_left must be less than (x+0.5) to include pixel x.
  1151.  
  1152.             x1        = (int)floor(xl + 0.5);
  1153.             x2        = (int)floor(xr + 0.5);
  1154.             xf        = (x1+0.5) - xl;
  1155.             
  1156.             r        = rl + xf * drdx;
  1157.             g        = gl + xf * dgdx;
  1158.             b        = bl + xf * dbdx;
  1159.             a        = al + xf * dadx;
  1160.             rhw        = rhwl + xf * drhwdx;
  1161.  
  1162.             float w = 1.0f / (float)rhw;
  1163.  
  1164.             if (x1 < x2) {
  1165.                 if (dst.format == nsVDPixmap::kPixFormat_XRGB8888) {
  1166.                     uint32 *dstp = (uint32 *)dstp0;
  1167.  
  1168.                     do {
  1169.                         float sr = (float)(r * w);
  1170.                         float sg = (float)(g * w);
  1171.                         float sb = (float)(b * w);
  1172.                         float sa = (float)(a * w);
  1173.  
  1174.                         uint8 ir = VDClampedRoundFixedToUint8Fast(sr);
  1175.                         uint8 ig = VDClampedRoundFixedToUint8Fast(sg);
  1176.                         uint8 ib = VDClampedRoundFixedToUint8Fast(sb);
  1177.                         uint8 ia = VDClampedRoundFixedToUint8Fast(sa);
  1178.  
  1179.                         dstp[x1] = ((uint32)ia << 24) + ((uint32)ir << 16) + ((uint32)ig << 8) + ib;
  1180.  
  1181.                         r += drdx;
  1182.                         g += dgdx;
  1183.                         b += dbdx;
  1184.                         a += dadx;
  1185.                         rhw += drhwdx;
  1186.  
  1187.                         w *= (2.0f - w*(float)rhw);
  1188.                     } while(++x1 < x2);
  1189.                 } else {
  1190.                     uint8 *dstp = (uint8 *)dstp0;
  1191.  
  1192.                     do {
  1193.                         float sg = (float)(g * w);
  1194.  
  1195.                         uint8 ig = VDClampedRoundFixedToUint8Fast(sg);
  1196.  
  1197.                         dstp[x1] = ig;
  1198.  
  1199.                         g += dgdx;
  1200.                         rhw += drhwdx;
  1201.  
  1202.                         w *= (2.0f - w*(float)rhw);
  1203.                     } while(++x1 < x2);
  1204.                 }
  1205.             }
  1206.  
  1207.             dstp0 = vdptroffset(dstp0, dstpitch);
  1208.             xl += dxl1;
  1209.             rl += drl1;
  1210.             gl += dgl1;
  1211.             bl += dbl1;
  1212.             al += dal1;
  1213.             rhwl += drhwl1;
  1214.             xr += dxr1;
  1215.             ++y;
  1216.         }
  1217.     }
  1218.  
  1219.     struct VDTriClipWorkspace {
  1220.         VDTriBltTransformedVertex *vxheapptr[2][19];
  1221.         VDTriBltTransformedVertex vxheap[21];
  1222.     };
  1223.  
  1224.     VDTriBltTransformedVertex **VDClipTriangle(VDTriClipWorkspace& ws,
  1225.                         const VDTriBltTransformedVertex *vx0,
  1226.                         const VDTriBltTransformedVertex *vx1,
  1227.                         const VDTriBltTransformedVertex *vx2,
  1228.                         int orflags) {
  1229.         // Each line segment can intersect all six planes, meaning the maximum bound is
  1230.         // 18 vertices.  Add 3 for the original.
  1231.  
  1232.         VDTriBltTransformedVertex *vxheapnext;
  1233.         VDTriBltTransformedVertex **vxlastheap = ws.vxheapptr[0], **vxnextheap = ws.vxheapptr[1];
  1234.  
  1235.         ws.vxheap[0]    = *vx0;
  1236.         ws.vxheap[1]    = *vx1;
  1237.         ws.vxheap[2]    = *vx2;
  1238.  
  1239.         vxlastheap[0] = &ws.vxheap[0];
  1240.         vxlastheap[1] = &ws.vxheap[1];
  1241.         vxlastheap[2] = &ws.vxheap[2];
  1242.         vxlastheap[3] = NULL;
  1243.  
  1244.         vxheapnext = ws.vxheap + 3;
  1245.  
  1246.         //    Current        Next        Action
  1247.         //    -------        ----        ------
  1248.         //    Unclipped    Unclipped    Copy vertex
  1249.         //    Unclipped    Clipped        Copy vertex and add intersection
  1250.         //    Clipped        Unclipped    Add intersection
  1251.         //    Clipped        Clipped        No action
  1252.  
  1253. #define    DOCLIP(cliptype, _sign_, cliparg)                \
  1254.         if (orflags & k##cliptype) {                    \
  1255.             VDTriBltTransformedVertex **src = vxlastheap;        \
  1256.             VDTriBltTransformedVertex **dst = vxnextheap;        \
  1257.                                                         \
  1258.             while(*src) {                                \
  1259.                 VDTriBltTransformedVertex *cur = *src;            \
  1260.                 VDTriBltTransformedVertex *next = src[1];        \
  1261.                                                         \
  1262.                 if (!next)                                \
  1263.                     next = vxlastheap[0];                \
  1264.                                                         \
  1265.                 if (!(cur->outcode & k##cliptype))    \
  1266.                     *dst++ = cur;                        \
  1267.                                                         \
  1268.                 if ((cur->outcode ^ next->outcode) & k##cliptype) {    \
  1269.                     double alpha = (cur->w _sign_ cur->cliparg) / ((cur->w _sign_ cur->cliparg) - (next->w _sign_ next->cliparg));    \
  1270.                                                         \
  1271.                     if (alpha >= 0.0 && alpha <= 1.0) {    \
  1272.                         vxheapnext->interp(cur, next, (float)alpha);    \
  1273.                         vxheapnext->cliparg = -(_sign_ vxheapnext->w);    \
  1274.                         *dst++ = vxheapnext++;            \
  1275.                     }                                    \
  1276.                 }                                        \
  1277.                 ++src;                                    \
  1278.             }                                            \
  1279.             *dst = NULL;                                \
  1280.             if (dst < vxnextheap+3) return NULL;        \
  1281.             src = vxlastheap; vxlastheap = vxnextheap; vxnextheap = src;    \
  1282.         }
  1283.  
  1284.  
  1285.         DOCLIP(Far, -, z);
  1286.         DOCLIP(Near, +, z);
  1287.         DOCLIP(Bottom, -, y);
  1288.         DOCLIP(Top, +, y);
  1289.         DOCLIP(Right, -, x);
  1290.         DOCLIP(Left, +, x);
  1291.  
  1292. #undef DOCLIP
  1293.  
  1294.         return vxlastheap;
  1295.     }
  1296.  
  1297.     void RenderClippedTri(VDPixmap& dst, const VDPixmap *const *pSources, int nMipmaps,
  1298.                             const VDTriBltTransformedVertex *vx0,
  1299.                             const VDTriBltTransformedVertex *vx1,
  1300.                             const VDTriBltTransformedVertex *vx2,
  1301.                             VDTriBltFilterMode filterMode,
  1302.                             float mipMapLODBias,
  1303.                             int orflags)
  1304.     {
  1305.  
  1306.         VDTriBltTransformedVertex *vxheapnext;
  1307.         VDTriBltTransformedVertex vxheap[21];
  1308.  
  1309.         VDTriBltTransformedVertex *vxheapptr[2][19];
  1310.         VDTriBltTransformedVertex **vxlastheap = vxheapptr[0], **vxnextheap = vxheapptr[1];
  1311.  
  1312.         vxheap[0]    = *vx0;
  1313.         vxheap[1]    = *vx1;
  1314.         vxheap[2]    = *vx2;
  1315.  
  1316.         vxlastheap[0] = &vxheap[0];
  1317.         vxlastheap[1] = &vxheap[1];
  1318.         vxlastheap[2] = &vxheap[2];
  1319.         vxlastheap[3] = NULL;
  1320.  
  1321.         vxheapnext = vxheap + 3;
  1322.  
  1323.         //    Current        Next        Action
  1324.         //    -------        ----        ------
  1325.         //    Unclipped    Unclipped    Copy vertex
  1326.         //    Unclipped    Clipped        Copy vertex and add intersection
  1327.         //    Clipped        Unclipped    Add intersection
  1328.         //    Clipped        Clipped        No action
  1329.  
  1330. #define    DOCLIP(cliptype, _sign_, cliparg)                \
  1331.         if (orflags & k##cliptype) {                    \
  1332.             VDTriBltTransformedVertex **src = vxlastheap;        \
  1333.             VDTriBltTransformedVertex **dst = vxnextheap;        \
  1334.                                                         \
  1335.             while(*src) {                                \
  1336.                 VDTriBltTransformedVertex *cur = *src;            \
  1337.                 VDTriBltTransformedVertex *next = src[1];        \
  1338.                                                         \
  1339.                 if (!next)                                \
  1340.                     next = vxlastheap[0];                \
  1341.                                                         \
  1342.                 if (!(cur->outcode & k##cliptype))    \
  1343.                     *dst++ = cur;                        \
  1344.                                                         \
  1345.                 if ((cur->outcode ^ next->outcode) & k##cliptype) {    \
  1346.                     double alpha = (cur->w _sign_ cur->cliparg) / ((cur->w _sign_ cur->cliparg) - (next->w _sign_ next->cliparg));    \
  1347.                                                         \
  1348.                     if (alpha >= 0.0 && alpha <= 1.0) {    \
  1349.                         vxheapnext->interp(cur, next, (float)alpha);    \
  1350.                         vxheapnext->cliparg = -(_sign_ vxheapnext->w);    \
  1351.                         *dst++ = vxheapnext++;            \
  1352.                     }                                    \
  1353.                 }                                        \
  1354.                 ++src;                                    \
  1355.             }                                            \
  1356.             *dst = NULL;                                \
  1357.             if (dst < vxnextheap+3) return;                \
  1358.             src = vxlastheap; vxlastheap = vxnextheap; vxnextheap = src;    \
  1359.         }
  1360.  
  1361.  
  1362.         DOCLIP(Far, -, z);
  1363.         DOCLIP(Near, +, z);
  1364.         DOCLIP(Bottom, -, y);
  1365.         DOCLIP(Top, +, y);
  1366.         DOCLIP(Right, -, x);
  1367.         DOCLIP(Left, +, x);
  1368.  
  1369. #undef DOCLIP
  1370.  
  1371.         VDTriBltTransformedVertex **src = vxlastheap+1;
  1372.  
  1373.         while(src[1]) {
  1374.             RenderTri(dst, pSources, nMipmaps, vxlastheap[0], src[0], src[1], filterMode, mipMapLODBias);
  1375.             ++src;
  1376.         }
  1377.     }
  1378.  
  1379. }
  1380.  
  1381. bool VDPixmapTriFill(VDPixmap& dst, const uint32 c, const VDTriBltVertex *pVertices, int nVertices, const int *pIndices, int nIndices, const float pTransform[16]) {
  1382.     if (dst.format != nsVDPixmap::kPixFormat_XRGB8888)
  1383.         return false;
  1384.  
  1385.     static const float xf_ident[16]={1.f,0.f,0.f,0.f,0.f,1.f,0.f,0.f,0.f,0.f,1.f,0.f,0.f,0.f,0.f,1.f};
  1386.     vdfastvector<VDTriBltTransformedVertex>    xverts(nVertices);
  1387.  
  1388.     if (!pTransform)
  1389.         pTransform = xf_ident;
  1390.  
  1391.     TransformVerts(xverts.data(), pVertices, nVertices, pTransform);
  1392.  
  1393.     const VDTriBltTransformedVertex *xsrc = xverts.data();
  1394.  
  1395.     VDTriClipWorkspace clipws;
  1396.  
  1397.     while(nIndices >= 3) {
  1398.         const int idx0 = pIndices[0];
  1399.         const int idx1 = pIndices[1];
  1400.         const int idx2 = pIndices[2];
  1401.         const VDTriBltTransformedVertex *xv0 = &xsrc[idx0];
  1402.         const VDTriBltTransformedVertex *xv1 = &xsrc[idx1];
  1403.         const VDTriBltTransformedVertex *xv2 = &xsrc[idx2];
  1404.         const int kode0 = xv0->outcode;
  1405.         const int kode1 = xv1->outcode;
  1406.         const int kode2 = xv2->outcode;
  1407.  
  1408.         if (!(kode0 & kode1 & kode2)) {
  1409.             if (int orflags = kode0 | kode1 | kode2) {
  1410.                 VDTriBltTransformedVertex **src = VDClipTriangle(clipws, xv0, xv1, xv2, orflags);
  1411.  
  1412.                 if (src) {
  1413.                     VDTriBltTransformedVertex *src0 = *src++;
  1414.  
  1415.                     // fan out triangles
  1416.                     while(src[1]) {
  1417.                         FillTri(dst, c, src0, src[0], src[1]);
  1418.                         ++src;
  1419.                     }
  1420.                 }
  1421.             } else
  1422.                 FillTri(dst, c, xv0, xv1, xv2);
  1423.         }
  1424.  
  1425.         pIndices += 3;
  1426.         nIndices -= 3;
  1427.     }
  1428.  
  1429.     return true;
  1430. }
  1431.  
  1432. bool VDPixmapTriFill(VDPixmap& dst, const VDTriColorVertex *pVertices, int nVertices, const int *pIndices, int nIndices, const float pTransform[16]) {
  1433.     VDPixmap pxY;
  1434.     VDPixmap pxCb;
  1435.     VDPixmap pxCr;
  1436.     bool ycbcr = false;
  1437.     float ycbcr_xoffset = 0;
  1438.  
  1439.     switch(dst.format) {
  1440.     case nsVDPixmap::kPixFormat_XRGB8888:
  1441.     case nsVDPixmap::kPixFormat_Y8:
  1442.         break;
  1443.     case nsVDPixmap::kPixFormat_YUV444_Planar:
  1444.     case nsVDPixmap::kPixFormat_YUV422_Planar:
  1445.     case nsVDPixmap::kPixFormat_YUV420_Planar:
  1446.     case nsVDPixmap::kPixFormat_YUV410_Planar:
  1447.         pxY.format = nsVDPixmap::kPixFormat_Y8;
  1448.         pxY.data = dst.data;
  1449.         pxY.pitch = dst.pitch;
  1450.         pxY.w = dst.w;
  1451.         pxY.h = dst.h;
  1452.  
  1453.         pxCb.format = nsVDPixmap::kPixFormat_Y8;
  1454.         pxCb.data = dst.data2;
  1455.         pxCb.pitch = dst.pitch2;
  1456.         pxCb.h = dst.h;
  1457.  
  1458.         pxCr.format = nsVDPixmap::kPixFormat_Y8;
  1459.         pxCr.data = dst.data3;
  1460.         pxCr.pitch = dst.pitch3;
  1461.         pxCr.h = dst.h;
  1462.  
  1463.         if (dst.format == nsVDPixmap::kPixFormat_YUV410_Planar) {
  1464.             pxCr.w = pxCb.w = dst.w >> 2;
  1465.             pxCr.h = pxCb.h = dst.h >> 2;
  1466.             ycbcr_xoffset = 0.75f / (float)pxCr.w;
  1467.         } else if (dst.format == nsVDPixmap::kPixFormat_YUV420_Planar) {
  1468.             pxCr.w = pxCb.w = dst.w >> 1;
  1469.             pxCr.h = pxCb.h = dst.h >> 1;
  1470.             ycbcr_xoffset = 0.5f / (float)pxCr.w;
  1471.         } else if (dst.format == nsVDPixmap::kPixFormat_YUV422_Planar) {
  1472.             pxCr.w = pxCb.w = dst.w >> 1;
  1473.             ycbcr_xoffset = 0.5f / (float)pxCr.w;
  1474.         } else if (dst.format == nsVDPixmap::kPixFormat_YUV444_Planar) {
  1475.             pxCr.w = pxCb.w = dst.w;
  1476.             ycbcr_xoffset = 0.0f;
  1477.         }
  1478.  
  1479.         ycbcr = true;
  1480.         break;
  1481.     default:
  1482.         return false;
  1483.     }
  1484.  
  1485.     VDTriBltTransformedVertex fastxverts[64];
  1486.     vdfastvector<VDTriBltTransformedVertex>    xverts;
  1487.  
  1488.     VDTriBltTransformedVertex *xsrc;
  1489.     if (nVertices <= 64) {
  1490.         xsrc = fastxverts;
  1491.     } else {
  1492.         xverts.resize(nVertices);
  1493.         xsrc = xverts.data();
  1494.     }
  1495.  
  1496.     static const float xf_ident[16]={1.f,0.f,0.f,0.f,0.f,1.f,0.f,0.f,0.f,0.f,1.f,0.f,0.f,0.f,0.f,1.f};
  1497.     if (!pTransform)
  1498.         pTransform = xf_ident;
  1499.  
  1500.     VDTriClipWorkspace clipws;
  1501.     for(int plane=0; plane<(ycbcr?3:1); ++plane) {
  1502.         VDPixmap& pxPlane = ycbcr ? plane == 0 ? pxY : plane == 1 ? pxCb : pxCr : dst;
  1503.  
  1504.         if (ycbcr && plane) {
  1505.             float xf_ycbcr[16];
  1506.             memcpy(xf_ycbcr, pTransform, sizeof(float) * 16);
  1507.  
  1508.             // translate in x by ycbcr_xoffset
  1509.             xf_ycbcr[0] += xf_ycbcr[12]*ycbcr_xoffset;
  1510.             xf_ycbcr[1] += xf_ycbcr[13]*ycbcr_xoffset;
  1511.             xf_ycbcr[2] += xf_ycbcr[14]*ycbcr_xoffset;
  1512.             xf_ycbcr[3] += xf_ycbcr[15]*ycbcr_xoffset;
  1513.  
  1514.             TransformVerts(xsrc, pVertices, nVertices, xf_ycbcr);
  1515.  
  1516.             switch(plane) {
  1517.                 case 1:
  1518.                     for(int i=0; i<nVertices; ++i)
  1519.                         xsrc[i].g = xsrc[i].b;
  1520.                     break;
  1521.                 case 2:
  1522.                     for(int i=0; i<nVertices; ++i)
  1523.                         xsrc[i].g = xsrc[i].r;
  1524.                     break;
  1525.             }
  1526.         } else {
  1527.             TransformVerts(xsrc, pVertices, nVertices, pTransform);
  1528.         }
  1529.  
  1530.         const int *nextIndex = pIndices;
  1531.         int indicesLeft = nIndices;
  1532.         while(indicesLeft >= 3) {
  1533.             const int idx0 = nextIndex[0];
  1534.             const int idx1 = nextIndex[1];
  1535.             const int idx2 = nextIndex[2];
  1536.             const VDTriBltTransformedVertex *xv0 = &xsrc[idx0];
  1537.             const VDTriBltTransformedVertex *xv1 = &xsrc[idx1];
  1538.             const VDTriBltTransformedVertex *xv2 = &xsrc[idx2];
  1539.             const int kode0 = xv0->outcode;
  1540.             const int kode1 = xv1->outcode;
  1541.             const int kode2 = xv2->outcode;
  1542.  
  1543.             if (!(kode0 & kode1 & kode2)) {
  1544.                 if (int orflags = kode0 | kode1 | kode2) {
  1545.                     VDTriBltTransformedVertex **src = VDClipTriangle(clipws, xv0, xv1, xv2, orflags);
  1546.  
  1547.                     if (src) {
  1548.                         VDTriBltTransformedVertex *src0 = *src++;
  1549.  
  1550.                         // fan out triangles
  1551.                         while(src[1]) {
  1552.                             FillTriGrad(pxPlane, src0, src[0], src[1]);
  1553.                             ++src;
  1554.                         }
  1555.                     }
  1556.                 } else {
  1557.                     FillTriGrad(pxPlane, xv0, xv1, xv2);
  1558.                 }
  1559.             }
  1560.  
  1561.             nextIndex += 3;
  1562.             indicesLeft -= 3;
  1563.         }
  1564.     }
  1565.  
  1566.     return true;
  1567. }
  1568.  
  1569. bool VDPixmapTriBlt(VDPixmap& dst, const VDPixmap *const *pSources, int nMipmaps,
  1570.                     const VDTriBltVertex *pVertices, int nVertices,
  1571.                     const int *pIndices, int nIndices,
  1572.                     VDTriBltFilterMode filterMode,
  1573.                     float mipMapLODBias,
  1574.                     const float pTransform[16])
  1575. {
  1576.     if (dst.format != nsVDPixmap::kPixFormat_XRGB8888)
  1577.         return false;
  1578.  
  1579.     static const float xf_ident[16]={1.f,0.f,0.f,0.f,0.f,1.f,0.f,0.f,0.f,0.f,1.f,0.f,0.f,0.f,0.f,1.f};
  1580.     vdfastvector<VDTriBltTransformedVertex>    xverts(nVertices);
  1581.  
  1582.     if (!pTransform)
  1583.         pTransform = xf_ident;
  1584.  
  1585.     TransformVerts(xverts.data(), pVertices, nVertices, pTransform);
  1586.  
  1587.     const VDTriBltTransformedVertex *xsrc = xverts.data();
  1588.  
  1589.     VDTriClipWorkspace clipws;
  1590.  
  1591.     while(nIndices >= 3) {
  1592.         const int idx0 = pIndices[0];
  1593.         const int idx1 = pIndices[1];
  1594.         const int idx2 = pIndices[2];
  1595.         const VDTriBltTransformedVertex *xv0 = &xsrc[idx0];
  1596.         const VDTriBltTransformedVertex *xv1 = &xsrc[idx1];
  1597.         const VDTriBltTransformedVertex *xv2 = &xsrc[idx2];
  1598.         const int kode0 = xv0->outcode;
  1599.         const int kode1 = xv1->outcode;
  1600.         const int kode2 = xv2->outcode;
  1601.  
  1602.         if (!(kode0 & kode1 & kode2)) {
  1603.             if (int orflags = kode0 | kode1 | kode2) {
  1604.                 VDTriBltTransformedVertex **src = VDClipTriangle(clipws, xv0, xv1, xv2, orflags);
  1605.  
  1606.                 if (src) {
  1607.                     VDTriBltTransformedVertex *src0 = *src++;
  1608.  
  1609.                     // fan out triangles
  1610.                     while(src[1]) {
  1611.                         RenderTri(dst, pSources, nMipmaps, src0, src[0], src[1], filterMode, mipMapLODBias);
  1612.                         ++src;
  1613.                     }
  1614.                 }
  1615.             } else
  1616.                 RenderTri(dst, pSources, nMipmaps, xv0, xv1, xv2, filterMode, mipMapLODBias);
  1617.         }
  1618.  
  1619.         pIndices += 3;
  1620.         nIndices -= 3;
  1621.     }
  1622.  
  1623.     return true;
  1624. }
  1625.  
  1626. ///////////////////////////////////////////////////////////////////////////
  1627.  
  1628. void VDPixmapSetTextureBorders(VDPixmap& px, bool wrap) {
  1629.     const int w = px.w;
  1630.     const int h = px.h;
  1631.  
  1632.     VDPixmapBlt(px, 0,   1,   px, wrap ? w-2 : 1, 1,              1, h-2);
  1633.     VDPixmapBlt(px, w-1, 1,   px, wrap ? 1 : w-2, 1,              1, h-2);
  1634.  
  1635.     VDPixmapBlt(px, 0,   0,   px, 0,              wrap ? h-2 : 1, w, 1);
  1636.     VDPixmapBlt(px, 0,   h-1, px, 0,              wrap ? 1 : h-2, w, 1);
  1637. }
  1638.  
  1639. void VDPixmapSetTextureBordersCubic(VDPixmap& px) {
  1640.     const int w = px.w;
  1641.     const int h = px.h;
  1642.  
  1643.     VDPixmapBlt(px, 0,   1, px, 2, 1, 1, h-2);
  1644.     VDPixmapBlt(px, 1,   1, px, 2, 1, 1, h-2);
  1645.     VDPixmapBlt(px, w-2, 1, px, w-3, 1, 1, h-2);
  1646.     VDPixmapBlt(px, w-1, 1, px, w-3, 1, 1, h-2);
  1647.  
  1648.     VDPixmapBlt(px, 0, 0,   px, 0, 2, w, 1);
  1649.     VDPixmapBlt(px, 0, 1,   px, 0, 2, w, 1);
  1650.     VDPixmapBlt(px, 0, h-2, px, 0, h-3, w, 1);
  1651.     VDPixmapBlt(px, 0, h-1, px, 0, h-3, w, 1);
  1652. }
  1653.  
  1654. ///////////////////////////////////////////////////////////////////////////
  1655.  
  1656. VDPixmapTextureMipmapChain::VDPixmapTextureMipmapChain(const VDPixmap& src, bool wrap, bool cubic, int maxlevels) {
  1657.     int w = src.w;
  1658.     int h = src.h;
  1659.     int mipcount = 0;
  1660.  
  1661.     while((w>1 || h>1) && maxlevels--) {
  1662.         ++mipcount;
  1663.         w >>= 1;
  1664.         h >>= 1;
  1665.     }
  1666.  
  1667.     mBuffers.resize(mipcount);
  1668.     mMipMaps.resize(mipcount);
  1669.  
  1670.     vdautoptr<IVDPixmapResampler> r(VDCreatePixmapResampler());
  1671.     r->SetFilters(IVDPixmapResampler::kFilterLinear, IVDPixmapResampler::kFilterLinear, false);
  1672.  
  1673.     float fw = (float)src.w;
  1674.     float fh = (float)src.h;
  1675.     for(int mip=0; mip<mipcount; ++mip) {
  1676.         const int mipw = VDCeilToInt(fw);
  1677.         const int miph = VDCeilToInt(fh);
  1678.  
  1679.         mMipMaps[mip] = &mBuffers[mip];
  1680.  
  1681.         if (cubic) {
  1682.             mBuffers[mip].init(mipw+4, miph+4, nsVDPixmap::kPixFormat_XRGB8888);
  1683.  
  1684.             if (!mip) {
  1685.                 VDPixmapBlt(mBuffers[0], 2, 2, src, 0, 0, src.w, src.h);
  1686.                 VDPixmapSetTextureBordersCubic(mBuffers[0]);
  1687.             } else {
  1688.                 const VDPixmap& curmip = mBuffers[mip];
  1689.                 const VDPixmap& prevmip = mBuffers[mip-1];
  1690.  
  1691.                 vdrect32f rdst( 0.0f,  0.0f,      (float)curmip.w       ,      (float)curmip.h       );
  1692.                 vdrect32f rsrc(-2.0f, -2.0f, 2.0f*(float)curmip.w - 2.0f, 2.0f*(float)curmip.h - 2.0f);
  1693.                 r->Init(rdst, curmip.w, curmip.h, curmip.format, rsrc, prevmip.w, prevmip.h, prevmip.format);
  1694.                 r->Process(curmip, prevmip);
  1695.             }
  1696.         } else {
  1697.             mBuffers[mip].init(mipw+2, miph+2, nsVDPixmap::kPixFormat_XRGB8888);
  1698.  
  1699.             if (!mip) {
  1700.                 VDPixmapBlt(mBuffers[0], 1, 1, src, 0, 0, src.w, src.h);
  1701.                 VDPixmapSetTextureBorders(mBuffers[0], wrap);
  1702.             } else {
  1703.                 const VDPixmap& curmip = mBuffers[mip];
  1704.                 const VDPixmap& prevmip = mBuffers[mip-1];
  1705.  
  1706.                 vdrect32f rdst( 0.0f,  0.0f,      (float)curmip.w       ,      (float)curmip.h       );
  1707.                 vdrect32f rsrc(-1.0f, -1.0f, 2.0f*(float)curmip.w - 1.0f, 2.0f*(float)curmip.h - 1.0f);
  1708.                 r->Init(rdst, curmip.w, curmip.h, curmip.format, rsrc, prevmip.w, prevmip.h, prevmip.format);
  1709.                 r->Process(curmip, prevmip);
  1710.             }
  1711.         }
  1712.  
  1713.         fw *= 0.5f;
  1714.         fh *= 0.5f;
  1715.     }
  1716. }
  1717.  
  1718.