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" />
+
+