Equalizer  1.6.1
eqPixelBench/channel.cpp
1 
2 /* Copyright (c) 2007-2013, Stefan Eilemann <eile@equalizergraphics.com>
3  * 2012, Daniel Nachbaur <danielnachbaur@gmail.com>
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * - Redistributions of source code must retain the above copyright notice, this
9  * list of conditions and the following disclaimer.
10  * - Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  * - Neither the name of Eyescale Software GmbH nor the names of its
14  * contributors may be used to endorse or promote products derived from this
15  * software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include "channel.h"
31 
32 #include "config.h"
33 #include "configEvent.h"
34 
35 #ifdef WIN32_API
36 # define snprintf _snprintf
37 #endif
38 
39 namespace eqPixelBench
40 {
41 namespace
42 {
43 #pragma warning(disable: 411) // class defines no constructor to initialize ...
44 struct EnumMap
45 {
46  const char* internalFormatString;
47  const uint32_t internalFormat;
48  const size_t pixelSize;
49 };
50 
51 #pragma warning(default: 411)
52 
53 #define ENUM_MAP_ITEM( internalFormat, pixelSize ) \
54  { #internalFormat, EQ_COMPRESSOR_DATATYPE_ ## internalFormat, pixelSize }
55 
56 static EnumMap _enums[] = {
57  ENUM_MAP_ITEM( RGBA32F, 16 ), // initial buffer resize
58  ENUM_MAP_ITEM( RGBA, 4 ),
59  ENUM_MAP_ITEM( RGB10_A2, 4 ),
60  ENUM_MAP_ITEM( RGBA16F, 8 ),
61  ENUM_MAP_ITEM( RGBA32F, 16 ),
62  ENUM_MAP_ITEM( DEPTH, 4 ),
63  { 0, 0, 0 }};
64 #define NUM_IMAGES 8
65 }
66 
67 Channel::Channel( eq::Window* parent )
68  : eq::Channel( parent )
69 {
70  eq::FrameDataPtr frameData = new eq::FrameData;
71  _frame.setFrameData( frameData );
72 
73  for( unsigned i = 0; i < NUM_IMAGES; ++i )
74  frameData->newImage( eq::Frame::TYPE_MEMORY, getDrawableConfig( ));
75 }
76 
78 {
79  _frame.getFrameData()->resetPlugins();
80  return eq::Channel::configExit();
81 }
82 
83 void Channel::frameStart( const eq::uint128_t& frameID,
84  const uint32_t frameNumber )
85 {
86  Config* config = static_cast< Config* >( getConfig( ));
87  const lunchbox::Clock* clock = config->getClock();
88 
89  if( clock )
90  {
91  const std::string formatType = "app->pipe thread latency";
92  _sendEvent( START_LATENCY, clock->getTimef(), eq::Vector2i( 0, 0 ),
93  formatType, 0, 0 );
94  }
95 
96  eq::Channel::frameStart( frameID, frameNumber );
97 }
98 
99 void Channel::frameDraw( const eq::uint128_t& frameID )
100 {
101  //----- setup GL state
102  applyBuffer();
103  applyViewport();
104 
105  glMatrixMode( GL_PROJECTION );
106  glLoadIdentity();
107 
108  applyFrustum();
109 
110  glMatrixMode( GL_MODELVIEW );
111  glLoadIdentity();
113 
115 
116  _testFormats( 1.0f );
117  _testFormats( 0.5f );
118  _testFormats( 2.0f );
119  _testTiledOperations();
120  _testDepthAssemble();
121 
123 }
124 
125 void Channel::_testFormats( float applyZoom )
126 {
127  glGetError(); // reset
128 
129  //----- setup constant data
130  const eq::Images& images = _frame.getImages();
131  eq::Image* image = images[ 0 ];
132  LBASSERT( image );
133 
134  const eq::PixelViewport& pvp = getPixelViewport();
135  const eq::Vector2i offset( pvp.x, pvp.y );
136  const eq::Zoom zoom( applyZoom, applyZoom );
137 
138  lunchbox::Clock clock;
140 
141  //----- test all default format/type combinations
142  for( uint32_t i=0; _enums[i].internalFormatString; ++i )
143  {
144  const uint32_t internalFormat = _enums[i].internalFormat;
145  image->flush();
146  image->setInternalFormat( eq::Frame::BUFFER_COLOR, internalFormat );
147  image->setQuality( eq::Frame::BUFFER_COLOR, 0.f );
148  image->setAlphaUsage( false );
149 
150  const GLEWContext* glewContext = glewGetContext();
151  const std::vector< uint32_t >& names =
152  image->findTransferers( eq::Frame::BUFFER_COLOR, glewContext );
153 
154  for( std::vector< uint32_t >::const_iterator j = names.begin();
155  j != names.end(); ++j )
156  {
157  _draw( eq::uint128_t( 0 ));
158 
159  image->allocDownloader( eq::Frame::BUFFER_COLOR, *j, glewContext );
160  image->setPixelViewport( pvp );
161 
162  const uint32_t outputToken =
164  std::stringstream formatType;
165  formatType << _enums[i].internalFormatString << outputToken << *j;
166 
167  // read
168  glFinish();
169  size_t nLoops = 0;
170  try
171  {
172  clock.reset();
173  while( clock.getTime64() < 100 /*ms*/ )
174  {
175  image->startReadback( eq::Frame::BUFFER_COLOR, pvp, zoom,
176  glObjects );
177  image->finishReadback( zoom, glObjects->glewGetContext( ));
178  ++nLoops;
179  }
180  glFinish();
181  const float msec = clock.getTimef() / float( nLoops );
182  const GLenum error = glGetError(); // release mode
183  if( error != GL_NO_ERROR )
184  throw eq::GLException( error );
185 
186  const eq::PixelData& pixels =
188  const eq::Vector2i area( pixels.pvp.w, pixels.pvp.h );
189  const uint64_t dataSizeGPU = area.x() * area.y() *
190  _enums[i].pixelSize;
191  const uint64_t dataSizeCPU =
193 
194  _sendEvent( READBACK, msec, area, formatType.str(), dataSizeGPU,
195  dataSizeCPU );
196  }
197  catch( const eq::GLException& e )
198  {
199  _sendEvent( READBACK, -static_cast<float>( e.glError ),
200  eq::Vector2i(), formatType.str(), 0, 0 );
201  continue;
202  }
203 
204  // write
206  op.channel = this;
208  op.offset = offset;
209  op.zoom = zoom;
210 
211  const uint64_t dataSizeCPU =
213  try
214  {
215  clock.reset();
216  eq::Compositor::assembleImage( image, op );
217  glFinish();
218  const float msec = clock.getTimef() / float( nLoops );
219  const GLenum error = glGetError(); // release mode
220  if( error != GL_NO_ERROR )
221  throw eq::Exception( error );
222 
223  const eq::PixelData& pixels =
225  const eq::Vector2i area( pixels.pvp.w, pixels.pvp.h );
226  const uint64_t dataSizeGPU =
228  _sendEvent( ASSEMBLE, msec, area, formatType.str(), dataSizeGPU,
229  dataSizeCPU );
230  }
231  catch( const eq::GLException& e ) // debug mode
232  {
233  _sendEvent( ASSEMBLE, -static_cast<float>( e.glError ),
234  eq::Vector2i(), formatType.str(), 0, 0 );
235  }
236  }
237  }
238 }
239 
240 void Channel::_testTiledOperations()
241 {
242  glGetError(); // reset
243 
244  //----- setup constant data
245  const eq::Images& images = _frame.getImages();
246  LBASSERT( images[0] );
247 
248  const eq::PixelViewport& pvp = getPixelViewport();
249  const eq::Vector2i offset( pvp.x, pvp.y );
250 
251  eq::Vector2i area;
252  area.x() = pvp.w;
253 
254  lunchbox::Clock clock;
256  const GLEWContext* glewContext = glewGetContext();
257 
258  //----- test tiled assembly algorithms
259  eq::PixelViewport subPVP = pvp;
260  subPVP.h /= NUM_IMAGES;
261 
262  for( unsigned i = 0; i < NUM_IMAGES; ++i )
263  {
264  LBASSERT( images[ i ] );
265  images[ i ]->setPixelViewport( subPVP );
266  }
267 
268  for( unsigned tiles = 0; tiles < NUM_IMAGES; ++tiles )
269  {
270  EQ_GL_CALL( _draw( eq::uint128_t( )));
271  area.y() = subPVP.h * (tiles+1);
272 
273  //---- readback of 'tiles' depth images
274  std::stringstream formatType;
275  formatType << tiles+1 << " depth tiles";
276 
277  float msec = 0;
278  for( unsigned j = 0; j <= tiles; ++j )
279  {
280  subPVP.y = pvp.y + j * subPVP.h;
281  eq::Image* image = images[ j ];
282  LBCHECK( image->allocDownloader( eq::Frame::BUFFER_DEPTH,
283  EQ_COMPRESSOR_TRANSFER_DEPTH_TO_DEPTH_UNSIGNED_INT,
284  glewContext ));
286 
287  clock.reset();
288  image->startReadback( eq::Frame::BUFFER_DEPTH, subPVP,
289  eq::Zoom::NONE, glObjects );
290  image->finishReadback( eq::Zoom::NONE, glObjects->glewGetContext());
291  msec += clock.getTimef();
292  }
293 
294  _sendEvent( READBACK, msec, area, formatType.str(), 0, 0 );
295 
296  if( tiles == NUM_IMAGES-1 )
297  for( unsigned j = 0; j <= tiles; ++j )
298  _saveImage( images[j],
299  "EQ_COMPRESSOR_DATATYPE_DEPTH_UNSIGNED_INT",
300  "tiles" );
301 
302  //---- readback of 'tiles' color images
303  formatType.str("");
304  formatType << tiles+1 << " color tiles";
305 
306  msec = 0;
307  for( unsigned j = 0; j <= tiles; ++j )
308  {
309  subPVP.y = pvp.y + j * subPVP.h;
310  eq::Image* image = images[ j ];
311 
312  LBCHECK( image->allocDownloader( eq::Frame::BUFFER_COLOR,
313  EQ_COMPRESSOR_TRANSFER_RGBA_TO_BGRA,
314  glewContext ));
316 
317  clock.reset();
318  image->startReadback( eq::Frame::BUFFER_COLOR, subPVP,
319  eq::Zoom::NONE, glObjects );
320  image->finishReadback( eq::Zoom::NONE, glObjects->glewGetContext());
321  msec += clock.getTimef();
322  }
323  _sendEvent( READBACK, msec, area, formatType.str(), 0, 0 );
324 
325  if( tiles == NUM_IMAGES-1 )
326  for( unsigned j = 0; j <= tiles; ++j )
327  _saveImage( images[j],"EQ_COMPRESSOR_DATATYPE_BGRA","tiles" );
328 
329  //---- benchmark assembly operations
330  subPVP.y = pvp.y + tiles * subPVP.h;
331 
333  op.channel = this;
335  op.offset = offset;
336 
337  // fixed-function
338  formatType.str("");
339  formatType << "tiles, GL1.1, " << tiles+1 << " images";
340 
341  clock.reset();
342  for( unsigned j = 0; j <= tiles; ++j )
343  eq::Compositor::assembleImage( images[j], op );
344 
345  msec = clock.getTimef();
346  _sendEvent( ASSEMBLE, msec, area, formatType.str(), 0, 0 );
347 
348  // CPU
349  formatType.str("");
350  formatType << "tiles, CPU, " << tiles+1 << " images";
351 
352  std::vector< eq::Frame* > frames;
353  frames.push_back( &_frame );
354 
355  clock.reset();
356  eq::Compositor::assembleFramesCPU( frames, this );
357  msec = clock.getTimef();
358  _sendEvent( ASSEMBLE, msec, area, formatType.str(), 0, 0 );
359  }
360 }
361 
362 void Channel::_testDepthAssemble()
363 {
364  glGetError(); // reset
365 
366  //----- setup constant data
367  const eq::Images& images = _frame.getImages();
368  eq::Image* image = images[ 0 ];
369  LBASSERT( image );
370 
371  const eq::PixelViewport& pvp = getPixelViewport();
372  const eq::Vector2i offset( pvp.x, pvp.y );
373 
374  eq::Vector2i area;
375  area.x() = pvp.w;
376 
377  lunchbox::Clock clock;
379  const GLEWContext* glewContext = glewGetContext();
380 
381  //----- test depth-based assembly algorithms
382  for( unsigned i = 0; i < NUM_IMAGES; ++i )
383  {
384  image = images[ i ];
385  LBASSERT( image );
386  image->setPixelViewport( pvp );
387  }
388 
389  area.y() = pvp.h;
390 
391  for( uint64_t i = 0; i < NUM_IMAGES; ++i )
392  {
393  _draw( eq::uint128_t( i ));
394 
395  // fill depth & color image
396  image = images[ i ];
397 
398  LBCHECK( image->allocDownloader( eq::Frame::BUFFER_COLOR,
399  EQ_COMPRESSOR_TRANSFER_RGBA_TO_BGRA,
400  glewContext ));
401 
402  LBCHECK( image->allocDownloader( eq::Frame::BUFFER_DEPTH,
403  EQ_COMPRESSOR_TRANSFER_DEPTH_TO_DEPTH_UNSIGNED_INT,
404  glewContext ));
405 
408 
410  pvp, eq::Zoom::NONE, glObjects );
411  image->finishReadback( eq::Zoom::NONE, glObjects->glewGetContext( ));
412  LBASSERT( image->hasPixelData( eq::Frame::BUFFER_COLOR ));
413  LBASSERT( image->hasPixelData( eq::Frame::BUFFER_DEPTH ));
414 
415  if( i == NUM_IMAGES-1 )
416  _saveImage( image,"EQ_COMPRESSOR_DATATYPE_DEPTH_UNSIGNED_INT",
417  "depthAssemble" );
418 
419  // benchmark
421  op.channel = this;
423  op.offset = offset;
424 
425  // fixed-function
426  std::stringstream formatType;
427  formatType << "depth, GL1.1, " << i+1 << " images";
428 
429  clock.reset();
430  for( unsigned j = 0; j <= i; ++j )
431  eq::Compositor::assembleImageDB_FF( images[j], op );
432 
433  float msec = clock.getTimef();
434  _sendEvent( ASSEMBLE, msec, area, formatType.str(), 0, 0 );
435 
436  // GLSL
437  if( GLEW_VERSION_2_0 )
438  {
439  formatType.str("");
440  formatType << "depth, GLSL, " << i+1 << " images";
441 
442  clock.reset();
443  for( unsigned j = 0; j <= i; ++j )
444  eq::Compositor::assembleImageDB_GLSL( images[j], op );
445  msec = clock.getTimef();
446  _sendEvent( ASSEMBLE, msec, area, formatType.str(), 0, 0 );
447  }
448 
449  // CPU
450  formatType.str("");
451  formatType << "depth, CPU, " << i+1 << " images";
452 
453  std::vector< eq::Frame* > frames;
454  frames.push_back( &_frame );
455 
456  clock.reset();
457  eq::Compositor::assembleFramesCPU( frames, this );
458  msec = clock.getTimef();
459  _sendEvent( ASSEMBLE, msec, area, formatType.str(), 0, 0 );
460  }
461 }
462 
463 void Channel::_sendEvent( ConfigEventType type, const float msec,
464  const eq::Vector2i& area,
465  const std::string& formatType,
466  const uint64_t dataSizeGPU,
467  const uint64_t dataSizeCPU )
468 {
469  std::string name = getName();
470  if( name.empty( ))
471  {
472  std::stringstream strName;
473  strName << this;
474  name = strName.str();
475  }
476 
477  getConfig()->sendEvent( type )
478  << msec << name << area << formatType << dataSizeGPU << dataSizeCPU;
479 }
480 
481 void Channel::_saveImage( const eq::Image* image,
482  const char* externalformat,
483  const char* info )
484 {
485  return;
486 
487  static uint32_t counter = 0;
488  std::ostringstream stringstream;
489  stringstream << "Image_" << ++counter << "_" << externalformat << "_"
490  << info;
491  image->writeImages( stringstream.str( ));
492 }
493 
494 void Channel::_draw( const eq::uint128_t& spin )
495 {
496  bindFrameBuffer();
497  EQ_GL_CALL( glPushAttrib( GL_ALL_ATTRIB_BITS ));
498 
499  eq::Channel::frameDraw( spin );
500  EQ_GL_CALL( glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT ));
501  EQ_GL_CALL( glEnable( GL_DEPTH_TEST ));
502 
503  const float lightPos[] = { 0.0f, 0.0f, 1.0f, 0.0f };
504  glLightfv( GL_LIGHT0, GL_POSITION, lightPos );
505 
506  const float lightAmbient[] = { 0.2f, 0.2f, 0.2f, 1.0f };
507  glLightfv( GL_LIGHT0, GL_AMBIENT, lightAmbient );
508 
509  // rotate scene around the origin
510  glRotatef( static_cast< float >( spin.low() + 3 ) * 10, 1.0f, 0.5f, 0.25f );
511 
512  // render six axis-aligned colored quads around the origin
513  // front
514  glColor3f( 1.0f, 0.5f, 0.5f );
515  glNormal3f( 0.0f, 0.0f, 1.0f );
516  glBegin( GL_TRIANGLE_STRIP );
517  glVertex3f( .7f, .7f, -1.0f );
518  glVertex3f( -.7f, .7f, -1.0f );
519  glVertex3f( .7f, -.7f, -1.0f );
520  glVertex3f( -.7f, -.7f, -1.0f );
521  glEnd();
522 
523  // bottom
524  glColor3f( 0.5f, 1.0f, 0.5f );
525  glNormal3f( 0.0f, 1.0f, 0.0f );
526  glBegin( GL_TRIANGLE_STRIP );
527  glVertex3f( .7f, -1.0f, .7f );
528  glVertex3f( -.7f, -1.0f, .7f );
529  glVertex3f( .7f, -1.0f, -.7f );
530  glVertex3f( -.7f, -1.0f, -.7f );
531  glEnd();
532 
533  // back
534  glColor3f( 0.5f, 0.5f, 1.0f );
535  glNormal3f( 0.0f, 0.0f, -1.0f );
536  glBegin( GL_TRIANGLE_STRIP );
537  glVertex3f( .7f, .7f, 1.0f );
538  glVertex3f( -.7f, .7f, 1.0f );
539  glVertex3f( .7f, -.7f, 1.0f );
540  glVertex3f( -.7f, -.7f, 1.0f );
541  glEnd();
542 
543  // top
544  glColor3f( 1.0f, 1.0f, 0.5f );
545  glNormal3f( 0.f, -1.f, 0.f );
546  glBegin( GL_TRIANGLE_STRIP );
547  glVertex3f( .7f, 1.0f, .7f );
548  glVertex3f( -.7f, 1.0f, .7f );
549  glVertex3f( .7f, 1.0f, -.7f );
550  glVertex3f( -.7f, 1.0f, -.7f );
551  glEnd();
552 
553  // right
554  glColor3f( 1.0f, 0.5f, 1.0f );
555  glNormal3f( -1.f, 0.f, 0.f );
556  glBegin( GL_TRIANGLE_STRIP );
557  glVertex3f( 1.0f, .7f, .7f );
558  glVertex3f( 1.0f, -.7f, .7f );
559  glVertex3f( 1.0f, .7f, -.7f );
560  glVertex3f( 1.0f, -.7f, -.7f );
561  glEnd();
562 
563  // left
564  glColor3f( 0.5f, 1.0f, 1.0f );
565  glNormal3f( 1.f, 0.f, 0.f );
566  glBegin( GL_TRIANGLE_STRIP );
567  glVertex3f( -1.0f, .7f, .7f );
568  glVertex3f( -1.0f, -.7f, .7f );
569  glVertex3f( -1.0f, .7f, -.7f );
570  glVertex3f( -1.0f, -.7f, -.7f );
571  glEnd();
572 
573  EQ_GL_CALL( glPopAttrib( ));
574 }
575 
576 
577 }
A holder for multiple images.
static void assembleImageDB_FF(const Image *image, const ImageOp &op)
Start a Z-based assembly of the image color and depth attachment, based on OpenGL 1...
A channel represents a two-dimensional viewport within a Window.
Exception class for Equalizer operations.
Definition: exception.h:26
const PixelData & getPixelData(const Frame::Buffer) const
virtual void setupAssemblyState()
Setup the OpenGL state for a readback or assemble operation.
const Images & getImages() const
virtual void applyViewport() const
Apply the OpenGL viewport for the current rendering task.
virtual void frameStart(const uint128_t &frameID, const uint32_t frameNumber)
Start rendering a frame.
The pixel data structure manages the pixel information for images.
Definition: pixelData.h:33
static void assembleImageDB_GLSL(const Image *image, const ImageOp &op)
Start a Z-based assembly of the image color and depth attachment, using GLSL.
A holder for pixel data.
Definition: image.h:35
void setInternalFormat(const Frame::Buffer buffer, const uint32_t internalFormat)
Set the internal format for the given buffer.
A Window represents an on-screen or off-screen drawable.
const GLEWContext * glewGetContext() const
Get the GLEW context for this channel.
OpenGL Exception.
Definition: glException.h:27
Channel * channel
The destination channel.
Definition: compositor.h:52
virtual void applyBuffer()
Apply the current rendering buffer, including the color mask.
Zoom zoom
The zoom factor.
Definition: compositor.h:57
virtual bool configExit()
Exit this channel.
A facility class to manage OpenGL objects across shared contexts.
use main memory to store pixel data
Definition: fabric/frame.h:52
std::vector< Image * > Images
A vector of pointers to eq::Image.
uint32_t getExternalFormat(const Frame::Buffer buffer) const
Get the external format of the given buffer.
void sendEvent(ConfigEvent &event)
Send an (old) event to the application node.
virtual bool configExit()
Exit this channel.
void flush()
Free all cached data of this image.
virtual void applyHeadTransform() const
Apply the transformation to position the view frustum.
uint32_t buffers
The Frame buffer attachments to use.
Definition: compositor.h:53
const lunchbox::Clock * getClock() const
void setQuality(const Frame::Buffer buffer, const float quality)
Set the minimum quality after a full download-compression path.
uint32_t getPixelDataSize(const Frame::Buffer buffer) const
void setAlphaUsage(const bool enabled)
Set alpha data preservation during download and compression.
bool hasPixelData(const Frame::Buffer buffer) const
A structure describing an image assembly task.
Definition: compositor.h:46
Image * newImage(const Frame::Type type, const DrawableConfig &config)
Allocate and add a new image.
Vector2i offset
The offset wrt destination window.
Definition: compositor.h:54
static void assembleImage(const Image *image, const ImageOp &operation)
Assemble an image into the frame buffer.
FrameDataPtr getFrameData()
virtual void applyFrustum() const
Apply the frustum matrix for the current rendering task.
void bindFrameBuffer()
Rebind the current alternate FBO of the channel or window.
void setPixelViewport(const PixelViewport &pvp)
Set the internal pixel viewport of the image.
void finishReadback(const Zoom &zoom, const GLEWContext *glewContext)
Finish an asynchronous readback.
virtual void frameDraw(const uint128_t &frameID)
Draw the scene.
const PixelViewport & getPixelViewport() const
ObjectManager * getObjectManager()
virtual void frameStart(const eq::uint128_t &frameID, const uint32_t frameNumber)
Start rendering a frame.
const std::string & getName() const
Config * getConfig()
lunchbox::RefPtr< FrameData > FrameDataPtr
A reference-counted pointer to an eq::FrameData.
bool writeImages(const std::string &filenameTemplate) const
Write all valid pixel data as separate images.
PixelViewport pvp
The dimensions of the pixel data in pixels.
Definition: pixelData.h:82
void clearPixelData(const Frame::Buffer buffer)
Clear and validate an image buffer.
bool startReadback(const uint32_t buffers, const PixelViewport &pvp, const Zoom &zoom, ObjectManager *glObjects)
Start reading back an image from the frame buffer.
virtual void frameDraw(const eq::uint128_t &frameID)
Draw the scene.
static uint32_t assembleFramesCPU(const Frames &frames, Channel *channel, const bool blendAlpha=false)
Assemble all frames in the given order in a memory buffer using the CPU before assembling the result ...
virtual void resetAssemblyState()
Reset the OpenGL state after an assembly operation.