diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp index 94c29d94579..1df16760910 100644 --- a/indra/llplugin/llpluginclassmedia.cpp +++ b/indra/llplugin/llpluginclassmedia.cpp @@ -997,6 +997,13 @@ void LLPluginClassMedia::setJavascriptEnabled(const bool enabled) sendMessage(message); } +void LLPluginClassMedia::setTransparentBackground(const bool enabled) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "transparent_background"); + message.setValueBoolean("enable", enabled); + sendMessage(message); +} + void LLPluginClassMedia::setWebSecurityDisabled(const bool disabled) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "web_security_disabled"); diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h index 40f6295e556..0c2e353bd8d 100644 --- a/indra/llplugin/llpluginclassmedia.h +++ b/indra/llplugin/llpluginclassmedia.h @@ -228,6 +228,7 @@ class LLPluginClassMedia : public LLPluginProcessParentOwner void setLanguageCode(const std::string &language_code); void setPluginsEnabled(const bool enabled); void setJavascriptEnabled(const bool enabled); + void setTransparentBackground(const bool enabled); void setWebSecurityDisabled(const bool disabled); void setFileAccessFromFileUrlsEnabled(const bool enabled); void setTarget(const std::string &target); diff --git a/indra/llprimitive/llmediaentry.cpp b/indra/llprimitive/llmediaentry.cpp index 48c6ba1fa5d..7ee11acafc5 100644 --- a/indra/llprimitive/llmediaentry.cpp +++ b/indra/llprimitive/llmediaentry.cpp @@ -53,6 +53,9 @@ #define MEDIA_PERMS_INTERACT_KEY_STR "perms_interact" #define MEDIA_PERMS_CONTROL_KEY_STR "perms_control" +// "display" fields +#define MEDIA_TRANSPARENT_BACKGROUND_KEY_STR "transparent_background" + // "general" fields const char* LLMediaEntry::ALT_IMAGE_ENABLE_KEY = MEDIA_ALT_IMAGE_ENABLE_KEY_STR; const char* LLMediaEntry::CONTROLS_KEY = MEDIA_CONTROLS_KEY_STR; @@ -74,6 +77,9 @@ const char* LLMediaEntry::WHITELIST_KEY = MEDIA_WHITELIST_KEY_STR; const char* LLMediaEntry::PERMS_INTERACT_KEY = MEDIA_PERMS_INTERACT_KEY_STR; const char* LLMediaEntry::PERMS_CONTROL_KEY = MEDIA_PERMS_CONTROL_KEY_STR; +// "display" fields +const char* LLMediaEntry::TRANSPARENT_BACKGROUND_KEY = MEDIA_TRANSPARENT_BACKGROUND_KEY_STR; + #define DEFAULT_URL_PREFIX "https://" // Constructor(s) @@ -93,6 +99,7 @@ LLMediaEntry::LLMediaEntry() : // mWhiteList mPermsInteract(PERM_ALL), mPermsControl(PERM_ALL), + mTransparentBackground(false), mMediaIDp(NULL) { } @@ -120,6 +127,9 @@ LLMediaEntry::LLMediaEntry(const LLMediaEntry &rhs) : // "permissions" fields mPermsInteract = rhs.mPermsInteract; mPermsControl = rhs.mPermsControl; + + // "display" fields + mTransparentBackground = rhs.mTransparentBackground; } LLMediaEntry::~LLMediaEntry() @@ -166,6 +176,9 @@ void LLMediaEntry::asLLSD(LLSD& sd) const // "permissions" fields sd[PERMS_INTERACT_KEY] = mPermsInteract; sd[PERMS_CONTROL_KEY] = mPermsControl; + + // "display" fields + sd[TRANSPARENT_BACKGROUND_KEY] = mTransparentBackground; } // static @@ -263,6 +276,16 @@ bool LLMediaEntry::fromLLSDInternal(const LLSD& sd, bool overwrite) status |= setPermsControl( 0xff & (LLSD::Integer)sd[PERMS_CONTROL_KEY] ); } + // "display" fields + // TODO: When the simulator adds "transparent_background" to ObjectMedia + // Change this block to match all other fields: + // if ( overwrite || sd.has(TRANSPARENT_BACKGROUND_KEY) ) + // Until then leave it session based. + if ( sd.has(TRANSPARENT_BACKGROUND_KEY) ) + { + status |= setTransparentBackground( sd[TRANSPARENT_BACKGROUND_KEY] ); + } + return LSL_STATUS_OK == status; } @@ -290,6 +313,9 @@ LLMediaEntry& LLMediaEntry::operator=(const LLMediaEntry &rhs) // "permissions" fields mPermsInteract = rhs.mPermsInteract; mPermsControl = rhs.mPermsControl; + + // "display" fields + mTransparentBackground = rhs.mTransparentBackground; } return *this; @@ -317,7 +343,10 @@ bool LLMediaEntry::operator==(const LLMediaEntry &rhs) const // "permissions" fields mPermsInteract == rhs.mPermsInteract && - mPermsControl == rhs.mPermsControl + mPermsControl == rhs.mPermsControl && + + // "display" fields + mTransparentBackground == rhs.mTransparentBackground ); } @@ -344,7 +373,10 @@ bool LLMediaEntry::operator!=(const LLMediaEntry &rhs) const // "permissions" fields mPermsInteract != rhs.mPermsInteract || - mPermsControl != rhs.mPermsControl + mPermsControl != rhs.mPermsControl || + + // "display" fields + mTransparentBackground != rhs.mTransparentBackground ); } diff --git a/indra/llprimitive/llmediaentry.h b/indra/llprimitive/llmediaentry.h index cabf06648e4..cd3ca4c34a3 100644 --- a/indra/llprimitive/llmediaentry.h +++ b/indra/llprimitive/llmediaentry.h @@ -78,6 +78,7 @@ class LLMediaEntry bool getFirstClickInteract() const { return mFirstClickInteract; } U16 getWidthPixels() const { return mWidthPixels; } U16 getHeightPixels() const { return mHeightPixels; } + bool getTransparentBackground() const { return mTransparentBackground; } // "security" fields bool getWhiteListEnable() const { return mWhiteListEnable; } @@ -100,6 +101,7 @@ class LLMediaEntry U32 setAutoScale(bool auto_scale) { mAutoScale = auto_scale; return LSL_STATUS_OK; } U32 setAutoZoom(bool auto_zoom) { mAutoZoom = auto_zoom; return LSL_STATUS_OK; } U32 setFirstClickInteract(bool first_click) { mFirstClickInteract = first_click; return LSL_STATUS_OK; } + U32 setTransparentBackground(bool transparent) { mTransparentBackground = transparent; return LSL_STATUS_OK; } U32 setWidthPixels(U16 width); U32 setHeightPixels(U16 height); @@ -138,6 +140,7 @@ class LLMediaEntry static const char* FIRST_CLICK_INTERACT_KEY; static const char* WIDTH_PIXELS_KEY; static const char* HEIGHT_PIXELS_KEY; + static const char* TRANSPARENT_BACKGROUND_KEY; // "security" fields static const char* WHITELIST_ENABLE_KEY; @@ -168,7 +171,8 @@ class LLMediaEntry WHITELIST_ID = 12, PERMS_INTERACT_ID = 13, PERMS_CONTROL_ID = 14, - PARAM_MAX_ID = PERMS_CONTROL_ID + TRANSPARENT_BACKGROUND_ID = 15, + PARAM_MAX_ID = TRANSPARENT_BACKGROUND_ID }; // "permissions" values @@ -204,6 +208,7 @@ class LLMediaEntry bool mAutoScale; bool mAutoZoom; bool mFirstClickInteract; + bool mTransparentBackground; U16 mWidthPixels; U16 mHeightPixels; diff --git a/indra/llprimitive/tests/llmediaentry_test.cpp b/indra/llprimitive/tests/llmediaentry_test.cpp index 414df666805..9e5db96abfa 100644 --- a/indra/llprimitive/tests/llmediaentry_test.cpp +++ b/indra/llprimitive/tests/llmediaentry_test.cpp @@ -62,6 +62,8 @@ 7\n\ perms_interact\n\ 7\n\ + transparent_background\n\ + 0\n\ whitelist_enable\n\ 0\n\ width_pixels\n\ @@ -95,6 +97,8 @@ 0\n\ perms_interact\n\ 0\n\ + transparent_background\n\ + 0\n\ whitelist_enable\n\ 0\n\ width_pixels\n\ @@ -128,6 +132,8 @@ 0\n\ perms_interact\n\ 0\n\ + transparent_background\n\ + 0\n\ whitelist_enable\n\ 0\n\ width_pixels\n\ diff --git a/indra/llrender/llgltexture.h b/indra/llrender/llgltexture.h index 122d2a7f9ca..43f1fee8025 100644 --- a/indra/llrender/llgltexture.h +++ b/indra/llrender/llgltexture.h @@ -147,7 +147,7 @@ class LLGLTexture : public LLTexture LLGLenum getPrimaryFormat() const; bool getIsAlphaMask() const ; LLTexUnit::eTextureType getTarget(void) const ; - bool getMask(const LLVector2 &tc); + virtual bool getMask(const LLVector2 &tc); F32 getTimePassedSinceLastBound(); bool getMissed() const ; bool isJustBound()const ; diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index caf804f915d..53f9ce84783 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -98,6 +98,7 @@ class MediaPluginCEF : std::string mProxyHost; int mProxyPort; bool mDisableGPU; + bool mTransparentBackground; bool mDisableNetworkService; bool mUseMockKeyChain; bool mDisableWebSecurity; @@ -140,6 +141,7 @@ MediaPluginBase(host_send_func, host_user_data) mProxyHost = ""; mProxyPort = 0; mDisableGPU = false; + mTransparentBackground = false; mDisableNetworkService = true; mUseMockKeyChain = true; mDisableWebSecurity = false; @@ -652,7 +654,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string) // SL-15560: Product team overruled my change to set the default // embedded background color to match the floater background // and set it to white - settings.background_color = 0xffffffff; // white + settings.background_color = mTransparentBackground ? 0x00ffffff : 0xffffffff; settings.root_cache_path = mRootCachePath; settings.cookies_enabled = mCookiesEnabled; @@ -734,7 +736,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string) message.setValueS32("default_width", 1024); message.setValueS32("default_height", 1024); message.setValueS32("depth", mDepth); - message.setValueU32("internalformat", GL_RGB); + message.setValueU32("internalformat", GL_RGBA); message.setValueU32("format", GL_BGRA); message.setValueU32("type", GL_UNSIGNED_BYTE); message.setValueBoolean("coords_opengl", true); @@ -1033,6 +1035,10 @@ void MediaPluginCEF::receiveMessage(const char* message_string) { mJavascriptEnabled = message_in.getValueBoolean("enable"); } + else if (message_name == "transparent_background") + { + mTransparentBackground = message_in.getValueBoolean("enable"); + } else if (message_name == "gpu_disabled") { mDisableGPU = message_in.getValueBoolean("disable"); diff --git a/indra/newview/llpanelmediasettingsgeneral.cpp b/indra/newview/llpanelmediasettingsgeneral.cpp index 380c2827acc..460f74111d5 100644 --- a/indra/newview/llpanelmediasettingsgeneral.cpp +++ b/indra/newview/llpanelmediasettingsgeneral.cpp @@ -67,6 +67,7 @@ LLPanelMediaSettingsGeneral::LLPanelMediaSettingsGeneral() : mAutoZoom( NULL ), mAutoPlay( NULL ), mAutoScale( NULL ), + mTransparentBackground( NULL ), mWidthPixels( NULL ), mHeightPixels( NULL ), mHomeURL( NULL ), @@ -87,6 +88,7 @@ bool LLPanelMediaSettingsGeneral::postBuild() mAutoPlay = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_PLAY_KEY ); mAutoScale = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_SCALE_KEY ); mAutoZoom = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_ZOOM_KEY ); + mTransparentBackground = getChild< LLCheckBoxCtrl >( LLMediaEntry::TRANSPARENT_BACKGROUND_KEY ); mCurrentURL = getChild< LLTextBox >( LLMediaEntry::CURRENT_URL_KEY ); mFirstClick = getChild< LLCheckBoxCtrl >( LLMediaEntry::FIRST_CLICK_INTERACT_KEY ); mHeightPixels = getChild< LLSpinCtrl >( LLMediaEntry::HEIGHT_PIXELS_KEY ); @@ -204,6 +206,7 @@ void LLPanelMediaSettingsGeneral::clearValues( void* userdata, bool editable, bo self->mHeightPixels->clear(); self->mHomeURL->clear(); self->mWidthPixels->clear(); + self->mTransparentBackground->clear(); self->mAutoLoop ->setEnabled(editable); self->mAutoPlay ->setEnabled(editable); self->mAutoScale ->setEnabled(editable); @@ -213,6 +216,7 @@ void LLPanelMediaSettingsGeneral::clearValues( void* userdata, bool editable, bo self->mHeightPixels ->setEnabled(editable); self->mHomeURL ->setEnabled(editable); self->mWidthPixels ->setEnabled(editable); + self->mTransparentBackground ->setEnabled(editable); if (update_preview) { self->updateMediaPreview(); @@ -277,6 +281,7 @@ void LLPanelMediaSettingsGeneral::initValues( void* userdata, const LLSD& _media { LLMediaEntry::HOME_URL_KEY, self->mHomeURL, "LLLineEditor" }, { LLMediaEntry::FIRST_CLICK_INTERACT_KEY, self->mFirstClick, "LLCheckBoxCtrl" }, { LLMediaEntry::WIDTH_PIXELS_KEY, self->mWidthPixels, "LLSpinCtrl" }, + { LLMediaEntry::TRANSPARENT_BACKGROUND_KEY, self->mTransparentBackground, "LLCheckBoxCtrl" }, { "", NULL , "" } }; @@ -414,6 +419,7 @@ void LLPanelMediaSettingsGeneral::getValues( LLSD &fill_me_in, bool include_tent fill_me_in[LLMediaEntry::HOME_URL_KEY] = (LLSD::String)mHomeURL->getValue(); if (include_tentative || !mFirstClick->getTentative()) fill_me_in[LLMediaEntry::FIRST_CLICK_INTERACT_KEY] = (LLSD::Boolean)mFirstClick->getValue(); if (include_tentative || !mWidthPixels->getTentative()) fill_me_in[LLMediaEntry::WIDTH_PIXELS_KEY] = (LLSD::Integer)mWidthPixels->getValue(); + if (include_tentative || !mTransparentBackground->getTentative()) fill_me_in[LLMediaEntry::TRANSPARENT_BACKGROUND_KEY] = (LLSD::Boolean)mTransparentBackground->getValue(); } //////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llpanelmediasettingsgeneral.h b/indra/newview/llpanelmediasettingsgeneral.h index 9fe97b9121b..6b79d5b17d3 100644 --- a/indra/newview/llpanelmediasettingsgeneral.h +++ b/indra/newview/llpanelmediasettingsgeneral.h @@ -89,6 +89,7 @@ class LLPanelMediaSettingsGeneral : public LLPanel LLCheckBoxCtrl* mAutoZoom; LLCheckBoxCtrl* mAutoPlay; LLCheckBoxCtrl* mAutoScale; + LLCheckBoxCtrl* mTransparentBackground; LLSpinCtrl* mWidthPixels; LLSpinCtrl* mHeightPixels; LLLineEditor* mHomeURL; diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index 0a69be528f8..16af9cd5a36 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -103,6 +103,25 @@ bool LLToolPie::handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType cli return result; } +// True if the pick landed on a media face at a fully transparent media +// pixel, so the pick should defer to whatever is visible behind it. +static bool is_transparent_media_pick(const LLPickInfo& pick) +{ + LLViewerObject* objectp = pick.getObject(); + if (!objectp || pick.mObjectFace < 0 || pick.mObjectFace >= objectp->getNumTEs()) + { + return false; + } + const LLTextureEntry* tep = objectp->getTE(pick.mObjectFace); + LLMediaEntry* mep = (tep && tep->hasMedia()) ? tep->getMediaData() : NULL; + if (!mep) + { + return false; + } + viewer_media_t media_impl = LLViewerMedia::getInstance()->getMediaImplFromTextureID(mep->getMediaID()); + return media_impl.notNull() && media_impl->isTransparentAt(pick.mUVCoords); +} + bool LLToolPie::handleMouseDown(S32 x, S32 y, MASK mask) { if (mDoubleClickTimer.getStarted()) @@ -129,7 +148,13 @@ bool LLToolPie::handleMouseDown(S32 x, S32 y, MASK mask) // left mouse down always picks transparent (but see handleMouseUp). // Also see LLToolPie::handleHover() - priorities are a bit different there. // Todo: we need a more consistent set of rules to work with - if (transp_object == visible_object || !visible_object || + if (transp_object != visible_object && is_transparent_media_pick(transparent_pick)) + { + // The transparent pick went through a fully transparent media pixel, + // act on whatever is visible behind it (object, land, or nothing). + mPick = visible_pick; + } + else if (transp_object == visible_object || !visible_object || !transp_object) // avoid potential for null dereference below, don't make assumptions about behavior of pickImmediate { mPick = transparent_pick; @@ -1666,6 +1691,14 @@ bool LLToolPie::handleMediaClick(const LLPickInfo& pick) viewer_media_t media_impl = LLViewerMedia::getInstance()->getMediaImplFromTextureID(mep->getMediaID()); + if (media_impl.notNull() && media_impl->isTransparentAt(pick.mUVCoords)) + { + // The click landed on a fully transparent part of the media, let it + // pass through to the world. + LLViewerMediaFocus::getInstance()->clearFocus(); + return false; + } + if (gSavedSettings.getBOOL("MediaOnAPrimUI")) { if (!LLViewerMediaFocus::getInstance()->isFocusedOnFace(pick.getObject(), pick.mObjectFace) || media_impl.isNull()) @@ -1730,6 +1763,14 @@ bool LLToolPie::handleMediaDblClick(const LLPickInfo& pick) viewer_media_t media_impl = LLViewerMedia::getInstance()->getMediaImplFromTextureID(mep->getMediaID()); + if (media_impl.notNull() && media_impl->isTransparentAt(pick.mUVCoords)) + { + // The click landed on a fully transparent part of the media, let it + // pass through to the world. + LLViewerMediaFocus::getInstance()->clearFocus(); + return false; + } + if (gSavedSettings.getBOOL("MediaOnAPrimUI")) { if (!LLViewerMediaFocus::getInstance()->isFocusedOnFace(pick.getObject(), pick.mObjectFace) || media_impl.isNull()) @@ -1785,6 +1826,14 @@ bool LLToolPie::handleMediaHover(const LLPickInfo& pick) { viewer_media_t media_impl = LLViewerMedia::getInstance()->getMediaImplFromTextureID(mep->getMediaID()); + if (media_impl.notNull() && media_impl->isTransparentAt(pick.mUVCoords)) + { + // Hovering over a fully transparent part of the media, treat it + // as normal in-world hover. + LLViewerMediaFocus::getInstance()->clearHover(); + return false; + } + if(media_impl.notNull()) { // Update media hover object diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index be4961e3c44..eb7b0c21bb3 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -323,11 +323,23 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s media_impl->mMediaHeight = media_entry->getHeightPixels(); media_impl->mMediaAutoPlay = media_entry->getAutoPlay(); media_impl->mMediaEntryURL = media_entry->getCurrentURL(); + bool transparent_bg_changed = (media_impl->mTransparentBackground != media_entry->getTransparentBackground()); + media_impl->mTransparentBackground = media_entry->getTransparentBackground(); if (media_impl->mMediaSource) { media_impl->mMediaSource->setAutoScale(media_impl->mMediaAutoScale); media_impl->mMediaSource->setLoop(media_impl->mMediaLoop); media_impl->mMediaSource->setSize(media_entry->getWidthPixels(), media_entry->getHeightPixels()); + if (transparent_bg_changed) + { + // CEF transparent mode is init only, reload to take effect. + std::string current_url = media_impl->mMediaEntryURL; + media_impl->destroyMediaSource(); + if (!current_url.empty()) + { + media_impl->navigateTo(current_url, "", false, false); + } + } } bool url_changed = (media_impl->mMediaEntryURL != previous_url); @@ -369,6 +381,7 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s media_impl->setHomeURL(media_entry->getHomeURL()); media_impl->mMediaAutoPlay = media_entry->getAutoPlay(); media_impl->mMediaEntryURL = media_entry->getCurrentURL(); + media_impl->mTransparentBackground = media_entry->getTransparentBackground(); if(media_impl->isAutoPlayable()) { needs_navigate = true; @@ -1657,6 +1670,7 @@ LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id, mTrustedBrowser(false), mZoomFactor(1.0), mCleanBrowser(false), + mTransparentBackground(false), mMimeProbe(), mCanceling(false) { @@ -1788,7 +1802,7 @@ void LLViewerMediaImpl::setMediaType(const std::string& media_type) ////////////////////////////////////////////////////////////////////////////////////////// /*static*/ -LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, F64 zoom_factor, const std::string target, bool clean_browser) +LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, F64 zoom_factor, const std::string target, bool clean_browser, bool transparent_background) { if (gNonInteractive) { @@ -1877,6 +1891,7 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ media_source->proxy_setup(gSavedSettings.getBOOL("BrowserProxyEnabled"), gSavedSettings.getString("BrowserProxyAddress"), gSavedSettings.getS32("BrowserProxyPort")); media_source->setTarget(target); + media_source->setTransparentBackground(transparent_background); const std::string plugin_dir = gDirUtilp->getLLPluginDir(); if (media_source->init(launcher_name, plugin_dir, plugin_name, gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins"))) @@ -1938,7 +1953,7 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type) // Save the MIME type that really caused the plugin to load mCurrentMimeType = mMimeType; - LLPluginClassMedia* media_source = newSourceFromMediaType(mMimeType, this, mMediaWidth, mMediaHeight, mZoomFactor, mTarget, mCleanBrowser); + LLPluginClassMedia* media_source = newSourceFromMediaType(mMimeType, this, mMediaWidth, mMediaHeight, mZoomFactor, mTarget, mCleanBrowser, mTransparentBackground); if (media_source) { @@ -2350,6 +2365,47 @@ void LLViewerMediaImpl::scaleTextureCoords(const LLVector2& texture_coords, S32 *y -= (mMediaSource->getTextureHeight() - mMediaSource->getHeight()); } +////////////////////////////////////////////////////////////////////////////////////////// +bool LLViewerMediaImpl::isTransparentAt(const LLVector2& texture_coords) +{ + if (!mMediaSource || !mMediaSource->textureValid()) + { + return false; + } + + // Only media with an alpha channel (BGRA) can have transparent areas. + const S32 depth = mMediaSource->getTextureDepth(); + if (depth != 4) + { + return false; + } + + const U8* pixels = mMediaSource->getBitsData(); + if (!pixels) + { + return false; + } + + S32 x, y; + scaleTextureCoords(texture_coords, &x, &y); + + // scaleTextureCoords returns browser coordinates (y = 0 at the top), but + // plugins with coords_opengl write rows bottom-up in GL order into the + // shared buffer (dullahan's flip_pixels_y), so flip y to address the buffer. + if (mMediaSource->getTextureCoordsOpenGL()) + { + y = mMediaSource->getHeight() - 1 - y; + } + + const S32 buffer_width = mMediaSource->getBitsWidth(); + if (x < 0 || y < 0 || x >= buffer_width || y >= mMediaSource->getBitsHeight()) + { + return false; + } + + return pixels[(y * buffer_width + x) * depth + 3] == 0; +} + ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::mouseDown(const LLVector2& texture_coords, MASK mask, S32 button) { @@ -3172,9 +3228,9 @@ LLViewerMediaTexture* LLViewerMediaImpl::updateMediaImage() // MEDIAOPT: seems insane that we actually have to make an imageraw then // immediately discard it LLPointer raw = new LLImageRaw(texture_width, texture_height, texture_depth); - // Clear the texture to the background color, ignoring alpha. + // Clear the texture to the background color with alpha. // convert background color channels from [0.0, 1.0] to [0, 255]; - raw->clear(int(mBackgroundColor.mV[VX] * 255.0f), int(mBackgroundColor.mV[VY] * 255.0f), int(mBackgroundColor.mV[VZ] * 255.0f), 0xff); + raw->clear(int(mBackgroundColor.mV[VX] * 255.0f), int(mBackgroundColor.mV[VY] * 255.0f), int(mBackgroundColor.mV[VZ] * 255.0f), 0x00); // ask media source for correct GL image format constants media_tex->setExplicitFormat(mMediaSource->getTextureFormatInternal(), diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index c840fbb72c9..425b5a43ff6 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -244,6 +244,9 @@ class LLViewerMediaImpl void scrollWheel(const LLVector2& texture_coords, S32 scroll_x, S32 scroll_y, MASK mask); void scrollWheel(S32 x, S32 y, S32 scroll_x, S32 scroll_y, MASK mask); void mouseCapture(); + // True if the media pixel at the given texture coordinates is fully + // transparent, so mouse events can pass through to the world. + bool isTransparentAt(const LLVector2& texture_coords); void navigateBack(); void navigateForward(); @@ -309,7 +312,7 @@ class LLViewerMediaImpl void setTarget(const std::string& target) { mTarget = target; } // utility function to create a ready-to-use media instance from a desired media type. - static LLPluginClassMedia* newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, F64 zoom_factor, const std::string target = LLStringUtil::null, bool clean_browser = false); + static LLPluginClassMedia* newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, F64 zoom_factor, const std::string target = LLStringUtil::null, bool clean_browser = false, bool transparent_background = false); // Internally set our desired browser user agent string, including // the Second Life version and skin name. Used because we can @@ -502,6 +505,7 @@ class LLViewerMediaImpl std::string mTarget; LLNotificationPtr mNotification; bool mCleanBrowser; // force the creation of a clean browsing target with full options enabled + bool mTransparentBackground; static std::vector sMimeTypesFailed; LLPointer mRawImage; //backing buffer for texture updates private: diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 0f23596c9a8..fd51de79c8f 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -3712,6 +3712,17 @@ F32 LLViewerMediaTexture::getMaxVirtualSize() return mMaxVirtualSize; } + +//virtual +bool LLViewerMediaTexture::getMask(const LLVector2 &tc) +{ + if (mIsPlaying && mMediaImplp) + { + return !mMediaImplp->isTransparentAt(tc); + } + + return LLViewerTexture::getMask(tc); +} //---------------------------------------------------------------------------------------------- //end of LLViewerMediaTexture //---------------------------------------------------------------------------------------------- diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 29376519953..b62e184598f 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -583,6 +583,10 @@ class LLViewerMediaTexture : public LLViewerTexture /*virtual*/ F32 getMaxVirtualSize(); + // Sample the live media pixel buffer so picks pass through fully + // transparent areas of the media. + /*virtual*/ bool getMask(const LLVector2 &tc); + private: void switchTexture(U32 ch, LLFace* facep) ; bool findFaces() ; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 54fa7a2c099..80cf105dba6 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -1780,7 +1780,7 @@ U32 LLPipeline::getPoolTypeFromTE(const LLTextureEntry* te, LLViewerTexture* ima bool alpha = color_alpha; if (imagep) { - alpha = alpha || (imagep->getComponents() == 4 && imagep->getType() != LLViewerTexture::MEDIA_TEXTURE) || (imagep->getComponents() == 2); + alpha = alpha || (imagep->getComponents() == 4) || (imagep->getComponents() == 2); } if (alpha && mat) diff --git a/indra/newview/skins/default/xui/en/panel_media_settings_general.xml b/indra/newview/skins/default/xui/en/panel_media_settings_general.xml index 5e7830f27c6..facb801a17a 100644 --- a/indra/newview/skins/default/xui/en/panel_media_settings_general.xml +++ b/indra/newview/skins/default/xui/en/panel_media_settings_general.xml @@ -174,6 +174,20 @@ radio_style="false" width="150" /> + +