DPF OpenGL examples
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

241 lines
5.7KB

  1. /*
  2. * DISTRHO Plugin Framework (DPF)
  3. * Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * Permission to use, copy, modify, and/or distribute this software for any purpose with
  6. * or without fee is hereby granted, provided that the above copyright notice and this
  7. * permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
  10. * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
  11. * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  12. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
  13. * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  14. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #ifndef NANO_PERF_WIDGET_HPP_INCLUDED
  17. #define NANO_PERF_WIDGET_HPP_INCLUDED
  18. // ------------------------------------------------------
  19. // DGL Stuff
  20. #include "NanoVG.hpp"
  21. #include "../../dpf/distrho/extra/String.hpp"
  22. // ------------------------------------------------------
  23. // get time
  24. #include <sys/time.h>
  25. #include <time.h>
  26. #ifdef DISTRHO_OS_WINDOWS
  27. #else
  28. struct TimePOSIX {
  29. bool monotonic;
  30. double resolution;
  31. uint64_t base;
  32. TimePOSIX()
  33. : monotonic(false),
  34. resolution(1e-6),
  35. base(0)
  36. {
  37. #if defined(CLOCK_MONOTONIC)
  38. struct timespec ts;
  39. if (::clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
  40. {
  41. monotonic = true;
  42. resolution = 1e-9;
  43. }
  44. #endif
  45. base = getRawTime();
  46. }
  47. uint64_t getRawTime()
  48. {
  49. #if defined(CLOCK_MONOTONIC)
  50. if (monotonic)
  51. {
  52. struct timespec ts;
  53. ::clock_gettime(CLOCK_MONOTONIC, &ts);
  54. return (uint64_t) ts.tv_sec * (uint64_t) 1000000000 + (uint64_t) ts.tv_nsec;
  55. }
  56. else
  57. #endif
  58. {
  59. struct timeval tv;
  60. ::gettimeofday(&tv, NULL);
  61. return (uint64_t) tv.tv_sec * (uint64_t) 1000000 + (uint64_t) tv.tv_usec;
  62. }
  63. }
  64. double getTime()
  65. {
  66. return (double)(getRawTime() - base) * resolution;
  67. }
  68. };
  69. static TimePOSIX gTime;
  70. #endif
  71. // ------------------------------------------------------
  72. // our widget
  73. class NanoPerfWidget : public NanoWidget,
  74. public IdleCallback
  75. {
  76. public:
  77. static const int kHistoryCount = 100;
  78. enum RenderStyle {
  79. RENDER_FPS,
  80. RENDER_MS,
  81. };
  82. NanoPerfWidget(Window& parent, RenderStyle style, const char* name)
  83. : NanoWidget(parent),
  84. fHead(0),
  85. fStyle(style),
  86. fName(name)
  87. {
  88. parent.addIdleCallback(this);
  89. setSize(200, 35);
  90. std::memset(fValues, 0, sizeof(float)*kHistoryCount);
  91. createFontFromFile("sans", "./nanovg_res/Roboto-Regular.ttf");
  92. prevt = gTime.getTime();
  93. }
  94. protected:
  95. void idleCallback() override
  96. {
  97. repaint();
  98. }
  99. void onNanoDisplay() override
  100. {
  101. double t, dt;
  102. t = gTime.getTime();
  103. dt = t - prevt;
  104. prevt = t;
  105. update(dt);
  106. const int w = 200; //getWidth();
  107. const int h = 35; //getHeight();
  108. int i;
  109. float avg;
  110. char str[64];
  111. avg = getAverage();
  112. beginPath();
  113. rect(0, 0, w, h);
  114. fillColor(0,0,0,128);
  115. fill();
  116. beginPath();
  117. moveTo(0, h);
  118. if (fStyle == RENDER_FPS)
  119. {
  120. for (i = 0; i < kHistoryCount; ++i)
  121. {
  122. float v = 1.0f / (0.00001f + fValues[(fHead+i) % kHistoryCount]);
  123. float vx, vy;
  124. if (v > 80.0f) v = 80.0f;
  125. vx = ((float)i/(kHistoryCount-1)) * w;
  126. vy = h - ((v / 80.0f) * h);
  127. lineTo(vx, vy);
  128. }
  129. }
  130. else
  131. {
  132. for (i = 0; i < kHistoryCount; ++i)
  133. {
  134. float v = fValues[(fHead+i) % kHistoryCount] * 1000.0f;
  135. float vx, vy;
  136. if (v > 20.0f) v = 20.0f;
  137. vx = ((float)i/(kHistoryCount-1)) * w;
  138. vy = h - ((v / 20.0f) * h);
  139. lineTo(vx, vy);
  140. }
  141. }
  142. lineTo(w, h);
  143. fillColor(255,192,0,128);
  144. fill();
  145. fontFace("sans");
  146. if (fName.isNotEmpty())
  147. {
  148. fontSize(14.0f);
  149. textAlign(ALIGN_LEFT|ALIGN_TOP);
  150. fillColor(240,240,240,192);
  151. text(3, 1, fName, nullptr);
  152. }
  153. if (fStyle == RENDER_FPS)
  154. {
  155. fontSize(18.0f);
  156. textAlign(ALIGN_RIGHT|ALIGN_TOP);
  157. fillColor(240,240,240,255);
  158. std::sprintf(str, "%.2f FPS", 1.0f / avg);
  159. text(w-3, 1, str, nullptr);
  160. fontSize(15.0f);
  161. textAlign(ALIGN_RIGHT|ALIGN_BOTTOM);
  162. fillColor(240,240,240,160);
  163. std::sprintf(str, "%.2f ms", avg * 1000.0f);
  164. text(w-3, h-1, str, nullptr);
  165. }
  166. else
  167. {
  168. fontSize(18.0f);
  169. textAlign(ALIGN_RIGHT|ALIGN_TOP);
  170. fillColor(240,240,240,255);
  171. std::sprintf(str, "%.2f ms", avg * 1000.0f);
  172. text(w-3, 1, str, nullptr);
  173. }
  174. }
  175. private:
  176. int fHead;
  177. float fValues[kHistoryCount];
  178. const int fStyle;
  179. const String fName;
  180. double prevt;
  181. void update(float frameTime) noexcept
  182. {
  183. fHead = (fHead+1) % kHistoryCount;
  184. fValues[fHead] = frameTime;
  185. }
  186. float getAverage() const noexcept
  187. {
  188. int i;
  189. float avg = 0;
  190. for (i = 0; i < kHistoryCount; ++i)
  191. avg += fValues[i];
  192. return avg / (float)kHistoryCount;
  193. }
  194. };
  195. // ------------------------------------------------------
  196. #endif // NANO_PERF_WIDGET_HPP_INCLUDED