1 /*---------------------------------------------------------------------------*\
5 * Copyright (C) 2000-2002,2002 by the OpenSG Forum *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
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. *
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. *
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. *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
37 \*---------------------------------------------------------------------------*/
44 #include "OSGConfig.h"
47 #include "OSGBaseFunctions.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
62 RenderNode
*RenderNode:: _predefined
[] =
68 1.0f
/ 83495245, // GF 4
73 "NVIDIA Corporation", "GeForce4 Ti 4600/AGP/3DNOW!"
78 1.0f
/ 83495245, // GF 4
83 "NVIDIA Corporation", "GeForce4 Ti 4600/AGP/SSE/3DNOW!"
88 1.0f
/ 83455190, // GF 4
93 "NVIDIA Corporation", "GeForce4 Ti 4800 SE/AGP/SSE/3DNOW!"
98 1.0f
/ 105725796, // GF 4
103 "NVIDIA Corporation", "GeForce4 Ti 4600/AGP/SSE2"
106 new RenderNode(1.0/ 7598000, // GF 256
111 "NVIDIA Corporation",
117 1.0f
/ 94383759, // GF 3
122 "NVIDIA Corporation", "GeForce3/AGP/3DNOW!"
127 1.0f
/ 94383759, // GF 3
132 "NVIDIA Corporation", "GeForce3/AGP/SSE2"
137 1.0f
/ 87097434, // GF 2 MX
142 "NVIDIA Corporation", "GeForce2 MX/AGP/3DNOW!"
149 1.0f
/ 1428577, // O2
159 1.0f
/ 10121349, // IR2
164 "SGI", "IRL/M/2/64/4"
169 1.0f
/ 12237547, // ATI
174 "ATI Technologies Inc.", "Radeon 9700 PRO Pentium 4 (SSE2)"
179 /*-------------------------------------------------------------------------*/
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
),
197 _renderer (renderer
)
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 /*-------------------------------------------------------------------------*/
217 /*! Destructor documentation
219 RenderNode::~RenderNode(void)
223 /*-------------------------------------------------------------------------*/
228 RenderNode
&RenderNode::operator=(const RenderNode
&source
)
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
;
244 /*-------------------------------------------------------------------------*/
245 /* Performance analysis */
247 /*! This is a rough estimation of rendering costst for visible faces,
248 * faces outside the viewport and fill rate.
250 * // face cost calculation
251 * cost = invisible * invisibleFaceCost +
252 * max( visible * visibleFaceCost , pixel * pixelCost)
255 void RenderNode::determinePerformance(Window
*window
)
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
];
276 SLOG
<< "Start rendering benchmark" << endl
;
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
);
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);
311 t
= -getSystemTime();
312 for(c
= 0; c
< 2; ++c
)
324 t
+= getSystemTime();
325 _readPixelCost
= Real32(t
/ (c
* width
* height
));
327 // test write performance
328 glMatrixMode(GL_MODELVIEW
);
331 glMatrixMode(GL_PROJECTION
);
334 gluOrtho2D(0, width
, 0, height
);
336 glDisable(GL_DEPTH_TEST
);
338 t
= -getSystemTime();
339 for(c
= 0; c
< 2; ++c
)
341 glDrawPixels(width
, height
, GL_RGB
, GL_UNSIGNED_BYTE
, &pixels
[0]);
344 t
+= getSystemTime();
345 _writePixelCost
= Real32(t
/ (c
* width
* height
));
346 glEnable(GL_DEPTH_TEST
);
348 glMatrixMode(GL_MODELVIEW
);
350 SLOG
<< "End rendering benchmark" << endl
;
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
)
390 Real32 invisibleFaces
= 0;
391 Real32 visibleFaces
= 0;
392 Real32 drawPixels
= 0;
393 Real32 readPixels
= 0;
394 Real32 writePixels
= 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
)
440 glGetIntegerv(GL_VIEWPORT
, view
);
442 int vw
= view
[2], vh
= view
[3];
445 glMatrixMode(GL_MODELVIEW
);
448 glMatrixMode(GL_PROJECTION
);
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
)
463 glVertex3i(x
, size
, 1);
464 if(((x
& 3) == 3) && (x
!= (vw
* w
)))
467 glBegin(GL_TRIANGLE_STRIP
);
471 glVertex3i(x
, size
, 1);
486 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
488 t
-= getSystemTime();
489 for(int y
= 0; y
< vh
; y
+= size
)
492 glTranslatef(0, GLfloat(size
), 0);
496 t
+= getSystemTime();
500 faces
= Int32(((vw
* w
* 2) / size
) * (vh
/ size
) * c
);
503 glMatrixMode(GL_PROJECTION
);
505 glMatrixMode(GL_MODELVIEW
);
507 glMatrixMode(GL_PROJECTION
);
509 glDeleteLists(dList
, 1);
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)
522 glGetIntegerv(GL_VIEWPORT
, view
);
524 int vw
= view
[2], vh
= view
[3];
527 glMatrixMode(GL_MODELVIEW
);
530 glMatrixMode(GL_PROJECTION
);
533 gluOrtho2D(0, vw
, 0, vh
);
535 // create display list
536 GLuint dList
= glGenLists(1);
537 glNewList(dList
, GL_COMPILE
);
541 glVertex3i(0, vh
- 1, 1);
543 glVertex3i(vw
- 1, vh
- 1, 1);
545 glVertex3i(vw
- 1, 0, 1);
556 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
558 t
-= getSystemTime();
561 t
+= getSystemTime();
567 glMatrixMode(GL_PROJECTION
);
569 glMatrixMode(GL_MODELVIEW
);
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
;
589 bool RenderNode::registerCleanup(void)
591 addPreMPExitFunction(&RenderNode::cleanPredefined
);
596 StaticInitFuncWrapper
RenderNode::RenderNodeInitCleanup(
597 &RenderNode::registerCleanup
);