SL-16418 bg thread for media texture updates
parent
c8926630af
commit
7dcca7f180
|
|
@ -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.
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -1604,6 +1609,25 @@ LLViewerMediaImpl::~LLViewerMediaImpl()
|
|||
remove_media_impl(this);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
//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)
|
||||
{
|
||||
|
|
@ -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;
|
||||
|
||||
if(width > 0 && height > 0)
|
||||
{
|
||||
|
||||
U8* data = NULL;
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_MEDIA("media get data"); //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_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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
mMediaSource->resetDirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
bool LLViewerMediaImpl::preUpdateMediaTexture()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
bool LLViewerMediaImpl::postUpdateMediaTexture()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
void LLViewerMediaImpl::doMediaTexUpdate()
|
||||
{
|
||||
LLViewerMediaTexture* placeholder_image = updatePlaceholderImage();
|
||||
|
||||
if (placeholder_image)
|
||||
{
|
||||
LLRect dirty_rect;
|
||||
|
||||
// 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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -197,7 +197,10 @@ public:
|
|||
U8 media_loop);
|
||||
|
||||
~LLViewerMediaImpl();
|
||||
|
||||
|
||||
static void initClass(LLWindow* window, bool multi_threaded = false);
|
||||
static void cleanupClass();
|
||||
|
||||
// Override inherited version from LLViewerMediaEventEmitter
|
||||
virtual void emitEvent(LLPluginClassMedia* self, LLViewerMediaObserver::EMediaEvent event);
|
||||
|
||||
|
|
@ -266,6 +269,9 @@ public:
|
|||
void scaleTextureCoords(const LLVector2& texture_coords, S32 *x, S32 *y);
|
||||
|
||||
void update();
|
||||
bool preUpdateMediaTexture();
|
||||
void doMediaTexUpdate();
|
||||
bool postUpdateMediaTexture();
|
||||
void updateImagesMediaStreams();
|
||||
LLUUID getMediaTextureID() const;
|
||||
|
||||
|
|
@ -490,6 +496,34 @@ private:
|
|||
|
||||
private:
|
||||
LLViewerMediaTexture *updatePlaceholderImage();
|
||||
LL::WorkQueue::weak_t mMainQueue;
|
||||
LL::WorkQueue::weak_t mTexUpdateQueue;
|
||||
|
||||
};
|
||||
|
||||
// Define a worker thread pool for media updates ( LLImageGLThread)
|
||||
class LLMediaTextureUpdateThread : public LLSimpleton<LLMediaTextureUpdateThread>, LL::ThreadPool
|
||||
{
|
||||
public:
|
||||
// follows gSavedSettings "RenderGLMultiThreaded"
|
||||
static bool sEnabled;
|
||||
|
||||
LLMediaTextureUpdateThread(LLWindow* window);
|
||||
|
||||
// post a function to be executed on the LLMediaTextureUpdateThread background thread
|
||||
template <typename CALLABLE>
|
||||
bool post(CALLABLE&& func)
|
||||
{
|
||||
return getQueue().postIfOpen(std::forward<CALLABLE>(func));
|
||||
}
|
||||
|
||||
void run() override;
|
||||
|
||||
private:
|
||||
LLWindow* mWindow;
|
||||
void* mContext = nullptr;
|
||||
LLAtomicBool mFinished;
|
||||
};
|
||||
|
||||
|
||||
#endif // LLVIEWERMEDIA_H
|
||||
|
|
|
|||
|
|
@ -2027,6 +2027,9 @@ LLViewerWindow::LLViewerWindow(const Params& p)
|
|||
gTextureList.init();
|
||||
LLViewerTextureManager::init() ;
|
||||
gBumpImageList.init();
|
||||
|
||||
// Init Media texture worker queue
|
||||
LLViewerMediaImpl::initClass(mWindow, gSavedSettings.getBOOL("RenderGLMultiThreaded"));
|
||||
|
||||
// Create container for all sub-views
|
||||
LLView::Params rvp;
|
||||
|
|
@ -2416,7 +2419,8 @@ void LLViewerWindow::shutdownGL()
|
|||
|
||||
LLViewerTextureManager::cleanup() ;
|
||||
SUBSYSTEM_CLEANUP(LLImageGL) ;
|
||||
|
||||
SUBSYSTEM_CLEANUP(LLViewerMediaImpl);
|
||||
|
||||
LL_INFOS() << "All textures and llimagegl images are destroyed!" << LL_ENDL ;
|
||||
|
||||
LL_INFOS() << "Cleaning up select manager" << LL_ENDL;
|
||||
|
|
|
|||
Loading…
Reference in New Issue