/indra/newview/llsceneview.cpp
C++ | 438 lines | 290 code | 109 blank | 39 comment | 39 complexity | 9234574910f25e4b54c1aafeacefb2b5 MD5 | raw file
Possible License(s): LGPL-2.1
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 27#include "llviewerprecompiledheaders.h" 28 29#include "llsceneview.h" 30#include "llviewerwindow.h" 31#include "pipeline.h" 32#include "llviewerobjectlist.h" 33#include "llviewerregion.h" 34#include "llagent.h" 35#include "llvolumemgr.h" 36 37LLSceneView* gSceneView = NULL; 38 39//borrow this helper function from llfasttimerview.cpp 40template <class VEC_TYPE> 41void removeOutliers(std::vector<VEC_TYPE>& data, F32 k); 42 43 44LLSceneView::LLSceneView(const LLRect& rect) 45 : LLFloater(LLSD()) 46{ 47 setRect(rect); 48 setVisible(FALSE); 49 50 setCanMinimize(false); 51 setCanClose(true); 52} 53 54void LLSceneView::onClickCloseBtn() 55{ 56 setVisible(false); 57} 58 59 60void LLSceneView::draw() 61{ 62 S32 margin = 10; 63 S32 height = (S32) (gViewerWindow->getWindowRectScaled().getHeight()*0.75f); 64 S32 width = (S32) (gViewerWindow->getWindowRectScaled().getWidth() * 0.75f); 65 66 LLRect new_rect; 67 new_rect.setLeftTopAndSize(getRect().mLeft, getRect().mTop, width, height); 68 setRect(new_rect); 69 70 // Draw the window background 71 gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); 72 gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4(0.f, 0.f, 0.f, 0.25f)); 73 74 75 //aggregate some statistics 76 77 //object sizes 78 std::vector<F32> size[2]; 79 80 //triangle counts 81 std::vector<S32> triangles[2]; 82 std::vector<S32> visible_triangles[2]; 83 S32 total_visible_triangles[] = {0, 0}; 84 S32 total_triangles[] = {0, 0}; 85 86 S32 total_visible_bytes[] = {0, 0}; 87 S32 total_bytes[] = {0, 0}; 88 89 //streaming cost 90 std::vector<F32> streaming_cost[2]; 91 F32 total_streaming[] = { 0.f, 0.f }; 92 93 //physics cost 94 std::vector<F32> physics_cost[2]; 95 F32 total_physics[] = { 0.f, 0.f }; 96 97 98 U32 object_count = 0; 99 100 LLViewerRegion* region = gAgent.getRegion(); 101 if (region) 102 { 103 for (U32 i = 0; i < gObjectList.getNumObjects(); ++i) 104 { 105 LLViewerObject* object = gObjectList.getObject(i); 106 107 if (object && 108 object->getVolume()&& 109 object->getRegion() == region) 110 { 111 U32 idx = object->isAttachment() ? 1 : 0; 112 113 LLVolume* volume = object->getVolume(); 114 object_count++; 115 116 F32 radius = object->getScale().magVec(); 117 size[idx].push_back(radius); 118 119 S32 visible = volume->getNumTriangles(); 120 S32 high_triangles = object->getHighLODTriangleCount(); 121 122 total_visible_triangles[idx] += visible; 123 total_triangles[idx] += high_triangles; 124 125 visible_triangles[idx].push_back(visible); 126 triangles[idx].push_back(high_triangles); 127 128 S32 bytes = 0; 129 S32 visible_bytes = 0; 130 131 F32 streaming = object->getStreamingCost(&bytes, &visible_bytes); 132 total_streaming[idx] += streaming; 133 streaming_cost[idx].push_back(streaming); 134 135 F32 physics = object->getPhysicsCost(); 136 total_physics[idx] += physics; 137 physics_cost[idx].push_back(physics); 138 139 total_bytes[idx] += bytes; 140 total_visible_bytes[idx] += visible_bytes; 141 } 142 } 143 } 144 145 const char* category[] = 146 { 147 "Region", 148 "Attachment" 149 }; 150 151 S32 graph_pos[4]; 152 153 for (U32 i = 0; i < 4; ++i) 154 { 155 graph_pos[i] = new_rect.getHeight()/4*(i+1); 156 } 157 158 for (U32 idx = 0; idx < 2; idx++) 159 { 160 if (!size[idx].empty()) 161 { //display graph of object sizes 162 std::sort(size[idx].begin(), size[idx].end()); 163 164 ll_remove_outliers(size[idx], 1.f); 165 166 LLRect size_rect; 167 168 if (idx == 0) 169 { 170 size_rect = LLRect(margin, graph_pos[0]-margin, new_rect.getWidth()/2-margin, margin*2); 171 } 172 else 173 { 174 size_rect = LLRect(margin+new_rect.getWidth()/2, graph_pos[0]-margin, new_rect.getWidth()-margin, margin*2); 175 } 176 177 gl_rect_2d(size_rect, LLColor4::white, false); 178 179 F32 size_domain[] = { 128.f, 0.f }; 180 181 //get domain of sizes 182 for (U32 i = 0; i < size[idx].size(); ++i) 183 { 184 size_domain[0] = llmin(size_domain[0], size[idx][i]); 185 size_domain[1] = llmax(size_domain[1], size[idx][i]); 186 } 187 188 F32 size_range = size_domain[1]-size_domain[0]; 189 190 U32 count = size[idx].size(); 191 192 F32 total = 0.f; 193 194 gGL.begin(LLRender::LINE_STRIP); 195 196 for (U32 i = 0; i < count; ++i) 197 { 198 F32 rad = size[idx][i]; 199 total += rad; 200 F32 y = (rad-size_domain[0])/size_range*size_rect.getHeight()+size_rect.mBottom; 201 F32 x = (F32) i / count * size_rect.getWidth() + size_rect.mLeft; 202 203 gGL.vertex2f(x,y); 204 205 if (i%4096 == 0) 206 { 207 gGL.end(); 208 gGL.flush(); 209 gGL.begin(LLRender::LINE_STRIP); 210 } 211 } 212 213 gGL.end(); 214 gGL.flush(); 215 216 std::string label = llformat("%s Object Sizes (m) -- [%.1f, %.1f] Mean: %.1f Median: %.1f -- %d samples", 217 category[idx], size_domain[0], size_domain[1], total/count, size[idx][count/2], count); 218 219 LLFontGL::getFontMonospace()->renderUTF8(label, 220 0 , size_rect.mLeft, size_rect.mTop+margin, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP); 221 222 } 223 } 224 225 for (U32 idx = 0; idx < 2; ++idx) 226 { 227 if (!triangles[idx].empty()) 228 { //plot graph of visible/total triangles 229 std::sort(triangles[idx].begin(), triangles[idx].end()); 230 231 ll_remove_outliers(triangles[idx], 1.f); 232 233 LLRect tri_rect; 234 if (idx == 0) 235 { 236 tri_rect = LLRect(margin, graph_pos[1]-margin, new_rect.getWidth()/2-margin, graph_pos[0]+margin); 237 } 238 else 239 { 240 tri_rect = LLRect(new_rect.getWidth()/2+margin, graph_pos[1]-margin, new_rect.getWidth()-margin, graph_pos[0]+margin); 241 } 242 243 gl_rect_2d(tri_rect, LLColor4::white, false); 244 245 S32 tri_domain[] = { 65536, 0 }; 246 247 //get domain of triangle counts 248 for (U32 i = 0; i < triangles[idx].size(); ++i) 249 { 250 tri_domain[0] = llmin(tri_domain[0], triangles[idx][i]); 251 tri_domain[1] = llmax(tri_domain[1], triangles[idx][i]); 252 } 253 254 U32 triangle_range = tri_domain[1]-tri_domain[0]; 255 256 U32 count = triangles[idx].size(); 257 258 U32 total = 0; 259 260 gGL.begin(LLRender::LINE_STRIP); 261 //plot triangles 262 for (U32 i = 0; i < count; ++i) 263 { 264 U32 tri_count = triangles[idx][i]; 265 total += tri_count; 266 F32 y = (F32) (tri_count-tri_domain[0])/triangle_range*tri_rect.getHeight()+tri_rect.mBottom; 267 F32 x = (F32) i / count * tri_rect.getWidth() + tri_rect.mLeft; 268 269 gGL.vertex2f(x,y); 270 271 if (i%4096 == 0) 272 { 273 gGL.end(); 274 gGL.flush(); 275 gGL.begin(LLRender::LINE_STRIP); 276 } 277 } 278 279 gGL.end(); 280 gGL.flush(); 281 282 U32 total_visible = 0; 283 count = visible_triangles[idx].size(); 284 285 for (U32 i = 0; i < count; ++i) 286 { 287 U32 tri_count = visible_triangles[idx][i]; 288 total_visible += tri_count; 289 } 290 291 std::string label = llformat("%s Object Triangle Counts (Ktris) -- Visible: %.2f/%.2f (%.2f KB Visible)", 292 category[idx], total_visible_triangles[idx]/1024.f, total_triangles[idx]/1024.f, total_visible_bytes[idx]/1024.f); 293 294 LLFontGL::getFontMonospace()->renderUTF8(label, 295 0 , tri_rect.mLeft, tri_rect.mTop+margin, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP); 296 297 } 298 } 299 300 for (U32 idx = 0; idx < 2; ++idx) 301 { 302 if (!streaming_cost[idx].empty()) 303 { //plot graph of streaming cost 304 std::sort(streaming_cost[idx].begin(), streaming_cost[idx].end()); 305 306 ll_remove_outliers(streaming_cost[idx], 1.f); 307 308 LLRect tri_rect; 309 if (idx == 0) 310 { 311 tri_rect = LLRect(margin, graph_pos[2]-margin, new_rect.getWidth()/2-margin, graph_pos[1]+margin); 312 } 313 else 314 { 315 tri_rect = LLRect(new_rect.getWidth()/2+margin, graph_pos[2]-margin, new_rect.getWidth()-margin, graph_pos[1]+margin); 316 } 317 318 gl_rect_2d(tri_rect, LLColor4::white, false); 319 320 F32 streaming_domain[] = { 65536, 0 }; 321 322 //get domain of triangle counts 323 for (U32 i = 0; i < streaming_cost[idx].size(); ++i) 324 { 325 streaming_domain[0] = llmin(streaming_domain[0], streaming_cost[idx][i]); 326 streaming_domain[1] = llmax(streaming_domain[1], streaming_cost[idx][i]); 327 } 328 329 F32 cost_range = streaming_domain[1]-streaming_domain[0]; 330 331 U32 count = streaming_cost[idx].size(); 332 333 F32 total = 0; 334 335 gGL.begin(LLRender::LINE_STRIP); 336 //plot triangles 337 for (U32 i = 0; i < count; ++i) 338 { 339 F32 sc = streaming_cost[idx][i]; 340 total += sc; 341 F32 y = (F32) (sc-streaming_domain[0])/cost_range*tri_rect.getHeight()+tri_rect.mBottom; 342 F32 x = (F32) i / count * tri_rect.getWidth() + tri_rect.mLeft; 343 344 gGL.vertex2f(x,y); 345 346 if (i%4096 == 0) 347 { 348 gGL.end(); 349 gGL.flush(); 350 gGL.begin(LLRender::LINE_STRIP); 351 } 352 } 353 354 gGL.end(); 355 gGL.flush(); 356 357 std::string label = llformat("%s Object Streaming Cost -- [%.2f, %.2f] Mean: %.2f Total: %.2f", 358 category[idx], streaming_domain[0], streaming_domain[1], total/count, total_streaming[idx]); 359 360 LLFontGL::getFontMonospace()->renderUTF8(label, 361 0 , tri_rect.mLeft, tri_rect.mTop+margin, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP); 362 363 } 364 } 365 366 for (U32 idx = 0; idx < 2; ++idx) 367 { 368 if (!physics_cost[idx].empty()) 369 { //plot graph of physics cost 370 std::sort(physics_cost[idx].begin(), physics_cost[idx].end()); 371 372 ll_remove_outliers(physics_cost[idx], 1.f); 373 374 LLRect tri_rect; 375 if (idx == 0) 376 { 377 tri_rect = LLRect(margin, graph_pos[3]-margin, new_rect.getWidth()/2-margin, graph_pos[2]+margin); 378 } 379 else 380 { 381 tri_rect = LLRect(new_rect.getWidth()/2+margin, graph_pos[3]-margin, new_rect.getWidth()-margin, graph_pos[2]+margin); 382 } 383 384 gl_rect_2d(tri_rect, LLColor4::white, false); 385 386 F32 physics_domain[] = { 65536, 0 }; 387 388 //get domain of triangle counts 389 for (U32 i = 0; i < physics_cost[idx].size(); ++i) 390 { 391 physics_domain[0] = llmin(physics_domain[0], physics_cost[idx][i]); 392 physics_domain[1] = llmax(physics_domain[1], physics_cost[idx][i]); 393 } 394 395 F32 cost_range = physics_domain[1]-physics_domain[0]; 396 397 U32 count = physics_cost[idx].size(); 398 399 F32 total = 0; 400 401 gGL.begin(LLRender::LINE_STRIP); 402 //plot triangles 403 for (U32 i = 0; i < count; ++i) 404 { 405 F32 pc = physics_cost[idx][i]; 406 total += pc; 407 F32 y = (F32) (pc-physics_domain[0])/cost_range*tri_rect.getHeight()+tri_rect.mBottom; 408 F32 x = (F32) i / count * tri_rect.getWidth() + tri_rect.mLeft; 409 410 gGL.vertex2f(x,y); 411 412 if (i%4096 == 0) 413 { 414 gGL.end(); 415 gGL.flush(); 416 gGL.begin(LLRender::LINE_STRIP); 417 } 418 } 419 420 gGL.end(); 421 gGL.flush(); 422 423 std::string label = llformat("%s Object Physics Cost -- [%.2f, %.2f] Mean: %.2f Total: %.2f", 424 category[idx], physics_domain[0], physics_domain[1], total/count, total_physics[idx]); 425 426 LLFontGL::getFontMonospace()->renderUTF8(label, 427 0 , tri_rect.mLeft, tri_rect.mTop+margin, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP); 428 429 } 430 } 431 432 433 434 435 LLView::draw(); 436} 437 438