2

I compared skia with gdi painting on windows. both drawing 98000 random lines. to my suprise that skia is far low efficiency than gdi(the skia painting cost 1600ms, while gdi cost 0ms). my testing code was paste below. any suggestions?

bool PaintCompare() {
    //generate ramdon points
    std::default_random_engine e(std::chrono::high_resolution_clock::now().time_since_epoch().count());
    std::uniform_real_distribution<float> u(10, 500);
    SkPoint pts[100];
    for (int i = 0; i<100; i++)
        pts[i].set(u(e), u(e));
    SkPaint paint;
    paint.setColor(SkColorSetRGB(255, 0, 0));

    //create skia canvas
    sk_sp<SkSurface> rasterSurface(
        SkSurface::MakeRasterN32Premul(600, 600));
    SkCanvas* canvas = rasterSurface->getCanvas();

    //draw lines with skia
    auto start = std::chrono::high_resolution_clock::now();
    for (int i = 0; i<1000; i++)
    {
        for (int j = 1; j<99; j++)
        {
            canvas->drawLine(pts[j].fX, pts[j].fY, pts[j + 1].fX, pts[j + 1].fY, paint);
        }
    }
    auto cost = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - start);
    sk_sp<SkImage> img(rasterSurface->makeImageSnapshot());
    if (!img) { return false; }
    SkBitmap skBmp;
    if (!img->asLegacyBitmap(&skBmp, SkImage::kRO_LegacyBitmapMode)) {
        return false;
    }

    //show bitmap on hdc
    BITMAPINFO bmi;
    memset(&bmi, 0, sizeof(bmi));
    bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmi.bmiHeader.biWidth = 600;
    bmi.bmiHeader.biHeight = -600; // top-down image 
    bmi.bmiHeader.biPlanes = 1;
    bmi.bmiHeader.biBitCount = 32;
    bmi.bmiHeader.biCompression = BI_RGB;
    bmi.bmiHeader.biSizeImage = 0;

    HDC hdc = GetDC();
    LPVOID pBits = NULL;
    HBITMAP hBmp = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, &pBits, 0, 0);
    skBmp.copyPixelsTo(pBits, skBmp.getSize());
    CDC memdc;
    memdc.CreateCompatibleDC(hdc);
    memdc.SelectBitmap(hBmp);
    BitBlt(hdc, 0, 0, 600, 600, memdc, 0, 0, SRCCOPY);
    memdc.DeleteDC();


    //draw with gdi
    CPen pen;
    pen.CreatePen(PS_SOLID, 1, RGB(0, 255, 0));
    RECT rc{ 0,0,600,600 };
    CBitmap bmp;
    bmp.CreateCompatibleBitmap(hdc, 600, 600);
    memdc.CreateCompatibleDC(hdc);
    memdc.SelectBitmap(bmp);
    memdc.FillSolidRect(&rc, RGB(0, 0, 0));
    memdc.SelectPen(pen);
    start = std::chrono::high_resolution_clock::now();
    for (int i = 0; i<1000; i++)
    {
        for (int j = 1; j<99; j++)
        {
            memdc.MoveTo(pts[j].fX, pts[j].fY);
            memdc.LineTo(pts[j + 1].fX, pts[j + 1].fY);
        }
    }
    auto cost2 = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - start);

    //copy bitmap to window
    BitBlt(hdc, 700, 0, 600, 600, memdc, 0, 0, SRCCOPY);
    ReleaseDC(hdc);
    memdc.DeleteDC();

    //wchar_t buf[256];
    //wsprintf(buf, L"left cost=%I64d, right cost=%I64d", cost.count(), cost2.count());
    //GetParent().SetWindowText(buf);

    //cost == 1596615 microseconds
    //cost2 == 107253 microseconds
}
qianyi
  • 71
  • 6
  • Please post a [Minimal, Complete, Verifiable Example](http://stackoverflow.com/help/mcve). – Jonathan Mee Aug 04 '16 at 12:03
  • 1
    sorry, i don't know how to post more code here. the code i paste above is the core. as you can see i calc time spent on drawing with skia and gdi . that cost and cost2 are varables contain the spent time. – qianyi Aug 05 '16 at 03:46

1 Answers1

3

I found the problem finally. i give the result in debug mode!

in debug mode that skia with raster backend is 20 times slower than gdi. however in release mode skia with raster backend is 4-5 times slower than gdi.

i had another test that skia uses opengl as backend. the result shows skia and gdi spend almost the same time. skia is about 15% slower than gdi.

qianyi
  • 71
  • 6