зеркало из https://github.com/mozilla/pjs.git
Merge m-c to s-c
This commit is contained in:
Коммит
006f8e2a5d
|
@ -654,7 +654,7 @@ nsAccessible::IsVisible(bool* aIsOffscreen)
|
|||
}
|
||||
|
||||
// The frame intersects the viewport, but we need to check the parent view chain :(
|
||||
bool isVisible = nsCoreUtils::CheckVisibilityInParentChain(frame);
|
||||
bool isVisible = frame->IsVisibleConsideringAncestors(nsIFrame::VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY);
|
||||
if (isVisible && rectVisibility == nsRectVisibility_kVisible) {
|
||||
*aIsOffscreen = false;
|
||||
}
|
||||
|
|
|
@ -758,31 +758,6 @@ nsCoreUtils::IsColumnHidden(nsITreeColumn *aColumn)
|
|||
nsGkAtoms::_true, eCaseMatters);
|
||||
}
|
||||
|
||||
bool
|
||||
nsCoreUtils::CheckVisibilityInParentChain(nsIFrame* aFrame)
|
||||
{
|
||||
nsIView* view = aFrame->GetClosestView();
|
||||
if (view && !view->IsEffectivelyVisible())
|
||||
return false;
|
||||
|
||||
nsIPresShell* presShell = aFrame->PresContext()->GetPresShell();
|
||||
while (presShell) {
|
||||
if (!presShell->IsActive()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsIFrame* rootFrame = presShell->GetRootFrame();
|
||||
presShell = nsnull;
|
||||
if (rootFrame) {
|
||||
nsIFrame* frame = nsLayoutUtils::GetCrossDocParentFrame(rootFrame);
|
||||
if (frame) {
|
||||
presShell = frame->PresContext()->GetPresShell();
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsAccessibleDOMStringList
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -370,11 +370,6 @@ public:
|
|||
aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::scope);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the visibility across both parent content and chrome.
|
||||
*/
|
||||
static bool CheckVisibilityInParentChain(nsIFrame* aFrame);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -311,7 +311,8 @@ nsDocAccessible::NativeState()
|
|||
state |= states::BUSY;
|
||||
|
||||
nsIFrame* frame = GetFrame();
|
||||
if (!frame || !nsCoreUtils::CheckVisibilityInParentChain(frame)) {
|
||||
if (!frame ||
|
||||
!frame->IsVisibleConsideringAncestors(nsIFrame::VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY)) {
|
||||
state |= states::INVISIBLE | states::OFFSCREEN;
|
||||
}
|
||||
|
||||
|
|
|
@ -1716,6 +1716,22 @@ public:
|
|||
*/
|
||||
static bool IsFullScreenKeyInputRestricted();
|
||||
|
||||
/**
|
||||
* Returns true if the doctree rooted at aDoc contains any plugins which
|
||||
* we don't control event dispatch for, i.e. do any plugins in this doc tree
|
||||
* receive key events outside of our control? This always returns false
|
||||
* on MacOSX.
|
||||
*/
|
||||
static bool HasPluginWithUncontrolledEventDispatch(nsIDocument* aDoc);
|
||||
|
||||
/**
|
||||
* Returns true if the content is in a document and contains a plugin
|
||||
* which we don't control event dispatch for, i.e. do any plugins in this
|
||||
* doc tree receive key events outside of our control? This always returns
|
||||
* false on MacOSX.
|
||||
*/
|
||||
static bool HasPluginWithUncontrolledEventDispatch(nsIContent* aContent);
|
||||
|
||||
/**
|
||||
* Returns the time limit on handling user input before
|
||||
* nsEventStateManager::IsHandlingUserInput() stops returning true.
|
||||
|
|
|
@ -203,8 +203,7 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID);
|
|||
#include "nsDOMTouchEvent.h"
|
||||
#include "nsIScriptElement.h"
|
||||
#include "nsIContentViewer.h"
|
||||
|
||||
#include "prdtoa.h"
|
||||
#include "nsIObjectLoadingContent.h"
|
||||
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
|
@ -5815,6 +5814,70 @@ nsContentUtils::IsFullScreenKeyInputRestricted()
|
|||
return sFullScreenKeyInputRestricted;
|
||||
}
|
||||
|
||||
static void
|
||||
CheckForWindowedPlugins(nsIContent* aContent, void* aResult)
|
||||
{
|
||||
if (!aContent->IsInDoc()) {
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIObjectLoadingContent> olc(do_QueryInterface(aContent));
|
||||
if (!olc) {
|
||||
return;
|
||||
}
|
||||
nsRefPtr<nsNPAPIPluginInstance> plugin;
|
||||
olc->GetPluginInstance(getter_AddRefs(plugin));
|
||||
if (!plugin) {
|
||||
return;
|
||||
}
|
||||
bool isWindowless = false;
|
||||
nsresult res = plugin->IsWindowless(&isWindowless);
|
||||
if (NS_SUCCEEDED(res) && !isWindowless) {
|
||||
*static_cast<bool*>(aResult) = true;
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
DocTreeContainsWindowedPlugins(nsIDocument* aDoc, void* aResult)
|
||||
{
|
||||
if (!nsContentUtils::IsChromeDoc(aDoc)) {
|
||||
aDoc->EnumerateFreezableElements(CheckForWindowedPlugins, aResult);
|
||||
}
|
||||
if (*static_cast<bool*>(aResult)) {
|
||||
// Return false to stop iteration, we found a windowed plugin.
|
||||
return false;
|
||||
}
|
||||
aDoc->EnumerateSubDocuments(DocTreeContainsWindowedPlugins, aResult);
|
||||
// Return false to stop iteration if we found a windowed plugin in
|
||||
// the sub documents.
|
||||
return !*static_cast<bool*>(aResult);
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
nsContentUtils::HasPluginWithUncontrolledEventDispatch(nsIDocument* aDoc)
|
||||
{
|
||||
#ifdef XP_MACOSX
|
||||
// We control dispatch to all mac plugins.
|
||||
return false;
|
||||
#endif
|
||||
bool result = false;
|
||||
DocTreeContainsWindowedPlugins(aDoc, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
nsContentUtils::HasPluginWithUncontrolledEventDispatch(nsIContent* aContent)
|
||||
{
|
||||
#ifdef XP_MACOSX
|
||||
// We control dispatch to all mac plugins.
|
||||
return false;
|
||||
#endif
|
||||
bool result = false;
|
||||
CheckForWindowedPlugins(aContent, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
nsContentUtils::ReleaseWrapper(nsISupports* aScriptObjectHolder,
|
||||
|
|
|
@ -8578,13 +8578,11 @@ nsDocument::GetMozFullScreenEnabled(bool *aFullScreen)
|
|||
NS_ENSURE_ARG_POINTER(aFullScreen);
|
||||
*aFullScreen = false;
|
||||
|
||||
if (!nsContentUtils::IsFullScreenApiEnabled()) {
|
||||
if (!nsContentUtils::IsFullScreenApiEnabled() ||
|
||||
nsContentUtils::HasPluginWithUncontrolledEventDispatch(this)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// todo: Bug 684618 - Deny requests for DOM full-screen when windowed
|
||||
// plugins are present.
|
||||
|
||||
// Ensure that all ancestor <iframe> elements have the mozallowfullscreen
|
||||
// boolean attribute set.
|
||||
nsINode* node = static_cast<nsINode*>(this);
|
||||
|
|
|
@ -70,6 +70,7 @@ CPPSRCS += \
|
|||
WebGLContextUtils.cpp \
|
||||
WebGLContextValidate.cpp \
|
||||
WebGLExtensionStandardDerivatives.cpp \
|
||||
WebGLExtensionLoseContext.cpp \
|
||||
$(NULL)
|
||||
|
||||
DEFINES += -DUSE_ANGLE
|
||||
|
|
|
@ -296,14 +296,21 @@ WebGLContext::WebGLContext()
|
|||
// See OpenGL ES 2.0.25 spec, 6.2 State Tables, table 6.13
|
||||
mPixelStorePackAlignment = 4;
|
||||
mPixelStoreUnpackAlignment = 4;
|
||||
|
||||
|
||||
WebGLMemoryReporter::AddWebGLContext(this);
|
||||
|
||||
mContextLost = false;
|
||||
mAllowRestore = false;
|
||||
}
|
||||
|
||||
WebGLContext::~WebGLContext()
|
||||
{
|
||||
DestroyResourcesAndContext();
|
||||
WebGLMemoryReporter::RemoveWebGLContext(this);
|
||||
if (mContextRestorer) {
|
||||
mContextRestorer->Cancel();
|
||||
mContextRestorer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
|
@ -822,6 +829,9 @@ WebGLContext::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
|
|||
CanvasLayer *aOldLayer,
|
||||
LayerManager *aManager)
|
||||
{
|
||||
if (mContextLost)
|
||||
return nsnull;
|
||||
|
||||
if (!mResetLayer && aOldLayer &&
|
||||
aOldLayer->HasUserData(&gWebGLLayerUserData)) {
|
||||
NS_ADDREF(aOldLayer);
|
||||
|
@ -885,6 +895,12 @@ WebGLContext::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
|
|||
NS_IMETHODIMP
|
||||
WebGLContext::GetContextAttributes(jsval *aResult)
|
||||
{
|
||||
if (mContextLost)
|
||||
{
|
||||
*aResult = OBJECT_TO_JSVAL(NULL);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
JSContext *cx = nsContentUtils::GetCurrentJSContext();
|
||||
if (!cx)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -923,6 +939,9 @@ WebGLContext::GetContextAttributes(jsval *aResult)
|
|||
NS_IMETHODIMP
|
||||
WebGLContext::MozGetUnderlyingParamString(PRUint32 pname, nsAString& retval)
|
||||
{
|
||||
if (mContextLost)
|
||||
return NS_OK;
|
||||
|
||||
retval.SetIsVoid(true);
|
||||
|
||||
MakeContextCurrent();
|
||||
|
@ -959,6 +978,10 @@ bool WebGLContext::IsExtensionSupported(WebGLExtensionID ei)
|
|||
// We always support this extension.
|
||||
isSupported = true;
|
||||
break;
|
||||
case WebGL_WEBKIT_lose_context:
|
||||
// We always support this extension.
|
||||
isSupported = true;
|
||||
break;
|
||||
default:
|
||||
isSupported = false;
|
||||
}
|
||||
|
@ -970,6 +993,8 @@ NS_IMETHODIMP
|
|||
WebGLContext::GetExtension(const nsAString& aName, nsIWebGLExtension **retval)
|
||||
{
|
||||
*retval = nsnull;
|
||||
if (mContextLost)
|
||||
return NS_OK;
|
||||
|
||||
if (mDisableExtensions) {
|
||||
return NS_OK;
|
||||
|
@ -985,6 +1010,10 @@ WebGLContext::GetExtension(const nsAString& aName, nsIWebGLExtension **retval)
|
|||
if (IsExtensionSupported(WebGL_OES_standard_derivatives))
|
||||
ei = WebGL_OES_standard_derivatives;
|
||||
}
|
||||
else if (aName.EqualsLiteral("WEBKIT_lose_context")) {
|
||||
if (IsExtensionSupported(WebGL_WEBKIT_lose_context))
|
||||
ei = WebGL_WEBKIT_lose_context;
|
||||
}
|
||||
|
||||
if (ei != WebGLExtensionID_Max) {
|
||||
if (!IsExtensionEnabled(ei)) {
|
||||
|
@ -992,6 +1021,9 @@ WebGLContext::GetExtension(const nsAString& aName, nsIWebGLExtension **retval)
|
|||
case WebGL_OES_standard_derivatives:
|
||||
mEnabledExtensions[ei] = new WebGLExtensionStandardDerivatives(this);
|
||||
break;
|
||||
case WebGL_WEBKIT_lose_context:
|
||||
mEnabledExtensions[ei] = new WebGLExtensionLoseContext(this);
|
||||
break;
|
||||
// create an extension for any types that don't
|
||||
// have any additional tokens or methods
|
||||
default:
|
||||
|
@ -1095,6 +1127,86 @@ WebGLContext::EnsureBackbufferClearedAsNeeded()
|
|||
Invalidate();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebGLContext::Notify(nsITimer* timer)
|
||||
{
|
||||
MaybeRestoreContext();
|
||||
|
||||
if (mContextRestorer) {
|
||||
mContextRestorer->Cancel();
|
||||
mContextRestorer = NULL;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::MaybeRestoreContext()
|
||||
{
|
||||
if (mContextLost || mAllowRestore)
|
||||
return;
|
||||
|
||||
GLContext::ContextResetARB resetStatus =
|
||||
(GLContext::ContextResetARB) gl->fGetGraphicsResetStatus();
|
||||
|
||||
if (resetStatus != GLContext::CONTEXT_NO_ERROR) {
|
||||
// It's already lost, but clean up after it and signal to JS that it is
|
||||
// lost.
|
||||
ForceLoseContext();
|
||||
}
|
||||
|
||||
switch (resetStatus) {
|
||||
case GLContext::CONTEXT_NO_ERROR:
|
||||
return;
|
||||
case GLContext::CONTEXT_GUILTY_CONTEXT_RESET_ARB:
|
||||
NS_WARNING("WebGL content on the page caused the graphics card to reset; not restoring the context");
|
||||
return;
|
||||
case GLContext::CONTEXT_INNOCENT_CONTEXT_RESET_ARB:
|
||||
break;
|
||||
case GLContext::CONTEXT_UNKNOWN_CONTEXT_RESET_ARB:
|
||||
NS_WARNING("WebGL content on the page might have caused the graphics card to reset");
|
||||
break;
|
||||
}
|
||||
|
||||
ForceRestoreContext();
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::ForceLoseContext()
|
||||
{
|
||||
if (mContextRestorer) {
|
||||
mContextRestorer->Cancel();
|
||||
mContextRestorer = NULL;
|
||||
}
|
||||
|
||||
mWebGLError = LOCAL_GL_CONTEXT_LOST;
|
||||
|
||||
bool defaultAction;
|
||||
mContextLost = true;
|
||||
DestroyResourcesAndContext();
|
||||
nsContentUtils::DispatchTrustedEvent(HTMLCanvasElement()->OwnerDoc(),
|
||||
(nsIDOMHTMLCanvasElement*) HTMLCanvasElement(),
|
||||
NS_LITERAL_STRING("webglcontextlost"),
|
||||
PR_TRUE,
|
||||
PR_TRUE,
|
||||
&defaultAction);
|
||||
if (defaultAction)
|
||||
mAllowRestore = false;
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::ForceRestoreContext()
|
||||
{
|
||||
mContextLost = false;
|
||||
mAllowRestore = false;
|
||||
SetDimensions(mHeight, mWidth);
|
||||
nsContentUtils::DispatchTrustedEvent(HTMLCanvasElement()->OwnerDoc(),
|
||||
(nsIDOMHTMLCanvasElement*) HTMLCanvasElement(),
|
||||
NS_LITERAL_STRING("webglcontextrestored"),
|
||||
PR_TRUE,
|
||||
PR_TRUE);
|
||||
}
|
||||
|
||||
//
|
||||
// XPCOM goop
|
||||
//
|
||||
|
@ -1116,6 +1228,7 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebGLContext)
|
|||
NS_INTERFACE_MAP_ENTRY(nsIDOMWebGLRenderingContext)
|
||||
NS_INTERFACE_MAP_ENTRY(nsICanvasRenderingContextInternal)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
||||
NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMWebGLRenderingContext)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLRenderingContext)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
@ -1254,10 +1367,24 @@ NS_INTERFACE_MAP_BEGIN(WebGLExtensionStandardDerivatives)
|
|||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLExtensionStandardDerivatives)
|
||||
NS_INTERFACE_MAP_END_INHERITING(WebGLExtension)
|
||||
|
||||
NS_IMPL_ADDREF(WebGLExtensionLoseContext)
|
||||
NS_IMPL_RELEASE(WebGLExtensionLoseContext)
|
||||
|
||||
DOMCI_DATA(WebGLExtensionLoseContext, WebGLExtensionLoseContext)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(WebGLExtensionLoseContext)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIWebGLExtensionLoseContext)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, WebGLExtension)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLExtensionLoseContext)
|
||||
NS_INTERFACE_MAP_END_INHERITING(WebGLExtension)
|
||||
|
||||
/* readonly attribute WebGLsizei drawingBufferWidth; */
|
||||
NS_IMETHODIMP
|
||||
WebGLContext::GetDrawingBufferWidth(WebGLsizei *aWidth)
|
||||
{
|
||||
if (mContextLost)
|
||||
return NS_OK;
|
||||
|
||||
*aWidth = mWidth;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1266,6 +1393,9 @@ WebGLContext::GetDrawingBufferWidth(WebGLsizei *aWidth)
|
|||
NS_IMETHODIMP
|
||||
WebGLContext::GetDrawingBufferHeight(WebGLsizei *aHeight)
|
||||
{
|
||||
if (mContextLost)
|
||||
return NS_OK;
|
||||
|
||||
*aHeight = mHeight;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1311,6 +1441,8 @@ NS_IMETHODIMP
|
|||
WebGLContext::GetSupportedExtensions(nsIVariant **retval)
|
||||
{
|
||||
*retval = nsnull;
|
||||
if (mContextLost)
|
||||
return NS_OK;
|
||||
|
||||
if (mDisableExtensions) {
|
||||
return NS_OK;
|
||||
|
@ -1343,7 +1475,7 @@ WebGLContext::GetSupportedExtensions(nsIVariant **retval)
|
|||
NS_IMETHODIMP
|
||||
WebGLContext::IsContextLost(WebGLboolean *retval)
|
||||
{
|
||||
*retval = false;
|
||||
*retval = mContextLost;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -339,9 +339,11 @@ struct WebGLContextOptions {
|
|||
class WebGLContext :
|
||||
public nsIDOMWebGLRenderingContext,
|
||||
public nsICanvasRenderingContextInternal,
|
||||
public nsSupportsWeakReference
|
||||
public nsSupportsWeakReference,
|
||||
public nsITimerCallback
|
||||
{
|
||||
friend class WebGLMemoryReporter;
|
||||
friend class WebGLExtensionLoseContext;
|
||||
|
||||
public:
|
||||
WebGLContext();
|
||||
|
@ -353,6 +355,8 @@ public:
|
|||
|
||||
NS_DECL_NSIDOMWEBGLRENDERINGCONTEXT
|
||||
|
||||
NS_DECL_NSITIMERCALLBACK
|
||||
|
||||
// nsICanvasRenderingContextInternal
|
||||
NS_IMETHOD SetCanvasElement(nsHTMLCanvasElement* aParentCanvas);
|
||||
NS_IMETHOD SetDimensions(PRInt32 width, PRInt32 height);
|
||||
|
@ -380,6 +384,9 @@ public:
|
|||
PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h)
|
||||
{ return NS_ERROR_NOT_IMPLEMENTED; }
|
||||
|
||||
bool LoseContext();
|
||||
bool RestoreContext();
|
||||
|
||||
nsresult SynthesizeGLError(WebGLenum err);
|
||||
nsresult SynthesizeGLError(WebGLenum err, const char *fmt, ...);
|
||||
|
||||
|
@ -438,6 +445,22 @@ public:
|
|||
return mMinCapability;
|
||||
}
|
||||
|
||||
// Sets up the GL_ARB_robustness timer if it isn't already, so that if the
|
||||
// driver gets restarted, the context may get reset with it.
|
||||
void SetupRobustnessTimer() {
|
||||
if (mContextLost)
|
||||
return;
|
||||
|
||||
if (!mContextRestorer)
|
||||
mContextRestorer = do_CreateInstance("@mozilla.org/timer;1");
|
||||
|
||||
// As long as there's still activity, we reset the timer each time that
|
||||
// this function gets called.
|
||||
mContextRestorer->InitWithCallback(static_cast<nsITimerCallback*>(this),
|
||||
PR_MillisecondsToInterval(1000),
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
}
|
||||
|
||||
protected:
|
||||
void SetDontKnowIfNeedFakeBlack() {
|
||||
mFakeBlackStatus = DontKnowIfNeedFakeBlack;
|
||||
|
@ -502,6 +525,7 @@ protected:
|
|||
enum WebGLExtensionID {
|
||||
WebGL_OES_texture_float,
|
||||
WebGL_OES_standard_derivatives,
|
||||
WebGL_WEBKIT_lose_context,
|
||||
WebGLExtensionID_Max
|
||||
};
|
||||
nsCOMPtr<WebGLExtension> mEnabledExtensions[WebGLExtensionID_Max];
|
||||
|
@ -633,6 +657,10 @@ protected:
|
|||
GLenum type,
|
||||
const GLvoid *data);
|
||||
|
||||
void MaybeRestoreContext();
|
||||
void ForceLoseContext();
|
||||
void ForceRestoreContext();
|
||||
|
||||
// the buffers bound to the current program's attribs
|
||||
nsTArray<WebGLVertexAttribData> mAttribBuffers;
|
||||
|
||||
|
@ -691,6 +719,10 @@ protected:
|
|||
|
||||
int mBackbufferClearingStatus;
|
||||
|
||||
nsCOMPtr<nsITimer> mContextRestorer;
|
||||
bool mContextLost;
|
||||
bool mAllowRestore;
|
||||
|
||||
public:
|
||||
// console logging helpers
|
||||
static void LogMessage(const char *fmt, ...);
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -53,3 +53,4 @@ DOMCI_DATA(WebGLRenderbuffer, void)
|
|||
DOMCI_DATA(WebGLUniformLocation, void)
|
||||
DOMCI_DATA(WebGLActiveInfo, void)
|
||||
DOMCI_DATA(WebGLExtension, void)
|
||||
DOMCI_DATA(WebGLExtensionLoseContext, void)
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Doug Sherk <dsherk@mozilla.com> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "WebGLContext.h"
|
||||
#include "WebGLExtensions.h"
|
||||
|
||||
#include "nsContentUtils.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
WebGLExtensionLoseContext::WebGLExtensionLoseContext(WebGLContext* context) :
|
||||
WebGLExtension(context)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
WebGLExtensionLoseContext::~WebGLExtensionLoseContext()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebGLExtensionLoseContext::LoseContext()
|
||||
{
|
||||
if (!mContext->LoseContext())
|
||||
return mContext->mWebGLError = LOCAL_GL_INVALID_OPERATION;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebGLExtensionLoseContext::RestoreContext()
|
||||
{
|
||||
if (!mContext->RestoreContext())
|
||||
return mContext->mWebGLError = LOCAL_GL_INVALID_OPERATION;
|
||||
|
||||
return NS_OK;
|
||||
}
|
|
@ -41,8 +41,27 @@
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
class WebGLExtensionLoseContext;
|
||||
class WebGLExtensionStandardDerivatives;
|
||||
|
||||
#define WEBGLEXTENSIONLOSECONTEXT_PRIVATE_IID \
|
||||
{0xb0afc2eb, 0x0895, 0x4509, {0x98, 0xde, 0x5c, 0x38, 0x3d, 0x16, 0x06, 0x94}}
|
||||
class WebGLExtensionLoseContext :
|
||||
public nsIWebGLExtensionLoseContext,
|
||||
public WebGLExtension
|
||||
{
|
||||
public:
|
||||
WebGLExtensionLoseContext(WebGLContext*);
|
||||
virtual ~WebGLExtensionLoseContext();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIWEBGLEXTENSIONLOSECONTEXT
|
||||
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(WEBGLEXTENSIONLOSECONTEXT_PRIVATE_IID)
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(WebGLExtensionLoseContext, WEBGLACTIVEINFO_PRIVATE_IID)
|
||||
|
||||
#define WEBGLEXTENSIONSTANDARDDERIVATIVES_PRIVATE_IID \
|
||||
{0x3de3dfd9, 0x864a, 0x4e4c, {0x98, 0x9b, 0x29, 0x77, 0xea, 0xa8, 0x0b, 0x7b}}
|
||||
class WebGLExtensionStandardDerivatives :
|
||||
|
|
|
@ -45,21 +45,27 @@
|
|||
|
||||
#include "WebGLContext.h"
|
||||
|
||||
#if defined _MSC_VER
|
||||
#define FORCE_INLINE __forceinline
|
||||
#elif defined __GNUC__
|
||||
#define FORCE_INLINE __attribute__((always_inline)) inline
|
||||
#else
|
||||
#define FORCE_INLINE inline
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
typedef PRUint8 uint8_t;
|
||||
typedef PRUint16 uint16_t;
|
||||
|
||||
namespace { // this is only included by WebGLContextGL.cpp anyway
|
||||
|
||||
namespace WebGLTexelConversions {
|
||||
|
||||
/****** BEGIN CODE TAKEN FROM WEBKIT ******/
|
||||
/****** BEGIN CODE SHARED WITH WEBKIT ******/
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Pixel unpacking routines.
|
||||
|
||||
void unpackRGBA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
FORCE_INLINE void unpackRGBA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
{
|
||||
destination[0] = source[0];
|
||||
destination[1] = source[1];
|
||||
|
@ -67,7 +73,7 @@ void unpackRGBA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict de
|
|||
destination[3] = source[3];
|
||||
}
|
||||
|
||||
void unpackRGB8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
FORCE_INLINE void unpackRGB8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
{
|
||||
destination[0] = source[0];
|
||||
destination[1] = source[1];
|
||||
|
@ -75,7 +81,7 @@ void unpackRGB8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict des
|
|||
destination[3] = 0xFF;
|
||||
}
|
||||
|
||||
void unpackBGRA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
FORCE_INLINE void unpackBGRA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
{
|
||||
destination[0] = source[2];
|
||||
destination[1] = source[1];
|
||||
|
@ -83,7 +89,7 @@ void unpackBGRA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict de
|
|||
destination[3] = source[3];
|
||||
}
|
||||
|
||||
void unpackBGR8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
FORCE_INLINE void unpackBGR8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
{
|
||||
destination[0] = source[2];
|
||||
destination[1] = source[1];
|
||||
|
@ -91,7 +97,7 @@ void unpackBGR8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict des
|
|||
destination[3] = 0xFF;
|
||||
}
|
||||
|
||||
void unpackRGBA5551ToRGBA8(const uint16_t* __restrict source, uint8_t* __restrict destination)
|
||||
FORCE_INLINE void unpackRGBA5551ToRGBA8(const uint16_t* __restrict source, uint8_t* __restrict destination)
|
||||
{
|
||||
uint16_t packedValue = source[0];
|
||||
uint8_t r = packedValue >> 11;
|
||||
|
@ -103,7 +109,7 @@ void unpackRGBA5551ToRGBA8(const uint16_t* __restrict source, uint8_t* __restric
|
|||
destination[3] = (packedValue & 0x1) ? 0xFF : 0x0;
|
||||
}
|
||||
|
||||
void unpackRGBA4444ToRGBA8(const uint16_t* __restrict source, uint8_t* __restrict destination)
|
||||
FORCE_INLINE void unpackRGBA4444ToRGBA8(const uint16_t* __restrict source, uint8_t* __restrict destination)
|
||||
{
|
||||
uint16_t packedValue = source[0];
|
||||
uint8_t r = packedValue >> 12;
|
||||
|
@ -116,7 +122,7 @@ void unpackRGBA4444ToRGBA8(const uint16_t* __restrict source, uint8_t* __restric
|
|||
destination[3] = a << 4 | a;
|
||||
}
|
||||
|
||||
void unpackRGB565ToRGBA8(const uint16_t* __restrict source, uint8_t* __restrict destination)
|
||||
FORCE_INLINE void unpackRGB565ToRGBA8(const uint16_t* __restrict source, uint8_t* __restrict destination)
|
||||
{
|
||||
uint16_t packedValue = source[0];
|
||||
uint8_t r = packedValue >> 11;
|
||||
|
@ -128,7 +134,7 @@ void unpackRGB565ToRGBA8(const uint16_t* __restrict source, uint8_t* __restrict
|
|||
destination[3] = 0xFF;
|
||||
}
|
||||
|
||||
void unpackR8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
FORCE_INLINE void unpackR8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
{
|
||||
destination[0] = source[0];
|
||||
destination[1] = source[0];
|
||||
|
@ -136,7 +142,7 @@ void unpackR8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict desti
|
|||
destination[3] = 0xFF;
|
||||
}
|
||||
|
||||
void unpackRA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
FORCE_INLINE void unpackRA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
{
|
||||
destination[0] = source[0];
|
||||
destination[1] = source[0];
|
||||
|
@ -144,7 +150,7 @@ void unpackRA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict dest
|
|||
destination[3] = source[1];
|
||||
}
|
||||
|
||||
void unpackA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
FORCE_INLINE void unpackA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
{
|
||||
destination[0] = 0x0;
|
||||
destination[1] = 0x0;
|
||||
|
@ -152,7 +158,7 @@ void unpackA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict desti
|
|||
destination[3] = source[0];
|
||||
}
|
||||
|
||||
void unpackRGB32FToRGBA32F(const float* __restrict source, float* __restrict destination)
|
||||
FORCE_INLINE void unpackRGB32FToRGBA32F(const float* __restrict source, float* __restrict destination)
|
||||
{
|
||||
destination[0] = source[0];
|
||||
destination[1] = source[1];
|
||||
|
@ -160,7 +166,7 @@ void unpackRGB32FToRGBA32F(const float* __restrict source, float* __restrict des
|
|||
destination[3] = 1;
|
||||
}
|
||||
|
||||
void unpackR32FToRGBA32F(const float* __restrict source, float* __restrict destination)
|
||||
FORCE_INLINE void unpackR32FToRGBA32F(const float* __restrict source, float* __restrict destination)
|
||||
{
|
||||
destination[0] = source[0];
|
||||
destination[1] = source[0];
|
||||
|
@ -168,7 +174,7 @@ void unpackR32FToRGBA32F(const float* __restrict source, float* __restrict desti
|
|||
destination[3] = 1;
|
||||
}
|
||||
|
||||
void unpackRA32FToRGBA32F(const float* __restrict source, float* __restrict destination)
|
||||
FORCE_INLINE void unpackRA32FToRGBA32F(const float* __restrict source, float* __restrict destination)
|
||||
{
|
||||
destination[0] = source[0];
|
||||
destination[1] = source[0];
|
||||
|
@ -176,7 +182,7 @@ void unpackRA32FToRGBA32F(const float* __restrict source, float* __restrict dest
|
|||
destination[3] = source[1];
|
||||
}
|
||||
|
||||
void unpackA32FToRGBA32F(const float* __restrict source, float* __restrict destination)
|
||||
FORCE_INLINE void unpackA32FToRGBA32F(const float* __restrict source, float* __restrict destination)
|
||||
{
|
||||
destination[0] = 0;
|
||||
destination[1] = 0;
|
||||
|
@ -188,17 +194,17 @@ void unpackA32FToRGBA32F(const float* __restrict source, float* __restrict desti
|
|||
// Pixel packing routines.
|
||||
//
|
||||
|
||||
void packRGBA8ToA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
FORCE_INLINE void packRGBA8ToA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
{
|
||||
destination[0] = source[3];
|
||||
}
|
||||
|
||||
void packRGBA8ToR8(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
FORCE_INLINE void packRGBA8ToR8(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
{
|
||||
destination[0] = source[0];
|
||||
}
|
||||
|
||||
void packRGBA8ToR8Premultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
FORCE_INLINE void packRGBA8ToR8Premultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
{
|
||||
float scaleFactor = source[3] / 255.0f;
|
||||
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
|
||||
|
@ -206,20 +212,20 @@ void packRGBA8ToR8Premultiply(const uint8_t* __restrict source, uint8_t* __restr
|
|||
}
|
||||
|
||||
// FIXME: this routine is lossy and must be removed.
|
||||
void packRGBA8ToR8Unmultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
FORCE_INLINE void packRGBA8ToR8Unmultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
{
|
||||
float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
|
||||
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
|
||||
destination[0] = sourceR;
|
||||
}
|
||||
|
||||
void packRGBA8ToRA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
FORCE_INLINE void packRGBA8ToRA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
{
|
||||
destination[0] = source[0];
|
||||
destination[1] = source[3];
|
||||
}
|
||||
|
||||
void packRGBA8ToRA8Premultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
FORCE_INLINE void packRGBA8ToRA8Premultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
{
|
||||
float scaleFactor = source[3] / 255.0f;
|
||||
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
|
||||
|
@ -228,7 +234,7 @@ void packRGBA8ToRA8Premultiply(const uint8_t* __restrict source, uint8_t* __rest
|
|||
}
|
||||
|
||||
// FIXME: this routine is lossy and must be removed.
|
||||
void packRGBA8ToRA8Unmultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
FORCE_INLINE void packRGBA8ToRA8Unmultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
{
|
||||
float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
|
||||
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
|
||||
|
@ -236,14 +242,14 @@ void packRGBA8ToRA8Unmultiply(const uint8_t* __restrict source, uint8_t* __restr
|
|||
destination[1] = source[3];
|
||||
}
|
||||
|
||||
void packRGBA8ToRGB8(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
FORCE_INLINE void packRGBA8ToRGB8(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
{
|
||||
destination[0] = source[0];
|
||||
destination[1] = source[1];
|
||||
destination[2] = source[2];
|
||||
}
|
||||
|
||||
void packRGBA8ToRGB8Premultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
FORCE_INLINE void packRGBA8ToRGB8Premultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
{
|
||||
float scaleFactor = source[3] / 255.0f;
|
||||
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
|
||||
|
@ -255,7 +261,7 @@ void packRGBA8ToRGB8Premultiply(const uint8_t* __restrict source, uint8_t* __res
|
|||
}
|
||||
|
||||
// FIXME: this routine is lossy and must be removed.
|
||||
void packRGBA8ToRGB8Unmultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
FORCE_INLINE void packRGBA8ToRGB8Unmultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
{
|
||||
float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
|
||||
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
|
||||
|
@ -267,7 +273,7 @@ void packRGBA8ToRGB8Unmultiply(const uint8_t* __restrict source, uint8_t* __rest
|
|||
}
|
||||
|
||||
// This is only used when the source format is different than kSourceFormatRGBA8.
|
||||
void packRGBA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
FORCE_INLINE void packRGBA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
{
|
||||
destination[0] = source[0];
|
||||
destination[1] = source[1];
|
||||
|
@ -275,7 +281,7 @@ void packRGBA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict dest
|
|||
destination[3] = source[3];
|
||||
}
|
||||
|
||||
void packRGBA8ToRGBA8Premultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
FORCE_INLINE void packRGBA8ToRGBA8Premultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
{
|
||||
float scaleFactor = source[3] / 255.0f;
|
||||
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
|
||||
|
@ -288,7 +294,7 @@ void packRGBA8ToRGBA8Premultiply(const uint8_t* __restrict source, uint8_t* __re
|
|||
}
|
||||
|
||||
// FIXME: this routine is lossy and must be removed.
|
||||
void packRGBA8ToRGBA8Unmultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
FORCE_INLINE void packRGBA8ToRGBA8Unmultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
|
||||
{
|
||||
float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
|
||||
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
|
||||
|
@ -300,7 +306,7 @@ void packRGBA8ToRGBA8Unmultiply(const uint8_t* __restrict source, uint8_t* __res
|
|||
destination[3] = source[3];
|
||||
}
|
||||
|
||||
void packRGBA8ToUnsignedShort4444(const uint8_t* __restrict source, uint16_t* __restrict destination)
|
||||
FORCE_INLINE void packRGBA8ToUnsignedShort4444(const uint8_t* __restrict source, uint16_t* __restrict destination)
|
||||
{
|
||||
*destination = (((source[0] & 0xF0) << 8)
|
||||
| ((source[1] & 0xF0) << 4)
|
||||
|
@ -308,7 +314,7 @@ void packRGBA8ToUnsignedShort4444(const uint8_t* __restrict source, uint16_t* __
|
|||
| (source[3] >> 4));
|
||||
}
|
||||
|
||||
void packRGBA8ToUnsignedShort4444Premultiply(const uint8_t* __restrict source, uint16_t* __restrict destination)
|
||||
FORCE_INLINE void packRGBA8ToUnsignedShort4444Premultiply(const uint8_t* __restrict source, uint16_t* __restrict destination)
|
||||
{
|
||||
float scaleFactor = source[3] / 255.0f;
|
||||
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
|
||||
|
@ -321,7 +327,7 @@ void packRGBA8ToUnsignedShort4444Premultiply(const uint8_t* __restrict source, u
|
|||
}
|
||||
|
||||
// FIXME: this routine is lossy and must be removed.
|
||||
void packRGBA8ToUnsignedShort4444Unmultiply(const uint8_t* __restrict source, uint16_t* __restrict destination)
|
||||
FORCE_INLINE void packRGBA8ToUnsignedShort4444Unmultiply(const uint8_t* __restrict source, uint16_t* __restrict destination)
|
||||
{
|
||||
float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
|
||||
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
|
||||
|
@ -333,7 +339,7 @@ void packRGBA8ToUnsignedShort4444Unmultiply(const uint8_t* __restrict source, ui
|
|||
| (source[3] >> 4));
|
||||
}
|
||||
|
||||
void packRGBA8ToUnsignedShort5551(const uint8_t* __restrict source, uint16_t* __restrict destination)
|
||||
FORCE_INLINE void packRGBA8ToUnsignedShort5551(const uint8_t* __restrict source, uint16_t* __restrict destination)
|
||||
{
|
||||
*destination = (((source[0] & 0xF8) << 8)
|
||||
| ((source[1] & 0xF8) << 3)
|
||||
|
@ -341,7 +347,7 @@ void packRGBA8ToUnsignedShort5551(const uint8_t* __restrict source, uint16_t* __
|
|||
| (source[3] >> 7));
|
||||
}
|
||||
|
||||
void packRGBA8ToUnsignedShort5551Premultiply(const uint8_t* __restrict source, uint16_t* __restrict destination)
|
||||
FORCE_INLINE void packRGBA8ToUnsignedShort5551Premultiply(const uint8_t* __restrict source, uint16_t* __restrict destination)
|
||||
{
|
||||
float scaleFactor = source[3] / 255.0f;
|
||||
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
|
||||
|
@ -354,7 +360,7 @@ void packRGBA8ToUnsignedShort5551Premultiply(const uint8_t* __restrict source, u
|
|||
}
|
||||
|
||||
// FIXME: this routine is lossy and must be removed.
|
||||
void packRGBA8ToUnsignedShort5551Unmultiply(const uint8_t* __restrict source, uint16_t* __restrict destination)
|
||||
FORCE_INLINE void packRGBA8ToUnsignedShort5551Unmultiply(const uint8_t* __restrict source, uint16_t* __restrict destination)
|
||||
{
|
||||
float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
|
||||
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
|
||||
|
@ -366,14 +372,14 @@ void packRGBA8ToUnsignedShort5551Unmultiply(const uint8_t* __restrict source, ui
|
|||
| (source[3] >> 7));
|
||||
}
|
||||
|
||||
void packRGBA8ToUnsignedShort565(const uint8_t* __restrict source, uint16_t* __restrict destination)
|
||||
FORCE_INLINE void packRGBA8ToUnsignedShort565(const uint8_t* __restrict source, uint16_t* __restrict destination)
|
||||
{
|
||||
*destination = (((source[0] & 0xF8) << 8)
|
||||
| ((source[1] & 0xFC) << 3)
|
||||
| ((source[2] & 0xF8) >> 3));
|
||||
}
|
||||
|
||||
void packRGBA8ToUnsignedShort565Premultiply(const uint8_t* __restrict source, uint16_t* __restrict destination)
|
||||
FORCE_INLINE void packRGBA8ToUnsignedShort565Premultiply(const uint8_t* __restrict source, uint16_t* __restrict destination)
|
||||
{
|
||||
float scaleFactor = source[3] / 255.0f;
|
||||
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
|
||||
|
@ -385,7 +391,7 @@ void packRGBA8ToUnsignedShort565Premultiply(const uint8_t* __restrict source, ui
|
|||
}
|
||||
|
||||
// FIXME: this routine is lossy and must be removed.
|
||||
void packRGBA8ToUnsignedShort565Unmultiply(const uint8_t* __restrict source, uint16_t* __restrict destination)
|
||||
FORCE_INLINE void packRGBA8ToUnsignedShort565Unmultiply(const uint8_t* __restrict source, uint16_t* __restrict destination)
|
||||
{
|
||||
float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
|
||||
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
|
||||
|
@ -396,14 +402,14 @@ void packRGBA8ToUnsignedShort565Unmultiply(const uint8_t* __restrict source, uin
|
|||
| ((sourceB & 0xF8) >> 3));
|
||||
}
|
||||
|
||||
void packRGBA32FToRGB32F(const float* __restrict source, float* __restrict destination)
|
||||
FORCE_INLINE void packRGBA32FToRGB32F(const float* __restrict source, float* __restrict destination)
|
||||
{
|
||||
destination[0] = source[0];
|
||||
destination[1] = source[1];
|
||||
destination[2] = source[2];
|
||||
}
|
||||
|
||||
void packRGBA32FToRGB32FPremultiply(const float* __restrict source, float* __restrict destination)
|
||||
FORCE_INLINE void packRGBA32FToRGB32FPremultiply(const float* __restrict source, float* __restrict destination)
|
||||
{
|
||||
float scaleFactor = source[3];
|
||||
destination[0] = source[0] * scaleFactor;
|
||||
|
@ -411,7 +417,7 @@ void packRGBA32FToRGB32FPremultiply(const float* __restrict source, float* __res
|
|||
destination[2] = source[2] * scaleFactor;
|
||||
}
|
||||
|
||||
void packRGBA32FToRGBA32FPremultiply(const float* __restrict source, float* __restrict destination)
|
||||
FORCE_INLINE void packRGBA32FToRGBA32FPremultiply(const float* __restrict source, float* __restrict destination)
|
||||
{
|
||||
float scaleFactor = source[3];
|
||||
destination[0] = source[0] * scaleFactor;
|
||||
|
@ -420,48 +426,46 @@ void packRGBA32FToRGBA32FPremultiply(const float* __restrict source, float* __re
|
|||
destination[3] = source[3];
|
||||
}
|
||||
|
||||
void packRGBA32FToA32F(const float* __restrict source, float* __restrict destination)
|
||||
FORCE_INLINE void packRGBA32FToA32F(const float* __restrict source, float* __restrict destination)
|
||||
{
|
||||
destination[0] = source[3];
|
||||
}
|
||||
|
||||
// identical to above, to avoid special-casing
|
||||
void packRGBA32FToA32FPremultiply(const float* __restrict source, float* __restrict destination)
|
||||
FORCE_INLINE void packRGBA32FToA32FPremultiply(const float* __restrict source, float* __restrict destination)
|
||||
{
|
||||
destination[0] = source[3];
|
||||
}
|
||||
|
||||
void packRGBA32FToR32F(const float* __restrict source, float* __restrict destination)
|
||||
FORCE_INLINE void packRGBA32FToR32F(const float* __restrict source, float* __restrict destination)
|
||||
{
|
||||
destination[0] = source[0];
|
||||
}
|
||||
|
||||
void packRGBA32FToR32FPremultiply(const float* __restrict source, float* __restrict destination)
|
||||
FORCE_INLINE void packRGBA32FToR32FPremultiply(const float* __restrict source, float* __restrict destination)
|
||||
{
|
||||
float scaleFactor = source[3];
|
||||
destination[0] = source[0] * scaleFactor;
|
||||
}
|
||||
|
||||
|
||||
void packRGBA32FToRA32F(const float* __restrict source, float* __restrict destination)
|
||||
FORCE_INLINE void packRGBA32FToRA32F(const float* __restrict source, float* __restrict destination)
|
||||
{
|
||||
destination[0] = source[0];
|
||||
destination[1] = source[3];
|
||||
}
|
||||
|
||||
void packRGBA32FToRA32FPremultiply(const float* __restrict source, float* __restrict destination)
|
||||
FORCE_INLINE void packRGBA32FToRA32FPremultiply(const float* __restrict source, float* __restrict destination)
|
||||
{
|
||||
float scaleFactor = source[3];
|
||||
destination[0] = source[0] * scaleFactor;
|
||||
destination[1] = scaleFactor;
|
||||
}
|
||||
|
||||
/****** END CODE TAKEN FROM WEBKIT ******/
|
||||
/****** END CODE SHARED WITH WEBKIT ******/
|
||||
|
||||
} // end namespace WebGLTexelConversions
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
} // end namespace mozilla
|
||||
|
||||
#endif // WEBGLTEXELCONVERSIONS_H_
|
||||
|
|
|
@ -1442,10 +1442,7 @@ IsAccessKeyTarget(nsIContent* aContent, nsIFrame* aFrame, nsAString& aKey)
|
|||
if (aFrame->IsFocusable())
|
||||
return true;
|
||||
|
||||
if (!aFrame->GetStyleVisibility()->IsVisible())
|
||||
return false;
|
||||
|
||||
if (!aFrame->AreAncestorViewsVisible())
|
||||
if (!aFrame->IsVisibleConsideringAncestors())
|
||||
return false;
|
||||
|
||||
// XUL controls can be activated.
|
||||
|
|
|
@ -282,6 +282,17 @@ nsHTMLSharedObjectElement::BindToTree(nsIDocument *aDocument,
|
|||
nsContentUtils::AddScriptRunner(NS_NewRunnableMethod(this, start));
|
||||
}
|
||||
|
||||
#ifndef XP_MACOSX
|
||||
if (aDocument &&
|
||||
aDocument->IsFullScreenDoc() &&
|
||||
nsContentUtils::HasPluginWithUncontrolledEventDispatch(this)) {
|
||||
// This content contains a windowed plugin for which we don't control
|
||||
// event dispatch, and we're in full-screen mode. Exit full-screen mode
|
||||
// to prevent phishing attacks.
|
||||
NS_DispatchToCurrentThread(
|
||||
NS_NewRunnableMethod(aDocument, &nsIDocument::CancelFullScreen));
|
||||
}
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -281,6 +281,7 @@ _TEST_FILES = \
|
|||
file_fullscreen-api.html \
|
||||
file_fullscreen-api-keys.html \
|
||||
test_fullscreen-api.html \
|
||||
file_fullscreen-plugins.html \
|
||||
test_li_attributes_reflection.html \
|
||||
test_ol_attributes_reflection.html \
|
||||
test_bug651956.html \
|
||||
|
|
|
@ -0,0 +1,180 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=545812
|
||||
|
||||
Test plugins with DOM full-screen API:
|
||||
* Presence of plugins has no effect on request for full-screen on MacOS.
|
||||
* Request for full-screen is denied when windowed plugin in current doc is present.
|
||||
* Request for full-screen is denied when windowed plugin in subdocument is present.
|
||||
* Request for full-screen is not denied when the only plugin present is windowless.
|
||||
* Adding an existing (out-of-doc) windowed plugin to a full-screen document causes document to exit full-screen.
|
||||
* Create windowed plugin and adding it to full-screen document caused exit from full-screen.
|
||||
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 545812</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<style>
|
||||
body:-moz-full-screen, div:-moz-full-screen {
|
||||
background-color: red;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body onload="scheduleTest();">
|
||||
|
||||
<!-- Windowed plugin, should prevent first full-screen request. -->
|
||||
<embed id="windowed-plugin" type="application/x-test" style="width:200px;height:100px;" wmode="window"></embed>
|
||||
|
||||
<!-- Windowless plugin, should not prevent full-screen requests. -->
|
||||
<embed type="application/x-test" style="width:200px;height:100px;"></embed>
|
||||
|
||||
|
||||
<!-- iframe contents:
|
||||
|
||||
<html><body><embed id='windowed-plugin' type='application/x-test' style='width:200px;height:100px;' wmode='window'></embed></body></html>
|
||||
|
||||
-->
|
||||
|
||||
<iframe id="subdoc-plugin" src="data:text/html;charset=utf-8,<html><body><embed id%3D'windowed-plugin' type%3D'application%2Fx-test' style%3D'width%3A200px%3Bheight%3A100px%3B' wmode%3D'window'><%2Fembed><%2Fbody><%2Fhtml>%0D%0A"></iframe>
|
||||
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 545812 **/
|
||||
|
||||
function ok(condition, msg) {
|
||||
opener.ok(condition, msg);
|
||||
}
|
||||
|
||||
function is(a, b, msg) {
|
||||
opener.is(a, b, msg);
|
||||
}
|
||||
|
||||
const isMacOs = navigator.appVersion.indexOf("Macintosh") != -1;
|
||||
|
||||
document.addEventListener("mozfullscreenchange", isMacOs ? macFullScreenChange : fullScreenChange, false);
|
||||
|
||||
var windowedPlugin = null;
|
||||
|
||||
function scheduleTest() {
|
||||
// Delay test startup long enough for the windowed plugin in the subframe to
|
||||
// start up and create its window.
|
||||
opener.SimpleTest.executeSoon(function() {
|
||||
opener.SimpleTest.executeSoon(function() {
|
||||
startTest();
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
function startTest() {
|
||||
ok(!document.mozFullScreen, "Should not be in full-screen mode initially");
|
||||
document.body.mozRequestFullScreen();
|
||||
|
||||
if (isMacOs) {
|
||||
// Running on MacOS, all plugins are effectively windowless, request for full-screen should be granted.
|
||||
// Continue test in the (mac-specific) "mozfullscreenchange" handler.
|
||||
return;
|
||||
}
|
||||
|
||||
ok(!document.mozFullScreen, "Request for full-screen from a document containing windowed plugin should be denied.");
|
||||
|
||||
// Remove plugin in this document. Should still be a windowed plugin in sub-document.
|
||||
windowedPlugin = document.getElementById("windowed-plugin");
|
||||
windowedPlugin.parentNode.removeChild(windowedPlugin);
|
||||
|
||||
document.body.mozRequestFullScreen();
|
||||
ok(!document.mozFullScreen, "Request for full-screen from a document with subdocument containing windowed plugin should be denied.");
|
||||
// Remove subdoc which contains windowed plugin, request full-screen, request should be granted.
|
||||
// Continue test in "mozfullscreenchange" handler.
|
||||
var f = document.getElementById("subdoc-plugin");
|
||||
f.parentNode.removeChild(f);
|
||||
document.body.mozRequestFullScreen();
|
||||
}
|
||||
|
||||
var fullScreenChangeCount = 0;
|
||||
|
||||
function createWindowedPlugin() {
|
||||
var p = document.createElement("embed");
|
||||
p.setAttribute("type", "application/x-test");
|
||||
p.setAttribute("wmode", "window");
|
||||
return p;
|
||||
}
|
||||
|
||||
function macFullScreenChange(event) {
|
||||
switch (fullScreenChangeCount) {
|
||||
case 0: {
|
||||
ok(document.mozFullScreen, "Requests for full-screen on pages with plugins should be granted on MacOS");
|
||||
|
||||
// Create a new windowed plugin, and add that to the document. Should *not* exit full-screen mode on MacOS.
|
||||
windowedPlugin = createWindowedPlugin();
|
||||
document.body.appendChild(windowedPlugin);
|
||||
|
||||
setTimeout(
|
||||
function() {
|
||||
ok(document.mozFullScreen, "Adding windowed plugin to document should not cause full-screen to exit on MacOS.");
|
||||
document.mozCancelFullScreen();
|
||||
}, 0);
|
||||
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
ok(!document.mozFullScreen, "Should have left full-screen mode after calling document.mozCancelFullScreen().");
|
||||
opener.pluginTestFinished();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
ok(false, "Should not receive any more fullscreenchange events!");
|
||||
}
|
||||
}
|
||||
fullScreenChangeCount++;
|
||||
}
|
||||
|
||||
function fullScreenChange(event) {
|
||||
switch (fullScreenChangeCount) {
|
||||
case 0: {
|
||||
ok(document.mozFullScreen, "Request for full-screen with document containing windowless plugin should be granted");
|
||||
// Add windowed plugin to document, should cause full-screen mode to exit.
|
||||
document.body.appendChild(windowedPlugin);
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
ok(!document.mozFullScreen, "Should have left full-screen mode after re-adding windowed plugin to document");
|
||||
windowedPlugin.parentNode.removeChild(windowedPlugin);
|
||||
document.body.mozRequestFullScreen();
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
ok(document.mozFullScreen, "Should have reentered full-screen mode");
|
||||
// Create a new windowed plugin, and add that to the document. Should exit full-screen mode.
|
||||
windowedPlugin = createWindowedPlugin();
|
||||
document.body.appendChild(windowedPlugin);
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
ok(!document.mozFullScreen, "Should have left full-screen mode after adding windowed plugin created after going full-screen to document");
|
||||
windowedPlugin.parentNode.removeChild(windowedPlugin);
|
||||
windowedPlugin = createWindowedPlugin();
|
||||
document.body.mozRequestFullScreen();
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
ok(document.mozFullScreen, "Should have (again) reentered full-screen mode");
|
||||
document.body.appendChild(windowedPlugin);
|
||||
break;
|
||||
}
|
||||
case 5: {
|
||||
ok(!document.mozFullScreen, "Should have left full-screen mode after adding windowed plugin created before going full-screen to document");
|
||||
opener.pluginTestFinished();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
ok(false, "Should not receive any more fullscreenchange events!");
|
||||
}
|
||||
}
|
||||
fullScreenChangeCount++;
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -86,6 +86,11 @@ function apiTestFinished() {
|
|||
}
|
||||
|
||||
function keysTestFinished() {
|
||||
testWindow.close();
|
||||
testWindow = window.open("file_fullscreen-plugins.html", "", "width=500,height=500");
|
||||
}
|
||||
|
||||
function pluginTestFinished() {
|
||||
testWindow.close();
|
||||
SpecialPowers.setBoolPref("full-screen-api.enabled", prevEnabled);
|
||||
SpecialPowers.setBoolPref("full-screen-api.allow-trusted-requests-only", prevTrusted);
|
||||
|
|
|
@ -656,14 +656,7 @@ nsXULElement::PerformAccesskey(bool aKeyCausesActivation,
|
|||
}
|
||||
|
||||
nsIFrame* frame = content->GetPrimaryFrame();
|
||||
if (!frame)
|
||||
return;
|
||||
|
||||
const nsStyleVisibility* vis = frame->GetStyleVisibility();
|
||||
|
||||
if (vis->mVisible == NS_STYLE_VISIBILITY_COLLAPSE ||
|
||||
vis->mVisible == NS_STYLE_VISIBILITY_HIDDEN ||
|
||||
!frame->AreAncestorViewsVisible())
|
||||
if (!frame || !frame->IsVisibleConsideringAncestors())
|
||||
return;
|
||||
|
||||
nsXULElement* elm = FromContent(content);
|
||||
|
|
|
@ -4821,8 +4821,11 @@ nsDocShell::GetVisibility(bool * aVisibility)
|
|||
nsIFrame* frame = shellContent ? shellContent->GetPrimaryFrame() : nsnull;
|
||||
bool isDocShellOffScreen = false;
|
||||
docShell->GetIsOffScreenBrowser(&isDocShellOffScreen);
|
||||
if (frame && !frame->AreAncestorViewsVisible() && !isDocShellOffScreen)
|
||||
if (frame &&
|
||||
!frame->IsVisibleConsideringAncestors(nsIFrame::VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY) &&
|
||||
!isDocShellOffScreen) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
treeItem = parentItem;
|
||||
treeItem->GetParent(getter_AddRefs(parentItem));
|
||||
|
|
|
@ -1450,6 +1450,8 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
|||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(WebGLExtensionStandardDerivatives, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(WebGLExtensionLoseContext, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA(PaintRequest, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
|
@ -3986,6 +3988,10 @@ nsDOMClassInfo::Init()
|
|||
DOM_CLASSINFO_MAP_ENTRY(nsIWebGLExtensionStandardDerivatives)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(WebGLExtensionLoseContext, nsIWebGLExtensionLoseContext)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIWebGLExtensionLoseContext)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(PaintRequest, nsIDOMPaintRequest)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMPaintRequest)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
|
|
@ -472,6 +472,7 @@ DOMCI_CLASS(WebGLUniformLocation)
|
|||
DOMCI_CLASS(WebGLActiveInfo)
|
||||
DOMCI_CLASS(WebGLExtension)
|
||||
DOMCI_CLASS(WebGLExtensionStandardDerivatives)
|
||||
DOMCI_CLASS(WebGLExtensionLoseContext)
|
||||
|
||||
DOMCI_CLASS(PaintRequest)
|
||||
DOMCI_CLASS(PaintRequestList)
|
||||
|
|
|
@ -1442,8 +1442,7 @@ nsFocusManager::CheckIfFocusable(nsIContent* aContent, PRUint32 aFlags)
|
|||
// HTML areas do not have their own frame, and the img frame we get from
|
||||
// GetPrimaryFrame() is not relevant as to whether it is focusable or
|
||||
// not, so we have to do all the relevant checks manually for them.
|
||||
return frame->AreAncestorViewsVisible() &&
|
||||
frame->GetStyleVisibility()->IsVisible() &&
|
||||
return frame->IsVisibleConsideringAncestors() &&
|
||||
aContent->IsFocusable() ? aContent : nsnull;
|
||||
}
|
||||
|
||||
|
|
|
@ -153,6 +153,12 @@ interface nsIWebGLExtensionStandardDerivatives : nsIWebGLExtension
|
|||
const WebGLenum FRAGMENT_SHADER_DERIVATIVE_HINT_OES = 0x8B8B;
|
||||
};
|
||||
|
||||
[scriptable, uuid(b0afc2eb-0895-4509-98de-5c383d160694)]
|
||||
interface nsIWebGLExtensionLoseContext : nsIWebGLExtension
|
||||
{
|
||||
void loseContext();
|
||||
void restoreContext();
|
||||
};
|
||||
|
||||
[scriptable, builtinclass, uuid(ef15ae85-4670-4dc4-848d-51ca81e8397a)]
|
||||
interface nsIDOMWebGLRenderingContext : nsISupports
|
||||
|
|
|
@ -3277,7 +3277,13 @@ NS_IMETHODIMP nsPluginInstanceOwner::CreateWidget(void)
|
|||
if (!mWidget) {
|
||||
bool windowless = false;
|
||||
mInstance->IsWindowless(&windowless);
|
||||
|
||||
nsIDocument *doc = mContent ? mContent->OwnerDoc() : nsnull;
|
||||
#ifndef XP_MACOSX
|
||||
if (!windowless && doc && doc->IsFullScreenDoc()) {
|
||||
NS_DispatchToCurrentThread(
|
||||
NS_NewRunnableMethod(doc, &nsIDocument::CancelFullScreen));
|
||||
}
|
||||
#endif
|
||||
// always create widgets in Twips, not pixels
|
||||
nsPresContext* context = mObjectFrame->PresContext();
|
||||
rv = mObjectFrame->CreateWidget(context->DevPixelsToAppUnits(mPluginWindow->width),
|
||||
|
|
|
@ -1111,7 +1111,7 @@ BasicCanvasLayer::UpdateSurface(gfxASurface* aDestSurface)
|
|||
mGLContext->MakeCurrent();
|
||||
|
||||
#if defined (MOZ_X11) && defined (MOZ_EGL_XRENDER_COMPOSITE)
|
||||
mGLContext->Finish();
|
||||
mGLContext->fFinish();
|
||||
gfxASurface* offscreenSurface = mGLContext->GetOffscreenPixmapSurface();
|
||||
|
||||
// XRender can only blend premuliplied alpha, so only allow xrender
|
||||
|
|
|
@ -174,6 +174,8 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
|
|||
return true;
|
||||
}
|
||||
|
||||
mHasRobustness = IsExtensionSupported(ARB_robustness);
|
||||
|
||||
SymLoadStruct symbols[] = {
|
||||
{ (PRFuncPtr*) &mSymbols.fActiveTexture, { "ActiveTexture", "ActiveTextureARB", NULL } },
|
||||
{ (PRFuncPtr*) &mSymbols.fAttachShader, { "AttachShader", "AttachShaderARB", NULL } },
|
||||
|
@ -325,6 +327,9 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
|
|||
{ mIsGLES2 ? (PRFuncPtr*) NULL : (PRFuncPtr*) &mSymbols.fUnmapBuffer,
|
||||
{ mIsGLES2 ? NULL : "UnmapBuffer", NULL } },
|
||||
|
||||
{ mHasRobustness ? (PRFuncPtr*) &mSymbols.fGetGraphicsResetStatus : (PRFuncPtr*) NULL,
|
||||
{ mHasRobustness ? "GetGraphicsResetStatusARB" : NULL, NULL } },
|
||||
|
||||
{ NULL, { NULL } },
|
||||
|
||||
};
|
||||
|
@ -470,6 +475,7 @@ static const char *sExtensionNames[] = {
|
|||
"GL_EXT_framebuffer_multisample",
|
||||
"GL_ANGLE_framebuffer_multisample",
|
||||
"GL_OES_rgb8_rgba8",
|
||||
"GL_ARB_robustness",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
|
@ -532,7 +532,8 @@ public:
|
|||
GLContext(const ContextFormat& aFormat,
|
||||
bool aIsOffscreen = false,
|
||||
GLContext *aSharedContext = nsnull)
|
||||
: mInitialized(false),
|
||||
: mOffscreenFBOsDirty(false),
|
||||
mInitialized(false),
|
||||
mIsOffscreen(aIsOffscreen),
|
||||
#ifdef USE_GLES2
|
||||
mIsGLES2(true),
|
||||
|
@ -550,7 +551,6 @@ public:
|
|||
mBlitFramebuffer(0),
|
||||
mOffscreenDrawFBO(0),
|
||||
mOffscreenReadFBO(0),
|
||||
mOffscreenFBOsDirty(false),
|
||||
mOffscreenColorRB(0),
|
||||
mOffscreenDepthRB(0),
|
||||
mOffscreenStencilRB(0)
|
||||
|
@ -1242,6 +1242,7 @@ public:
|
|||
EXT_framebuffer_multisample,
|
||||
ANGLE_framebuffer_multisample,
|
||||
OES_rgb8_rgba8,
|
||||
ARB_robustness,
|
||||
Extensions_Max
|
||||
};
|
||||
|
||||
|
@ -1278,11 +1279,24 @@ public:
|
|||
bool values[setlen];
|
||||
};
|
||||
|
||||
/**
|
||||
* Context reset constants.
|
||||
* These are used to determine who is guilty when a context reset
|
||||
* happens.
|
||||
*/
|
||||
enum ContextResetARB {
|
||||
CONTEXT_NO_ERROR = 0,
|
||||
CONTEXT_GUILTY_CONTEXT_RESET_ARB = 0x8253,
|
||||
CONTEXT_INNOCENT_CONTEXT_RESET_ARB = 0x8254,
|
||||
CONTEXT_UNKNOWN_CONTEXT_RESET_ARB = 0x8255,
|
||||
};
|
||||
|
||||
protected:
|
||||
bool mInitialized;
|
||||
bool mIsOffscreen;
|
||||
bool mIsGLES2;
|
||||
bool mIsGlobalSharedContext;
|
||||
bool mHasRobustness;
|
||||
|
||||
PRInt32 mVendor;
|
||||
|
||||
|
@ -2498,6 +2512,14 @@ public:
|
|||
AFTER_GL_CALL;
|
||||
TRACKING_CONTEXT(DeletedRenderbuffers(this, n, names));
|
||||
}
|
||||
|
||||
GLenum GLAPIENTRY fGetGraphicsResetStatus() {
|
||||
BEFORE_GL_CALL;
|
||||
GLenum ret = mHasRobustness ? mSymbols.fGetGraphicsResetStatus() : 0;
|
||||
AFTER_GL_CALL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void THEBES_API CreatedProgram(GLContext *aOrigin, GLuint aName);
|
||||
void THEBES_API CreatedShader(GLContext *aOrigin, GLuint aName);
|
||||
|
|
|
@ -581,8 +581,6 @@ GLContextProviderCGL::CreateOffscreen(const gfxIntSize& aSize,
|
|||
glContext->mOffscreenSize = aSize;
|
||||
glContext->mOffscreenActualSize = aSize;
|
||||
|
||||
printf("GL Offscreen: CGL+PBuffer\n");
|
||||
|
||||
return glContext.forget();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2251,38 +2251,32 @@ GLContextProviderEGL::CreateOffscreen(const gfxIntSize& aSize,
|
|||
if (!sEGLLibrary.EnsureInitialized()) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
ContextFormat actualFormat(aFormat);
|
||||
// actualFormat.samples = 0;
|
||||
|
||||
#if defined(ANDROID) || defined(XP_WIN)
|
||||
nsRefPtr<GLContextEGL> glContext =
|
||||
GLContextEGL::CreateEGLPBufferOffscreenContext(aSize, actualFormat);
|
||||
GLContextEGL::CreateEGLPBufferOffscreenContext(aSize, aFormat);
|
||||
|
||||
if (!glContext)
|
||||
return nsnull;
|
||||
|
||||
if (!glContext->ResizeOffscreenFBO(glContext->OffscreenActualSize(), false))
|
||||
return nsnull;
|
||||
|
||||
printf("GL Offscreen: EGL+PBuffer\n");
|
||||
return glContext.forget();
|
||||
|
||||
return glContext.forget();
|
||||
#elif defined(MOZ_X11) && defined(MOZ_EGL_XRENDER_COMPOSITE)
|
||||
nsRefPtr<GLContextEGL> glContext =
|
||||
GLContextEGL::CreateBasicEGLPixmapOffscreenContext(aSize, actualFormat);
|
||||
GLContextEGL::CreateBasicEGLPixmapOffscreenContext(aSize, aFormat);
|
||||
|
||||
if (!glContext)
|
||||
return nsnull;
|
||||
|
||||
if (!glContext->ResizeOffscreenFBO(glContext->OffscreenActualSize(), true))
|
||||
return nsnull;
|
||||
|
||||
printf("GL Offscreen: EGL+Pixmap\n");
|
||||
|
||||
return glContext.forget();
|
||||
#elif defined(MOZ_X11)
|
||||
nsRefPtr<GLContextEGL> glContext =
|
||||
GLContextEGL::CreateEGLPixmapOffscreenContext(aSize, actualFormat, true);
|
||||
GLContextEGL::CreateEGLPixmapOffscreenContext(aSize, aFormat, true);
|
||||
|
||||
if (!glContext) {
|
||||
return nsnull;
|
||||
|
|
|
@ -183,6 +183,11 @@ GLXLibrary::EnsureInitialized()
|
|||
{ NULL, { NULL } }
|
||||
};
|
||||
|
||||
LibrarySymbolLoader::SymLoadStruct symbols_robustness[] = {
|
||||
{ (PRFuncPtr*) &xCreateContextAttribsInternal, { "glXCreateContextAttribsARB", NULL } },
|
||||
{ NULL, { NULL } }
|
||||
};
|
||||
|
||||
if (!LibrarySymbolLoader::LoadSymbols(mOGLLibrary, &symbols[0])) {
|
||||
NS_WARNING("Couldn't find required entry point in OpenGL shared library");
|
||||
return false;
|
||||
|
@ -251,6 +256,17 @@ GLXLibrary::EnsureInitialized()
|
|||
NS_WARNING("Texture from pixmap disabled");
|
||||
}
|
||||
|
||||
if (HasExtension(extensionsStr, "GL_ARB_robustness")) {
|
||||
if (!LibrarySymbolLoader::LoadSymbols(mOGLLibrary, symbols_robustness)) {
|
||||
// We have no easy way of checking whether or not this extension
|
||||
// exists, so it's best to just try to load it and accept that it
|
||||
// might fail.
|
||||
//NS_WARNING("Couldn't load ARB_robustness symbols");
|
||||
} else {
|
||||
mHasRobustness = true;
|
||||
}
|
||||
}
|
||||
|
||||
gIsATI = serverVendor && DoesVendorStringMatch(serverVendor, "ATI");
|
||||
gIsChromium = (serverVendor &&
|
||||
DoesVendorStringMatch(serverVendor, "Chromium")) ||
|
||||
|
@ -633,6 +649,23 @@ GLXLibrary::xWaitX()
|
|||
AFTER_GLX_CALL;
|
||||
}
|
||||
|
||||
GLXContext
|
||||
GLXLibrary::xCreateContextAttribs(Display* display,
|
||||
GLXFBConfig config,
|
||||
GLXContext share_list,
|
||||
Bool direct,
|
||||
const int* attrib_list)
|
||||
{
|
||||
BEFORE_GLX_CALL;
|
||||
GLXContext result = xCreateContextAttribsInternal(display,
|
||||
config,
|
||||
share_list,
|
||||
direct,
|
||||
attrib_list);
|
||||
AFTER_GLX_CALL;
|
||||
return result;
|
||||
}
|
||||
|
||||
GLXLibrary sGLXLibrary;
|
||||
|
||||
class GLContextGLX : public GLContext
|
||||
|
@ -667,11 +700,25 @@ TRY_AGAIN_NO_SHARING:
|
|||
|
||||
error = false;
|
||||
|
||||
context = sGLXLibrary.xCreateNewContext(display,
|
||||
cfg,
|
||||
GLX_RGBA_TYPE,
|
||||
shareContext ? shareContext->mContext : NULL,
|
||||
True);
|
||||
if (sGLXLibrary.HasRobustness()) {
|
||||
int attrib_list[] = {
|
||||
LOCAL_GL_CONTEXT_FLAGS_ARB, LOCAL_GL_CONTEXT_ROBUST_ACCESS_BIT_ARB,
|
||||
LOCAL_GL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, LOCAL_GL_LOSE_CONTEXT_ON_RESET_ARB,
|
||||
0,
|
||||
};
|
||||
|
||||
context = sGLXLibrary.xCreateContextAttribs(display,
|
||||
cfg,
|
||||
shareContext ? shareContext->mContext : NULL,
|
||||
True,
|
||||
attrib_list);
|
||||
} else {
|
||||
context = sGLXLibrary.xCreateNewContext(display,
|
||||
cfg,
|
||||
GLX_RGBA_TYPE,
|
||||
shareContext ? shareContext->mContext : NULL,
|
||||
True);
|
||||
}
|
||||
|
||||
if (context) {
|
||||
glContext = new GLContextGLX(format,
|
||||
|
@ -1241,11 +1288,8 @@ already_AddRefed<GLContext>
|
|||
GLContextProviderGLX::CreateOffscreen(const gfxIntSize& aSize,
|
||||
const ContextFormat& aFormat)
|
||||
{
|
||||
ContextFormat actualFormat(aFormat);
|
||||
// actualFormat.samples = 0;
|
||||
|
||||
nsRefPtr<GLContextGLX> glContext =
|
||||
CreateOffscreenPixmapContext(aSize, actualFormat, true);
|
||||
CreateOffscreenPixmapContext(aSize, aFormat, true);
|
||||
|
||||
if (!glContext) {
|
||||
return nsnull;
|
||||
|
|
|
@ -650,9 +650,6 @@ GLContextProviderWGL::CreateOffscreen(const gfxIntSize& aSize,
|
|||
return nsnull;
|
||||
}
|
||||
|
||||
ContextFormat actualFormat(aFormat);
|
||||
// actualFormat.samples = 0;
|
||||
|
||||
nsRefPtr<GLContextWGL> glContext;
|
||||
|
||||
// Always try to create a pbuffer context first, because we
|
||||
|
@ -663,12 +660,12 @@ GLContextProviderWGL::CreateOffscreen(const gfxIntSize& aSize,
|
|||
sWGLLibrary.fCreatePbuffer &&
|
||||
sWGLLibrary.fChoosePixelFormat)
|
||||
{
|
||||
glContext = CreatePBufferOffscreenContext(aSize, actualFormat);
|
||||
glContext = CreatePBufferOffscreenContext(aSize, aFormat);
|
||||
}
|
||||
|
||||
// If it failed, then create a window context and use a FBO.
|
||||
if (!glContext) {
|
||||
glContext = CreateWindowOffscreenContext(actualFormat);
|
||||
glContext = CreateWindowOffscreenContext(aFormat);
|
||||
}
|
||||
|
||||
if (!glContext ||
|
||||
|
|
|
@ -373,6 +373,8 @@ struct GLContextSymbols
|
|||
typedef realGLboolean (GLAPIENTRY * PFNGLUNMAPBUFFER) (GLenum target);
|
||||
PFNGLUNMAPBUFFER fUnmapBuffer;
|
||||
|
||||
typedef GLenum (GLAPIENTRY * PFNGLGETGRAPHICSRESETSTATUS) (void);
|
||||
PFNGLGETGRAPHICSRESETSTATUS fGetGraphicsResetStatus;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -178,6 +178,7 @@ typedef ptrdiff_t GLintptr;
|
|||
#define LOCAL_GL_STACK_OVERFLOW 0x0503
|
||||
#define LOCAL_GL_STACK_UNDERFLOW 0x0504
|
||||
#define LOCAL_GL_OUT_OF_MEMORY 0x0505
|
||||
#define LOCAL_GL_CONTEXT_LOST 0x9242
|
||||
#define LOCAL_GL_2D 0x0600
|
||||
#define LOCAL_GL_3D 0x0601
|
||||
#define LOCAL_GL_3D_COLOR 0x0602
|
||||
|
@ -3039,6 +3040,49 @@ typedef ptrdiff_t GLintptr;
|
|||
#define LOCAL_GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125
|
||||
#define LOCAL_GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122
|
||||
|
||||
#define LOCAL_GL_GUILTY_CONTEXT_RESET_ARB 0x8253
|
||||
#define LOCAL_GL_INNOCENT_CONTEXT_RESET_ARB 0x8254
|
||||
#define LOCAL_GL_UNKNOWN_CONTEXT_RESET_ARB 0x8255
|
||||
|
||||
#define LOCAL_GL_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
|
||||
|
||||
#define LOCAL_GL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
|
||||
#define LOCAL_GL_NO_RESET_NOTIFICATION_ARB 0x8261
|
||||
|
||||
#define LOCAL_GL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
|
||||
#define LOCAL_GL_NO_RESET_NOTIFICATION_ARB 0x8261
|
||||
#define LOCAL_GL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
|
||||
|
||||
#define LOCAL_WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
|
||||
#define LOCAL_WGL_NO_RESET_NOTIFICATION_ARB 0x8261
|
||||
#define LOCAL_WGL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
|
||||
|
||||
#define LOCAL_GL_CONTEXT_MAJOR_VERSION_ARB 0x2091
|
||||
#define LOCAL_GL_CONTEXT_MINOR_VERSION_ARB 0x2092
|
||||
#define LOCAL_GL_CONTEXT_LAYER_PLANE_ARB 0x2093
|
||||
#define LOCAL_GL_CONTEXT_FLAGS_ARB 0x2094
|
||||
#define LOCAL_GL_CONTEXT_PROFILE_MASK_ARB 0x9126
|
||||
|
||||
#define LOCAL_WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
|
||||
#define LOCAL_WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
|
||||
#define LOCAL_WGL_CONTEXT_LAYER_PLANE_ARB 0x2093
|
||||
#define LOCAL_WGL_CONTEXT_FLAGS_ARB 0x2094
|
||||
#define LOCAL_WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
|
||||
|
||||
#define LOCAL_GL_CONTEXT_DEBUG_BIT_ARB 0x0001
|
||||
#define LOCAL_GL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
|
||||
|
||||
#define LOCAL_WGL_CONTEXT_DEBUG_BIT_ARB 0x0001
|
||||
#define LOCAL_WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
|
||||
|
||||
#define LOCAL_GL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
|
||||
#define LOCAL_GL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
|
||||
#define LOCAL_GL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
|
||||
|
||||
#define LOCAL_WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
|
||||
#define LOCAL_WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
|
||||
#define LOCAL_WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
|
||||
|
||||
#define LOCAL_WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
|
||||
#define LOCAL_WGL_DRAW_TO_WINDOW_ARB 0x2001
|
||||
#define LOCAL_WGL_DRAW_TO_BITMAP_ARB 0x2002
|
||||
|
|
|
@ -50,7 +50,7 @@ class GLXLibrary
|
|||
public:
|
||||
GLXLibrary() : mInitialized(false), mTriedInitializing(false),
|
||||
mHasTextureFromPixmap(false), mDebug(false),
|
||||
mOGLLibrary(nsnull) {}
|
||||
mHasRobustness(false), mOGLLibrary(nsnull) {}
|
||||
|
||||
void xDestroyContext(Display* display, GLXContext context);
|
||||
Bool xMakeCurrent(Display* display,
|
||||
|
@ -108,6 +108,12 @@ public:
|
|||
void xWaitGL();
|
||||
void xWaitX();
|
||||
|
||||
GLXContext xCreateContextAttribs(Display* display,
|
||||
GLXFBConfig config,
|
||||
GLXContext share_list,
|
||||
Bool direct,
|
||||
const int* attrib_list);
|
||||
|
||||
bool EnsureInitialized();
|
||||
|
||||
GLXPixmap CreatePixmap(gfxASurface* aSurface);
|
||||
|
@ -116,6 +122,7 @@ public:
|
|||
void ReleaseTexImage(GLXPixmap aPixmap);
|
||||
|
||||
bool HasTextureFromPixmap() { return mHasTextureFromPixmap; }
|
||||
bool HasRobustness() { return mHasRobustness; }
|
||||
bool SupportsTextureFromPixmap(gfxASurface* aSurface);
|
||||
|
||||
private:
|
||||
|
@ -209,6 +216,13 @@ private:
|
|||
typedef void (GLAPIENTRY * PFNGLXWAITX) ();
|
||||
PFNGLXWAITGL xWaitXInternal;
|
||||
|
||||
typedef GLXContext (GLAPIENTRY * PFNGLXCREATECONTEXTATTRIBS) (Display *,
|
||||
GLXFBConfig,
|
||||
GLXContext,
|
||||
Bool,
|
||||
const int *);
|
||||
PFNGLXCREATECONTEXTATTRIBS xCreateContextAttribsInternal;
|
||||
|
||||
#ifdef DEBUG
|
||||
void BeforeGLXCall();
|
||||
void AfterGLXCall();
|
||||
|
@ -218,6 +232,7 @@ private:
|
|||
bool mTriedInitializing;
|
||||
bool mHasTextureFromPixmap;
|
||||
bool mDebug;
|
||||
bool mHasRobustness;
|
||||
PRLibrary *mOGLLibrary;
|
||||
};
|
||||
|
||||
|
|
|
@ -43,8 +43,7 @@ namespace JSC {
|
|||
|
||||
class MacroAssemblerARM : public AbstractMacroAssembler<ARMAssembler> {
|
||||
static const int DoubleConditionMask = 0x0f;
|
||||
static const int DoubleConditionBitSpecial = 0x10;
|
||||
COMPILE_ASSERT(!(DoubleConditionBitSpecial & DoubleConditionMask), DoubleConditionBitSpecial_should_not_interfere_with_ARMAssembler_Condition_codes);
|
||||
static const int DoubleConditionBitSpecial = 0x8;
|
||||
public:
|
||||
enum Condition {
|
||||
Equal = ARMAssembler::EQ,
|
||||
|
|
|
@ -2723,6 +2723,11 @@ if test "$ac_cv_header_endian_h" = yes; then
|
|||
AC_DEFINE(JS_HAVE_ENDIAN_H)
|
||||
fi
|
||||
|
||||
AC_CHECK_HEADERS(sys/isa_defs.h)
|
||||
if test "$ac_cv_header_sys_isa_defs_h" = yes; then
|
||||
AC_DEFINE(JS_HAVE_SYS_ISA_DEFS_H)
|
||||
fi
|
||||
|
||||
dnl Check for int16_t, int32_t, int64_t, int64, uint, uint_t, and uint16_t.
|
||||
dnl ========================================================
|
||||
AC_MSG_CHECKING(for int16_t)
|
||||
|
|
|
@ -63,6 +63,10 @@
|
|||
useable. See jscpucfg.h. */
|
||||
#undef JS_HAVE_ENDIAN_H
|
||||
|
||||
/* Define to 1 if the <sys/isa_defs.h> header is present and
|
||||
useable. See jscpucfg.h. */
|
||||
#undef JS_HAVE_SYS_ISA_DEFS_H
|
||||
|
||||
/* Define to 1 if the <sys/types.h> defines int8_t, etc. */
|
||||
#undef JS_SYS_TYPES_H_DEFINES_EXACT_SIZE_TYPES
|
||||
|
||||
|
|
|
@ -92,7 +92,37 @@
|
|||
#error "endian.h does not define __BYTE_ORDER. Cannot determine endianness."
|
||||
#endif
|
||||
|
||||
#else /* !defined(HAVE_ENDIAN_H) */
|
||||
#elif defined(JS_HAVE_SYS_ISA_DEFS_H)
|
||||
#include <sys/isa_defs.h>
|
||||
|
||||
#if defined(_BIG_ENDIAN)
|
||||
#undef IS_LITTLE_ENDIAN
|
||||
#define IS_BIG_ENDIAN 1
|
||||
#elif defined(_LITTLE_ENDIAN)
|
||||
#define IS_LITTLE_ENDIAN 1
|
||||
#undef IS_BIG_ENDIAN
|
||||
#else /* !defined(_LITTLE_ENDIAN) */
|
||||
#error "sys/isa_defs.h does not define _BIG_ENDIAN or _LITTLE_ENDIAN. Cannot determine endianness."
|
||||
#endif
|
||||
#if !defined(JS_STACK_GROWTH_DIRECTION)
|
||||
#if defined(_STACK_GROWS_UPWARD)
|
||||
#define JS_STACK_GROWTH_DIRECTION (1)
|
||||
#elif defined(_STACK_GROWS_DOWNWARD)
|
||||
#define JS_STACK_GROWTH_DIRECTION (-1)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#elif defined(__sparc) || defined(__sparc__) || \
|
||||
defined(_POWER) || defined(__powerpc__) || \
|
||||
defined(__ppc__) || defined(__hppa) || \
|
||||
defined(_MIPSEB) || defined(_BIG_ENDIAN)
|
||||
/* IA64 running HP-UX will have _BIG_ENDIAN defined.
|
||||
* IA64 running Linux will have endian.h and be handled above.
|
||||
*/
|
||||
#undef IS_LITTLE_ENDIAN
|
||||
#define IS_BIG_ENDIAN 1
|
||||
|
||||
#else /* !defined(__sparc) && !defined(__sparc__) && ... */
|
||||
#error "Cannot determine endianness of your platform. Please add support to jscpucfg.h."
|
||||
#endif
|
||||
|
||||
|
|
|
@ -4954,7 +4954,7 @@ MarkIteratorUnknownSlow(JSContext *cx)
|
|||
|
||||
void
|
||||
TypeMonitorCallSlow(JSContext *cx, JSObject *callee,
|
||||
const CallArgs &args, bool constructing)
|
||||
CallArgs &args, bool constructing)
|
||||
{
|
||||
unsigned nargs = callee->getFunctionPrivate()->nargs;
|
||||
JSScript *script = callee->getFunctionPrivate()->script();
|
||||
|
@ -4972,8 +4972,10 @@ TypeMonitorCallSlow(JSContext *cx, JSObject *callee,
|
|||
TypeScript::SetArgument(cx, script, arg, args[arg]);
|
||||
|
||||
/* Watch for fewer actuals than formals to the call. */
|
||||
for (; arg < nargs; arg++)
|
||||
TypeScript::SetArgument(cx, script, arg, UndefinedValue());
|
||||
for (; arg < nargs; arg++) {
|
||||
Value v = UndefinedValue();
|
||||
TypeScript::SetArgument(cx, script, arg, v);
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool
|
||||
|
@ -5091,8 +5093,10 @@ TypeDynamicResult(JSContext *cx, JSScript *script, jsbytecode *pc, Type type)
|
|||
}
|
||||
|
||||
void
|
||||
TypeMonitorResult(JSContext *cx, JSScript *script, jsbytecode *pc, const js::Value &rval)
|
||||
TypeMonitorResult(JSContext *cx, JSScript *script, jsbytecode *pc, js::Value &rval)
|
||||
{
|
||||
TryCoerceNumberToInt32(rval);
|
||||
|
||||
UntrapOpcode untrap(cx, script, pc);
|
||||
|
||||
/* Allow the non-TYPESET scenario to simplify stubs used in compound opcodes. */
|
||||
|
|
|
@ -1077,9 +1077,14 @@ class TypeScript
|
|||
* by type inference or where the pc has type barriers. For simplicity, we
|
||||
* always monitor JOF_TYPESET opcodes in the interpreter and stub calls,
|
||||
* and only look at barriers when generating JIT code for the script.
|
||||
*
|
||||
* 'val' is passed by reference, and must refer to the location of the op's
|
||||
* result which will be subsequently used (i.e. not a temporary value).
|
||||
* This call may change val by coercing a double-representable-as-an-int
|
||||
* into an integer.
|
||||
*/
|
||||
static inline void Monitor(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
const js::Value &val);
|
||||
js::Value &val);
|
||||
|
||||
/* Monitor an assignment at a SETELEM on a non-integer identifier. */
|
||||
static inline void MonitorAssign(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
|
@ -1091,7 +1096,7 @@ class TypeScript
|
|||
static inline void SetLocal(JSContext *cx, JSScript *script, unsigned local, Type type);
|
||||
static inline void SetLocal(JSContext *cx, JSScript *script, unsigned local, const js::Value &value);
|
||||
static inline void SetArgument(JSContext *cx, JSScript *script, unsigned arg, Type type);
|
||||
static inline void SetArgument(JSContext *cx, JSScript *script, unsigned arg, const js::Value &value);
|
||||
static inline void SetArgument(JSContext *cx, JSScript *script, unsigned arg, js::Value &value);
|
||||
|
||||
static void Sweep(JSContext *cx, JSScript *script);
|
||||
inline void trace(JSTracer *trc);
|
||||
|
|
|
@ -310,14 +310,15 @@ MarkIteratorUnknown(JSContext *cx)
|
|||
}
|
||||
|
||||
/*
|
||||
* Monitor a javascript call, either on entry to the interpreter or made
|
||||
* from within the interpreter.
|
||||
* Monitor a javascript call, either on entry to the interpreter or made from
|
||||
* within the interpreter. As with TypeScript::Monitor, this may coerce double
|
||||
* arguments to the call into integers.
|
||||
*/
|
||||
inline void
|
||||
TypeMonitorCall(JSContext *cx, const js::CallArgs &args, bool constructing)
|
||||
TypeMonitorCall(JSContext *cx, js::CallArgs &args, bool constructing)
|
||||
{
|
||||
extern void TypeMonitorCallSlow(JSContext *cx, JSObject *callee,
|
||||
const CallArgs &args, bool constructing);
|
||||
CallArgs &args, bool constructing);
|
||||
|
||||
JSObject *callee = &args.callee();
|
||||
if (callee->isFunction()) {
|
||||
|
@ -444,7 +445,7 @@ FixObjectType(JSContext *cx, JSObject *obj)
|
|||
}
|
||||
|
||||
/* Interface helpers for JSScript */
|
||||
extern void TypeMonitorResult(JSContext *cx, JSScript *script, jsbytecode *pc, const js::Value &rval);
|
||||
extern void TypeMonitorResult(JSContext *cx, JSScript *script, jsbytecode *pc, js::Value &rval);
|
||||
extern void TypeDynamicResult(JSContext *cx, JSScript *script, jsbytecode *pc, js::types::Type type);
|
||||
|
||||
inline bool
|
||||
|
@ -559,7 +560,7 @@ TypeScript::InitObject(JSContext *cx, JSScript *script, const jsbytecode *pc, JS
|
|||
}
|
||||
|
||||
/* static */ inline void
|
||||
TypeScript::Monitor(JSContext *cx, JSScript *script, jsbytecode *pc, const js::Value &rval)
|
||||
TypeScript::Monitor(JSContext *cx, JSScript *script, jsbytecode *pc, js::Value &rval)
|
||||
{
|
||||
if (cx->typeInferenceEnabled())
|
||||
TypeMonitorResult(cx, script, pc, rval);
|
||||
|
@ -677,9 +678,10 @@ TypeScript::SetArgument(JSContext *cx, JSScript *script, unsigned arg, Type type
|
|||
}
|
||||
|
||||
/* static */ inline void
|
||||
TypeScript::SetArgument(JSContext *cx, JSScript *script, unsigned arg, const js::Value &value)
|
||||
TypeScript::SetArgument(JSContext *cx, JSScript *script, unsigned arg, js::Value &value)
|
||||
{
|
||||
if (cx->typeInferenceEnabled()) {
|
||||
TryCoerceNumberToInt32(value);
|
||||
Type type = GetValueType(cx, value);
|
||||
SetArgument(cx, script, arg, type);
|
||||
}
|
||||
|
|
|
@ -3488,10 +3488,10 @@ BEGIN_CASE(JSOP_LENGTH)
|
|||
}
|
||||
} while (0);
|
||||
|
||||
TypeScript::Monitor(cx, script, regs.pc, rval);
|
||||
|
||||
regs.sp[-1] = rval;
|
||||
assertSameCompartment(cx, regs.sp[-1]);
|
||||
|
||||
TypeScript::Monitor(cx, script, regs.pc, regs.sp[-1]);
|
||||
}
|
||||
END_CASE(JSOP_GETPROP)
|
||||
|
||||
|
@ -3583,7 +3583,7 @@ BEGIN_CASE(JSOP_CALLPROP)
|
|||
goto error;
|
||||
}
|
||||
#endif
|
||||
TypeScript::Monitor(cx, script, regs.pc, rval);
|
||||
TypeScript::Monitor(cx, script, regs.pc, regs.sp[-2]);
|
||||
}
|
||||
END_CASE(JSOP_CALLPROP)
|
||||
|
||||
|
@ -4089,7 +4089,7 @@ BEGIN_CASE(JSOP_CALLNAME)
|
|||
}
|
||||
|
||||
PUSH_COPY(rval);
|
||||
TypeScript::Monitor(cx, script, regs.pc, rval);
|
||||
TypeScript::Monitor(cx, script, regs.pc, regs.sp[-1]);
|
||||
|
||||
/* obj must be on the scope chain, thus not a function. */
|
||||
if (op == JSOP_CALLNAME || op == JSOP_CALLGNAME)
|
||||
|
|
|
@ -658,6 +658,17 @@ ToInteger(JSContext *cx, const js::Value &v, jsdouble *dp)
|
|||
return true;
|
||||
}
|
||||
|
||||
/* If v is a double value which fits in an int32, coerce it to that int32. */
|
||||
static inline void
|
||||
TryCoerceNumberToInt32(Value &v)
|
||||
{
|
||||
if (v.isDouble()) {
|
||||
int32_t res;
|
||||
if (JSDOUBLE_IS_INT32(v.toDouble(), &res))
|
||||
v.setInt32(res);
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* jsnum_h___ */
|
||||
|
|
|
@ -2157,9 +2157,9 @@ ASTSerializer::statement(ParseNode *pn, Value *dst)
|
|||
|
||||
return expression(pn->pn_left, &expr) &&
|
||||
statement(pn->pn_right, &stmt) &&
|
||||
pn->isKind(TOK_WITH)
|
||||
? builder.withStatement(expr, stmt, &pn->pn_pos, dst)
|
||||
: builder.whileStatement(expr, stmt, &pn->pn_pos, dst);
|
||||
(pn->isKind(TOK_WITH)
|
||||
? builder.withStatement(expr, stmt, &pn->pn_pos, dst)
|
||||
: builder.whileStatement(expr, stmt, &pn->pn_pos, dst));
|
||||
}
|
||||
|
||||
case TOK_DO:
|
||||
|
|
|
@ -223,9 +223,9 @@ WeakMap_set(JSContext *cx, uintN argc, Value *vp)
|
|||
obj->setPrivate(map);
|
||||
}
|
||||
|
||||
args.thisv() = UndefinedValue();
|
||||
if (!map->put(key, value))
|
||||
goto out_of_memory;
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
|
||||
out_of_memory:
|
||||
|
|
|
@ -6810,6 +6810,12 @@ xml_setName(JSContext *cx, uintN argc, jsval *vp)
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/* Utility function used within xml_setNamespace */
|
||||
static JSBool qn_match(const void *xml, const void *qn) {
|
||||
return qname_identity(((JSXML *)xml)->name, (JSObject *)qn);
|
||||
}
|
||||
|
||||
/* ECMA-357 13.4.4.36 */
|
||||
static JSBool
|
||||
xml_setNamespace(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
|
@ -6838,6 +6844,22 @@ xml_setNamespace(JSContext *cx, uintN argc, jsval *vp)
|
|||
if (!qn)
|
||||
return JS_FALSE;
|
||||
|
||||
/*
|
||||
* Erratum: setting the namespace of an attribute may cause it to duplicate
|
||||
* an already-existing attribute. To preserve the invariant that there are
|
||||
* not multiple attributes with the same name, we delete the existing
|
||||
* attribute so that the mutated attribute will not be a duplicate.
|
||||
*/
|
||||
if (xml->xml_class == JSXML_CLASS_ATTRIBUTE &&
|
||||
xml->parent && xml->parent->xml_class == JSXML_CLASS_ELEMENT &&
|
||||
!qn_match(xml, qn))
|
||||
{
|
||||
JSXMLArray *array = &xml->parent->xml_attrs;
|
||||
uint32 i = XMLArrayFindMember(array, qn, qn_match);
|
||||
if (i != XML_NOT_FOUND)
|
||||
XMLArrayDelete(cx, array, i, JS_TRUE);
|
||||
}
|
||||
|
||||
xml->name = qn;
|
||||
|
||||
/*
|
||||
|
|
|
@ -230,6 +230,17 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::SparcRegist
|
|||
}
|
||||
#endif
|
||||
|
||||
void moveDoubleRegisters(RegisterID data, RegisterID type, Address address, FPRegisterID fpreg)
|
||||
{
|
||||
#ifdef JS_CPU_X86
|
||||
fastLoadDouble(data, type, fpreg);
|
||||
#else
|
||||
/* Store the components, then read it back out as a double. */
|
||||
storeValueFromComponents(type, data, address);
|
||||
loadDouble(address, fpreg);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Move a register pair which may indicate either an int32 or double into fpreg,
|
||||
* converting to double in the int32 case.
|
||||
|
@ -1164,6 +1175,29 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::SparcRegist
|
|||
} else if (types->hasType(types::Type::Int32Type())) {
|
||||
if (!matches.append(testInt32(Assembler::Equal, address)))
|
||||
return false;
|
||||
|
||||
/* Generate a path to try coercing doubles to integers in place. */
|
||||
Jump notDouble = testDouble(Assembler::NotEqual, address);
|
||||
|
||||
Registers tempRegs(Registers::AvailRegs);
|
||||
RegisterID T1 = tempRegs.takeAnyReg().reg();
|
||||
|
||||
Registers tempFPRegs(Registers::TempFPRegs);
|
||||
FPRegisterID FP1 = tempFPRegs.takeAnyReg().fpreg();
|
||||
FPRegisterID FP2 = tempFPRegs.takeAnyReg().fpreg();
|
||||
|
||||
loadDouble(address, FP1);
|
||||
|
||||
JumpList isDouble;
|
||||
branchConvertDoubleToInt32(FP1, T1, isDouble, FP2);
|
||||
|
||||
storeValueFromComponents(ImmType(JSVAL_TYPE_INT32), T1, address);
|
||||
|
||||
if (!matches.append(jump()))
|
||||
return false;
|
||||
|
||||
isDouble.linkTo(label(), this);
|
||||
notDouble.linkTo(label(), this);
|
||||
}
|
||||
|
||||
if (types->hasType(types::Type::UndefinedType())) {
|
||||
|
|
|
@ -7369,39 +7369,6 @@ mjit::Compiler::pushAddressMaybeBarrier(Address address, JSValueType type, bool
|
|||
return testBarrier(typeReg, dataReg, testUndefined);
|
||||
}
|
||||
|
||||
MaybeJump
|
||||
mjit::Compiler::trySingleTypeTest(types::TypeSet *types, RegisterID typeReg)
|
||||
{
|
||||
/*
|
||||
* If a type set we have a barrier on is monomorphic, generate a single
|
||||
* jump taken if a type register has a match. This doesn't handle type sets
|
||||
* containing objects, as these require two jumps regardless (test for
|
||||
* object, then test the type of the object).
|
||||
*/
|
||||
MaybeJump res;
|
||||
|
||||
switch (types->getKnownTypeTag(cx)) {
|
||||
case JSVAL_TYPE_INT32:
|
||||
res.setJump(masm.testInt32(Assembler::NotEqual, typeReg));
|
||||
return res;
|
||||
|
||||
case JSVAL_TYPE_DOUBLE:
|
||||
res.setJump(masm.testNumber(Assembler::NotEqual, typeReg));
|
||||
return res;
|
||||
|
||||
case JSVAL_TYPE_BOOLEAN:
|
||||
res.setJump(masm.testBoolean(Assembler::NotEqual, typeReg));
|
||||
return res;
|
||||
|
||||
case JSVAL_TYPE_STRING:
|
||||
res.setJump(masm.testString(Assembler::NotEqual, typeReg));
|
||||
return res;
|
||||
|
||||
default:
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
JSC::MacroAssembler::Jump
|
||||
mjit::Compiler::addTypeTest(types::TypeSet *types, RegisterID typeReg, RegisterID dataReg)
|
||||
{
|
||||
|
@ -7413,11 +7380,32 @@ mjit::Compiler::addTypeTest(types::TypeSet *types, RegisterID typeReg, RegisterI
|
|||
|
||||
Vector<Jump> matches(CompilerAllocPolicy(cx, *this));
|
||||
|
||||
if (types->hasType(types::Type::Int32Type()))
|
||||
if (types->hasType(types::Type::DoubleType())) {
|
||||
matches.append(masm.testNumber(Assembler::Equal, typeReg));
|
||||
} else if (types->hasType(types::Type::Int32Type())) {
|
||||
matches.append(masm.testInt32(Assembler::Equal, typeReg));
|
||||
|
||||
if (types->hasType(types::Type::DoubleType()))
|
||||
matches.append(masm.testDouble(Assembler::Equal, typeReg));
|
||||
/* Generate a path to try coercing doubles to integers in place. */
|
||||
Jump notDouble = masm.testDouble(Assembler::NotEqual, typeReg);
|
||||
|
||||
FPRegisterID fpTemp = frame.getScratchFPReg();
|
||||
masm.moveDoubleRegisters(dataReg, typeReg, frame.addressOfTop(), fpTemp);
|
||||
|
||||
JumpList isDouble;
|
||||
masm.branchConvertDoubleToInt32(fpTemp, dataReg, isDouble, Registers::FPConversionTemp);
|
||||
masm.move(ImmType(JSVAL_TYPE_INT32), typeReg);
|
||||
|
||||
frame.restoreScratchFPReg(fpTemp);
|
||||
|
||||
matches.append(masm.jump());
|
||||
|
||||
isDouble.linkTo(masm.label(), &masm);
|
||||
|
||||
masm.breakDouble(fpTemp, typeReg, dataReg);
|
||||
frame.restoreScratchFPReg(fpTemp);
|
||||
|
||||
notDouble.linkTo(masm.label(), &masm);
|
||||
}
|
||||
|
||||
if (types->hasType(types::Type::UndefinedType()))
|
||||
matches.append(masm.testUndefined(Assembler::Equal, typeReg));
|
||||
|
@ -7511,9 +7499,7 @@ mjit::Compiler::testBarrier(RegisterID typeReg, RegisterID dataReg,
|
|||
/* Cannot have type barriers when the result of the operation is already unknown. */
|
||||
JS_ASSERT(!types->unknown());
|
||||
|
||||
state.jump = trySingleTypeTest(types, typeReg);
|
||||
if (!state.jump.isSet())
|
||||
state.jump.setJump(addTypeTest(types, typeReg, dataReg));
|
||||
state.jump.setJump(addTypeTest(types, typeReg, dataReg));
|
||||
|
||||
return state;
|
||||
}
|
||||
|
|
|
@ -556,7 +556,6 @@ private:
|
|||
RegisterID dataReg;
|
||||
};
|
||||
|
||||
MaybeJump trySingleTypeTest(types::TypeSet *types, RegisterID typeReg);
|
||||
Jump addTypeTest(types::TypeSet *types, RegisterID typeReg, RegisterID dataReg);
|
||||
BarrierState pushAddressMaybeBarrier(Address address, JSValueType type, bool reuseBase,
|
||||
bool testUndefined = false);
|
||||
|
|
|
@ -1974,7 +1974,6 @@ mjit::Compiler::jsop_getelem_typed(int atype)
|
|||
|
||||
frame.popn(2);
|
||||
|
||||
BarrierState barrier;
|
||||
if (dataReg.isFPReg()) {
|
||||
frame.pushDouble(dataReg.fpreg());
|
||||
} else if (typeReg.isSet()) {
|
||||
|
@ -1985,8 +1984,6 @@ mjit::Compiler::jsop_getelem_typed(int atype)
|
|||
}
|
||||
stubcc.rejoin(Changes(2));
|
||||
|
||||
finishBarrier(barrier, REJOIN_FALLTHROUGH, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif /* JS_METHODJIT_TYPED_ARRAY */
|
||||
|
@ -2010,7 +2007,12 @@ mjit::Compiler::jsop_getelem(bool isCall)
|
|||
if (cx->typeInferenceEnabled() && id->mightBeType(JSVAL_TYPE_INT32) && !isCall) {
|
||||
types::TypeSet *types = analysis->poppedTypes(PC, 1);
|
||||
if (types->isLazyArguments(cx) && !outerScript->analysis()->modifiesArguments()) {
|
||||
// Inline arguments path.
|
||||
// Inline arguments path. This path can access non-canonical args
|
||||
// if fun->nargs != 0, so we require that the script never has any
|
||||
// of its arguments directly modified. Note that the canonical and
|
||||
// formal arg may not be the exact same value if we coerced a
|
||||
// double actual into an int32 formal from a type barrier at entry,
|
||||
// but this is ok as the underlying number is the same.
|
||||
jsop_getelem_args();
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -195,6 +195,36 @@ FrameState::takeReg(AnyRegisterID reg)
|
|||
}
|
||||
}
|
||||
|
||||
JSC::MacroAssembler::FPRegisterID
|
||||
FrameState::getScratchFPReg()
|
||||
{
|
||||
if (freeRegs.hasRegInMask(Registers::TempFPRegs)) {
|
||||
FPRegisterID reg = freeRegs.takeAnyReg(Registers::TempFPRegs).fpreg();
|
||||
freeRegs.putReg(reg);
|
||||
return reg;
|
||||
}
|
||||
|
||||
Registers regs(Registers::TempFPRegs);
|
||||
FPRegisterID reg;
|
||||
|
||||
do {
|
||||
reg = regs.takeAnyReg().fpreg();
|
||||
} while (!regstate(reg).fe());
|
||||
|
||||
masm.storeDouble(reg, addressOf(regstate(reg).fe()));
|
||||
|
||||
return reg;
|
||||
}
|
||||
|
||||
void
|
||||
FrameState::restoreScratchFPReg(FPRegisterID reg)
|
||||
{
|
||||
if (freeRegs.hasReg(reg))
|
||||
return;
|
||||
|
||||
masm.loadDouble(addressOf(regstate(reg).fe()), reg);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
const char *
|
||||
FrameState::entryName(const FrameEntry *fe) const
|
||||
|
|
|
@ -613,6 +613,14 @@ class FrameState
|
|||
*/
|
||||
void takeReg(AnyRegisterID reg);
|
||||
|
||||
/*
|
||||
* Gets an FP register which the compiler does not own but can freely write
|
||||
* over. Can only be used in the inline path, and must be matched with a
|
||||
* restoreScratchFPReg. (Emits sync/restore code if the reg is in use).
|
||||
*/
|
||||
FPRegisterID getScratchFPReg();
|
||||
void restoreScratchFPReg(FPRegisterID reg);
|
||||
|
||||
/*
|
||||
* Returns a FrameEntry * for a slot on the operation stack.
|
||||
*/
|
||||
|
|
|
@ -2367,7 +2367,7 @@ stubs::TypeBarrierHelper(VMFrame &f, uint32 which)
|
|||
void JS_FASTCALL
|
||||
stubs::StubTypeHelper(VMFrame &f, int32 which)
|
||||
{
|
||||
const Value &result = f.regs.sp[which];
|
||||
Value &result = f.regs.sp[which];
|
||||
|
||||
if (f.script()->hasAnalysis() && f.script()->analysis()->ranInference()) {
|
||||
AutoEnterTypeInference enter(f.cx);
|
||||
|
|
|
@ -68,4 +68,15 @@ TEST(3, 1, xhtml.namespaceDeclarations().length);
|
|||
|
||||
TEST(4, xhtml1NS, xhtml.namespace());
|
||||
|
||||
var xml = <root xmlns:ns="http://example.org/"><blah/></root>
|
||||
var ns = new Namespace('ns','http://example.org/');
|
||||
xml.blah.@foo = 'bar';
|
||||
xml.blah.@foo.setNamespace(ns);
|
||||
xml.blah.@foo = 'baz';
|
||||
xml.blah.@foo.setNamespace(ns);
|
||||
|
||||
var expected = <root xmlns:ns="http://example.org/"><blah ns:foo="baz"/></root>;
|
||||
|
||||
TEST(5, xml, expected);
|
||||
|
||||
END();
|
||||
|
|
|
@ -58,4 +58,6 @@ require-or(debugMode,skip) script regress-672804-2.js
|
|||
require-or(debugMode,skip) script regress-672804-3.js
|
||||
skip-if(!xulRuntime.shell) script regress-677589.js
|
||||
script regress-677924.js
|
||||
skip-if(!xulRuntime.shell) script regress-696109.js
|
||||
script regress-691746.js
|
||||
script regress-697515.js
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/licenses/publicdomain/
|
||||
* Contributor: Dave Herman <dherman@mozilla.com>
|
||||
*/
|
||||
|
||||
// Bug 696109 - fixed a precedence bug in with/while nodes
|
||||
try {
|
||||
Reflect.parse("with({foo})bar");
|
||||
throw new Error("supposed to be a syntax error");
|
||||
} catch (e if e instanceof SyntaxError) { }
|
||||
try {
|
||||
Reflect.parse("while({foo})bar");
|
||||
throw new Error("supposed to be a syntax error");
|
||||
} catch (e if e instanceof SyntaxError) { }
|
||||
|
||||
reportCompare(true, true);
|
|
@ -0,0 +1,6 @@
|
|||
// Any copyright is dedicated to the Public Domain.
|
||||
// http://creativecommons.org/licenses/publicdomain/
|
||||
|
||||
assertEq(new WeakMap().set({}, 0), undefined);
|
||||
|
||||
reportCompare(0, 0, 'ok');
|
|
@ -546,7 +546,7 @@ class Writer
|
|||
}
|
||||
|
||||
nj::LIns *ldiConstTypedArrayLength(nj::LIns *obj) const {
|
||||
return name(lir->insLoad(nj::LIR_ldi, obj, TypedArray::lengthOffset(), ACCSET_TARRAY,
|
||||
return name(lir->insLoad(nj::LIR_ldi, obj, TypedArray::lengthOffset() + sPayloadOffset, ACCSET_TARRAY,
|
||||
nj::LOAD_CONST),
|
||||
"typedArrayLength");
|
||||
}
|
||||
|
|
|
@ -65,6 +65,7 @@ members = [
|
|||
'nsIDOMWindow.name',
|
||||
'nsIDOMWindow.parent',
|
||||
'nsIDOMWindow.top',
|
||||
'nsIDOMWindow.self',
|
||||
# Several window properties are magically resolved, including
|
||||
# location, _content, navigator, document, and window itself.
|
||||
# These do not need quick stubs.
|
||||
|
@ -486,6 +487,7 @@ irregularFilenames = {
|
|||
'nsIWebGLUniformLocation': 'nsIDOMWebGLRenderingContext',
|
||||
'nsIWebGLExtension': 'nsIDOMWebGLRenderingContext',
|
||||
'nsIWebGLExtensionStandardDerivatives' : 'nsIDOMWebGLRenderingContext',
|
||||
'nsIWebGLExtensionLoseContext' : 'nsIDOMWebGLRenderingContext',
|
||||
|
||||
'nsIIndexedDatabaseUsageCallback': 'nsIIndexedDatabaseManager',
|
||||
|
||||
|
|
|
@ -1780,10 +1780,26 @@ nsDisplayOpacity::BuildLayer(nsDisplayListBuilder* aBuilder,
|
|||
return layer.forget();
|
||||
}
|
||||
|
||||
/**
|
||||
* This doesn't take into account layer scaling --- the layer may be
|
||||
* rendered at a higher (or lower) resolution, affecting the retained layer
|
||||
* size --- but this should be good enough.
|
||||
*/
|
||||
static bool
|
||||
IsItemTooSmallForActiveLayer(nsDisplayItem* aItem)
|
||||
{
|
||||
nsIntRect visibleDevPixels = aItem->GetVisibleRect().ToOutsidePixels(
|
||||
aItem->GetUnderlyingFrame()->PresContext()->AppUnitsPerDevPixel());
|
||||
static const int MIN_ACTIVE_LAYER_SIZE_DEV_PIXELS = 16;
|
||||
return visibleDevPixels.Size() <
|
||||
nsIntSize(MIN_ACTIVE_LAYER_SIZE_DEV_PIXELS, MIN_ACTIVE_LAYER_SIZE_DEV_PIXELS);
|
||||
}
|
||||
|
||||
nsDisplayItem::LayerState
|
||||
nsDisplayOpacity::GetLayerState(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager) {
|
||||
if (mFrame->AreLayersMarkedActive(nsChangeHint_UpdateOpacityLayer))
|
||||
if (mFrame->AreLayersMarkedActive(nsChangeHint_UpdateOpacityLayer) &&
|
||||
!IsItemTooSmallForActiveLayer(this))
|
||||
return LAYER_ACTIVE;
|
||||
nsIFrame* activeScrolledRoot =
|
||||
nsLayoutUtils::GetActiveScrolledRootFor(mFrame, nsnull);
|
||||
|
@ -2605,7 +2621,10 @@ already_AddRefed<Layer> nsDisplayTransform::BuildLayer(nsDisplayListBuilder *aBu
|
|||
nsDisplayItem::LayerState
|
||||
nsDisplayTransform::GetLayerState(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager) {
|
||||
if (mFrame->AreLayersMarkedActive(nsChangeHint_UpdateTransformLayer))
|
||||
// Here we check if the *post-transform* bounds of this item are big enough
|
||||
// to justify an active layer.
|
||||
if (mFrame->AreLayersMarkedActive(nsChangeHint_UpdateTransformLayer) &&
|
||||
!IsItemTooSmallForActiveLayer(this))
|
||||
return LAYER_ACTIVE;
|
||||
if (!GetTransform(mFrame->PresContext()->AppUnitsPerDevPixel()).Is2D() || mFrame->Preserves3D())
|
||||
return LAYER_ACTIVE;
|
||||
|
|
|
@ -5251,8 +5251,11 @@ static nsIView* FindFloatingViewContaining(nsIView* aView, nsPoint aPt)
|
|||
return nsnull;
|
||||
|
||||
nsIFrame* frame = static_cast<nsIFrame*>(aView->GetClientData());
|
||||
if (frame && !frame->PresContext()->PresShell()->IsActive()) {
|
||||
return nsnull;
|
||||
if (frame) {
|
||||
if (!frame->IsVisibleConsideringAncestors(nsIFrame::VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY) ||
|
||||
!frame->PresContext()->PresShell()->IsActive()) {
|
||||
return nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
for (nsIView* v = aView->GetFirstChild(); v; v = v->GetNextSibling()) {
|
||||
|
@ -5285,8 +5288,11 @@ static nsIView* FindViewContaining(nsIView* aView, nsPoint aPt)
|
|||
}
|
||||
|
||||
nsIFrame* frame = static_cast<nsIFrame*>(aView->GetClientData());
|
||||
if (frame && !frame->PresContext()->PresShell()->IsActive()) {
|
||||
return nsnull;
|
||||
if (frame) {
|
||||
if (!frame->IsVisibleConsideringAncestors(nsIFrame::VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY) ||
|
||||
!frame->PresContext()->PresShell()->IsActive()) {
|
||||
return nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
for (nsIView* v = aView->GetFirstChild(); v; v = v->GetNextSibling()) {
|
||||
|
@ -6864,7 +6870,7 @@ PresShell::WillPaint(bool aWillSendDidPaint)
|
|||
{
|
||||
// Don't bother doing anything if some viewmanager in our tree is painting
|
||||
// while we still have painting suppressed or we are not active.
|
||||
if (mPaintingSuppressed || !mIsActive) {
|
||||
if (mPaintingSuppressed || !mIsActive || !IsVisible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -6890,7 +6896,7 @@ PresShell::WillPaint(bool aWillSendDidPaint)
|
|||
NS_IMETHODIMP_(void)
|
||||
PresShell::DidPaint()
|
||||
{
|
||||
if (mPaintingSuppressed || !mIsActive) {
|
||||
if (mPaintingSuppressed || !mIsActive || !IsVisible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -6903,6 +6909,33 @@ PresShell::DidPaint()
|
|||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(bool)
|
||||
PresShell::IsVisible()
|
||||
{
|
||||
if (!mViewManager)
|
||||
return false;
|
||||
|
||||
nsIView* view = mViewManager->GetRootView();
|
||||
if (!view)
|
||||
return true;
|
||||
|
||||
// inner view of subdoc frame
|
||||
view = view->GetParent();
|
||||
if (!view)
|
||||
return true;
|
||||
|
||||
// subdoc view
|
||||
view = view->GetParent();
|
||||
if (!view)
|
||||
return true;
|
||||
|
||||
nsIFrame* frame = static_cast<nsIFrame*>(view->GetClientData());
|
||||
if (!frame)
|
||||
return true;
|
||||
|
||||
return frame->IsVisibleConsideringAncestors(nsIFrame::VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY);
|
||||
}
|
||||
|
||||
nsresult
|
||||
PresShell::GetAgentStyleSheets(nsCOMArray<nsIStyleSheet>& aSheets)
|
||||
{
|
||||
|
|
|
@ -337,6 +337,7 @@ public:
|
|||
NS_IMETHOD_(void) DispatchSynthMouseMove(nsGUIEvent *aEvent,
|
||||
bool aFlushOnHoverChange);
|
||||
NS_IMETHOD_(void) ClearMouseCapture(nsIView* aView);
|
||||
NS_IMETHOD_(bool) IsVisible();
|
||||
|
||||
// caret handling
|
||||
virtual NS_HIDDEN_(already_AddRefed<nsCaret>) GetCaret() const;
|
||||
|
|
|
@ -119,6 +119,7 @@
|
|||
#include "nsSVGIntegrationUtils.h"
|
||||
#include "nsSVGEffects.h"
|
||||
#include "nsChangeHint.h"
|
||||
#include "nsDeckFrame.h"
|
||||
|
||||
#include "gfxContext.h"
|
||||
#include "CSSCalc.h"
|
||||
|
@ -301,6 +302,48 @@ nsIFrame::CheckAndClearPaintedState()
|
|||
return result;
|
||||
}
|
||||
|
||||
bool
|
||||
nsIFrame::IsVisibleConsideringAncestors(PRUint32 aFlags) const
|
||||
{
|
||||
if (!GetStyleVisibility()->IsVisible()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const nsIFrame* frame = this;
|
||||
while (frame) {
|
||||
nsIView* view = frame->GetView();
|
||||
if (view && view->GetVisibility() == nsViewVisibility_kHide)
|
||||
return false;
|
||||
|
||||
nsIFrame* parent = frame->GetParent();
|
||||
nsDeckFrame* deck = do_QueryFrame(parent);
|
||||
if (deck) {
|
||||
if (deck->GetSelectedBox() != frame)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (parent) {
|
||||
frame = parent;
|
||||
} else {
|
||||
parent = nsLayoutUtils::GetCrossDocParentFrame(frame);
|
||||
if (!parent)
|
||||
break;
|
||||
|
||||
if ((aFlags & nsIFrame::VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY) == 0 &&
|
||||
parent->PresContext()->IsChrome() && !frame->PresContext()->IsChrome()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!parent->GetStyleVisibility()->IsVisible())
|
||||
return false;
|
||||
|
||||
frame = parent;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ApplyOverflowClipping(nsDisplayListBuilder* aBuilder,
|
||||
const nsIFrame* aFrame,
|
||||
const nsStyleDisplay* aDisp,
|
||||
|
@ -4196,30 +4239,6 @@ NS_IMETHODIMP nsFrame::GetOffsetFromView(nsPoint& aOffset,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
/* virtual */ bool
|
||||
nsIFrame::AreAncestorViewsVisible() const
|
||||
{
|
||||
const nsIFrame* parent;
|
||||
for (const nsIFrame* f = this; f; f = parent) {
|
||||
nsIView* view = f->GetView();
|
||||
if (view && view->GetVisibility() == nsViewVisibility_kHide) {
|
||||
return false;
|
||||
}
|
||||
parent = f->GetParent();
|
||||
if (!parent) {
|
||||
parent = nsLayoutUtils::GetCrossDocParentFrame(f);
|
||||
if (parent && parent->PresContext()->IsChrome() &&
|
||||
!f->PresContext()->IsChrome()) {
|
||||
// Don't look beyond chrome/content boundary ... if the chrome
|
||||
// has hidden a content docshell, the content in the content
|
||||
// docshell shouldn't be affected (e.g. it should remain focusable).
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
nsIWidget*
|
||||
nsIFrame::GetNearestWidget() const
|
||||
{
|
||||
|
@ -7005,38 +7024,34 @@ nsIFrame::IsFocusable(PRInt32 *aTabIndex, bool aWithMouse)
|
|||
}
|
||||
bool isFocusable = false;
|
||||
|
||||
if (mContent && mContent->IsElement() && AreAncestorViewsVisible()) {
|
||||
const nsStyleVisibility* vis = GetStyleVisibility();
|
||||
if (vis->mVisible != NS_STYLE_VISIBILITY_COLLAPSE &&
|
||||
vis->mVisible != NS_STYLE_VISIBILITY_HIDDEN) {
|
||||
const nsStyleUserInterface* ui = GetStyleUserInterface();
|
||||
if (ui->mUserFocus != NS_STYLE_USER_FOCUS_IGNORE &&
|
||||
ui->mUserFocus != NS_STYLE_USER_FOCUS_NONE) {
|
||||
// Pass in default tabindex of -1 for nonfocusable and 0 for focusable
|
||||
tabIndex = 0;
|
||||
}
|
||||
isFocusable = mContent->IsFocusable(&tabIndex, aWithMouse);
|
||||
if (!isFocusable && !aWithMouse &&
|
||||
GetType() == nsGkAtoms::scrollFrame &&
|
||||
mContent->IsHTML() &&
|
||||
!mContent->IsRootOfNativeAnonymousSubtree() &&
|
||||
mContent->GetParent() &&
|
||||
!mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex)) {
|
||||
// Elements with scrollable view are focusable with script & tabbable
|
||||
// Otherwise you couldn't scroll them with keyboard, which is
|
||||
// an accessibility issue (e.g. Section 508 rules)
|
||||
// However, we don't make them to be focusable with the mouse,
|
||||
// because the extra focus outlines are considered unnecessarily ugly.
|
||||
// When clicked on, the selection position within the element
|
||||
// will be enough to make them keyboard scrollable.
|
||||
nsIScrollableFrame *scrollFrame = do_QueryFrame(this);
|
||||
if (scrollFrame &&
|
||||
scrollFrame->GetScrollbarStyles() != nsIScrollableFrame::ScrollbarStyles(NS_STYLE_OVERFLOW_HIDDEN, NS_STYLE_OVERFLOW_HIDDEN) &&
|
||||
!scrollFrame->GetScrollRange().IsEqualEdges(nsRect(0, 0, 0, 0))) {
|
||||
// Scroll bars will be used for overflow
|
||||
isFocusable = true;
|
||||
tabIndex = 0;
|
||||
}
|
||||
if (mContent && mContent->IsElement() && IsVisibleConsideringAncestors()) {
|
||||
const nsStyleUserInterface* ui = GetStyleUserInterface();
|
||||
if (ui->mUserFocus != NS_STYLE_USER_FOCUS_IGNORE &&
|
||||
ui->mUserFocus != NS_STYLE_USER_FOCUS_NONE) {
|
||||
// Pass in default tabindex of -1 for nonfocusable and 0 for focusable
|
||||
tabIndex = 0;
|
||||
}
|
||||
isFocusable = mContent->IsFocusable(&tabIndex, aWithMouse);
|
||||
if (!isFocusable && !aWithMouse &&
|
||||
GetType() == nsGkAtoms::scrollFrame &&
|
||||
mContent->IsHTML() &&
|
||||
!mContent->IsRootOfNativeAnonymousSubtree() &&
|
||||
mContent->GetParent() &&
|
||||
!mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex)) {
|
||||
// Elements with scrollable view are focusable with script & tabbable
|
||||
// Otherwise you couldn't scroll them with keyboard, which is
|
||||
// an accessibility issue (e.g. Section 508 rules)
|
||||
// However, we don't make them to be focusable with the mouse,
|
||||
// because the extra focus outlines are considered unnecessarily ugly.
|
||||
// When clicked on, the selection position within the element
|
||||
// will be enough to make them keyboard scrollable.
|
||||
nsIScrollableFrame *scrollFrame = do_QueryFrame(this);
|
||||
if (scrollFrame &&
|
||||
scrollFrame->GetScrollbarStyles() != nsIScrollableFrame::ScrollbarStyles(NS_STYLE_OVERFLOW_HIDDEN, NS_STYLE_OVERFLOW_HIDDEN) &&
|
||||
!scrollFrame->GetScrollRange().IsEqualEdges(nsRect(0, 0, 0, 0))) {
|
||||
// Scroll bars will be used for overflow
|
||||
isFocusable = true;
|
||||
tabIndex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1897,12 +1897,6 @@ public:
|
|||
NS_IMETHOD GetOffsetFromView(nsPoint& aOffset,
|
||||
nsIView** aView) const = 0;
|
||||
|
||||
/**
|
||||
* Returns true if and only if all views, from |GetClosestView| up to
|
||||
* the top of the view hierarchy are visible.
|
||||
*/
|
||||
virtual bool AreAncestorViewsVisible() const;
|
||||
|
||||
/**
|
||||
* Returns the nearest widget containing this frame. If this frame has a
|
||||
* view and the view has a widget, then this frame's widget is
|
||||
|
@ -2760,6 +2754,19 @@ NS_PTR_TO_INT32(frame->Properties().Get(nsIFrame::EmbeddingLevelProperty()))
|
|||
// clears this bit if so.
|
||||
bool CheckAndClearPaintedState();
|
||||
|
||||
// CSS visibility just doesn't cut it because it doesn't inherit through
|
||||
// documents. Also if this frame is in a hidden card of a deck then it isn't
|
||||
// visible either and that isn't expressed using CSS visibility. Also if it
|
||||
// is in a hidden view (there are a few cases left and they are hopefully
|
||||
// going away soon).
|
||||
// If the VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY flag is passed then we
|
||||
// ignore the chrome/content boundary, otherwise we stop looking when we
|
||||
// reach it.
|
||||
enum {
|
||||
VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY = 0x01
|
||||
};
|
||||
bool IsVisibleConsideringAncestors(PRUint32 aFlags = 0) const;
|
||||
|
||||
protected:
|
||||
// Members
|
||||
nsRect mRect;
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
<body>
|
||||
<div id="d">
|
||||
<div id="e">
|
||||
<div style="width:10px; height:10px; background:yellow;"></div>
|
||||
<div style="width:80px; height:80px; background:yellow;"></div>
|
||||
<div id="f">
|
||||
<div style="width:10px; height:10px; background:blue;"></div>
|
||||
<div style="width:80px; height:80px; background:blue;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
<body onload="step()">
|
||||
<div id="d">
|
||||
<div id="e">
|
||||
<div style="width:10px; height:10px; background:yellow;"></div>
|
||||
<div style="width:80px; height:80px; background:yellow;"></div>
|
||||
<div id="f">
|
||||
<div style="width:10px; height:10px; background:blue;"></div>
|
||||
<div style="width:80px; height:80px; background:blue;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -56,7 +56,10 @@ nsNthIndexCache::~nsNthIndexCache()
|
|||
void
|
||||
nsNthIndexCache::Reset()
|
||||
{
|
||||
mCache.clear();
|
||||
mCaches[0][0].clear();
|
||||
mCaches[0][1].clear();
|
||||
mCaches[1][0].clear();
|
||||
mCaches[1][1].clear();
|
||||
}
|
||||
|
||||
inline bool
|
||||
|
@ -69,29 +72,28 @@ nsNthIndexCache::SiblingMatchesElement(nsIContent* aSibling, Element* aElement,
|
|||
}
|
||||
|
||||
inline bool
|
||||
nsNthIndexCache::IndexDetermined(nsIContent* aSibling, Element* aChild,
|
||||
bool aIsOfType, bool aIsFromEnd,
|
||||
bool aCheckEdgeOnly, PRInt32& aResult)
|
||||
nsNthIndexCache::IndexDeterminedFromPreviousSibling(nsIContent* aSibling,
|
||||
Element* aChild,
|
||||
bool aIsOfType,
|
||||
bool aIsFromEnd,
|
||||
const Cache& aCache,
|
||||
PRInt32& aResult)
|
||||
{
|
||||
if (SiblingMatchesElement(aSibling, aChild, aIsOfType)) {
|
||||
if (aCheckEdgeOnly) {
|
||||
// The caller only cares whether or not the result is 1, and we
|
||||
// now know it's not.
|
||||
aResult = -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
Cache::Ptr siblingEntry = mCache.lookup(aSibling);
|
||||
Cache::Ptr siblingEntry = aCache.lookup(aSibling);
|
||||
if (siblingEntry) {
|
||||
PRInt32 siblingIndex = siblingEntry->value.mNthIndices[aIsOfType][aIsFromEnd];
|
||||
PRInt32 siblingIndex = siblingEntry->value;
|
||||
NS_ASSERTION(siblingIndex != 0,
|
||||
"How can a non-anonymous node have an anonymous sibling?");
|
||||
if (siblingIndex > 0) {
|
||||
// At this point, aResult is a count of how many elements matching
|
||||
// aChild we have seen after aSibling, including aChild itself. So if
|
||||
// |siblingIndex| is the index of aSibling, we need to add aResult to
|
||||
// get the right answer here.
|
||||
aResult = siblingIndex + aResult;
|
||||
// aChild we have seen after aSibling, including aChild itself.
|
||||
// |siblingIndex| is the index of aSibling.
|
||||
// So if aIsFromEnd, we want |aResult = siblingIndex - aResult| and
|
||||
// otherwise we want |aResult = siblingIndex + aResult|.
|
||||
NS_ABORT_IF_FALSE(aIsFromEnd == 0 || aIsFromEnd == 1,
|
||||
"Bogus bool value");
|
||||
aResult = siblingIndex + aResult * (1 - 2 * aIsFromEnd);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -112,48 +114,75 @@ nsNthIndexCache::GetNthIndex(Element* aChild, bool aIsOfType,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (!mCache.initialized() && !mCache.init()) {
|
||||
Cache &cache = mCaches[aIsOfType][aIsFromEnd];
|
||||
|
||||
if (!cache.initialized() && !cache.init()) {
|
||||
// Give up and just don't match.
|
||||
return 0;
|
||||
}
|
||||
|
||||
Cache::AddPtr entry = mCache.lookupForAdd(aChild);
|
||||
|
||||
if (!entry && !mCache.add(entry, aChild)) {
|
||||
Cache::AddPtr entry = cache.lookupForAdd(aChild);
|
||||
|
||||
// Default the value to -2 when adding
|
||||
if (!entry && !cache.add(entry, aChild, -2)) {
|
||||
// No good; don't match.
|
||||
return 0;
|
||||
}
|
||||
|
||||
PRInt32 &slot = entry->value.mNthIndices[aIsOfType][aIsFromEnd];
|
||||
PRInt32 &slot = entry->value;
|
||||
if (slot != -2 && (slot != -1 || aCheckEdgeOnly)) {
|
||||
return slot;
|
||||
}
|
||||
|
||||
PRInt32 result = 1;
|
||||
if (aIsFromEnd) {
|
||||
for (nsIContent *cur = aChild->GetNextSibling();
|
||||
cur;
|
||||
cur = cur->GetNextSibling()) {
|
||||
// It doesn't make sense to do cache lookups for siblings when
|
||||
// aIsFromEnd. In general, the cache will only be primed for
|
||||
// things that are _before_ us in the DOM.
|
||||
if (SiblingMatchesElement(cur, aChild, aIsOfType)) {
|
||||
if (aCheckEdgeOnly) {
|
||||
// The caller only cares whether or not the result is 1, and we
|
||||
// now know it's not.
|
||||
if (aCheckEdgeOnly) {
|
||||
// The caller only cares whether or not the result is 1, so we can
|
||||
// stop as soon as we see any other elements that match us.
|
||||
if (aIsFromEnd) {
|
||||
for (nsIContent *cur = aChild->GetNextSibling();
|
||||
cur;
|
||||
cur = cur->GetNextSibling()) {
|
||||
if (SiblingMatchesElement(cur, aChild, aIsOfType)) {
|
||||
result = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (nsIContent *cur = aChild->GetPreviousSibling();
|
||||
cur;
|
||||
cur = cur->GetPreviousSibling()) {
|
||||
if (SiblingMatchesElement(cur, aChild, aIsOfType)) {
|
||||
result = -1;
|
||||
break;
|
||||
}
|
||||
++result;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// In the common case, we already have a cached index for one of
|
||||
// our previous siblings, so check that first.
|
||||
for (nsIContent *cur = aChild->GetPreviousSibling();
|
||||
cur;
|
||||
cur = cur->GetPreviousSibling()) {
|
||||
if (IndexDetermined(cur, aChild, aIsOfType, aIsFromEnd, aCheckEdgeOnly,
|
||||
result)) {
|
||||
break;
|
||||
if (IndexDeterminedFromPreviousSibling(cur, aChild, aIsOfType,
|
||||
aIsFromEnd, cache, result)) {
|
||||
slot = result;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// Now if aIsFromEnd we lose: need to actually compute our index,
|
||||
// since looking at previous siblings wouldn't have told us
|
||||
// anything about it. Note that it doesn't make sense to do cache
|
||||
// lookups on our following siblings, since chances are the cache
|
||||
// is not primed for them.
|
||||
if (aIsFromEnd) {
|
||||
result = 1;
|
||||
for (nsIContent *cur = aChild->GetNextSibling();
|
||||
cur;
|
||||
cur = cur->GetNextSibling()) {
|
||||
if (SiblingMatchesElement(cur, aChild, aIsOfType)) {
|
||||
++result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,30 +80,11 @@ private:
|
|||
inline bool SiblingMatchesElement(nsIContent* aSibling, Element* aElement,
|
||||
bool aIsOfType);
|
||||
|
||||
/**
|
||||
* Returns true if aResult has been set to the correct value for aChild and
|
||||
* no more work needs to be done. Returns false otherwise.
|
||||
*/
|
||||
inline bool IndexDetermined(nsIContent* aSibling, Element* aChild,
|
||||
bool aIsOfType, bool aIsFromEnd,
|
||||
bool aCheckEdgeOnly, PRInt32& aResult);
|
||||
|
||||
struct CacheEntry {
|
||||
CacheEntry() {
|
||||
mNthIndices[0][0] = -2;
|
||||
mNthIndices[0][1] = -2;
|
||||
mNthIndices[1][0] = -2;
|
||||
mNthIndices[1][1] = -2;
|
||||
}
|
||||
|
||||
// This node's index for :nth-child(), :nth-last-child(),
|
||||
// :nth-of-type(), :nth-last-of-type(). If -2, needs to be computed.
|
||||
// If -1, needs to be computed but known not to be 1.
|
||||
// If 0, the node is not at any index in its parent.
|
||||
// The first subscript is 0 for -child and 1 for -of-type, the second
|
||||
// subscript is 0 for nth- and 1 for nth-last-.
|
||||
PRInt32 mNthIndices[2][2];
|
||||
};
|
||||
// This node's index for this cache.
|
||||
// If -2, needs to be computed.
|
||||
// If -1, needs to be computed but known not to be 1.
|
||||
// If 0, the node is not at any index in its parent.
|
||||
typedef PRInt32 CacheEntry;
|
||||
|
||||
class SystemAllocPolicy {
|
||||
public:
|
||||
|
@ -116,7 +97,30 @@ private:
|
|||
typedef js::HashMap<nsIContent*, CacheEntry, js::DefaultHasher<nsIContent*>,
|
||||
SystemAllocPolicy> Cache;
|
||||
|
||||
Cache mCache;
|
||||
/**
|
||||
* Returns true if aResult has been set to the correct value for aChild and
|
||||
* no more work needs to be done. Returns false otherwise.
|
||||
*
|
||||
* aResult is an inout parameter. The in value is the number of elements
|
||||
* that are in the half-open range (aSibling, aChild] (so including aChild
|
||||
* but not including aSibling) that match aChild. The out value is the
|
||||
* correct index for aChild if this function returns true and the number of
|
||||
* elements in the closed range [aSibling, aChild] that match aChild
|
||||
* otherwise.
|
||||
*/
|
||||
inline bool IndexDeterminedFromPreviousSibling(nsIContent* aSibling,
|
||||
Element* aChild,
|
||||
bool aIsOfType,
|
||||
bool aIsFromEnd,
|
||||
const Cache& aCache,
|
||||
PRInt32& aResult);
|
||||
|
||||
// Caches of indices for :nth-child(), :nth-last-child(),
|
||||
// :nth-of-type(), :nth-last-of-type(), keyed by Element*.
|
||||
//
|
||||
// The first subscript is 0 for -child and 1 for -of-type, the second
|
||||
// subscript is 0 for nth- and 1 for nth-last-.
|
||||
Cache mCaches[2][2];
|
||||
};
|
||||
|
||||
#endif /* nsContentIndexCache_h__ */
|
||||
|
|
|
@ -66,6 +66,10 @@ NS_NewDeckFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
|
|||
|
||||
NS_IMPL_FRAMEARENA_HELPERS(nsDeckFrame)
|
||||
|
||||
NS_QUERYFRAME_HEAD(nsDeckFrame)
|
||||
NS_QUERYFRAME_ENTRY(nsDeckFrame)
|
||||
NS_QUERYFRAME_TAIL_INHERITING(nsBoxFrame)
|
||||
|
||||
|
||||
nsDeckFrame::nsDeckFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
|
||||
: nsBoxFrame(aPresShell, aContext), mIndex(0)
|
||||
|
@ -92,7 +96,7 @@ nsDeckFrame::AttributeChanged(PRInt32 aNameSpaceID,
|
|||
|
||||
// if the index changed hide the old element and make the new element visible
|
||||
if (aAttribute == nsGkAtoms::selectedIndex) {
|
||||
IndexChanged(PresContext());
|
||||
IndexChanged();
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
@ -110,68 +114,14 @@ nsDeckFrame::Init(nsIContent* aContent,
|
|||
return rv;
|
||||
}
|
||||
|
||||
static void
|
||||
CreateViewsForFrames(const nsFrameList& aFrames)
|
||||
void
|
||||
nsDeckFrame::HideBox(nsIBox* aBox)
|
||||
{
|
||||
for (nsFrameList::Enumerator f(aFrames); !f.AtEnd(); f.Next()) {
|
||||
nsContainerFrame::CreateViewForFrame(f.get(), true);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDeckFrame::SetInitialChildList(ChildListID aListID,
|
||||
nsFrameList& aChildList)
|
||||
{
|
||||
CreateViewsForFrames(aChildList);
|
||||
return nsBoxFrame::SetInitialChildList(aListID, aChildList);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDeckFrame::AppendFrames(ChildListID aListID,
|
||||
nsFrameList& aFrameList)
|
||||
{
|
||||
CreateViewsForFrames(aFrameList);
|
||||
return nsBoxFrame::AppendFrames(aListID, aFrameList);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDeckFrame::InsertFrames(ChildListID aListID,
|
||||
nsIFrame* aPrevFrame,
|
||||
nsFrameList& aFrameList)
|
||||
{
|
||||
CreateViewsForFrames(aFrameList);
|
||||
return nsBoxFrame::InsertFrames(aListID, aPrevFrame, aFrameList);
|
||||
nsIPresShell::ClearMouseCapture(aBox);
|
||||
}
|
||||
|
||||
void
|
||||
nsDeckFrame::HideBox(nsPresContext* aPresContext, nsIBox* aBox)
|
||||
{
|
||||
nsIView* view = aBox->GetView();
|
||||
|
||||
if (view) {
|
||||
nsIViewManager* viewManager = view->GetViewManager();
|
||||
viewManager->SetViewVisibility(view, nsViewVisibility_kHide);
|
||||
viewManager->ResizeView(view, nsRect(0, 0, 0, 0));
|
||||
|
||||
nsIPresShell::ClearMouseCapture(aBox);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDeckFrame::ShowBox(nsPresContext* aPresContext, nsIBox* aBox)
|
||||
{
|
||||
nsRect rect = aBox->GetRect();
|
||||
nsIView* view = aBox->GetView();
|
||||
if (view) {
|
||||
nsIViewManager* viewManager = view->GetViewManager();
|
||||
rect.x = rect.y = 0;
|
||||
viewManager->ResizeView(view, rect);
|
||||
viewManager->SetViewVisibility(view, nsViewVisibility_kShow);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDeckFrame::IndexChanged(nsPresContext* aPresContext)
|
||||
nsDeckFrame::IndexChanged()
|
||||
{
|
||||
//did the index change?
|
||||
PRInt32 index = GetSelectedIndex();
|
||||
|
@ -184,14 +134,9 @@ nsDeckFrame::IndexChanged(nsPresContext* aPresContext)
|
|||
// hide the currently showing box
|
||||
nsIBox* currentBox = GetSelectedBox();
|
||||
if (currentBox) // only hide if it exists
|
||||
HideBox(aPresContext, currentBox);
|
||||
HideBox(currentBox);
|
||||
|
||||
mIndex = index;
|
||||
|
||||
// show the new box
|
||||
nsIBox* newBox = GetSelectedBox();
|
||||
if (newBox) // only show if it exists
|
||||
ShowBox(aPresContext, newBox);
|
||||
}
|
||||
|
||||
PRInt32
|
||||
|
@ -213,7 +158,7 @@ nsDeckFrame::GetSelectedIndex()
|
|||
return index;
|
||||
}
|
||||
|
||||
nsIBox*
|
||||
nsIFrame*
|
||||
nsDeckFrame::GetSelectedBox()
|
||||
{
|
||||
return (mIndex >= 0) ? mFrames.FrameAt(mIndex) : nsnull;
|
||||
|
@ -267,10 +212,8 @@ nsDeckFrame::DoLayout(nsBoxLayoutState& aState)
|
|||
while (box)
|
||||
{
|
||||
// make collapsed children not show up
|
||||
if (count == mIndex)
|
||||
ShowBox(aState.PresContext(), box);
|
||||
else
|
||||
HideBox(aState.PresContext(), box);
|
||||
if (count != mIndex)
|
||||
HideBox(box);
|
||||
|
||||
box = box->GetNextBox();
|
||||
count++;
|
||||
|
|
|
@ -51,6 +51,8 @@
|
|||
class nsDeckFrame : public nsBoxFrame
|
||||
{
|
||||
public:
|
||||
NS_DECL_QUERYFRAME_TARGET(nsDeckFrame)
|
||||
NS_DECL_QUERYFRAME
|
||||
NS_DECL_FRAMEARENA_HELPERS
|
||||
|
||||
friend nsIFrame* NS_NewDeckFrame(nsIPresShell* aPresShell,
|
||||
|
@ -74,16 +76,6 @@ public:
|
|||
nsIFrame* aParent,
|
||||
nsIFrame* aPrevInFlow);
|
||||
|
||||
// Override SetInitialChildList/AppendFrames/InsertFrames to
|
||||
// create views for our child frames if necessary
|
||||
NS_IMETHOD SetInitialChildList(ChildListID aListID,
|
||||
nsFrameList& aChildList);
|
||||
NS_IMETHOD AppendFrames(ChildListID aListID,
|
||||
nsFrameList& aFrameList);
|
||||
NS_IMETHOD InsertFrames(ChildListID aListID,
|
||||
nsIFrame* aPrevFrame,
|
||||
nsFrameList& aFrameList);
|
||||
|
||||
virtual nsIAtom* GetType() const;
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
|
@ -95,14 +87,13 @@ public:
|
|||
|
||||
nsDeckFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
|
||||
|
||||
nsIFrame* GetSelectedBox();
|
||||
|
||||
protected:
|
||||
|
||||
// REVIEW: Sorry, I couldn't resist devirtualizing these.
|
||||
nsIBox* GetSelectedBox();
|
||||
void IndexChanged(nsPresContext* aPresContext);
|
||||
void IndexChanged();
|
||||
PRInt32 GetSelectedIndex();
|
||||
void HideBox(nsPresContext* aPresContext, nsIBox* aBox);
|
||||
void ShowBox(nsPresContext* aPresContext, nsIBox* aBox);
|
||||
void HideBox(nsIBox* aBox);
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -50,8 +50,8 @@ class nsRegion;
|
|||
class nsIntRegion;
|
||||
|
||||
#define NS_IVIEWOBSERVER_IID \
|
||||
{ 0xdc283a18, 0x61cb, 0x468c, \
|
||||
{ 0x8d, 0xb8, 0x9b, 0x81, 0xf7, 0xc9, 0x33, 0x25 } }
|
||||
{ 0xac6eec35, 0x65d2, 0x4fe8, \
|
||||
{ 0xa1, 0x37, 0x1a, 0xc3, 0xf6, 0x51, 0x52, 0x56 } }
|
||||
|
||||
class nsIViewObserver : public nsISupports
|
||||
{
|
||||
|
@ -145,6 +145,11 @@ public:
|
|||
*/
|
||||
NS_IMETHOD_(void) ClearMouseCapture(nsIView* aView) = 0;
|
||||
|
||||
/**
|
||||
* Returns true if the view observer is visible in some way. Otherwise false.
|
||||
*/
|
||||
NS_IMETHOD_(bool) IsVisible() = 0;
|
||||
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIViewObserver, NS_IVIEWOBSERVER_IID)
|
||||
|
|
|
@ -265,7 +265,7 @@ void nsViewManager::DoSetWindowDimensions(nscoord aWidth, nscoord aHeight)
|
|||
NS_IMETHODIMP nsViewManager::SetWindowDimensions(nscoord aWidth, nscoord aHeight)
|
||||
{
|
||||
if (mRootView) {
|
||||
if (mRootView->IsEffectivelyVisible()) {
|
||||
if (mRootView->IsEffectivelyVisible() && mObserver && mObserver->IsVisible()) {
|
||||
if (mDelayedResize != nsSize(NSCOORD_NONE, NSCOORD_NONE) &&
|
||||
mDelayedResize != nsSize(aWidth, aHeight)) {
|
||||
// We have a delayed resize; that now obsolete size may already have
|
||||
|
@ -827,7 +827,8 @@ NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent,
|
|||
? vm->mRootView->GetParent()->GetViewManager()
|
||||
: nsnull) {
|
||||
if (vm->mDelayedResize != nsSize(NSCOORD_NONE, NSCOORD_NONE) &&
|
||||
vm->mRootView->IsEffectivelyVisible()) {
|
||||
vm->mRootView->IsEffectivelyVisible() &&
|
||||
mObserver && mObserver->IsVisible()) {
|
||||
vm->FlushDelayedResize(true);
|
||||
|
||||
// Paint later.
|
||||
|
|
Загрузка…
Ссылка в новой задаче