void Window::setXDrawable( XID drawable ) { if( _xDrawable == drawable ) return; if( _xDrawable ) exitEventHandler(); _xDrawable = drawable; if( !drawable ) return; initEventHandler(); // query pixel viewport of window EQASSERT( _xDisplay ); switch( getIAttribute( eq::Window::IATTR_HINT_DRAWABLE )) { case PBUFFER: { unsigned width = 0; unsigned height = 0; glXQueryDrawable( _xDisplay, drawable, GLX_WIDTH, &width ); glXQueryDrawable( _xDisplay, drawable, GLX_HEIGHT, &height ); getWindow()->setPixelViewport( PixelViewport( 0, 0, int32_t( width ), int32_t( height ))); break; } case WINDOW: { XWindowAttributes wa; XGetWindowAttributes( _xDisplay, drawable, &wa ); // position is relative to parent: translate to absolute coords ::Window root, parent, *children; unsigned nChildren; XQueryTree( _xDisplay, drawable, &root, &parent, &children, &nChildren ); if( children != 0 ) XFree( children ); int x,y; ::Window childReturn; XTranslateCoordinates( _xDisplay, parent, root, wa.x, wa.y, &x, &y, &childReturn ); getWindow()->setPixelViewport( PixelViewport( x, y, wa.width, wa.height )); break; } default: EQUNIMPLEMENTED; case FBO: EQASSERT( getWindow()->getPixelViewport().hasArea( )); } }
void ROIFinder::_dumpDebug( const GLEWContext* gl, const uint32_t stage ) { static uint32_t counter = 0; std::ostringstream ss; ss << "_img_" << ++counter << "_" << stage; _tmpImg.reset(); _tmpImg.setPixelViewport( PixelViewport( 0, 0, _wb, _hb )); _tmpImg.allocDownloader( Frame::BUFFER_COLOR, EQ_COMPRESSOR_TRANSFER_RGBA_TO_BGR, gl ); _tmpImg.validatePixelData( Frame::BUFFER_COLOR ); uint8_t* dst = _tmpImg.getPixelPointer( Frame::BUFFER_COLOR ); uint8_t* src1 = &_mask[0]; uint8_t* src2 = &_tmpMask[0]; memset( dst, 0, _wbhb*3 ); for( int32_t y = 0; y < _hb; y++ ) for( int32_t x = 0; x < _wb; x++ ) { dst[0] = *src1++; dst[1] = *src2++; dst += 3; } LBWARN << "Dumping ROI image: " << ss.str( ) << std::endl; _tmpImg.writeImages( ss.str( )); }
void ROIFinder::_findAreas( PixelViewports& resultPVPs ) { LBASSERT( _areasToCheck.empty() ); Area area( PixelViewport( 0, 0, _w, _h )); area.pvp = _getObjectPVP( area.pvp, &_mask[0] ); if( area.pvp.w <= 0 || area.pvp.h <= 0 ) return; area.hole = _emptyFinder.getLargestEmptyArea( area.pvp ); if( area.hole.getArea() == 0 ) resultPVPs.push_back( area.pvp ); else _areasToCheck.push_back( area ); // try to split areas while( !_areasToCheck.empty() ) { Area curArea = _areasToCheck.back(); _areasToCheck.pop_back(); uint8_t n = _splitArea( curArea ); LBASSERT( n >= 2 && n <= 4 ); for( uint8_t i = 0; i < n; i++ ) { LBASSERT( _finalAreas[i].valid ); LBASSERT( _finalAreas[i].pvp.hasArea( )); if( _finalAreas[i].hole.getArea() == 0 ) resultPVPs.push_back( _finalAreas[i].pvp ); else _areasToCheck.push_back( _finalAreas[i] ); } } // correct position and sizes for( uint32_t i = 0; i < resultPVPs.size(); i++ ) { #ifndef NDEBUG // fill temporary array with found regions to // dump it later in _dumpDebug _fillWithColor( resultPVPs[i], &_tmpMask[0], uint8_t( 255 - i*200/resultPVPs.size( ))); #endif PixelViewport& pvp = resultPVPs[i]; pvp.x += _pvp.x; pvp.y += _pvp.y; pvp.apply( Zoom( GRID_SIZE, GRID_SIZE )); } }
PixelViewport ROIFinder::_getObjectPVP( const PixelViewport& pvp, const uint8_t* src ) { LBASSERT( pvp.x >= 0 && pvp.x+pvp.w <= _wb && pvp.y >= 0 && pvp.y+pvp.h <= _hb ); // Calculate per-pixel histograms const uint8_t* s = src + pvp.y*_wb + pvp.x; memset( _histX, 0, pvp.w ); memset( _histY, 0, pvp.h ); for( int32_t y = 0; y < pvp.h; y++ ) { for( int32_t x = 0; x < pvp.w; x++ ) { const uint8_t val = s[ x ] & 1; _histX[ x ] += val; _histY[ y ] += val; } s += _wb; } // Find AABB based on X and Y axis historgams int32_t xMin = pvp.w; for( int32_t x = 0; x < pvp.w; x++ ) if( _histX[x] != 0 ) { xMin = x; break; } int32_t xMax = 0; for( int32_t x = pvp.w-1; x >= 0; x-- ) if( _histX[x] != 0 ) { xMax = x; break; } if( xMax < xMin ) return PixelViewport( pvp.x, pvp.y, 0, 0 ); int32_t yMin = pvp.h; for( int32_t y = 0; y < pvp.h; y++ ) if( _histY[y] != 0 ) { yMin = y; break; } int32_t yMax = 0; for( int32_t y = pvp.h-1; y >= 0; y-- ) if( _histY[y] != 0 ) { yMax = y; break; } if( yMax < yMin ) return PixelViewport( pvp.x, pvp.y, 0, 0 ); return PixelViewport( pvp.x+xMin, pvp.y+yMin, xMax-xMin+1, yMax-yMin+1 ); }
ROIFinder::ROIFinder() { _tmpAreas[0].pvp = PixelViewport( 0, 0, 0, 0 ); _tmpAreas[0].hole = PixelViewport( 0, 0, 0, 0 ); _tmpAreas[0].emptySize = 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 }
bool Window::processEvent( const Event& event ) { // see comment in _updateEvent _updateEvent( const_cast< Event& >( event )); switch( event.type ) { case Event::WINDOW_HIDE: setPixelViewport( PixelViewport( 0, 0, 0, 0 )); break; case Event::WINDOW_SHOW: case Event::WINDOW_RESIZE: setPixelViewport( PixelViewport( event.resize.x, event.resize.y, event.resize.w, event.resize.h )); break; case Event::KEY_PRESS: case Event::KEY_RELEASE: if( event.key.key == KC_VOID ) return true; // ignore // else fall through case Event::WINDOW_EXPOSE: case Event::WINDOW_CLOSE: case Event::STATISTIC: case Event::MAGELLAN_AXIS: case Event::MAGELLAN_BUTTON: break; case Event::WINDOW_POINTER_GRAB: _grabbedChannels = _getEventChannels( event.pointer ); break; case Event::WINDOW_POINTER_UNGRAB: _grabbedChannels.clear(); break; case Event::WINDOW_POINTER_MOTION: case Event::WINDOW_POINTER_BUTTON_PRESS: case Event::WINDOW_POINTER_BUTTON_RELEASE: case Event::WINDOW_POINTER_WHEEL: { const Channels& channels = _getEventChannels( event.pointer ); for( Channels::const_iterator i = channels.begin(); i != channels.end(); ++i ) { Channel* channel = *i; Event channelEvent = event; switch( event.type ) { case Event::WINDOW_POINTER_MOTION: channelEvent.type = Event::CHANNEL_POINTER_MOTION; break; case Event::WINDOW_POINTER_BUTTON_PRESS: channelEvent.type = Event::CHANNEL_POINTER_BUTTON_PRESS; break; case Event::WINDOW_POINTER_BUTTON_RELEASE: channelEvent.type = Event::CHANNEL_POINTER_BUTTON_RELEASE; break; case Event::WINDOW_POINTER_WHEEL: channelEvent.type = Event::CHANNEL_POINTER_WHEEL; break; default: LBWARN << "Unhandled window event of type " << event.type << std::endl; LBUNIMPLEMENTED; } // convert y to GL notation (Channel PVP uses GL coordinates) const PixelViewport& pvp = getPixelViewport(); const int32_t y = pvp.h - event.pointer.y; const PixelViewport& channelPVP = channel->getNativePixelViewport(); channelEvent.originator = channel->getID(); channelEvent.serial = channel->getSerial(); channelEvent.pointer.x -= channelPVP.x; channelEvent.pointer.y = channelPVP.h - y + channelPVP.y; channel->processEvent( channelEvent ); } break; } case Event::WINDOW_SCREENSAVER: switch( getIAttribute( WindowSettings::IATTR_HINT_SCREENSAVER )) { case OFF: return true; // screen saver stays inactive case ON: return false; // screen saver becomes active default: // AUTO if( getDrawableConfig().doublebuffered && getIAttribute( WindowSettings::IATTR_HINT_DRAWABLE ) == WINDOW ) { return true; // screen saver stays inactive } return false; } case Event::UNKNOWN: // unknown window-system native event, which was not handled return false; default: LBWARN << "Unhandled window event of type " << event.type << std::endl; LBUNIMPLEMENTED; } Config* config = getConfig(); ConfigEvent configEvent; configEvent.data = event; config->sendEvent( configEvent ); return true; }
void Window::setXDrawable( XID drawable ) { LBASSERT( _impl->xDisplay ); if( _impl->xDrawable == drawable ) return; if( _impl->xDrawable ) exitEventHandler(); _impl->xDrawable = drawable; if( !drawable ) return; const int32_t drawableType = getIAttribute( IATTR_HINT_DRAWABLE ); if( drawableType != OFF ) initEventHandler(); // query pixel viewport of window switch( drawableType ) { case PBUFFER: { unsigned width = 0; unsigned height = 0; glXQueryDrawable( _impl->xDisplay, drawable, GLX_WIDTH, &width ); glXQueryDrawable( _impl->xDisplay, drawable, GLX_HEIGHT, &height ); setPixelViewport( PixelViewport( 0, 0, int32_t( width ), int32_t( height ))); break; } case WINDOW: case AUTO: case UNDEFINED: { XWindowAttributes wa; XGetWindowAttributes( _impl->xDisplay, drawable, &wa ); // position is relative to parent: translate to absolute coords ::Window root, parent, *children; unsigned nChildren; XQueryTree( _impl->xDisplay, drawable, &root, &parent, &children, &nChildren ); if( children != 0 ) XFree( children ); int x,y; ::Window childReturn; XTranslateCoordinates( _impl->xDisplay, parent, root, wa.x, wa.y, &x, &y, &childReturn ); setPixelViewport( PixelViewport( x, y, wa.width, wa.height )); break; } default: LBERROR << "Unknown drawable type " << drawableType << std::endl; LBUNIMPLEMENTED; case OFF: case FBO: LBASSERT( getPixelViewport().hasArea( )); } }