This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Internal compiler error 191


On 29 Mar 1999, Alexandre Oliva wrote:

> As per instructions in the FAQ, you should have posted the
> preprocessed source code too.  Please do :-)

Oops.  Sorry about that.  The file soft_g3d.ii has been attached.

	-Michael

# 0 "soft_g3d.cpp"
#define __BASE_FILE__ "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
#define __VERSION__ "egcs-2.91.66 19990314 (egcs-1.1.2 release)"
# 0 "soft_g3d.cpp"
#define __SIZE_TYPE__ unsigned int
# 0 "soft_g3d.cpp"
#define __PTRDIFF_TYPE__ int
# 0 "soft_g3d.cpp"
#define __WCHAR_TYPE__ __wchar_t
# 0 "soft_g3d.cpp"
#define __DATE__ "Mar 26 1999"
# 0 "soft_g3d.cpp"
#define __TIME__ "22:40:08"
# 0 "soft_g3d.cpp"
#define __STDC__ 1
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 0 "soft_g3d.cpp"
# 1 "soft_g3d.cpp"
 

















# 1 "/usr/lib/gcc-lib/i686-redhat-linux/egcs-2.91.66/include/stdarg.h" 1 3
 







#define _STDARG_H
#define _ANSI_STDARG_H_




















































 


#define __GNUC_VA_LIST



typedef void *__gnuc_va_list;



 



 






#define __va_rounded_size(TYPE) (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))



#define va_start(AP, LASTARG) (AP = ((__gnuc_va_list) __builtin_next_arg (LASTARG)))



void va_end (__gnuc_va_list);		 
#define va_end(AP)	((void)0)

 



 
#define va_arg(AP, TYPE)	(AP = (__gnuc_va_list) ((char *) (AP) + __va_rounded_size (TYPE)),	*((TYPE *) (void *) ((char *) (AP) - __va_rounded_size (TYPE))))











 
#define __va_copy(dest, src) (dest) = (src)





















 
 













# 168 "/usr/lib/gcc-lib/i686-redhat-linux/egcs-2.91.66/include/stdarg.h" 3


 




 

 

 

typedef __gnuc_va_list va_list;




#define _VA_LIST_


#define _VA_LIST


#define _VA_LIST_DEFINED


#define _VA_LIST_T_H










# 19 "soft_g3d.cpp" 2























 
bool csGraphics3DSoftware::do_lighting = true;
 
bool csGraphics3DSoftware::do_transp = true;
 
bool csGraphics3DSoftware::do_textured = true;
 
bool csGraphics3DSoftware::do_light_frust = false;
 
bool csGraphics3DSoftware::do_debug = false;
 
int csGraphics3DSoftware::do_interlaced = -1;
bool csGraphics3DSoftware::ilace_fastmove = false;
 
bool csGraphics3DSoftware::do_texel_filt = false;
 
bool csGraphics3DSoftware::do_mmx = true;

 

IMPLEMENT_UNKNOWN (csGraphics3DSoftware)

BEGIN_INTERFACE_TABLE (csGraphics3DSoftware)
    IMPLEMENTS_INTERFACE (IGraphics3D)



    IMPLEMENTS_INTERFACE (IHaloRasterizer)

    IMPLEMENTS_COMPOSITE_INTERFACE_EX (IConfig, XConfig3DSoft)
END_INTERFACE_TABLE ()


char* get_software_2d_driver ()
{
  if (getenv ("GGI_DISPLAY"))
    return SOFTWARE_2D_DRIVER_GGI;
  else if (getenv ("DISPLAY"))
    return SOFTWARE_2D_DRIVER_XLIB;
  else
    return SOFTWARE_2D_DRIVER_SVGA;
}
# 93 "soft_g3d.cpp"


csGraphics3DSoftware::csGraphics3DSoftware (ISystem* piSystem) : m_piG2D(NULL)
{
  HRESULT hRes;
  CLSID clsid2dDriver;
  char *sz2DDriver = SOFTWARE_2D_DRIVER;	 
  IGraphics2DFactory* piFactory = NULL;
  tcache = NULL;
  txtmgr = NULL;
  
  m_piSystem = piSystem;

  hRes = csCLSIDFromProgID( &sz2DDriver, &clsid2dDriver );

  if (FAILED(hRes))
  {	  
    SysPrintf(MSG_FATAL_ERROR, "Error! 2D Graphics DLL with ProgID \"%s\" not found on this system.", sz2DDriver);
    exit(0);
  }

  hRes = csCoGetClassObject( clsid2dDriver, CLSCTX_INPROC_SERVER, NULL, (REFIID)IID_IGraphics2DFactory, (void**)&piFactory );
  if (FAILED(hRes))
  {
    SysPrintf(MSG_FATAL_ERROR, "Error! Couldn't create 2D graphics driver instance.");
    exit(0);
  }

  hRes = piFactory->CreateInstance( (REFIID)IID_IGraphics2D, m_piSystem, (void**)&m_piG2D );
  if (FAILED(hRes))
  {
    SysPrintf(MSG_FATAL_ERROR, "Error! Couldn't create 2D graphics driver instance.");
    exit(0);
  }

  FINAL_RELEASE( piFactory );

  CHK (txtmgr = new csTextureManagerSoftware (m_piSystem, m_piG2D));

  zdist_mipmap1 = 12;
  zdist_mipmap2 = 24;
  zdist_mipmap3 = 40;
}

STDMETHODIMP csGraphics3DSoftware::Initialize ()
{
  m_piG2D->Initialize ();
  txtmgr->InitSystem ();

  z_buffer = NULL;
  z_buf_mode = ZBuf_None;

  width = height = -1;

  rstate_alphablend = true;
  rstate_flat = false;
  rstate_mipmap = 0;
  rstate_edges = false;

  fog_buffers = NULL;
  line_table = NULL;
  return S_OK;
}

STDMETHODIMP csGraphics3DSoftware::Open (char *Title)
{
  DrawMode = 0;

  IGraphicsInfo* piGI = NULL;

  VERIFY_SUCCESS( m_piG2D->QueryInterface((IID&)IID_IGraphicsInfo, (void**)&piGI) );

  if (FAILED(m_piG2D->Open (Title)))
  {
      SysPrintf (MSG_FATAL_ERROR, "Error opening Graphics2D context.");
      FINAL_RELEASE( piGI );
       
      width = height = -1;

      return E_UNEXPECTED;
  }
  
  int nWidth, nHeight;
  bool bFullScreen;

  piGI->GetWidth(nWidth);
  piGI->GetHeight(nHeight);
  piGI->GetIsFullScreen(bFullScreen);

  width = nWidth;
  height = nHeight;
  width2 = nWidth/2;
  height2 = nHeight/2;
  SetDimensions (width, height);

  SysPrintf(MSG_INITIALIZATION, "Using %s mode at resolution %dx%d.\n",
            bFullScreen ? "full screen" : "windowed", nWidth, nHeight);
  
  csPixelFormat pfmt;
  piGI->GetPixelFormat (&pfmt);
  int gi_pixelbytes = pfmt.PixelBytes;

  if (gi_pixelbytes == 4)
  {
    SysPrintf (MSG_INITIALIZATION, "Using truecolor mode with %d bytes per pixel and %d:%d:%d RGB mode.\n",
          gi_pixelbytes, pfmt.RedBits, pfmt.GreenBits, pfmt.BlueBits);

    CHK (tcache = new TextureCache32 (&pfmt));
    pixel_shift = 2;
  }
  else if (gi_pixelbytes == 2)
  {
    SysPrintf (MSG_INITIALIZATION, "Using truecolor mode with %d bytes per pixel and %d:%d:%d RGB mode.\n",
          gi_pixelbytes, pfmt.RedBits, pfmt.GreenBits, pfmt.BlueBits);

    CHK (tcache = new TextureCache16 (&pfmt));
    pixel_shift = 1;
  }
  else
  {
    SysPrintf (MSG_INITIALIZATION, "Using palette mode with 1 byte per pixel (256 colors).\n");
    CHK (tcache = new TextureCache (&pfmt));
    pixel_shift = 0;
  }
  tcache->set_cache_size (-1);
  








 
  FINAL_RELEASE( piGI );
  return S_OK;
}

STDMETHODIMP csGraphics3DSoftware::Close()
{
  CHK (delete tcache); tcache = NULL;

  if ((width == height) && (width == -1))
    return S_OK;
  HRESULT rc = m_piG2D->Close();
  width = height = -1;
  return rc;
}

csGraphics3DSoftware::~csGraphics3DSoftware ()
{
  Close ();
  CHK (delete [] z_buffer);
  FINAL_RELEASE (m_piG2D);

  while (fog_buffers)
  {
    FogBuffer* n = fog_buffers->next;
    CHK (delete fog_buffers);
    fog_buffers = n;
  }

  CHK (delete [] line_table);
  CHK (delete txtmgr);
}

STDMETHODIMP csGraphics3DSoftware::SetDimensions (int width, int height)
{
  csGraphics3DSoftware::width = width;
  csGraphics3DSoftware::height = height;
  csGraphics3DSoftware::width2 = width/2;
  csGraphics3DSoftware::height2 = height/2;

  CHK (delete [] z_buffer);
  CHK (z_buffer = new unsigned long [width*height]);
  z_buf_size = sizeof (unsigned long)*width*height;

  CHK (delete [] line_table);
  CHK (line_table = new UByte* [height+1]);

  return S_OK;
}

STDMETHODIMP csGraphics3DSoftware::BeginDraw (int DrawFlags)
{
   

   
  if ((DrawFlags & (CSDRAW_2DGRAPHICS | CSDRAW_3DGRAPHICS))
   && (!(DrawMode & (CSDRAW_2DGRAPHICS | CSDRAW_3DGRAPHICS))))
  {
    if (FAILED (m_piG2D->BeginDraw()))
      return E_UNEXPECTED;
  }

  if (DrawFlags & CSDRAW_CLEARZBUFFER)
    memset (z_buffer, 0, z_buf_size);
  
  if (DrawFlags & CSDRAW_CLEARSCREEN)
    m_piG2D->Clear (0);

  if (DrawFlags & CSDRAW_3DGRAPHICS)
  {
     
    int i;
    for (i = 0 ; i < height ; i++)
      m_piG2D->GetPixelAt (0, i, &line_table[i]);
  }
  
  DrawMode = DrawFlags;
  
  return S_OK;
}

STDMETHODIMP csGraphics3DSoftware::FinishDraw ()
{
   

  if (DrawMode & (CSDRAW_2DGRAPHICS | CSDRAW_3DGRAPHICS))
  {
    m_piG2D->FinishDraw ();
  }
  DrawMode = 0;
  return S_OK;
}

STDMETHODIMP csGraphics3DSoftware::Print (csRect *area)
{
  m_piG2D->Print (area);
  if (do_interlaced != -1)
    do_interlaced ^= 1;
  return S_OK;
}

STDMETHODIMP csGraphics3DSoftware::SetZBufMode (ZBufMode mode)
{
  z_buf_mode = mode;
  return S_OK;
}

#define SMALL_D 0.01

 








#define VERTEX_NEAR_THRESHOLD   0.001

 


struct
{
  int step1, shift1;
  int step2, shift2;
  int step3, shift3;
  int step4, shift4;
} inter_modes[4] =
{
  { 128, 7, 64, 6, 32, 5, 16, 4 },       
  { 32, 5, 32, 5, 32, 5, 32, 5 },        
  { 16, 4, 16, 4, 16, 4, 16, 4 },        
  { 8, 3, 8, 3, 8, 3, 8, 3 }       	 
};

STDMETHODIMP csGraphics3DSoftware::DrawPolygon (G3DPolygon& poly)
{
  int i;
  float P1, P2, P3, P4;
  float Q1, Q2, Q3, Q4;
  int max_i, min_i;
  float max_y, min_y;
  float min_z;
  void (*dscan) (int len, unsigned char* d, unsigned long* z_buf,
    float inv_z, float u_div_z, float v_div_z);
  unsigned char *d;
  unsigned long *z_buf;
  
  IGraphicsInfo* piGI = NULL;
  int gi_pixelbytes;
  float inv_aspect = poly.inv_aspect;

  if (poly.num < 3) return S_FALSE;

   
   
  VERIFY_SUCCESS (m_piG2D->QueryInterface ((REFIID)IID_IGraphicsInfo, (void**)&piGI));
  piGI->GetPixelBytes (gi_pixelbytes);
  csPixelFormat pfmt;
  piGI->GetPixelFormat (&pfmt);
  FINAL_RELEASE (piGI);
  
   
   
  float Ac, Bc, Cc, Dc, inv_Dc;
  Ac = poly.normal.A;
  Bc = poly.normal.B;
  Cc = poly.normal.C;
  Dc = poly.normal.D;

  float M, N, O;
  if (ABS (Dc) < 0.01 ) Dc = - 0.01 ;
  if (ABS (Dc) < 0.01 )
  {

    ComVector3 vcam_0;
    poly.polygon->GetCameraVector (0, &vcam_0);

     
     
     
     
    M = 0;
    N = 0;
     
     
    O = 1/vcam_0.z;
  }
  else
  {
    inv_Dc = 1/Dc;
    M = -Ac*inv_Dc*inv_aspect;
    N = -Bc*inv_Dc*inv_aspect;
    O = -Cc*inv_Dc;
  }

   
   
   
   
  min_i = max_i = 0;
  min_y = max_y = poly.vertices[0].sy;
  min_z = M * (poly.vertices[0].sx - width2)
        + N * (poly.vertices[0].sy - height2) + O;
   
  int num_vertices = 1;
  for (i = 1 ; i < poly.num ; i++)
  {
    if (poly.vertices[i].sy > max_y)
    {
      max_y = poly.vertices[i].sy;
      max_i = i;
    }
    else if (poly.vertices[i].sy < min_y)
    {
      min_y = poly.vertices[i].sy;
      min_i = i;
    }
    float inv_z = M * (poly.vertices[i].sx - width2)
                + N * (poly.vertices[i].sy - height2) + O;
    if (inv_z > min_z) min_z = inv_z;
     
     
    if ((fabs (poly.vertices [i].sx - poly.vertices [i - 1].sx)
       + fabs (poly.vertices [i].sy - poly.vertices [i - 1].sy)) > 0.001 )
      num_vertices++;
  }

   
  if (num_vertices < 3) return S_FALSE;

   
  min_z = 1/min_z;

   
  int mipmap;
  if (poly.polygon->UsesMipMaps () == S_FALSE  ||  rstate_mipmap == 1)
    mipmap = 0;
  else if (rstate_mipmap == 0)
  {
    if (min_z < zdist_mipmap1) mipmap =  0;
    else if (min_z < zdist_mipmap2) mipmap = 1;
    else if (min_z < zdist_mipmap3) mipmap = 2;
    else mipmap = 3;
  }
  else
    mipmap = rstate_mipmap - 1;
  IPolygonTexture* tex;
  poly.polygon->GetTexture (mipmap, &tex);
  csTextureMMSoftware* txt_mm = (csTextureMMSoftware*)GetcsTextureMMFromITextureHandle (poly.txt_handle);
  csTexture* txt_unl = txt_mm->get_texture (mipmap);

   
   
   
   
  int subtex_size;
  tex->GetSubtexSize (subtex_size);
  if (subtex_size) CacheInitTexture (tex);
  else CacheTexture (tex);

  Scan::init_draw (poly.polygon, tex, txt_mm, txt_unl);

   
   
   
   
   
  P1 = poly.plane.m_cam2tex->m11;
  P2 = poly.plane.m_cam2tex->m12;
  P3 = poly.plane.m_cam2tex->m13;
  P4 = - (P1 * poly.plane.v_cam2tex->x
        + P2 * poly.plane.v_cam2tex->y
        + P3 * poly.plane.v_cam2tex->z);
  Q1 = poly.plane.m_cam2tex->m21;
  Q2 = poly.plane.m_cam2tex->m22;
  Q3 = poly.plane.m_cam2tex->m23;
  Q4 = - (Q1 * poly.plane.v_cam2tex->x
        + Q2 * poly.plane.v_cam2tex->y
        + Q3 * poly.plane.v_cam2tex->z);

  P1 *= Scan::tw; P2 *= Scan::tw; P3 *= Scan::tw; P4 *= Scan::tw;
  Q1 *= Scan::th; Q2 *= Scan::th; Q3 *= Scan::th; Q4 *= Scan::th;
  P4 -= Scan::fdu; Q4 -= Scan::fdv;

   
   
   
  float J1, J2, J3, K1, K2, K3;
  if (ABS (Dc) < 0.01 )
  {
     
    J1 = J2 = J3 = 0;
    K1 = K2 = K3 = 0;
  } else
  {
    J1 = P1 * inv_aspect + P4 * M;
    J2 = P2 * inv_aspect + P4 * N;
    J3 = P3              + P4 * O;
    K1 = Q1 * inv_aspect + Q4 * M;
    K2 = Q2 * inv_aspect + Q4 * N;
    K3 = Q3              + Q4 * O;
  }
  
  
   
   
   
  if (ABS (M) < .000001)
  {
    Scan::INTERPOL_STEP = inter_modes[Scan::inter_mode].step1;
    Scan::INTERPOL_SHFT = inter_modes[Scan::inter_mode].shift1;
  }
  else if (ABS (M) < .00005)
  {
    Scan::INTERPOL_STEP = inter_modes[Scan::inter_mode].step2;
    Scan::INTERPOL_SHFT = inter_modes[Scan::inter_mode].shift2;
  }
  else if (ABS (M) < .001)
  {
    Scan::INTERPOL_STEP = inter_modes[Scan::inter_mode].step3;
    Scan::INTERPOL_SHFT = inter_modes[Scan::inter_mode].shift3;
  }
  else
  {
    Scan::INTERPOL_STEP = inter_modes[Scan::inter_mode].step4;
    Scan::INTERPOL_SHFT = inter_modes[Scan::inter_mode].shift4;
  }

   
  Scan::M = M;
  Scan::J1 = J1;
  Scan::K1 = K1;
  Scan::dM = M*Scan::INTERPOL_STEP;
  Scan::dJ1 = J1*Scan::INTERPOL_STEP;
  Scan::dK1 = K1*Scan::INTERPOL_STEP;

   
  dscan = NULL;

  int tex_transp, poly_alpha;

  tex_transp = Scan::texture->get_transparent ();
  poly.polygon->GetAlpha (poly_alpha);

  if (!do_textured)
  {
     
    if (do_transp && (tex_transp != -1) || poly_alpha)
      dscan = NULL;    
    else if (gi_pixelbytes == 4)
    {
       
         
       
         
    }
    else if (gi_pixelbytes == 2)
    {
      if (z_buf_mode == ZBuf_Use)
        dscan = Scan16::draw_scanline_z_buf_flat;
      else
        dscan = Scan16::draw_scanline_flat;
    }
    else
    {
      if (z_buf_mode == ZBuf_Use)
        dscan = Scan::draw_scanline_z_buf_flat;
      else
        dscan = Scan::draw_scanline_flat;
    }
  }
  else if (gi_pixelbytes == 2)
  {
     
    if (Scan::tmap2)
    {
      if (z_buf_mode == ZBuf_Use)
        dscan = Scan16::draw_scanline_z_buf_map;
      else if (do_transp && tex_transp != -1)
        dscan = Scan16::draw_scanline_transp_map;
      else if (do_transp && poly_alpha)
      {
	Scan::alpha_mask = txtmgr->alpha_mask;
        if (poly_alpha == 50)
          dscan = Scan16::draw_scanline_map_alpha50;
	else
	{
	  Scan::alpha_fact = poly_alpha*256/100;
	  if (pfmt.GreenBits == 5)
	    dscan = Scan16::draw_scanline_map_alpha_555;
	  else
	    dscan = Scan16::draw_scanline_map_alpha_565;
	}
      }
      else





        if (do_texel_filt)
          dscan = Scan16::draw_scanline_map_filter;
        else
          dscan = Scan16::draw_scanline_map;
    }
    else
    {
      TextureTablesPalette* lt_pal = txtmgr->lt_pal;
      int txtMode = txtmgr->txtMode;
      
      Scan16::pal_table = lt_pal->pal_to_true;
      if (txtMode == TXT_PRIVATE)
      {
        unsigned char* priv_to_global;
	priv_to_global = Scan::texture->get_private_to_global ();

        if (z_buf_mode == ZBuf_Use)
          dscan = Scan16::draw_scanline_z_buf_private;
        else
          dscan = Scan16::draw_scanline_private;
      } else
      {
        if (z_buf_mode == ZBuf_Use)
          dscan = Scan16::draw_scanline_z_buf;
        else





          dscan = Scan16::draw_scanline;
      }
    }
  }
  else if (gi_pixelbytes == 4)
  {
     
    if (Scan::tmap2)
    {
      if (z_buf_mode == ZBuf_Use)
        dscan = Scan32::draw_scanline_z_buf_map;
      else if (do_transp && poly_alpha)
      {
        if (poly_alpha == 50)
          dscan = Scan32::draw_scanline_map_alpha50;
	else
	{
	  Scan::alpha_fact = poly_alpha*256/100;
	  dscan = Scan32::draw_scanline_map_alpha;
	}
      }
      else
        dscan = Scan32::draw_scanline_map;
    }
  }
  else
  {
    if (z_buf_mode == ZBuf_Use)
    {
      if (Scan::tmap2)
      {

         
 






          dscan = Scan::draw_scanline_z_buf_map;
      } 
      else
      {
        int txtMode = txtmgr->txtMode;

        if (txtMode == TXT_PRIVATE)
        {
          unsigned char* priv_to_global;
	  priv_to_global = Scan::texture->get_private_to_global ();
          
          dscan = Scan::draw_scanline_z_buf_private;
        } 
        else
        {
          dscan = Scan::draw_scanline_z_buf;
        }
      }
    }
    else if (do_transp && tex_transp != -1)
    {
      if (Scan::tmap2)
        dscan = Scan::draw_scanline_transp_map;
      else
      {
        int txtMode = txtmgr->txtMode;

        if (txtMode == TXT_PRIVATE)
        {
          unsigned char* priv_to_global;
	  priv_to_global = Scan::texture->get_private_to_global ();
          dscan = Scan::draw_scanline_transp_private;
        } 
        else
        {
          dscan = Scan::draw_scanline_transp;
        }
      }
    }
    else if (Scan::tmap2)
    {
     
 






      if (do_transp && poly_alpha)
      {
        extern RGB8map* alpha_map;
        TextureTablesAlpha* lt_alpha = txtmgr->lt_alpha;

        if (poly_alpha < 37)
        {
          alpha_map = lt_alpha->alpha_map25;
          dscan = Scan::draw_scanline_map_alpha1;
        }
	else if (poly_alpha >= 37 && poly_alpha < 63)
        {
          alpha_map = lt_alpha->alpha_map50;
          dscan = Scan::draw_scanline_map_alpha1;
        }
	else
        {
          alpha_map = lt_alpha->alpha_map25;
          dscan = Scan::draw_scanline_map_alpha2;
        }
      }
      else
      {





        if (do_texel_filt)
          dscan = Scan::draw_scanline_map_filter;
        else
          dscan = Scan::draw_scanline_map;
      }
    }
    else
    {
      int txtMode = txtmgr->txtMode;

      if (txtMode == TXT_PRIVATE)
      {
        unsigned char* priv_to_global;
	priv_to_global = Scan::texture->get_private_to_global ();
        dscan = Scan::draw_scanline_private;
      }
      else





        dscan = Scan::draw_scanline;
    }
  }

  if (!dscan) goto finish;    

   
   
   
   
   
  int nDirty;
  tex->GetNumberDirtySubTex (nDirty);

  if (subtex_size && nDirty)
  {
     
     
     

     
     
     

    float cx = (poly.vertices[0].sx - (float)width2);
    float cy = ((poly.vertices[0].sy - 0.5) - height2);
    float inv_z = M * cx + N * cy + O;
    float u_div_z = J1 * cx + J2 * cy + J3;
    float v_div_z = K1 * cx + K2 * cy + K3;
    float z = 1. / inv_z;
    float u = u_div_z*z;
    float v = v_div_z*z;
    float min_u = u;
    float max_u = u;
    float min_v = v;
    float max_v = v;

    for (i = 1 ; i < poly.num ; i++)
    {
      cx = poly.vertices[i].sx - (float)width2;
      cy = (poly.vertices[i].sy - 0.5) - height2;
      inv_z = M * cx + N * cy + O;
      u_div_z = J1 * cx + J2 * cy + J3;
      v_div_z = K1 * cx + K2 * cy + K3;
      z = 1. / inv_z;
      u = u_div_z*z;
      v = v_div_z*z;
      if (u < min_u) min_u = u; else if (u > max_u) max_u = u;
      if (v < min_v) min_v = v; else if (v > max_v) max_v = v;
    }

    int imin_u = QInt (min_u);
    int imin_v = QInt (min_v);
    int imax_u = QInt (max_u);
    int imax_v = QInt (max_v);
    CacheRectTexture (tex, imin_u, imin_v, imax_u, imax_v);
  }

   
   
   
   
   
   
   
   
   

  int scanL1, scanL2, scanR1, scanR2;    
  float sxL, sxR, dxL, dxR;              
  int sy, fyL, fyR;                      
  int xL, xR;
  int screenY;

  sxL = sxR = dxL = dxR = 0;             
  scanL2 = scanR2 = max_i;
  sy = fyL = fyR = QRound (poly.vertices [scanL2].sy);

  for ( ; ; )
  {
     
     
     
    bool leave;
    do
    {
      leave = true;
      if (sy <= fyR)
      {
         
        if (scanR2 == min_i) goto finish;
        scanR1 = scanR2;
        scanR2 = (scanR2 + 1) % poly.num;

        fyR = QRound (poly.vertices [scanR2].sy);
        float dyR = (poly.vertices [scanR1].sy - poly.vertices [scanR2].sy);
        if (dyR > 0)
        {
          sxR = poly.vertices [scanR1].sx;
          dxR = (poly.vertices [scanR2].sx - sxR) / dyR;
           
          sxR += dxR * (poly.vertices [scanR1].sy - ((float)sy - 0.5));
        }  
        leave = false;
      }  
      if (sy <= fyL)
      {
        scanL1 = scanL2;
        scanL2 = (scanL2 - 1 + poly.num) % poly.num;

        fyL = QRound (poly.vertices [scanL2].sy);
        float dyL = (poly.vertices [scanL1].sy - poly.vertices [scanL2].sy);
        if (dyL)
        {
          sxL = poly.vertices [scanL1].sx;
          dxL = (poly.vertices [scanL2].sx - sxL) / dyL;
           
          sxL += dxL * (poly.vertices [scanL1].sy - ((float)sy - 0.5));
        }  
        leave = false;
      }  
    } while (!leave);  

     
    float vd_inv_z = - dxL * M + N;
    float vd_u_div_z = - dxL * J1 + J2;
    float vd_v_div_z = - dxL * K1 + K2;

    float cx = (sxL - (float)width2);
    float cy = ((sy - 0.5) - height2);
    float inv_z = M * cx + N * cy + O;
    float u_div_z = J1 * cx + J2 * cy + J3;
    float v_div_z = K1 * cx + K2 * cy + K3;

     
    int fin_y;
    if (fyL > fyR)
      fin_y = fyL;
    else
      fin_y = fyR;

    screenY = height - 1 - sy;

    while (sy > fin_y)
    {
       
       
       

      if ((sy & 1) != do_interlaced)



      {
         
        xL = QRound (sxL);
        xR = QRound (sxR);

         
        float deltaX = (float)xL - sxL;

         
	d = line_table[screenY] + (xL << pixel_shift);
        z_buf = z_buffer + width * screenY + xL;

         
         
         
        extern int filter_bf;
        if (sy&1) filter_bf = 3; else filter_bf = 1;

         
         
        dscan (xR - xL, d, z_buf, inv_z + deltaX * M, u_div_z + deltaX * J1, v_div_z + deltaX * K1);
      }

      sxL += dxL;
      sxR += dxR;
      inv_z -= vd_inv_z;
      u_div_z -= vd_u_div_z;
      v_div_z -= vd_v_div_z;
      sy--;
      screenY++;
    }  
  }  

finish:
  FINAL_RELEASE( tex );
  return S_OK;
}

# 1018 "soft_g3d.cpp"



STDMETHODIMP csGraphics3DSoftware::DrawPolygonDebug (G3DPolygon& poly)
{
  (void)poly;
  return S_OK;
}

FogBuffer* csGraphics3DSoftware::find_fog_buffer (CS_ID id)
{
  FogBuffer* f = fog_buffers;
  while (f)
  {
    if (f->id == id) return f;
    f = f->next;
  }
  return NULL;
}

STDMETHODIMP csGraphics3DSoftware::OpenFogObject (CS_ID id, csFog* fog)
{
  CHK (FogBuffer* fb = new FogBuffer ());
  fb->next = fog_buffers;
  fb->prev = NULL;
  fb->id = id;
  fb->density = fog->density;
  fb->red = fog->red;
  fb->green = fog->green;
  fb->blue = fog->blue;
  if (fog_buffers) fog_buffers->prev = fb;
  fog_buffers = fb;
  return S_OK;
}

STDMETHODIMP csGraphics3DSoftware::CloseFogObject (CS_ID id)
{
  FogBuffer* fb = find_fog_buffer (id);
  if (!fb)
  {
    SysPrintf (MSG_INTERNAL_ERROR, "ENGINE FAILURE! Try to close a non-open fog object!\n");
    return E_FAIL;
  }
  if (fb->next) fb->next->prev = fb->prev;
  if (fb->prev) fb->prev->next = fb->next;
  else fog_buffers = fb->next;
  CHK (delete fb);
  return S_OK;
}

STDMETHODIMP csGraphics3DSoftware::AddFogPolygon (CS_ID id, G3DPolygon& poly, int fog_type)
{
  int i;
  int max_i, min_i;
  float max_y, min_y;
  void (*dscan) (int len, unsigned char* d, unsigned long* z_buf,
    float inv_z, float u_div_z, float v_div_z);
  unsigned char *d;
  unsigned long *z_buf;
  
  IGraphicsInfo* piGI = NULL;
  int gi_pixelbytes;
  float inv_aspect = poly.inv_aspect;

  if (poly.num < 3) return S_FALSE;

  VERIFY_SUCCESS( m_piG2D->QueryInterface( (REFIID)IID_IGraphicsInfo, (void**)&piGI) );
  piGI->GetPixelBytes( gi_pixelbytes );
  csPixelFormat pfmt;
  piGI->GetPixelFormat (&pfmt);
  FINAL_RELEASE( piGI );
  
  float M = 0, N = 0, O = 0;
  if (fog_type != CS_FOG_VIEW)
  {
     
     
    float Ac, Bc, Cc, Dc, inv_Dc;
    Ac = poly.normal.A;
    Bc = poly.normal.B;
    Cc = poly.normal.C;
    Dc = poly.normal.D;

    if (ABS (Dc) < 0.01 )
    {
      ComVector3 vcam_0;
      poly.polygon->GetCameraVector(0, &vcam_0);

       
       
       
       
      M = 0;
      N = 0;
       
       
      O = 1/vcam_0.z;
    }
    else
    {
      inv_Dc = 1/Dc;
      M = -Ac*inv_Dc*inv_aspect;
      N = -Bc*inv_Dc*inv_aspect;
      O = -Cc*inv_Dc;
    }
  }

   
   
  min_i = max_i = 0;
  min_y = max_y = poly.vertices[0].sy;
   
  int num_vertices = 1;
  for (i = 1 ; i < poly.num ; i++)
  {
    if (poly.vertices[i].sy > max_y)
    {
      max_y = poly.vertices[i].sy;
      max_i = i;
    }
    else if (poly.vertices[i].sy < min_y)
    {
      min_y = poly.vertices[i].sy;
      min_i = i;
    }
     
     
    if ((fabs (poly.vertices [i].sx - poly.vertices [i - 1].sx)
       + fabs (poly.vertices [i].sy - poly.vertices [i - 1].sy)) > 0.001 )
      num_vertices++;
  }

   
  if (num_vertices < 3) return S_FALSE;

  FogBuffer* fb = find_fog_buffer (id);
  if (!fb)
  {
    SysPrintf (MSG_INTERNAL_ERROR, "ENGINE FAILURE! Fog object not open!\n");
    exit (0);
  }

  Scan::fog_density = QInt16 (fb->density) << 16;
  if (pfmt.PixelBytes == 4)
  {
    Scan::fog_red = QInt (fb->red * 256);
    Scan::fog_green = QInt (fb->green * 256);
    Scan::fog_blue = QInt (fb->blue * 256);
  }
  else
  {
    Scan::fog_red = QInt (fb->red * 32);
    if (pfmt.GreenBits == 5)
      Scan::fog_green = QInt (fb->green * 32);
    else
      Scan::fog_green = QInt (fb->green * 64);
    Scan::fog_blue = QInt (fb->blue * 32);
  }

   
   
   
  if (ABS (M) < .00005)
  {
    Scan::INTERPOL_STEP = inter_modes[Scan::inter_mode].step1;
    Scan::INTERPOL_SHFT = inter_modes[Scan::inter_mode].shift1;
  }
  else if (ABS (M) < .0001)
  {
    Scan::INTERPOL_STEP = inter_modes[Scan::inter_mode].step2;
    Scan::INTERPOL_SHFT = inter_modes[Scan::inter_mode].shift2;
  }
  else if (ABS (M) < .001)
  {
    Scan::INTERPOL_STEP = inter_modes[Scan::inter_mode].step3;
    Scan::INTERPOL_SHFT = inter_modes[Scan::inter_mode].shift3;
  }
  else
  {
    Scan::INTERPOL_STEP = inter_modes[Scan::inter_mode].step4;
    Scan::INTERPOL_SHFT = inter_modes[Scan::inter_mode].shift4;
  }

   
  Scan::M = M;
  Scan::dM = M*Scan::INTERPOL_STEP;

   
  dscan = NULL;
  if (gi_pixelbytes == 2)
  {
    switch (fog_type)
    {
      case CS_FOG_FRONT:
        if (pfmt.GreenBits == 5) dscan = Scan16::draw_scanline_fog_555;
	else dscan = Scan16::draw_scanline_fog_565;
	break;
      case CS_FOG_BACK:
        dscan = Scan16::draw_scanline_zfill_only;
	break;
      case CS_FOG_VIEW:
        if (pfmt.GreenBits == 5) dscan = Scan16::draw_scanline_fog_view_555;
        else dscan = Scan16::draw_scanline_fog_view_565;
	break;
    }
  }
  else if (gi_pixelbytes == 4)
  {
    switch (fog_type)
    {
      case CS_FOG_FRONT: dscan = Scan32::draw_scanline_fog; break;
      case CS_FOG_BACK: dscan = Scan16::draw_scanline_zfill_only; break;
      case CS_FOG_VIEW: dscan = Scan32::draw_scanline_fog_view; break;
    }
  }
  else
  {
     
     
    dscan = NULL;
  }

  if (!dscan) goto finish;    

   
   
   
   
   
   
   
   
   

  int scanL1, scanL2, scanR1, scanR2;    
  float sxL, sxR, dxL, dxR;              
  int sy, fyL, fyR;                      
  int xL, xR;
  int screenY;

  sxL = sxR = dxL = dxR = 0;             
  scanL2 = scanR2 = max_i;
  sy = fyL = fyR = QRound (poly.vertices [scanL2].sy);

  for ( ; ; )
  {
     
     
     
    bool leave;
    do
    {
      leave = true;
      if (sy <= fyR)
      {
         
        if (scanR2 == min_i)
          goto finish;
        scanR1 = scanR2;
        scanR2 = (scanR2 + 1) % poly.num;

        fyR = QRound (poly.vertices [scanR2].sy);
        float dyR = (poly.vertices [scanR1].sy - poly.vertices [scanR2].sy);
        if (dyR > 0)
        {
          sxR = poly.vertices [scanR1].sx;
          dxR = (poly.vertices [scanR2].sx - sxR) / dyR;
           
          sxR += dxR * (poly.vertices [scanR1].sy - ((float)sy - 0.5));
        }  
        leave = false;
      }  
      if (sy <= fyL)
      {
        scanL1 = scanL2;
        scanL2 = (scanL2 - 1 + poly.num) % poly.num;

        fyL = QRound (poly.vertices [scanL2].sy);
        float dyL = (poly.vertices [scanL1].sy - poly.vertices [scanL2].sy);
        if (dyL)
        {
          sxL = poly.vertices [scanL1].sx;
          dxL = (poly.vertices [scanL2].sx - sxL) / dyL;
           
          sxL += dxL * (poly.vertices [scanL1].sy - ((float)sy - 0.5));
        }  
        leave = false;
      }  
    } while (!leave);  

     
    float vd_inv_z = - dxL * M + N;

    float cx = (sxL - (float)width2);
    float cy = ((sy - 0.5) - height2);
    float inv_z = M * cx + N * cy + O;

     
    int fin_y;
    if (fyL > fyR)
      fin_y = fyL;
    else
      fin_y = fyR;

    screenY = height - 1 - sy;

    while (sy > fin_y)
    {
       
       
       

      if ((sy & 1) != do_interlaced)



      {
         
        xL = QRound (sxL);
        xR = QRound (sxR);

         
        float deltaX = (float)xL - sxL;

         
	d = line_table[screenY] + (xL << pixel_shift);
        z_buf = z_buffer + width * screenY + xL;

         
         
        dscan (xR - xL, d, z_buf, inv_z + deltaX * M, 0, 0);
      }

      sxL += dxL;
      sxR += dxR;
      inv_z -= vd_inv_z;
      sy--;
      screenY++;
    }  
  }  

finish:
  return S_OK;
}

 
 
inline long round16 (long f)
{
  return (f + 0x8000) >> 16;
}

STDMETHODIMP csGraphics3DSoftware::DrawPolygonQuick (G3DPolygon& poly, bool gouroud)
{
  csTextureMMSoftware* txt_mm = (csTextureMMSoftware*)GetcsTextureMMFromITextureHandle (poly.txt_handle);
  csTexture* txt_unl = txt_mm->get_texture (0);

  unsigned char* bm;
  int itw, ith;
  int shf_w;

  bm = txt_unl->get_bitmap8 ();
  itw = txt_unl->get_width ();
  ith = txt_unl->get_height ();
  shf_w = txt_unl->get_w_shift ();

  float tw = (float)itw; 
  float th = (float)ith; 
  int twfp = QInt16 (tw);
  int thfp = QInt16 (th);
  int i;

  IGraphicsInfo* piGI;
  int gi_pixelbytes;

   
  VERIFY_SUCCESS (m_piG2D->QueryInterface( (REFIID)IID_IGraphicsInfo, (void**)&piGI));
  piGI->GetPixelBytes (gi_pixelbytes);
  csPixelFormat pfmt;
  piGI->GetPixelFormat (&pfmt);
  FINAL_RELEASE (piGI);

  Scan::alpha_mask = txtmgr->alpha_mask;
  
  if (gi_pixelbytes <= 1) gouroud = false;	 

   
   
   
   
  float uu[64], vv[64], iz[64];
  float rr[64], gg[64], bb[64];
  int top, bot;
  float top_y = -99999;
  float bot_y = 99999;
  top = bot = 0;                         
  int redFact = (1<<pfmt.RedBits)-1;	 
  int greenFact = (1<<pfmt.GreenBits)-1;
  int blueFact = (1<<pfmt.BlueBits)-1;
  for (i = 0 ; i < poly.num ; i++)
  {
    uu[i] = tw * poly.pi_texcoords [i].u;
    vv[i] = th * poly.pi_texcoords [i].v;
    iz[i] = poly.pi_texcoords [i].z;
    rr[i] = redFact*poly.pi_texcoords[i].r;
    gg[i] = greenFact*poly.pi_texcoords[i].g;
    bb[i] = blueFact*poly.pi_texcoords[i].b;
    if (poly.vertices [i].sy > top_y)
    {
      top_y = poly.vertices [i].sy;
      top = i;
    }  
    if (poly.vertices [i].sy < bot_y)
    {
      bot_y = poly.vertices [i].sy;
      bot = i;
    }  
  }

   
   
   
   
   
   
   
  float dd = (poly.pi_triangle [0].x - poly.pi_triangle [2].x)
           * (poly.pi_triangle [1].y - poly.pi_triangle [2].y)
           - (poly.pi_triangle [1].x - poly.pi_triangle [2].x)
           * (poly.pi_triangle [0].y - poly.pi_triangle [2].y);
  float uu0 = tw * poly.pi_tritexcoords [0].u;
  float uu1 = tw * poly.pi_tritexcoords [1].u;
  float uu2 = tw * poly.pi_tritexcoords [2].u;
  int du = QInt16 (((uu0 - uu2) * (poly.pi_triangle [1].y - poly.pi_triangle [2].y)
                  - (uu1 - uu2) * (poly.pi_triangle [0].y - poly.pi_triangle [2].y)) / dd);
  float vv0 = th * poly.pi_tritexcoords [0].v;
  float vv1 = th * poly.pi_tritexcoords [1].v;
  float vv2 = th * poly.pi_tritexcoords [2].v;
  int dv = QInt16 (((vv0 - vv2) * (poly.pi_triangle [1].y - poly.pi_triangle [2].y)
                  - (vv1 - vv2) * (poly.pi_triangle [0].y - poly.pi_triangle [2].y)) / dd);
  float iz0 = poly.pi_tritexcoords [0].z;
  float iz1 = poly.pi_tritexcoords [1].z;
  float iz2 = poly.pi_tritexcoords [2].z;
  int dz = QInt24 (((iz0 - iz2) * (poly.pi_triangle [1].y - poly.pi_triangle [2].y)
                  - (iz1 - iz2) * (poly.pi_triangle [0].y - poly.pi_triangle [2].y)) / dd);
  long dr = 0, dg = 0, db = 0;
  if (gouroud)
  {
    float rr0 = redFact*poly.pi_tritexcoords [0].r;
    float rr1 = redFact*poly.pi_tritexcoords [1].r;
    float rr2 = redFact*poly.pi_tritexcoords [2].r;
    dr = QInt16 (((rr0 - rr2) * (poly.pi_triangle [1].y - poly.pi_triangle [2].y)
                - (rr1 - rr2) * (poly.pi_triangle [0].y - poly.pi_triangle [2].y)) / dd);
    float gg0 = greenFact*poly.pi_tritexcoords [0].g;
    float gg1 = greenFact*poly.pi_tritexcoords [1].g;
    float gg2 = greenFact*poly.pi_tritexcoords [2].g;
    dg = QInt16 (((gg0 - gg2) * (poly.pi_triangle [1].y - poly.pi_triangle [2].y)
                - (gg1 - gg2) * (poly.pi_triangle [0].y - poly.pi_triangle [2].y)) / dd);
    float bb0 = blueFact*poly.pi_tritexcoords [0].b;
    float bb1 = blueFact*poly.pi_tritexcoords [1].b;
    float bb2 = blueFact*poly.pi_tritexcoords [2].b;
    db = QInt16 (((bb0 - bb2) * (poly.pi_triangle [1].y - poly.pi_triangle [2].y)
                - (bb1 - bb2) * (poly.pi_triangle [0].y - poly.pi_triangle [2].y)) / dd);
  }

   
  void (*drawline) (void *dest, int len, long *zbuff, long u, long du, long v,
    long dv, long z, long dz, unsigned char *bitmap, int bitmap_log2w);
  void (*drawline_gouroud) (void *dest, int len, long *zbuff, long u, long du, long v,
    long dv, long z, long dz, unsigned char *bitmap, int bitmap_log2w,
    long r, long g, long b, long dr, long dg, long db);

  drawline = NULL;
  drawline_gouroud = NULL;

  if (gi_pixelbytes == 2)
  {
    TextureTablesPalette* lt_pal = txtmgr->lt_pal;
    Scan16::pal_table = lt_pal->pal_to_true;

    if (gouroud)
    {
      if (z_buf_mode == ZBuf_Use)
	if (pfmt.GreenBits == 5)
          drawline_gouroud = Scan16::draw_pi_scanline_gouroud_555;
	else
          drawline_gouroud = Scan16::draw_pi_scanline_gouroud_565;
      else
	if (pfmt.GreenBits == 5)
          drawline_gouroud = Scan16::draw_pi_scanline_gouroud_zfill_555;
	else
          drawline_gouroud = Scan16::draw_pi_scanline_gouroud_zfill_565;
    }
    else
    {
      if (z_buf_mode == ZBuf_Use)
      {





        drawline = Scan16::draw_pi_scanline;
      }
      else
        drawline = Scan16::draw_pi_scanline_zfill;
    }
  }
  else if (gi_pixelbytes == 4)
  {
    if (gouroud)
    {
      if (z_buf_mode == ZBuf_Use)
        drawline_gouroud = Scan32::draw_pi_scanline_gouroud;
      else
        drawline_gouroud = Scan32::draw_pi_scanline_gouroud_zfill;
    }
    else
    {
      if (z_buf_mode == ZBuf_Use)
        drawline = Scan32::draw_pi_scanline;
      else
        drawline = Scan32::draw_pi_scanline_zfill;
    }
  }
  else
  {
    if (z_buf_mode == ZBuf_Use)
    {





      drawline = Scan::draw_pi_scanline;
    }
    else
      drawline = Scan::draw_pi_scanline_zfill;
  }
  if (!drawline && !drawline_gouroud) return S_OK;

   
   
   
   
   
  int scanL1, scanL2 = top;
  int scanR1, scanR2 = top;

  int xL = 0, xR = 0, dxdyL = 0, dxdyR = 0;
  int uL = 0, vL = 0, zL = 0, rL = 0, gL = 0, bL = 0;
  int dudyL = 0, dvdyL = 0, dzdyL = 0, drdyL = 0, dgdyL = 0, dbdyL = 0;

  int sy, fyL, fyR;
  sy = fyL = fyR = QRound (poly.vertices [top].sy);

   
   
   
  for ( ; ; )
  {
     
     
     
    bool leave;
    do
    {
      leave = true;
      if (sy <= fyR)
      {
         
         
         
         
        if (scanR2 == bot) goto finish;
        scanR1 = scanR2;
        scanR2 = (scanR2 + 1) % poly.num;

        fyR = QRound (poly.vertices [scanR2].sy);
        float dyR = poly.vertices [scanR1].sy - poly.vertices [scanR2].sy;
        if (dyR > 0)
        {
          xR = QInt16 (poly.vertices [scanR1].sx);
          dxdyR = QInt16 ((poly.vertices [scanR2].sx - poly.vertices [scanR1].sx) / dyR);
           
          xR += QRound (dxdyR * (poly.vertices [scanR1].sy -
            ((float)QRound (poly.vertices [scanR1].sy) - 0.5)));
        }  
        leave = false;
      }  
      if (sy <= fyL)
      {
         
         
         
        scanL1 = scanL2;
        scanL2 = (scanL2 - 1 + poly.num) % poly.num;

        fyL = QRound (poly.vertices [scanL2].sy);
        float dyL = poly.vertices [scanL1].sy - poly.vertices [scanL2].sy;
        if (dyL > 0)
        {
          dxdyL = QInt16 ((poly.vertices [scanL2].sx - poly.vertices [scanL1].sx) / dyL);
          dudyL = QInt16 ((uu[scanL2] - uu[scanL1]) / dyL);
          dvdyL = QInt16 ((vv[scanL2] - vv[scanL1]) / dyL);
          dzdyL = QInt24 ((iz[scanL2] - iz[scanL1]) / dyL);
	  if (gouroud)
	  {
            drdyL = QInt16 ((rr[scanL2] - rr[scanL1]) / dyL);
            dgdyL = QInt16 ((gg[scanL2] - gg[scanL1]) / dyL);
            dbdyL = QInt16 ((bb[scanL2] - bb[scanL1]) / dyL);
	  }
          xL = QInt16 (poly.vertices [scanL1].sx);

           
          float deltaY = poly.vertices [scanL1].sy - ((float)sy - 0.5);
          float deltaX = (dxdyL / 65536.) * deltaY;
          xL += QInt16 (deltaX);

           
          float Factor;
          if (poly.vertices [scanL2].sx != poly.vertices [scanL1].sx)
            Factor = deltaX / (poly.vertices [scanL2].sx - poly.vertices [scanL1].sx);
          else
            Factor = 0;
          uL = QInt16 (uu [scanL1] + (uu [scanL2] - uu [scanL1]) * Factor);
          vL = QInt16 (vv [scanL1] + (vv [scanL2] - vv [scanL1]) * Factor);
          zL = QInt24 (iz [scanL1] + (iz [scanL2] - iz [scanL1]) * Factor);
          if (gouroud)
	  {
	    rL = QInt16 (rr [scanL1] + (rr [scanL2] - rr [scanL1]) * Factor);
	    gL = QInt16 (gg [scanL1] + (gg [scanL2] - gg [scanL1]) * Factor);
	    bL = QInt16 (bb [scanL1] + (bb [scanL2] - bb [scanL1]) * Factor);
	  }
        }  
        leave = false;
      }  
    } while (!leave);  

     
     
     
    int fin_y;
    if (fyL > fyR)
      fin_y = fyL;
    else
      fin_y = fyR;

    int screenY = height - 1 - sy;
    while (sy > fin_y)
    {
      if ((sy & 1) != do_interlaced)
      {
         
         
         
        int xl = round16 (xL);
        int xr = round16 (xR);

        register long* zbuff = (long *)z_buffer + width * screenY + xl;

         
        int uu = uL, vv = vL;
        int duu = du, dvv = dv;
        if (uu < 0) uu = 0; if (uu > twfp) uu = twfp;
        if (vv < 0) vv = 0; if (vv > thfp) vv = thfp;
        if (xr > xl)
        {
          int tmpu = uu + du * (xr - xl);
          int tmpv = vv + dv * (xr - xl);
          if (tmpu < 0 || tmpu > twfp)
          {
            if (tmpu < 0) tmpu = 0; if (tmpu > twfp) tmpu = twfp;
            duu = (tmpu - uu) / (xr - xl);
          }  
          if (tmpv < 0 || tmpv > thfp)
          {
            if (tmpv < 0) tmpv = 0; if (tmpv > thfp) tmpv = thfp;
            dvv = (tmpv - vv) / (xr - xl);
          }  
        }  

        unsigned char* pixel_at;
         
	pixel_at = line_table[screenY] + (xl << pixel_shift);
	if (gouroud)
          drawline_gouroud (pixel_at, xr - xl, zbuff, uu, duu,
                  vv, dvv, zL, dz, bm, shf_w, rL, gL, bL, dr, dg, db);
        else
	  drawline (pixel_at, xr - xl, zbuff, uu, duu,
                  vv, dvv, zL, dz, bm, shf_w);
      }  

      xL += dxdyL;
      xR += dxdyR;
      uL += dudyL;
      vL += dvdyL;
      zL += dzdyL;
      if (gouroud)
      {
        rL += drdyL;
        gL += dgdyL;
        bL += dbdyL;
      }
      sy--;
      screenY++;
    }  
  }  

finish:
  if (rstate_edges)
  {
    int white = txtmgr->white ();

    for (i = 0; i < poly.num; i++)
    {
      int next = (i == poly.num - 1 ? 0 : i + 1);
      m_piG2D->DrawLine (QRound (poly.vertices [i].sx),
                         height - 1 - QRound (poly.vertices [i].sy),
                         QRound (poly.vertices [next].sx),
                         height - 1 - QRound (poly.vertices [next].sy), white);
    }  
  }

  return S_OK;
}

STDMETHODIMP csGraphics3DSoftware::CacheTexture (IPolygonTexture* texture)
{
  tcache->use_texture (texture, txtmgr);
  return S_OK;
}

void csGraphics3DSoftware::CacheInitTexture (IPolygonTexture* texture)
{
  tcache->init_texture (texture, txtmgr);
}

void csGraphics3DSoftware::CacheSubTexture (IPolygonTexture* texture, int u, int v)
{
  tcache->use_sub_texture (texture, txtmgr, u, v);
}

void csGraphics3DSoftware::CacheRectTexture (IPolygonTexture* tex,
	int minu, int minv, int maxu, int maxv)
{
  int subtex_size;
  tex->GetSubtexSize (subtex_size);

  int iu, iv;
  for (iu = minu ; iu < maxu ; iu += subtex_size)
  {
    for (iv = minv ; iv < maxv ; iv += subtex_size)
        tcache->use_sub_texture (tex, txtmgr, iu, iv);
    tcache->use_sub_texture (tex, txtmgr, iu, maxv);
  }
  for (iv = minv ; iv < maxv ; iv += subtex_size)
      tcache->use_sub_texture (tex, txtmgr, maxu, iv);
  tcache->use_sub_texture (tex, txtmgr, maxu, maxv);
}

STDMETHODIMP csGraphics3DSoftware::UncacheTexture (IPolygonTexture* texture)
{
  (void)texture;
  return E_NOTIMPL;
}

STDMETHODIMP csGraphics3DSoftware::SetRenderState (G3D_RENDERSTATEOPTION op,
  long value)
{
  switch (op)
  {
    case G3DRENDERSTATE_NOTHING:
      return S_OK;
    case G3DRENDERSTATE_ZBUFFERTESTENABLE:
      if (value)
      {
         if (z_buf_mode == ZBuf_Test)
           return S_OK;
         if (z_buf_mode == ZBuf_None)
           z_buf_mode = ZBuf_Test;
         else if (z_buf_mode == ZBuf_Fill)
           z_buf_mode = ZBuf_Use;
      }
      else
      {
         if (z_buf_mode == ZBuf_Fill)
           return S_OK;
         if (z_buf_mode == ZBuf_Use)
           z_buf_mode = ZBuf_Fill;
         else if (z_buf_mode == ZBuf_Test)
           z_buf_mode = ZBuf_None;
      }
      break;
    case G3DRENDERSTATE_ZBUFFERFILLENABLE:
      if (value)
      {
        if (z_buf_mode == ZBuf_Fill)
          return S_OK;
        if (z_buf_mode == ZBuf_None)
          z_buf_mode = ZBuf_Fill;
        else if (z_buf_mode == ZBuf_Test)
          z_buf_mode = ZBuf_Use;
      }
      else
      {
        if (z_buf_mode == ZBuf_Test)
          return S_OK;
        if (z_buf_mode == ZBuf_Use)
          z_buf_mode = ZBuf_Test;
        else if (z_buf_mode == ZBuf_Fill)
          z_buf_mode = ZBuf_None;
      }
      break;
    case G3DRENDERSTATE_DITHERENABLE:
      rstate_dither = value;
      break;
    case G3DRENDERSTATE_SPECULARENABLE:
      rstate_specular = value;
      break;
    case G3DRENDERSTATE_BILINEARMAPPINGENABLE:
      rstate_bilinearmap = value;
      break;
    case G3DRENDERSTATE_TRILINEARMAPPINGENABLE:
      rstate_trilinearmap = value;
      break;
    case G3DRENDERSTATE_TRANSPARENCYENABLE:
      rstate_alphablend = value;
      break;
    case G3DRENDERSTATE_MIPMAPENABLE:
      rstate_mipmap = value;
      break;
    case G3DRENDERSTATE_TEXTUREMAPPINGENABLE:
      rstate_flat = !value;
      break;
    case G3DRENDERSTATE_EDGESENABLE:
      rstate_edges = value;
      break;
    case G3DRENDERSTATE_MMXENABLE:

      do_mmx = value;
      break;



    case G3DRENDERSTATE_INTERLACINGENABLE:
      if (m_piG2D->DoubleBuffer (!value) != S_OK)
        return E_FAIL;
      do_interlaced = value ? 0 : -1;
      break;
    case G3DRENDERSTATE_INTERPOLATIONSTEP:
      Scan::inter_mode = value;
      break;
    case G3DRENDERSTATE_DEBUGENABLE:
      do_debug = value;
      break;
    case G3DRENDERSTATE_LIGHTFRUSTRUMENABLE:
      do_light_frust = value;
      break;
    case G3DRENDERSTATE_FILTERINGENABLE:
      do_texel_filt = value;
      break;
    case G3DRENDERSTATE_LIGHTINGENABLE:
      do_lighting = value;
      break;
    default:
      return E_INVALIDARG;
  }

  return S_OK;
}

STDMETHODIMP csGraphics3DSoftware::GetRenderState(G3D_RENDERSTATEOPTION op, long& retval)
{
  switch (op)
  {
    case G3DRENDERSTATE_NOTHING:
      retval = 0;
      break;
    case G3DRENDERSTATE_ZBUFFERTESTENABLE:
      retval = (bool)(z_buf_mode & ZBuf_Test);
      break;
    case G3DRENDERSTATE_ZBUFFERFILLENABLE:
      retval = (bool)(z_buf_mode & ZBuf_Fill);
      break;
    case G3DRENDERSTATE_DITHERENABLE:
      retval = rstate_dither;
      break;
    case G3DRENDERSTATE_SPECULARENABLE:
      retval = rstate_specular;
      break;
    case G3DRENDERSTATE_BILINEARMAPPINGENABLE:
      retval = rstate_bilinearmap;
      break;
    case G3DRENDERSTATE_TRILINEARMAPPINGENABLE:
      retval = rstate_trilinearmap;
      break;
    case G3DRENDERSTATE_TRANSPARENCYENABLE:
      retval = rstate_alphablend;
      break;
    case G3DRENDERSTATE_MIPMAPENABLE:
      retval = rstate_mipmap;
      break;
    case G3DRENDERSTATE_TEXTUREMAPPINGENABLE:
      retval = !rstate_flat;
      break;
    case G3DRENDERSTATE_EDGESENABLE:
      retval = rstate_edges;
      break;
    case G3DRENDERSTATE_MMXENABLE:

      retval = do_mmx;



      break;
    case G3DRENDERSTATE_INTERLACINGENABLE:
      retval = do_interlaced == -1 ? false : true;
      break;
    case G3DRENDERSTATE_INTERPOLATIONSTEP:
      retval = Scan::inter_mode;
      break;
    case G3DRENDERSTATE_DEBUGENABLE:
      retval = do_debug;
      break;
    case G3DRENDERSTATE_LIGHTFRUSTRUMENABLE:
      retval = do_light_frust;
      break;
    case G3DRENDERSTATE_FILTERINGENABLE:
      retval = do_texel_filt;
      break;
    case G3DRENDERSTATE_LIGHTINGENABLE:
      retval = do_lighting;
      break;
    default:
      retval = 0;
      return E_INVALIDARG;
  }
  
  return S_OK;
}

STDMETHODIMP csGraphics3DSoftware::GetCaps(G3D_CAPS *caps)
{
  if (!caps)
    return E_INVALIDARG;

  caps->ColorModel = G3DCOLORMODEL_RGB;
  caps->CanClip = false;
  caps->SupportsArbitraryMipMapping = true;
  caps->BitDepth = 8;
  caps->ZBufBitDepth = 32;
  caps->minTexHeight = 2;
  caps->minTexWidth = 2;
  caps->maxTexHeight = 1024;
  caps->maxTexWidth = 1024;
  caps->PrimaryCaps.RasterCaps = G3DRASTERCAPS_SUBPIXEL;
  caps->PrimaryCaps.canBlend = true;
  caps->PrimaryCaps.ShadeCaps = G3DRASTERCAPS_LIGHTMAP;
  caps->PrimaryCaps.PerspectiveCorrects = true;
  caps->PrimaryCaps.FilterCaps = G3D_FILTERCAPS((int)G3DFILTERCAPS_NEAREST | (int)G3DFILTERCAPS_MIPNEAREST);

  return 1;
}

STDMETHODIMP csGraphics3DSoftware::ClearCache()
{
  if (tcache) tcache->clear ();
  return S_OK;
}

STDMETHODIMP csGraphics3DSoftware::SetCacheSize (long size)
{
  if (tcache) tcache->set_cache_size (size);
  else TextureCache::set_default_cache_size (size);
  return S_OK;
}

STDMETHODIMP csGraphics3DSoftware::DumpCache()
{
  if (tcache) tcache->dump();
  return S_OK;
}

STDMETHODIMP csGraphics3DSoftware::DrawLine (Vector3& v1, Vector3& v2, float fov, int color)
{
  if (v1.z < SMALL_Z && v2.z < SMALL_Z) return S_FALSE;

  float x1 = v1.x, y1 = v1.y, z1 = v1.z;
  float x2 = v2.x, y2 = v2.y, z2 = v2.z;

  if (z1 < SMALL_Z)
  {
     
     
     
    float t = (SMALL_Z-z1) / (z2-z1);
    x1 = t*(x2-x1)+x1;
    y1 = t*(y2-y1)+y1;
    z1 = SMALL_Z;
  }
  else if (z2 < SMALL_Z)
  {
     
     
     
    float t = (SMALL_Z-z1) / (z2-z1);
    x2 = t*(x2-x1)+x1;
    y2 = t*(y2-y1)+y1;
    z2 = SMALL_Z;
  }

  float iz1 = fov/z1;
  int px1 = QInt (x1 * iz1 + (width/2));
  int py1 = height - 1 - QInt (y1 * iz1 + (height/2));
  float iz2 = fov/z2;
  int px2 = QInt (x2 * iz2 + (width/2));
  int py2 = height - 1 - QInt (y2 * iz2 + (height/2));

  m_piG2D->DrawLine (px1, py1, px2, py2, color);

  return S_OK;
}

void csGraphics3DSoftware::SysPrintf (int mode, char* szMsg, ...)
{
  char buf[1024];
  va_list arg;

  ( arg  = ((__gnuc_va_list) __builtin_next_arg (  szMsg ))) ;
  vsprintf (buf, szMsg, arg);
  ((void)0) ;

  m_piSystem->Print (mode, buf);
}

 

 
STDMETHODIMP csGraphics3DSoftware::DrawHalo(Vector3* pCenter, float fIntensity, HALOINFO haloInfo)
{
  int gi_pixelbytes;
  csPixelFormat pfmt;

  IGraphicsInfo* piGI = NULL;
  VERIFY_SUCCESS( m_piG2D->QueryInterface( (REFIID)IID_IGraphicsInfo, (void**)&piGI) );
  piGI->GetPixelBytes (gi_pixelbytes);
  piGI->GetPixelFormat (&pfmt);
  FINAL_RELEASE( piGI );

  if (gi_pixelbytes != 2) return S_FALSE;

  int izz = QInt24 (1.0f / pCenter->z);
  HRESULT hRes = S_OK;

  if (haloInfo == NULL)
    return E_INVALIDARG;

  if (pCenter->x > width || pCenter->x < 0 || pCenter->y > height || pCenter->y < 0  ) 
    return S_FALSE;
 
  unsigned long zb = z_buffer[(int)pCenter->x + (width * (int)pCenter->y)];

   
  if (izz < (int)zb)	      
    hRes = S_FALSE;

   
  unsigned short* pBuffer = ((csG3DSoftwareHaloInfo*)haloInfo)->pbuf;
  unsigned char* pAlphaBuffer = ((csG3DSoftwareHaloInfo*)haloInfo)->palpha;

  int hdiv3 = height / 3;

  int nx = QInt(pCenter->x) - (hdiv3 >> 1),
      ny = QInt(pCenter->y) - (hdiv3 >> 1);

  int x, y;
  int hh = hdiv3, hw = hdiv3;

  if (fIntensity == 0.0f)
    return S_FALSE;

  if (nx >= width || ny >= height)
    return S_FALSE;

  if (nx < 0)
  {
    hw += nx;     
    nx = 0;	     
  }
    
  if (ny < 0)
  {
    hh += ny; 
    ny = 0;
  }

  if (nx + hw > width)  
    hw -= (nx + hw) - width;

  if (ny + hh > height)
    hh -= (ny + hh) - height;

  int startx = nx - (QInt(pCenter->x) - (hdiv3 >> 1)), 
      starty = ny - (QInt(pCenter->y) - (hdiv3 >> 1));

  int br1, bg1, bb1,
      br2, bg2, bb2;

  int red_shift, green_mask;
  if (pfmt.GreenBits == 5)
  {
    red_shift = 10;
    green_mask = 0x1f;
  }
  else
  {
    red_shift = 11;
    green_mask = 0x3f;
  }

  for (y=0; y < hh; y++)
  {
    unsigned short b, p;

    unsigned short* pScreen;
    unsigned short* pBufY;
    unsigned char* pAlphaBufY;

     
    pScreen = (unsigned short*)(line_table[ny+y] + (nx << pixel_shift));
    pBufY = &pBuffer[startx + (hdiv3 * (starty + y))];
    pAlphaBufY = &pAlphaBuffer[startx + (hdiv3 * (starty + y))];

    for (x=0; x < hw; x++)
    {
      b = pBufY[x];
      
      int a = QInt((float)pAlphaBufY[x] * fIntensity);
      int na = 256-a;

      p = pScreen[x];

      br1 = b >> red_shift;
      bg1 = (b >> 5) & green_mask;
      bb1 = b & 0x1f;

      br2 = p >> red_shift;
      bg2 = (p >> 5) & green_mask;
      bb2 = p & 0x1f;
      
      br1 = (a*br1 + br2*na) >> 8;
      bg1 = (a*bg1 + bg2*na) >> 8;
      bb1 = (a*bb1 + bb2*na) >> 8;
      
      pScreen[x] = (br1<<red_shift) | (bg1<<5) | bb1;
    }
  }

  return hRes;
}

STDMETHODIMP csGraphics3DSoftware::CreateHalo(float r, float g, float b, HALOINFO* pRetVal)
{
  m_piG2D->AddRef();
  csHaloDrawer halo(m_piG2D, r, g, b);

  csG3DSoftwareHaloInfo* retval = new csG3DSoftwareHaloInfo();

  retval->pbuf = halo.GetBuffer();
  retval->palpha = halo.GetAlphaBuffer();

  *pRetVal = (HALOINFO)retval;

  return S_OK;
}

STDMETHODIMP csGraphics3DSoftware::DestroyHalo(HALOINFO haloInfo)
{
  delete [] ((csG3DSoftwareHaloInfo*)haloInfo)->pbuf;
  delete [] ((csG3DSoftwareHaloInfo*)haloInfo)->palpha;

  delete (csG3DSoftwareHaloInfo*)haloInfo;
  return S_OK;
}

STDMETHODIMP csGraphics3DSoftware::TestHalo (Vector3* pCenter)
{
  int izz = QInt24 (1.0f / pCenter->z);

  if (pCenter->x > width || pCenter->x < 0 || pCenter->y > height || pCenter->y < 0  ) 
    return S_FALSE;

  unsigned long zb = z_buffer[(int)pCenter->x + (width * (int)pCenter->y)];

  if (izz < (int)zb)
    return S_FALSE;

  return S_OK;
}

 

 

csGraphics3DSoftware::csHaloDrawer::csHaloDrawer(IGraphics2D* piG2D, float r, float g, float b)
{
  mpBuffer = NULL;
  mpAlphaBuffer = NULL;

  IGraphicsInfo* piGI;
  
  piG2D->QueryInterface(IID_IGraphicsInfo, (void**)&piGI);
  mpiG2D = piG2D;

  piGI->GetWidth(mWidth);
  piGI->GetHeight(mHeight);

  int gi_pixelbytes;
  csPixelFormat pfmt;
  piGI->GetPixelBytes (gi_pixelbytes);
  piGI->GetPixelFormat (&pfmt);

  if (gi_pixelbytes != 2)
  {
    red_shift = 0;
    FINAL_RELEASE (piGI);
    return;
  }

  if (pfmt.GreenBits == 5)
  {
    red_shift = 10;
    green_mask = 0x1f;
    not_green_bits = 3;
  }
  else
  {
    red_shift = 11;
    green_mask = 0x3f;
    not_green_bits = 2;
  }

  int dim = mHeight / 3;

   
  int x=0;
  int y=dim/2;
   
  int d = 1 - y;

  mpBuffer = new unsigned short[dim*dim];
  mpAlphaBuffer = new unsigned char[dim*dim];
  memset(mpBuffer, 0, dim*dim*sizeof(short));
  memset(mpAlphaBuffer, 0, dim*dim*sizeof(char));

  mBufferWidth = dim;
  mDim = dim;
  
  mRed = r; mGreen = b; mBlue = b;
  mx = my = dim / 2;

   

  drawline_outerrim(-y, y, x);
  
  while (true)
  {
    if (d < 0)
      d += 2 * x + 3;
    else
    {
      d += 2 * (x - y) + 5;
      y--;
      if (y <= x)
	break;

      drawline_outerrim(-x, x, y);
      drawline_outerrim(-x, x, -y);
    }
    x++;

    drawline_outerrim(-y, y, x);
    drawline_outerrim(-y, y, -x);
  }

   

  x=0;
  y=dim/3;
  d = 1 - y;

  mDim = QInt (dim/1.5);

  mRatioRed = (r - (r/3.f)) / y;
  mRatioGreen = (g - (g/3.f)) / y;
  mRatioBlue = (b - (b/3.f)) / y;

  drawline_innerrim(-y, y, x);
  
  while (true)
  {
    if (d < 0)
      d += 2 * x + 3;
    else
    {
      d += 2 * (x - y) + 5;
      y--;
      if (y <= x)
	break;

      drawline_innerrim(-x, x, y);
      drawline_innerrim(-x, x, -y);
    }
    x++;
    drawline_innerrim(-y, y, x);
    drawline_innerrim(-y, y, -x);
  }

   
  
   
# 2358 "soft_g3d.cpp"


  FINAL_RELEASE(piGI);
}

csGraphics3DSoftware::csHaloDrawer::~csHaloDrawer()
{
  FINAL_RELEASE(mpiG2D);
}

void csGraphics3DSoftware::csHaloDrawer::drawline_vertical(int  , int y1, int y2)
{
  int i;
  unsigned short* buf;
  unsigned char* abuf;

  int r = (int)(mRed/2.5f * 256.0f) >> 3;
  int g = (int)(mGreen/2.5f * 256.0f) >> not_green_bits;
  int b = (int)(mBlue/2.5f * 256.0f) >> 3;

  int c = (r << red_shift) | (g << 5) | b;

  while (y1 < y2)
  {
    buf = &mpBuffer[(mx-1) + (mBufferWidth * y1++)];
    abuf = &mpAlphaBuffer[(mx-1) + (mBufferWidth * y1++)];
    
    for(i=0; i<3; i++)
    {
        buf[i] = c;    
	abuf[i] = 0;
    }
  }

}

void csGraphics3DSoftware::csHaloDrawer::drawline_outerrim(int x1, int x2, int y)
{
  if (x1 == x2) return;

  int r = (int)(mRed / 3.5f * 256.0f);
  int g = (int)(mGreen / 3.5f * 256.0f);
  int b = (int)(mBlue / 3.5f * 256.0f);
 
  int a = QInt((r + g + b) / 3);

   
   
   
  float sq = (mDim/3.0)*(mDim/3.0) - ((double)y*(double)y);
  int stopx = 0;
  if (sq > 0) stopx = (int)sqrt (sq);

  r >>= 3; g >>= not_green_bits; b >>= 3;

  unsigned short* bufy;
  unsigned char*  abufy;

  x1 += mx;
  x2 += mx;
  y += my;

  bufy = &mpBuffer[y * mBufferWidth];
  abufy = &mpAlphaBuffer[y * mBufferWidth];

  if (stopx)
  {    
    while (x1 <= (mx - stopx) + 2)
    { 
      bufy[x1] = (r << red_shift) | (g << 5) | b;
      abufy[x1++] = a;
    }

    x1 = mx + stopx - 2;
    
    while (x1 <= x2)
    { 
      bufy[x1] = (r << red_shift) | (g << 5) | b;
      abufy[x1++] = a;
    }
  }
  else
  {
    while (x1 <= x2)
    {
      bufy[x1] = (r << red_shift) | (g << 5) | b;
      abufy[x1++] = a;
    }
  
  }
}

void csGraphics3DSoftware::csHaloDrawer::drawline_innerrim(int x1, int x2, int y)
{
  float w2 = x2 - x1;
  unsigned short* bufy;
  unsigned char* abufy;

  x1 += mx;
  x2 += mx;
  y += my;

  if (y >= mHeight || y <= 0) return;
  bufy = &mpBuffer[y * mBufferWidth];
  abufy = &mpAlphaBuffer[y * mBufferWidth];

  if (w2 == 0.0f) return;
  w2 /= 2.0f;

  int halfx = QInt (x1 + w2);

  float ir, ig, ib, ia;

  float rlow = mRed / 4.5f;
  float glow = mGreen / 4.5f;
  float blow = mBlue / 4.5f;
  
  if (y <= my)
  {
    int iy = y - (my - (mDim / 2));

    ir = (iy * mRatioRed + rlow) * 256;
    ig = (iy * mRatioGreen + glow) * 256;
    ib = (iy * mRatioBlue + blow) * 256;    
    ia = (ir + ig + ib) / 3.0f;     
  }
  else
  {
    int iy = (my + (mDim/2)) - y;

    ir = (iy * mRatioRed + rlow) * 256;
    ig = (iy * mRatioGreen + glow) * 256;
    ib = (iy * mRatioBlue + blow) * 256;
    ia = (ir + ig + ib) / 3.0f;
  }

  float r = rlow * 256;
  float g = glow * 256;
  float b = blow * 256;
  float a = (r + g + b) / 3.0f;

  if (a < 0) a = 0;
 
  if (ir > 245) ir = 245;
  if (ig > 245) ig = 245;
  if (ib > 245) ib = 245;
  if (ia > 250) ia = 250;

  float rdelta = (ir - r) / w2;
  float gdelta = (ig - g) / w2;
  float bdelta = (ib - b) / w2;
  float adelta = (ia - a) / w2;
 
  int br, bg, bb;

  unsigned short p;
  int inta;

  while (x1 <= halfx)
  {
    p = bufy[x1];
    
    inta = QInt(a);

    br = QInt(r) >> 3;
    bg = QInt(g) >> not_green_bits;
    bb = QInt(b) >> 3;

    bufy[x1] = (br<<red_shift) | (bg<<5) | bb;
    abufy[x1++] = inta;

    r += rdelta; g+=gdelta; b+=bdelta; a+=adelta;
  }

  while(x1 <= x2)
  {
    p = bufy[x1];
    
    inta = QInt(a);

    br = QInt(r) >> 3;
    bg = QInt(g) >> not_green_bits;
    bb = QInt(b) >> 3;

    bufy[x1] = (br<<red_shift) | (bg<<5) | bb;
    abufy[x1++] = inta;

    r -= rdelta; g -= gdelta; b -= bdelta; a -= adelta;
  }
}

 

 

IMPLEMENT_COMPOSITE_UNKNOWN (csGraphics3DSoftware, XConfig3DSoft)

csOptionDescription IXConfig3DSoft::config_options[] =
{
  { 0, "ilace", "Interlacing", CSVAR_BOOL },
  { 1, "light", "Texture lighting", CSVAR_BOOL },
  { 2, "transp", "Transparent textures", CSVAR_BOOL },
  { 3, "txtmap", "Texture mapping", CSVAR_BOOL },
  { 4, "txtfilt", "Texture filtering", CSVAR_BOOL },
  { 5, "mmx", "MMX support", CSVAR_BOOL },
  { 6, "lfrust", "Light frustrum", CSVAR_BOOL },
  { 7, "gamma", "Gamma value", CSVAR_FLOAT },
  { 8, "dmipmap1", "Mipmap distance 1", CSVAR_FLOAT },
  { 9, "dmipmap2", "Mipmap distance 2", CSVAR_FLOAT },
  { 10, "dmipmap3", "Mipmap distance 3", CSVAR_FLOAT },
};

#define NUM_OPTIONS 11

STDMETHODIMP IXConfig3DSoft::SetOption (int id, csVariant* value)
{
  METHOD_PROLOGUE (csGraphics3DSoftware, XConfig3DSoft);
  if (value->type != config_options[id].type) return E_FAIL;
  switch (id)
  {
    case 0: pThis->do_interlaced = value->v.bVal ? 0 : -1; break;
    case 1: pThis->do_lighting = value->v.bVal; break;
    case 2: pThis->do_transp = value->v.bVal; break;
    case 3: pThis->do_textured = value->v.bVal; break;
    case 4: pThis->do_texel_filt = value->v.bVal; break;
    case 5: pThis->do_mmx = value->v.bVal; break;
    case 6: pThis->do_light_frust = value->v.bVal; break;
    case 7: pThis->txtmgr->Gamma = value->v.fVal; break;
    case 8: pThis->zdist_mipmap1 = value->v.fVal; break;
    case 9: pThis->zdist_mipmap2 = value->v.fVal; break;
    case 10: pThis->zdist_mipmap3 = value->v.fVal; break;
    default: return E_FAIL;
  }
  return S_OK;
}

STDMETHODIMP IXConfig3DSoft::GetOption (int id, csVariant* value)
{
  METHOD_PROLOGUE (csGraphics3DSoftware, XConfig3DSoft);
  value->type = config_options[id].type;
  switch (id)
  {
    case 0: value->v.bVal = pThis->do_interlaced != -1; break;
    case 1: value->v.bVal = pThis->do_lighting; break;
    case 2: value->v.bVal = pThis->do_transp; break;
    case 3: value->v.bVal = pThis->do_textured; break;
    case 4: value->v.bVal = pThis->do_texel_filt; break;
    case 5: value->v.bVal = pThis->do_mmx; break;
    case 6: value->v.bVal = pThis->do_light_frust; break;
    case 7: value->v.fVal = pThis->txtmgr->Gamma; break;
    case 8: value->v.fVal = pThis->zdist_mipmap1; break;
    case 9: value->v.fVal = pThis->zdist_mipmap2; break;
    case 10: value->v.fVal = pThis->zdist_mipmap3; break;
    default: return E_FAIL;
  }
  return S_OK;
}

STDMETHODIMP IXConfig3DSoft::GetNumberOptions (int& num)
{
  METHOD_PROLOGUE (csGraphics3DSoftware, XConfig3DSoft);
  num = 11 ;
  return S_OK;
}

STDMETHODIMP IXConfig3DSoft::GetOptionDescription (int idx, csOptionDescription* option)
{
  METHOD_PROLOGUE (csGraphics3DSoftware, XConfig3DSoft);
  if (idx < 0 || idx >= 11 ) return E_FAIL;
  *option = config_options[idx];
  return S_OK;
}



 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]