fixed: auto_ptr -> unique_ptr
[opensg.git] / Source / System / Cluster / Base / OSGRenderNode.cpp
blobc692d013b0c6018173228dbfdec47664d547a57b
1 /*---------------------------------------------------------------------------*\
2 * OpenSG *
3 * *
4 * *
5 * Copyright (C) 2000-2002,2002 by the OpenSG Forum *
6 * *
7 * www.opensg.org *
8 * *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
10 * *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
13 * License *
14 * *
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
18 * *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
23 * *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
27 * *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
30 * Changes *
31 * *
32 * *
33 * *
34 * *
35 * *
36 * *
37 \*---------------------------------------------------------------------------*/
39 #include <stdlib.h>
40 #include <stdio.h>
42 #include <vector>
44 #include "OSGConfig.h"
45 #include "OSGGL.h"
46 #include "OSGGLU.h"
47 #include "OSGBaseFunctions.h"
48 #include "OSGTime.h"
49 #include "OSGLog.h"
50 #include "OSGMatrix.h"
51 #include "OSGWindow.h"
53 #include "OSGRenderNode.h"
55 OSG_USING_NAMESPACE using namespace std;
57 /** \class OSG::RenderNode
58 * \ingroup GrpSystemCluster
59 * \brief cluster node information
60 **/
62 RenderNode *RenderNode:: _predefined[] =
64 // some nvidia cards
65 new
66 RenderNode
68 1.0f / 83495245, // GF 4
69 1.0f / 16750624,
70 1.0f / 1161538447,
71 1.0f / 42022724,
72 1.0f / 83570644,
73 "NVIDIA Corporation", "GeForce4 Ti 4600/AGP/3DNOW!"
75 new
76 RenderNode
78 1.0f / 83495245, // GF 4
79 1.0f / 16750624,
80 1.0f / 1161538447,
81 1.0f / 42022724,
82 1.0f / 83570644,
83 "NVIDIA Corporation", "GeForce4 Ti 4600/AGP/SSE/3DNOW!"
85 new
86 RenderNode
88 1.0f / 83455190, // GF 4
89 1.0f / 16881114,
90 1.0f / 1061266770,
91 1.0f / 42022724,
92 1.0f / 83570644,
93 "NVIDIA Corporation", "GeForce4 Ti 4800 SE/AGP/SSE/3DNOW!"
95 new
96 RenderNode
98 1.0f / 105725796, // GF 4
99 1.0f / 20313509,
100 1.0f / 1168604741,
101 1.0f / 45037981,
102 1.0f / 107106583,
103 "NVIDIA Corporation", "GeForce4 Ti 4600/AGP/SSE2"
106 new RenderNode(1.0/ 7598000, // GF 256
107 1.0/ 7597000,
108 1.0/110599000,
109 1.0/ 18896143,
110 1.0/ 26220918,
111 "NVIDIA Corporation",
112 "GeForce 256/AGP"),
115 RenderNode
117 1.0f / 94383759, // GF 3
118 1.0f / 17733654,
119 1.0f / 897012437,
120 1.0f / 24905933,
121 1.0f / 45649003,
122 "NVIDIA Corporation", "GeForce3/AGP/3DNOW!"
125 RenderNode
127 1.0f / 94383759, // GF 3
128 1.0f / 17733654,
129 1.0f / 897012437,
130 1.0f / 24905933,
131 1.0f / 45649003,
132 "NVIDIA Corporation", "GeForce3/AGP/SSE2"
135 RenderNode
137 1.0f / 87097434, // GF 2 MX
138 1.0f / 18473570,
139 1.0f / 172343128,
140 1.0f / 49542156,
141 1.0f / 77120245,
142 "NVIDIA Corporation", "GeForce2 MX/AGP/3DNOW!"
145 // some sgi cards
147 RenderNode
149 1.0f / 1428577, // O2
150 1.0f / 581803,
151 1.0f / 66498959,
152 1.0f / 4047028,
153 1.0f / 1101353,
154 "SGI", "CRIME"
157 RenderNode
159 1.0f / 10121349, // IR2
160 1.0f / 7749685,
161 1.0f / 466657941,
162 1.0f / 38311070,
163 1.0f / 73507039,
164 "SGI", "IRL/M/2/64/4"
167 RenderNode
169 1.0f / 12237547, // ATI
170 1.0f / 12422953,
171 1.0f / 190803343,
172 1.0f / 41767062,
173 1.0f / 157129952,
174 "ATI Technologies Inc.", "Radeon 9700 PRO Pentium 4 (SSE2)"
176 NULL
179 /*-------------------------------------------------------------------------*/
180 /* Constructors */
182 /*! Constructor
184 RenderNode::RenderNode( Real32 invisibleFaceCost,
185 Real32 visibleFaceCost,
186 Real32 drawPixelCost,
187 Real32 readPixelCost,
188 Real32 writePixelCost,
189 const std::string &vendor,
190 const std::string &renderer) :
191 _visibleFaceCost (visibleFaceCost ),
192 _invisibleFaceCost(invisibleFaceCost),
193 _drawPixelCost (drawPixelCost ),
194 _readPixelCost (readPixelCost ),
195 _writePixelCost (writePixelCost ),
196 _vendor (vendor ),
197 _renderer (renderer )
201 /*! copy constructor
203 RenderNode::RenderNode(const RenderNode &source) :
204 _visibleFaceCost (source._visibleFaceCost ),
205 _invisibleFaceCost(source._invisibleFaceCost),
206 _drawPixelCost (source._drawPixelCost ),
207 _readPixelCost (source._readPixelCost ),
208 _writePixelCost (source._writePixelCost ),
209 _vendor (source._vendor ),
210 _renderer (source._renderer )
214 /*-------------------------------------------------------------------------*/
215 /* Destructor */
217 /*! Destructor documentation
219 RenderNode::~RenderNode(void)
223 /*-------------------------------------------------------------------------*/
224 /* Assignment */
226 /*! assignment
228 RenderNode &RenderNode::operator=(const RenderNode &source)
230 if(this == &source)
231 return *this;
233 _visibleFaceCost = source._visibleFaceCost;
234 _invisibleFaceCost = source._invisibleFaceCost;
235 _drawPixelCost = source._drawPixelCost;
236 _readPixelCost = source._readPixelCost;
237 _writePixelCost = source._writePixelCost;
238 _vendor = source._vendor;
239 _renderer = source._renderer;
241 return *this;
244 /*-------------------------------------------------------------------------*/
245 /* Performance analysis */
247 /*! This is a rough estimation of rendering costst for visible faces,
248 * faces outside the viewport and fill rate.
249 * <pre>
250 * // face cost calculation
251 * cost = invisible * invisibleFaceCost +
252 * max( visible * visibleFaceCost , pixel * pixelCost)
253 * </pre>
255 void RenderNode::determinePerformance(Window *window)
257 int c;
258 double t;
259 UInt32 width, height;
261 setVendor (reinterpret_cast<const char *>(glGetString(GL_VENDOR)));
262 setRenderer(reinterpret_cast<const char *>(glGetString(GL_RENDERER)));
264 // try to find precalculated values
265 for(c = 0; _predefined[c] != NULL; ++c)
267 if(_predefined[c]->getVendor() == getVendor() &&
268 _predefined[c]->getRenderer() == getRenderer())
270 SLOG << "Predefined performance values used." << endl;
271 *this = *_predefined[c];
272 return;
276 SLOG << "Start rendering benchmark" << endl;
277 window->activate();
279 // set viewport
280 glViewport(0, 0, window->getWidth(), window->getHeight());
282 glPushAttrib(GL_ALL_ATTRIB_BITS);
283 glDisable(GL_SCISSOR_TEST);
284 glEnable(GL_DEPTH_TEST);
285 glDisable(GL_COLOR_MATERIAL);
286 glEnable(GL_LIGHTING);
287 glDepthFunc(GL_LEQUAL);
288 for(int i = 0; i < 8; ++i)
289 glDisable(GL_LIGHT0 + i);
290 glEnable(GL_LIGHT0);
292 double a1, a2, b, r;
293 a1 = runFaceBench(1, 1);
294 a2 = runFaceBench(4, 1);
295 b = (a2 - .25 * a1) / .75;
296 r = runRasterBench();
298 _visibleFaceCost = Real32(1.0 / a1);
299 _invisibleFaceCost = Real32(1.0 / b);
300 _drawPixelCost = Real32(1.0 / r);
302 // test write performance
303 glPixelStorei(GL_PACK_ALIGNMENT, 1);
304 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
306 vector<UInt8> pixels;
307 width = window->getWidth();
308 height = window->getHeight();
309 pixels.resize(width * height * 4);
310 glFinish();
311 t = -getSystemTime();
312 for(c = 0; c < 2; ++c)
314 glReadPixels(0,
316 width,
317 height,
318 GL_RGB,
319 GL_UNSIGNED_BYTE,
320 &pixels[0]);
323 glFinish();
324 t += getSystemTime();
325 _readPixelCost = Real32(t / (c * width * height));
327 // test write performance
328 glMatrixMode(GL_MODELVIEW);
329 glPushMatrix();
330 glLoadIdentity();
331 glMatrixMode(GL_PROJECTION);
332 glPushMatrix();
333 glLoadIdentity();
334 gluOrtho2D(0, width, 0, height);
335 glRasterPos2i(0, 0);
336 glDisable(GL_DEPTH_TEST);
337 glFinish();
338 t = -getSystemTime();
339 for(c = 0; c < 2; ++c)
341 glDrawPixels(width, height, GL_RGB, GL_UNSIGNED_BYTE, &pixels[0]);
343 glFinish();
344 t += getSystemTime();
345 _writePixelCost = Real32(t / (c * width * height));
346 glEnable(GL_DEPTH_TEST);
347 glPopMatrix();
348 glMatrixMode(GL_MODELVIEW);
349 glPopMatrix();
350 SLOG << "End rendering benchmark" << endl;
352 glPopAttrib();
355 /*! Write class contents to the given data stream
357 void RenderNode::copyToBin(BinaryDataHandler &handle)
359 handle.putValue(_invisibleFaceCost);
360 handle.putValue(_visibleFaceCost);
361 handle.putValue(_drawPixelCost);
362 handle.putValue(_readPixelCost);
363 handle.putValue(_writePixelCost);
366 /*! Read class contents from the given data stream
368 void RenderNode::copyFromBin(BinaryDataHandler &handle)
370 handle.getValue(_invisibleFaceCost);
371 handle.getValue(_visibleFaceCost);
372 handle.getValue(_drawPixelCost);
373 handle.getValue(_readPixelCost);
374 handle.getValue(_writePixelCost);
377 /*! Set render performance values for a group of render nodes. The
378 * parameter <code>begin</code> points to the first and the parameter
379 * <code>end</code> points behind the last member of the group.
381 * It is assumed the a render group is as fast as all its members together.
382 * Render costs of culled faces are handled different. In the worst case
383 * invisible faces have to be culled by each render node. To take this
384 * into account, we set the group speed to process culled faces to the
385 * average of all group members.
387 void RenderNode::setGroup(const RenderNode *begin, const RenderNode *end)
389 const RenderNode *i;
390 Real32 invisibleFaces = 0;
391 Real32 visibleFaces = 0;
392 Real32 drawPixels = 0;
393 Real32 readPixels = 0;
394 Real32 writePixels = 0;
395 UInt32 count = 0;
397 for(count = 0, i = begin; i != end; ++i, count++)
399 invisibleFaces += 1.f / i->_invisibleFaceCost;
400 visibleFaces += 1.f / i->_visibleFaceCost;
401 drawPixels += 1.f / i->_drawPixelCost;
402 readPixels += 1.f / i->_readPixelCost;
403 writePixels += 1.f / i->_writePixelCost;
406 _invisibleFaceCost = (1.f / invisibleFaces);
407 _visibleFaceCost = (1.f / visibleFaces);
408 _drawPixelCost = (1.f / drawPixels);
409 _readPixelCost = (1.f / readPixels);
410 _writePixelCost = (1.f / writePixels);
413 /*! Dump class contents
415 void RenderNode::dump(void) const
417 FLOG(("Vendor : %s\n", _vendor.c_str()));
418 FLOG(("Rnderer : %s\n", _renderer.c_str()));
419 FLOG(("Culled Faces/s : %20.5f\n", 1.0 / _invisibleFaceCost));
420 FLOG(("Faces/s : %20.5f\n", 1.0 / _visibleFaceCost));
421 FLOG(("Pixel/s : %20.5f\n", 1.0 / _drawPixelCost));
422 FLOG(("Read pixel/s : %20.5f\n", 1.0 / _readPixelCost));
423 FLOG(("Write pixel/s : %20.5f\n", 1.0 / _writePixelCost));
426 /*! Render small faces as triangle stripes. With the parameter w
427 * it is possible to set the amount of visible faces. If w=1
428 * then all faces are visible. If w=2 then 1/2 of the faces are
429 * visible. The function returns the number of faces that could
430 * be rendered in one second. We are using triangle stripes with
431 * 8 faces to run the benchmark.
433 double RenderNode::runFaceBench(float w, int size)
435 int c;
436 int faces = 0;
438 // vp size
439 GLint view[4];
440 glGetIntegerv(GL_VIEWPORT, view);
442 int vw = view[2], vh = view[3];
444 // set projection
445 glMatrixMode(GL_MODELVIEW);
446 glPushMatrix();
447 glLoadIdentity();
448 glMatrixMode(GL_PROJECTION);
449 glPushMatrix();
450 glLoadIdentity();
451 gluOrtho2D(0, vw, 0, vh);
452 glMatrixMode(GL_MODELVIEW);
454 // create display list
455 GLuint dList = glGenLists(1);
456 glNewList(dList, GL_COMPILE);
457 glBegin(GL_TRIANGLE_STRIP);
458 for(int x = 0; x <= (vw * w); x += size)
460 glNormal3f(0, 0, 1);
461 glVertex3i(x, 0, 1);
462 glNormal3f(0, 0, 1);
463 glVertex3i(x, size, 1);
464 if(((x & 3) == 3) && (x != (vw * w)))
466 glEnd();
467 glBegin(GL_TRIANGLE_STRIP);
468 glNormal3f(0, 0, 1);
469 glVertex3i(x, 0, 1);
470 glNormal3f(0, 0, 1);
471 glVertex3i(x, size, 1);
475 glEnd();
476 glEndList();
477 glFinish();
479 // run test
480 Time t = 0;
481 c = 0;
482 glPushMatrix();
485 glLoadIdentity();
486 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
487 glFinish();
488 t -= getSystemTime();
489 for(int y = 0; y < vh; y += size)
491 glCallList(dList);
492 glTranslatef(0, GLfloat(size), 0);
495 glFinish();
496 t += getSystemTime();
497 c++;
498 } while(t < .5);
499 glPopMatrix();
500 faces = Int32(((vw * w * 2) / size) * (vh / size) * c);
502 // reset projection
503 glMatrixMode(GL_PROJECTION);
504 glPopMatrix();
505 glMatrixMode(GL_MODELVIEW);
506 glPopMatrix();
507 glMatrixMode(GL_PROJECTION);
509 glDeleteLists(dList, 1);
510 return faces / t;
513 /*! Render one large face over the whole viewport. The returned value
514 * is the number of pixels that could be rendered in one second.
516 double RenderNode::runRasterBench(void)
518 int c;
520 // vp size
521 GLint view[4];
522 glGetIntegerv(GL_VIEWPORT, view);
524 int vw = view[2], vh = view[3];
526 // set projection
527 glMatrixMode(GL_MODELVIEW);
528 glPushMatrix();
529 glLoadIdentity();
530 glMatrixMode(GL_PROJECTION);
531 glPushMatrix();
532 glLoadIdentity();
533 gluOrtho2D(0, vw, 0, vh);
535 // create display list
536 GLuint dList = glGenLists(1);
537 glNewList(dList, GL_COMPILE);
538 glBegin(GL_QUADS);
539 glVertex3i(0, 0, 1);
540 glNormal3f(0, 0, 1);
541 glVertex3i(0, vh - 1, 1);
542 glNormal3f(0, 0, 1);
543 glVertex3i(vw - 1, vh - 1, 1);
544 glNormal3f(0, 0, 1);
545 glVertex3i(vw - 1, 0, 1);
546 glNormal3f(0, 0, 1);
547 glEnd();
548 glEndList();
549 glFinish();
551 // run test
552 Time t = 0;
553 c = 0;
556 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
557 glFinish();
558 t -= getSystemTime();
559 glCallList(dList);
560 glFinish();
561 t += getSystemTime();
562 c++;
564 while(t < .5);
566 // reset projection
567 glMatrixMode(GL_PROJECTION);
568 glPopMatrix();
569 glMatrixMode(GL_MODELVIEW);
570 glPopMatrix();
571 glMatrixMode(GL_PROJECTION);
573 glDeleteLists(dList, 1);
574 return (vw * vh * c) / t;
577 bool RenderNode::cleanPredefined(void)
579 for(UInt32 c = 0; _predefined[c] != NULL; ++c)
581 delete _predefined[c];
583 _predefined[c] = NULL;
586 return true;
589 bool RenderNode::registerCleanup(void)
591 addPreMPExitFunction(&RenderNode::cleanPredefined);
593 return true;
596 StaticInitFuncWrapper RenderNode::RenderNodeInitCleanup(
597 &RenderNode::registerCleanup);