From bc312e29e3baf4e1444d34bbc514ed503d4c1c1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Nusser?= Date: Wed, 22 Feb 2017 13:54:27 +0100 Subject: Change hugin submodule URL to version on DG server. --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index e5c413b..718eb14 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "hugin"] path = hugin - url = http://git.oftal.dk/hugin.git + url = http://git.drumgizmo.org/hugin.git [submodule "plugin/plugingizmo"] path = plugin/plugingizmo url = http://git.drumgizmo.org/plugingizmo.git -- cgit v1.2.3 From bbc7e836f054aea09a1cde23d553a01892ea18c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Goran=20Meki=C4=87?= Date: Sat, 25 Feb 2017 00:58:18 +0100 Subject: Disk streaming cli option --- .gitignore | 3 +- AUTHORS | 3 ++ drumgizmo/drumgizmoc.cc | 20 ++++++++-- src/Makefile.am | 3 ++ src/bytesizeparser.cc | 99 +++++++++++++++++++++++++++++++++++++++++++++++++ src/bytesizeparser.h | 33 +++++++++++++++++ tools/add_file | 10 +++-- 7 files changed, 164 insertions(+), 7 deletions(-) create mode 100644 src/bytesizeparser.cc create mode 100644 src/bytesizeparser.h diff --git a/.gitignore b/.gitignore index c2ab71f..9486c44 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,7 @@ INSTALL *.o *.a *.la +*.core test_* *.exe Makefile.am.test @@ -73,4 +74,4 @@ plugin/vst/public.sdk/ plugingui/tests/*test *~ \#*\# -.\#* \ No newline at end of file +.\#* diff --git a/AUTHORS b/AUTHORS index 056ec04..f30f477 100644 --- a/AUTHORS +++ b/AUTHORS @@ -13,5 +13,8 @@ Developer: Developer, Graphics, GUI design and logo: Lars Muldjord [muldjord] (muldjordlars@gmail.com) +Developer: + Goran Mekić [meka] (meka@tilda.center) + Patches: John Hammen (sample multichannel support) diff --git a/drumgizmo/drumgizmoc.cc b/drumgizmo/drumgizmoc.cc index 1ba9516..6ea6b5d 100644 --- a/drumgizmo/drumgizmoc.cc +++ b/drumgizmo/drumgizmoc.cc @@ -39,6 +39,7 @@ #include "drumgizmo.h" #include "drumgizmoc.h" #include "enginefactory.h" +#include "bytesizeparser.h" #include "event.h" @@ -65,6 +66,7 @@ static const char usage_str[] = "output engine.\n" " -O, --outputparms parmlist Set output engine parameters.\n" " -e, --endpos Number of samples to process, -1: infinite.\n" + " -m, --diskstreamsize Size of buffer for disk streaming, eg. 5{k,M,G}.\n" #ifndef DISABLE_HUGIN " -D, --debug ddd Enable debug messages on 'ddd'; see hugin " "documentation for details\n" @@ -92,10 +94,12 @@ static const char usage_str[] = " dummy:\n" "\n"; + int main(int argc, char* argv[]) { int c; - + Settings settings; + settings.disk_cache_enable = false; std::string hugin_filter; unsigned int hugin_flags = 0; #ifndef DISABLE_HUGIN @@ -121,6 +125,7 @@ int main(int argc, char* argv[]) {"outputengine", required_argument, 0, 'o'}, {"outputparms", required_argument, 0, 'O'}, {"endpos", required_argument, 0, 'e'}, + {"diskstreamsize", required_argument, 0, 'm'}, #ifndef DISABLE_HUGIN {"debug", required_argument, 0, 'D'}, #endif /*DISABLE_HUGIN*/ @@ -128,7 +133,7 @@ int main(int argc, char* argv[]) {"help", no_argument, 0, 'h'}, {0, 0, 0, 0}}; - c = getopt_long(argc, argv, "hvpo:O:i:I:e:a" + c = getopt_long(argc, argv, "hvpo:O:i:I:e:am:" #ifndef DISABLE_HUGIN "D:" #endif /*DISABLE_HUGIN*/ @@ -203,6 +208,16 @@ int main(int argc, char* argv[]) printf("%s", copyright_str); return 0; + case 'm': + settings.disk_cache_upper_limit = byteSizeParser(optarg); + if(!settings.disk_cache_upper_limit) + { + printf("%s", version_str); + printf(usage_str, argv[0]); + return 1; + } + settings.disk_cache_enable = true; + default: break; } @@ -343,7 +358,6 @@ int main(int argc, char* argv[]) printf("Using kitfile: %s\n", kitfile.c_str()); - Settings settings; DrumGizmo gizmo(settings, *oe.get(), *ie.get()); gizmo.setFrameSize(oe->getBufferSize()); diff --git a/src/Makefile.am b/src/Makefile.am index 2277eeb..06e189f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -17,6 +17,7 @@ nodist_libdg_la_SOURCES = \ audiocacheidmanager.cc \ audioinputenginemidi.cc \ audiofile.cc \ + bytesizeparser.cc \ channel.cc \ channelmixer.cc \ chresampler.cc \ @@ -57,6 +58,7 @@ EXTRA_DIST = \ audioinputenginemidi.h \ audiooutputengine.h \ beatmapper.h \ + bytesizeparser.h \ channel.h \ channelmixer.h \ chresampler.h \ @@ -102,6 +104,7 @@ EXTRA_DIST = \ audioinputenginemidi.cc \ audiooutputengine.cc \ beatmapper.cc \ + bytesizeparser.cc \ channel.cc \ channelmixer.cc \ chresampler.cc \ diff --git a/src/bytesizeparser.cc b/src/bytesizeparser.cc new file mode 100644 index 0000000..0bab316 --- /dev/null +++ b/src/bytesizeparser.cc @@ -0,0 +1,99 @@ +/* -*- Mode: c++ -*- */ +/*************************************************************************** + * bytesize_parser.cc + * + * Sat Mar 4 18:00:12 CET 2017 + * Copyright 2017 Goran Mekić + * meka@tilda.center + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * DrumGizmo 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "bytesizeparser.h" +#include +#include + + +static std::size_t suffixToSize(const char& suffix) +{ + int size = 1; + switch(suffix) + { + case 'k': + size <<= 10; + break; + case 'M': + size <<= 20; + break; + case 'G': + size <<= 30; + break; + default: + size = 0; + break; + } + return size; +} + + +std::size_t byteSizeParser(const std::string& argument) +{ + std::string::size_type suffix_index; + std::size_t stream_size; + std::string suffix; + bool error = false; + + try + { + stream_size = std::stoi(argument, &suffix_index); + } + catch(std::invalid_argument) + { + std::cerr << "Invalid option for diskstreamsize" << std::endl; + error = true; + } + catch(std::out_of_range) + { + std::cerr << "Number too big. Try using bigger suffix for diskstreamsize" << std::endl; + error = true; + } + if(!error) + { + suffix = argument.substr(suffix_index); + if (suffix.length() > 1) + { + error = true; + } + } + if(!error) + { + std::size_t suffix_size = suffixToSize(suffix[0]); + if (suffix_size) + { + stream_size *= suffix_size; + } + } + if(error) + { + std::cerr << "Stream size should be in [suffix] format "; + std::cerr << "where [suffix] is k, M, or G." << std::endl; + std::cerr << "Example: 10M which is 10 * 1024 * 1024 bytes" << std::endl; + return 0; + } + return stream_size; +} diff --git a/src/bytesizeparser.h b/src/bytesizeparser.h new file mode 100644 index 0000000..3007454 --- /dev/null +++ b/src/bytesizeparser.h @@ -0,0 +1,33 @@ +/* -*- Mode: c++ -*- */ +/*************************************************************************** + * bytesize_parser.h + * + * Sat Mar 4 18:00:12 CET 2017 + * Copyright 2017 Goran Mekić + * meka@tilda.center + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * DrumGizmo 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once +#include + + +//! Returns size in bytes +//! \param argument The size in n{k,M,G} format +std::size_t byteSizeParser(const std::string& argument); diff --git a/tools/add_file b/tools/add_file index d1b190f..a704029 100755 --- a/tools/add_file +++ b/tools/add_file @@ -16,14 +16,18 @@ function allfile() { fi if [ "$USER" == "chaot" ] then - NAME="André Nusser"; EMAIL="andre.nusser@googlemail.com" + NAME="André Nusser"; EMAIL="andre.nusser@googlemail.com" fi if [ "$DGUSER" == "glocke" ] then - NAME="Christian Glöckner"; EMAIL="cgloeckner@freenet.de" + NAME="Christian Glöckner"; EMAIL="cgloeckner@freenet.de" + fi + if [ "$USER" == "meka" ] + then + NAME="Goran Mekić"; EMAIL="meka@tilda.center" fi - echo "/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */" > $1; + echo "/* -*- Mode: c++ -*- */" > $1; echo "/***************************************************************************" >> $1; echo " * $1" >> $1; echo " *" >> $1 ; -- cgit v1.2.3 From faf80b071b54f2f736df2390171f7b3b939d03c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Goran=20Meki=C4=87?= Date: Sun, 5 Mar 2017 11:40:07 +0100 Subject: Test diskstreaming CLI --- .gitignore | 1 + drumgizmo/drumgizmoc.cc | 3 ++ src/bytesizeparser.cc | 18 ++++--- test/Makefile.am | 12 ++++- test/bytesizeparsertest.cc | 127 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 152 insertions(+), 9 deletions(-) create mode 100644 test/bytesizeparsertest.cc diff --git a/.gitignore b/.gitignore index 9486c44..b2d9feb 100644 --- a/.gitignore +++ b/.gitignore @@ -57,6 +57,7 @@ test/semaphoretest test/enginetest test/paintertest test/drumkitcreatortest +test/bytesizeparsertest test/dgreftest/dgreftest test/dgreftest/*.mid test/dgreftest/*.wav diff --git a/drumgizmo/drumgizmoc.cc b/drumgizmo/drumgizmoc.cc index 6ea6b5d..56b2367 100644 --- a/drumgizmo/drumgizmoc.cc +++ b/drumgizmo/drumgizmoc.cc @@ -214,6 +214,9 @@ int main(int argc, char* argv[]) { printf("%s", version_str); printf(usage_str, argv[0]); + std::cerr << "Stream size should be in [suffix] format "; + std::cerr << "where [suffix] is k, M, or G." << std::endl; + std::cerr << "Example: 10M which is 10 * 1024 * 1024 bytes" << std::endl; return 1; } settings.disk_cache_enable = true; diff --git a/src/bytesizeparser.cc b/src/bytesizeparser.cc index 0bab316..329407d 100644 --- a/src/bytesizeparser.cc +++ b/src/bytesizeparser.cc @@ -58,13 +58,18 @@ std::size_t byteSizeParser(const std::string& argument) std::string suffix; bool error = false; + if(argument.find('-') != std::string::npos) + { + error = true; + } + try { stream_size = std::stoi(argument, &suffix_index); } catch(std::invalid_argument) { - std::cerr << "Invalid option for diskstreamsize" << std::endl; + std::cerr << "Invalid argument for diskstreamsize" << std::endl; error = true; } catch(std::out_of_range) @@ -82,17 +87,16 @@ std::size_t byteSizeParser(const std::string& argument) } if(!error) { - std::size_t suffix_size = suffixToSize(suffix[0]); - if (suffix_size) + std::size_t suffix_size = 1; + if(suffix_index <= suffix.length()) { - stream_size *= suffix_size; + suffix_size = suffixToSize(suffix[0]); + } + stream_size *= suffix_size; } if(error) { - std::cerr << "Stream size should be in [suffix] format "; - std::cerr << "where [suffix] is k, M, or G." << std::endl; - std::cerr << "Example: 10M which is 10 * 1024 * 1024 bytes" << std::endl; return 0; } return stream_size; diff --git a/test/Makefile.am b/test/Makefile.am index 12d4713..58d7f1b 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -6,7 +6,7 @@ if ENABLE_TESTS TESTS = resource enginetest paintertest resampler configfile audiocache \ audiocachefile audiocacheidmanager audiocacheeventhandler \ memchecker randomtest atomictest syncedsettingstest imagecachetest \ - semaphoretest drumkitcreatortest + semaphoretest drumkitcreatortest bytesizeparsertest if ENABLE_LV2 TESTS += lv2 @@ -189,7 +189,7 @@ semaphoretest_SOURCES = \ semaphoretest.cc \ test.cc -drumkitcreatortest_CXXFLAGS = -DOUTPUT=\"drumkitcreatortest\" $(CPPUNIT_CFLAGS) +drumkitcreatortest_CXXFLAGS = -DOUTPUT=\"drumkitcreatortest\" $(CPPUNIT_CFLAGS) \ -I$(top_srcdir)/src \ -I$(top_srcdir)/hugin -DDISABLE_HUGIN drumkitcreatortest_CFLAGS = -DDISABLE_HUGIN @@ -200,4 +200,12 @@ drumkitcreatortest_SOURCES = \ drumkit_creator.cc \ drumkitcreatortest.cc +bytesizeparsertest_CXXFLAGS = -DOUTPUT=\"bytesizeparsertest\" $(CPPUNIT_CFLAGS) \ + -I$(top_srcdir)/src +bytesizeparsertest_LDFLAGS = $(CPPUNIT_LIBS) +bytesizeparsertest_SOURCES = \ + $(top_srcdir)/src/bytesizeparser.cc \ + bytesizeparsertest.cc \ + test.cc + endif diff --git a/test/bytesizeparsertest.cc b/test/bytesizeparsertest.cc new file mode 100644 index 0000000..e4776fe --- /dev/null +++ b/test/bytesizeparsertest.cc @@ -0,0 +1,127 @@ +/* -*- Mode: c++ -*- */ +/*************************************************************************** + * bytesizeparsertest.cc + * + * Sun Mar 05 11:44:23 CET 2017 + * Copyright 2017 Goran Mekić + * meka@tilda.center + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * DrumGizmo 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include + +#include "bytesizeparser.h" + + +class ByteSizeParserTest + : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(ByteSizeParserTest); + CPPUNIT_TEST(suffixTest); + CPPUNIT_TEST(falseSuffixTest); + CPPUNIT_TEST(falseNumberTest); + CPPUNIT_TEST(tooBigNumberTest); + CPPUNIT_TEST_SUITE_END(); + +public: + void setUp() {} + + void tearDown() {} + + void suffixTest() + { + std::size_t computed_size, expected_size; + std::size_t kilo = 1024, mega = kilo * 1024, giga = mega * 1024; + computed_size = byteSizeParser("3"); + expected_size = 3; + CPPUNIT_ASSERT_EQUAL(expected_size, computed_size); + + computed_size = byteSizeParser("3k"); + expected_size = 3 * kilo; + CPPUNIT_ASSERT_EQUAL(expected_size, computed_size); + + computed_size = byteSizeParser("3M"); + expected_size = 3 * mega; + CPPUNIT_ASSERT_EQUAL(expected_size, computed_size); + + computed_size = byteSizeParser("3G"); + expected_size = 3 * giga; + CPPUNIT_ASSERT_EQUAL(expected_size, computed_size); + } + + void falseSuffixTest() + { + std::size_t computed_size, expected_size = 0; + computed_size = byteSizeParser("3K"); + CPPUNIT_ASSERT_EQUAL(expected_size, computed_size); + + computed_size = byteSizeParser("3m"); + CPPUNIT_ASSERT_EQUAL(expected_size, computed_size); + + computed_size = byteSizeParser("3g"); + CPPUNIT_ASSERT_EQUAL(expected_size, computed_size); + + computed_size = byteSizeParser("3ddDD"); + CPPUNIT_ASSERT_EQUAL(expected_size, computed_size); + } + + void falseNumberTest() + { + std::size_t computed_size, expected_size = 0; + computed_size = byteSizeParser("K3k"); + CPPUNIT_ASSERT_EQUAL(expected_size, computed_size); + + computed_size = byteSizeParser("-3"); + CPPUNIT_ASSERT_EQUAL(expected_size, computed_size); + + computed_size = byteSizeParser("-3k"); + CPPUNIT_ASSERT_EQUAL(expected_size, computed_size); + + computed_size = byteSizeParser("-3M"); + CPPUNIT_ASSERT_EQUAL(expected_size, computed_size); + + computed_size = byteSizeParser("-3G"); + CPPUNIT_ASSERT_EQUAL(expected_size, computed_size); + + computed_size = byteSizeParser("3-"); + CPPUNIT_ASSERT_EQUAL(expected_size, computed_size); + + computed_size = byteSizeParser("3-k"); + CPPUNIT_ASSERT_EQUAL(expected_size, computed_size); + + computed_size = byteSizeParser("k-3"); + CPPUNIT_ASSERT_EQUAL(expected_size, computed_size); + + computed_size = byteSizeParser("3-1"); + CPPUNIT_ASSERT_EQUAL(expected_size, computed_size); + + computed_size = byteSizeParser(" -3"); + CPPUNIT_ASSERT_EQUAL(expected_size, computed_size); + } + + void tooBigNumberTest() + { + std::size_t computed_size, expected_size = 0; + computed_size = byteSizeParser("999999999999999999999999999999999999G"); + CPPUNIT_ASSERT_EQUAL(expected_size, computed_size); + } +}; + +// Registers the fixture into the 'registry' +CPPUNIT_TEST_SUITE_REGISTRATION(ByteSizeParserTest); -- cgit v1.2.3 From 75de9c0ac782fa6fecb92f3a22f311b517856abb Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Sun, 12 Mar 2017 09:09:07 +0100 Subject: Add reload_counter to Settings and use it in DrumKitLoader to reload a drumkit whenever it changes (ie. increments). --- src/drumkitloader.cc | 3 ++- src/settings.h | 13 +++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/drumkitloader.cc b/src/drumkitloader.cc index 1d66597..103b60c 100644 --- a/src/drumkitloader.cc +++ b/src/drumkitloader.cc @@ -201,7 +201,8 @@ void DrumKitLoader::thread_main() } bool newKit = false; - if(getter.drumkit_file.hasChanged()) + if(getter.drumkit_file.hasChanged() || + getter.reload_counter.hasChanged()) { loadkit(getter.drumkit_file.getValue()); newKit = true; diff --git a/src/settings.h b/src/settings.h index cb707ef..8a646a1 100644 --- a/src/settings.h +++ b/src/settings.h @@ -50,12 +50,13 @@ struct Settings Atomic drumkit_load_status{LoadStatus::Idle}; //! The maximum amount of memory in bytes that the AudioCache - //! is allowed to use for preloading - //! The default std::numeric_limits::max() means "unlimited" - //Atomic cache_upper_limit{std::numeric_limits::max()}; - Atomic disk_cache_upper_limit{1024*1024*1024}; + //! is allowed to use for preloading. Default is 1GB. + Atomic disk_cache_upper_limit{1024 * 1024 * 1024}; Atomic disk_cache_enable{true}; + //! Increment this in order to invoke a reload of the current drumkit. + Atomic reload_counter{0}; + Atomic midimap_file{""}; Atomic midimap_load_status{LoadStatus::Idle}; @@ -83,6 +84,7 @@ struct SettingsGetter SettingRef disk_cache_upper_limit; SettingRef disk_cache_enable; + SettingRef reload_counter; SettingRef midimap_file; SettingRef midimap_load_status; @@ -107,6 +109,7 @@ struct SettingsGetter , drumkit_load_status(settings.drumkit_load_status) , disk_cache_upper_limit(settings.disk_cache_upper_limit) , disk_cache_enable(settings.disk_cache_enable) + , reload_counter(settings.reload_counter) , midimap_file(settings.midimap_file) , midimap_load_status(settings.midimap_load_status) , enable_velocity_modifier{settings.enable_velocity_modifier} @@ -132,6 +135,7 @@ public: Notifier disk_cache_upper_limit; Notifier disk_cache_enable; + Notifier reload_counter; Notifier midimap_file; Notifier midimap_load_status; @@ -160,6 +164,7 @@ public: EVAL(disk_cache_upper_limit); EVAL(disk_cache_enable); + EVAL(reload_counter); EVAL(midimap_file); EVAL(midimap_load_status); -- cgit v1.2.3 From 494e7218597a6cd94902b3ae6f827e74b41c00b0 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Sun, 12 Mar 2017 17:25:04 +0100 Subject: Fix redrawing of underlying exposed area on Widget moves/resizing. --- plugingui/pixelbuffer.cc | 18 +++++++++--------- plugingui/pixelbuffer.h | 37 +++++++++++++++++++++++------------- plugingui/widget.cc | 49 +++++++++++++++++++++++++++++++++++++++++------- plugingui/window.cc | 43 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 118 insertions(+), 29 deletions(-) diff --git a/plugingui/pixelbuffer.cc b/plugingui/pixelbuffer.cc index bbef84c..360ad06 100644 --- a/plugingui/pixelbuffer.cc +++ b/plugingui/pixelbuffer.cc @@ -33,7 +33,7 @@ namespace GUI { -PixelBuffer::PixelBuffer(size_t width, size_t height) +PixelBuffer::PixelBuffer(std::size_t width, std::size_t height) : buf(nullptr) { realloc(width, height); @@ -44,7 +44,7 @@ PixelBuffer::~PixelBuffer() free(buf); } -void PixelBuffer::realloc(size_t width, size_t height) +void PixelBuffer::realloc(std::size_t width, std::size_t height) { free(buf); buf = (unsigned char *)calloc(width * height, 3); @@ -53,7 +53,7 @@ void PixelBuffer::realloc(size_t width, size_t height) } #define PX(k) ((x + y * width) * 3 + k) -void PixelBuffer::setPixel(size_t x, size_t y, +void PixelBuffer::setPixel(std::size_t x, std::size_t y, unsigned char red, unsigned char green, unsigned char blue, @@ -84,7 +84,7 @@ void PixelBuffer::setPixel(size_t x, size_t y, } } -PixelBufferAlpha::PixelBufferAlpha(size_t width, size_t height) +PixelBufferAlpha::PixelBufferAlpha(std::size_t width, std::size_t height) : managed(true) , buf(nullptr) , x(0) @@ -101,7 +101,7 @@ PixelBufferAlpha::~PixelBufferAlpha() } } -void PixelBufferAlpha::realloc(size_t width, size_t height) +void PixelBufferAlpha::realloc(std::size_t width, std::size_t height) { free(buf); buf = (unsigned char *)calloc(width * height, 4); @@ -111,7 +111,7 @@ void PixelBufferAlpha::realloc(size_t width, size_t height) #undef PX #define PX(k) ((x + y * width) * 4 + k) -void PixelBufferAlpha::setPixel(size_t x, size_t y, +void PixelBufferAlpha::setPixel(std::size_t x, std::size_t y, unsigned char red, unsigned char green, unsigned char blue, @@ -135,7 +135,7 @@ static inline void getAlpha(unsigned char _a, unsigned char _b, b *= (1 - a); } -void PixelBufferAlpha::addPixel(size_t x, size_t y, +void PixelBufferAlpha::addPixel(std::size_t x, std::size_t y, unsigned char red, unsigned char green, unsigned char blue, @@ -172,13 +172,13 @@ void PixelBufferAlpha::addPixel(size_t x, size_t y, } } -void PixelBufferAlpha::addPixel(size_t x, size_t y, const Colour& c) +void PixelBufferAlpha::addPixel(std::size_t x, std::size_t y, const Colour& c) { addPixel(x, y, c.red() * 255, c.green() * 255, c.blue() * 255, c.alpha() * 255); } -void PixelBufferAlpha::pixel(size_t x, size_t y, +void PixelBufferAlpha::pixel(std::size_t x, std::size_t y, unsigned char* red, unsigned char* green, unsigned char* blue, diff --git a/plugingui/pixelbuffer.h b/plugingui/pixelbuffer.h index 94c5496..71869a0 100644 --- a/plugingui/pixelbuffer.h +++ b/plugingui/pixelbuffer.h @@ -33,47 +33,49 @@ namespace GUI { -class PixelBuffer { +class PixelBuffer +{ public: - PixelBuffer(size_t width, size_t height); + PixelBuffer(std::size_t width, std::size_t height); ~PixelBuffer(); - void realloc(size_t width, size_t height); + void realloc(std::size_t width, std::size_t height); - void setPixel(size_t x, size_t y, + void setPixel(std::size_t x, std::size_t y, unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha); unsigned char* buf{nullptr}; - size_t width{0}; - size_t height{0}; + std::size_t width{0}; + std::size_t height{0}; }; -class PixelBufferAlpha { +class PixelBufferAlpha +{ public: PixelBufferAlpha() = default; - PixelBufferAlpha(size_t width, size_t height); + PixelBufferAlpha(std::size_t width, std::size_t height); ~PixelBufferAlpha(); - void realloc(size_t width, size_t height); + void realloc(std::size_t width, std::size_t height); - void setPixel(size_t x, size_t y, + void setPixel(std::size_t x, std::size_t y, unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha); - void addPixel(size_t x, size_t y, + void addPixel(std::size_t x, std::size_t y, unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha); - void addPixel(size_t x, size_t y, const Colour& c); + void addPixel(std::size_t x, std::size_t y, const Colour& c); - void pixel(size_t x, size_t y, + void pixel(std::size_t x, std::size_t y, unsigned char* red, unsigned char* green, unsigned char* blue, @@ -86,6 +88,15 @@ public: int x{0}; int y{0}; bool dirty{true}; + bool visible{true}; + + // Add optional dirty rect that this pixelbuffer took up since it was last + // rendered. Make sure to update this list on resize and/or move. + std::size_t last_width{0}; + std::size_t last_height{0}; + int last_x{0}; + int last_y{0}; + bool has_last{false}; }; } // GUI:: diff --git a/plugingui/widget.cc b/plugingui/widget.cc index 7d92a22..00acfbf 100644 --- a/plugingui/widget.cc +++ b/plugingui/widget.cc @@ -42,6 +42,9 @@ Widget::Widget(Widget* parent) parent->addChild(this); _window = parent->window(); } + + pixbuf.x = translateToWindowX(); + pixbuf.y = translateToWindowY(); } Widget::~Widget() @@ -64,12 +67,14 @@ void Widget::hide() void Widget::setVisible(bool visible) { - _visible = visible; - - if(visible) + if(_visible == visible) { - redraw(); + return; } + + _visible = visible; + pixbuf.visible = visible; + redraw(); } bool Widget::visible() const @@ -130,7 +135,20 @@ void Widget::resize(std::size_t width, std::size_t height) _width = width; _height = height; + + // Store old size/position in pixelbuffer for rendering invalidation. + if(!pixbuf.has_last) + { + pixbuf.last_width = pixbuf.width; + pixbuf.last_height = pixbuf.height; + pixbuf.last_x = pixbuf.x; + pixbuf.last_y = pixbuf.y; + pixbuf.has_last = true; + } + pixbuf.realloc(width, height); + pixbuf.x = translateToWindowX(); + pixbuf.y = translateToWindowY(); redraw(); sizeChangeNotifier(width, height); } @@ -145,6 +163,20 @@ void Widget::move(int x, int y) _x = x; _y = y; + + // Store old size/position in pixelbuffer for rendering invalidation. + if(!pixbuf.has_last) + { + pixbuf.last_width = pixbuf.width; + pixbuf.last_height = pixbuf.height; + pixbuf.last_x = pixbuf.x; + pixbuf.last_y = pixbuf.y; + pixbuf.has_last = true; + } + + //pixbuf.x = translateToWindowX(); + //pixbuf.y = translateToWindowY(); + positionChangeNotifier(x, y); } @@ -216,11 +248,14 @@ std::vector Widget::getPixelBuffers() dirty = false; } - pixelBuffers.push_back(&pixbuf); + if(pixbuf.dirty || visible()) + { + pixelBuffers.push_back(&pixbuf); + } - for(auto child : children) + if(visible()) { - if(child->visible()) + for(auto child : children) { auto childPixelBuffers = child->getPixelBuffers(); pixelBuffers.insert(pixelBuffers.end(), diff --git a/plugingui/window.cc b/plugingui/window.cc index d4046c2..8bc5c62 100644 --- a/plugingui/window.cc +++ b/plugingui/window.cc @@ -262,10 +262,50 @@ bool Window::updateBuffer() }; } } + + if(pixel_buffer->has_last) + { + auto x1 = (std::size_t)pixel_buffer->last_x; + auto x2 = (std::size_t)(pixel_buffer->last_x + pixel_buffer->last_width); + auto y1 = (std::size_t)pixel_buffer->last_y; + auto y2 = (std::size_t)(pixel_buffer->last_y + pixel_buffer->last_height); + + pixel_buffer->has_last = false; + if(!has_dirty_rect) + { + // Insert this area: + dirty_rect = {x1, y1, x2, y2}; + has_dirty_rect = true; + } + else + { + // Expand existing area: + auto x1_0 = dirty_rect.x1; + auto y1_0 = dirty_rect.y1; + auto x2_0 = dirty_rect.x2; + auto y2_0 = dirty_rect.y2; + dirty_rect = { + (x1_0 < x1) ? x1_0 : x1, + (y1_0 < y1) ? y1_0 : y1, + (x2_0 > x2) ? x2_0 : x2, + (y2_0 > y2) ? y2_0 : y2 + }; + } + } + } + + if(!has_dirty_rect) + { + return false; } for(auto& pixel_buffer : pixel_buffers) { + if(!pixel_buffer->visible) + { + continue; + } + int update_width = pixel_buffer->width; int update_height = pixel_buffer->height; @@ -308,6 +348,9 @@ bool Window::updateBuffer() } } + dirty_rect.x2 = std::min(wpixbuf.width, dirty_rect.x2); + dirty_rect.y2 = std::min(wpixbuf.height, dirty_rect.y2); + native->redraw(dirty_rect); needs_redraw = false; -- cgit v1.2.3