From 236c03cc333246be44a20569fcd0d1c2c82c4079 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 4 Jul 2014 14:12:49 +0200 Subject: [PATCH] Add pixel conversion speed test Add a tests directory where we can put tests programs that can be useful during testing. Start with a speed test for the pixel conversion routines. --- CMakeLists.txt | 2 + tests/CMakeLists.txt | 6 ++ tests/pixelconv.cxx | 201 +++++++++++++++++++++++++++++++++++++++++++ tests/util.cxx | 76 ++++++++++++++++ tests/util.h | 27 ++++++ 5 files changed, 312 insertions(+) create mode 100644 tests/CMakeLists.txt create mode 100644 tests/pixelconv.cxx create mode 100644 tests/util.cxx create mode 100644 tests/util.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 2593a64b..bdb1824a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -416,6 +416,8 @@ if(BUILD_VIEWER) add_subdirectory(media) endif() +add_subdirectory(tests) + include(cmake/BuildPackages.cmake) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 00000000..fd47c15a --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,6 @@ +include_directories(${CMAKE_SOURCE_DIR}/common) + +add_library(test_util STATIC util.cxx) + +add_executable(pixelconv pixelconv.cxx) +target_link_libraries(pixelconv test_util rfb) diff --git a/tests/pixelconv.cxx b/tests/pixelconv.cxx new file mode 100644 index 00000000..ef9d3aac --- /dev/null +++ b/tests/pixelconv.cxx @@ -0,0 +1,201 @@ +#include +#include +#include +#include + +#include +#include + +#include "util.h" + +static const int tile = 64; +static const int fbsize = 4096; + +static rdr::U8 *fb1, *fb2; + +static rfb::PixelTransformer *pt = NULL; + +typedef void (*testfn) (rfb::PixelFormat&, rfb::PixelFormat&, rdr::U8*, rdr::U8*); + +struct TestEntry { + const char *label; + testfn fn; +}; + +static void testMemcpy(rfb::PixelFormat &dstpf, rfb::PixelFormat &srcpf, + rdr::U8 *dst, rdr::U8 *src) +{ + int h; + h = tile; + while (h--) { + memcpy(dst, src, tile * dstpf.bpp/8); + dst += fbsize * dstpf.bpp/8; + src += fbsize * dstpf.bpp/8; + } +} + +static void testPixelTransformer(rfb::PixelFormat &dstpf, + rfb::PixelFormat &srcpf, + rdr::U8 *dst, rdr::U8 *src) +{ + pt->translateRect(src, fbsize, rfb::Rect(0, 0, tile, tile), + dst, fbsize, rfb::Point(0, 0)); +} + +static void testToRGB(rfb::PixelFormat &dstpf, rfb::PixelFormat &srcpf, + rdr::U8 *dst, rdr::U8 *src) +{ + srcpf.rgbFromBuffer(dst, src, tile, fbsize, tile); +} + +static void testFromRGB(rfb::PixelFormat &dstpf, rfb::PixelFormat &srcpf, + rdr::U8 *dst, rdr::U8 *src) +{ + dstpf.bufferFromRGB(dst, src, tile, fbsize, tile); +} + +static void doTest(testfn fn, rfb::PixelFormat &dstpf, rfb::PixelFormat &srcpf) +{ + if (!srcpf.isLittleEndian() && (fn == testPixelTransformer)) { + printf("NaN"); + return; + } + + startCpuCounter(); + + for (int i = 0;i < 10000;i++) { + int x, y; + rdr::U8 *dst, *src; + x = rand() % (fbsize - tile); + y = rand() % (fbsize - tile); + dst = fb1 + (x + y * fbsize) * dstpf.bpp/8; + src = fb2 + (x + y * fbsize) * srcpf.bpp/8; + fn(dstpf, srcpf, dst, src); + } + + endCpuCounter(); + + float data, time; + + data = (double)tile * tile * 10000; + time = getCpuCounter(); + + printf("%g", data / (1000.0*1000.0) / time); +} + +struct TestEntry tests[] = { + {"memcpy", testMemcpy}, + {"PixelTransformer", testPixelTransformer}, + {"rgbFromBuffer", testToRGB}, + {"bufferFromRGB", testFromRGB}, +}; + +static void doTests(rfb::PixelFormat &dstpf, rfb::PixelFormat &srcpf) +{ + int i; + char dstb[256], srcb[256]; + + dstpf.print(dstb, sizeof(dstb)); + srcpf.print(srcb, sizeof(srcb)); + + if (srcpf.isLittleEndian()) { + delete pt; + pt = new rfb::PixelTransformer; + pt->init(srcpf, NULL, dstpf); + } + + printf("%s,%s", srcb, dstb); + + for (i = 0;i < sizeof(tests)/sizeof(tests[0]);i++) { + printf(","); + doTest(tests[i].fn, dstpf, srcpf); + } + + printf("\n"); +} + +int main(int argc, char **argv) +{ + int bufsize; + + time_t t; + char datebuffer[256]; + + int i; + + bufsize = fbsize * fbsize * 4; + + fb1 = new rdr::U8[bufsize]; + fb2 = new rdr::U8[bufsize]; + + for (int i = 0;i < bufsize;i++) { + fb1[i] = rand(); + fb2[i] = rand(); + } + + time(&t); + strftime(datebuffer, sizeof(datebuffer), "%Y-%m-%d %H:%M UTC", gmtime(&t)); + + printf("# Pixel Conversion Test %s\n", datebuffer); + printf("#\n"); + printf("# Frame buffer: %dx%d pixels\n", fbsize, fbsize); + printf("# Tile size: %dx%d pixels\n", tile, tile); + printf("#\n"); + printf("# Note: Results are Mpixels/sec\n"); + printf("#\n"); + + printf("Source format,Destination Format"); + for (i = 0;i < sizeof(tests)/sizeof(tests[0]);i++) + printf(",%s", tests[i].label); + printf("\n"); + + rfb::PixelFormat dstpf, srcpf; + + /* rgb888 targets */ + + dstpf.parse("rgb888"); + + srcpf.parse("rgb888"); + doTests(dstpf, srcpf); + + srcpf.parse("bgr888"); + doTests(dstpf, srcpf); + + srcpf.parse("rgb565"); + doTests(dstpf, srcpf); + + srcpf.parse("rgb232"); + doTests(dstpf, srcpf); + + /* rgb565 targets */ + + dstpf.parse("rgb565"); + + srcpf.parse("rgb888"); + doTests(dstpf, srcpf); + + srcpf.parse("bgr565"); + doTests(dstpf, srcpf); + + srcpf.parse("rgb232"); + doTests(dstpf, srcpf); + + /* rgb565 with endian conversion (both ways) */ + + dstpf = rfb::PixelFormat(32, 24, false, true, 255, 255, 255, 0, 8, 16); + srcpf = rfb::PixelFormat(32, 24, true, true, 255, 255, 255, 0, 8, 16); + + doTests(srcpf, dstpf); + + doTests(dstpf, srcpf); + + dstpf = rfb::PixelFormat(16, 16, false, true, 31, 63, 31, 0, 5, 11); + srcpf = rfb::PixelFormat(16, 16, true, true, 31, 63, 31, 0, 5, 11); + + doTests(srcpf, dstpf); + + doTests(dstpf, srcpf); + + return 0; +} + diff --git a/tests/util.cxx b/tests/util.cxx new file mode 100644 index 00000000..c2685abb --- /dev/null +++ b/tests/util.cxx @@ -0,0 +1,76 @@ +/* Copyright 2013-2014 Pierre Ossman 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 + +#ifdef WIN32 +#include +#else +#include +#endif + +#ifdef WIN32 +static FILETIME cpuCounters[2]; +#else +struct rusage cpuCounters[2]; +#endif + +static void measureCpu(void *counter) +{ +#ifdef WIN32 + FILETIME dummy1, dummy2, dummy3; + + GetProcessTimes(GetCurrentProcess(), &dummy1, &dummy2, + &dummy3, (FILETIME*)counter); +#else + getrusage(RUSAGE_SELF, (struct rusage*)counter); +#endif +} + +void startCpuCounter(void) +{ + measureCpu(&cpuCounters[0]); +} + +void endCpuCounter(void) +{ + measureCpu(&cpuCounters[1]); +} + +double getCpuCounter(void) +{ + double seconds; + +#ifdef WIN32 + uint64_t counters[2]; + + counters[0] = (uint64_t)cpuCounters[0].dwHighDateTime << 32 | + cpuCounters[0].dwLowDateTime; + counters[1] = (uint64_t)cpuCounters[1].dwHighDateTime << 32 | + cpuCounters[1].dwLowDateTime; + + seconds = (double)(counters[1] - counters[2]) / 10000000.0; +#else + seconds = (double)(cpuCounters[1].ru_utime.tv_sec - + cpuCounters[0].ru_utime.tv_sec); + seconds += (double)(cpuCounters[1].ru_utime.tv_usec - + cpuCounters[0].ru_utime.tv_usec) / 1000000.0; +#endif + + return seconds; +} diff --git a/tests/util.h b/tests/util.h new file mode 100644 index 00000000..ebeadeba --- /dev/null +++ b/tests/util.h @@ -0,0 +1,27 @@ +/* Copyright 2013-2014 Pierre Ossman 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. + */ + +#ifndef __TESTS_UTIL_H__ +#define __TESTS_UTIL_H__ + +void startCpuCounter(void); +void endCpuCounter(void); + +double getCpuCounter(void); + +#endif -- 2.39.5