AGG和GDI+图形渲染效率的对比

一、起因:

之前我用agg封装实现了一个类似GDI+的接口(AGGDI+)。但是测试下来,大部分情况下效率要低于GDI+。这使我怀疑AGG官方所宣称的其所具有的高性能表现。然而,在那个同样是封装AGG实现GDI+的AggPlus中的测试表明:AGG的效率某些情况下超过GDI+10倍之多。显然我是难以相信AGG在效率上的这种优势的。于是下决心对AGG和GDI+的图形渲染效率进行比较。

二、比较的具体细节:

首先,我决定先比较下两者在光珊化速度上的表现。同时由于AGG宣称其反走样技术的优质和高效,所以决定先只比较反走样模式下,两者渲染多边形的效率。同时,对颜色混合的过程也进行了简单的测试。主要针对非alpha混合和alpha混合两种模式下的填充进行比对。比较过程如下:

1、agg和gdi+生成同样大小的32位位图(可调整长宽)

2、根据位图大小生成位图范围内的随机的多边形(多边形边数和个数可调整)

3、根据多边形个数生成同样个数的随机颜色(带alpha和不带alpha的)

4、开始计时

5、agg或者gdi+分别使用rasterizer和graphics进行光栅化和填充

6、结束计时

7、agg或者gdi+分别保存渲染得到的图片

测试的具体环境:由于gdi+似乎是用vc7或者vc8编译生成的。所以我在vc2005下运行了测试程序。当然,在vc6下也是可以的。只是vc6的优化做得不够好。同时在c++代码编译方面有几个bug(当然,为了避免这些bug,代码已经修改是可以在vc6下编译运行的)。

核心测试代码如下:
// ------------------------------------------------------------TestAggRender
template <class PolygonSource, class ColorSource>
double TestAggRender(const PolygonSource& polygons,
      const ColorSource& colors,
      bool bAa = true,
      bool bFillEvenOdd = true)
{
typedef typename PolygonSource::polygon_type PolygonType;
agg::pixel_map bmp;
bmp.create(PolygonType::PolygonRangeRight - PolygonType::PolygonRangeLeft,
   PolygonType::PolygonRangeBottom - PolygonType::PolygonRangeTop, agg::org_color32, 255);
agg::rendering_buffer rbuf(bmp.buf(), bmp.width(), bmp.height(), -bmp.stride());
agg::pixfmt_bgra32 pixfmt(rbuf);
agg::renderer_base<agg::pixfmt_bgra32> renb(pixfmt);

WinClockRecorder recorder;
recorder.BeginRecord();
if (bAa)
{
   for (unsigned i = 0; i < polygons.Count(); ++i)
   {
    typedef typename PolygonSource::polygon_type PolygonType;
    typedef typename PolygonType::point_type PointType;

    const PolygonType& polygon = polygons[i];
    const PointType& pt0 = polygon[0];
    agg::rasterizer_scanline_aa<> ras;
    ras.filling_rule(bFillEvenOdd ? agg::fill_even_odd : agg::fill_non_zero);
    ras.move_to_d(pt0.X(), pt0.Y());
    for (unsigned j = 1; j < PolygonType::PolygonSides; ++j)
    {
     const PointType& pt = polygon[j];
     ras.line_to_d(pt.X(), pt.Y());
    }

    agg::render_scanlines_aa_solid(ras, agg::scanline_p8(), renb,
     agg::rgba8(colors.GetR(i), colors.GetG(i), colors.GetB(i), colors.GetA(i)));
   }
}
else
{

}
double ret = recorder.EndRecord();

char szFileName[256] = {'\0'};
sprintf(szFileName, "%s%d_%d_%d_%d_%f_agg.bmp", agg_folder,
   polygons.Count(), PolygonType::PolygonSides, bAa, bFillEvenOdd, ret);
bmp.save_as_bmp(szFileName);
bmp.destroy();

Sleep(7);
return ret;
}

template <class PolygonSource, class ColorSource>
double TestGdipRender(const PolygonSource& polygons,
       const ColorSource& colors,
       bool bAa = true,
       bool bFillEvenOdd = true)
{
using namespace Gdiplus;
typedef typename PolygonSource::polygon_type PolygonType;
Bitmap bmp(PolygonType::PolygonRangeRight - PolygonType::PolygonRangeLeft,
         PolygonType::PolygonRangeBottom - PolygonType::PolygonRangeTop);
Graphics g(&bmp);
g.Clear(Color::White);

WinClockRecorder recorder;
recorder.BeginRecord();

if (bAa)
{
   g.SetSmoothingMode(SmoothingModeHighQuality);
}

for (unsigned i = 0; i < polygons.Count(); ++i)
{
   typedef typename PolygonSource::polygon_type PolygonType;
   typedef typename PolygonType::point_type PointType;
  
   const PolygonType& polygon = polygons[i];
   const PointType& pt0 = polygon[0];
   GraphicsPath path(bFillEvenOdd ? FillModeAlternate : FillModeWinding);
   for (unsigned j = 0; j < PolygonType::PolygonSides; ++j)
   {
    const PointType& pt = polygon[j];
    path.AddLines(&PointF((REAL)pt.X(),(REAL)pt.Y()), 1);
   }
  
   g.FillPath(&SolidBrush(Color(colors.GetA(i), colors.GetR(i),
    colors.GetG(i), colors.GetB(i))), &path);
}

double ret = recorder.EndRecord();

wchar_t szFileName[256] = {'\0'};
swprintf(szFileName, L"%s%d_%d_%d_%d_%f_gdip.bmp", gdip_folder,
   polygons.Count(), PolygonType::PolygonSides, bAa, bFillEvenOdd, ret);
CLSID bmpClsid;
GetEncoderClsid(L"image/bmp", &bmpClsid);
bmp.Save(szFileName, &bmpClsid, NULL);

Sleep(7);
return ret;
}

 

三、结果

   AGG的表现整体来说超过gdi+。尤其在没有使用aplha混合的时候,效率优势较为明显。但是肯定没有AggPlus所宣称的10倍的优势。(微软的工程师估计会很有意见,呵呵。)

四、不足

这次测试的面还是比较偏。没有考虑到裁剪以及坐标系的转换等渲染参数(反走样、填充模式、坐标系转换、alpha混合模式)的设置以及其他画刷(线性渐变,图案填充等)。

posted @ 2008-12-27 11:18  Kane_BJ  阅读(2995)  评论(1编辑  收藏  举报