diff --git a/qt4/run/qpluginwidget.run b/qt4/run/qpluginwidget.run new file mode 100644 index 000000000..10da43289 --- /dev/null +++ b/qt4/run/qpluginwidget.run @@ -0,0 +1,142 @@ +# +# Build +# + +build { + core + init + drivers/input/ps2 + drivers/pci + drivers/framebuffer + drivers/timer + server/nitpicker + server/loader + server/tar_rom + test/nitpicker + test/qpluginwidget +} + +create_boot_directory + +# +# Generate config +# + +set config { + + + + + + + + + + + + + + + + + } + +append_if [have_spec sdl] config { + + + + + + + } + +append_if [have_spec pci] config { + + + + } + +append_if [have_spec vesa] config { + + + + } + +append_if [have_spec pl11x] config { + + + + } + +append_if [have_spec ps2] config { + + + + } + +append config { + + + + + + + + + + + + + + + + +} + +install_config $config + +# +# Boot modules +# + +exec sh -c "ln -sf ../test/qpluginwidget/test-plugin.tar bin/" + +# generic modules +set boot_modules { + core + init + timer + nitpicker + loader + tar_rom + testnit + test-qpluginwidget + dejavusans.lib.so + freetype.lib.so + ld.lib.so + libc.lib.so + libc_lock_pipe.lib.so + libm.lib.so + libpng.lib.so + jpeg.lib.so + qt_core.lib.so + qt_gui.lib.so + qt_network.lib.so + zlib.lib.so + qnitpickerviewwidget.lib.so + qpluginwidget.lib.so + test-plugin.tar +} + +# platform-specific modules +lappend_if [have_spec linux] boot_modules fb_sdl +lappend_if [have_spec pci] boot_modules pci_drv +lappend_if [have_spec vesa] boot_modules vesa_drv +lappend_if [have_spec ps2] boot_modules ps2_drv +lappend_if [have_spec pl11x] boot_modules pl11x_drv + +build_boot_image $boot_modules + +append qemu_args " -m 128" + +run_genode_until forever diff --git a/qt4/src/lib/qpluginwidget/qpluginwidget.cpp b/qt4/src/lib/qpluginwidget/qpluginwidget.cpp index a0aecb8a9..58ac4a1e0 100644 --- a/qt4/src/lib/qpluginwidget/qpluginwidget.cpp +++ b/qt4/src/lib/qpluginwidget/qpluginwidget.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -19,6 +20,70 @@ QPluginWidget *QPluginWidget::_last = 0; +using namespace Genode; + + +const char *config = " \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ +"; + + +class Signal_wait_thread : public QThread +{ + private: + + Signal_receiver &_signal_receiver; + Timed_semaphore &_timeout_semaphore; + + protected: + + void run() + { + _signal_receiver.wait_for_signal(); + _timeout_semaphore.up(); + } + + public: + + Signal_wait_thread(Signal_receiver &signal_receiver, Timed_semaphore &timeout_semaphore) + : _signal_receiver(signal_receiver), + _timeout_semaphore(timeout_semaphore) { } +}; + + PluginStarter::PluginStarter(QUrl plugin_url, QString &args, int max_width, int max_height) : _plugin_url(plugin_url), @@ -43,22 +108,19 @@ void PluginStarter::_start_plugin(QString &file_name, QByteArray const &file_buf PDBG("file_size_uncompressed = %u", file_size); - size_t ram_quota = Genode::Arg_string::find_arg(_args.constData(), "ram_quota").long_value(0) + file_size; + size_t ram_quota = Arg_string::find_arg(_args.constData(), "ram_quota").long_value(0) + file_size; - if ((long)Genode::env()->ram_session()->avail() - (long)ram_quota < QPluginWidget::RAM_QUOTA) { + if ((long)env()->ram_session()->avail() - (long)ram_quota < QPluginWidget::RAM_QUOTA) { PERR("quota exceeded"); _plugin_loading_state = QUOTA_EXCEEDED_ERROR; return; } - QByteArray ram_quota_string("ram_quota=" + QByteArray::number((unsigned long long) ram_quota)); - QByteArray ds_size_string("ds_size=" + QByteArray::number((unsigned long long)file_size)); - QByteArray plugin_connection_args(ram_quota_string + "," + ds_size_string); - _pc = new Loader::Connection(plugin_connection_args.constData()); + _pc = new Loader::Connection(ram_quota); - Genode::Dataspace_capability ds = _pc->dataspace(); + Dataspace_capability ds = _pc->alloc_rom_module(file_name.toUtf8().constData(), file_size); if (ds.valid()) { - void *ds_addr = Genode::env()->rm_session()->attach(ds); + void *ds_addr = env()->rm_session()->attach(ds); z_stream zs; zs.next_in = (Bytef*)(file_buf.data()); @@ -76,7 +138,7 @@ void PluginStarter::_start_plugin(QString &file_name, QByteArray const &file_buf _plugin_loading_state = INFLATE_ERROR; inflateEnd(&zs); - Genode::env()->rm_session()->detach(ds_addr); + env()->rm_session()->detach(ds_addr); return; } @@ -86,45 +148,60 @@ void PluginStarter::_start_plugin(QString &file_name, QByteArray const &file_buf _plugin_loading_state = INFLATE_ERROR; inflateEnd(&zs); - Genode::env()->rm_session()->detach(ds_addr); + env()->rm_session()->detach(ds_addr); return; } inflateEnd(&zs); - Genode::env()->rm_session()->detach(ds_addr); + env()->rm_session()->detach(ds_addr); + _pc->commit_rom_module(file_name.toUtf8().constData()); } } else { - size_t ram_quota = Genode::Arg_string::find_arg(_args.constData(), "ram_quota").long_value(0); + size_t ram_quota = Arg_string::find_arg(_args.constData(), "ram_quota").long_value(0); - if ((long)Genode::env()->ram_session()->avail() - (long)ram_quota < QPluginWidget::RAM_QUOTA) { + if ((long)env()->ram_session()->avail() - (long)ram_quota < QPluginWidget::RAM_QUOTA) { _plugin_loading_state = QUOTA_EXCEEDED_ERROR; return; } - QByteArray ram_quota_string("ram_quota=" + QByteArray::number((unsigned long long) ram_quota)); - QByteArray ds_size_string("ds_size=" + QByteArray::number((unsigned long long)file_buf.size())); - QByteArray plugin_connection_args(ram_quota_string + "," + ds_size_string); - _pc = new Loader::Connection(plugin_connection_args.constData()); + _pc = new Loader::Connection(ram_quota); - Genode::Dataspace_capability ds = _pc->dataspace(); - if (ds.valid()) { - void *ds_addr = Genode::env()->rm_session()->attach(_pc->dataspace()); - - memcpy(ds_addr, file_buf.constData(), file_buf.size()); - - Genode::env()->rm_session()->detach(ds_addr); + Dataspace_capability plugin_ds = _pc->alloc_rom_module("plugin.tar", file_buf.size()); + if (plugin_ds.valid()) { + void *plugin_ds_addr = env()->rm_session()->attach(plugin_ds); + ::memcpy(plugin_ds_addr, file_buf.constData(), file_buf.size()); + env()->rm_session()->detach(plugin_ds_addr); + _pc->commit_rom_module("plugin.tar"); } } - try { - _pc->start(_args.constData(), _max_width, _max_height, 10000, file_name.toLatin1().constData()); - _plugin_loading_state = LOADED; - } catch (Loader::Session::Rom_access_failed) { - _plugin_loading_state = ROM_CONNECTION_FAILED_EXCEPTION; - } catch (Loader::Session::Plugin_start_timed_out) { - _plugin_loading_state = TIMEOUT_EXCEPTION; + Dataspace_capability config_ds = _pc->alloc_rom_module("config", ::strlen(config) + 1); + if (config_ds.valid()) { + void *config_ds_addr = env()->rm_session()->attach(config_ds); + ::memcpy(config_ds_addr, config, ::strlen(config) + 1); + env()->rm_session()->detach(config_ds_addr); + _pc->commit_rom_module("config"); } + + Signal_receiver sig_rec; + Signal_context sig_ctx; + + _pc->view_ready_sigh(sig_rec.manage(&sig_ctx)); + _pc->constrain_geometry(_max_width, _max_height); + _pc->start("init", "init"); + + Timed_semaphore view_ready_semaphore; + Signal_wait_thread signal_wait_thread(sig_rec, view_ready_semaphore); + signal_wait_thread.start(); + try { + view_ready_semaphore.down(10000); + _plugin_loading_state = LOADED; + } catch (Timeout_exception) { + _plugin_loading_state = TIMEOUT_EXCEPTION; + signal_wait_thread.terminate(); + } + signal_wait_thread.wait(); } @@ -135,19 +212,19 @@ void PluginStarter::run() QString file_name = _plugin_url.path().remove("/"); try { - Genode::Rom_connection rc(file_name.toLatin1().constData()); + Rom_connection rc(file_name.toLatin1().constData()); - Genode::Dataspace_capability rom_ds = rc.dataspace(); + Dataspace_capability rom_ds = rc.dataspace(); - char const *rom_ds_addr = (char const *)Genode::env()->rm_session()->attach(rom_ds); + char const *rom_ds_addr = (char const *)env()->rm_session()->attach(rom_ds); - QByteArray file_buf = QByteArray::fromRawData(rom_ds_addr, Genode::Dataspace_client(rom_ds).size()); + QByteArray file_buf = QByteArray::fromRawData(rom_ds_addr, Dataspace_client(rom_ds).size()); _start_plugin(file_name, file_buf); - Genode::env()->rm_session()->detach(rom_ds_addr); + env()->rm_session()->detach(rom_ds_addr); - } catch (Genode::Rom_connection::Rom_connection_failed) { + } catch (Rom_connection::Rom_connection_failed) { _plugin_loading_state = ROM_CONNECTION_FAILED_EXCEPTION; } @@ -195,7 +272,12 @@ void PluginStarter::networkReplyFinished() Nitpicker::View_capability PluginStarter::plugin_view(int *w, int *h, int *buf_x, int *buf_y) { - return _pc->view(w, h, buf_x, buf_y); + Loader::Session::View_geometry geometry = _pc->view_geometry(); + if (w) *w = geometry.width; + if (h) *h = geometry.height; + if (buf_x) *buf_x = geometry.buf_x; + if (buf_y) *buf_y = geometry.buf_y; + return _pc->view(); } @@ -242,8 +324,6 @@ void QPluginWidget::cleanup() _plugin_starter->exit(); /* wait until the thread has left the run() function */ _plugin_starter->wait(); - /* terminate the Genode thread */ - _plugin_starter->terminate(); /* delete the QThread object */ delete _plugin_starter; _plugin_starter = 0; diff --git a/qt4/src/lib/qt4/src/corelib/thread/qthread_genode.cpp b/qt4/src/lib/qt4/src/corelib/thread/qthread_genode.cpp index 6787e5786..a76fd5a4d 100644 --- a/qt4/src/lib/qt4/src/corelib/thread/qthread_genode.cpp +++ b/qt4/src/lib/qt4/src/corelib/thread/qthread_genode.cpp @@ -341,6 +341,7 @@ void QThread::terminate() d->genode_thread = 0; d->terminated = true; + d->running = false; } } diff --git a/qt4/src/test/qpluginwidget/config.plugin b/qt4/src/test/qpluginwidget/config.plugin new file mode 100644 index 000000000..ec274cfca --- /dev/null +++ b/qt4/src/test/qpluginwidget/config.plugin @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/qt4/src/test/qpluginwidget/main.cpp b/qt4/src/test/qpluginwidget/main.cpp new file mode 100644 index 000000000..27a83914e --- /dev/null +++ b/qt4/src/test/qpluginwidget/main.cpp @@ -0,0 +1,30 @@ +/* + * \brief QPluginWidget test + * \author Christian Prochaska + * \date 2012-04-23 + */ + +/* Qt includes */ +#include +#include +#include + +/* Qoost includes */ +#include + +int main(int argc, char *argv[]) +{ + static QApplication app(argc, argv); + + static Compound_widget w; + + static QString plugin_args("ram_quota=3M"); + static QPluginWidget plugin_widget(&w, QUrl("rom:///test-plugin.tar"), plugin_args, 100, 100); + + w.layout()->addWidget(&plugin_widget); + w.resize(150, 150); + + w.show(); + + return app.exec(); +} diff --git a/qt4/src/test/qpluginwidget/qpluginwidget.pro b/qt4/src/test/qpluginwidget/qpluginwidget.pro new file mode 100644 index 000000000..86868fe21 --- /dev/null +++ b/qt4/src/test/qpluginwidget/qpluginwidget.pro @@ -0,0 +1,4 @@ +TEMPLATE = app +TARGET = test-qpluginwidget +QT = core gui +SOURCES += main.cpp diff --git a/qt4/src/test/qpluginwidget/target.mk b/qt4/src/test/qpluginwidget/target.mk new file mode 100644 index 000000000..df08d51b2 --- /dev/null +++ b/qt4/src/test/qpluginwidget/target.mk @@ -0,0 +1,17 @@ +# identify the qt4 repository by searching for a file that is unique for qt4 +QT4_REP_DIR := $(call select_from_repositories,lib/import/import-qt4.inc) +QT4_REP_DIR := $(realpath $(dir $(QT4_REP_DIR))../..) + +include $(QT4_REP_DIR)/src/app/tmpl/target_defaults.inc + +include $(QT4_REP_DIR)/src/app/tmpl/target_final.inc + +LIBS += qpluginwidget + +$(TARGET): test-plugin.tar + +test-plugin.tar: config.plugin + $(VERBOSE)tar cf $@ -C $(PRG_DIR) config.plugin + +clean: + $(VERBOSE)rm test-plugin.tar