/indra/newview/llsceneview.cpp

https://bitbucket.org/lindenlab/viewer-beta/ · C++ · 438 lines · 290 code · 109 blank · 39 comment · 39 complexity · 9234574910f25e4b54c1aafeacefb2b5 MD5 · raw file

  1. /**
  2. * @file llsceneview.cpp
  3. * @brief LLSceneView class implementation
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "llviewerprecompiledheaders.h"
  27. #include "llsceneview.h"
  28. #include "llviewerwindow.h"
  29. #include "pipeline.h"
  30. #include "llviewerobjectlist.h"
  31. #include "llviewerregion.h"
  32. #include "llagent.h"
  33. #include "llvolumemgr.h"
  34. LLSceneView* gSceneView = NULL;
  35. //borrow this helper function from llfasttimerview.cpp
  36. template <class VEC_TYPE>
  37. void removeOutliers(std::vector<VEC_TYPE>& data, F32 k);
  38. LLSceneView::LLSceneView(const LLRect& rect)
  39. : LLFloater(LLSD())
  40. {
  41. setRect(rect);
  42. setVisible(FALSE);
  43. setCanMinimize(false);
  44. setCanClose(true);
  45. }
  46. void LLSceneView::onClickCloseBtn()
  47. {
  48. setVisible(false);
  49. }
  50. void LLSceneView::draw()
  51. {
  52. S32 margin = 10;
  53. S32 height = (S32) (gViewerWindow->getWindowRectScaled().getHeight()*0.75f);
  54. S32 width = (S32) (gViewerWindow->getWindowRectScaled().getWidth() * 0.75f);
  55. LLRect new_rect;
  56. new_rect.setLeftTopAndSize(getRect().mLeft, getRect().mTop, width, height);
  57. setRect(new_rect);
  58. // Draw the window background
  59. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  60. gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4(0.f, 0.f, 0.f, 0.25f));
  61. //aggregate some statistics
  62. //object sizes
  63. std::vector<F32> size[2];
  64. //triangle counts
  65. std::vector<S32> triangles[2];
  66. std::vector<S32> visible_triangles[2];
  67. S32 total_visible_triangles[] = {0, 0};
  68. S32 total_triangles[] = {0, 0};
  69. S32 total_visible_bytes[] = {0, 0};
  70. S32 total_bytes[] = {0, 0};
  71. //streaming cost
  72. std::vector<F32> streaming_cost[2];
  73. F32 total_streaming[] = { 0.f, 0.f };
  74. //physics cost
  75. std::vector<F32> physics_cost[2];
  76. F32 total_physics[] = { 0.f, 0.f };
  77. U32 object_count = 0;
  78. LLViewerRegion* region = gAgent.getRegion();
  79. if (region)
  80. {
  81. for (U32 i = 0; i < gObjectList.getNumObjects(); ++i)
  82. {
  83. LLViewerObject* object = gObjectList.getObject(i);
  84. if (object &&
  85. object->getVolume()&&
  86. object->getRegion() == region)
  87. {
  88. U32 idx = object->isAttachment() ? 1 : 0;
  89. LLVolume* volume = object->getVolume();
  90. object_count++;
  91. F32 radius = object->getScale().magVec();
  92. size[idx].push_back(radius);
  93. S32 visible = volume->getNumTriangles();
  94. S32 high_triangles = object->getHighLODTriangleCount();
  95. total_visible_triangles[idx] += visible;
  96. total_triangles[idx] += high_triangles;
  97. visible_triangles[idx].push_back(visible);
  98. triangles[idx].push_back(high_triangles);
  99. S32 bytes = 0;
  100. S32 visible_bytes = 0;
  101. F32 streaming = object->getStreamingCost(&bytes, &visible_bytes);
  102. total_streaming[idx] += streaming;
  103. streaming_cost[idx].push_back(streaming);
  104. F32 physics = object->getPhysicsCost();
  105. total_physics[idx] += physics;
  106. physics_cost[idx].push_back(physics);
  107. total_bytes[idx] += bytes;
  108. total_visible_bytes[idx] += visible_bytes;
  109. }
  110. }
  111. }
  112. const char* category[] =
  113. {
  114. "Region",
  115. "Attachment"
  116. };
  117. S32 graph_pos[4];
  118. for (U32 i = 0; i < 4; ++i)
  119. {
  120. graph_pos[i] = new_rect.getHeight()/4*(i+1);
  121. }
  122. for (U32 idx = 0; idx < 2; idx++)
  123. {
  124. if (!size[idx].empty())
  125. { //display graph of object sizes
  126. std::sort(size[idx].begin(), size[idx].end());
  127. ll_remove_outliers(size[idx], 1.f);
  128. LLRect size_rect;
  129. if (idx == 0)
  130. {
  131. size_rect = LLRect(margin, graph_pos[0]-margin, new_rect.getWidth()/2-margin, margin*2);
  132. }
  133. else
  134. {
  135. size_rect = LLRect(margin+new_rect.getWidth()/2, graph_pos[0]-margin, new_rect.getWidth()-margin, margin*2);
  136. }
  137. gl_rect_2d(size_rect, LLColor4::white, false);
  138. F32 size_domain[] = { 128.f, 0.f };
  139. //get domain of sizes
  140. for (U32 i = 0; i < size[idx].size(); ++i)
  141. {
  142. size_domain[0] = llmin(size_domain[0], size[idx][i]);
  143. size_domain[1] = llmax(size_domain[1], size[idx][i]);
  144. }
  145. F32 size_range = size_domain[1]-size_domain[0];
  146. U32 count = size[idx].size();
  147. F32 total = 0.f;
  148. gGL.begin(LLRender::LINE_STRIP);
  149. for (U32 i = 0; i < count; ++i)
  150. {
  151. F32 rad = size[idx][i];
  152. total += rad;
  153. F32 y = (rad-size_domain[0])/size_range*size_rect.getHeight()+size_rect.mBottom;
  154. F32 x = (F32) i / count * size_rect.getWidth() + size_rect.mLeft;
  155. gGL.vertex2f(x,y);
  156. if (i%4096 == 0)
  157. {
  158. gGL.end();
  159. gGL.flush();
  160. gGL.begin(LLRender::LINE_STRIP);
  161. }
  162. }
  163. gGL.end();
  164. gGL.flush();
  165. std::string label = llformat("%s Object Sizes (m) -- [%.1f, %.1f] Mean: %.1f Median: %.1f -- %d samples",
  166. category[idx], size_domain[0], size_domain[1], total/count, size[idx][count/2], count);
  167. LLFontGL::getFontMonospace()->renderUTF8(label,
  168. 0 , size_rect.mLeft, size_rect.mTop+margin, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP);
  169. }
  170. }
  171. for (U32 idx = 0; idx < 2; ++idx)
  172. {
  173. if (!triangles[idx].empty())
  174. { //plot graph of visible/total triangles
  175. std::sort(triangles[idx].begin(), triangles[idx].end());
  176. ll_remove_outliers(triangles[idx], 1.f);
  177. LLRect tri_rect;
  178. if (idx == 0)
  179. {
  180. tri_rect = LLRect(margin, graph_pos[1]-margin, new_rect.getWidth()/2-margin, graph_pos[0]+margin);
  181. }
  182. else
  183. {
  184. tri_rect = LLRect(new_rect.getWidth()/2+margin, graph_pos[1]-margin, new_rect.getWidth()-margin, graph_pos[0]+margin);
  185. }
  186. gl_rect_2d(tri_rect, LLColor4::white, false);
  187. S32 tri_domain[] = { 65536, 0 };
  188. //get domain of triangle counts
  189. for (U32 i = 0; i < triangles[idx].size(); ++i)
  190. {
  191. tri_domain[0] = llmin(tri_domain[0], triangles[idx][i]);
  192. tri_domain[1] = llmax(tri_domain[1], triangles[idx][i]);
  193. }
  194. U32 triangle_range = tri_domain[1]-tri_domain[0];
  195. U32 count = triangles[idx].size();
  196. U32 total = 0;
  197. gGL.begin(LLRender::LINE_STRIP);
  198. //plot triangles
  199. for (U32 i = 0; i < count; ++i)
  200. {
  201. U32 tri_count = triangles[idx][i];
  202. total += tri_count;
  203. F32 y = (F32) (tri_count-tri_domain[0])/triangle_range*tri_rect.getHeight()+tri_rect.mBottom;
  204. F32 x = (F32) i / count * tri_rect.getWidth() + tri_rect.mLeft;
  205. gGL.vertex2f(x,y);
  206. if (i%4096 == 0)
  207. {
  208. gGL.end();
  209. gGL.flush();
  210. gGL.begin(LLRender::LINE_STRIP);
  211. }
  212. }
  213. gGL.end();
  214. gGL.flush();
  215. U32 total_visible = 0;
  216. count = visible_triangles[idx].size();
  217. for (U32 i = 0; i < count; ++i)
  218. {
  219. U32 tri_count = visible_triangles[idx][i];
  220. total_visible += tri_count;
  221. }
  222. std::string label = llformat("%s Object Triangle Counts (Ktris) -- Visible: %.2f/%.2f (%.2f KB Visible)",
  223. category[idx], total_visible_triangles[idx]/1024.f, total_triangles[idx]/1024.f, total_visible_bytes[idx]/1024.f);
  224. LLFontGL::getFontMonospace()->renderUTF8(label,
  225. 0 , tri_rect.mLeft, tri_rect.mTop+margin, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP);
  226. }
  227. }
  228. for (U32 idx = 0; idx < 2; ++idx)
  229. {
  230. if (!streaming_cost[idx].empty())
  231. { //plot graph of streaming cost
  232. std::sort(streaming_cost[idx].begin(), streaming_cost[idx].end());
  233. ll_remove_outliers(streaming_cost[idx], 1.f);
  234. LLRect tri_rect;
  235. if (idx == 0)
  236. {
  237. tri_rect = LLRect(margin, graph_pos[2]-margin, new_rect.getWidth()/2-margin, graph_pos[1]+margin);
  238. }
  239. else
  240. {
  241. tri_rect = LLRect(new_rect.getWidth()/2+margin, graph_pos[2]-margin, new_rect.getWidth()-margin, graph_pos[1]+margin);
  242. }
  243. gl_rect_2d(tri_rect, LLColor4::white, false);
  244. F32 streaming_domain[] = { 65536, 0 };
  245. //get domain of triangle counts
  246. for (U32 i = 0; i < streaming_cost[idx].size(); ++i)
  247. {
  248. streaming_domain[0] = llmin(streaming_domain[0], streaming_cost[idx][i]);
  249. streaming_domain[1] = llmax(streaming_domain[1], streaming_cost[idx][i]);
  250. }
  251. F32 cost_range = streaming_domain[1]-streaming_domain[0];
  252. U32 count = streaming_cost[idx].size();
  253. F32 total = 0;
  254. gGL.begin(LLRender::LINE_STRIP);
  255. //plot triangles
  256. for (U32 i = 0; i < count; ++i)
  257. {
  258. F32 sc = streaming_cost[idx][i];
  259. total += sc;
  260. F32 y = (F32) (sc-streaming_domain[0])/cost_range*tri_rect.getHeight()+tri_rect.mBottom;
  261. F32 x = (F32) i / count * tri_rect.getWidth() + tri_rect.mLeft;
  262. gGL.vertex2f(x,y);
  263. if (i%4096 == 0)
  264. {
  265. gGL.end();
  266. gGL.flush();
  267. gGL.begin(LLRender::LINE_STRIP);
  268. }
  269. }
  270. gGL.end();
  271. gGL.flush();
  272. std::string label = llformat("%s Object Streaming Cost -- [%.2f, %.2f] Mean: %.2f Total: %.2f",
  273. category[idx], streaming_domain[0], streaming_domain[1], total/count, total_streaming[idx]);
  274. LLFontGL::getFontMonospace()->renderUTF8(label,
  275. 0 , tri_rect.mLeft, tri_rect.mTop+margin, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP);
  276. }
  277. }
  278. for (U32 idx = 0; idx < 2; ++idx)
  279. {
  280. if (!physics_cost[idx].empty())
  281. { //plot graph of physics cost
  282. std::sort(physics_cost[idx].begin(), physics_cost[idx].end());
  283. ll_remove_outliers(physics_cost[idx], 1.f);
  284. LLRect tri_rect;
  285. if (idx == 0)
  286. {
  287. tri_rect = LLRect(margin, graph_pos[3]-margin, new_rect.getWidth()/2-margin, graph_pos[2]+margin);
  288. }
  289. else
  290. {
  291. tri_rect = LLRect(new_rect.getWidth()/2+margin, graph_pos[3]-margin, new_rect.getWidth()-margin, graph_pos[2]+margin);
  292. }
  293. gl_rect_2d(tri_rect, LLColor4::white, false);
  294. F32 physics_domain[] = { 65536, 0 };
  295. //get domain of triangle counts
  296. for (U32 i = 0; i < physics_cost[idx].size(); ++i)
  297. {
  298. physics_domain[0] = llmin(physics_domain[0], physics_cost[idx][i]);
  299. physics_domain[1] = llmax(physics_domain[1], physics_cost[idx][i]);
  300. }
  301. F32 cost_range = physics_domain[1]-physics_domain[0];
  302. U32 count = physics_cost[idx].size();
  303. F32 total = 0;
  304. gGL.begin(LLRender::LINE_STRIP);
  305. //plot triangles
  306. for (U32 i = 0; i < count; ++i)
  307. {
  308. F32 pc = physics_cost[idx][i];
  309. total += pc;
  310. F32 y = (F32) (pc-physics_domain[0])/cost_range*tri_rect.getHeight()+tri_rect.mBottom;
  311. F32 x = (F32) i / count * tri_rect.getWidth() + tri_rect.mLeft;
  312. gGL.vertex2f(x,y);
  313. if (i%4096 == 0)
  314. {
  315. gGL.end();
  316. gGL.flush();
  317. gGL.begin(LLRender::LINE_STRIP);
  318. }
  319. }
  320. gGL.end();
  321. gGL.flush();
  322. std::string label = llformat("%s Object Physics Cost -- [%.2f, %.2f] Mean: %.2f Total: %.2f",
  323. category[idx], physics_domain[0], physics_domain[1], total/count, total_physics[idx]);
  324. LLFontGL::getFontMonospace()->renderUTF8(label,
  325. 0 , tri_rect.mLeft, tri_rect.mTop+margin, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP);
  326. }
  327. }
  328. LLView::draw();
  329. }