diff options
author | Dave Houlton <euclid@lindenlab.com> | 2022-01-14 10:34:21 -0700 |
---|---|---|
committer | Dave Houlton <euclid@lindenlab.com> | 2022-01-27 15:44:35 -0700 |
commit | 7dcca7f180c2204daefbc3648ebe766a46c7cf85 (patch) | |
tree | 6074e9b9ef3c06cf1e24267e80a200a7cbcc15a2 /indra/newview/llviewermedia.cpp | |
parent | c8926630af2b80c7db817b78df3a90378f0ecbbb (diff) |
SL-16418 bg thread for media texture updates
Diffstat (limited to 'indra/newview/llviewermedia.cpp')
-rw-r--r-- | indra/newview/llviewermedia.cpp | 179 |
1 files changed, 136 insertions, 43 deletions
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index ba9bbcc57e..8515d61f64 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -78,6 +78,9 @@ #include <boost/bind.hpp> // for SkinFolder listener #include <boost/signals2.hpp> +// Statics +bool LLMediaTextureUpdateThread::sEnabled = false; + class LLMediaFilePicker : public LLFilePickerThread // deletes itself when done { public: @@ -1591,6 +1594,8 @@ LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id, media_tex->setMediaImpl(); } + mMainQueue = LL::WorkQueue::getInstance("mainloop"); + mTexUpdateQueue = LL::WorkQueue::getInstance("LLMediaTextureUpdate"); // Share work queue with tex loader. } ////////////////////////////////////////////////////////////////////////////////////////// @@ -1605,6 +1610,25 @@ LLViewerMediaImpl::~LLViewerMediaImpl() } ////////////////////////////////////////////////////////////////////////////////////////// +//static +void LLViewerMediaImpl::initClass(LLWindow* window, bool multi_threaded /* = false */) +{ + LL_PROFILE_ZONE_SCOPED; + if (multi_threaded) + { + LLMediaTextureUpdateThread::createInstance(window); + } +} + +////////////////////////////////////////////////////////////////////////////////////////// +//static +void LLViewerMediaImpl::cleanupClass() +{ + LL_PROFILE_ZONE_SCOPED; + LLMediaTextureUpdateThread::deleteSingleton(); +} + +////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::emitEvent(LLPluginClassMedia* plugin, LLViewerMediaObserver::EMediaEvent event) { // Broadcast to observers using the superclass version @@ -2876,65 +2900,108 @@ void LLViewerMediaImpl::update() return; } - LLViewerMediaTexture* placeholder_image = updatePlaceholderImage(); + ref(); - if(placeholder_image) - { - LLRect dirty_rect; + if (preUpdateMediaTexture()) + { + // Push update to worker thread + auto main_queue = LLMediaTextureUpdateThread::sEnabled ? mMainQueue.lock() : nullptr; + if (main_queue) + { + main_queue->postTo( + mTexUpdateQueue, // Worker thread queue + [this]() // work done on update worker thread + { + doMediaTexUpdate(); + }, + [this]() // callback to main thread + { + postUpdateMediaTexture(); + //unref(); + }); + } + else + { + doMediaTexUpdate(); // otherwise, update on main thread + //unref(); + } + } + unref(); - // Since we're updating this texture, we know it's playing. Tell the texture to do its replacement magic so it gets rendered. - placeholder_image->setPlaying(TRUE); +} - if(mMediaSource->getDirty(&dirty_rect)) - { - // Constrain the dirty rect to be inside the texture - S32 x_pos = llmax(dirty_rect.mLeft, 0); - S32 y_pos = llmax(dirty_rect.mBottom, 0); - S32 width = llmin(dirty_rect.mRight, placeholder_image->getWidth()) - x_pos; - S32 height = llmin(dirty_rect.mTop, placeholder_image->getHeight()) - y_pos; +////////////////////////////////////////////////////////////////////////////////////////// +bool LLViewerMediaImpl::preUpdateMediaTexture() +{ + return true; +} - if(width > 0 && height > 0) - { +////////////////////////////////////////////////////////////////////////////////////////// +bool LLViewerMediaImpl::postUpdateMediaTexture() +{ + return true; +} - U8* data = NULL; - { - LL_PROFILE_ZONE_NAMED_CATEGORY_MEDIA("media get data"); //LL_RECORD_BLOCK_TIME(FTM_MEDIA_GET_DATA); - data = mMediaSource->getBitsData(); - } +////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::doMediaTexUpdate() +{ + LLViewerMediaTexture* placeholder_image = updatePlaceholderImage(); - if(data != NULL) - { - // Offset the pixels pointer to match x_pos and y_pos - data += ( x_pos * mMediaSource->getTextureDepth() * mMediaSource->getBitsWidth() ); - data += ( y_pos * mMediaSource->getTextureDepth() ); + if (placeholder_image) + { + LLRect dirty_rect; - { - LL_PROFILE_ZONE_NAMED_CATEGORY_MEDIA("media set subimage"); //LL_RECORD_BLOCK_TIME(FTM_MEDIA_SET_SUBIMAGE); - placeholder_image->setSubImage( - data, - mMediaSource->getBitsWidth(), - mMediaSource->getBitsHeight(), - x_pos, - y_pos, - width, - height); - } - } + // Since we're updating this texture, we know it's playing. Tell the texture to do its replacement magic so it gets rendered. + placeholder_image->setPlaying(TRUE); - } + if (mMediaSource->getDirty(&dirty_rect)) + { + // Constrain the dirty rect to be inside the texture + S32 x_pos = llmax(dirty_rect.mLeft, 0); + S32 y_pos = llmax(dirty_rect.mBottom, 0); + S32 width = llmin(dirty_rect.mRight, placeholder_image->getWidth()) - x_pos; + S32 height = llmin(dirty_rect.mTop, placeholder_image->getHeight()) - y_pos; - mMediaSource->resetDirty(); - } - } -} + if (width > 0 && height > 0) + { + U8* data = NULL; + { + LL_RECORD_BLOCK_TIME(FTM_MEDIA_GET_DATA); + data = mMediaSource->getBitsData(); + } + + if (data != NULL) + { + // Offset the pixels pointer to match x_pos and y_pos + data += (x_pos * mMediaSource->getTextureDepth() * mMediaSource->getBitsWidth()); + data += (y_pos * mMediaSource->getTextureDepth()); + + { + LL_RECORD_BLOCK_TIME(FTM_MEDIA_SET_SUBIMAGE); + placeholder_image->setSubImage( + data, + mMediaSource->getBitsWidth(), + mMediaSource->getBitsHeight(), + x_pos, + y_pos, + width, + height); + } + } + + } + + mMediaSource->resetDirty(); + } + } +} ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::updateImagesMediaStreams() { } - ////////////////////////////////////////////////////////////////////////////////////////// LLViewerMediaTexture* LLViewerMediaImpl::updatePlaceholderImage() { @@ -3927,3 +3994,29 @@ bool LLViewerMediaImpl::isObjectInAgentParcel(LLVOVolume *obj) { return (LLViewerParcelMgr::getInstance()->inAgentParcel(obj->getPositionGlobal())); } + +LLMediaTextureUpdateThread::LLMediaTextureUpdateThread(LLWindow* window) +// We want exactly one thread, of moderate capacity: there are likely only a handful +// of media texture frames in-flight at any one time + : ThreadPool("LLMediaTextureUpdate", 1, 4096) + , mWindow(window) +{ + LL_PROFILE_ZONE_SCOPED; + sEnabled = true; + mFinished = false; + + mContext = mWindow->createSharedContext(); + ThreadPool::start(); +} + +void LLMediaTextureUpdateThread::run() +{ + LL_PROFILE_ZONE_SCOPED; + // We must perform setup on this thread before actually servicing our + // WorkQueue, likewise cleanup afterwards. + mWindow->makeContextCurrent(mContext); + gGL.init(); + ThreadPool::run(); + gGL.shutdown(); + mWindow->destroySharedContext(mContext); +} |