void main_thread( AppData& app_data, CommonData& common, const std::string& screen_name ) { #ifdef CLOUD_TRACE_USE_NV_copy_image x11::Display display(screen_name.empty()?nullptr:screen_name.c_str()); #else const x11::Display& display = common.display; (void)screen_name; #endif static int visual_attribs[] = { GLX_DRAWABLE_TYPE , GLX_PIXMAP_BIT, GLX_RENDER_TYPE , GLX_RGBA_BIT, GLX_X_VISUAL_TYPE , GLX_TRUE_COLOR, GLX_RED_SIZE , 8, GLX_GREEN_SIZE , 8, GLX_BLUE_SIZE , 8, GLX_ALPHA_SIZE , 8, None }; glx::FBConfig fbc = glx::FBConfigs( display, visual_attribs ).FindBest(display); x11::VisualInfo vi(display, fbc); x11::Pixmap xpm(display, vi, 8, 8); glx::Pixmap gpm(display, vi, xpm); #ifdef CLOUD_TRACE_USE_NV_copy_image glx::Context context(display, fbc, 3, 3); #else glx::Context context(display, fbc, common.context, 3, 3); #endif context.MakeCurrent(gpm); common.thread_ready.Signal(); common.master_ready.Wait(); if(!common.Done()) { try { thread_loop(app_data, common, display, context); } catch(...) { common.PushError(std::current_exception()); } } context.Release(display); }
void example_thread_main(ExampleThreadData& data) { const ExampleThreadData::Common& common = data.common(); const x11::ScreenNames& sn = common.screen_names; // pick one of the available display screens // for this thread std::size_t disp_idx = data.thread_index; if(sn.size() > 1) ++disp_idx; disp_idx %= sn.size(); // open the picked display x11::Display display(sn[disp_idx].c_str()); // initialize the pixelmaps and the sharing context x11::Pixmap xpm(display, common.vi, 8, 8); glx::Pixmap gpm(display, common.vi, xpm); glx::Context ctx(display, common.fbc, common.ctx, 3, 3); ctx.MakeCurrent(gpm); // signal that the context is created common.thread_ready.Signal(); // wait for the example to be created // in the main thread common.master_ready.Wait(); // if something failed - quit if(common.failure) { common.thread_ready.Signal(); return; } else { try { assert(common.example); // call makeExampleThread std::unique_ptr<ExampleThread> example_thread( makeExampleThread( *common.example, data.thread_index, common.example_params ) ); data.example_thread = example_thread.get(); // signal that it is created common.thread_ready.Signal(); // wait for the main thread common.master_ready.Wait(); // if something failed - quit if(common.failure) return; // start rendering while(!common.done && !common.failure) { example_thread->Render(common.clock); glFlush(); } data.example_thread = nullptr; } catch(...) { data.example_thread = nullptr; throw; } } ctx.Release(display); }
void BlockUpdater:: processUpdates(bool isMainThread) { if (!isMainThread) { /** * MergerTexture needs to prepare the block when it is about to be rendered. * Which is a tad late and requires a new FBO and then a swap back to the main FBO. * * Then after a glFlush the update thread can write to the block, but not before * the glFlush as the merged texture might not be ready. updater_->processUpdates * should check this and put the update on hold until showNewTexture has been called, * indicating that a new frame has begun an thus that there has been a glFlush since * MergerTexture. */ EXCEPTION_ASSERTX(false, "Painting on blocks from the update thread is not implemented"); } list<pair<pBlock, DrawFunc>> q; queue_->swap(q); if (q.empty ()) return; GlGroupMarker gpm("ProcessUpdates"); if (!fbo2block_) fbo2block_.reset (new Fbo2Block); // draw multiple updates to a block together map<pBlock, list<DrawFunc>> p; for (auto i = q.begin (); i != q.end (); i++) p[i->first].push_back(move(i->second)); // release resources bound in function objects q_success_.clear (); list<pair<pBlock, DrawFunc>> q_failed; map<Heightmap::pBlock,GlTexture::ptr> textures; for (auto i = p.begin (); i != p.end (); i++) { const pBlock& block = i->first; glProjection M; if (isMainThread) textures[block] = block->sourceTexture (); else textures[block] = Heightmap::Render::BlockTextures::get1 (); auto fbo_mapping = fbo2block_->begin (block->getOverlappingRegion (), block->sourceTexture (), textures[block], M); for (auto j = i->second.begin (); j != i->second.end (); j++) { DrawFunc& draw = *j; // try again next frame with draw calls that return false (i.e if a sync object isn'r ready yet) // keep successfull draw calls around to prevent opengl resources from being reused (causing sync or corrupted data) before opengl is done with them (draw(M) ? q_success_ : q_failed) .push_back (pair<pBlock, DrawFunc>(block,move(*j))); } fbo_mapping.release (); } for (const auto& v : textures) v.first->setTexture(v.second); // reinsert failed draw attempts auto w = queue_.write (); w->swap (q_failed); // if any new updates arrived during processing push any failed draw attempts to the back of the queue for (auto& a : q_failed) w->push_back (std::move(a)); }
bool QueueThread::doStartup() { coreprintln("Initializing startup"); // In startup // Send a msg for a parameter and wait for reply then Nav2 is // considered started // Test to wait for msg before sending { WFAPISync sync(&m_guiMonitor); isab::Buffer buf; bool readRes = false; do { readRes = m_guiChannel->readData(&buf, &m_guiMonitor); } while (!readRes && !m_shutDown); if (buf.getLength() > 8) { buf.setReadPos(4); // Start after version and length std::auto_ptr<isab::GuiProtMess> guiProtMess( isab::GuiProtMess::createMsgFromBuf(&buf)); nav2log << "QueueThread run got first msg from Nav2, id " << guiProtMess->getMessageID() << endl; } else { nav2log << "QueueThread run got first msg from Nav2, empty" << endl; } } for (size_t i = 0; i < m_initialMsgs.size(); ++i) { m_nav2API->sendGuiMessage(m_initialMsgs[i]); m_initialMsgs[i]->deleteMembers(); delete m_initialMsgs[i]; m_initialMsgs[i] = NULL; } // Timeout. If there is a problem this might happen. // Send parameter get for wayfinder username. isab::GeneralParameterMess gpm( (uint16)isab::GuiProtEnums::paramUserAndPassword); wf_uint16 reqID = m_nav2API->sendGuiMessage(&gpm); // Wait for reply, then Nav2 is up and running! StatusCode startupCode = OK; while (m_inStartup && !m_shutDown) { WFAPISync sync(&m_guiMonitor); isab::Buffer buf; m_guiChannel->readData(&buf, &m_guiMonitor); if (buf.getLength() != 0) { // Check if it is the reply we want! while (buf.remaining() > 4) { // Start after version and length buf.setReadPos(buf.getReadPos() + 4); std::auto_ptr<isab::GuiProtMess> guiProtMess( isab::GuiProtMess::createMsgFromBuf(&buf)); if (guiProtMess.get() != NULL && guiProtMess->getMessageID() == reqID) { m_inStartup = false; // Set startup result startupCode = OK; } else if (guiProtMess.get() != NULL && guiProtMess->getMessageType() == isab::GuiProtEnums::SET_GENERAL_PARAMETER) { // Check if to store it for later use in MapLib below isab::GeneralParameterMess* mess = static_cast<isab::GeneralParameterMess*> ( guiProtMess.get()); m_nav2API->handleSetParameter(*mess); if (mess->getParamId() == isab::GuiProtEnums::paramMapCacheSize || mess->getParamId() == isab::GuiProtEnums::paramPoiCategories || mess->getParamId() == isab::GuiProtEnums::userTrafficUpdatePeriod || mess->getParamId() == isab::GuiProtEnums::paramDistanceMode) { m_mapLibParams.push_back(mess); guiProtMess.release(); } } else if (guiProtMess.get() != NULL && guiProtMess->getMessageType() == isab::GuiProtEnums::SOUND_FILE_LIST) { nav2log << "QueueThread run got SOUND_FILE_LIST!" << endl; // Send it to NavigationInterfaceImpl m_nav2API->getNavigationInterface().getImpl()-> receiveAsynchronousReply( *guiProtMess, RequestID( RequestID::INVALID_REQUEST_ID)); } if (guiProtMess.get() != NULL) { guiProtMess->deleteMembers(); } } } else { // Wait for data m_guiMonitor.wait(); } } coreprintln("Startup is now complete."); // Call startupComplete m_nav2API->startupComplete(startupCode); return true; }