Ejemplo n.º 1
0
bool Node::_cmdFrameDataTransmit( co::ICommand& cmd )
{
    co::ObjectICommand command( cmd );

    const co::ObjectVersion frameDataVersion =
                                             command.get< co::ObjectVersion >();
    const PixelViewport pvp = command.get< PixelViewport >();
    const Zoom zoom = command.get< Zoom >();
    const uint32_t buffers = command.get< uint32_t >();
    const uint32_t frameNumber = command.get< uint32_t >();
    const bool useAlpha = command.get< bool >();
    const uint8_t* data = reinterpret_cast< const uint8_t* >(
                command.getRemainingBuffer( command.getRemainingBufferSize( )));

    LBLOG( LOG_ASSEMBLY )
        << "received image data for " << frameDataVersion << ", buffers "
        << buffers << " pvp " << pvp << std::endl;

    LBASSERT( pvp.isValid( ));

    FrameDataPtr frameData = getFrameData( frameDataVersion );
    LBASSERT( !frameData->isReady() );

    NodeStatistics event( Statistic::NODE_FRAME_DECOMPRESS, this,
                          frameNumber );

    // Note on the const_cast: since the PixelData structure stores non-const
    // pointers, we have to go non-const at some point, even though we do not
    // modify the data.
    LBCHECK( frameData->addImage( frameDataVersion, pvp, zoom, buffers,
                                  useAlpha, const_cast< uint8_t* >( data )));
    return true;
}
Ejemplo n.º 2
0
void Viewport::applyView( const Viewport& segmentVP, const Viewport& viewVP,
                          const PixelViewport& pvp, const Vector4i& overdraw )
{
    // part of view covered by segment/view channel
    Viewport contribution( segmentVP );
    contribution.intersect( viewVP );
    contribution.transform( viewVP );
        
    // extend by overdraw percentage
    EQASSERT( pvp.hasArea( ));

    const float xDelta(( static_cast< float >( overdraw.x() + pvp.w ) /
                         static_cast< float >( pvp.w ) - 1.0f ) * 
                       contribution.w );
    contribution.x -= xDelta;
    contribution.w += (( static_cast< float >( overdraw.z() + pvp.w ) /
                         static_cast< float >( pvp.w ) - 1.0f ) * 
                       contribution.w ); 
    contribution.w += xDelta;

    const float yDelta(( static_cast< float >( overdraw.y() + pvp.h ) /
                         static_cast< float >( pvp.h ) - 1.0f ) *
                       contribution.h ); 
    contribution.y -= yDelta;
    contribution.h += (( static_cast< float >( overdraw.w() + pvp.h ) /
                         static_cast< float >( pvp.h ) - 1.0f ) *
                       contribution.h ); 
    contribution.h += yDelta;
    
    x = contribution.x + x * contribution.w;
    y = contribution.y + y * contribution.h;
    w *= contribution.w;
    h *= contribution.h;
}
Ejemplo n.º 3
0
void ROIFinder::_updateSubArea( const uint8_t type )
{
    LBASSERT( type <= 16 );

    if( type == 0 )
        return;

    PixelViewport pvp;
    switch( type )
    {
        case 1:  pvp = PixelViewport( _dim.x1,_dim.y2,_dim.w1,_dim.h2 ); break;
        case 2:  pvp = PixelViewport( _dim.x2,_dim.y3,_dim.w2,_dim.h3 ); break;
        case 3:  pvp = PixelViewport( _dim.x3,_dim.y2,_dim.w3,_dim.h2 ); break;
        case 4:  pvp = PixelViewport( _dim.x2,_dim.y1,_dim.w2,_dim.h1 ); break;
        case 5:  pvp = PixelViewport( _dim.x1,_dim.y1,_dim.w1,_dim.h4 ); break;
        case 6:  pvp = PixelViewport( _dim.x1,_dim.y3,_dim.w4,_dim.h3 ); break;
        case 7:  pvp = PixelViewport( _dim.x3,_dim.y2,_dim.w3,_dim.h5 ); break;
        case 8:  pvp = PixelViewport( _dim.x2,_dim.y1,_dim.w5,_dim.h1 ); break;
        case 9:  pvp = PixelViewport( _dim.x1,_dim.y2,_dim.w1,_dim.h5 ); break;
        case 10: pvp = PixelViewport( _dim.x2,_dim.y3,_dim.w5,_dim.h3 ); break;
        case 11: pvp = PixelViewport( _dim.x3,_dim.y1,_dim.w3,_dim.h4 ); break;
        case 12: pvp = PixelViewport( _dim.x1,_dim.y1,_dim.w4,_dim.h1 ); break;
        case 13: pvp = PixelViewport( _dim.x1,_dim.y1,_dim.w1,_dim.h6 ); break;
        case 14: pvp = PixelViewport( _dim.x3,_dim.y1,_dim.w3,_dim.h6 ); break;
        case 15: pvp = PixelViewport( _dim.x1,_dim.y3,_dim.w6,_dim.h3 ); break;
        case 16: pvp = PixelViewport( _dim.x1,_dim.y1,_dim.w6,_dim.h1 ); break;
        default:
            LBUNIMPLEMENTED;
    }

    LBASSERT( pvp.hasArea( ));
    LBASSERT( pvp.x >=0 && pvp.y >=0 && pvp.x+pvp.w <=_w && pvp.y+pvp.h <=_h );

    Area& a = _tmpAreas[type];

    a.pvp = _getObjectPVP( pvp, &_mask[0] );

    a.hole = _emptyFinder.getLargestEmptyArea( a.pvp );

    a.emptySize = pvp.getArea() - a.pvp.getArea() + a.hole.getArea();

#ifndef NDEBUG
    LBASSERT( !a.valid );
    a.valid = true;
#endif
}
void CompoundUpdateOutputVisitor::_generateTiles( TileQueue* queue,
                                                  Compound* compound )
{
    const Vector2i& tileSize = queue->getTileSize();
    const PixelViewport pvp = compound->getInheritPixelViewport();
    if( !pvp.hasArea( ))
        return;

    const Vector2i dim( pvp.w / tileSize.x() + ((pvp.w%tileSize.x()) ? 1 : 0),
                        pvp.h / tileSize.y() + ((pvp.h%tileSize.y()) ? 1 : 0));

    std::vector< Vector2i > tiles;
    tiles.reserve( dim.x() * dim.y() );

    tiles::TILE_STRATEGY strategy;
    strategy( tiles, dim );
    _addTilesToQueue( queue, compound, tiles );
}
Ejemplo n.º 5
0
void LoadEqualizer::_update( Node* node, const Viewport& vp,
                             const Range& range )
{
    if( !node )
        return;

    node->mode = getMode();
    if( node->mode == MODE_2D )
    {
        PixelViewport pvp = getCompound()->getChannel()->getPixelViewport();
        pvp.apply( vp );

        if( pvp.w > pvp.h ) // split along longest axis
            node->mode = MODE_VERTICAL;
        else
            node->mode = MODE_HORIZONTAL;
    }

    if( node->compound )
        _updateLeaf( node );
    else
        _updateNode( node, vp, range );
}
Ejemplo n.º 6
0
void Pipe::_setCGDisplayID( CGDirectDisplayID id )
{
    if( _cgDisplayID == id )
        return;

    _cgDisplayID = id;
    PixelViewport pvp = getPipe()->getPixelViewport();

    if( pvp.isValid( ))
        return;

    if( id )
    {
        const CGRect displayRect = CGDisplayBounds( id );
        pvp.x = int32_t(displayRect.origin.x);
        pvp.y = int32_t(displayRect.origin.y);
        pvp.w = int32_t(displayRect.size.width);
        pvp.h = int32_t(displayRect.size.height);
    }
    else
        pvp.invalidate();

    getPipe()->setPixelViewport( pvp );
}
Ejemplo n.º 7
0
void ROIFinder::_readbackInfo( util::ObjectManager& glObjects )
{
    LBASSERT( glObjects.supportsEqTexture( ));
    LBASSERT( glObjects.supportsEqFrameBufferObject( ));

    PixelViewport pvp = _pvp;
    pvp.apply( Zoom( GRID_SIZE, GRID_SIZE ));
    pvp.w = LB_MIN( pvp.w+pvp.x, _pvpOriginal.w+_pvpOriginal.x ) - pvp.x;
    pvp.h = LB_MIN( pvp.h+pvp.y, _pvpOriginal.h+_pvpOriginal.y ) - pvp.y;

    LBASSERT( pvp.isValid());

    // copy frame buffer to texture
    const void* bufferKey = _getInfoKey( );
    util::Texture* texture =
        glObjects.obtainEqTexture( bufferKey, GL_TEXTURE_RECTANGLE_ARB );

#ifdef EQ_ROI_USE_DEPTH_TEXTURE
    texture->copyFromFrameBuffer( GL_DEPTH_COMPONENT, pvp );
#else
    texture->copyFromFrameBuffer( GL_RGBA, pvp );
#endif

    // draw zoomed quad into FBO
    const void*     fboKey = _getInfoKey( );
    util::FrameBufferObject* fbo = glObjects.getEqFrameBufferObject( fboKey );

    if( fbo )
    {
        LBCHECK( fbo->resize( _pvp.w, _pvp.h ));
    }
    else
    {
        fbo = glObjects.newEqFrameBufferObject( fboKey );
        LBCHECK( fbo->init( _pvp.w, _pvp.h, GL_RGBA32F, 0, 0 ));
    }
    fbo->bind();

    texture->bind();

    // Enable & download depth texture
    glEnable( GL_TEXTURE_RECTANGLE_ARB );

    texture->applyWrap();
    texture->applyZoomFilter( FILTER_LINEAR );

    // Enable shaders
    GLuint program = glObjects.getProgram( shaderRBInfo );
    if( program == util::ObjectManager::INVALID )
    {
        // Create fragment shader which reads depth values from
        // rectangular textures
        const GLuint shader = glObjects.newShader( shaderRBInfo,
                                                        GL_FRAGMENT_SHADER );
        LBASSERT( shader != util::ObjectManager::INVALID );

#ifdef EQ_ROI_USE_DEPTH_TEXTURE
        const GLchar* fShaderPtr = roiFragmentShader_glsl.c_str();
#else
        const GLchar* fShaderPtr = roiFragmentShaderRGB_glsl.c_str();
#endif
        EQ_GL_CALL( glShaderSource( shader, 1, &fShaderPtr, 0 ));
        EQ_GL_CALL( glCompileShader( shader ));

        GLint status;
        glGetShaderiv( shader, GL_COMPILE_STATUS, &status );
        if( !status )
            LBERROR << "Failed to compile fragment shader for ROI finder"
                    << std::endl;

        program = glObjects.newProgram( shaderRBInfo );

        EQ_GL_CALL( glAttachShader( program, shader ));
        EQ_GL_CALL( glLinkProgram( program ));

        glGetProgramiv( program, GL_LINK_STATUS, &status );
        if( !status )
        {
            LBWARN << "Failed to link shader program for ROI finder"
                   << std::endl;
            return;
        }

        // use fragment shader and setup uniforms
        EQ_GL_CALL( glUseProgram( program ));

        GLint param = glGetUniformLocation( program, "texture" );
        glUniform1i( param, 0 );
    }
    else
    {
        // use fragment shader
        EQ_GL_CALL( glUseProgram( program ));
    }

    // Draw Quad
    glDisable( GL_LIGHTING );
    glColor3f( 1.0f, 1.0f, 1.0f );

    glBegin( GL_QUADS );
        glVertex3i(      0,      0, 0 );
        glVertex3i( _pvp.w,      0, 0 );
        glVertex3i( _pvp.w, _pvp.h, 0 );
        glVertex3i(      0, _pvp.h, 0 );
    glEnd();

    // restore state
    glDisable( GL_TEXTURE_RECTANGLE_ARB );
    EQ_GL_CALL( glUseProgram( 0 ));

    fbo->unbind();

    // finish readback of info
    LBASSERT( static_cast<int32_t>(_perBlockInfo.size()) >= _pvp.w*_pvp.h*4 );

    texture = fbo->getColorTextures()[0];
    LBASSERT( texture->getFormat() == GL_RGBA );
    LBASSERT( texture->getType() == GL_FLOAT );
    texture->download( &_perBlockInfo[0] );
}
Ejemplo n.º 8
0
Images FrameData::startReadback( const Frame& frame,
                                 util::ObjectManager& glObjects,
                                 const DrawableConfig& config,
                                 const PixelViewports& regions )
{
    if( _impl->data.buffers == Frame::BUFFER_NONE )
        return Images();

    const Zoom& zoom = frame.getZoom();
    if( !zoom.isValid( ))
    {
        LBWARN << "Invalid zoom factor, skipping frame" << std::endl;
        return Images();
    }

    const eq::PixelViewport& framePVP = getPixelViewport();
    const PixelViewport      absPVP   = framePVP + frame.getOffset();
    if( !absPVP.isValid( ))
        return Images();

    Images images;

    // readback the whole screen when using textures
    if( getType() == eq::Frame::TYPE_TEXTURE )
    {
        Image* image = newImage( getType(), config );
        if( image->startReadback( getBuffers(), absPVP, zoom, glObjects ))
            images.push_back( image );
        image->setOffset( 0, 0 );
        return images;
    }
    //else read only required regions

#if 0
    // TODO: issue #85: move automatic ROI detection to eq::Channel
    PixelViewports regions;
    if( _impl->data.buffers & Frame::BUFFER_DEPTH && zoom == Zoom::NONE )
        regions = _impl->roiFinder->findRegions( _impl->data.buffers, absPVP,
                                                 zoom, frame.getAssemblyStage(),
                                                 frame.getFrameID(), glObjects);
    else
        regions.push_back( absPVP );
#endif

    LBASSERT( getType() == eq::Frame::TYPE_MEMORY );
    const eq::Pixel& pixel = getPixel();

    for( uint32_t i = 0; i < regions.size(); ++i )
    {
        PixelViewport pvp = regions[ i ] + frame.getOffset();
        pvp.intersect( absPVP );
        if( !pvp.hasArea( ))
            continue;

        Image* image = newImage( getType(), config );
        if( image->startReadback( getBuffers(), pvp, zoom, glObjects ))
            images.push_back( image );

        pvp -= frame.getOffset();
        pvp.apply( zoom );
        image->setOffset( (pvp.x - framePVP.x) * pixel.w,
                          (pvp.y - framePVP.y) * pixel.h );
    }
    return images;
}
Ejemplo n.º 9
0
bool ROITracker::useROIFinder( const PixelViewport& pvp,
                               const uint32_t       stage,
                               const uint128_t&     frameID,
                                     uint8_t*&      ticket )
{
    LBASSERT( !_needsUpdate );
    ticket = 0;

    const uint32_t pvpArea = pvp.getArea();
    if( pvpArea < 100 )
        return false;

    if( _lastFrameID != frameID ) // new frame
    {
        stde::hash_map< uint32_t, Stage >* tmp = _prvFrame;
        _prvFrame = _curFrame;
        _curFrame = tmp;
        _curFrame->clear();
        _lastFrameID = frameID;
    }

    _lastStage = stage;

    Stage& curStage = (*_curFrame)[ stage ];

    // check if proper stage is avaliable
    if( _prvFrame->find( stage ) == _prvFrame->end( )) // new stage
    {
        curStage.areas.push_back( Area( pvp ));
        return _returnPositive( ticket );
    }
    //else existing stage, try to find matching area

    const Area*    match     = 0;
          uint32_t bestArea  = 0;
    const Stage&   prvStage  = (*_prvFrame)[ stage ];
    for( uint32_t i = 0; i < prvStage.areas.size(); i++ )
    {
        PixelViewport tmp = prvStage.areas[i].pvp;
        tmp.intersect( pvp );
        const uint32_t area = tmp.getArea();
        if( area > bestArea )
        {
            bestArea = area;
            match    = &prvStage.areas[i];
            if( area == pvpArea ) // full match
                break;
        }
    }

    if( bestArea < pvpArea*2/3 ) // no proper match found, new area
    {
        curStage.areas.push_back( Area( pvp ));
        return _returnPositive( ticket );
    }
    // else good match

    if( match->skip == 0 ) // don't skip frame
    {
        curStage.areas.push_back( Area( pvp, match->lastSkip ));
        return _returnPositive( ticket );
    }
    //else skip frame

    curStage.areas.push_back( Area( pvp, match->lastSkip, match->skip-1 ));
    return false;
}
Ejemplo n.º 10
0
void Config::activateCanvas( Canvas* canvas )
{
    LBASSERT( canvas->isStopped( ));
    LBASSERT( lunchbox::find( getCanvases(), canvas ) != getCanvases().end( ));

    const Layouts& layouts = canvas->getLayouts();
    const Segments& segments = canvas->getSegments();

    for( Layouts::const_iterator i = layouts.begin();
         i != layouts.end(); ++i )
    {
        const Layout* layout = *i;
        if( !layout )
            continue;

        const Views& views = layout->getViews();
        for( Views::const_iterator j = views.begin();
             j != views.end(); ++j )
        {
            View* view = *j;

            for( Segments::const_iterator k = segments.begin();
                 k != segments.end(); ++k )
            {
                Segment* segment = *k;
                Viewport viewport = segment->getViewport();
                viewport.intersect( view->getViewport( ));

                if( !viewport.hasArea( ))
                {
                    LBLOG( LOG_VIEW )
                        << "View " << view->getName() << view->getViewport()
                        << " doesn't intersect " << segment->getName()
                        << segment->getViewport() << std::endl;

                    continue;
                }

                Channel* segmentChannel = segment->getChannel();
                if( !segmentChannel )
                {
                    LBWARN << "Segment " << segment->getName()
                           << " has no output channel" << std::endl;
                    continue;
                }

                if ( findChannel( segment, view ))
                    continue;

                // create and add new channel
                Channel* channel = new Channel( *segmentChannel );
                channel->init(); // not in ctor, virtual method
                channel->setOutput( view, segment );

                //----- compute channel viewport:
                // segment/view intersection in canvas space...
                Viewport contribution = viewport;
                // ... in segment space...
                contribution.transform( segment->getViewport( ));

                // segment output area
                if( segmentChannel->hasFixedViewport( ))
                {
                    Viewport subViewport = segmentChannel->getViewport();
                    LBASSERT( subViewport.isValid( ));
                    if( !subViewport.isValid( ))
                        subViewport = eq::fabric::Viewport::FULL;

                    // ...our part of it
                    subViewport.apply( contribution );
                    channel->setViewport( subViewport );
                    LBLOG( LOG_VIEW )
                        << "View @" << (void*)view << ' ' << view->getViewport()
                        << " intersects " << segment->getName()
                        << segment->getViewport() << " at " << subViewport
                        << " using channel @" << (void*)channel << std::endl;
                }
                else
                {
                    PixelViewport pvp = segmentChannel->getPixelViewport();
                    LBASSERT( pvp.isValid( ));
                    pvp.apply( contribution );
                    channel->setPixelViewport( pvp );
                    LBLOG( LOG_VIEW )
                        << "View @" << (void*)view << ' ' << view->getViewport()
                        << " intersects " << segment->getName()
                        << segment->getViewport() << " at " << pvp
                        << " using channel @" << (void*)channel << std::endl;
                }

                if( channel->getWindow()->isAttached( ))
                    // parent is already registered - register channel as well
                    getServer()->registerObject( channel );
            }
        }
    }
}
Ejemplo n.º 11
0
//---------------------------------------------------------------------------
// WGL init
//---------------------------------------------------------------------------
bool Pipe::configInit()
{
    if ( !_configInitWGLEW() )
        return false;

    PixelViewport pvp = getPipe()->getPixelViewport();
    if( pvp.isValid( ))
        return true;

    // setup pvp
    // ...using gpu affinity API
    HGPUNV hGPU = 0;
    if( !_getGPUHandle( hGPU ))
        return false;

    if( hGPU != 0 )
    {
        GPU_DEVICE gpuDevice;
        gpuDevice.cb = sizeof( gpuDevice );
        const bool found = wglEnumGpuDevicesNV( hGPU, 0, &gpuDevice );
        EQASSERT( found );

        if( gpuDevice.Flags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP )
        {
            const RECT& rect = gpuDevice.rcVirtualScreen;
            pvp.x = rect.left;
            pvp.y = rect.top;
            pvp.w = rect.right  - rect.left;
            pvp.h = rect.bottom - rect.top; 
        }
        else
        {
            pvp.x = 0;
            pvp.y = 0;
            pvp.w = 4096;
            pvp.h = 4096;
        }
    }
    else // ... using Win32 API
    {
        HDC dc = createWGLDisplayDC();

        pvp.x = 0;
        pvp.y = 0;
        if( dc )
        {
            pvp.w = GetDeviceCaps( dc, HORZRES );
            pvp.h = GetDeviceCaps( dc, VERTRES );
            DeleteDC( dc );
        }
        else
        {
            EQWARN << "Can't create display dc query pipe resolution: "
                   << co::base::sysError << std::endl;
            pvp.w = 2048;
            pvp.h = 2048;
        }
    }

    getPipe()->setPixelViewport( pvp );
    EQINFO << "Pipe pixel viewport " << pvp << std::endl;
    return true;
}