]> source.dussan.org Git - tigervnc.git/commitdiff
Add test to measure framebuffer performance
authorPierre Ossman <ossman@cendio.se>
Tue, 20 Dec 2016 11:32:37 +0000 (12:32 +0100)
committerPierre Ossman <ossman@cendio.se>
Wed, 4 Jan 2017 14:37:34 +0000 (15:37 +0100)
tests/CMakeLists.txt
tests/fbperf.cxx [new file with mode: 0644]
tests/util.cxx
tests/util.h

index bfd69dcd5d1989421e22e02401658aa99db4602d..164660a323c572b61bb0b8341bda2f2db4211c03 100644 (file)
@@ -16,3 +16,20 @@ target_link_libraries(encperf test_util rfb)
 
 add_executable(hostport hostport.cxx)
 target_link_libraries(hostport rfb)
+
+set(FBPERF_SOURCES
+  fbperf.cxx
+  ../vncviewer/FLTKPixelBuffer.cxx
+  ../vncviewer/PlatformPixelBuffer.cxx)
+if(WIN32)
+  set(FBPERF_SOURCES ${FBPERF_SOURCES} ../vncviewer/Win32PixelBuffer.cxx)
+elseif(APPLE)
+  set(FBPERF_SOURCES ${FBPERF_SOURCES} ../vncviewer/OSXPixelBuffer.cxx)
+else()
+  set(FBPERF_SOURCES ${FBPERF_SOURCES} ../vncviewer/X11PixelBuffer.cxx)
+endif()
+add_executable(fbperf ${FBPERF_SOURCES})
+target_link_libraries(fbperf test_util rfb ${FLTK_LIBRARIES} ${GETTEXT_LIBRARIES})
+if(APPLE)
+  target_link_libraries(fbperf "-framework Cocoa" "-framework Carbon")
+endif()
diff --git a/tests/fbperf.cxx b/tests/fbperf.cxx
new file mode 100644 (file)
index 0000000..53334a6
--- /dev/null
@@ -0,0 +1,225 @@
+/* Copyright 2016 Pierre Ossman <ossman@cendio.se> for Cendio AB
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
+ * USA.
+ */
+
+#include <sys/time.h>
+
+#include <FL/Fl.H>
+#include <FL/Fl_Window.H>
+#include <FL/fl_draw.H>
+
+#include <rdr/Exception.h>
+#include <rfb/util.h>
+
+#include "../vncviewer/PlatformPixelBuffer.h"
+#include "../vncviewer/FLTKPixelBuffer.h"
+
+#if defined(WIN32)
+#include "../vncviewer/Win32PixelBuffer.h"
+#elif defined(__APPLE__)
+#include "../vncviewer/OSXPixelBuffer.h"
+#else
+#include "../vncviewer/X11PixelBuffer.h"
+#endif
+
+#include "util.h"
+
+class TestWindow: public Fl_Window {
+public:
+  TestWindow();
+  ~TestWindow();
+
+  virtual void draw();
+
+protected:
+  virtual void flush();
+
+  void update();
+  virtual void changefb();
+
+  static void timer(void* data);
+
+public:
+  unsigned long long pixels, frames;
+  double time;
+
+protected:
+  PlatformPixelBuffer* fb;
+};
+
+class PartialTestWindow: public TestWindow {
+protected:
+  virtual void changefb();
+};
+
+TestWindow::TestWindow() :
+  Fl_Window(1024, 768, "Framebuffer Performance Test")
+{
+  rdr::U32 pixel;
+
+  pixels = 0;
+  frames = 0;
+  time = 0;
+
+  try {
+#if defined(WIN32)
+    fb = new Win32PixelBuffer(w(), h());
+#elif defined(__APPLE__)
+    fb = new OSXPixelBuffer(w(), h());
+#else
+    fb = new X11PixelBuffer(w(), h());
+#endif
+  } catch (rdr::Exception& e) {
+    fb = new FLTKPixelBuffer(w(), h());
+  }
+
+  pixel = 0;
+  fb->fillRect(fb->getRect(), &pixel);
+}
+
+TestWindow::~TestWindow()
+{
+  delete fb;
+
+  Fl::remove_idle(timer, this);
+}
+
+void TestWindow::draw()
+{
+  int X, Y, W, H;
+
+  // We cannot update the damage region from inside the draw function,
+  // so delegate this to an idle function
+  Fl::add_idle(timer, this);
+
+  // Check what actually needs updating
+  fl_clip_box(0, 0, w(), h(), X, Y, W, H);
+  if ((W == 0) || (H == 0))
+    return;
+
+  fb->draw(X, Y, X, Y, W, H);
+
+  pixels += W*H;
+  frames++;
+}
+
+void TestWindow::flush()
+{
+  startTimeCounter();
+  Fl_Window::flush();
+#if !defined(WIN32) && !defined(__APPLE__)
+  // Make sure we measure any work we queue up
+  XSync(fl_display, False);
+#endif
+  endTimeCounter();
+
+  time += getTimeCounter();
+}
+
+void TestWindow::update()
+{
+  rfb::Rect r;
+
+  startTimeCounter();
+
+  while (fb->isRendering())
+    Fl::wait();
+
+  changefb();
+
+  r = fb->getDamage();
+  damage(FL_DAMAGE_USER1, r.tl.x, r.tl.y, r.width(), r.height());
+
+#if !defined(WIN32) && !defined(__APPLE__)
+  // Make sure we measure any work we queue up
+  XSync(fl_display, False);
+#endif
+
+  endTimeCounter();
+
+  time += getTimeCounter();
+}
+
+void TestWindow::changefb()
+{
+  rdr::U32 pixel;
+
+  pixel = rand();
+  fb->fillRect(fb->getRect(), &pixel);
+}
+
+void TestWindow::timer(void* data)
+{
+  TestWindow* self;
+
+  Fl::remove_idle(timer, data);
+
+  self = (TestWindow*)data;
+  self->update();
+}
+
+void PartialTestWindow::changefb()
+{
+  rfb::Rect r;
+  rdr::U32 pixel;
+
+  r = fb->getRect();
+  r.tl.x += w() / 4;
+  r.tl.y += h() / 4;
+  r.br.x -= w() / 4;
+  r.br.y -= h() / 4;
+
+  pixel = rand();
+  fb->fillRect(r, &pixel);
+}
+
+static void dotest(TestWindow* win)
+{
+  struct timeval start;
+  char s[1024];
+
+  win->show();
+
+  gettimeofday(&start, NULL);
+  while (rfb::msSince(&start) < 10000)
+    Fl::wait();
+
+  fprintf(stderr, "Rendering time: %g ms/frame\n",
+          win->time * 1000.0 / win->frames);
+  rfb::siPrefix(win->pixels / win->time,
+                "pixels/s", s, sizeof(s));
+  fprintf(stderr, "Rendering rate: %s\n", s);
+}
+
+int main(int argc, char** argv)
+{
+  TestWindow* win;
+
+  fprintf(stderr, "Full window update:\n\n");
+  win = new TestWindow();
+  dotest(win);
+  delete win;
+  fprintf(stderr, "\n");
+
+  fprintf(stderr, "Partial window update:\n\n");
+  win = new PartialTestWindow();
+  dotest(win);
+  delete win;
+  fprintf(stderr, "\n");
+
+  return 0;
+}
index 4683d3513b78abf6b3bbe7cfbb3143cbbde8d0a4..17a8369888cde0aa3ad7987e9cc9bfd07986fb02 100644 (file)
@@ -24,6 +24,7 @@
 #include <windows.h>
 #else
 #include <sys/resource.h>
+#include <sys/time.h>
 #endif
 
 #include "util.h"
@@ -132,3 +133,46 @@ double getCpuCounter(cpucounter_t c)
 
   return sysSeconds + userSeconds;
 }
+
+#ifdef WIN32
+static LARGE_INTEGER timeStart, timeEnd;
+#else
+static struct timeval timeStart, timeEnd;
+#endif
+
+void startTimeCounter(void)
+{
+#ifdef WIN32
+  QueryPerformanceCounter(&timeStart);
+#else
+  gettimeofday(&timeStart, NULL);
+#endif
+}
+
+void endTimeCounter(void)
+{
+#ifdef WIN32
+  QueryPerformanceCounter(&timeEnd);
+#else
+  gettimeofday(&timeEnd, NULL);
+#endif
+}
+
+double getTimeCounter(void)
+{
+  double time;
+
+#ifdef WIN32
+  LARGE_INTEGER freq;
+
+  QueryPerformanceFrequency(&freq);
+
+  time = timeEnd.QuadPart - timeStart.QuadPart;
+  time = time / freq.QuadPart;
+#else
+  time = (double)timeEnd.tv_sec - timeStart.tv_sec;
+  time += (double)(timeEnd.tv_usec - timeStart.tv_usec) / 1000000.0;
+#endif
+
+  return time;
+}
index 16f2ba2f7d9f3b054562a855c959cc1bf99f04ce..2b8ab4a8d2d060ecfb110b9a56c8b78083ea8635 100644 (file)
@@ -34,4 +34,9 @@ void endCpuCounter(cpucounter_t c);
 
 double getCpuCounter(cpucounter_t c);
 
+void startTimeCounter(void);
+void endTimeCounter(void);
+
+double getTimeCounter(void);
+
 #endif