summaryrefslogtreecommitdiff
path: root/indra/newview/llviewermedia.cpp
diff options
context:
space:
mode:
authorDave Houlton <euclid@lindenlab.com>2022-01-14 10:34:21 -0700
committerDave Houlton <euclid@lindenlab.com>2022-01-27 15:44:35 -0700
commit7dcca7f180c2204daefbc3648ebe766a46c7cf85 (patch)
tree6074e9b9ef3c06cf1e24267e80a200a7cbcc15a2 /indra/newview/llviewermedia.cpp
parentc8926630af2b80c7db817b78df3a90378f0ecbbb (diff)
SL-16418 bg thread for media texture updates
Diffstat (limited to 'indra/newview/llviewermedia.cpp')
-rw-r--r--indra/newview/llviewermedia.cpp179
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);
+}