diff --git a/examples/testVideo/CMakeLists.txt b/examples/testVideo/CMakeLists.txt new file mode 100644 index 00000000..8c1258e0 --- /dev/null +++ b/examples/testVideo/CMakeLists.txt @@ -0,0 +1,28 @@ +####################################################################################################################### +# Source files +SET( srcs + libstreamport.cpp + video_buf_pool.cpp + video_ctrl.cpp + video_stream_manager.cpp + video_stream_port.cpp + main.cpp + ) + +####################################################################################################################### +# Headers +SET( headers + libstreamport.h + video_buf_pool.h + video_ctrl.h + video_stream_manager.h + video_stream_port.h + ) + +####################################################################################################################### +# Setup compile info +add_executable(testVideo ${srcs} ${headers}) +set_target_properties(testVideo PROPERTIES FOLDER examples) +target_link_libraries(testVideo omega omegaToolkit) + + diff --git a/examples/testVideo/libstreamport.cpp b/examples/testVideo/libstreamport.cpp new file mode 100644 index 00000000..8f0a12cc --- /dev/null +++ b/examples/testVideo/libstreamport.cpp @@ -0,0 +1,94 @@ +#include + +#include + +#include "libstreamport.h" + +class streamport : public omicron::Thread +{ +public: + streamport() + { + _color = n; + n += 10000; + _w = 1920; + _h = 1080; + int size = _w * _h * 3 / 2; + _buf = new char[ size ]; + memset( _buf, _color, size ); + } + ~streamport() + { + + } + virtual void threadProc() + { + while( !_stop ) + { + if( _handler ) + { + int size = _w * _h * 3 / 2; + memset( _buf, _color++, size ); + _handler->on_video_frame_got( ( unsigned char* )_buf, _w, _h ); + } + + omega::osleep( 16 ); //for 60fps + } + } + + bool start() + { + _stop = false; + omicron::Thread::start(); + return true; + } + bool stop() + { + _stop = true; + omicron::Thread::stop(); + return true; + } + + libstreamport_handler *_handler; + bool _stop; + int _color; + void* _buf; + int _w; + int _h; + + static int n; +}; + +int streamport::n = 0; + +libstreamport::libstreamport() + : sp( NULL ) +{ + sp = new streamport; +} + +libstreamport::libstreamport( libstreamport_handler *_handler, int _output_format ) + : sp( NULL ) +{ + sp = new streamport; + sp->_handler = _handler; +} + +libstreamport::~libstreamport() +{ +} + +void libstreamport::set_prama( libstreamport_handler *_handler, int _output_format ) +{ + sp->_handler = _handler; +} + +bool libstreamport::start_video( ) +{ + return sp->start(); +} + +bool libstreamport::stop_video() +{ + return sp->stop(); +} diff --git a/examples/testVideo/libstreamport.h b/examples/testVideo/libstreamport.h new file mode 100644 index 00000000..9dc0dbd4 --- /dev/null +++ b/examples/testVideo/libstreamport.h @@ -0,0 +1,30 @@ +#pragma once + +#include + +class streamport; + +#define OUTPUT_FMT_YUV 0 +#define OUTPUT_FMT_RGB 1 + +class libstreamport_handler +{ +public: + virtual void on_video_frame_got( unsigned char *buf, int width, int height ) = 0; +}; + +class libstreamport +{ +public: + libstreamport(); + libstreamport( libstreamport_handler *_handler, int _output_format = OUTPUT_FMT_YUV ); + virtual ~libstreamport(); + + void set_prama( libstreamport_handler *_handler, int _output_format = OUTPUT_FMT_YUV ); + + bool start_video( ); + bool stop_video(); + +protected: + streamport *sp; +}; \ No newline at end of file diff --git a/examples/testVideo/main.cpp b/examples/testVideo/main.cpp new file mode 100644 index 00000000..25976727 --- /dev/null +++ b/examples/testVideo/main.cpp @@ -0,0 +1,120 @@ +/********************************************************************************************************************** + * THE OMEGA LIB PROJECT + *--------------------------------------------------------------------------------------------------------------------- + * Copyright 2010 Electronic Visualization Laboratory, University of Illinois at Chicago + * Authors: + * Alessandro Febretti febret@gmail.com + *--------------------------------------------------------------------------------------------------------------------- + * Copyright (c) 2010, Electronic Visualization Laboratory, University of Illinois at Chicago + * All rights reserved. + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions + * and the following disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *--------------------------------------------------------------------------------------------------------------------- + * ohello + * Implements the simplest possible omegalib application. Just a synchronized renderer that performs some + * opengl drawing on one or multiple nodes. + *********************************************************************************************************************/ +#include +#include +#include + +using namespace omega; +using namespace omegaToolkit; +using namespace omegaToolkit::ui; + +#include + +#include + +#include "video_ctrl.h" +#include "video_stream_manager.h" + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class VideoApplication: public EngineModule +{ +public: + VideoApplication(): EngineModule( "VideoApplication" ) {} + virtual void initialize() + { + EngineModule::initialize(); + + omega::Console* console = getEngine()->getConsole(); + console->setDrawFlags( omega::Console::DrawStats ); + + myUiModule = UiModule::createAndInitialize(); + Ref myUi = myUiModule->getUi(); + + int nXOff = 0; + int nScreenW = 3840; + int nScreenH = 800; + + std::vector< int > xx; + std::vector< int > yy; + + int xNum = 6; + int yNum = 4; + int w = nScreenW / xNum; + int h = nScreenH / yNum; + + for( int i = 0; i < xNum; i ++ ) + { + xx.push_back( nScreenW * i / xNum ); + } + for( int i = 0; i < yNum; i ++ ) + { + yy.push_back( nScreenH * i / yNum ); + } + + int nVideoPort = 4602; + const char* ip = "168.168.68.42"; + int n = 0; + for( int i = 0; i < xx.size(); i++ ) + { + for( int j = 0; j < yy.size(); j ++ ) + { + VideoCtrl* v1 = VideoCtrl::create( myUi ); + v1->startVideo( ip, ip, nVideoPort, nVideoPort + 1, 60, 0 ); + v1->setPosition( omega::Vector2f( nXOff + xx[ i ], yy[ j ] ) ); + v1->setSize( omega::Vector2f( w, h ) ); + + nVideoPort += 2; + } + } + } + + void update( const UpdateContext & context ) + { + omicron::Timer timer; + timer.start(); + //update all video streams to next frame + VideoStreamManager::instance()->updateAllStreams(); + + timer.stop(); + fprintf( stderr, "--------------- update : %f\n", timer.getElapsedTimeInMilliSec() ); + //fprintf( stderr, "------------------------------------------\n" ); + } + +private: + // The ui manager + Ref myUiModule; +}; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// ApplicationBase entry point +int main( int argc, char** argv ) +{ + Application app( "testVideo" ); + return omain( app, argc, argv ); +} diff --git a/examples/testVideo/video_buf_pool.cpp b/examples/testVideo/video_buf_pool.cpp new file mode 100644 index 00000000..638e5932 --- /dev/null +++ b/examples/testVideo/video_buf_pool.cpp @@ -0,0 +1,106 @@ +#include "video_buf_pool.h" + +VideoData::VideoData() + : data( NULL ) + , w( 0 ) + , h( 0 ) + , size( 0 ) +{ +} + +VideoData::VideoData( int w, int h, int size ) +{ + this->w = w; + this->h = h; + this->size = size; + this->data = new char[ size ]; +} + +VideoData::~VideoData() +{ + if( data ) + { + delete[] data; + data = NULL; + } +} + +void VideoData::resize( int w, int h, int size ) +{ + if( data ) + { + delete[] data; + data = NULL; + } + + this->w = w; + this->h = h; + this->size = size; + this->data = new char[ size ]; +} + +VideoBufPool::VideoBufPool() + : _maxSize( 0 ) +{ +} + +VideoBufPool::~VideoBufPool() +{ + release(); +} + +bool VideoBufPool::init( int maxSize ) +{ + _maxSize = maxSize; + for( int i = 0; i < maxSize; ++i ) + { + _bufs.push( new VideoData() ); + } + return true; +} + +void VideoBufPool::release() +{ + fast_mutex_autolock autolock( _mutex ); + while( !_bufs.empty() ) + { + VideoData* buf = _bufs.top(); + _bufs.pop(); + delete buf; + } +} + +int VideoBufPool::getMaxSize() +{ + fast_mutex_autolock autolock( _mutex ); + return _maxSize; +} + +int VideoBufPool::getFreeCount() +{ + fast_mutex_autolock autolock( _mutex ); + return _bufs.size(); +} + +VideoData* VideoBufPool::malloc( int w, int h, int size ) +{ + fast_mutex_autolock autolock( _mutex ); + if( _bufs.empty() ) + { + return NULL; + } + VideoData* buf = _bufs.top(); + _bufs.pop(); + + if( buf->size != size ) + { + buf->resize( w, h, size ); + } + return buf; +} + +void VideoBufPool::free( VideoData* buf ) +{ + fast_mutex_autolock autolock( _mutex ); + _bufs.push( buf ); +} diff --git a/examples/testVideo/video_buf_pool.h b/examples/testVideo/video_buf_pool.h new file mode 100644 index 00000000..2f0cec81 --- /dev/null +++ b/examples/testVideo/video_buf_pool.h @@ -0,0 +1,42 @@ +#ifndef __SUYUN_DISPLAY_SYSTEM_RENDER_VIDEO_BUF_POOL_HEADER__ +#define __SUYUN_DISPLAY_SYSTEM_RENDER_VIDEO_BUF_POOL_HEADER__ + +#include + +#include + +struct VideoData +{ + VideoData(); + VideoData( int w, int h, int size ); + ~VideoData(); + void resize( int w, int h, int size ); + char* data; + int w; + int h; + int size; +}; + +class VideoBufPool +{ +public: + VideoBufPool(); + ~VideoBufPool(); + + bool init( int maxSize ); + void release(); + + int getMaxSize(); + int getFreeCount(); + + VideoData* malloc( int w, int h, int size ); + void free( VideoData* buf ); + +private: + std::stack< VideoData* > _bufs; + int _maxSize; + + fast_mutex _mutex; +}; + +#endif diff --git a/examples/testVideo/video_ctrl.cpp b/examples/testVideo/video_ctrl.cpp new file mode 100644 index 00000000..e9a4dab2 --- /dev/null +++ b/examples/testVideo/video_ctrl.cpp @@ -0,0 +1,433 @@ +#include "video_ctrl.h" +#include "video_stream.h" +#include "video_stream_manager.h" + +using namespace omega; +using namespace omegaToolkit::ui; + +VideoCtrl::VideoCtrl( Engine* e ) + : Widget( e ) + , _videoStream( NULL ) + , _subtitleX( 0 ) + , _subtitleY( 0 ) + , _fontSize( 60 ) + , _usePbo( true ) + , _showBorder( true ) + , _borderColor( 1.f, 0.f, 0.f, 1.f ) + , _borderWidth( 5 ) +{ + setShaderName( "ui/widget-label" ); +} + +VideoCtrl::~VideoCtrl( void ) +{ + stopVideo(); +} + +VideoCtrl* VideoCtrl::create( Container* container ) +{ + VideoCtrl* video = new VideoCtrl( Engine::instance() ); + container->addChild( video ); + return video; +} + +Renderable* VideoCtrl::createRenderable() +{ + return new VideoCtrlRenderable( this ); +} + +void VideoCtrl::startVideo( const std::string& realIp, const std::string& ip, + int port, int qosPort, int mediaType, int encrypt ) +{ + if( !_videoStream ) + { + _videoStream = VideoStreamManager::instance()-> + getVideoStream(); + refresh(); + } +} + +void VideoCtrl::stopVideo() +{ + if( _videoStream ) + { + VideoStreamManager::instance()->delVideoStream( _videoStream ); + _videoStream = NULL; + } +} + +bool VideoCtrl::getShowBorder() +{ + return _showBorder; +} + +void VideoCtrl::setShowBorder( bool show ) +{ + _showBorder = show; +} + +void VideoCtrl::setBorder( const omega::Color& borderColor, int width ) +{ + _borderColor = borderColor; + _borderWidth = width; +} + +///////////////////////////////////////////////////////////////////////////////////////////////// + +VideoCtrlRenderable::VideoCtrlRenderable( VideoCtrl* video ) + : WidgetRenderable( video ) + , _video( video ) + , _yuvProgram( 0 ) + , _pboIndex( 0 ) + , _videoSrcW( 0 ) + , _videoSrcH( 0 ) + , _font( NULL ) + , _textureUniform( 0 ) +{ + memset( _textureIds, 0, sizeof( _textureIds ) ); + memset( _pboIds, 0, sizeof( _pboIds ) ); +} + + +VideoCtrlRenderable::~VideoCtrlRenderable( void ) +{ +} + +void VideoCtrlRenderable::dispose() +{ + if( _textureIds[0] != 0 ) + { + glDeleteTextures( 3, _textureIds ); + memset( _textureIds, 0, sizeof( _textureIds ) ); + } + if( _pboIds[ 0 ][ 0 ] != 0 ) + { + glDeleteBuffersARB( 6, ( GLuint* )_pboIds ); + memset( _pboIds, 0, sizeof( _pboIds ) ); + } +} + +void VideoCtrlRenderable::refresh() +{ + WidgetRenderable::refresh(); + //refreshVideo(); + //refreshFont(); + + if( _textureIds[0] != 0 ) + { + glDeleteTextures( 3, _textureIds ); + memset( _textureIds, 0, sizeof( _textureIds ) ); + } + if( _pboIds[ 0 ][ 0 ] != 0 ) + { + glDeleteBuffersARB( 6, ( GLuint* )_pboIds ); + memset( _pboIds, 0, sizeof( _pboIds ) ); + } +} + +void VideoCtrlRenderable::refreshVideo() +{ + VideoData* video_data = _video->_videoStream->getVideoData(); + if( !video_data ) + { + return; + } + + int w = video_data->w; + int h = video_data->h; + + glGenTextures( 3, _textureIds ); + int ww[] = {w, w / 2, w / 2}; + int hh[] = {h, h / 2, h / 2}; + + for( int i = 0; i < 3; ++i ) + { + glBindTexture( GL_TEXTURE_RECTANGLE, _textureIds[i] ); + //glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + //glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); + glTexImage2D( GL_TEXTURE_RECTANGLE, 0, GL_LUMINANCE, ww[ i ], hh[ i ], 0, + GL_LUMINANCE, GL_UNSIGNED_BYTE, 0 ); + } + + if( _video->_usePbo ) + { + glGenBuffersARB( 6, ( GLuint* )_pboIds ); + for( int i = 0; i < 2; ++i ) + { + for( int j = 0; j < 3; ++j ) + { + glBindBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB, _pboIds[i][j] ); + glBufferDataARB( GL_PIXEL_UNPACK_BUFFER_ARB, ww[j] * hh[j], 0, GL_STREAM_DRAW_ARB ); + } + } + glBindBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB, 0 ); + } + + //_yuv_program = getRenderer()-> + // getOrCreateProgram("yuv_video", omicron::String("yuv_video.vert"), "yuv_video.frag"); + const char* YUV_SHADER_SRC = "uniform sampler2DRect Ytex;\r\n" + "uniform sampler2DRect Utex,Vtex;\r\n" + "void main(void)\r\n" + "{\r\n" + "float nx,ny,r,g,b,y,u,v;\r\n" + "nx=gl_TexCoord[0].x;\r\n" + "ny=gl_TexCoord[0].y;\r\n" + "y=texture2DRect(Ytex,vec2(nx,ny)).r;\r\n" + "u=texture2DRect(Utex,vec2(nx/2.0,ny/2.0)).r;\r\n" + "v=texture2DRect(Vtex,vec2(nx/2.0,ny/2.0)).r;\r\n" + "y=1.1643*(y-0.0625);\r\n" + "u=u - 0.5;\r\n" + "v=v - 0.5;\r\n" + "r=y+1.5958*v;\r\n" + "g=y-0.39173*u-0.81290*v;\r\n" + "b=y+2.017*u;\r\n" + "gl_FragColor=vec4(r,g,b,1.0);\r\n" + "}\r\n"; + + if( _yuvProgram == 0 ) + { + _yuvProgram = getRenderer()->getOrCreateProgramFromSource( "yuv_video_frag", "", YUV_SHADER_SRC ); + if( oglError ) + { + _yuvProgram = 0; + return; + } + } + if( _yuvProgram != 0 ) + { + glUseProgram( _yuvProgram ); + int tex = 0; + tex = glGetUniformLocation( _yuvProgram, "Ytex" ); + glUniform1i( tex, 0 ); + tex = glGetUniformLocation( _yuvProgram, "Utex" ); + glUniform1i( tex, 1 ); + tex = glGetUniformLocation( _yuvProgram, "Vtex" ); + glUniform1i( tex, 2 ); + glUseProgram( 0 ); + if( oglError ) + { + return; + } + } +} + +void VideoCtrlRenderable::refreshFont() +{ + if( _video->_subtitle.size() == 0 ) + { + return; + } + + if( _video->_fontFamily != "" ) + { + _font = getRenderer()->getFont( _video->_fontFamily, DrawInterface::FTGLPolygon ); + } + if( _font == NULL ) + { + _font = getRenderer()->getDefaultFont(); + } + _textureUniform = glGetUniformLocation( myShaderProgram, "unif_Texture" ); +} + +void VideoCtrlRenderable::drawContent( const DrawContext& context ) +{ + omega::Vector2f tileOffs( context.tile->offset[ 0 ], context.tile->offset[ 1 ] ); + omega::Rectf vpTilePixel( tileOffs.cast< double >(), + ( tileOffs + context.tile->pixelSize.cast< double >() ).cast< double >() ); + + omega::Rectf vpCtrl( omega::Vector2f( _video->getPosition().x() + 1, _video->getPosition().y() + 1 ), + omega::Vector2f( ( _video->getPosition().x() + _video->getSize().x() - 1 ), + ( _video->getPosition().y() + _video->getSize().y() - 1 ) ) ); + if( !vpTilePixel.intersects( vpCtrl ) ) + { + return; + } + + //fprintf( stderr, "%s %p\n", context.tile->name.c_str(), this ); + // Calling the base WidgetRenderable draw function is not + // required but is useful to draw widget background and borders. + glUseProgram( 0 ); + WidgetRenderable::drawContent( context ); + + //Sleep( 100 ); + renderVideo( context ); + glUseProgram( myShaderProgram ); + renderSubtitle( context ); +} + +void VideoCtrlRenderable::renderVideo( const DrawContext& context ) +{ + VideoStreamPort* vs = _video->_videoStream; + if( !vs ) + { + return; + } + + float display_w = _video->getWidth(); + float display_h = _video->getHeight(); + VideoData* video_data = vs->getVideoData(); + if( video_data ) + { + _videoSrcW = video_data->w; + _videoSrcH = video_data->h; + + char* data = video_data->data; + if( data ) + { + int x = 0, y = 0; + if( _textureIds[0] == 0 ) + { + refreshVideo(); + } + + if( _video->_usePbo ) + { + _pboIndex = ( _pboIndex + 1 ) % 2; + int nextPboIndex = ( _pboIndex + 1 ) % 2; + + glBindTexture( GL_TEXTURE_RECTANGLE_NV, _textureIds[0] ); + glBindBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB, _pboIds[_pboIndex][0] ); + glTexSubImage2D( GL_TEXTURE_RECTANGLE_NV, 0, x, y, + _videoSrcW, _videoSrcH, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0 ); + + glBindTexture( GL_TEXTURE_RECTANGLE_NV, _textureIds[1] ); + glBindBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB, _pboIds[_pboIndex][1] ); + glTexSubImage2D( GL_TEXTURE_RECTANGLE_NV, 0, x / 2, y / 2, + _videoSrcW / 2, _videoSrcH / 2, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0 ); + + glBindTexture( GL_TEXTURE_RECTANGLE_NV, _textureIds[2] ); + glBindBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB, _pboIds[_pboIndex][2] ); + glTexSubImage2D( GL_TEXTURE_RECTANGLE_NV, 0, x / 2, y / 2, + _videoSrcW / 2, _videoSrcH / 2, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0 ); + + const char* dataPtr[] = + { + data, + data + _videoSrcW * _videoSrcH, + data + _videoSrcW * _videoSrcH * 5 / 4 + }; + int dataSize[] = + { + _videoSrcW * _videoSrcH, + _videoSrcW * _videoSrcH / 4, + _videoSrcW * _videoSrcH / 4 + }; + for( int i = 0; i < 3; ++i ) + { + // bind PBO to update pixel values + glBindBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB, _pboIds[nextPboIndex][i] ); + + // map the buffer object into client's memory + // Note that glMapBufferARB() causes sync issue. + // If GPU is working with this buffer, glMapBufferARB() will wait(stall) + // for GPU to finish its job. To avoid waiting (stall), you can call + // first glBufferDataARB() with NULL pointer before glMapBufferARB(). + // If you do that, the previous data in PBO will be discarded and + // glMapBufferARB() returns a new allocated pointer immediately + // even if GPU is still working with the previous data. + glBufferDataARB( GL_PIXEL_UNPACK_BUFFER_ARB, dataSize[i], 0, GL_STREAM_DRAW_ARB ); + GLubyte* ptr = ( GLubyte* )glMapBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB ); + if( ptr ) + { + // update data directly on the mapped buffer + memcpy( ptr, dataPtr[i], dataSize[i] ); + glUnmapBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB ); // release pointer to mapping buffer + } + } + glBindBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB, 0 ); + } + else + { + glEnable( GL_TEXTURE_2D ); + glBindTexture( GL_TEXTURE_RECTANGLE, _textureIds[0] ); + glTexSubImage2D( GL_TEXTURE_RECTANGLE, 0, x, y, _videoSrcW, _videoSrcH, + GL_LUMINANCE, GL_UNSIGNED_BYTE, data ); + + glBindTexture( GL_TEXTURE_RECTANGLE, _textureIds[1] ); + glTexSubImage2D( GL_TEXTURE_RECTANGLE, 0, x / 2, y / 2, _videoSrcW / 2, _videoSrcH / 2, + GL_LUMINANCE, GL_UNSIGNED_BYTE, data + _videoSrcW * _videoSrcH ); + + glBindTexture( GL_TEXTURE_RECTANGLE, _textureIds[2] ); + glTexSubImage2D( GL_TEXTURE_RECTANGLE, 0, x / 2, y / 2, _videoSrcW / 2, _videoSrcH / 2, + GL_LUMINANCE, GL_UNSIGNED_BYTE, data + _videoSrcW * _videoSrcH * 5 / 4 ); + } + } + } + + // video border + if( _textureIds[0] == 0 ) + { + if( _video->_showBorder ) + { + omega::Color& color = _video->_borderColor; + int lineWidth = _video->_borderWidth; + glLineWidth( lineWidth ); + glColor3f( color.getRed(), color.getGreen(), color.getBlue() ); + glBegin( GL_LINE_LOOP ); + glVertex2i( lineWidth, lineWidth ); + glVertex2i( lineWidth, display_h - lineWidth ); + glVertex2i( display_w, display_h - lineWidth ); + glVertex2i( display_w, lineWidth ); + glVertex2i( lineWidth, lineWidth ); + glEnd(); + } + return; + } + + glUseProgram( _yuvProgram ); + + glActiveTexture( GL_TEXTURE0 ); + glEnable( GL_TEXTURE_2D ); + glBindTexture( GL_TEXTURE_RECTANGLE, _textureIds[ 0 ] ); + + glActiveTexture( GL_TEXTURE1 ); + glEnable( GL_TEXTURE_2D ); + glBindTexture( GL_TEXTURE_RECTANGLE, _textureIds[ 1 ] ); + + glActiveTexture( GL_TEXTURE2 ); + glEnable( GL_TEXTURE_2D ); + glBindTexture( GL_TEXTURE_RECTANGLE, _textureIds[ 2 ] ); + + glBegin( GL_QUADS ); + glTexCoord2i( 0, 0 ); + glVertex2i( 0, 0 ); + glTexCoord2i( 0, _videoSrcH ); + glVertex2i( 0, display_h ); + glTexCoord2i( _videoSrcW, _videoSrcH ); + glVertex2i( display_w, display_h ); + glTexCoord2i( _videoSrcW, 0 ); + glVertex2i( display_w, 0 ); + glEnd(); + + glActiveTexture( GL_TEXTURE2 ); + glBindTexture( GL_TEXTURE_RECTANGLE, 0 ); + glDisable( GL_TEXTURE_2D ); + + glActiveTexture( GL_TEXTURE1 ); + glBindTexture( GL_TEXTURE_RECTANGLE, 0 ); + glDisable( GL_TEXTURE_2D ); + + glActiveTexture( GL_TEXTURE0 ); + glBindTexture( GL_TEXTURE_RECTANGLE, 0 ); + glDisable( GL_TEXTURE_2D ); + + glUseProgram( 0 ); +} + +void VideoCtrlRenderable::renderSubtitle( const DrawContext& context ) +{ + if( _video->_subtitle.size() == 0 ) + { + return; + } + + // If not font has been set, use default ui font. + if( !_font ) + { + refreshFont(); + } + + Vector2f text_pos( _video->_subtitleX, _video->_subtitleY ); + getRenderer()->drawWText( _video->_subtitle, _font, text_pos, + Font::HALeft | Font::VATop, _video->_fontColor ); +} diff --git a/examples/testVideo/video_ctrl.h b/examples/testVideo/video_ctrl.h new file mode 100644 index 00000000..66292b37 --- /dev/null +++ b/examples/testVideo/video_ctrl.h @@ -0,0 +1,80 @@ +#ifndef __SUYUN_DISPLAY_SYSTEM_RENDER_VIDEO_CTRL_HEADER__ +#define __SUYUN_DISPLAY_SYSTEM_RENDER_VIDEO_CTRL_HEADER__ + +#include +#include +#include +#include + +class VideoStreamPort; +class VideoCtrl : public omegaToolkit::ui::Widget +{ + friend class VideoCtrlRenderable; +public: + VideoCtrl( omega::Engine* e ); + ~VideoCtrl( void ); + + static VideoCtrl* create( omegaToolkit::ui::Container* container ); + + virtual omega::Renderable* createRenderable(); + + void startVideo( const std::string& realIp, const std::string& ip, + int port, int qosPort, int mediaType, int encrypt ); + void stopVideo(); + + + bool getShowBorder(); + void setShowBorder( bool show ); + + void setBorder( const omega::Color& borderColor, int width ); + +private: + VideoStreamPort* _videoStream; + + std::wstring _subtitle; + int _subtitleX; + int _subtitleY; + omega::Color _fontColor; + int _fontSize; + std::string _fontFamily; + + bool _showBorder; + omega::Color _borderColor; + int _borderWidth; + + bool _usePbo; +}; + +class VideoCtrlRenderable + : public omegaToolkit::ui::WidgetRenderable +{ +public: + VideoCtrlRenderable( VideoCtrl* video ); + ~VideoCtrlRenderable( void ); + + virtual void dispose(); + virtual void refresh(); + virtual void drawContent( const omega::DrawContext& context ); + +private: + void refreshVideo(); + void refreshFont(); + void renderVideo( const omega::DrawContext& context ); + void renderSubtitle( const omega::DrawContext& context ); + +private: + VideoCtrl* _video; + + GLuint _yuvProgram; + GLuint _textureIds[3]; + GLuint _pboIds[2][3]; + int _pboIndex; + + int _videoSrcW; + int _videoSrcH; + + omega::Ref< omega::Font > _font; + GLuint _textureUniform; +}; + +#endif diff --git a/examples/testVideo/video_stream.cpp b/examples/testVideo/video_stream.cpp new file mode 100644 index 00000000..88f1a1cb --- /dev/null +++ b/examples/testVideo/video_stream.cpp @@ -0,0 +1,74 @@ +#include "video_stream.h" + +namespace SUYUN_DISPLAY_SYSTEM +{ +namespace RENDER +{ +VideoStream::VideoStream( void ) + : _videoData( NULL ) +{ + omicron::AutoLock autolock( _videoDataMutex ); + while( _videoDataBuf.size() > 0 ) + { + VideoData* video_data = _videoDataBuf.front(); + _videoDataBuf.pop(); + + delete video_data; + } +} + +VideoStream::~VideoStream( void ) +{ + release(); +} + +bool VideoStream::init() +{ + if( !_pool.init( 10 ) ) + { + return false; + } + + return true; +} + +void VideoStream::release() +{ + omicron::AutoLock autolock( _videoDataMutex ); + while( _videoDataBuf.size() > 0 ) + { + VideoData* video_data = _videoDataBuf.front(); + _videoDataBuf.pop(); + + delete video_data; + } + if( _videoData ) + { + delete _videoData; + _videoData = NULL; + } + _pool.release(); +} + +VideoData* VideoStream::getVideoData() +{ + return _videoData; +} + +void VideoStream::updateFrame() +{ + if( _videoData ) + { + delete _videoData; + _videoData = NULL; + } + omicron::AutoLock lock( _videoDataMutex ); + if( _videoDataBuf.size() == 0 ) + { + return; + } + _videoData = _videoDataBuf.front(); + _videoDataBuf.pop(); +} +} +} diff --git a/examples/testVideo/video_stream.h b/examples/testVideo/video_stream.h new file mode 100644 index 00000000..27906cd2 --- /dev/null +++ b/examples/testVideo/video_stream.h @@ -0,0 +1,50 @@ +#ifndef __SUYUN_DISPLAY_SYSTEM_RENDER_VIDEO_STREAM_HEADER__ +#define __SUYUN_DISPLAY_SYSTEM_RENDER_VIDEO_STREAM_HEADER__ + +#include + +#include +#include + +#include +#include + +#include "video_buf_pool.h" + +namespace SUYUN_DISPLAY_SYSTEM +{ +namespace RENDER +{ +class VideoStream : public omicron::ReferenceType +{ +public: + enum VideoStreamType + { + VIDEO_STREAM_NONE, + VIDEO_STREAM_TERMINAL, + VIDEO_STREAM_PORT, + VIDEO_STREAM_FFMPEG + }; +public: + VideoStream( void ); + virtual ~VideoStream( void ); + + bool init(); + virtual void release(); + + virtual void updateFrame(); + VideoData* getVideoData(); + + virtual VideoStreamType type() const = 0; + +protected: + VideoData* _videoData; + std::queue _videoDataBuf; + omicron::Lock _videoDataMutex; + + VideoBufPool _pool; +}; +} +} + +#endif diff --git a/examples/testVideo/video_stream_manager.cpp b/examples/testVideo/video_stream_manager.cpp new file mode 100644 index 00000000..610c27d7 --- /dev/null +++ b/examples/testVideo/video_stream_manager.cpp @@ -0,0 +1,69 @@ +#include "video_stream_manager.h" + +#include "video_stream_port.h" + +VideoStreamManager* VideoStreamManager::instance() +{ + static VideoStreamManager mgr; + return &mgr; +} + +VideoStreamManager::VideoStreamManager( void ) +{ +} + +VideoStreamManager::~VideoStreamManager( void ) +{ +} + +VideoStreamPort* VideoStreamManager::getVideoStream( ) +{ + fast_mutex_autolock autolock( _mutex ); + VideoStreamPort* vsd = new VideoStreamPort; + vsd->init( ); + _videoStreams.push_back( vsd ); + return vsd; +} + +void VideoStreamManager::delVideoStream( VideoStreamPort* video_stream ) +{ + fast_mutex_autolock autolock( _mutex ); + for( std::list< VideoStreamPort* >::iterator it = _videoStreams.begin(); + it != _videoStreams.end(); ++it ) + { + VideoStreamPort* vs = *it; + if( vs == video_stream ) + { + vs->release(); + delete vs; + _videoStreams.erase( it ); + return; + } + } +} + +void VideoStreamManager::updateAllStreams() +{ + foreach( VideoStreamPort* vs, _videoStreams ) + { + vs->updateFrame(); + } +} + +bool VideoStreamManager::init() +{ + return true; +} + +void VideoStreamManager::release() +{ + fast_mutex_autolock autolock( _mutex ); + for( std::list< VideoStreamPort* >::iterator it = _videoStreams.begin(); + it != _videoStreams.end(); ++it ) + { + VideoStreamPort* vs = *it; + vs->release(); + delete vs; + } + _videoStreams.clear(); +} diff --git a/examples/testVideo/video_stream_manager.h b/examples/testVideo/video_stream_manager.h new file mode 100644 index 00000000..77c0d9dd --- /dev/null +++ b/examples/testVideo/video_stream_manager.h @@ -0,0 +1,34 @@ +#ifndef __SUYUN_DISPLAY_SYSTEM_RENDER_VIDEO_STREAM_MANAGER_HEADER__ +#define __SUYUN_DISPLAY_SYSTEM_RENDER_VIDEO_STREAM_MANAGER_HEADER__ + +#include + +#include +#include + +#include "video_stream_port.h" + +class VideoStreamManager +{ +public: + static VideoStreamManager* instance(); + + bool init(); + void release(); + + ~VideoStreamManager( void ); + + VideoStreamPort* getVideoStream( ); + void delVideoStream( VideoStreamPort* video_stream ); + + void updateAllStreams(); + +private: + VideoStreamManager( void ); + +private: + std::list< VideoStreamPort* > _videoStreams; + fast_mutex _mutex; +}; + +#endif diff --git a/examples/testVideo/video_stream_port.cpp b/examples/testVideo/video_stream_port.cpp new file mode 100644 index 00000000..5ce087d4 --- /dev/null +++ b/examples/testVideo/video_stream_port.cpp @@ -0,0 +1,88 @@ +#include "video_stream_port.h" + +VideoStreamPort::VideoStreamPort( void ) + : _videoData( NULL ) +{ +} + +VideoStreamPort::~VideoStreamPort( void ) +{ +} + +bool VideoStreamPort::init() +{ + if( !_pool.init( 10 ) ) + { + return false; + } + + _videoSrc.set_prama( this, OUTPUT_FMT_YUV ); + + return _videoSrc.start_video(); +} + +void VideoStreamPort::release() +{ + _videoSrc.stop_video(); + + fast_mutex_autolock autolock( _mutex ); + while( _videoDataBuf.size() > 0 ) + { + VideoData* video_data = _videoDataBuf.front(); + _videoDataBuf.pop(); + + delete video_data; + } + if( _videoData ) + { + delete _videoData; + _videoData = NULL; + } + _pool.release(); +} + +void VideoStreamPort::updateFrame() +{ + fast_mutex_autolock autolock( _mutex ); + if( _videoData ) + { + _pool.free( _videoData ); + _videoData = NULL; + } + if( _videoDataBuf.size() == 0 ) + { + return; + } + _videoData = _videoDataBuf.front(); + _videoDataBuf.pop(); +} + +void VideoStreamPort::on_video_frame_got( unsigned char* buf, int w, int h ) +{ + if( _pool.getFreeCount() == 0 ) + { + fast_mutex_autolock autolock( _mutex ); + VideoData* videoData = _videoDataBuf.front(); + _videoDataBuf.pop(); + _pool.free( videoData ); + } + int size = ( int )( w * h * 1.5 ); + VideoData* videoData = _pool.malloc( w, h, size ); + if( !videoData ) + { + //DebugBreak(); + } + else + { + memcpy( videoData->data, buf, size ); + videoData->w = w; + videoData->h = h; + fast_mutex_autolock autolock( _mutex ); + _videoDataBuf.push( videoData ); + } +} + +VideoData* VideoStreamPort::getVideoData() +{ + return _videoData; +} diff --git a/examples/testVideo/video_stream_port.h b/examples/testVideo/video_stream_port.h new file mode 100644 index 00000000..095b41ea --- /dev/null +++ b/examples/testVideo/video_stream_port.h @@ -0,0 +1,34 @@ +#ifndef __SUYUN_DISPLAY_SYSTEM_RENDER_VIDEO_STREAM_PORT_HEADER__ +#define __SUYUN_DISPLAY_SYSTEM_RENDER_VIDEO_STREAM_PORT_HEADER__ + +#include + +#include "libstreamport.h" +#include "video_buf_pool.h" + +class VideoStreamPort + : public libstreamport_handler +{ +public: + VideoStreamPort( void ); + ~VideoStreamPort( void ); + + bool init(); + void release(); + + void updateFrame(); + VideoData* getVideoData(); + + virtual void on_video_frame_got( unsigned char* buf, int w, int h ); + +private: + VideoData* _videoData; + std::queue _videoDataBuf; + fast_mutex _mutex; + + VideoBufPool _pool; + + libstreamport _videoSrc; +}; + +#endif diff --git a/include/omega/AsyncTask.h b/include/omega/AsyncTask.h index cc317c7b..a01e606a 100644 --- a/include/omega/AsyncTask.h +++ b/include/omega/AsyncTask.h @@ -85,8 +85,8 @@ namespace omega { void setCompletionHandler(IAsyncTaskHandler* handler) { myHandler = handler; } IAsyncTaskHandler* setCompletionHandler() { return myHandler; } - void setTaskId(const String& value) {myTaskId = value; } - const String& getTaskId(); + void setTaskId(const String& value) { myTaskId = value; } + const String& getTaskId() { return myTaskId; } bool hasFailed() { return myFailed; } const String& getCompletionMessage() { return myCompletionMessage; } diff --git a/include/omega/Engine.h b/include/omega/Engine.h index b07f2cdd..28ea6b8f 100644 --- a/include/omega/Engine.h +++ b/include/omega/Engine.h @@ -90,7 +90,7 @@ namespace omega { //@{ void addRenderer(Renderer* client); Renderer* getRendererByContextId(int id); - RendererList& getRendererList(); + const RendererList& getRendererList(); void removeRenderPass(const String& renderPassName); //@} @@ -249,7 +249,7 @@ namespace omega { { return SystemManager::instance()->getServiceManager(); } /////////////////////////////////////////////////////////////////////////// - inline RendererList& Engine::getRendererList() + inline const RendererList& Engine::getRendererList() { return myClients; } /////////////////////////////////////////////////////////////////////////// diff --git a/include/omega/Renderable.h b/include/omega/Renderable.h index afcd091e..ee59932a 100644 --- a/include/omega/Renderable.h +++ b/include/omega/Renderable.h @@ -84,7 +84,7 @@ namespace omega { virtual ~RenderableFactory(); virtual Renderable* createRenderable() = 0; virtual void initialize(Engine* srv); - void dispose(); + virtual void dispose(); void refresh(); virtual bool isInitialized(); Renderable* getRenderable(Renderer* client); @@ -95,6 +95,7 @@ namespace omega { private: bool myInitialized; + bool myDisposed; Engine* myServer; List< Ref > myRenderables; }; @@ -117,4 +118,4 @@ namespace omega { }; // namespace omega -#endif \ No newline at end of file +#endif diff --git a/include/omegaToolkit/ui/Container.h b/include/omegaToolkit/ui/Container.h index 291052a6..fbf9ba81 100644 --- a/include/omegaToolkit/ui/Container.h +++ b/include/omegaToolkit/ui/Container.h @@ -79,8 +79,6 @@ namespace omegaToolkit { namespace ui { friend class UiRenderPass; public: enum Layout {LayoutFree, LayoutHorizontal, LayoutVertical, LayoutGridHorizontal, LayoutGridVertical}; - enum HorizontalAlign { AlignRight, AlignLeft, AlignCenter}; - enum VerticalAlign { AlignTop, AlignMiddle, AlignBottom}; static Container* create(Layout layout, Container* parent); @@ -120,10 +118,6 @@ namespace omegaToolkit { namespace ui { //! Sets the padding space between elements within the container. void setMargin(float value); float getMargin(); - HorizontalAlign getHorizontalAlign(); - void setHorizontalAlign(HorizontalAlign value); - VerticalAlign getVerticalAlign(); - void setVerticalAlign(VerticalAlign value); int getGridRows(); int getGridColumns(); void setGridRows(int value); @@ -181,8 +175,6 @@ namespace omegaToolkit { namespace ui { float myMargin; int myGridRows; int myGridColumns; - HorizontalAlign myHorizontalAlign; - VerticalAlign myVerticalAlign; bool myClipping; Container3dSettings my3dSettings; @@ -241,22 +233,6 @@ namespace omegaToolkit { namespace ui { inline void Container::setMargin(float value) { myMargin = value; requestLayoutRefresh(); } - //////////////////////////////////////////////////////////////////////////// - inline Container::HorizontalAlign Container::getHorizontalAlign() - { return myHorizontalAlign; } - - //////////////////////////////////////////////////////////////////////////// - inline void Container::setHorizontalAlign(HorizontalAlign value) - { myHorizontalAlign = value; requestLayoutRefresh();} - - //////////////////////////////////////////////////////////////////////////// - inline Container::VerticalAlign Container::getVerticalAlign() - { return myVerticalAlign; } - - //////////////////////////////////////////////////////////////////////////// - inline void Container::setVerticalAlign(VerticalAlign value) - { myVerticalAlign = value; requestLayoutRefresh();} - //////////////////////////////////////////////////////////////////////////// inline int Container::getGridRows() { return myGridRows; } diff --git a/include/omegaToolkit/ui/Widget.h b/include/omegaToolkit/ui/Widget.h index 074ef5b4..8fff80fe 100644 --- a/include/omegaToolkit/ui/Widget.h +++ b/include/omegaToolkit/ui/Widget.h @@ -56,6 +56,8 @@ namespace omegaToolkit { public: enum Layer { Back, Middle, Front, NumLayers }; enum BlendMode { BlendInherit, BlendNormal, BlendAdditive, BlendDisabled }; + enum HorizontalAlign { AlignRight, AlignLeft, AlignCenter}; + enum VerticalAlign { AlignTop, AlignMiddle, AlignBottom}; static const int MaxWidgets = 16384; // Border style data @@ -257,6 +259,11 @@ namespace omegaToolkit { void setSizeAnchor(const Vector2f& value) { mySizeAnchor = value; } const Vector2f getSizeAnchor() { return mySizeAnchor; } + HorizontalAlign getHorizontalAlign(); + void setHorizontalAlign(HorizontalAlign value); + VerticalAlign getVerticalAlign(); + void setVerticalAlign(VerticalAlign value); + WidgetFactory* getFactory(); //! Debug mode @@ -298,6 +305,8 @@ namespace omegaToolkit { // Menu Widget Sounds void playMenuScrollSound(); + unsigned int getFontAlignFlags(); + protected: omega::Vector2f myPosition; omega::Vector2f mySize; @@ -387,6 +396,9 @@ namespace omegaToolkit { static Dictionary mysWidgets; static fast_mutex mysWidgetsMutex; //mutex for Dictionary above + + HorizontalAlign myHorizontalAlign; + VerticalAlign myVerticalAlign; }; /////////////////////////////////////////////////////////////////////////// @@ -628,12 +640,9 @@ namespace omegaToolkit { { if(myContainer != NULL) { - if(myContainer != NULL) - { - ((Widget*)myContainer)->setPosition( - ((Widget*)myContainer)->getPosition()[dimension] + - value - myPosition[dimension], dimension); - } + ((Widget*)myContainer)->setPosition( + ((Widget*)myContainer)->getPosition()[dimension] + + value - myPosition[dimension], dimension); } } else @@ -650,6 +659,22 @@ namespace omegaToolkit { refresh(); } + //////////////////////////////////////////////////////////////////////////// + inline Widget::HorizontalAlign Widget::getHorizontalAlign() + { return myHorizontalAlign; } + + //////////////////////////////////////////////////////////////////////////// + inline void Widget::setHorizontalAlign(HorizontalAlign value) + { myHorizontalAlign = value; requestLayoutRefresh();} + + //////////////////////////////////////////////////////////////////////////// + inline Widget::VerticalAlign Widget::getVerticalAlign() + { return myVerticalAlign; } + + //////////////////////////////////////////////////////////////////////////// + inline void Widget::setVerticalAlign(VerticalAlign value) + { myVerticalAlign = value; requestLayoutRefresh();} + /////////////////////////////////////////////////////////////////////////// // NOTE: Widget::getSource is only used by UiScriptCommand. See if there is a way to get rid of this. template diff --git a/omicron b/omicron index 80dcf3cc..dd14cd69 160000 --- a/omicron +++ b/omicron @@ -1 +1 @@ -Subproject commit 80dcf3ccafdf01b459b7b70daea3aa9f14261949 +Subproject commit dd14cd696f2aa33d860e34fbd5fdcd4ff2846a44 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bce78b87..bbd7ec6a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -102,6 +102,7 @@ if(OMEGA_BUILD_EXAMPLES) add_subdirectory(${CMAKE_SOURCE_DIR}/examples/omegaSound ${CMAKE_BINARY_DIR}/examples/omegaSound) add_subdirectory(${CMAKE_SOURCE_DIR}/examples/ohelloView ${CMAKE_BINARY_DIR}/examples/ohelloView) add_subdirectory(${CMAKE_SOURCE_DIR}/examples/text2texture ${CMAKE_BINARY_DIR}/examples/text2texture) + add_subdirectory(${CMAKE_SOURCE_DIR}/examples/testVideo ${CMAKE_BINARY_DIR}/examples/testVideo) endif() # Add the omegaToolkit library diff --git a/src/omega/Renderable.cpp b/src/omega/Renderable.cpp index c35cf02d..257634b2 100644 --- a/src/omega/Renderable.cpp +++ b/src/omega/Renderable.cpp @@ -79,6 +79,7 @@ DrawInterface* Renderable::getRenderer() /////////////////////////////////////////////////////////////////////////////////////////////////// RenderableFactory::RenderableFactory(): myInitialized(false), + myDisposed(false), myServer(NULL) { } @@ -102,6 +103,10 @@ Renderable* RenderableFactory::addRenderable(Renderer* cli) /////////////////////////////////////////////////////////////////////////////////////////////////// void RenderableFactory::initialize(Engine* srv) { + if(myDisposed) + { + return; + } if(!myInitialized) { //ofmsg("Initializing renderable factory: %1%", %toString()); @@ -121,6 +126,7 @@ void RenderableFactory::initialize(Engine* srv) /////////////////////////////////////////////////////////////////////////////////////////////////// void RenderableFactory::dispose() { + myDisposed = true; if(myInitialized || myRenderables.size() > 0) { //ofmsg("Disposing renderable factory: %1%", %toString()); diff --git a/src/omega/eqinternal/WindowImpl.cpp b/src/omega/eqinternal/WindowImpl.cpp index 5fa1b57f..e7d68075 100644 --- a/src/omega/eqinternal/WindowImpl.cpp +++ b/src/omega/eqinternal/WindowImpl.cpp @@ -72,6 +72,9 @@ bool WindowImpl::configInit(const uint128_t& initID) myTile = ds->getDisplayConfig().tiles[name]; } + // Serialize window init execution since we are tinkering with x cursors on linux inside there. + sInitLock.lock(); + ApplicationBase* app = SystemManager::instance()->getApplication(); if(app) { @@ -79,10 +82,6 @@ bool WindowImpl::configInit(const uint128_t& initID) myRenderer->setGpuContext(myPipe->getGpuContext()); myRenderer->initialize(); } - else return false; - - // Serialize window init execution since we are tinkering with x cursors on linux inside there. - sInitLock.lock(); bool res = Window::configInit(initID); sInitLock.unlock(); return res; diff --git a/src/omega/omegaPythonApi.cpp b/src/omega/omegaPythonApi.cpp index 3cb276ee..9164a466 100644 --- a/src/omega/omegaPythonApi.cpp +++ b/src/omega/omegaPythonApi.cpp @@ -1180,8 +1180,10 @@ BOOST_PYTHON_MODULE(omega) PYAPI_METHOD(Event, isProcessed) PYAPI_METHOD(Event, setProcessed) PYAPI_GETTER(Event, getPosition) - PYAPI_GETTER(Event, getOrientation) - PYAPI_GETTER(Event, getExtraDataInt) + PYAPI_GETTER(Event, getOrientation) + PYAPI_GETTER(Event, getExtraDataInt) + PYAPI_GETTER(Event, getExtraDataString) + PYAPI_GETTER(Event, getExtraDataString) ; PYAPI_ENUM(Node::TransformSpace, Space) diff --git a/src/omegaToolkit/UiRenderPass.cpp b/src/omegaToolkit/UiRenderPass.cpp index 6dd85fdf..f1f06393 100644 --- a/src/omegaToolkit/UiRenderPass.cpp +++ b/src/omegaToolkit/UiRenderPass.cpp @@ -57,7 +57,7 @@ UiRenderPass::UiRenderPass(Renderer* client, const String& name): /////////////////////////////////////////////////////////////////////////////////////////////////// void UiRenderPass::render(Renderer* client, const DrawContext& context) { - sLock.lock(); + //sLock.lock(); myDrawTimeStat->startTiming(); if(context.task == DrawContext::SceneDrawTask) @@ -109,5 +109,5 @@ void UiRenderPass::render(Renderer* client, const DrawContext& context) } myDrawTimeStat->stopTiming(); - sLock.unlock(); + //sLock.unlock(); } diff --git a/src/omegaToolkit/omegaToolkitPythonApi.cpp b/src/omegaToolkit/omegaToolkitPythonApi.cpp index 03600154..71d3e252 100644 --- a/src/omegaToolkit/omegaToolkitPythonApi.cpp +++ b/src/omegaToolkit/omegaToolkitPythonApi.cpp @@ -105,17 +105,17 @@ BOOST_PYTHON_MODULE(omegaToolkit) ; // Vertical Align - PYAPI_ENUM(Container::VerticalAlign, VAlign) - PYAPI_ENUM_VALUE(Container, AlignTop) - PYAPI_ENUM_VALUE(Container, AlignMiddle) - PYAPI_ENUM_VALUE(Container, AlignBottom) + PYAPI_ENUM(Widget::VerticalAlign, VAlign) + PYAPI_ENUM_VALUE(Widget, AlignTop) + PYAPI_ENUM_VALUE(Widget, AlignMiddle) + PYAPI_ENUM_VALUE(Widget, AlignBottom) ; // Horizontal Align - PYAPI_ENUM(Container::HorizontalAlign, HAlign) - PYAPI_ENUM_VALUE(Container, AlignLeft) - PYAPI_ENUM_VALUE(Container, AlignCenter) - PYAPI_ENUM_VALUE(Container, AlignRight) + PYAPI_ENUM(Widget::HorizontalAlign, HAlign) + PYAPI_ENUM_VALUE(Widget, AlignLeft) + PYAPI_ENUM_VALUE(Widget, AlignCenter) + PYAPI_ENUM_VALUE(Widget, AlignRight) ; PYAPI_BASE_CLASS(ToolkitUtils) @@ -202,6 +202,7 @@ BOOST_PYTHON_MODULE(omegaToolkit) PYAPI_REF_GETTER(UiModule, destroyExtendedUi) PYAPI_METHOD(UiModule, setCullingEnabled) PYAPI_METHOD(UiModule, isCullingEnabled) + PYAPI_METHOD(UiModule, activateWidget) ; // WidgetFactory @@ -281,6 +282,10 @@ BOOST_PYTHON_MODULE(omegaToolkit) PYAPI_REF_GETTER(Widget, getHorizontalPrevWidget) PYAPI_REF_GETTER(Widget, getVerticalNextWidget) PYAPI_REF_GETTER(Widget, getVerticalPrevWidget) + PYAPI_METHOD(Widget, setHorizontalAlign) + PYAPI_METHOD(Widget, getHorizontalAlign) + PYAPI_METHOD(Widget, setVerticalAlign) + PYAPI_METHOD(Widget, getVerticalAlign) ; // Container @@ -304,10 +309,6 @@ BOOST_PYTHON_MODULE(omegaToolkit) PYAPI_METHOD(Container, setPadding) PYAPI_METHOD(Container, getMargin) PYAPI_METHOD(Container, setMargin) - PYAPI_METHOD(Container, setHorizontalAlign) - PYAPI_METHOD(Container, getHorizontalAlign) - PYAPI_METHOD(Container, setVerticalAlign) - PYAPI_METHOD(Container, getVerticalAlign) PYAPI_METHOD(Container, setGridRows) PYAPI_METHOD(Container, getGridRows) PYAPI_METHOD(Container, setGridColumns) @@ -390,4 +391,4 @@ void OTK_API omegaToolkitPythonApiInit() } } -#endif \ No newline at end of file +#endif diff --git a/src/omegaToolkit/ui/Container.cpp b/src/omegaToolkit/ui/Container.cpp index 95d1beca..1803b1de 100644 --- a/src/omegaToolkit/ui/Container.cpp +++ b/src/omegaToolkit/ui/Container.cpp @@ -58,8 +58,6 @@ Container::Container(Engine* server): Widget(server), myPadding(5), myMargin(5), - myHorizontalAlign(AlignCenter), - myVerticalAlign(AlignMiddle), myGridRows(1), myGridColumns(1), myClipping(false), diff --git a/src/omegaToolkit/ui/TextBox.cpp b/src/omegaToolkit/ui/TextBox.cpp index f772c1aa..3188285b 100644 --- a/src/omegaToolkit/ui/TextBox.cpp +++ b/src/omegaToolkit/ui/TextBox.cpp @@ -84,7 +84,7 @@ void TextBox::updateSize() if(myFont.size() == 0) { myFont = Engine::instance()->getDefaultFont().filename + " " + - boost::lexical_cast(Engine::instance()->getDefaultFont().size); + boost::lexical_cast(getHeight()); } Vector2f size = Font::getTextSize("A", myFont); size[1] = size[1] + myAutosizeVerticalPadding; diff --git a/src/omegaToolkit/ui/Widget.cpp b/src/omegaToolkit/ui/Widget.cpp index 5f51646d..6ad50254 100644 --- a/src/omegaToolkit/ui/Widget.cpp +++ b/src/omegaToolkit/ui/Widget.cpp @@ -88,7 +88,9 @@ Widget::Widget(Engine* server): myPinned(false), myShaderEnabled(true), mySizeAnchorEnabled(false), - mySizeAnchor(Vector2f::Zero()) + mySizeAnchor(Vector2f::Zero()), + myHorizontalAlign(AlignCenter), + myVerticalAlign(AlignMiddle) { myId = mysNameGenerator.getNext(); myName = mysNameGenerator.generate(); @@ -614,6 +616,25 @@ bool Widget::isIn3DContainer() return myContainer->isIn3DContainer(); } +/////////////////////////////////////////////////////////////////////////////// +unsigned int Widget::getFontAlignFlags() +{ + unsigned int alignFlags = 0; + switch(myHorizontalAlign) + { + case AlignRight: alignFlags |= Font::HARight; break; + case AlignLeft: alignFlags |= Font::HALeft; break; + case AlignCenter: alignFlags |= Font::HACenter; break; + } + switch(myVerticalAlign) + { + case AlignTop: alignFlags |= Font::VATop; break; + case AlignBottom: alignFlags |= Font::VABottom; break; + case AlignMiddle: alignFlags |= Font::VAMiddle; break; + } + return alignFlags; +} + /////////////////////////////////////////////////////////////////////////////// void WidgetRenderable::refresh() {