Thursday, 25 October 2007

Viewer Call Stack Notes

Given that I have no SL budget for land or audio uploads to the main grid, and my OpenSim grid doesn't support scripting I've spent the day looking into the structure of Linden's viewer ("newview").

Here are my notes from the callstack.


Startup

crt0.cpp
WinMainCRTStartup()

viewer.cpp
WinMain()
lldxhardware.cpp
LLDXHardware::getInfo()
CoInitialize(NULL);
CoUninitialize();

gViewerWindow = new LLViewerWindow(...);

llviewerwindow.cpp
LLViewerWindow::LLViewerWindow()
mWindow = LLWindowManager::createWindow(...);

pipeline.cpp
LLPipeline::init()
LLPipeline::getPool(LLDrawPool::POOL_ALPHA); // + others such as Glow, etc
LLDrawPool::createPool()
LLPipeline::addPool()
mPools.insert(new_poolp);

mRootView = new LLRootView(...);

LLViewerWindow::initBase()
gFloaterView = new LLFloaterView(...);

gConsole = new LLConsole(...);
mRootView->addChild(gConsole);

mRootView->addChild(gFloaterView, -1);

main_loop()
idle()
llviewerdisplay.cpp
display()
llstartup.cpp
idle_startup()
messaging.cpp
start_messaging_system()
LLMessageSystem::setHandlerFuncFast(...) // eg, _PREHASH_StartPingCheck with process_start_ping_check()
llmessagetemplate.h
setHandlerFunc()

gWorldp = new LLWorld()
llworld.cpp
LLWorld::addRegion()
llviewerregion.cpp
LLViewerRegion::LLViewerRegion()
llsurface.cpp
LLSurface::create()
LLSurface::initTextures()
pipeline.cpp
LLPipeline::addObject()
LLDrawable::createDrawable(this); // eg, LLVOWater
LLPipeline::getPool()
LLPipeline::addPool()
mPools.insert(new_poolp); // eg, DrawPoolWater,Terrain,SkyStars,Ground


register_viewer_callbacks()
msg->setHandlerFuncFast(_PREHASH_ChatFromSimulator, process_chat_from_simulator);

llviewerobject.cpp
LLViewerObjectList::update()
LLViewerObject.idleUpdate();

Menu Bar

llwindowwin32.cpp
LLWindowWin32::mainWindowProc()
llkeyboardwin32.cpp
LLKeyboardWin32::handleKeyDown()
llkeyboard.cpp
LLKeyboard::handleTranslatedKeyDown()
llviewerwindow.cpp
LLViewerWindow::handleTranslatedKeyDown()
llviewerkeyboard.cpp
LLViewerKeyboard::handleKey()
llviewerwindow.cpp
LLViewerWindow::handleKey()
llmenugl.cpp
LLMenuBarGL::handleAcceleratorKey()
llmenugl.cpp
LLMenuGL::handleAcceleratorKey()
LLMenuItemBranchDownGL::handleAcceleratorKey()
LLMenuGL::handleAcceleratorKey()
LLMenuItemCallGL::handleAcceleratorKey()
LLMenuItemGL::handleAcceleratorKey()
LLMenuItemCallGL::doIt()
LLPointer fired_event = new LLEvent(this);
fireEvent(fired_event, "on_click");
llevent.cpp
LLObservable::fireEvent()
mDispatcher->fireEvent()
LLEventDispatcher::fireEvent()
impl->fireEvent()
LLSimpleDispatcher::fireEvent()
llviewermenu.cpp
LLWorldAlwaysRun::handleEvent() // Sends SetAlwaysRun message
LLMenuItemGL::doIt();


Login
todo

Launch external website from Login panel

crt0.cpp
WinMainCRTStartup()
viewer.cpp
WinMain()
main_loop()
idle()
llmortician.cpp
LLMortician::updateClass()
llalertdialog.cpp
LLAlertDialog::~LLAlertDialog()
llpanellogin.cpp

LLPanelLogin::newAccountAlertCallback() // Passes CREATE_ACCOUNT_URL from llsecondlifeurls.cpp
llweb.h
LLWeb::loadURL()
llweb.cpp
LLWeb::loadURL()
LLWeb::loadURLExternal()
llwindowwin32.cpp
spawn_web_browser()
ShellExecute() // Win32 API

Messaging


main_loop()
idle()
idle_network()
message.cpp
LLMessageSystem::checkAllMessages()
LLMessageSystem::checkMessages()
lltemplatemessagereader.cpp
LLTemplateMessageReader::readMessage()
LLTemplateMessageReader::decodeData()
llmessagetemplate.h
LLMessageTemplate::callHandlerFunc()
llviewermessage.cpp

process_object_update()
llviewerobjectlist.cpp
LLViewerObjectList::processObjectUpdate()
LLViewerObjectList::createObject()
LLViewerObject::createObject(...);
LLViewerObjectList::updateActive()
mActiveObjects.insert(...); // LLVOAvatar, LLVOClouds, etc.

LLViewerObjectList::processUpdateCore()
pipeline.cpp
LLPipeline::addObject()
LLDrawable->createDrawable(this); // LLVOAvatar,Tree

llvoavatar.cpp
LLVOAvatar::createDrawable()
pipeline.cpp
LLPipeline::getPool()
LLPipeline::addPool(); // LLDrawPoolAvatar,Tree


Render

viewer.cpp
WinMain()
main_loop()
idle()
llviewerdisplay.cpp
display()
pipeline.cpp
LLPipeline::updateGeom()
LLPipeline::updateDrawableGeom()
lldrawable.cpp
LLDrawable::updateGeometry()
mVObjp->updateGeometry(this); // where mVObjp is LLVOWater, LLVOSurfacePatch

LLPipeline::renderGeom()
LLDrawPool->prerender(); // LLDrawPoolSky, LLDrawPoolStars, LLDrawPoolGround, LLDrawPoolTerrain, LLDrawPoolSimple, LLDrawPoolBump, LLDrawPoolAvatar, LLDrawPoolTree, LlDrawPoolGlow, LLDrawPoolWater, LLDrawPoolAlphaPostWater
LLDrawPool->render(i); // Same types as above

Notification
(e.g., click on an object, it gives you a card)

message.cpp
LLMessageSystem::checkMessages()

lltemplatemessagereader.cpp
LLTemplateMessageReader::decodeData()

llviewermessage.cpp
process_improved_im()
msg->getU8Fast( _PREHASH_MessageBlock, _PREHASH_Dialog, d); // IM_TASK_INVENTORY_OFFERED, IM_MESSAGEBOX, IM_GROUP_INVITATION, IM_INVENTORY_ACCEPTED, IM_GROUP_VOTE ... IM_GROUP_NOTICE ( LLGroupNotifyBox::show(), LLFloaterGroupInfo::showNotice() ),
inventory_offer_handler()
llnotify.cpp
LLNotifyBox::showXml()
notify = new LLNotifyBox(...);
gNotifyBoxView->addChildAtEnd(notify);
LLNotifyBox::moveToBack()
LLNotifyBoxView::showOnly()
LLNotifyBox::setVisible()
llview.cpp
LLPanel::setVisible() // Actually resolves to LLView
LLView::setVisible()

viewer.cpp
WinMain()
gViewerWindow = new LLViewerWindow()

llviewerdisplay.cpp
display_startup()
gViewerWindow->setup2DRender()

viewer.cpp
main_loop()
llviewerdisplay.cpp
display()
render_ui_and_swap()
render_ui_2d()
llviewerwindow.cpp
LLViewerWindow::draw()
llview.cpp
LLView::draw()
for (child_list_reverse_iter_t child_iter = mChildList.rbegin(); child_iter != mChildList.rend(); ++child_iter)
llnotify.cpp
LLNotifyBox::draw()

// The following are also rendered in this stack,

llconsole.cpp
LLConsol::draw()

llview.cpp
LL::draw()

llnotify.cpp
LLNotifyBox::draw()

llhudview.cpp
LLHUDView::draw()

llfloater.cpp
LLFloaterView::draw()

llfloatermap.cpp
LLFloaterMap::draw()

lldraghandle.cpp
LLDragHandleTop::draw()

llnetmap.cpp
LLNetMap::draw()

lltextbox.cpp
LLTextBox::draw()

llresizehandle.cpp
LLResizeHandle::draw()

llbutton.cpp
LLButton::draw()

llviewerwindow.cpp
LLBottomPanel::draw()

llpanel.cpp
LLPanel::draw()

lloverlaybar.cpp
LLOverlayBar::draw()

llvoiceremotectrl.cpp
LLVoiceRemoteCtrl::draw()

lliconctrl.cpp
LLIconCtrl::draw()

llmediaremotectrl.cpp
LLMediaRemoteCtrl::draw()

llslider.cpp
LLSlider::draw()

llhoverview.cpp
LLHoverView::draw() // Tooltips - could use this to speak currently selected interface element

llstatgraph.cpp
LLStatGraph::draw()

llmenugl.cpp
LLMenuHolderGL::draw()
LLMenuBarGL::draw()
LLMenuItemBranchDownGL::draw()

llprogressview.cpp
LLProgressView::draw() // Loading bar?

Chat

llstartup.cpp
register_viewer_callbacks()
msg->setHandlerFuncFast(_PREHASH_ChatFromSimulator, process_chat_from_simulator);

llviewermessage.cpp

process_chat_from_simulator()
llfloaterchat.cpp
LLFloaterChat::addChat()

llconsole.cpp
LLConsole::addLine()

addChatHistory()
llpanelactivespeakers.cpp
LLPanelActiveSpeakers::setSpeaker()
llfloateractivespeakers.cpp
LLSpeakerMgr::setSpeaker()

SelfVoicing::Speak() // Added by me

Windows
crt0.cpp
WinMainCRTStartup()
viewer.cpp
WinMain()
gViewerWindow = new LLViewerWindow();
mRootView = new LLRootView();

gViewerWindow->initBase();
llviewerwindow.cpp
LLViewerWindow::initBase()
gFloaterView = new LLFloaterView();
mRootView->addChild(gFloaterView, -1);

gSnapshotFloaterView = new LLSnapshotFloaterView();
mRootView->addChild(gSnapshotFloaterView);

gConsole = new LLConsole();
mRootView->addChild(gConsole);

gDebugView = new LLDebugView();
mRootView->addChild(gDebugView);

gHUDView = new LLHUDView();
mRootView->addChild(gHUDView);

gNotifyBoxView = new LLNotifyBoxView();
mRootView->addChild(gNotifyBoxView, -2);

mProgressView = new LLProgressView();
mRootView->addChild(mProgressView);
llviewerwindow.cpp
LLViewerWindow::initWorldUI()
gChatBar = new LLChatBar("chat", chat_bar_rect);
gToolBar = new LLToolBar("toolbar", bar_rect);
gOverlayBar = new LLOverlayBar("overlay", bar_rect);

gBottomPanel = new LLBottomPanel()
gBottomPanel->addChild(gChatBar);
gBottomPanel->addChild(gToolBar);
gBottomPanel->addChild(gOverlayBar);

mRootView->addChild(gBottomPanel);

gHoverView = new LLHoverView("gHoverView", full_window);
gFloaterMap = new LLFloaterMap("Map");
gFloaterWorldMap = new LLFloaterWorldMap();
gFloaterTools = new LLFloaterTools();
gStatusBar = new LLStatusBar("status", status_rect);
gViewerWindow->getRootView()->addChild(gStatusBar);

crt0.cpp
WinMainCRTStartup()
viewer.cpp
WinMain()
main_loop()
idle()
llstartup.cpp
idle_startup()
init_stat_view()
llstatview.cpp
LLStatView::LLStatView()

gDebugView->mStatViewp->addChildAtEnd();


MSAA

This is where the windows mmessage queue is dealt with (callback).

llwindowwin32.cpp

LLWindowWin32::mainWindowProc()

LLView is responsible for handling input and so is perhaps one place to insert MSAA code.
In particular during the startup procedure documented above, mRootView is created as the top level view.
Note the following members:

LLView::tab_order_t;
LLView::focusNextRoot();
LLView::focusPrevRoot();
LLView::focusNextItem();
LLView::focusPrevItem();
LLView::focusFirstItem();
LLView::focusLastItem();

Additionally important is llfocusmgr.h with its class LLFocusMgr

Upon state change (eg, focus moved to a different UI element), issue,
NotifyWinEvent(EVENT_OBJECT_STATECHANGE, hWnd, (LONG)&lpData->btnSelf, CHILDID_SELF)

Focus
crt0.cpp
WinMainCRTStartup()
viewer.cpp
WinMain()
main_loop()
idle()
llstartup.cpp
idle_startup()
login_show()
llpanellogin.cpp
LLPanelLogin::show()
LLPanelLogin::setFocus()
LLPanelLogin::giveFocus()
lllineeditor.cpp
LLLineEditor::setFocus()
lluictrl.cpp
LLUICtrl::setFocus()
gFocusMgr.setKeyboardFocus()
llfocusmgr.cpp
LLFocusMgr::setKeyboardFocus()


Click on Username box in login screen:

llwindowwin32.cpp
LLWindowWin32::mainWindowProc()
case WM_LBUTTONDOWN
llviewerwindow.cpp
LLViewerWindow::handleMouseDown()
llview.cpp LLView::handleMouseDown()
LLView::childrenHandleMouseDown()
LLView::handleMouseDown()
LLView::childrenHandleMouseDown()
lllineeditor.cpp
LLLineEditor::handleMouseDown()
LLLineEditor::setFocus()
LLUICtrl::setFocus()
llfocusmgr.cpp
LLFocusMgr::setKeyboardFocus()
llwebbrowserctrl.cpp
LLWebBrowserCtrl::onFocusLost()
llviewerwindow.h
LLViewerWindow::focusClient()
llwindowwin32.cpp
LLWindowWin32::focusClient()
Platform SDK - SetFocus(HWND)

Tab from Username to Password

llwindowwin32.cpp
LLWindowWin32::mainWindowProc()
case WM_KEYDOWN
llkeyboardwin32.cpp
LLKeyboardWin32::handleKeyDown()
llkeyboard.cpp
LLKeyboard::handleTranslatedKeyDown()
llviewerwindow.cpp
LLViewerWindow::handleTranslatedKeyDown()
llviewerkeyboard.cpp
LLViewerKeyboard::handleKey()
llviewerwindow.cpp
LLViewerWindow::handleKey()
llpanel.cpp
LLPanel::handleKey()
LLUICtrl* keyboard_focus = gFocusMgr.getKeyboardFocus();

llfocusmgr.cpp
LLFocusMgr::childHasKeyboardFocus()

llview.cpp
LLView::isFocusRoot()

LLView::focusNextItem()
LLView::getTabOrderQuery()
query.addPreFilter( LLVisibleFilter::getInstance() );
query.addPreFilter( LLEnabledFilter::getInstance() );
query.addPreFilter( LLTabStopFilter::getInstance() );
query.addPostFilter( LLUICtrl::LLTabStopPostFilter::getInstance() );

LLView::focusNext()
// For example
lllineeditor.cpp
LLLineEditor::setFocus()
lluictrl.cpp
LLUICtrl::setFocus()
llfocusmgr.cpp
gFocusMgr.setKeyboardFocus()

llpanel.cpp
LLPanel::handleKey()
llview.cpp
LLView::handleKey()

In game, focus currently on Inventory window.
Click into main 3D display.

llwindowwin32.cpp
LLWindowWin32::mainWindowProc()
LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(h_wnd, GWL_USERDATA);
case WM_LBUTTONDOWN:
window_imp->mCallbacks->handleMouseDown()

llviewerwindow.cpp
LLViewerWindow::handleMouseDown()
gToolMgr->getCurrentTool()->handleMouseDown()

lltoolpie.cpp
LLToolPie::handleMouseDown()
gViewerWindow->hitObjectOrLandGlobalAsync()
llviewerwindow.cpp
LLViewerWindow::hitObjectOrLandGlobalAsync()
llfocusmgr.cpp
gFocusMgr.setKeyboardFocus()
lllineeditor.cpp
LLLineEditor::onFocusLost()

Gestures
Typing "/yes" into the chat window to activate a gesture

llwindowwin32.cpp

LLWindowWin32::mainWindowProc()
llwindow.cpp
LLWindow::handleUnicodeUTF16()
llviewerwindow.cpp
LLViewerWindow::handleUnicodeChar()
llviewerkeyboard.cpp
LLViewerKeyboard::handleKey()
llviewerwindow.cpp
LLViewerWindow::handleKey()
llview.cpp
LLView::handleKey()
llpanel.cpp
LLPanel::handleKey()
llview.cpp

LLView::handleKey()
llchatbar.cpp
LLChatBar::handleKeyHere()
LLChatBar::sendChat()
llgesturemgr.cpp
LLGestureManager::triggerAndReviseString()
LLGestureManager::playGesture()
SelfVoicing::Speak() // Added by me


viewer.cpp
main_loop()
idle()
llgesturemgr.cpp
LLGestureManager::update()
LLGestureManager::stepGesture()
LLGestureManager::runStep()
llagent.cpp
LLAgent::sendAnimationRequest() // Sends AgentAnimation message


Audio

LLAudioSource* findAudioSource( const LLUUID& source_id );
void addAudioSource( LLAudioSource* asp );
LLAudioChannel* getFreeChannel( const F32 priority );
BOOL hasLocalFile( const LLUUID& uuid );
BOOL preloadSound( const LLUUID& uuid );
void setListener( LLVector3 pos, LLVector3 vel, LLVector3 up, LLVector3 at );
void triggerSound( const LLUUID& sound_id, const LLUUID& owner_id, const F32 gain, const LLVector3d& pos_global = LLVector3d::zero );

audioengine.cpp
LLAudioEngine* gAudiop = NULL;

llstartup.cpp
BOOL idle_startup()
gAudiop = (LLAudioEngine *) new LLAudioEngine_FMOD();
BOOL init = gAudiop->init(kAUDIO_NUM_SOURCES, window_handle);

viewer.cpp
void init_audio()
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndAlert"))); // Lots of other preloaded sounds too

lscript_library.cpp
LLScriptLibrary::init()
addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llPlaySound", NULL, "sf", "llPlaySound(string sound, float volume)\nplays attached sound once at volume (0.0 - 1.0)"));

llpreviewsound.cpp
LLPreviewSound::playSound( void *userdata )
llviewermessage.cpp
send_sound_trigger(const LLUUID& sound_id, F32 gain)
msg->newMessageFast(_PREHASH_SoundTrigger);

llpreviewsound.cpp
LLPreviewSound::auditionSound( void *userdata )
gAudiop->triggerSound( ... )

llvoavatar.cpp
LLVOAvatar::updateCharacter(LLAgent &agent)
gAudiop->triggerSound(step_sound_id, getID(), gain, foot_pos_global);

audioengine.cpp

LLAudioEngine::triggerSound(const LLUUID &audio_uuid, const LLUUID& owner_id, const F32 gain, const LLVector3d &pos_global)
LLAudioSource *asp = new LLAudioSource(source_id, owner_id, gain);
gAudiop->addAudioSource(asp);
asp->play(audio_uuid);

BOOL LLAudioSource::play(const LLUUID &audio_uuid)
LLAudioData *adp = gAudiop->getAudioData(audio_uuid);
addAudioData(adp);
getChannel()->play();

audioengine_fmod.cpp
LLAudioChannelFMOD::play()
getSource()->setPlayedOnce(TRUE);

Object Detection

llvolume.h
const LLPCode LL_PCODE_CUBE = 1;
const LLPCode LL_PCODE_LEGACY_AVATAR = 0x20 | LL_PCODE_LEGACY; // PLAYER

llviewerobject.cpp
LLViewerObject *LLViewerObject::createObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
case LL_PCODE_VOLUME:
res = new LLVOVolume(id, pcode, regionp); break;
case LL_PCODE_LEGACY_AVATAR:
res = new LLVOAvatar(id, pcode, regionp); break;

llviewerobjectlist.cpp
void LLViewerObjectList::processObjectUpdate( ... )
objectp = createObject(pcode, regionp, fullid, local_id, gMessageSystem->getSender());

LLViewerObject *LLViewerObjectList::createObjectViewer(const LLPCode pcode, LLViewerRegion *regionp)
LLViewerObject *objectp = LLViewerObject::createObject(fullid, pcode, regionp);
mUUIDObjectMap[fullid] = objectp;
mObjects.put(objectp);

llviewerobjectlist.h
LLDynamicArrayPtr<>, 256 > LLViewerObjectList::mObjects;


llviewerobjectlist.cpp
LLViewerObjectList::processObjectUpdate( ... )
objectp = createObject(pcode, regionp, fullid, local_id, gMessageSystem->getSender());
LLViewerObject *LLViewerObjectList::createObject( ... )
LLViewerObject *objectp = LLViewerObject::createObject(fullid, pcode, regionp);
llviewerobject.cpp
LLViewerObject *LLViewerObject::createObject( ... )
case LL_PCODE_LEGACY_AVATAR:
res = new LLVOAvatar(id, pcode, regionp); break;


llviewermessage.cpp
process_object_update()

llviewerobjectlist.cpp
LLViewerObjectList::processObjectUpdate( ... )
LLViewerObjectList::processUpdateCore( ... )

llvovolume.cpp
LLVOVolume::processUpdateMessage()
if (update_type == OUT_FULL)
BOOL LLVOVolume::setVolume( ... )
LLPrimitive::setVolume( ... )


pipeline.cpp
LLPipeline::updateGeom()
LLPipeline::updateDrawableGeom()

lldrawable.cpp
LLDrawable::updateGeometry()
mVObjp->updateGeometry(this);

llvovolume.cpp
LLVOVolume::updateGeometry(LLDrawable *drawable)


llviewermessage.cpp
process_object_update()
llviewerobjectlist.cpp
LLViewerObjectList::processObjectUpdate()
LLViewerObjectList::createObject()
LLViewerObject::createObject(...);
LLViewerObjectList::updateActive()
mActiveObjects.insert(...); // LLVOAvatar, LLVOClouds, etc.

No comments: