]> git.saurik.com Git - wxWidgets.git/blobdiff - tests/benchmarks/graphics.cpp
Really disable wxAny tests under wxOSX.
[wxWidgets.git] / tests / benchmarks / graphics.cpp
index 4ebb8541c3304d67ab7d908ff76b963bc43857be..19ebbb6a25c7e4c30968b2dacc48029d4df0fc77 100644 (file)
 #include "wx/dcclient.h"
 #include "wx/dcmemory.h"
 #include "wx/dcgraph.h"
 #include "wx/dcclient.h"
 #include "wx/dcmemory.h"
 #include "wx/dcgraph.h"
+#include "wx/image.h"
+#include "wx/rawbmp.h"
 #include "wx/stopwatch.h"
 #include "wx/crt.h"
 
 #include "wx/stopwatch.h"
 #include "wx/crt.h"
 
+#if wxUSE_GLCANVAS
+    #include "wx/glcanvas.h"
+    #ifdef _MSC_VER
+        #pragma comment(lib, "opengl32")
+    #endif
+#endif // wxUSE_GLCANVAS
+
+#if wxUSE_GLCANVAS
+
+GLuint g_texture;
+wxImage g_image;
+
+void InitializeTexture(int w, int h)
+{
+    glGenTextures(1, &g_texture);
+    glBindTexture(GL_TEXTURE_2D, g_texture);
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+    g_image.Create(w, h, false /* don't clear */);
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+    glTexImage2D(GL_TEXTURE_2D, 0,
+                 GL_RGB, g_image.GetWidth(), g_image.GetHeight(), 0,
+                 GL_RGB, GL_UNSIGNED_BYTE, g_image.GetData());
+}
+#endif // wxUSE_GLCANVAS
+
 struct GraphicsBenchmarkOptions
 {
     GraphicsBenchmarkOptions()
 struct GraphicsBenchmarkOptions
 {
     GraphicsBenchmarkOptions()
@@ -27,14 +56,42 @@ struct GraphicsBenchmarkOptions
         width = 800;
         height = 600;
 
         width = 800;
         height = 600;
 
-        numLines = 10000;
+        numIters = 1000;
+
+        testBitmaps =
+        testImages =
+        testLines =
+        testRawBitmaps =
+        testRectangles = false;
+
+        usePaint =
+        useClient =
+        useMemory = false;
+
+        useDC =
+        useGC =
+        useGL = false;
     }
 
     long mapMode,
          penWidth,
          width,
          height,
     }
 
     long mapMode,
          penWidth,
          width,
          height,
-         numLines;
+         numIters;
+
+    bool testBitmaps,
+         testImages,
+         testLines,
+         testRawBitmaps,
+         testRectangles;
+
+    bool usePaint,
+         useClient,
+         useMemory;
+
+    bool useDC,
+         useGC,
+         useGL;
 } opts;
 
 class GraphicsBenchmarkFrame : public wxFrame
 } opts;
 
 class GraphicsBenchmarkFrame : public wxFrame
@@ -43,71 +100,178 @@ public:
     GraphicsBenchmarkFrame()
         : wxFrame(NULL, wxID_ANY, "wxWidgets Graphics Benchmark")
     {
     GraphicsBenchmarkFrame()
         : wxFrame(NULL, wxID_ANY, "wxWidgets Graphics Benchmark")
     {
-        Connect(wxEVT_CREATE,
-                wxWindowCreateEventHandler(GraphicsBenchmarkFrame::OnCreate));
-        Connect(wxEVT_PAINT,
-                wxPaintEventHandler(GraphicsBenchmarkFrame::OnPaint));
+        SetClientSize(opts.width, opts.height);
+
+#if wxUSE_GLCANVAS
+        m_glCanvas = NULL;
+
+        if ( opts.useGL )
+        {
+            m_glCanvas = new wxGLCanvas(this, wxID_ANY, NULL,
+                                        wxPoint(0, 0),
+                                        wxSize(opts.width, opts.height));
+            m_glContext = new wxGLContext(m_glCanvas);
+            m_glContext->SetCurrent(*m_glCanvas);
+
+            glViewport(0, 0, opts.width, opts.height);
+            glMatrixMode(GL_PROJECTION);
+            glLoadIdentity();
+            glOrtho(-1, 1, -1, 1, -1, 1);
+            glMatrixMode(GL_MODELVIEW);
+            glLoadIdentity();
+
+            InitializeTexture(opts.width, opts.height);
+
+            m_glCanvas->Connect(
+                wxEVT_PAINT,
+                wxPaintEventHandler(GraphicsBenchmarkFrame::OnGLRender),
+                NULL,
+                this
+            );
+        }
+        else // Not using OpenGL
+#endif // wxUSE_GLCANVAS
+        {
+            Connect(wxEVT_PAINT,
+                    wxPaintEventHandler(GraphicsBenchmarkFrame::OnPaint));
+        }
+
+        Connect(wxEVT_SIZE, wxSizeEventHandler(GraphicsBenchmarkFrame::OnSize));
 
         m_bitmap.Create(64, 64, 32);
 
         Show();
 
         m_bitmap.Create(64, 64, 32);
 
         Show();
-        SetClientSize(opts.width, opts.height);
     }
 
     }
 
+#if wxUSE_GLCANVAS
+    virtual ~GraphicsBenchmarkFrame()
+    {
+        delete m_glContext;
+    }
+#endif // wxUSE_GLCANVAS
+
 private:
 private:
-    void OnCreate(wxWindowCreateEvent&)
+    // Just change the image in some (quick) way to show that it's really being
+    // updated on screen.
+    void UpdateRGB(unsigned char* data, int n)
     {
     {
-        wxClientDC dc(this);
-        BenchmarkLines("dc   client", dc);
-        BenchmarkRectangles("dc   client", dc);
-        BenchmarkBitmaps("dc   client", dc);
+        for ( int y = 0; y < opts.height; ++y )
+        {
+            memset(data, n % 256, 3*opts.width);
+
+            data += 3*opts.width;
+            n++;
+        }
+    }
+
+#if wxUSE_GLCANVAS
+    void OnGLRender(wxPaintEvent& WXUNUSED(event))
+    {
+        m_glContext->SetCurrent(*m_glCanvas);
+        glEnable(GL_TEXTURE_2D);
+
+        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        wxPrintf("Benchmarking %s: ", "OpenGL images");
+        fflush(stdout);
+
+        wxStopWatch sw;
+        for ( int n = 0; n < opts.numIters; n++ )
+        {
+            UpdateRGB(g_image.GetData(), n);
+
+            glTexSubImage2D(GL_TEXTURE_2D, 0,
+                            0, 0, opts.width, opts.height,
+                            GL_RGB, GL_UNSIGNED_BYTE, g_image.GetData());
+            glBegin(GL_QUADS);
+                glTexCoord2f(0, 0);
+                glVertex2f(-1.0, -1.0);
+
+                glTexCoord2f(0, 1);
+                glVertex2f(-1.0, 1.0);
 
 
-        wxGCDC gcdc( dc );
-        BenchmarkLines("gcdc client", gcdc);
-        BenchmarkRectangles("gcdc client", gcdc);
-        BenchmarkBitmaps("gcdc client", gcdc);
+                glTexCoord2f(1, 1);
+                glVertex2f(1.0, 1.0);
 
 
-        wxBitmap bmp(opts.width, opts.height);
-        wxMemoryDC dc2(bmp);
-        BenchmarkLines("dc   memory", dc2);
-        BenchmarkRectangles("dc   memory", dc2);
-        BenchmarkBitmaps("dc   memory", dc2);
+                glTexCoord2f(1, 0);
+                glVertex2f(1.0, -1.0);
+            glEnd();
 
 
-        wxGCDC gcdc2( dc2 );
-        BenchmarkLines("gcdc memory", gcdc2);
-        BenchmarkRectangles("gcdc memory", gcdc2);
-        BenchmarkBitmaps("gcdc memory", gcdc2);
+            m_glCanvas->SwapBuffers();
+        }
+
+        const long t = sw.Time();
+
+        wxPrintf("%ld images done in %ldms = %gus/image or %ld FPS\n",
+                 opts.numIters, t, (1000. * t)/opts.numIters,
+                 (1000*opts.numIters + t - 1)/t);
+
+        wxTheApp->ExitMainLoop();
     }
     }
+#endif // wxUSE_GLCANVAS
 
     void OnPaint(wxPaintEvent& WXUNUSED(event))
     {
 
     void OnPaint(wxPaintEvent& WXUNUSED(event))
     {
-        wxPaintDC dc(this);
-        BenchmarkLines("dc    paint", dc);
-        BenchmarkRectangles("dc    paint", dc);
-        BenchmarkBitmaps("dc    paint", dc);
+        if ( opts.usePaint )
+        {
+            wxPaintDC dc(this);
+            wxGCDC gcdc(dc);
+            BenchmarkDCAndGC("paint", dc, gcdc);
+        }
+
+        if ( opts.useClient )
+        {
+            wxClientDC dc(this);
+            wxGCDC gcdc(dc);
+            BenchmarkDCAndGC("client", dc, gcdc);
+        }
 
 
-        wxGCDC gcdc( dc );
-        BenchmarkLines("gcdc  paint", gcdc);
-        BenchmarkRectangles("gcdc  paint", gcdc);
-        BenchmarkBitmaps("gcdc  paint", gcdc);
+        if ( opts.useMemory )
+        {
+            wxBitmap bmp(opts.width, opts.height);
+            wxMemoryDC dc(bmp);
+            wxGCDC gcdc(dc);
+            BenchmarkDCAndGC("memory", dc, gcdc);
+        }
 
         wxTheApp->ExitMainLoop();
     }
 
 
         wxTheApp->ExitMainLoop();
     }
 
+    void BenchmarkDCAndGC(const char* dckind, wxDC& dc, wxGCDC& gcdc)
+    {
+        if ( opts.useDC )
+            BenchmarkAll(wxString::Format("%6s DC", dckind), dc);
+        if ( opts.useGC )
+            BenchmarkAll(wxString::Format("%6s GC", dckind), gcdc);
+    }
 
 
-    void BenchmarkLines(const char *msg, wxDC& dc)
+    void BenchmarkAll(const wxString& msg, wxDC& dc)
     {
     {
+        BenchmarkBitmaps(msg, dc);
+        BenchmarkImages(msg, dc);
+        BenchmarkLines(msg, dc);
+        BenchmarkRawBitmaps(msg, dc);
+        BenchmarkRectangles(msg, dc);
+    }
+
+    void BenchmarkLines(const wxString& msg, wxDC& dc)
+    {
+        if ( !opts.testLines )
+            return;
+
         if ( opts.mapMode != 0 )
             dc.SetMapMode((wxMappingMode)opts.mapMode);
         if ( opts.penWidth != 0 )
             dc.SetPen(wxPen(*wxWHITE, opts.penWidth));
 
         if ( opts.mapMode != 0 )
             dc.SetMapMode((wxMappingMode)opts.mapMode);
         if ( opts.penWidth != 0 )
             dc.SetPen(wxPen(*wxWHITE, opts.penWidth));
 
-        wxPrintf("Benchmarking %s DC: ", msg);
+        wxPrintf("Benchmarking %s: ", msg);
+        fflush(stdout);
 
         wxStopWatch sw;
         int x = 0,
             y = 0;
 
         wxStopWatch sw;
         int x = 0,
             y = 0;
-        for ( int n = 0; n < opts.numLines; n++ )
+        for ( int n = 0; n < opts.numIters; n++ )
         {
             int x1 = rand() % opts.width,
                 y1 = rand() % opts.height;
         {
             int x1 = rand() % opts.width,
                 y1 = rand() % opts.height;
@@ -121,12 +285,15 @@ private:
         const long t = sw.Time();
 
         wxPrintf("%ld lines done in %ldms = %gus/line\n",
         const long t = sw.Time();
 
         wxPrintf("%ld lines done in %ldms = %gus/line\n",
-                 opts.numLines, t, (1000. * t)/opts.numLines);
+                 opts.numIters, t, (1000. * t)/opts.numIters);
     }
 
 
     }
 
 
-    void BenchmarkRectangles(const char *msg, wxDC& dc)
+    void BenchmarkRectangles(const wxString& msg, wxDC& dc)
     {
     {
+        if ( !opts.testRectangles )
+            return;
+
         if ( opts.mapMode != 0 )
             dc.SetMapMode((wxMappingMode)opts.mapMode);
         if ( opts.penWidth != 0 )
         if ( opts.mapMode != 0 )
             dc.SetMapMode((wxMappingMode)opts.mapMode);
         if ( opts.penWidth != 0 )
@@ -134,10 +301,11 @@ private:
 
         dc.SetBrush( *wxRED_BRUSH );
 
 
         dc.SetBrush( *wxRED_BRUSH );
 
-        wxPrintf("Benchmarking %s DC: ", msg);
+        wxPrintf("Benchmarking %s: ", msg);
+        fflush(stdout);
 
         wxStopWatch sw;
 
         wxStopWatch sw;
-        for ( int n = 0; n < opts.numLines; n++ )
+        for ( int n = 0; n < opts.numIters; n++ )
         {
             int x = rand() % opts.width,
                 y = rand() % opts.height;
         {
             int x = rand() % opts.width,
                 y = rand() % opts.height;
@@ -148,20 +316,24 @@ private:
         const long t = sw.Time();
 
         wxPrintf("%ld rects done in %ldms = %gus/rect\n",
         const long t = sw.Time();
 
         wxPrintf("%ld rects done in %ldms = %gus/rect\n",
-                 opts.numLines, t, (1000. * t)/opts.numLines);
+                 opts.numIters, t, (1000. * t)/opts.numIters);
     }
 
     }
 
-    void BenchmarkBitmaps(const char *msg, wxDC& dc)
+    void BenchmarkBitmaps(const wxString& msg, wxDC& dc)
     {
     {
+        if ( !opts.testBitmaps )
+            return;
+
         if ( opts.mapMode != 0 )
             dc.SetMapMode((wxMappingMode)opts.mapMode);
         if ( opts.penWidth != 0 )
             dc.SetPen(wxPen(*wxWHITE, opts.penWidth));
 
         if ( opts.mapMode != 0 )
             dc.SetMapMode((wxMappingMode)opts.mapMode);
         if ( opts.penWidth != 0 )
             dc.SetPen(wxPen(*wxWHITE, opts.penWidth));
 
-        wxPrintf("Benchmarking %s DC: ", msg);
+        wxPrintf("Benchmarking %s: ", msg);
+        fflush(stdout);
 
         wxStopWatch sw;
 
         wxStopWatch sw;
-        for ( int n = 0; n < opts.numLines; n++ )
+        for ( int n = 0; n < opts.numIters; n++ )
         {
             int x = rand() % opts.width,
                 y = rand() % opts.height;
         {
             int x = rand() % opts.width,
                 y = rand() % opts.height;
@@ -172,11 +344,90 @@ private:
         const long t = sw.Time();
 
         wxPrintf("%ld bitmaps done in %ldms = %gus/bitmap\n",
         const long t = sw.Time();
 
         wxPrintf("%ld bitmaps done in %ldms = %gus/bitmap\n",
-                 opts.numLines, t, (1000. * t)/opts.numLines);
+                 opts.numIters, t, (1000. * t)/opts.numIters);
+    }
+
+    void BenchmarkImages(const wxString& msg, wxDC& dc)
+    {
+        if ( !opts.testImages )
+            return;
+
+        if ( opts.mapMode != 0 )
+            dc.SetMapMode((wxMappingMode)opts.mapMode);
+
+        wxPrintf("Benchmarking %s: ", msg);
+        fflush(stdout);
+
+        wxImage image(wxSize(opts.width, opts.height), false /* don't clear */);
+
+        wxStopWatch sw;
+        for ( int n = 0; n < opts.numIters; n++ )
+        {
+            UpdateRGB(image.GetData(), n);
+            dc.DrawBitmap(image, 0, 0);
+        }
+
+        const long t = sw.Time();
+
+        wxPrintf("%ld images done in %ldms = %gus/image or %ld FPS\n",
+                 opts.numIters, t, (1000. * t)/opts.numIters,
+                 (1000*opts.numIters + t - 1)/t);
+    }
+
+    void BenchmarkRawBitmaps(const wxString& msg, wxDC& dc)
+    {
+        if ( !opts.testRawBitmaps )
+            return;
+
+        if ( opts.mapMode != 0 )
+            dc.SetMapMode((wxMappingMode)opts.mapMode);
+
+        wxPrintf("Benchmarking %s: ", msg);
+        fflush(stdout);
+
+        wxBitmap bitmap(opts.width, opts.height, 24);
+        wxNativePixelData data(bitmap);
+
+        wxStopWatch sw;
+        for ( int n = 0; n < opts.numIters; n++ )
+        {
+            unsigned char c = n % 256;
+            {
+                wxNativePixelData::Iterator p(data);
+                for ( int y = 0; y < opts.height; ++y )
+                {
+                    wxNativePixelData::Iterator rowStart = p;
+
+                    for ( int x = 0; x < opts.width; ++x )
+                    {
+                        p.Red() =
+                        p.Green() =
+                        p.Blue() = c;
+                        ++p;
+                    }
+
+                    p = rowStart;
+                    p.OffsetY(data, 1);
+                    c++;
+                }
+            }
+
+            dc.DrawBitmap(bitmap, 0, 0);
+        }
+
+        const long t = sw.Time();
+
+        wxPrintf("%ld raw bitmaps done in %ldms = %gus/bitmap or %ld FPS\n",
+                 opts.numIters, t, (1000. * t)/opts.numIters,
+                 (1000*opts.numIters + t - 1)/t);
     }
 
 
     wxBitmap m_bitmap;
     }
 
 
     wxBitmap m_bitmap;
+#if wxUSE_GLCANVAS
+    wxGLCanvas* m_glCanvas;
+    wxGLContext* m_glContext;
+#endif // wxUSE_GLCANVAS
 };
 
 class GraphicsBenchmarkApp : public wxApp
 };
 
 class GraphicsBenchmarkApp : public wxApp
@@ -186,11 +437,25 @@ public:
     {
         static const wxCmdLineEntryDesc desc[] =
         {
     {
         static const wxCmdLineEntryDesc desc[] =
         {
+            { wxCMD_LINE_SWITCH, "",  "bitmaps" },
+            { wxCMD_LINE_SWITCH, "",  "images" },
+            { wxCMD_LINE_SWITCH, "",  "lines" },
+            { wxCMD_LINE_SWITCH, "",  "rawbmp" },
+            { wxCMD_LINE_SWITCH, "",  "rectangles" },
+            { wxCMD_LINE_SWITCH, "",  "paint" },
+            { wxCMD_LINE_SWITCH, "",  "client" },
+            { wxCMD_LINE_SWITCH, "",  "memory" },
+            { wxCMD_LINE_SWITCH, "",  "dc" },
+            { wxCMD_LINE_SWITCH, "",  "gc" },
+#if wxUSE_GLCANVAS
+            { wxCMD_LINE_SWITCH, "",  "gl" },
+#endif // wxUSE_GLCANVAS
             { wxCMD_LINE_OPTION, "m", "map-mode", "", wxCMD_LINE_VAL_NUMBER },
             { wxCMD_LINE_OPTION, "p", "pen-width", "", wxCMD_LINE_VAL_NUMBER },
             { wxCMD_LINE_OPTION, "w", "width", "", wxCMD_LINE_VAL_NUMBER },
             { wxCMD_LINE_OPTION, "h", "height", "", wxCMD_LINE_VAL_NUMBER },
             { wxCMD_LINE_OPTION, "m", "map-mode", "", wxCMD_LINE_VAL_NUMBER },
             { wxCMD_LINE_OPTION, "p", "pen-width", "", wxCMD_LINE_VAL_NUMBER },
             { wxCMD_LINE_OPTION, "w", "width", "", wxCMD_LINE_VAL_NUMBER },
             { wxCMD_LINE_OPTION, "h", "height", "", wxCMD_LINE_VAL_NUMBER },
-            { wxCMD_LINE_OPTION, "L", "lines", "", wxCMD_LINE_VAL_NUMBER },
+            { wxCMD_LINE_OPTION, "I", "images", "", wxCMD_LINE_VAL_NUMBER },
+            { wxCMD_LINE_OPTION, "N", "number-of-iterations", "", wxCMD_LINE_VAL_NUMBER },
             { wxCMD_LINE_NONE },
         };
 
             { wxCMD_LINE_NONE },
         };
 
@@ -208,9 +473,57 @@ public:
             return false;
         if ( parser.Found("h", &opts.height) && opts.height < 1 )
             return false;
             return false;
         if ( parser.Found("h", &opts.height) && opts.height < 1 )
             return false;
-        if ( parser.Found("L", &opts.numLines) && opts.numLines < 1 )
+        if ( parser.Found("N", &opts.numIters) && opts.numIters < 1 )
             return false;
 
             return false;
 
+        opts.testBitmaps = parser.Found("bitmaps");
+        opts.testImages = parser.Found("images");
+        opts.testLines = parser.Found("lines");
+        opts.testRawBitmaps = parser.Found("rawbmp");
+        opts.testRectangles = parser.Found("rectangles");
+        if ( !(opts.testBitmaps || opts.testImages || opts.testLines
+                    || opts.testRawBitmaps || opts.testRectangles) )
+        {
+            // Do everything by default.
+            opts.testBitmaps =
+            opts.testImages =
+            opts.testLines =
+            opts.testRawBitmaps =
+            opts.testRectangles = true;
+        }
+
+        opts.usePaint = parser.Found("paint");
+        opts.useClient = parser.Found("client");
+        opts.useMemory = parser.Found("memory");
+        if ( !(opts.usePaint || opts.useClient || opts.useMemory) )
+        {
+            opts.usePaint =
+            opts.useClient =
+            opts.useMemory = true;
+        }
+
+        opts.useDC = parser.Found("dc");
+        opts.useGC = parser.Found("gc");
+#if wxUSE_GLCANVAS
+        opts.useGL = parser.Found("gl");
+        if ( opts.useGL )
+        {
+            if ( opts.useDC || opts.useGC )
+            {
+                wxLogError("Can't use both OpenGL and normal graphics.");
+                return false;
+            }
+        }
+        else // Not using OpenGL
+#endif // wxUSE_GLCANVAS
+        {
+            if ( !(opts.useDC || opts.useGC) )
+            {
+                opts.useDC =
+                opts.useGC = true;
+            }
+        }
+
         return true;
     }
 
         return true;
     }