merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2015-06-05 15:25:08 +02:00
commit 0f0eb9d111
2744 changed files with 68314 additions and 5333 deletions

View File

@ -1836,9 +1836,9 @@ pref("ui.key.menuAccessKeyFocuses", true);
// Encrypted media extensions.
pref("media.eme.enabled", true);
pref("media.eme.apiVisible", true);
pref("browser.eme.ui.enabled", true);
#ifdef MOZ_ADOBE_EME
pref("browser.eme.ui.enabled", true);
pref("media.gmp-eme-adobe.enabled", true);
#endif

View File

@ -1,4 +1,3 @@
[DEFAULT]
skip-if = e10s # Bug 1170385 - csp-on-violate-policy message not sent in browser tests with e10s
[browser_test_web_manifest.js]
[browser_test_web_manifest_mixed_content.js]

View File

@ -4670,6 +4670,7 @@ CanvasRenderingContext2D::DrawWindow(nsGlobalWindow& window, double x,
if (!sw || !sh) {
return;
}
nsRefPtr<gfxContext> thebes;
RefPtr<DrawTarget> drawDT;
// Rendering directly is faster and can be done if mTarget supports Azure
@ -4818,6 +4819,51 @@ CanvasRenderingContext2D::AsyncDrawXULElement(nsXULElement& elem,
#endif
}
void
CanvasRenderingContext2D::DrawWidgetAsOnScreen(nsGlobalWindow& aWindow,
mozilla::ErrorResult& error)
{
EnsureTarget();
// This is an internal API.
if (!nsContentUtils::IsCallerChrome()) {
error.Throw(NS_ERROR_DOM_SECURITY_ERR);
return;
}
nsRefPtr<nsPresContext> presContext;
nsIDocShell* docshell = aWindow.GetDocShell();
if (docshell) {
docshell->GetPresContext(getter_AddRefs(presContext));
}
if (!presContext) {
error.Throw(NS_ERROR_FAILURE);
return;
}
nsIWidget* widget = presContext->GetRootWidget();
if (!widget) {
error.Throw(NS_ERROR_FAILURE);
return;
}
RefPtr<SourceSurface> snapshot = widget->SnapshotWidgetOnScreen();
if (!snapshot) {
error.Throw(NS_ERROR_FAILURE);
return;
}
mgfx::Rect sourceRect(mgfx::Point(0, 0), mgfx::Size(snapshot->GetSize()));
mTarget->DrawSurface(snapshot, sourceRect, sourceRect,
DrawSurfaceOptions(mgfx::Filter::POINT),
DrawOptions(GlobalAlpha(), CompositionOp::OP_OVER,
AntialiasMode::NONE));
mTarget->Flush();
RedrawUser(gfxRect(0, 0,
std::min(mWidth, snapshot->GetSize().width),
std::min(mHeight, snapshot->GetSize().height)));
}
//
// device pixel getting/setting
//

View File

@ -402,6 +402,7 @@ public:
void DrawWindow(nsGlobalWindow& window, double x, double y, double w, double h,
const nsAString& bgColor, uint32_t flags,
mozilla::ErrorResult& error);
void DrawWidgetAsOnScreen(nsGlobalWindow& aWindow, mozilla::ErrorResult& error);
void AsyncDrawXULElement(nsXULElement& elem, double x, double y, double w,
double h, const nsAString& bgColor, uint32_t flags,
mozilla::ErrorResult& error);

View File

@ -1806,8 +1806,8 @@ SetFullAlpha(void* data, GLenum format, GLenum type, size_t width,
{
if (format == LOCAL_GL_ALPHA && type == LOCAL_GL_UNSIGNED_BYTE) {
// Just memset the rows.
uint8_t* row = static_cast<uint8_t*>(data);
for (size_t j = 0; j < height; ++j) {
uint8_t* row = static_cast<uint8_t*>(data) + j*stride;
memset(row, 0xff, width);
row += stride;
}

View File

@ -734,10 +734,8 @@ skip-if = os == 'android'
[webgl-conformance/_wrappers/test_conformance__rendering__gl-scissor-test.html]
[webgl-conformance/_wrappers/test_conformance__rendering__more-than-65536-indices.html]
[webgl-conformance/_wrappers/test_conformance__rendering__point-size.html]
fail-if = (os == 'mac' && os_version == '10.10')
[webgl-conformance/_wrappers/test_conformance__rendering__triangle.html]
[webgl-conformance/_wrappers/test_conformance__rendering__line-loop-tri-fan.html]
fail-if = (os == 'mac' && os_version == '10.10')
[webgl-conformance/_wrappers/test_conformance__state__gl-enable-enum-test.html]
[webgl-conformance/_wrappers/test_conformance__state__gl-enum-tests.html]
[webgl-conformance/_wrappers/test_conformance__state__gl-get-calls.html]
@ -746,7 +744,6 @@ fail-if = (os == 'mac' && os_version == '10.10')
[webgl-conformance/_wrappers/test_conformance__state__gl-object-get-calls.html]
[webgl-conformance/_wrappers/test_conformance__textures__compressed-tex-image.html]
[webgl-conformance/_wrappers/test_conformance__textures__copy-tex-image-and-sub-image-2d.html]
fail-if = (os == 'mac' && os_version == '10.10')
[webgl-conformance/_wrappers/test_conformance__textures__gl-pixelstorei.html]
[webgl-conformance/_wrappers/test_conformance__textures__gl-teximage.html]
skip-if = (os == 'android') || (os == 'b2g') || (os == 'linux')

View File

@ -108,15 +108,6 @@ fail-if = (os == 'linux')
[_wrappers/test_conformance__canvas__drawingbuffer-static-canvas-test.html]
# Intermittent crash on OSX.
skip-if = os == 'mac'
[_wrappers/test_conformance__rendering__line-loop-tri-fan.html]
# Fails on OS X 10.10
fail-if = (os == 'mac' && os_version == '10.10')
[_wrappers/test_conformance__rendering__point-size.html]
# Fails on OS X 10.10
fail-if = (os == 'mac' && os_version == '10.10')
[_wrappers/test_conformance__textures__copy-tex-image-and-sub-image-2d.html]
# Fails on OS X 10.10
fail-if = (os == 'mac' && os_version == '10.10')
########################################################################
# Win

View File

@ -140,6 +140,10 @@ public:
MOZ_ASSERT(IsValid() && aOther.IsValid());
return mValue.value() == aOther.mValue.value();
}
bool operator != (const TimeUnit& aOther) const {
MOZ_ASSERT(IsValid() && aOther.IsValid());
return mValue.value() != aOther.mValue.value();
}
bool operator >= (const TimeUnit& aOther) const {
MOZ_ASSERT(IsValid() && aOther.IsValid());
return mValue.value() >= aOther.mValue.value();

View File

@ -41,7 +41,7 @@ class AppendDataRunnable : public nsRunnable {
public:
AppendDataRunnable(SourceBuffer* aSourceBuffer,
MediaLargeByteBuffer* aData,
double aTimestampOffset,
TimeUnit aTimestampOffset,
uint32_t aUpdateID)
: mSourceBuffer(aSourceBuffer)
, mData(aData)
@ -60,7 +60,7 @@ public:
private:
nsRefPtr<SourceBuffer> mSourceBuffer;
nsRefPtr<MediaLargeByteBuffer> mData;
double mTimestampOffset;
TimeUnit mTimestampOffset;
uint32_t mUpdateID;
};
@ -140,10 +140,7 @@ SourceBuffer::GetBuffered(ErrorResult& aRv)
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return nullptr;
}
// We only manage a single trackbuffer in our source buffer.
// As such, there's no need to adjust the end of the trackbuffers as per
// Step 4: http://w3c.github.io/media-source/index.html#widl-SourceBuffer-buffered
media::TimeIntervals ranges = mTrackBuffer->Buffered();
TimeIntervals ranges = mContentManager->Buffered();
MSE_DEBUGV("ranges=%s", DumpTimeRanges(ranges).get());
nsRefPtr<dom::TimeRanges> tr = new dom::TimeRanges();
ranges.ToTimeRanges(tr);
@ -175,8 +172,7 @@ SourceBuffer::SetAppendWindowEnd(double aAppendWindowEnd, ErrorResult& aRv)
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
if (IsNaN(aAppendWindowEnd) ||
aAppendWindowEnd <= mAppendWindowStart) {
if (IsNaN(aAppendWindowEnd) || aAppendWindowEnd <= mAppendWindowStart) {
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
return;
}
@ -215,12 +211,9 @@ SourceBuffer::Abort(ErrorResult& aRv)
return;
}
AbortBufferAppend();
mTrackBuffer->ResetParserState();
mContentManager->ResetParserState();
mAppendWindowStart = 0;
mAppendWindowEnd = PositiveInfinity<double>();
// Discard the current decoder so no new data will be added to it.
MSE_DEBUG("Discarding decoder");
mTrackBuffer->DiscardCurrentDecoder();
}
void
@ -230,7 +223,7 @@ SourceBuffer::AbortBufferAppend()
mPendingAppend.DisconnectIfExists();
// TODO: Abort segment parser loop, and stream append loop algorithms.
// cancel any pending buffer append.
mTrackBuffer->AbortAppendData();
mContentManager->AbortAppendData();
AbortUpdating();
}
}
@ -277,9 +270,9 @@ void
SourceBuffer::DoRangeRemoval(double aStart, double aEnd)
{
MSE_DEBUG("DoRangeRemoval(%f, %f)", aStart, aEnd);
if (mTrackBuffer && !IsInfinite(aStart)) {
mTrackBuffer->RangeRemoval(media::TimeUnit::FromSeconds(aStart),
media::TimeUnit::FromSeconds(aEnd));
if (mContentManager && !IsInfinite(aStart)) {
mContentManager->RangeRemoval(TimeUnit::FromSeconds(aStart),
TimeUnit::FromSeconds(aEnd));
}
}
@ -289,10 +282,10 @@ SourceBuffer::Detach()
MOZ_ASSERT(NS_IsMainThread());
MSE_DEBUG("Detach");
AbortBufferAppend();
if (mTrackBuffer) {
mTrackBuffer->Detach();
if (mContentManager) {
mContentManager->Detach();
}
mTrackBuffer = nullptr;
mContentManager = nullptr;
mMediaSource = nullptr;
}
@ -302,7 +295,7 @@ SourceBuffer::Ended()
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(IsAttached());
MSE_DEBUG("Ended");
mTrackBuffer->EndCurrentDecoder();
mContentManager->Ended();
}
SourceBuffer::SourceBuffer(MediaSource* aMediaSource, const nsACString& aType)
@ -321,9 +314,9 @@ SourceBuffer::SourceBuffer(MediaSource* aMediaSource, const nsACString& aType)
MOZ_ASSERT(aMediaSource);
mEvictionThreshold = Preferences::GetUint("media.mediasource.eviction_threshold",
75 * (1 << 20));
mTrackBuffer = new TrackBuffer(aMediaSource->GetDecoder(), aType);
MSE_DEBUG("Create mTrackBuffer=%p",
mTrackBuffer.get());
mContentManager = SourceBufferContentManager::CreateManager(aMediaSource->GetDecoder(), aType);
MSE_DEBUG("Create mContentManager=%p",
mContentManager.get());
}
SourceBuffer::~SourceBuffer()
@ -425,12 +418,12 @@ SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aR
MOZ_ASSERT(mAppendMode == SourceBufferAppendMode::Segments,
"We don't handle timestampOffset for sequence mode yet");
nsCOMPtr<nsIRunnable> task =
new AppendDataRunnable(this, data, mTimestampOffset, mUpdateID);
new AppendDataRunnable(this, data, TimeUnit::FromSeconds(mTimestampOffset), mUpdateID);
NS_DispatchToMainThread(task);
}
void
SourceBuffer::AppendData(MediaLargeByteBuffer* aData, double aTimestampOffset,
SourceBuffer::AppendData(MediaLargeByteBuffer* aData, TimeUnit aTimestampOffset,
uint32_t aUpdateID)
{
if (!mUpdating || aUpdateID != mUpdateID) {
@ -451,14 +444,14 @@ SourceBuffer::AppendData(MediaLargeByteBuffer* aData, double aTimestampOffset,
return;
}
mPendingAppend.Begin(mTrackBuffer->AppendData(aData, aTimestampOffset * USECS_PER_S)
mPendingAppend.Begin(mContentManager->AppendData(aData, aTimestampOffset)
->Then(AbstractThread::MainThread(), __func__, this,
&SourceBuffer::AppendDataCompletedWithSuccess,
&SourceBuffer::AppendDataErrored));
}
void
SourceBuffer::AppendDataCompletedWithSuccess(bool aGotMedia)
SourceBuffer::AppendDataCompletedWithSuccess(bool aHasActiveTracks)
{
mPendingAppend.Complete();
if (!mUpdating) {
@ -466,7 +459,7 @@ SourceBuffer::AppendDataCompletedWithSuccess(bool aGotMedia)
return;
}
if (mTrackBuffer->HasInitSegment()) {
if (aHasActiveTracks) {
if (!mActive) {
mActive = true;
mMediaSource->SourceBufferIsActive(this);
@ -474,9 +467,7 @@ SourceBuffer::AppendDataCompletedWithSuccess(bool aGotMedia)
}
}
if (aGotMedia) {
CheckEndTime();
}
CheckEndTime();
StopUpdating();
}
@ -504,7 +495,7 @@ SourceBuffer::AppendError(bool aDecoderError)
// The buffer append algorithm has been interrupted by abort().
return;
}
mTrackBuffer->ResetParserState();
mContentManager->ResetParserState();
mUpdating = false;
@ -522,6 +513,8 @@ SourceBuffer::AppendError(bool aDecoderError)
already_AddRefed<MediaLargeByteBuffer>
SourceBuffer::PrepareAppend(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv)
{
typedef SourceBufferContentManager::EvictDataResult Result;
if (!IsAttached() || mUpdating) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return nullptr;
@ -538,29 +531,29 @@ SourceBuffer::PrepareAppend(const uint8_t* aData, uint32_t aLength, ErrorResult&
// TODO: Make the eviction threshold smaller for audio-only streams.
// TODO: Drive evictions off memory pressure notifications.
// TODO: Consider a global eviction threshold rather than per TrackBuffer.
double newBufferStartTime = 0.0;
TimeUnit newBufferStartTime;
// Attempt to evict the amount of data we are about to add by lowering the
// threshold.
uint32_t toEvict =
(mEvictionThreshold > aLength) ? mEvictionThreshold - aLength : aLength;
bool evicted =
mTrackBuffer->EvictData(mMediaSource->GetDecoder()->GetCurrentTime(),
toEvict, &newBufferStartTime);
if (evicted) {
Result evicted =
mContentManager->EvictData(TimeUnit::FromSeconds(mMediaSource->GetDecoder()->GetCurrentTime()),
toEvict, &newBufferStartTime);
if (evicted == Result::DATA_EVICTED) {
MSE_DEBUG("AppendData Evict; current buffered start=%f",
GetBufferedStart());
// We notify that we've evicted from the time range 0 through to
// the current start point.
mMediaSource->NotifyEvicted(0.0, newBufferStartTime);
mMediaSource->NotifyEvicted(0.0, newBufferStartTime.ToSeconds());
}
// See if we have enough free space to append our new data.
// As we can only evict once we have playable data, we must give a chance
// to the DASH player to provide a complete media segment.
if (aLength > mEvictionThreshold ||
((mTrackBuffer->GetSize() > mEvictionThreshold - aLength) &&
!mTrackBuffer->HasOnlyIncompleteMedia())) {
((mContentManager->GetSize() > mEvictionThreshold - aLength) &&
evicted != Result::CANT_EVICT)) {
aRv.Throw(NS_ERROR_DOM_QUOTA_EXCEEDED_ERR);
return nullptr;
}
@ -603,15 +596,15 @@ SourceBuffer::Evict(double aStart, double aEnd)
if (currentTime + safety_threshold >= evictTime) {
evictTime -= safety_threshold;
}
mTrackBuffer->EvictBefore(evictTime);
mContentManager->EvictBefore(TimeUnit::FromSeconds(evictTime));
}
#if defined(DEBUG)
void
SourceBuffer::Dump(const char* aPath)
{
if (mTrackBuffer) {
mTrackBuffer->Dump(aPath);
if (mContentManager) {
mContentManager->Dump(aPath);
}
}
#endif
@ -620,9 +613,9 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(SourceBuffer)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(SourceBuffer)
// Tell the TrackBuffer to end its current SourceBufferResource.
TrackBuffer* track = tmp->mTrackBuffer;
if (track) {
track->Detach();
SourceBufferContentManager* manager = tmp->mContentManager;
if (manager) {
manager->Detach();
}
NS_IMPL_CYCLE_COLLECTION_UNLINK(mMediaSource)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED(DOMEventTargetHelper)

View File

@ -23,6 +23,7 @@
#include "nsISupports.h"
#include "nsString.h"
#include "nscore.h"
#include "SourceBufferContentManager.h"
class JSObject;
struct JSContext;
@ -33,10 +34,12 @@ class ErrorResult;
class MediaLargeByteBuffer;
class TrackBuffer;
template <typename T> class AsyncEventRunner;
typedef MediaPromise<bool, nsresult, /* IsExclusive = */ true> TrackBufferAppendPromise;
namespace dom {
using media::TimeUnit;
using media::TimeIntervals;
class TimeRanges;
class SourceBuffer final : public DOMEventTargetHelper
@ -147,7 +150,7 @@ private:
// Shared implementation of AppendBuffer overloads.
void AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv);
void AppendData(MediaLargeByteBuffer* aData, double aTimestampOffset,
void AppendData(MediaLargeByteBuffer* aData, TimeUnit aTimestampOffset,
uint32_t aAppendID);
// Implement the "Append Error Algorithm".
@ -162,14 +165,14 @@ private:
uint32_t aLength,
ErrorResult& aRv);
void AppendDataCompletedWithSuccess(bool aValue);
void AppendDataCompletedWithSuccess(bool aHasActiveTracks);
void AppendDataErrored(nsresult aError);
nsRefPtr<MediaSource> mMediaSource;
uint32_t mEvictionThreshold;
nsRefPtr<TrackBuffer> mTrackBuffer;
nsRefPtr<SourceBufferContentManager> mContentManager;
double mAppendWindowStart;
double mAppendWindowEnd;
@ -186,7 +189,7 @@ private:
// aborted and another AppendData queued.
uint32_t mUpdateID;
MediaPromiseRequestHolder<TrackBufferAppendPromise> mPendingAppend;
MediaPromiseRequestHolder<SourceBufferContentManager::AppendPromise> mPendingAppend;
const nsCString mType;
};

View File

@ -0,0 +1,20 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "SourceBufferContentManager.h"
namespace mozilla {
already_AddRefed<SourceBufferContentManager>
SourceBufferContentManager::CreateManager(MediaSourceDecoder* aParentDecoder,
const nsACString &aType)
{
nsRefPtr<SourceBufferContentManager> manager;
manager = new TrackBuffer(aParentDecoder, aType);
return manager.forget();
}
}

View File

@ -0,0 +1,89 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef MOZILLA_SOURCEBUFFERCONTENTMANAGER_H_
#define MOZILLA_SOURCEBUFFERCONTENTMANAGER_H_
#include "MediaData.h"
#include "MediaPromise.h"
#include "MediaSourceDecoder.h"
#include "SourceBuffer.h"
#include "TimeUnits.h"
#include "nsString.h"
namespace mozilla {
using media::TimeUnit;
using media::TimeIntervals;
class SourceBufferContentManager {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SourceBufferContentManager);
typedef MediaPromise<bool, nsresult, /* IsExclusive = */ true> AppendPromise;
static already_AddRefed<SourceBufferContentManager>
CreateManager(MediaSourceDecoder* aParentDecoder, const nsACString& aType);
// Append data to the current decoder. Also responsible for calling
// NotifyDataArrived on the decoder to keep buffered range computation up
// to date. Returns false if the append failed.
virtual nsRefPtr<AppendPromise>
AppendData(MediaLargeByteBuffer* aData, TimeUnit aTimestampOffset /* microseconds */) = 0;
// Abort any pending AppendData.
virtual void AbortAppendData() = 0;
// Run MSE Reset Parser State Algorithm.
// 3.5.2 Reset Parser State
// http://w3c.github.io/media-source/#sourcebuffer-reset-parser-state
virtual void ResetParserState() = 0;
// Runs MSE range removal algorithm.
// http://w3c.github.io/media-source/#sourcebuffer-coded-frame-removal
virtual bool RangeRemoval(TimeUnit aStart, TimeUnit aEnd) = 0;
enum class EvictDataResult : int8_t
{
NO_DATA_EVICTED,
DATA_EVICTED,
CANT_EVICT,
};
// Evicts data up to aPlaybackTime. aThreshold is used to
// bound the data being evicted. It will not evict more than aThreshold
// bytes. aBufferStartTime contains the new start time of the data after the
// eviction.
virtual EvictDataResult
EvictData(TimeUnit aPlaybackTime, uint32_t aThreshold, TimeUnit* aBufferStartTime) = 0;
// Evicts data up to aTime.
virtual void EvictBefore(TimeUnit aTime) = 0;
// Returns the buffered range currently managed.
// This may be called on any thread.
// Buffered must conform to http://w3c.github.io/media-source/index.html#widl-SourceBuffer-buffered
virtual media::TimeIntervals Buffered() = 0;
// Return the size of the data managed by this SourceBufferContentManager.
virtual int64_t GetSize() = 0;
// Indicate that the MediaSource parent object got into "ended" state.
virtual void Ended() = 0;
// The parent SourceBuffer is about to be destroyed.
virtual void Detach() = 0;
#if defined(DEBUG)
virtual void Dump(const char* aPath) { }
#endif
protected:
virtual ~SourceBufferContentManager() { }
};
} // namespace mozilla
#endif /* MOZILLA_SOURCEBUFFERCONTENTMANAGER_H_ */

View File

@ -42,8 +42,6 @@ TrackBuffer::TrackBuffer(MediaSourceDecoder* aParentDecoder, const nsACString& a
: mParentDecoder(aParentDecoder)
, mType(aType)
, mLastStartTimestamp(0)
, mLastTimestampOffset(0)
, mAdjustedTimestamp(0)
, mIsWaitingOnCDM(false)
, mShutdown(false)
{
@ -75,7 +73,7 @@ public:
}
}
bool NewDecoder(int64_t aTimestampOffset)
bool NewDecoder(TimeUnit aTimestampOffset)
{
nsRefPtr<SourceBufferDecoder> decoder = mOwner->NewDecoder(aTimestampOffset);
if (!decoder) {
@ -140,14 +138,14 @@ TrackBuffer::ContinueShutdown()
mShutdownPromise.Resolve(true, __func__);
}
nsRefPtr<TrackBufferAppendPromise>
TrackBuffer::AppendData(MediaLargeByteBuffer* aData, int64_t aTimestampOffset)
nsRefPtr<TrackBuffer::AppendPromise>
TrackBuffer::AppendData(MediaLargeByteBuffer* aData, TimeUnit aTimestampOffset)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mInitializationPromise.IsEmpty());
DecodersToInitialize decoders(this);
nsRefPtr<TrackBufferAppendPromise> p = mInitializationPromise.Ensure(__func__);
nsRefPtr<AppendPromise> p = mInitializationPromise.Ensure(__func__);
bool hadInitData = mParser->HasInitData();
bool hadCompleteInitData = mParser->HasCompleteInitData();
nsRefPtr<MediaLargeByteBuffer> oldInit = mParser->InitData();
@ -221,11 +219,13 @@ TrackBuffer::AppendData(MediaLargeByteBuffer* aData, int64_t aTimestampOffset)
mLastEndTimestamp.emplace(end);
}
if (gotMedia && start != mAdjustedTimestamp &&
((start < 0 && -start < FUZZ_TIMESTAMP_OFFSET && start < mAdjustedTimestamp) ||
(start > 0 && (start < FUZZ_TIMESTAMP_OFFSET || start < mAdjustedTimestamp)))) {
AdjustDecodersTimestampOffset(mAdjustedTimestamp - start);
mAdjustedTimestamp = start;
TimeUnit starttu{TimeUnit::FromMicroseconds(start)};
if (gotMedia && starttu != mAdjustedTimestamp &&
((start < 0 && -start < FUZZ_TIMESTAMP_OFFSET && starttu < mAdjustedTimestamp) ||
(start > 0 && (start < FUZZ_TIMESTAMP_OFFSET || starttu < mAdjustedTimestamp)))) {
AdjustDecodersTimestampOffset(mAdjustedTimestamp - starttu);
mAdjustedTimestamp = starttu;
}
if (!AppendDataToCurrentResource(aData, end - start)) {
@ -243,7 +243,7 @@ TrackBuffer::AppendData(MediaLargeByteBuffer* aData, int64_t aTimestampOffset)
// required when data is appended.
NotifyTimeRangesChanged();
mInitializationPromise.Resolve(gotMedia, __func__);
mInitializationPromise.Resolve(HasInitSegment(), __func__);
return p;
}
@ -282,48 +282,49 @@ class DecoderSorter
public:
bool LessThan(SourceBufferDecoder* aFirst, SourceBufferDecoder* aSecond) const
{
media::TimeIntervals first = aFirst->GetBuffered();
media::TimeIntervals second = aSecond->GetBuffered();
TimeIntervals first = aFirst->GetBuffered();
TimeIntervals second = aSecond->GetBuffered();
return first.GetStart() < second.GetStart();
}
bool Equals(SourceBufferDecoder* aFirst, SourceBufferDecoder* aSecond) const
{
media::TimeIntervals first = aFirst->GetBuffered();
media::TimeIntervals second = aSecond->GetBuffered();
TimeIntervals first = aFirst->GetBuffered();
TimeIntervals second = aSecond->GetBuffered();
return first.GetStart() == second.GetStart();
}
};
bool
TrackBuffer::EvictData(double aPlaybackTime,
TrackBuffer::EvictDataResult
TrackBuffer::EvictData(TimeUnit aPlaybackTime,
uint32_t aThreshold,
double* aBufferStartTime)
TimeUnit* aBufferStartTime)
{
MOZ_ASSERT(NS_IsMainThread());
ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
if (!mCurrentDecoder) {
return false;
if (!mCurrentDecoder || mInitializedDecoders.IsEmpty()) {
return EvictDataResult::CANT_EVICT;
}
int64_t totalSize = GetSize();
int64_t toEvict = totalSize - aThreshold;
if (toEvict <= 0 || mInitializedDecoders.IsEmpty()) {
return false;
if (toEvict <= 0) {
return EvictDataResult::NO_DATA_EVICTED;
}
// Get a list of initialized decoders.
nsTArray<SourceBufferDecoder*> decoders;
decoders.AppendElements(mInitializedDecoders);
const TimeUnit evictThresholdTime{TimeUnit::FromSeconds(MSE_EVICT_THRESHOLD_TIME)};
// First try to evict data before the current play position, starting
// with the oldest decoder.
for (uint32_t i = 0; i < decoders.Length() && toEvict > 0; ++i) {
media::TimeIntervals buffered = decoders[i]->GetBuffered();
TimeIntervals buffered = decoders[i]->GetBuffered();
MSE_DEBUG("Step1. decoder=%u/%u threshold=%u toEvict=%lld",
i, decoders.Length(), aThreshold, toEvict);
@ -331,9 +332,8 @@ TrackBuffer::EvictData(double aPlaybackTime,
// To ensure we don't evict data past the current playback position
// we apply a threshold of a few seconds back and evict data up to
// that point.
if (aPlaybackTime > MSE_EVICT_THRESHOLD_TIME) {
media::TimeUnit time = media::TimeUnit::FromSeconds(aPlaybackTime) -
media::TimeUnit::FromSeconds(MSE_EVICT_THRESHOLD_TIME);
if (aPlaybackTime > evictThresholdTime) {
TimeUnit time = aPlaybackTime - evictThresholdTime;
bool isActive = decoders[i] == mCurrentDecoder ||
mParentDecoder->IsActiveReader(decoders[i]->GetReader());
if (!isActive && buffered.GetEnd() < time) {
@ -341,16 +341,16 @@ TrackBuffer::EvictData(double aPlaybackTime,
// It can be fully evicted.
MSE_DEBUG("evicting all bufferedEnd=%f "
"aPlaybackTime=%f time=%f, size=%lld",
buffered.GetEnd().ToSeconds(), aPlaybackTime, time,
decoders[i]->GetResource()->GetSize());
buffered.GetEnd().ToSeconds(), aPlaybackTime.ToSeconds(),
time, decoders[i]->GetResource()->GetSize());
toEvict -= decoders[i]->GetResource()->EvictAll();
} else {
int64_t playbackOffset =
decoders[i]->ConvertToByteOffset(time.ToSeconds());
MSE_DEBUG("evicting some bufferedEnd=%f "
"aPlaybackTime=%f time=%f, playbackOffset=%lld size=%lld",
buffered.GetEnd().ToSeconds(), aPlaybackTime, time,
playbackOffset, decoders[i]->GetResource()->GetSize());
buffered.GetEnd().ToSeconds(), aPlaybackTime.ToSeconds(),
time, playbackOffset, decoders[i]->GetResource()->GetSize());
if (playbackOffset > 0) {
ErrorResult rv;
toEvict -= decoders[i]->GetResource()->EvictData(playbackOffset,
@ -358,7 +358,7 @@ TrackBuffer::EvictData(double aPlaybackTime,
rv);
if (NS_WARN_IF(rv.Failed())) {
rv.SuppressException();
return false;
return EvictDataResult::CANT_EVICT;
}
}
}
@ -376,7 +376,7 @@ TrackBuffer::EvictData(double aPlaybackTime,
if (decoders[i] == mCurrentDecoder) {
continue;
}
media::TimeIntervals buffered = decoders[i]->GetBuffered();
TimeIntervals buffered = decoders[i]->GetBuffered();
// Remove data from older decoders than the current one.
MSE_DEBUG("evicting all "
@ -406,7 +406,7 @@ TrackBuffer::EvictData(double aPlaybackTime,
// Find the next decoder we're likely going to play with.
nsRefPtr<SourceBufferDecoder> nextPlayingDecoder = nullptr;
if (playingDecoder) {
media::TimeIntervals buffered = playingDecoder->GetBuffered();
TimeIntervals buffered = playingDecoder->GetBuffered();
nextPlayingDecoder =
mParentDecoder->SelectDecoder(buffered.GetEnd().ToMicroseconds() + 1,
EOS_FUZZ_US,
@ -423,7 +423,7 @@ TrackBuffer::EvictData(double aPlaybackTime,
decoders[i] == mCurrentDecoder) {
continue;
}
media::TimeIntervals buffered = decoders[i]->GetBuffered();
TimeIntervals buffered = decoders[i]->GetBuffered();
MSE_DEBUG("evicting all "
"bufferedStart=%f bufferedEnd=%f aPlaybackTime=%f size=%lld",
@ -438,12 +438,12 @@ TrackBuffer::EvictData(double aPlaybackTime,
bool evicted = toEvict < (totalSize - aThreshold);
if (evicted) {
if (playingDecoder) {
media::TimeIntervals ranges = playingDecoder->GetBuffered();
*aBufferStartTime = std::max(0.0, ranges.GetStart().ToSeconds());
TimeIntervals ranges = playingDecoder->GetBuffered();
*aBufferStartTime = std::max(TimeUnit::FromSeconds(0), ranges.GetStart());
} else {
// We do not currently have data to play yet.
// Avoid evicting anymore data to minimize rebuffering time.
*aBufferStartTime = 0.0;
*aBufferStartTime = TimeUnit::FromSeconds(0.0);
}
}
@ -451,7 +451,9 @@ TrackBuffer::EvictData(double aPlaybackTime,
NotifyTimeRangesChanged();
}
return evicted;
return evicted ?
EvictDataResult::DATA_EVICTED :
(HasOnlyIncompleteMedia() ? EvictDataResult::CANT_EVICT : EvictDataResult::NO_DATA_EVICTED);
}
void
@ -461,7 +463,7 @@ TrackBuffer::RemoveEmptyDecoders(nsTArray<mozilla::SourceBufferDecoder*>& aDecod
// Remove decoders that have no data in them
for (uint32_t i = 0; i < aDecoders.Length(); ++i) {
media::TimeIntervals buffered = aDecoders[i]->GetBuffered();
TimeIntervals buffered = aDecoders[i]->GetBuffered();
MSE_DEBUG("maybe remove empty decoders=%d "
"size=%lld start=%f end=%f",
i, aDecoders[i]->GetResource()->GetSize(),
@ -495,7 +497,7 @@ TrackBuffer::HasOnlyIncompleteMedia()
if (!mCurrentDecoder) {
return false;
}
media::TimeIntervals buffered = mCurrentDecoder->GetBuffered();
TimeIntervals buffered = mCurrentDecoder->GetBuffered();
MSE_DEBUG("mCurrentDecoder.size=%lld, start=%f end=%f",
mCurrentDecoder->GetResource()->GetSize(),
buffered.GetStart(), buffered.GetEnd());
@ -503,12 +505,12 @@ TrackBuffer::HasOnlyIncompleteMedia()
}
void
TrackBuffer::EvictBefore(double aTime)
TrackBuffer::EvictBefore(TimeUnit aTime)
{
MOZ_ASSERT(NS_IsMainThread());
ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
for (uint32_t i = 0; i < mInitializedDecoders.Length(); ++i) {
int64_t endOffset = mInitializedDecoders[i]->ConvertToByteOffset(aTime);
int64_t endOffset = mInitializedDecoders[i]->ConvertToByteOffset(aTime.ToSeconds());
if (endOffset > 0) {
MSE_DEBUG("decoder=%u offset=%lld",
i, endOffset);
@ -524,12 +526,12 @@ TrackBuffer::EvictBefore(double aTime)
NotifyTimeRangesChanged();
}
media::TimeIntervals
TimeIntervals
TrackBuffer::Buffered()
{
ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
media::TimeIntervals buffered;
TimeIntervals buffered;
for (auto& decoder : mInitializedDecoders) {
buffered += decoder->GetBuffered();
@ -537,14 +539,14 @@ TrackBuffer::Buffered()
// mParser may not be initialized yet, and will only be so if we have a
// buffered range.
if (buffered.Length()) {
buffered.SetFuzz(media::TimeUnit::FromMicroseconds(mParser->GetRoundingError()));
buffered.SetFuzz(TimeUnit::FromMicroseconds(mParser->GetRoundingError()));
}
return buffered;
}
already_AddRefed<SourceBufferDecoder>
TrackBuffer::NewDecoder(int64_t aTimestampOffset)
TrackBuffer::NewDecoder(TimeUnit aTimestampOffset)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mParentDecoder);
@ -552,7 +554,7 @@ TrackBuffer::NewDecoder(int64_t aTimestampOffset)
DiscardCurrentDecoder();
nsRefPtr<SourceBufferDecoder> decoder =
mParentDecoder->CreateSubDecoder(mType, aTimestampOffset - mAdjustedTimestamp);
mParentDecoder->CreateSubDecoder(mType, (aTimestampOffset - mAdjustedTimestamp).ToMicroseconds());
if (!decoder) {
return nullptr;
}
@ -820,7 +822,7 @@ TrackBuffer::CompleteInitializeDecoder(SourceBufferDecoder* aDecoder)
MSE_DEBUG("Reader %p activated",
aDecoder->GetReader());
mInitializationPromise.ResolveIfExists(aDecoder->GetRealMediaDuration() > 0, __func__);
mInitializationPromise.ResolveIfExists(true, __func__);
}
bool
@ -914,10 +916,10 @@ bool
TrackBuffer::ContainsTime(int64_t aTime, int64_t aTolerance)
{
ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
media::TimeUnit time{media::TimeUnit::FromMicroseconds(aTime)};
TimeUnit time{TimeUnit::FromMicroseconds(aTime)};
for (auto& decoder : mInitializedDecoders) {
media::TimeIntervals r = decoder->GetBuffered();
r.SetFuzz(media::TimeUnit::FromMicroseconds(aTolerance));
TimeIntervals r = decoder->GetBuffered();
r.SetFuzz(TimeUnit::FromMicroseconds(aTolerance));
if (r.Contains(time)) {
return true;
}
@ -1073,15 +1075,14 @@ TrackBuffer::RemoveDecoder(SourceBufferDecoder* aDecoder)
}
bool
TrackBuffer::RangeRemoval(media::TimeUnit aStart,
media::TimeUnit aEnd)
TrackBuffer::RangeRemoval(TimeUnit aStart, TimeUnit aEnd)
{
MOZ_ASSERT(NS_IsMainThread());
ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
media::TimeIntervals buffered = Buffered();
media::TimeUnit bufferedStart = buffered.GetStart();
media::TimeUnit bufferedEnd = buffered.GetEnd();
TimeIntervals buffered = Buffered();
TimeUnit bufferedStart = buffered.GetStart();
TimeUnit bufferedEnd = buffered.GetEnd();
if (!buffered.Length() || aStart > bufferedEnd || aEnd < bufferedStart) {
// Nothing to remove.
@ -1101,7 +1102,7 @@ TrackBuffer::RangeRemoval(media::TimeUnit aStart,
if (aStart <= bufferedStart && aEnd < bufferedEnd) {
// Evict data from beginning.
for (size_t i = 0; i < decoders.Length(); ++i) {
media::TimeIntervals buffered = decoders[i]->GetBuffered();
TimeIntervals buffered = decoders[i]->GetBuffered();
if (buffered.GetEnd() < aEnd) {
// Can be fully removed.
MSE_DEBUG("remove all bufferedEnd=%f size=%lld",
@ -1144,11 +1145,11 @@ TrackBuffer::RangeRemoval(media::TimeUnit aStart,
}
void
TrackBuffer::AdjustDecodersTimestampOffset(int32_t aOffset)
TrackBuffer::AdjustDecodersTimestampOffset(TimeUnit aOffset)
{
ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
for (uint32_t i = 0; i < mDecoders.Length(); i++) {
mDecoders[i]->SetTimestampOffset(mDecoders[i]->GetTimestampOffset() + aOffset);
mDecoders[i]->SetTimestampOffset(mDecoders[i]->GetTimestampOffset() + aOffset.ToMicroseconds());
}
}

View File

@ -24,10 +24,8 @@ class ContainerParser;
class MediaSourceDecoder;
class MediaLargeByteBuffer;
class TrackBuffer final {
class TrackBuffer final : public SourceBufferContentManager {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TrackBuffer);
TrackBuffer(MediaSourceDecoder* aParentDecoder, const nsACString& aType);
nsRefPtr<ShutdownPromise> Shutdown();
@ -35,24 +33,38 @@ public:
// Append data to the current decoder. Also responsible for calling
// NotifyDataArrived on the decoder to keep buffered range computation up
// to date. Returns false if the append failed.
nsRefPtr<TrackBufferAppendPromise> AppendData(MediaLargeByteBuffer* aData,
int64_t aTimestampOffset /* microseconds */);
nsRefPtr<AppendPromise> AppendData(MediaLargeByteBuffer* aData,
TimeUnit aTimestampOffset /* microseconds */) override;
// Evicts data held in the current decoders SourceBufferResource from the
// start of the buffer through to aPlaybackTime. aThreshold is used to
// bound the data being evicted. It will not evict more than aThreshold
// bytes. aBufferStartTime contains the new start time of the current
// decoders buffered data after the eviction. Returns true if data was
// evicted.
bool EvictData(double aPlaybackTime, uint32_t aThreshold, double* aBufferStartTime);
// decoders buffered data after the eviction.
EvictDataResult EvictData(TimeUnit aPlaybackTime, uint32_t aThreshold, TimeUnit* aBufferStartTime) override;
// Evicts data held in all the decoders SourceBufferResource from the start
// of the buffer through to aTime.
void EvictBefore(double aTime);
void EvictBefore(TimeUnit aTime) override;
bool RangeRemoval(TimeUnit aStart, TimeUnit aEnd) override;
void AbortAppendData() override;
int64_t GetSize() override;
void ResetParserState() override;
// Returns the union of the decoders buffered ranges in aRanges.
// This may be called on any thread.
media::TimeIntervals Buffered();
media::TimeIntervals Buffered() override;
void Ended() override
{
EndCurrentDecoder();
}
void Detach() override;
// Mark the current decoder's resource as ended, clear mCurrentDecoder and
// reset mLast{Start,End}Timestamp. Main thread only.
@ -60,8 +72,6 @@ public:
// Mark the current decoder's resource as ended.
void EndCurrentDecoder();
void Detach();
// Returns true if an init segment has been appended.
bool HasInitSegment();
@ -77,30 +87,11 @@ public:
void BreakCycles();
// Run MSE Reset Parser State Algorithm.
// 3.5.2 Reset Parser State
// http://w3c.github.io/media-source/#sourcebuffer-reset-parser-state
void ResetParserState();
// Returns a reference to mInitializedDecoders, used by MediaSourceReader
// to select decoders.
// TODO: Refactor to a cleaner interface between TrackBuffer and MediaSourceReader.
const nsTArray<nsRefPtr<SourceBufferDecoder>>& Decoders();
// Runs MSE range removal algorithm.
// http://w3c.github.io/media-source/#sourcebuffer-coded-frame-removal
// Implementation is only partial, we can only trim a buffer.
// Returns true if data was evicted.
// Times are in microseconds.
bool RangeRemoval(mozilla::media::TimeUnit aStart,
mozilla::media::TimeUnit aEnd);
// Abort any pending appendBuffer by rejecting any pending promises.
void AbortAppendData();
// Return the size used by all decoders managed by this TrackBuffer.
int64_t GetSize();
// Return true if we have a partial media segment being appended that is
// currently not playable.
bool HasOnlyIncompleteMedia();
@ -116,14 +107,14 @@ public:
private:
friend class DecodersToInitialize;
friend class MetadataRecipient;
~TrackBuffer();
virtual ~TrackBuffer();
// Create a new decoder, set mCurrentDecoder to the new decoder and
// returns it. The new decoder must be queued using QueueInitializeDecoder
// for initialization.
// The decoder is not considered initialized until it is added to
// mInitializedDecoders.
already_AddRefed<SourceBufferDecoder> NewDecoder(int64_t aTimestampOffset /* microseconds */);
already_AddRefed<SourceBufferDecoder> NewDecoder(TimeUnit aTimestampOffset);
// Helper for AppendData, ensures NotifyDataArrived is called whenever
// data is appended to the current decoder's SourceBufferResource.
@ -201,11 +192,11 @@ private:
// AppendData. Accessed on the main thread only.
int64_t mLastStartTimestamp;
Maybe<int64_t> mLastEndTimestamp;
void AdjustDecodersTimestampOffset(int32_t aOffset);
void AdjustDecodersTimestampOffset(TimeUnit aOffset);
// The timestamp offset used by our current decoder, in microseconds.
int64_t mLastTimestampOffset;
int64_t mAdjustedTimestamp;
// The timestamp offset used by our current decoder.
TimeUnit mLastTimestampOffset;
TimeUnit mAdjustedTimestamp;
// True if at least one of our decoders has encrypted content.
bool mIsWaitingOnCDM;
@ -219,7 +210,7 @@ private:
bool mDecoderPerSegment;
bool mShutdown;
MediaPromiseHolder<TrackBufferAppendPromise> mInitializationPromise;
MediaPromiseHolder<AppendPromise> mInitializationPromise;
// Track our request for metadata from the reader.
MediaPromiseRequestHolder<MediaDecoderReader::MetadataPromise> mMetadataRequest;
};

View File

@ -9,6 +9,7 @@ EXPORTS += [
'AsyncEventRunner.h',
'MediaSourceDecoder.h',
'MediaSourceReader.h',
'SourceBufferContentManager.h',
]
EXPORTS.mozilla.dom += [
@ -25,6 +26,7 @@ UNIFIED_SOURCES += [
'MediaSourceUtils.cpp',
'ResourceQueue.cpp',
'SourceBuffer.cpp',
'SourceBufferContentManager.cpp',
'SourceBufferDecoder.cpp',
'SourceBufferList.cpp',
'SourceBufferResource.cpp',

View File

@ -135,11 +135,17 @@ function setupEnvironment() {
['media.peerconnection.enabled', true],
['media.peerconnection.identity.enabled', true],
['media.peerconnection.identity.timeout', 12000],
['media.peerconnection.ice.stun_client_maximum_transmits', 14],
['media.peerconnection.ice.trickle_grace_period', 30000],
['media.navigator.permission.disabled', true],
['media.getusermedia.screensharing.enabled', true],
['media.getusermedia.screensharing.allowed_domains', "mochi.test"]
]
}, setTestOptions);
// We don't care about waiting for this to complete, we just want to ensure
// that we don't build up a huge backlog of GC work.
SpecialPowers.exactGC(window);
}
// This is called by steeplechase; which provides the test configuration options

View File

@ -1,7 +1,7 @@
[DEFAULT]
# strictContentSandbox - bug 1042735, Android 2.3 - bug 981881
tags = msg webrtc
skip-if = (os == 'win' && strictContentSandbox) || android_version == '10' || android_version == '18' || (buildapp == 'mulet')
skip-if = (os == 'win' && strictContentSandbox) || android_version == '10' || android_version == '18' || (buildapp == 'mulet') || (toolkit == 'gonk' && debug) # b2g(Either bug 1171118 or bug 1169838, take your pick)
support-files =
head.js
dataChannel.js
@ -23,13 +23,11 @@ skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video suppo
[test_dataChannel_basicAudioVideoCombined.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
[test_dataChannel_basicDataOnly.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
[test_dataChannel_basicVideo.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
[test_dataChannel_bug1013809.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g emulator seems to be too slow (Bug 1016498 and 1008080)
[test_dataChannel_noOffer.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
[test_enumerateDevices.html]
skip-if = buildapp == 'mulet'
[test_getUserMedia_basicAudio.html]
@ -45,41 +43,29 @@ skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' # no
[test_getUserMedia_basicVideoAudio.html]
skip-if = (toolkit == 'gonk' || buildapp == 'mulet' && debug) # debug-only failure, turned an intermittent (bug 962579) into a permanant orange
[test_getUserMedia_constraints.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' || toolkit == 'android' # Bug 1063290, intermittent timeout
[test_getUserMedia_callbacks.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' || toolkit == 'android' || buildapp == 'mulet' # Bug 1063290, intermittent timeout # TC: Bug 1144079 - Re-enable Mulet mochitests and reftests taskcluster-specific disables.
[test_getUserMedia_gumWithinGum.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' || toolkit == 'android' # Bug 1063290, intermittent timeout
[test_getUserMedia_playAudioTwice.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' || toolkit == 'android' # Bug 1063290, intermittent timeout
[test_getUserMedia_playVideoAudioTwice.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' || toolkit == 'android' # Bug 1063290, intermittent timeout # bug 926558, debug-only failure
[test_getUserMedia_playVideoTwice.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' || toolkit == 'android' # Bug 1063290, intermittent timeout
[test_getUserMedia_stopAudioStream.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' || toolkit == 'android' # Bug 1063290, intermittent timeout
[test_getUserMedia_stopAudioStreamWithFollowupAudio.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' || toolkit == 'android' # Bug 1063290, intermittent timeout
[test_getUserMedia_stopVideoAudioStream.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' || toolkit == 'android' # Bug 1063290, intermittent timeout # bug 926558, debug-only failure
[test_getUserMedia_stopVideoAudioStreamWithFollowupVideoAudio.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' || toolkit == 'android' # Bug 1063290, intermittent timeout
[test_getUserMedia_stopVideoStream.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' || toolkit == 'android' # Bug 1063290, intermittent timeout
[test_getUserMedia_stopVideoStreamWithFollowupVideo.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' || toolkit == 'android' # Bug 1063290, intermittent timeout
[test_getUserMedia_peerIdentity.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 1021776, too --ing slow on b2g)
[test_peerConnection_addIceCandidate.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
[test_peerConnection_basicAudio.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
skip-if = toolkit == 'gonk' # B2G emulator is too slow to handle a two-way audio call reliably
[test_peerConnection_basicAudioVideo.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
[test_peerConnection_basicAudioVideoCombined.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
[test_peerConnection_basicAudioVideoNoBundle.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
[test_peerConnection_basicVideo.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
[test_peerConnection_basicScreenshare.html]
@ -93,15 +79,12 @@ skip-if = buildapp == 'b2g' || buildapp == 'mulet' || toolkit == 'android' || e1
[test_peerConnection_basicH264Video.html]
skip-if = buildapp == 'b2g' || buildapp == 'mulet' || os == 'android' # bug 1043403 # Bug 1141029 Mulet parity with B2G Desktop for TC
[test_peerConnection_bug822674.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
[test_peerConnection_bug825703.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
[test_peerConnection_bug827843.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
[test_peerConnection_bug834153.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
[test_peerConnection_bug1013809.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g emulator seems to be too slow (Bug 1016498 and 1008080)
skip-if = toolkit == 'gonk' # B2G emulator is too slow to handle a two-way audio call reliably
[test_peerConnection_bug1042791.html]
skip-if = buildapp == 'b2g' || buildapp == 'mulet' || os == 'android' # bug 1043403 # Bug 1141029 Mulet parity with B2G Desktop for TC
[test_peerConnection_capturedVideo.html]
@ -112,19 +95,16 @@ skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video suppo
[test_peerConnection_captureStream_canvas_webgl.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
[test_peerConnection_close.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
[test_peerConnection_errorCallbacks.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
[test_peerConnection_forwarding_basicAudioVideoCombined.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
[test_peerConnection_noTrickleAnswer.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
skip-if = toolkit == 'gonk' # B2G emulator is too slow to handle a two-way audio call reliably
[test_peerConnection_noTrickleOffer.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
skip-if = toolkit == 'gonk' # B2G emulator is too slow to handle a two-way audio call reliably
[test_peerConnection_noTrickleOfferAnswer.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
skip-if = toolkit == 'gonk' # B2G emulator is too slow to handle a two-way audio call reliably
[test_peerConnection_offerRequiresReceiveAudio.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
[test_peerConnection_offerRequiresReceiveVideo.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
[test_peerConnection_offerRequiresReceiveVideoAudio.html]
@ -138,62 +118,55 @@ skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video suppo
[test_peerConnection_syncSetDescription.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
[test_peerConnection_setLocalAnswerInHaveLocalOffer.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
[test_peerConnection_setLocalAnswerInStable.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
[test_peerConnection_setLocalOfferInHaveRemoteOffer.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
[test_peerConnection_setRemoteAnswerInHaveRemoteOffer.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
[test_peerConnection_setRemoteAnswerInStable.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
[test_peerConnection_setRemoteOfferInHaveLocalOffer.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
[test_peerConnection_throwInCallbacks.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
[test_peerConnection_toJSON.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
[test_peerConnection_twoAudioStreams.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
[test_peerConnection_twoAudioTracksInOneStream.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
[test_peerConnection_twoAudioVideoStreams.html]
skip-if = (toolkit == 'gonk' || buildapp == 'mulet') # b2g (Bug 1059867)
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
[test_peerConnection_twoAudioVideoStreamsCombined.html]
skip-if = (toolkit == 'gonk' || buildapp == 'mulet') # b2g (Bug 1059867)
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
[test_peerConnection_twoVideoStreams.html]
skip-if = (toolkit == 'gonk' || buildapp == 'mulet') # b2g (Bug 1059867)
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
[test_peerConnection_twoVideoTracksInOneStream.html]
skip-if = (toolkit == 'gonk' || buildapp == 'mulet') # b2g (Bug 1059867)
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
[test_peerConnection_addSecondAudioStream.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
skip-if = toolkit == 'gonk' # B2G emulator is too slow to finish a renegotiation test in under 5 minutes
[test_peerConnection_answererAddSecondAudioStream.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
skip-if = toolkit == 'gonk' # B2G emulator is too slow to finish a renegotiation test in under 5 minutes
[test_peerConnection_removeAudioTrack.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
skip-if = toolkit == 'gonk' # B2G emulator is too slow to finish a renegotiation test in under 5 minutes
[test_peerConnection_removeThenAddAudioTrack.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
skip-if = toolkit == 'gonk' # B2G emulator is too slow to finish a renegotiation test in under 5 minutes
[test_peerConnection_addSecondVideoStream.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
skip-if = toolkit == 'gonk' # B2G emulator is too slow to finish a renegotiation test in under 5 minutes
[test_peerConnection_removeVideoTrack.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
skip-if = toolkit == 'gonk' # B2G emulator is too slow to finish a renegotiation test in under 5 minutes
[test_peerConnection_removeThenAddVideoTrack.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
skip-if = toolkit == 'gonk' # B2G emulator is too slow to finish a renegotiation test in under 5 minutes
[test_peerConnection_replaceVideoThenRenegotiate.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
skip-if = toolkit == 'gonk' # B2G emulator is too slow to finish a renegotiation test in under 5 minutes
[test_peerConnection_addSecondAudioStreamNoBundle.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
skip-if = toolkit == 'gonk' # B2G emulator is too slow to finish a renegotiation test in under 5 minutes
[test_peerConnection_removeThenAddAudioTrackNoBundle.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
skip-if = toolkit == 'gonk' # B2G emulator is too slow to finish a renegotiation test in under 5 minutes
[test_peerConnection_addSecondVideoStreamNoBundle.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
skip-if = toolkit == 'gonk' # B2G emulator is too slow to finish a renegotiation test in under 5 minutes
[test_peerConnection_removeThenAddVideoTrackNoBundle.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
skip-if = toolkit == 'gonk' # B2G emulator is too slow to finish a renegotiation test in under 5 minutes
[test_peerConnection_addDataChannel.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
skip-if = toolkit == 'gonk' # B2G emulator seems to be so slow that DTLS cannot establish properly
[test_peerConnection_addDataChannelNoBundle.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
skip-if = toolkit == 'gonk' # B2G emulator seems to be so slow that DTLS cannot establish properly
[test_peerConnection_webAudio.html]
tags = webaudio webrtc
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)

View File

@ -615,7 +615,7 @@ function DataChannelWrapper(dataChannel, peerConnectionWrapper) {
is(this.readyState, "open", "data channel is 'open' after 'onopen'");
resolve(this);
};
}), 60000, "channel didn't open in time");
}), 180000, "channel didn't open in time");
}
DataChannelWrapper.prototype = {

View File

@ -224,6 +224,18 @@ interface CanvasRenderingContext2D {
void asyncDrawXULElement(XULElement elem, double x, double y, double w,
double h, DOMString bgColor,
optional unsigned long flags = 0);
/**
* Render the root widget of a window into the canvas. Unlike drawWindow,
* this uses the operating system to snapshot the widget on-screen, rather
* than reading from our own compositor.
*
* Currently, this is only supported on Windows, and only on widgets that
* use OMTC, and only from within the chrome process.
*/
[Throws, ChromeOnly]
void drawWidgetAsOnScreen(Window window);
/**
* This causes a context that is currently using a hardware-accelerated
* backend to fallback to a software one. All state should be preserved.

View File

@ -2565,10 +2565,9 @@ GLContext::Readback(SharedSurface* src, gfx::DataSourceSurface* dest)
{
ScopedBindFramebuffer autoFB(this);
// Even though we're reading. We're doing it on
// the producer side. So we call ProducerAcquire
// instead of ConsumerAcquire.
src->ProducerAcquire();
// We're consuming from the producer side, so which do we use?
// Really, we just want a read-only lock, so ConsumerAcquire is the best match.
src->ProducerReadAcquire();
if (src->mAttachType == AttachmentType::Screen) {
fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
@ -2595,7 +2594,7 @@ GLContext::Readback(SharedSurface* src, gfx::DataSourceSurface* dest)
ReadPixelsIntoDataSurface(this, dest);
src->ProducerRelease();
src->ProducerReadRelease();
}
if (tempFB)

View File

@ -21,6 +21,7 @@
#include "ScopedGLHelpers.h"
#include "gfx2DGlue.h"
#include "../layers/ipc/ShadowLayers.h"
#include "mozilla/layers/TextureClientSharedSurface.h"
namespace mozilla {
namespace gl {
@ -39,55 +40,43 @@ GLScreenBuffer::Create(GLContext* gl,
return Move(ret);
}
UniquePtr<SurfaceFactory> factory;
#ifdef MOZ_WIDGET_GONK
/* On B2G, we want a Gralloc factory, and we want one right at the start */
layers::ISurfaceAllocator* allocator = caps.surfaceAllocator;
if (!factory &&
allocator &&
XRE_GetProcessType() != GeckoProcessType_Default)
{
layers::TextureFlags flags = layers::TextureFlags::DEALLOCATE_CLIENT |
layers::TextureFlags::ORIGIN_BOTTOM_LEFT;
if (!caps.premultAlpha) {
flags |= layers::TextureFlags::NON_PREMULTIPLIED;
}
layers::TextureFlags flags = layers::TextureFlags::ORIGIN_BOTTOM_LEFT;
if (!caps.premultAlpha) {
flags |= layers::TextureFlags::NON_PREMULTIPLIED;
}
factory = MakeUnique<SurfaceFactory_Gralloc>(gl, caps, flags,
allocator);
}
#endif
#ifdef XP_MACOSX
/* On OSX, we want an IOSurface factory, and we want one right at the start */
if (!factory) {
factory = SurfaceFactory_IOSurface::Create(gl, caps);
}
#endif
if (!factory) {
factory = MakeUnique<SurfaceFactory_Basic>(gl, caps);
}
UniquePtr<SurfaceFactory> factory = MakeUnique<SurfaceFactory_Basic>(gl, caps, flags);
ret.reset( new GLScreenBuffer(gl, caps, Move(factory)) );
return Move(ret);
}
GLScreenBuffer::GLScreenBuffer(GLContext* gl,
const SurfaceCaps& caps,
UniquePtr<SurfaceFactory> factory)
: mGL(gl)
, mCaps(caps)
, mFactory(Move(factory))
, mNeedsBlit(true)
, mUserReadBufferMode(LOCAL_GL_BACK)
, mUserDrawFB(0)
, mUserReadFB(0)
, mInternalDrawFB(0)
, mInternalReadFB(0)
#ifdef DEBUG
, mInInternalMode_DrawFB(true)
, mInInternalMode_ReadFB(true)
#endif
{ }
GLScreenBuffer::~GLScreenBuffer()
{
mFactory = nullptr;
mDraw = nullptr;
mRead = nullptr;
// bug 914823: it is crucial to destroy the Factory _after_ we destroy
// the SharedSurfaces around here! Reason: the shared surfaces will want
// to ask the Allocator (e.g. the ClientLayerManager) to destroy their
// buffers, but that Allocator may be kept alive by the Factory,
// as it currently the case in SurfaceFactory_Gralloc holding a nsRefPtr
// to the Allocator!
mFactory = nullptr;
}
void
GLScreenBuffer::BindAsFramebuffer(GLContext* const gl, GLenum target) const
{
@ -465,7 +454,7 @@ GLScreenBuffer::Attach(SharedSurface* surf, const gfx::IntSize& size)
bool
GLScreenBuffer::Swap(const gfx::IntSize& size)
{
RefPtr<ShSurfHandle> newBack = mFactory->NewShSurfHandle(size);
RefPtr<SharedSurfaceTextureClient> newBack = mFactory->NewTexClient(size);
if (!newBack)
return false;
@ -522,7 +511,7 @@ GLScreenBuffer::PublishFrame(const gfx::IntSize& size)
bool
GLScreenBuffer::Resize(const gfx::IntSize& size)
{
RefPtr<ShSurfHandle> newBack = mFactory->NewShSurfHandle(size);
RefPtr<SharedSurfaceTextureClient> newBack = mFactory->NewTexClient(size);
if (!newBack)
return false;

View File

@ -24,6 +24,10 @@
#include "SurfaceTypes.h"
namespace mozilla {
namespace layers {
class SharedSurfaceTextureClient;
}
namespace gl {
class GLContext;
@ -136,8 +140,8 @@ public:
protected:
UniquePtr<SurfaceFactory> mFactory;
RefPtr<ShSurfHandle> mBack;
RefPtr<ShSurfHandle> mFront;
RefPtr<layers::SharedSurfaceTextureClient> mBack;
RefPtr<layers::SharedSurfaceTextureClient> mFront;
UniquePtr<DrawBuffer> mDraw;
UniquePtr<ReadBuffer> mRead;
@ -159,21 +163,7 @@ protected:
GLScreenBuffer(GLContext* gl,
const SurfaceCaps& caps,
UniquePtr<SurfaceFactory> factory)
: mGL(gl)
, mCaps(caps)
, mFactory(Move(factory))
, mNeedsBlit(true)
, mUserReadBufferMode(LOCAL_GL_BACK)
, mUserDrawFB(0)
, mUserReadFB(0)
, mInternalDrawFB(0)
, mInternalReadFB(0)
#ifdef DEBUG
, mInInternalMode_DrawFB(true)
, mInInternalMode_ReadFB(true)
#endif
{}
UniquePtr<SurfaceFactory> factory);
public:
virtual ~GLScreenBuffer();
@ -182,7 +172,7 @@ public:
return mFactory.get();
}
ShSurfHandle* Front() const {
const RefPtr<layers::SharedSurfaceTextureClient>& Front() const {
return mFront;
}

View File

@ -12,6 +12,9 @@
#include "nsThreadUtils.h"
#include "ScopedGLHelpers.h"
#include "SharedSurfaceGL.h"
#include "mozilla/layers/CompositorTypes.h"
#include "mozilla/layers/TextureClientSharedSurface.h"
#include "mozilla/unused.h"
namespace mozilla {
namespace gl {
@ -32,12 +35,9 @@ SharedSurface::ProdCopy(SharedSurface* src, SharedSurface* dest,
dest->mAttachType == AttachmentType::Screen)
{
// Here, we actually need to blit through a temp surface, so let's make one.
UniquePtr<SharedSurface_GLTexture> tempSurf;
tempSurf = SharedSurface_GLTexture::Create(gl,
gl,
factory->mFormats,
src->mSize,
factory->mCaps.alpha);
UniquePtr<SharedSurface_Basic> tempSurf;
tempSurf = SharedSurface_Basic::Create(gl, factory->mFormats, src->mSize,
factory->mCaps.alpha);
ProdCopy(src, tempSurf.get(), factory);
ProdCopy(tempSurf.get(), dest, factory);
@ -203,20 +203,21 @@ SharedSurface::SharedSurface(SharedSurfaceType type,
AttachmentType attachType,
GLContext* gl,
const gfx::IntSize& size,
bool hasAlpha)
bool hasAlpha,
bool canRecycle)
: mType(type)
, mAttachType(attachType)
, mGL(gl)
, mSize(size)
, mHasAlpha(hasAlpha)
, mCanRecycle(canRecycle)
, mIsLocked(false)
, mIsProducerAcquired(false)
, mIsConsumerAcquired(false)
#ifdef DEBUG
, mOwningThread(NS_GetCurrentThread())
#endif
{
}
{ }
void
SharedSurface::LockProd()
@ -262,8 +263,6 @@ SharedSurface::PollSync_ContentThread()
return PollSync_ContentThread_Impl();
}
////////////////////////////////////////////////////////////////////////
// SurfaceFactory
@ -301,12 +300,15 @@ ChooseBufferBits(const SurfaceCaps& caps,
}
}
SurfaceFactory::SurfaceFactory(GLContext* gl,
SharedSurfaceType type,
const SurfaceCaps& caps)
: mGL(gl)
SurfaceFactory::SurfaceFactory(SharedSurfaceType type, GLContext* gl,
const SurfaceCaps& caps,
const RefPtr<layers::ISurfaceAllocator>& allocator,
const layers::TextureFlags& flags)
: mType(type)
, mGL(gl)
, mCaps(caps)
, mType(type)
, mAllocator(allocator)
, mFlags(flags)
, mFormats(gl->ChooseGLFormats(caps))
{
ChooseBufferBits(mCaps, &mDrawCaps, &mReadCaps);
@ -314,51 +316,95 @@ SurfaceFactory::SurfaceFactory(GLContext* gl,
SurfaceFactory::~SurfaceFactory()
{
while (!mScraps.Empty()) {
mScraps.Pop();
}
}
UniquePtr<SharedSurface>
SurfaceFactory::NewSharedSurface(const gfx::IntSize& size)
{
// Attempt to reuse an old surface.
while (!mScraps.Empty()) {
UniquePtr<SharedSurface> cur = mScraps.Pop();
if (cur->mSize == size)
return Move(cur);
// Let `cur` be destroyed as it falls out of scope, if it wasn't
// moved.
while (!mRecycleTotalPool.empty()) {
StopRecycling(*mRecycleTotalPool.begin());
}
return CreateShared(size);
MOZ_RELEASE_ASSERT(mRecycleTotalPool.empty());
// If we mRecycleFreePool.clear() before StopRecycling(), we may try to recycle it,
// fail, call StopRecycling(), then return here and call it again.
mRecycleFreePool.clear();
}
TemporaryRef<ShSurfHandle>
SurfaceFactory::NewShSurfHandle(const gfx::IntSize& size)
TemporaryRef<layers::SharedSurfaceTextureClient>
SurfaceFactory::NewTexClient(const gfx::IntSize& size)
{
auto surf = NewSharedSurface(size);
while (!mRecycleFreePool.empty()) {
RefPtr<layers::SharedSurfaceTextureClient> cur = mRecycleFreePool.front();
mRecycleFreePool.pop();
if (cur->Surf()->mSize == size) {
return cur.forget();
}
StopRecycling(cur);
}
UniquePtr<SharedSurface> surf = Move(CreateShared(size));
if (!surf)
return nullptr;
// Before next use, wait until SharedSurface's buffer
// is no longer being used.
surf->WaitForBufferOwnership();
RefPtr<layers::SharedSurfaceTextureClient> ret;
ret = new layers::SharedSurfaceTextureClient(mAllocator, mFlags, Move(surf), this);
return MakeAndAddRef<ShSurfHandle>(this, Move(surf));
StartRecycling(ret);
return ret.forget();
}
// Auto-deletes surfs of the wrong type.
void
SurfaceFactory::Recycle(UniquePtr<SharedSurface> surf)
SurfaceFactory::StartRecycling(layers::SharedSurfaceTextureClient* tc)
{
MOZ_ASSERT(surf);
tc->SetRecycleCallback(&SurfaceFactory::RecycleCallback, static_cast<void*>(this));
if (surf->mType == mType) {
mScraps.Push(Move(surf));
bool didInsert = mRecycleTotalPool.insert(tc);
MOZ_RELEASE_ASSERT(didInsert);
mozilla::unused << didInsert;
}
void
SurfaceFactory::StopRecycling(layers::SharedSurfaceTextureClient* tc)
{
// Must clear before releasing ref.
tc->ClearRecycleCallback();
bool didErase = mRecycleTotalPool.erase(tc);
MOZ_RELEASE_ASSERT(didErase);
mozilla::unused << didErase;
}
/*static*/ void
SurfaceFactory::RecycleCallback(layers::TextureClient* rawTC, void* rawFactory)
{
MOZ_ASSERT(NS_IsMainThread());
RefPtr<layers::SharedSurfaceTextureClient> tc;
tc = static_cast<layers::SharedSurfaceTextureClient*>(rawTC);
SurfaceFactory* factory = static_cast<SurfaceFactory*>(rawFactory);
if (tc->mSurf->mCanRecycle) {
if (factory->Recycle(tc))
return;
}
// Did not recover the tex client. End the (re)cycle!
factory->StopRecycling(tc);
}
bool
SurfaceFactory::Recycle(layers::SharedSurfaceTextureClient* texClient)
{
MOZ_ASSERT(texClient);
if (mRecycleFreePool.size() >= 2) {
return false;
}
RefPtr<layers::SharedSurfaceTextureClient> texClientRef = texClient;
mRecycleFreePool.push(texClientRef);
return true;
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -16,6 +16,7 @@
#define SHARED_SURFACE_H_
#include <queue>
#include <set>
#include <stdint.h>
#include "GLContextTypes.h"
@ -34,6 +35,15 @@ namespace mozilla {
namespace gfx {
class DrawTarget;
}
namespace layers {
class ISurfaceAllocator;
class SharedSurfaceTextureClient;
enum class TextureFlags : uint32_t;
class SurfaceDescriptor;
class TextureClient;
}
namespace gl {
class GLContext;
@ -51,6 +61,7 @@ public:
GLContext* const mGL;
const gfx::IntSize mSize;
const bool mHasAlpha;
const bool mCanRecycle;
protected:
bool mIsLocked;
bool mIsProducerAcquired;
@ -61,7 +72,8 @@ protected:
AttachmentType attachType,
GLContext* gl,
const gfx::IntSize& size,
bool hasAlpha);
bool hasAlpha,
bool canRecycle);
public:
virtual ~SharedSurface() {
@ -86,6 +98,8 @@ protected:
virtual void ProducerReleaseImpl() {
Fence();
}
virtual void ProducerReadAcquireImpl() {}
virtual void ProducerReadReleaseImpl() {}
virtual void ConsumerAcquireImpl() {
WaitSync();
}
@ -102,6 +116,16 @@ public:
ProducerReleaseImpl();
mIsProducerAcquired = false;
}
void ProducerReadAcquire() {
MOZ_ASSERT(!mIsProducerAcquired);
ProducerReadAcquireImpl();
mIsProducerAcquired = true;
}
void ProducerReadRelease() {
MOZ_ASSERT(mIsProducerAcquired);
ProducerReadReleaseImpl();
mIsProducerAcquired = false;
}
void ConsumerAcquire() {
MOZ_ASSERT(!mIsConsumerAcquired);
ConsumerAcquireImpl();
@ -173,36 +197,91 @@ public:
virtual bool NeedsIndirectReads() const {
return false;
}
virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) = 0;
};
template<typename T>
class UniquePtrQueue
class RefSet
{
std::set<T*> mSet;
public:
~RefSet() {
clear();
}
auto begin() -> decltype(mSet.begin()) {
return mSet.begin();
}
void clear() {
for (auto itr = mSet.begin(); itr != mSet.end(); ++itr) {
(*itr)->Release();
}
mSet.clear();
}
bool empty() const {
return mSet.empty();
}
bool insert(T* x) {
if (mSet.insert(x).second) {
x->AddRef();
return true;
}
return false;
}
bool erase(T* x) {
if (mSet.erase(x)) {
x->Release();
return true;
}
return false;
}
};
template<typename T>
class RefQueue
{
std::queue<T*> mQueue;
public:
~UniquePtrQueue() {
MOZ_ASSERT(Empty());
~RefQueue() {
clear();
}
bool Empty() const {
void clear() {
while (!empty()) {
pop();
}
}
bool empty() const {
return mQueue.empty();
}
void Push(UniquePtr<T> up) {
T* p = up.release();
mQueue.push(p);
size_t size() const {
return mQueue.size();
}
UniquePtr<T> Pop() {
UniquePtr<T> ret;
void push(T* x) {
mQueue.push(x);
x->AddRef();
}
if (!mQueue.empty()) {
ret.reset(mQueue.front());
mQueue.pop();
}
T* front() const {
return mQueue.front();
}
return Move(ret);
void pop() {
T* x = mQueue.front();
x->Release();
mQueue.pop();
}
};
@ -213,18 +292,21 @@ public:
// with SupportsWeakPtr. (bug 1049278)
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(SurfaceFactory)
const SharedSurfaceType mType;
GLContext* const mGL;
const SurfaceCaps mCaps;
const SharedSurfaceType mType;
const RefPtr<layers::ISurfaceAllocator> mAllocator;
const layers::TextureFlags mFlags;
const GLFormats mFormats;
protected:
SurfaceCaps mDrawCaps;
SurfaceCaps mReadCaps;
RefQueue<layers::SharedSurfaceTextureClient> mRecycleFreePool;
RefSet<layers::SharedSurfaceTextureClient> mRecycleTotalPool;
SurfaceFactory(GLContext* gl,
SharedSurfaceType type,
const SurfaceCaps& caps);
SurfaceFactory(SharedSurfaceType type, GLContext* gl, const SurfaceCaps& caps,
const RefPtr<layers::ISurfaceAllocator>& allocator,
const layers::TextureFlags& flags);
public:
virtual ~SurfaceFactory();
@ -240,44 +322,19 @@ public:
protected:
virtual UniquePtr<SharedSurface> CreateShared(const gfx::IntSize& size) = 0;
UniquePtrQueue<SharedSurface> mScraps;
void StartRecycling(layers::SharedSurfaceTextureClient* tc);
void SetRecycleCallback(layers::SharedSurfaceTextureClient* tc);
void StopRecycling(layers::SharedSurfaceTextureClient* tc);
public:
UniquePtr<SharedSurface> NewSharedSurface(const gfx::IntSize& size);
TemporaryRef<ShSurfHandle> NewShSurfHandle(const gfx::IntSize& size);
//TemporaryRef<ShSurfHandle> NewShSurfHandle(const gfx::IntSize& size);
TemporaryRef<layers::SharedSurfaceTextureClient> NewTexClient(const gfx::IntSize& size);
static void RecycleCallback(layers::TextureClient* tc, void* /*closure*/);
// Auto-deletes surfs of the wrong type.
void Recycle(UniquePtr<SharedSurface> surf);
};
class ShSurfHandle : public RefCounted<ShSurfHandle>
{
public:
MOZ_DECLARE_REFCOUNTED_TYPENAME(ShSurfHandle)
private:
const WeakPtr<SurfaceFactory> mFactory;
UniquePtr<SharedSurface> mSurf;
public:
ShSurfHandle(SurfaceFactory* factory, UniquePtr<SharedSurface> surf)
: mFactory(factory)
, mSurf(Move(surf))
{
MOZ_ASSERT(mFactory);
MOZ_ASSERT(mSurf);
}
~ShSurfHandle() {
if (mFactory) {
mFactory->Recycle(Move(mSurf));
}
}
SharedSurface* Surf() const {
MOZ_ASSERT(mSurf.get());
return mSurf.get();
}
bool Recycle(layers::SharedSurfaceTextureClient* texClient);
};
class ScopedReadbackFB

View File

@ -4,11 +4,12 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "SharedSurfaceANGLE.h"
#include "GLContextEGL.h"
#include "GLLibraryEGL.h"
#include <d3d11.h>
#include "gfxWindowsPlatform.h"
#include "GLContextEGL.h"
#include "GLLibraryEGL.h"
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc
namespace mozilla {
namespace gl {
@ -105,7 +106,8 @@ SharedSurface_ANGLEShareHandle::SharedSurface_ANGLEShareHandle(GLContext* gl,
AttachmentType::Screen,
gl,
size,
hasAlpha)
hasAlpha,
true)
, mEGL(egl)
, mContext(context)
, mPBuffer(pbuffer)
@ -182,6 +184,21 @@ SharedSurface_ANGLEShareHandle::ProducerReleaseImpl()
Fence();
}
void
SharedSurface_ANGLEShareHandle::ProducerReadAcquireImpl()
{
ProducerAcquireImpl();
}
void
SharedSurface_ANGLEShareHandle::ProducerReadReleaseImpl()
{
if (mKeyedMutex) {
mKeyedMutex->ReleaseSync(0);
return;
}
}
void
SharedSurface_ANGLEShareHandle::ConsumerAcquireImpl()
{
@ -253,6 +270,16 @@ SharedSurface_ANGLEShareHandle::PollSync_ContentThread_Impl()
return PollSync();
}
bool
SharedSurface_ANGLEShareHandle::ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor)
{
gfx::SurfaceFormat format = mHasAlpha ? gfx::SurfaceFormat::B8G8R8A8
: gfx::SurfaceFormat::B8G8R8X8;
*out_descriptor = layers::SurfaceDescriptorD3D10((WindowsHandle)mShareHandle, format,
mSize);
return true;
}
////////////////////////////////////////////////////////////////////////////////
// Factory
@ -388,8 +415,9 @@ ChooseConfig(GLContext* gl, GLLibraryEGL* egl, const SurfaceCaps& caps)
}
/*static*/ UniquePtr<SurfaceFactory_ANGLEShareHandle>
SurfaceFactory_ANGLEShareHandle::Create(GLContext* gl,
const SurfaceCaps& caps)
SurfaceFactory_ANGLEShareHandle::Create(GLContext* gl, const SurfaceCaps& caps,
const RefPtr<layers::ISurfaceAllocator>& allocator,
const layers::TextureFlags& flags)
{
GLLibraryEGL* egl = &sEGLLibrary;
if (!egl)
@ -401,7 +429,7 @@ SurfaceFactory_ANGLEShareHandle::Create(GLContext* gl,
bool success;
typedef SurfaceFactory_ANGLEShareHandle ptrT;
UniquePtr<ptrT> ret( new ptrT(gl, egl, caps, &success) );
UniquePtr<ptrT> ret( new ptrT(gl, caps, allocator, flags, egl, &success) );
if (!success)
return nullptr;
@ -410,10 +438,12 @@ SurfaceFactory_ANGLEShareHandle::Create(GLContext* gl,
}
SurfaceFactory_ANGLEShareHandle::SurfaceFactory_ANGLEShareHandle(GLContext* gl,
GLLibraryEGL* egl,
const SurfaceCaps& caps,
const RefPtr<layers::ISurfaceAllocator>& allocator,
const layers::TextureFlags& flags,
GLLibraryEGL* egl,
bool* const out_success)
: SurfaceFactory(gl, SharedSurfaceType::EGLSurfaceANGLE, caps)
: SurfaceFactory(SharedSurfaceType::EGLSurfaceANGLE, gl, caps, allocator, flags)
, mProdGL(gl)
, mEGL(egl)
{

View File

@ -38,7 +38,9 @@ protected:
GLLibraryEGL* const mEGL;
const EGLContext mContext;
const EGLSurface mPBuffer;
public:
const HANDLE mShareHandle;
protected:
RefPtr<IDXGIKeyedMutex> mKeyedMutex;
RefPtr<IDXGIKeyedMutex> mConsumerKeyedMutex;
RefPtr<ID3D11Texture2D> mConsumerTexture;
@ -66,6 +68,8 @@ public:
virtual void Fence() override;
virtual void ProducerAcquireImpl() override;
virtual void ProducerReleaseImpl() override;
virtual void ProducerReadAcquireImpl() override;
virtual void ProducerReadReleaseImpl() override;
virtual void ConsumerAcquireImpl() override;
virtual void ConsumerReleaseImpl() override;
virtual bool WaitSync() override;
@ -75,14 +79,11 @@ public:
virtual bool WaitSync_ContentThread_Impl() override;
virtual bool PollSync_ContentThread_Impl() override;
// Implementation-specific functions below:
HANDLE GetShareHandle() {
return mShareHandle;
}
const RefPtr<ID3D11Texture2D>& GetConsumerTexture() const {
return mConsumerTexture;
}
virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) override;
};
@ -98,12 +99,14 @@ protected:
public:
static UniquePtr<SurfaceFactory_ANGLEShareHandle> Create(GLContext* gl,
const SurfaceCaps& caps);
const SurfaceCaps& caps,
const RefPtr<layers::ISurfaceAllocator>& allocator,
const layers::TextureFlags& flags);
protected:
SurfaceFactory_ANGLEShareHandle(GLContext* gl,
GLLibraryEGL* egl,
const SurfaceCaps& caps,
SurfaceFactory_ANGLEShareHandle(GLContext* gl, const SurfaceCaps& caps,
const RefPtr<layers::ISurfaceAllocator>& allocator,
const layers::TextureFlags& flags, GLLibraryEGL* egl,
bool* const out_success);
virtual UniquePtr<SharedSurface> CreateShared(const gfx::IntSize& size) override {

View File

@ -9,6 +9,7 @@
#include "GLContextEGL.h"
#include "GLLibraryEGL.h"
#include "GLReadTexImageHelper.h"
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc
#include "ScopedGLHelpers.h"
#include "SharedSurface.h"
#include "TextureGarbageBin.h"
@ -72,7 +73,8 @@ SharedSurface_EGLImage::SharedSurface_EGLImage(GLContext* gl,
AttachmentType::GLTexture,
gl,
size,
hasAlpha)
hasAlpha,
false) // Can't recycle, as mSync changes never update TextureHost.
, mMutex("SharedSurface_EGLImage mutex")
, mEGL(egl)
, mFormats(formats)
@ -115,6 +117,7 @@ SharedSurface_EGLImage::Fence()
mGL->IsExtensionSupported(GLContext::OES_EGL_sync))
{
if (mSync) {
MOZ_RELEASE_ASSERT(false, "Non-recycleable should not Fence twice.");
MOZ_ALWAYS_TRUE( mEGL->fDestroySync(Display(), mSync) );
mSync = 0;
}
@ -152,14 +155,7 @@ SharedSurface_EGLImage::WaitSync()
0,
LOCAL_EGL_FOREVER);
if (status != LOCAL_EGL_CONDITION_SATISFIED) {
return false;
}
MOZ_ALWAYS_TRUE( mEGL->fDestroySync(Display(), mSync) );
mSync = 0;
return true;
return status == LOCAL_EGL_CONDITION_SATISFIED;
}
bool
@ -177,14 +173,8 @@ SharedSurface_EGLImage::PollSync()
mSync,
LOCAL_EGL_SYNC_STATUS_KHR,
&status) );
if (status != LOCAL_EGL_SIGNALED_KHR) {
return false;
}
MOZ_ALWAYS_TRUE( mEGL->fDestroySync(mEGL->Display(), mSync) );
mSync = 0;
return true;
return status == LOCAL_EGL_SIGNALED_KHR;
}
EGLDisplay
@ -215,10 +205,20 @@ SharedSurface_EGLImage::AcquireConsumerTexture(GLContext* consGL, GLuint* out_te
*out_target = LOCAL_GL_TEXTURE_EXTERNAL;
}
bool
SharedSurface_EGLImage::ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor)
{
*out_descriptor = layers::EGLImageDescriptor((uintptr_t)mImage, (uintptr_t)mSync,
mSize, mHasAlpha);
return true;
}
////////////////////////////////////////////////////////////////////////
/*static*/ UniquePtr<SurfaceFactory_EGLImage>
SurfaceFactory_EGLImage::Create(GLContext* prodGL,
const SurfaceCaps& caps)
SurfaceFactory_EGLImage::Create(GLContext* prodGL, const SurfaceCaps& caps,
const RefPtr<layers::ISurfaceAllocator>& allocator,
const layers::TextureFlags& flags)
{
EGLContext context = GLContextEGL::Cast(prodGL)->GetEGLContext();
@ -227,7 +227,7 @@ SurfaceFactory_EGLImage::Create(GLContext* prodGL,
GLLibraryEGL* egl = &sEGLLibrary;
if (SharedSurface_EGLImage::HasExtensions(egl, prodGL)) {
ret.reset( new ptrT(prodGL, context, caps) );
ret.reset( new ptrT(prodGL, caps, allocator, flags, context) );
}
return Move(ret);

View File

@ -77,6 +77,8 @@ public:
// Implementation-specific functions below:
// Returns texture and target
void AcquireConsumerTexture(GLContext* consGL, GLuint* out_texture, GLuint* out_target);
virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) override;
};
@ -87,17 +89,20 @@ class SurfaceFactory_EGLImage
public:
// Fallible:
static UniquePtr<SurfaceFactory_EGLImage> Create(GLContext* prodGL,
const SurfaceCaps& caps);
const SurfaceCaps& caps,
const RefPtr<layers::ISurfaceAllocator>& allocator,
const layers::TextureFlags& flags);
protected:
const EGLContext mContext;
SurfaceFactory_EGLImage(GLContext* prodGL,
EGLContext context,
const SurfaceCaps& caps)
: SurfaceFactory(prodGL, SharedSurfaceType::EGLImageShare, caps)
SurfaceFactory_EGLImage(GLContext* prodGL, const SurfaceCaps& caps,
const RefPtr<layers::ISurfaceAllocator>& allocator,
const layers::TextureFlags& flags,
EGLContext context)
: SurfaceFactory(SharedSurfaceType::EGLImageShare, prodGL, caps, allocator, flags)
, mContext(context)
{}
{ }
public:
virtual UniquePtr<SharedSurface> CreateShared(const gfx::IntSize& size) override {

View File

@ -39,40 +39,37 @@ SharedSurface_Basic::Create(GLContext* gl,
return Move(ret);
}
SurfaceFormat format = SurfaceFormat::B8G8R8X8;
switch (formats.color_texInternalFormat) {
case LOCAL_GL_RGB:
case LOCAL_GL_RGB8:
if (formats.color_texType == LOCAL_GL_UNSIGNED_SHORT_5_6_5)
format = SurfaceFormat::R5G6B5;
else
format = SurfaceFormat::B8G8R8X8;
break;
case LOCAL_GL_RGBA:
case LOCAL_GL_RGBA8:
case LOCAL_GL_BGRA:
case LOCAL_GL_BGRA8_EXT:
format = SurfaceFormat::B8G8R8A8;
break;
default:
MOZ_CRASH("Unhandled Tex format.");
}
bool ownsTex = true;
ret.reset( new SharedSurface_Basic(gl, size, hasAlpha, tex, ownsTex) );
return Move(ret);
}
ret.reset( new SharedSurface_Basic(gl, size, hasAlpha, format, tex) );
/*static*/ UniquePtr<SharedSurface_Basic>
SharedSurface_Basic::Wrap(GLContext* gl,
const IntSize& size,
bool hasAlpha,
GLuint tex)
{
bool ownsTex = false;
UniquePtr<SharedSurface_Basic> ret( new SharedSurface_Basic(gl, size, hasAlpha, tex,
ownsTex) );
return Move(ret);
}
SharedSurface_Basic::SharedSurface_Basic(GLContext* gl,
const IntSize& size,
bool hasAlpha,
SurfaceFormat format,
GLuint tex)
GLuint tex,
bool ownsTex)
: SharedSurface(SharedSurfaceType::Basic,
AttachmentType::GLTexture,
gl,
size,
hasAlpha)
hasAlpha,
true)
, mTex(tex)
, mOwnsTex(ownsTex)
, mFB(0)
{
mGL->MakeCurrent();
@ -97,150 +94,16 @@ SharedSurface_Basic::~SharedSurface_Basic()
if (mFB)
mGL->fDeleteFramebuffers(1, &mFB);
mGL->fDeleteTextures(1, &mTex);
if (mOwnsTex)
mGL->fDeleteTextures(1, &mTex);
}
////////////////////////////////////////////////////////////////////////
// SharedSurface_GLTexture
/*static*/ UniquePtr<SharedSurface_GLTexture>
SharedSurface_GLTexture::Create(GLContext* prodGL,
GLContext* consGL,
const GLFormats& formats,
const IntSize& size,
bool hasAlpha,
GLuint texture)
{
MOZ_ASSERT(prodGL);
MOZ_ASSERT(!consGL || prodGL->SharesWith(consGL));
prodGL->MakeCurrent();
GLuint tex = texture;
bool ownsTex = false;
UniquePtr<SharedSurface_GLTexture> ret;
if (!tex) {
GLContext::LocalErrorScope localError(*prodGL);
tex = CreateTextureForOffscreen(prodGL, formats, size);
GLenum err = localError.GetError();
MOZ_ASSERT_IF(err != LOCAL_GL_NO_ERROR, err == LOCAL_GL_OUT_OF_MEMORY);
if (err) {
prodGL->fDeleteTextures(1, &tex);
return Move(ret);
}
ownsTex = true;
}
ret.reset( new SharedSurface_GLTexture(prodGL, consGL, size,
hasAlpha, tex, ownsTex) );
return Move(ret);
}
SharedSurface_GLTexture::~SharedSurface_GLTexture()
{
if (!mGL->MakeCurrent())
return;
if (mOwnsTex) {
mGL->fDeleteTextures(1, &mTex);
}
if (mSync) {
mGL->fDeleteSync(mSync);
}
}
void
SharedSurface_GLTexture::Fence()
{
MutexAutoLock lock(mMutex);
mGL->MakeCurrent();
if (mConsGL && mGL->IsExtensionSupported(GLContext::ARB_sync)) {
if (mSync) {
mGL->fDeleteSync(mSync);
mSync = 0;
}
mSync = mGL->fFenceSync(LOCAL_GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
if (mSync) {
mGL->fFlush();
return;
}
}
MOZ_ASSERT(!mSync);
mGL->fFinish();
}
bool
SharedSurface_GLTexture::WaitSync()
{
MutexAutoLock lock(mMutex);
if (!mSync) {
// We either used glFinish, or we passed this fence already.
// (PollSync/WaitSync returned true previously)
return true;
}
mConsGL->MakeCurrent();
MOZ_ASSERT(mConsGL->IsExtensionSupported(GLContext::ARB_sync));
mConsGL->fWaitSync(mSync,
0,
LOCAL_GL_TIMEOUT_IGNORED);
mConsGL->fDeleteSync(mSync);
mSync = 0;
return true;
}
bool
SharedSurface_GLTexture::PollSync()
{
MutexAutoLock lock(mMutex);
if (!mSync) {
// We either used glFinish, or we passed this fence already.
// (PollSync/WaitSync returned true previously)
return true;
}
mConsGL->MakeCurrent();
MOZ_ASSERT(mConsGL->IsExtensionSupported(GLContext::ARB_sync));
GLint status = 0;
mConsGL->fGetSynciv(mSync,
LOCAL_GL_SYNC_STATUS,
1,
nullptr,
&status);
if (status != LOCAL_GL_SIGNALED)
return false;
mConsGL->fDeleteSync(mSync);
mSync = 0;
return true;
}
GLuint
SharedSurface_GLTexture::ConsTexture(GLContext* consGL)
{
MutexAutoLock lock(mMutex);
MOZ_ASSERT(consGL);
MOZ_ASSERT(mGL->SharesWith(consGL));
MOZ_ASSERT_IF(mConsGL, consGL == mConsGL);
mConsGL = consGL;
return mTex;
}
SurfaceFactory_Basic::SurfaceFactory_Basic(GLContext* gl, const SurfaceCaps& caps,
const layers::TextureFlags& flags)
: SurfaceFactory(SharedSurfaceType::Basic, gl, caps, nullptr, flags)
{ }
} /* namespace gfx */
} /* namespace mozilla */

View File

@ -38,6 +38,11 @@ public:
const gfx::IntSize& size,
bool hasAlpha);
static UniquePtr<SharedSurface_Basic> Wrap(GLContext* gl,
const gfx::IntSize& size,
bool hasAlpha,
GLuint tex);
static SharedSurface_Basic* Cast(SharedSurface* surf) {
MOZ_ASSERT(surf->mType == SharedSurfaceType::Basic);
@ -46,13 +51,14 @@ public:
protected:
const GLuint mTex;
const bool mOwnsTex;
GLuint mFB;
SharedSurface_Basic(GLContext* gl,
const gfx::IntSize& size,
bool hasAlpha,
gfx::SurfaceFormat format,
GLuint tex);
GLuint tex,
bool ownsTex);
public:
virtual ~SharedSurface_Basic();
@ -67,15 +73,19 @@ public:
virtual GLuint ProdTexture() override {
return mTex;
}
virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) override {
MOZ_CRASH("don't do this");
return false;
}
};
class SurfaceFactory_Basic
: public SurfaceFactory
{
public:
SurfaceFactory_Basic(GLContext* gl, const SurfaceCaps& caps)
: SurfaceFactory(gl, SharedSurfaceType::Basic, caps)
{}
SurfaceFactory_Basic(GLContext* gl, const SurfaceCaps& caps,
const layers::TextureFlags& flags);
virtual UniquePtr<SharedSurface> CreateShared(const gfx::IntSize& size) override {
bool hasAlpha = mReadCaps.alpha;
@ -83,99 +93,6 @@ public:
}
};
// Using shared GL textures:
class SharedSurface_GLTexture
: public SharedSurface
{
public:
static UniquePtr<SharedSurface_GLTexture> Create(GLContext* prodGL,
GLContext* consGL,
const GLFormats& formats,
const gfx::IntSize& size,
bool hasAlpha,
GLuint texture = 0);
static SharedSurface_GLTexture* Cast(SharedSurface* surf) {
MOZ_ASSERT(surf->mType == SharedSurfaceType::GLTextureShare);
return (SharedSurface_GLTexture*)surf;
}
protected:
GLContext* mConsGL;
const GLuint mTex;
const bool mOwnsTex;
GLsync mSync;
mutable Mutex mMutex;
SharedSurface_GLTexture(GLContext* prodGL,
GLContext* consGL,
const gfx::IntSize& size,
bool hasAlpha,
GLuint tex,
bool ownsTex)
: SharedSurface(SharedSurfaceType::GLTextureShare,
AttachmentType::GLTexture,
prodGL,
size,
hasAlpha)
, mConsGL(consGL)
, mTex(tex)
, mOwnsTex(ownsTex)
, mSync(0)
, mMutex("SharedSurface_GLTexture mutex")
{
}
public:
virtual ~SharedSurface_GLTexture();
virtual void LockProdImpl() override {}
virtual void UnlockProdImpl() override {}
virtual void Fence() override;
virtual bool WaitSync() override;
virtual bool PollSync() override;
virtual GLuint ProdTexture() override {
return mTex;
}
// Custom:
GLuint ConsTexture(GLContext* consGL);
GLenum ConsTextureTarget() const {
return ProdTextureTarget();
}
};
class SurfaceFactory_GLTexture
: public SurfaceFactory
{
protected:
GLContext* const mConsGL;
public:
// If we don't know `consGL` at construction time, use `nullptr`, and call
// `SetConsumerGL()` on each `SharedSurface_GLTexture` before calling its
// `WaitSync()`.
SurfaceFactory_GLTexture(GLContext* prodGL,
GLContext* consGL,
const SurfaceCaps& caps)
: SurfaceFactory(prodGL, SharedSurfaceType::GLTextureShare, caps)
, mConsGL(consGL)
{
MOZ_ASSERT(consGL != prodGL);
}
virtual UniquePtr<SharedSurface> CreateShared(const gfx::IntSize& size) override {
bool hasAlpha = mReadCaps.alpha;
return SharedSurface_GLTexture::Create(mGL, mConsGL, mFormats, size, hasAlpha);
}
};
} /* namespace gfx */
} /* namespace mozilla */

View File

@ -35,13 +35,10 @@ namespace gl {
using namespace mozilla::layers;
using namespace android;
SurfaceFactory_Gralloc::SurfaceFactory_Gralloc(GLContext* prodGL,
const SurfaceCaps& caps,
layers::TextureFlags flags,
layers::ISurfaceAllocator* allocator)
: SurfaceFactory(prodGL, SharedSurfaceType::Gralloc, caps)
, mFlags(flags)
, mAllocator(allocator)
SurfaceFactory_Gralloc::SurfaceFactory_Gralloc(GLContext* prodGL, const SurfaceCaps& caps,
const RefPtr<layers::ISurfaceAllocator>& allocator,
const layers::TextureFlags& flags)
: SurfaceFactory(SharedSurfaceType::Gralloc, prodGL, caps, allocator, flags)
{
MOZ_ASSERT(mAllocator);
}
@ -132,7 +129,8 @@ SharedSurface_Gralloc::SharedSurface_Gralloc(GLContext* prodGL,
AttachmentType::GLTexture,
prodGL,
size,
hasAlpha)
hasAlpha,
true)
, mEGL(egl)
, mSync(0)
, mAllocator(allocator)
@ -282,5 +280,12 @@ SharedSurface_Gralloc::WaitForBufferOwnership()
mTextureClient->WaitForBufferOwnership();
}
bool
SharedSurface_Gralloc::ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor)
{
mTextureClient->MarkShared();
return mTextureClient->ToSurfaceDescriptor(*out_descriptor);
}
}
} // namespace gl
} // namespace mozilla

View File

@ -73,20 +73,17 @@ public:
layers::GrallocTextureClientOGL* GetTextureClient() {
return mTextureClient;
}
virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) override;
};
class SurfaceFactory_Gralloc
: public SurfaceFactory
{
protected:
const layers::TextureFlags mFlags;
RefPtr<layers::ISurfaceAllocator> mAllocator;
public:
SurfaceFactory_Gralloc(GLContext* prodGL,
const SurfaceCaps& caps,
layers::TextureFlags flags,
layers::ISurfaceAllocator* allocator);
SurfaceFactory_Gralloc(GLContext* prodGL, const SurfaceCaps& caps,
const RefPtr<layers::ISurfaceAllocator>& allocator,
const layers::TextureFlags& flags);
virtual UniquePtr<SharedSurface> CreateShared(const gfx::IntSize& size) override {
bool hasAlpha = mReadCaps.alpha;

View File

@ -6,8 +6,9 @@
#include "SharedSurfaceIO.h"
#include "GLContextCGL.h"
#include "mozilla/gfx/MacIOSurface.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/gfx/MacIOSurface.h"
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc
#include "ScopedGLHelpers.h"
namespace mozilla {
@ -152,7 +153,8 @@ SharedSurface_IOSurface::SharedSurface_IOSurface(const RefPtr<MacIOSurface>& ioS
AttachmentType::GLTexture,
gl,
size,
hasAlpha)
hasAlpha,
true)
, mIOSurf(ioSurf)
{
gl->MakeCurrent();
@ -170,18 +172,29 @@ SharedSurface_IOSurface::~SharedSurface_IOSurface()
}
}
bool
SharedSurface_IOSurface::ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor)
{
bool isOpaque = !mHasAlpha;
*out_descriptor = layers::SurfaceDescriptorMacIOSurface(mIOSurf->GetIOSurfaceID(),
mIOSurf->GetContentsScaleFactor(),
isOpaque);
return true;
}
////////////////////////////////////////////////////////////////////////
// SurfaceFactory_IOSurface
/*static*/ UniquePtr<SurfaceFactory_IOSurface>
SurfaceFactory_IOSurface::Create(GLContext* gl,
const SurfaceCaps& caps)
SurfaceFactory_IOSurface::Create(GLContext* gl, const SurfaceCaps& caps,
const RefPtr<layers::ISurfaceAllocator>& allocator,
const layers::TextureFlags& flags)
{
gfx::IntSize maxDims(MacIOSurface::GetMaxWidth(),
MacIOSurface::GetMaxHeight());
typedef SurfaceFactory_IOSurface ptrT;
UniquePtr<ptrT> ret( new ptrT(gl, caps, maxDims) );
UniquePtr<ptrT> ret( new ptrT(gl, caps, allocator, flags, maxDims) );
return Move(ret);
}

View File

@ -16,11 +16,21 @@ namespace gl {
class SharedSurface_IOSurface : public SharedSurface
{
private:
const RefPtr<MacIOSurface> mIOSurf;
GLuint mProdTex;
public:
static UniquePtr<SharedSurface_IOSurface> Create(const RefPtr<MacIOSurface>& ioSurf,
GLContext* gl,
bool hasAlpha);
private:
SharedSurface_IOSurface(const RefPtr<MacIOSurface>& ioSurf,
GLContext* gl, const gfx::IntSize& size,
bool hasAlpha);
public:
~SharedSurface_IOSurface();
virtual void LockProdImpl() override { }
@ -57,13 +67,7 @@ public:
return true;
}
private:
SharedSurface_IOSurface(const RefPtr<MacIOSurface>& ioSurf,
GLContext* gl, const gfx::IntSize& size,
bool hasAlpha);
RefPtr<MacIOSurface> mIOSurf;
GLuint mProdTex;
virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) override;
};
class SurfaceFactory_IOSurface : public SurfaceFactory
@ -71,17 +75,19 @@ class SurfaceFactory_IOSurface : public SurfaceFactory
public:
// Infallible.
static UniquePtr<SurfaceFactory_IOSurface> Create(GLContext* gl,
const SurfaceCaps& caps);
const SurfaceCaps& caps,
const RefPtr<layers::ISurfaceAllocator>& allocator,
const layers::TextureFlags& flags);
protected:
const gfx::IntSize mMaxDims;
SurfaceFactory_IOSurface(GLContext* gl,
const SurfaceCaps& caps,
SurfaceFactory_IOSurface(GLContext* gl, const SurfaceCaps& caps,
const RefPtr<layers::ISurfaceAllocator>& allocator,
const layers::TextureFlags& flags,
const gfx::IntSize& maxDims)
: SurfaceFactory(gl, SharedSurfaceType::IOSurface, caps)
: SurfaceFactory(SharedSurfaceType::IOSurface, gl, caps, allocator, flags)
, mMaxDims(maxDims)
{
}
{ }
virtual UniquePtr<SharedSurface> CreateShared(const gfx::IntSize& size) override;
};

View File

@ -70,7 +70,6 @@ enum class SharedSurfaceType : uint8_t {
Unknown = 0,
Basic,
GLTextureShare,
EGLImageShare,
EGLSurfaceANGLE,
DXGLInterop,

View File

@ -13,16 +13,35 @@
#include "base/task.h"
#include "mozilla/gfx/Logging.h"
#define ADDREF_MANUALLY(obj) (obj)->AddRefManually(__FUNCTION__, __FILE__, __LINE__)
#define RELEASE_MANUALLY(obj) (obj)->ReleaseManually(__FUNCTION__, __FILE__, __LINE__)
namespace mozilla {
template<class U>
class StaticRefPtr;
namespace gl {
template<typename T>
class RefSet;
template<typename T>
class RefQueue;
}
template<typename T>
class AtomicRefCountedWithFinalize
{
protected:
protected:
AtomicRefCountedWithFinalize()
: mRecycleCallback(nullptr)
, mRefCount(0)
, mMessageLoopToPostDestructionTo(nullptr)
#ifdef DEBUG
, mSpew(false)
, mManualAddRefs(0)
, mManualReleases(0)
#endif
{}
~AtomicRefCountedWithFinalize() {
@ -41,12 +60,69 @@ class AtomicRefCountedWithFinalize
delete ptr;
}
public:
public:
// Mark user classes that are considered flawless.
template<typename U>
friend class RefPtr;
template<class U>
friend class ::mozilla::StaticRefPtr;
template<typename U>
friend class TemporaryRef;
template<class U>
friend class ::nsRefPtr;
template<class U>
friend struct ::RunnableMethodTraits;
template<typename U>
friend class ::mozilla::gl::RefSet;
template<typename U>
friend class ::mozilla::gl::RefQueue;
//friend class mozilla::gl::SurfaceFactory;
void AddRefManually(const char* funcName, const char* fileName, uint32_t lineNum) {
#ifdef DEBUG
uint32_t count = ++mManualAddRefs;
if (mSpew) {
printf_stderr("AddRefManually() #%u in %s at %s:%u\n", count, funcName,
fileName, lineNum);
}
#else
(void)funcName;
(void)fileName;
(void)lineNum;
#endif
AddRef();
}
void ReleaseManually(const char* funcName, const char* fileName, uint32_t lineNum) {
#ifdef DEBUG
uint32_t count = ++mManualReleases;
if (mSpew) {
printf_stderr("ReleaseManually() #%u in %s at %s:%u\n", count, funcName,
fileName, lineNum);
}
#else
(void)funcName;
(void)fileName;
(void)lineNum;
#endif
Release();
}
private:
void AddRef() {
MOZ_ASSERT(mRefCount >= 0, "AddRef() during/after Finalize()/dtor.");
++mRefCount;
}
void Release() {
MOZ_ASSERT(mRefCount > 0, "Release() during/after Finalize()/dtor.");
// Read mRecycleCallback early so that it does not get set to
// deleted memory, if the object is goes away. See bug 994903.
// This saves us in the case where there is no callback, so that
@ -70,6 +146,8 @@ class AtomicRefCountedWithFinalize
mRecycleCallback = nullptr;
}
MOZ_ASSERT(mManualAddRefs == mManualReleases);
T* derived = static_cast<T*>(this);
derived->Finalize();
if (MOZ_LIKELY(!mMessageLoopToPostDestructionTo)) {
@ -93,6 +171,7 @@ class AtomicRefCountedWithFinalize
}
}
public:
typedef void (*RecycleCallback)(T* aObject, void* aClosure);
/**
* Set a callback responsible for recycling this object
@ -126,8 +205,15 @@ private:
void *mClosure;
Atomic<int> mRefCount;
MessageLoop *mMessageLoopToPostDestructionTo;
#ifdef DEBUG
public:
bool mSpew;
private:
Atomic<uint32_t> mManualAddRefs;
Atomic<uint32_t> mManualReleases;
#endif
};
}
} // namespace mozilla
#endif

View File

@ -3,8 +3,9 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "BasicLayersImpl.h" // for FillWithMask, etc
#include "CopyableCanvasLayer.h"
#include "BasicLayersImpl.h" // for FillWithMask, etc
#include "GLContext.h" // for GLContext
#include "GLScreenBuffer.h" // for GLScreenBuffer
#include "SharedSurface.h" // for SharedSurface
@ -21,6 +22,7 @@
#include "nsISupportsImpl.h" // for gfxContext::AddRef, etc
#include "nsRect.h" // for mozilla::gfx::IntRect
#include "gfxUtils.h"
#include "client/TextureClientSharedSurface.h"
namespace mozilla {
namespace layers {
@ -56,11 +58,8 @@ CopyableCanvasLayer::Initialize(const Data& aData)
if (aData.mFrontbufferGLTex) {
gfx::IntSize size(aData.mSize.width, aData.mSize.height);
mGLFrontbuffer = SharedSurface_GLTexture::Create(aData.mGLContext,
nullptr,
aData.mGLContext->GetGLFormats(),
size, aData.mHasAlpha,
aData.mFrontbufferGLTex);
mGLFrontbuffer = SharedSurface_Basic::Wrap(aData.mGLContext, size, aData.mHasAlpha,
aData.mFrontbufferGLTex);
}
} else if (aData.mDrawTarget) {
mDrawTarget = aData.mDrawTarget;
@ -108,7 +107,7 @@ CopyableCanvasLayer::UpdateTarget(DrawTarget* aDestTarget)
frontbuffer = mGLFrontbuffer.get();
} else {
GLScreenBuffer* screen = mGLContext->Screen();
ShSurfHandle* front = screen->Front();
const auto& front = screen->Front();
if (front) {
frontbuffer = front->Surf();
}
@ -137,7 +136,7 @@ CopyableCanvasLayer::UpdateTarget(DrawTarget* aDestTarget)
Factory::CreateWrappingDataSourceSurface(destData, destStride, destSize, destFormat);
mGLContext->Readback(frontbuffer, data);
if (needsPremult) {
gfxUtils::PremultiplyDataSurface(data, data);
gfxUtils::PremultiplyDataSurface(data, data);
}
aDestTarget->ReleaseBits(destData);
return;

View File

@ -39,7 +39,7 @@ MacIOSurfaceTextureHostBasic::MacIOSurfaceTextureHostBasic(
)
: TextureHost(aFlags)
{
mSurface = MacIOSurface::LookupSurface(aDescriptor.surface(),
mSurface = MacIOSurface::LookupSurface(aDescriptor.surfaceId(),
aDescriptor.scaleFactor(),
!aDescriptor.isOpaque());
}

View File

@ -22,9 +22,7 @@
#include "nsAutoPtr.h" // for nsRefPtr
#include "nsDebug.h" // for printf_stderr, NS_ASSERTION
#include "nsXULAppAPI.h" // for XRE_GetProcessType, etc
#ifdef MOZ_WIDGET_GONK
#include "SharedSurfaceGralloc.h"
#endif
#include "TextureClientSharedSurface.h"
using namespace mozilla::gfx;
using namespace mozilla::gl;
@ -37,13 +35,6 @@ CanvasClient::CreateCanvasClient(CanvasClientType aType,
CompositableForwarder* aForwarder,
TextureFlags aFlags)
{
#ifndef MOZ_WIDGET_GONK
if (XRE_GetProcessType() != GeckoProcessType_Default) {
NS_WARNING("Most platforms still need an optimized way to share GL cross process.");
return MakeAndAddRef<CanvasClient2D>(aForwarder, aFlags);
}
#endif
switch (aType) {
case CanvasClientTypeShSurf:
return MakeAndAddRef<CanvasClientSharedSurface>(aForwarder, aFlags);
@ -149,28 +140,11 @@ CanvasClient2D::CreateTextureClientForCanvas(gfx::SurfaceFormat aFormat,
CanvasClientSharedSurface::CanvasClientSharedSurface(CompositableForwarder* aLayerForwarder,
TextureFlags aFlags)
: CanvasClient(aLayerForwarder, aFlags)
{ }
CanvasClientSharedSurface::~CanvasClientSharedSurface()
{
}
////////////////////////////////////////
// Accelerated backends
static TemporaryRef<TextureClient>
TexClientFromShSurf(ISurfaceAllocator* aAllocator, SharedSurface* surf,
TextureFlags flags)
{
switch (surf->mType) {
case SharedSurfaceType::Basic:
return nullptr;
#ifdef MOZ_WIDGET_GONK
case SharedSurfaceType::Gralloc:
return GrallocTextureClientOGL::FromSharedSurface(surf, flags);
#endif
default:
return MakeAndAddRef<SharedSurfaceTextureClient>(aAllocator, flags, surf);
}
ClearSurfaces();
}
////////////////////////////////////////
@ -330,91 +304,92 @@ TexClientFromReadback(SharedSurface* src, ISurfaceAllocator* allocator,
////////////////////////////////////////
static TemporaryRef<gl::ShSurfHandle>
static TemporaryRef<SharedSurfaceTextureClient>
CloneSurface(gl::SharedSurface* src, gl::SurfaceFactory* factory)
{
RefPtr<gl::ShSurfHandle> dest = factory->NewShSurfHandle(src->mSize);
RefPtr<SharedSurfaceTextureClient> dest = factory->NewTexClient(src->mSize);
if (!dest) {
return nullptr;
return nullptr;
}
SharedSurface::ProdCopy(src, dest->Surf(), factory);
dest->Surf()->Fence();
return dest.forget();
}
void
CanvasClientSharedSurface::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
{
if (mFront) {
mPrevFront = mFront;
mFront = nullptr;
}
auto gl = aLayer->mGLContext;
gl->MakeCurrent();
RefPtr<TextureClient> newFront;
if (aLayer->mGLFrontbuffer) {
mFront = CloneSurface(aLayer->mGLFrontbuffer.get(), aLayer->mFactory.get());
if (mFront)
mFront->Surf()->Fence();
mShSurfClient = CloneSurface(aLayer->mGLFrontbuffer.get(), aLayer->mFactory.get());
if (!mShSurfClient) {
gfxCriticalError() << "Invalid canvas front buffer";
return;
}
} else {
mFront = gl->Screen()->Front();
}
if (!mFront) {
gfxCriticalError() << "Invalid canvas front buffer";
return;
mShSurfClient = gl->Screen()->Front();
if (!mShSurfClient) {
return;
}
}
MOZ_ASSERT(mShSurfClient);
newFront = mShSurfClient;
SharedSurface* surf = mShSurfClient->Surf();
// Readback if needed.
mReadbackClient = nullptr;
// Alright, now sort out the IPC goop.
SharedSurface* surf = mFront->Surf();
auto forwarder = GetForwarder();
auto flags = GetTextureFlags() | TextureFlags::IMMUTABLE;
// Get a TexClient from our surf.
RefPtr<TextureClient> newTex = TexClientFromShSurf(GetForwarder(), surf, flags);
if (!newTex) {
bool needsReadback = (surf->mType == SharedSurfaceType::Basic);
if (needsReadback) {
TextureFlags flags = aLayer->Flags() |
TextureFlags::IMMUTABLE;
auto manager = aLayer->ClientManager();
auto shadowForwarder = manager->AsShadowForwarder();
auto layersBackend = shadowForwarder->GetCompositorBackendType();
mReadbackClient = TexClientFromReadback(surf, forwarder, flags, layersBackend);
newTex = TexClientFromReadback(surf, forwarder, flags, layersBackend);
newFront = mReadbackClient;
} else {
mReadbackClient = nullptr;
}
if (!newTex) {
MOZ_ASSERT(newFront);
if (!newFront) {
// May happen in a release build in case of memory pressure.
gfxCriticalError() << "Failed to allocate a TextureClient for SharedSurface Canvas. size: " << aSize;
gfxCriticalError() << "Failed to allocate a TextureClient for SharedSurface Canvas. Size: " << aSize;
return;
}
// Add the new TexClient.
MOZ_ALWAYS_TRUE( AddTextureClient(newTex) );
// Remove the old TexClient.
if (mFrontTex) {
// remove old buffer from CompositableHost
RefPtr<AsyncTransactionTracker> tracker = new RemoveTextureFromCompositableTracker();
// Hold TextureClient until transaction complete.
tracker->SetTextureClient(mFrontTex);
mFrontTex->SetRemoveFromCompositableTracker(tracker);
// RemoveTextureFromCompositableAsync() expects CompositorChild's presence.
GetForwarder()->RemoveTextureFromCompositableAsync(tracker, this, mFrontTex);
mFrontTex = nullptr;
if (mFront) {
if (mFront->GetFlags() & TextureFlags::RECYCLE) {
mFront->WaitForCompositorRecycle();
}
}
// Use the new TexClient.
mFrontTex = newTex;
mFront = newFront;
forwarder->UseTexture(this, mFrontTex);
// Add the new TexClient.
MOZ_ALWAYS_TRUE( AddTextureClient(mFront) );
forwarder->UseTexture(this, mFront);
}
void
CanvasClientSharedSurface::ClearSurfaces()
{
mFrontTex = nullptr;
// It is important to destroy the SharedSurface *after* the TextureClient.
mFront = nullptr;
mPrevFront = nullptr;
mShSurfClient = nullptr;
mReadbackClient = nullptr;
}
}
}
} // namespace layers
} // namespace mozilla

View File

@ -18,18 +18,12 @@
#include "mozilla/gfx/Point.h" // for IntSize
#include "mozilla/gfx/Types.h" // for SurfaceFormat
namespace mozilla {
namespace gl {
class SharedSurface;
class ShSurfHandle;
}
}
namespace mozilla {
namespace layers {
class ClientCanvasLayer;
class CompositableForwarder;
class SharedSurfaceTextureClient;
/**
* Compositable client for 2d and webgl canvas.
@ -114,10 +108,9 @@ private:
class CanvasClientSharedSurface : public CanvasClient
{
private:
RefPtr<gl::ShSurfHandle> mFront;
RefPtr<gl::ShSurfHandle> mPrevFront;
RefPtr<TextureClient> mFrontTex;
RefPtr<SharedSurfaceTextureClient> mShSurfClient;
RefPtr<TextureClient> mReadbackClient;
RefPtr<TextureClient> mFront;
void ClearSurfaces();
@ -125,10 +118,7 @@ public:
CanvasClientSharedSurface(CompositableForwarder* aLayerForwarder,
TextureFlags aFlags);
~CanvasClientSharedSurface()
{
ClearSurfaces();
}
~CanvasClientSharedSurface();
virtual TextureInfo GetTextureInfo() const override {
return TextureInfo(CompositableType::IMAGE);

View File

@ -70,48 +70,40 @@ ClientCanvasLayer::Initialize(const Data& aData)
}
MOZ_ASSERT(caps.alpha == aData.mHasAlpha);
auto forwarder = ClientManager()->AsShadowForwarder();
mFlags = TextureFlags::ORIGIN_BOTTOM_LEFT;
if (!aData.mIsGLAlphaPremult) {
mFlags |= TextureFlags::NON_PREMULTIPLIED;
}
UniquePtr<SurfaceFactory> factory;
if (!gfxPrefs::WebGLForceLayersReadback()) {
switch (ClientManager()->AsShadowForwarder()->GetCompositorBackendType()) {
switch (forwarder->GetCompositorBackendType()) {
case mozilla::layers::LayersBackend::LAYERS_OPENGL: {
#if defined(XP_MACOSX)
factory = SurfaceFactory_IOSurface::Create(mGLContext, caps, forwarder, mFlags);
#elif defined(MOZ_WIDGET_GONK)
factory = MakeUnique<SurfaceFactory_Gralloc>(mGLContext, caps, forwarder, mFlags);
#else
if (mGLContext->GetContextType() == GLContextType::EGL) {
#ifdef MOZ_WIDGET_GONK
TextureFlags flags = TextureFlags::DEALLOCATE_CLIENT |
TextureFlags::ORIGIN_BOTTOM_LEFT;
if (!aData.mIsGLAlphaPremult) {
flags |= TextureFlags::NON_PREMULTIPLIED;
}
factory = MakeUnique<SurfaceFactory_Gralloc>(mGLContext,
caps,
flags,
ClientManager()->AsShadowForwarder());
#else
bool isCrossProcess = !(XRE_GetProcessType() == GeckoProcessType_Default);
bool isCrossProcess = (XRE_GetProcessType() != GeckoProcessType_Default);
if (!isCrossProcess) {
// [Basic/OGL Layers, OMTC] WebGL layer init.
factory = SurfaceFactory_EGLImage::Create(mGLContext, caps);
} else {
// we could do readback here maybe
NS_NOTREACHED("isCrossProcess but not on native B2G!");
factory = SurfaceFactory_EGLImage::Create(mGLContext, caps, forwarder,
mFlags);
}
#endif
} else {
// [Basic Layers, OMTC] WebGL layer init.
// Well, this *should* work...
#ifdef XP_MACOSX
factory = SurfaceFactory_IOSurface::Create(mGLContext, caps);
#else
GLContext* nullConsGL = nullptr; // Bug 1050044.
factory = MakeUnique<SurfaceFactory_GLTexture>(mGLContext, nullConsGL, caps);
#endif
}
#endif
break;
}
case mozilla::layers::LayersBackend::LAYERS_D3D11: {
#ifdef XP_WIN
if (mGLContext->IsANGLE() && DoesD3D11TextureSharingWork(gfxWindowsPlatform::GetPlatform()->GetD3D11Device())) {
factory = SurfaceFactory_ANGLEShareHandle::Create(mGLContext, caps);
if (mGLContext->IsANGLE() &&
DoesD3D11TextureSharingWork(gfxWindowsPlatform::GetPlatform()->GetD3D11Device()))
{
factory = SurfaceFactory_ANGLEShareHandle::Create(mGLContext, caps, forwarder,
mFlags);
}
#endif
break;
@ -127,7 +119,7 @@ ClientCanvasLayer::Initialize(const Data& aData)
mFactory = Move(factory);
if (!mFactory) {
// Absolutely must have a factory here, so create a basic one
mFactory = MakeUnique<SurfaceFactory_Basic>(mGLContext, caps);
mFactory = MakeUnique<SurfaceFactory_Basic>(mGLContext, caps, mFlags);
}
} else {
if (factory)

View File

@ -6,7 +6,7 @@
#ifndef GFX_CLIENTCANVASLAYER_H
#define GFX_CLIENTCANVASLAYER_H
#include "mozilla/layers/CanvasClient.h" // for CanvasClient, etc
#include "CanvasClient.h" // for CanvasClient, etc
#include "ClientLayerManager.h" // for ClientLayerManager, etc
#include "CopyableCanvasLayer.h" // for CopyableCanvasLayer
#include "Layers.h" // for CanvasLayer, etc
@ -21,7 +21,6 @@
namespace mozilla {
namespace gl {
class SharedSurface;
class SurfaceFactory;
}
@ -81,6 +80,9 @@ public:
{
return mCanvasClient;
}
const TextureFlags& Flags() const { return mFlags; }
protected:
ClientLayerManager* ClientManager()
{
@ -93,6 +95,8 @@ protected:
UniquePtr<gl::SurfaceFactory> mFactory;
TextureFlags mFlags;
friend class DeprecatedCanvasClient2D;
friend class CanvasClient2D;
friend class CanvasClientSharedSurface;

View File

@ -20,8 +20,6 @@
#include "mozilla/gfx/Logging.h" // for gfxDebug
#include "mozilla/layers/TextureClientOGL.h"
#include "mozilla/layers/PTextureChild.h"
#include "SharedSurface.h"
#include "GLContext.h"
#include "mozilla/gfx/DataSurfaceHelpers.h" // for CreateDataSourceSurfaceByCloning
#include "nsPrintfCString.h" // for nsPrintfCString
#include "LayersLogging.h" // for AppendToString
@ -113,7 +111,7 @@ public:
bool RecvCompositorRecycle() override
{
RECYCLE_LOG("Receive recycle %p (%p)\n", mTextureClient, mWaitForRecycle.get());
RECYCLE_LOG("[CLIENT] Receive recycle %p (%p)\n", mTextureClient, mWaitForRecycle.get());
mWaitForRecycle = nullptr;
return true;
}
@ -121,7 +119,7 @@ public:
void WaitForCompositorRecycle()
{
mWaitForRecycle = mTextureClient;
RECYCLE_LOG("Wait for recycle %p\n", mWaitForRecycle.get());
RECYCLE_LOG("[CLIENT] Wait for recycle %p\n", mWaitForRecycle.get());
SendClientRecycle();
}
@ -587,6 +585,10 @@ TextureClient::Finalize()
// Null it before RemoveTexture calls to avoid invalid actor->mTextureClient
// when calling TextureChild::ActorDestroy()
actor->mTextureClient = nullptr;
// `actor->mWaitForRecycle` may not be null, as we may be being called from setting
// this RefPtr to null! Clearing it here will double-Release() it.
// this will call ForceRemove in the right thread, using a sync proxy if needed
if (actor->GetForwarder()) {
actor->GetForwarder()->RemoveTexture(this);
@ -915,32 +917,6 @@ BufferTextureClient::GetLockedData() const
return serializer.GetData();
}
////////////////////////////////////////////////////////////////////////
// SharedSurfaceTextureClient
SharedSurfaceTextureClient::SharedSurfaceTextureClient(ISurfaceAllocator* aAllocator,
TextureFlags aFlags,
gl::SharedSurface* surf)
: TextureClient(aAllocator, aFlags)
, mIsLocked(false)
, mSurf(surf)
, mGL(mSurf->mGL)
{
AddFlags(TextureFlags::DEALLOCATE_CLIENT);
}
SharedSurfaceTextureClient::~SharedSurfaceTextureClient()
{
// the data is owned externally.
}
bool
SharedSurfaceTextureClient::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
{
aOutDescriptor = SharedSurfaceDescriptor((uintptr_t)mSurf);
return true;
}
TemporaryRef<SyncObject>
SyncObject::CreateSyncObject(SyncHandle aHandle)
{

View File

@ -8,7 +8,6 @@
#include <stddef.h> // for size_t
#include <stdint.h> // for uint32_t, uint8_t, uint64_t
#include "GLContextTypes.h" // for GLContext (ptr only), etc
#include "GLTextureImage.h" // for TextureImage
#include "ImageTypes.h" // for StereoMode
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
@ -32,10 +31,6 @@
class gfxImageSurface;
namespace mozilla {
namespace gl {
class GLContext;
class SharedSurface;
}
// When defined, we track which pool the tile came from and test for
// any inconsistencies. This can be defined in release build as well.
@ -476,9 +471,13 @@ public:
virtual void SetReadbackSink(TextureReadbackSink* aReadbackSink) {
mReadbackSink = aReadbackSink;
}
virtual void SyncWithObject(SyncObject* aSyncObject) { }
void MarkShared() {
mShared = true;
}
private:
/**
* Called once, just before the destructor.
@ -690,66 +689,6 @@ protected:
size_t mBufSize;
};
/**
* A TextureClient implementation to share SharedSurfaces.
*/
class SharedSurfaceTextureClient : public TextureClient
{
public:
SharedSurfaceTextureClient(ISurfaceAllocator* aAllocator, TextureFlags aFlags,
gl::SharedSurface* surf);
protected:
~SharedSurfaceTextureClient();
public:
// Boilerplate start
virtual bool IsAllocated() const override { return true; }
virtual bool Lock(OpenMode) override {
MOZ_ASSERT(!mIsLocked);
mIsLocked = true;
return true;
}
virtual void Unlock() override {
MOZ_ASSERT(mIsLocked);
mIsLocked = false;
}
virtual bool IsLocked() const override { return mIsLocked; }
virtual bool HasInternalBuffer() const override { return false; }
virtual gfx::SurfaceFormat GetFormat() const override {
return gfx::SurfaceFormat::UNKNOWN;
}
virtual gfx::IntSize GetSize() const override { return gfx::IntSize(); }
// This TextureClient should not be used in a context where we use CreateSimilar
// (ex. component alpha) because the underlying texture data is always created by
// an external producer.
virtual TemporaryRef<TextureClient>
CreateSimilar(TextureFlags, TextureAllocationFlags) const override {
return nullptr;
}
virtual bool AllocateForSurface(gfx::IntSize,
TextureAllocationFlags) override {
MOZ_CRASH("Should never hit this.");
return false;
}
// Boilerplate end
virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) override;
protected:
bool mIsLocked;
gl::SharedSurface* const mSurf;
RefPtr<gl::GLContext> mGL; // Just for reference holding.
};
struct TextureClientAutoUnlock
{
TextureClient* mTexture;

View File

@ -0,0 +1,45 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "TextureClientSharedSurface.h"
#include "GLContext.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/gfx/Logging.h" // for gfxDebug
#include "mozilla/layers/ISurfaceAllocator.h"
#include "mozilla/unused.h"
#include "nsThreadUtils.h"
#include "SharedSurface.h"
namespace mozilla {
namespace layers {
SharedSurfaceTextureClient::SharedSurfaceTextureClient(ISurfaceAllocator* aAllocator,
TextureFlags aFlags,
UniquePtr<gl::SharedSurface> surf,
gl::SurfaceFactory* factory)
: TextureClient(aAllocator, aFlags | TextureFlags::RECYCLE)
, mSurf(Move(surf))
{ }
SharedSurfaceTextureClient::~SharedSurfaceTextureClient()
{
// Free the ShSurf implicitly.
}
gfx::IntSize
SharedSurfaceTextureClient::GetSize() const
{
return mSurf->mSize;
}
bool
SharedSurfaceTextureClient::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
{
return mSurf->ToSurfaceDescriptor(&aOutDescriptor);
}
} // namespace layers
} // namespace mozilla

View File

@ -0,0 +1,75 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef MOZILLA_GFX_TEXTURECLIENT_SHAREDSURFACE_H
#define MOZILLA_GFX_TEXTURECLIENT_SHAREDSURFACE_H
#include <cstddef> // for size_t
#include <stdint.h> // for uint32_t, uint8_t, uint64_t
#include "GLContextTypes.h" // for GLContext (ptr only), etc
#include "TextureClient.h"
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
#include "mozilla/RefPtr.h" // for RefPtr, RefCounted
#include "mozilla/gfx/Point.h" // for IntSize
#include "mozilla/gfx/Types.h" // for SurfaceFormat
#include "mozilla/layers/CompositorTypes.h" // for TextureFlags, etc
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor
namespace mozilla {
namespace gl {
class GLContext;
class SharedSurface;
class SurfaceFactory;
}
namespace layers {
class SharedSurfaceTextureClient : public TextureClient
{
protected:
const UniquePtr<gl::SharedSurface> mSurf;
friend class gl::SurfaceFactory;
SharedSurfaceTextureClient(ISurfaceAllocator* aAllocator, TextureFlags aFlags,
UniquePtr<gl::SharedSurface> surf,
gl::SurfaceFactory* factory);
~SharedSurfaceTextureClient();
public:
virtual bool IsAllocated() const override { return true; }
virtual bool Lock(OpenMode) override { return false; }
virtual bool IsLocked() const override { return false; }
virtual bool HasInternalBuffer() const override { return false; }
virtual gfx::SurfaceFormat GetFormat() const override {
return gfx::SurfaceFormat::UNKNOWN;
}
virtual TemporaryRef<TextureClient>
CreateSimilar(TextureFlags, TextureAllocationFlags) const override {
return nullptr;
}
virtual bool AllocateForSurface(gfx::IntSize,
TextureAllocationFlags) override {
MOZ_CRASH("Should never hit this.");
return false;
}
virtual gfx::IntSize GetSize() const override;
virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) override;
gl::SharedSurface* Surf() const {
return mSurf.get();
}
};
} // namespace layers
} // namespace mozilla
#endif // MOZILLA_GFX_TEXTURECLIENT_SHAREDSURFACE_H

View File

@ -25,7 +25,6 @@ namespace mozilla {
namespace layers {
using namespace mozilla::gfx;
using namespace mozilla::gl;
FPSCounter::FPSCounter(const char* aName)
: mWriteIndex(0)
@ -396,7 +395,7 @@ static void DrawDigits(unsigned int aValue,
Rect drawRect = Rect(aOffsetX + n * FontWidth, aOffsetY, FontWidth, FontHeight);
Rect clipRect = Rect(0, 0, 300, 100);
aCompositor->DrawQuad(drawRect, clipRect,
aEffectChain, opacity, transform);
aEffectChain, opacity, transform);
}
}

View File

@ -34,8 +34,7 @@ ImageHost::ImageHost(const TextureInfo& aTextureInfo)
{}
ImageHost::~ImageHost()
{
}
{}
void
ImageHost::UseTextureHost(TextureHost* aTexture)

View File

@ -22,9 +22,6 @@
#include "mozilla/layers/PTextureParent.h"
#include "mozilla/unused.h"
#include <limits>
#include "SharedSurface.h"
#include "SharedSurfaceEGL.h"
#include "SharedSurfaceGL.h"
#include "../opengl/CompositorOGL.h"
#include "gfxUtils.h"
@ -35,7 +32,6 @@
#ifdef MOZ_WIDGET_GONK
#include "../opengl/GrallocTextureClient.h"
#include "../opengl/GrallocTextureHost.h"
#include "SharedSurfaceGralloc.h"
#endif
#ifdef MOZ_X11
@ -43,12 +39,10 @@
#endif
#ifdef XP_MACOSX
#include "SharedSurfaceIO.h"
#include "../opengl/MacIOSurfaceTextureHostOGL.h"
#endif
#ifdef XP_WIN
#include "SharedSurfaceANGLE.h"
#include "mozilla/layers/TextureDIB.h"
#endif
@ -96,6 +90,8 @@ public:
RefPtr<TextureHost> mTextureHost;
};
////////////////////////////////////////////////////////////////////////////////
// static
PTextureParent*
TextureHost::CreateIPDLActor(CompositableParentManager* aManager,
@ -217,9 +213,6 @@ TextureHost::Create(const SurfaceDescriptor& aDesc,
case SurfaceDescriptor::TSurfaceTextureDescriptor:
return CreateTextureHostOGL(aDesc, aDeallocator, aFlags);
case SurfaceDescriptor::TSharedSurfaceDescriptor:
return MakeAndAddRef<SharedSurfaceTextureHost>(aFlags, aDesc.get_SharedSurfaceDescriptor());
case SurfaceDescriptor::TSurfaceDescriptorMacIOSurface:
if (Compositor::GetBackend() == LayersBackend::LAYERS_OPENGL) {
return CreateTextureHostOGL(aDesc, aDeallocator, aFlags);
@ -875,153 +868,6 @@ TextureParent::RecvRecycleTexture(const TextureFlags& aTextureFlags)
return true;
}
////////////////////////////////////////////////////////////////////////////////
static RefPtr<TextureSource>
SharedSurfaceToTexSource(gl::SharedSurface* abstractSurf, Compositor* compositor)
{
MOZ_ASSERT(abstractSurf);
MOZ_ASSERT(abstractSurf->mType != gl::SharedSurfaceType::Basic);
MOZ_ASSERT(abstractSurf->mType != gl::SharedSurfaceType::Gralloc);
if (!compositor) {
return nullptr;
}
gfx::SurfaceFormat format = abstractSurf->mHasAlpha ? gfx::SurfaceFormat::R8G8B8A8
: gfx::SurfaceFormat::R8G8B8X8;
RefPtr<TextureSource> texSource;
switch (abstractSurf->mType) {
#ifdef XP_WIN
case gl::SharedSurfaceType::EGLSurfaceANGLE: {
auto surf = gl::SharedSurface_ANGLEShareHandle::Cast(abstractSurf);
MOZ_ASSERT(compositor->GetBackendType() == LayersBackend::LAYERS_D3D11);
CompositorD3D11* compositorD3D11 = static_cast<CompositorD3D11*>(compositor);
RefPtr<ID3D11Texture2D> tex = surf->GetConsumerTexture();
if (!tex) {
NS_WARNING("Failed to open shared resource.");
break;
}
texSource = new DataTextureSourceD3D11(format, compositorD3D11, tex);
break;
}
#endif
case gl::SharedSurfaceType::GLTextureShare: {
auto surf = gl::SharedSurface_GLTexture::Cast(abstractSurf);
MOZ_ASSERT(compositor->GetBackendType() == LayersBackend::LAYERS_OPENGL);
CompositorOGL* compositorOGL = static_cast<CompositorOGL*>(compositor);
gl::GLContext* gl = compositorOGL->gl();
GLenum target = surf->ConsTextureTarget();
GLuint tex = surf->ConsTexture(gl);
texSource = new GLTextureSource(compositorOGL, tex, target,
surf->mSize, format,
true/*externally owned*/);
break;
}
case gl::SharedSurfaceType::EGLImageShare: {
auto surf = gl::SharedSurface_EGLImage::Cast(abstractSurf);
MOZ_ASSERT(compositor->GetBackendType() == LayersBackend::LAYERS_OPENGL);
CompositorOGL* compositorOGL = static_cast<CompositorOGL*>(compositor);
gl::GLContext* gl = compositorOGL->gl();
MOZ_ASSERT(gl->IsCurrent());
GLenum target = 0;
GLuint tex = 0;
surf->AcquireConsumerTexture(gl, &tex, &target);
texSource = new GLTextureSource(compositorOGL, tex, target,
surf->mSize, format,
true/*externally owned*/);
break;
}
#ifdef XP_MACOSX
case gl::SharedSurfaceType::IOSurface: {
auto surf = gl::SharedSurface_IOSurface::Cast(abstractSurf);
MacIOSurface* ioSurf = surf->GetIOSurface();
MOZ_ASSERT(compositor->GetBackendType() == LayersBackend::LAYERS_OPENGL);
CompositorOGL* compositorOGL = static_cast<CompositorOGL*>(compositor);
texSource = new MacIOSurfaceTextureSourceOGL(compositorOGL, ioSurf);
break;
}
#endif
default:
break;
}
MOZ_ASSERT(texSource.get(), "TextureSource creation failed.");
return texSource;
}
////////////////////////////////////////////////////////////////////////////////
// SharedSurfaceTextureHost
SharedSurfaceTextureHost::SharedSurfaceTextureHost(TextureFlags aFlags,
const SharedSurfaceDescriptor& aDesc)
: TextureHost(aFlags)
, mIsLocked(false)
, mSurf((gl::SharedSurface*)aDesc.surf())
, mCompositor(nullptr)
{
MOZ_ASSERT(mSurf);
}
gfx::SurfaceFormat
SharedSurfaceTextureHost::GetFormat() const
{
MOZ_ASSERT(mTexSource);
return mTexSource->GetFormat();
}
gfx::IntSize
SharedSurfaceTextureHost::GetSize() const
{
MOZ_ASSERT(mTexSource);
return mTexSource->GetSize();
}
void
SharedSurfaceTextureHost::EnsureTexSource()
{
MOZ_ASSERT(mIsLocked);
if (mTexSource)
return;
mTexSource = SharedSurfaceToTexSource(mSurf, mCompositor);
MOZ_ASSERT(mTexSource);
}
bool
SharedSurfaceTextureHost::Lock()
{
MOZ_ASSERT(!mIsLocked);
mSurf->ConsumerAcquire();
mIsLocked = true;
EnsureTexSource();
return true;
}
void
SharedSurfaceTextureHost::Unlock()
{
MOZ_ASSERT(mIsLocked);
mSurf->ConsumerRelease();
mIsLocked = false;
}
////////////////////////////////////////////////////////////////////////////////
} // namespace

View File

@ -31,9 +31,6 @@
#include "mozilla/gfx/Rect.h"
namespace mozilla {
namespace gl {
class SharedSurface;
}
namespace ipc {
class Shmem;
}
@ -43,7 +40,6 @@ namespace layers {
class Compositor;
class CompositableParentManager;
class SurfaceDescriptor;
class SharedSurfaceDescriptor;
class ISurfaceAllocator;
class TextureHostOGL;
class TextureSourceOGL;
@ -681,64 +677,6 @@ protected:
uint8_t* mBuffer;
};
/**
* A TextureHost for SharedSurfaces
*/
class SharedSurfaceTextureHost : public TextureHost
{
public:
SharedSurfaceTextureHost(TextureFlags aFlags,
const SharedSurfaceDescriptor& aDesc);
virtual ~SharedSurfaceTextureHost() {
MOZ_ASSERT(!mIsLocked);
}
virtual void DeallocateDeviceData() override {};
virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() override {
return nullptr; // XXX - implement this (for MOZ_DUMP_PAINTING)
}
virtual void SetCompositor(Compositor* aCompositor) override {
MOZ_ASSERT(!mIsLocked);
if (aCompositor == mCompositor)
return;
mTexSource = nullptr;
mCompositor = aCompositor;
}
public:
virtual bool Lock() override;
virtual void Unlock() override;
virtual bool BindTextureSource(CompositableTextureSourceRef& aTexture) override {
MOZ_ASSERT(mIsLocked);
MOZ_ASSERT(mTexSource);
aTexture = mTexSource;
return !!aTexture;
}
virtual gfx::SurfaceFormat GetFormat() const override;
virtual gfx::IntSize GetSize() const override;
#ifdef MOZ_LAYERS_HAVE_LOG
virtual const char* Name() override { return "SharedSurfaceTextureHost"; }
#endif
protected:
void EnsureTexSource();
bool mIsLocked;
gl::SharedSurface* const mSurf;
RefPtr<Compositor> mCompositor;
RefPtr<TextureSource> mTexSource;
};
class MOZ_STACK_CLASS AutoLockTextureHost
{
public:

View File

@ -802,6 +802,18 @@ CompositorParent::RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot,
return true;
}
bool
CompositorParent::RecvMakeWidgetSnapshot(const SurfaceDescriptor& aInSnapshot)
{
if (!mCompositor || !mCompositor->GetWidget()) {
return false;
}
RefPtr<DrawTarget> target = GetDrawTargetForDescriptor(aInSnapshot, gfx::BackendType::CAIRO);
mCompositor->GetWidget()->CaptureWidgetOnScreen(target);
return true;
}
bool
CompositorParent::RecvFlushRendering()
{
@ -1688,6 +1700,8 @@ public:
virtual bool RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot,
const gfx::IntRect& aRect) override
{ return true; }
virtual bool RecvMakeWidgetSnapshot(const SurfaceDescriptor& aInSnapshot) override
{ return true; }
virtual bool RecvFlushRendering() override { return true; }
virtual bool RecvNotifyRegionInvalidated(const nsIntRegion& aRegion) override { return true; }
virtual bool RecvStartFrameTimeRecording(const int32_t& aBufferSize, uint32_t* aOutStartIndex) override { return true; }

View File

@ -240,6 +240,7 @@ public:
virtual bool RecvAdoptChild(const uint64_t& child) override;
virtual bool RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot,
const gfx::IntRect& aRect) override;
virtual bool RecvMakeWidgetSnapshot(const SurfaceDescriptor& aInSnapshot) override;
virtual bool RecvFlushRendering() override;
virtual bool RecvGetTileSize(int32_t* aWidth, int32_t* aHeight) override;

View File

@ -351,7 +351,7 @@ void ImageBridgeChild::DispatchReleaseImageClient(ImageClient* aClient)
static void ReleaseTextureClientNow(TextureClient* aClient)
{
MOZ_ASSERT(InImageBridgeChildThread());
aClient->Release();
RELEASE_MANUALLY(aClient);
}
// static
@ -368,7 +368,7 @@ void ImageBridgeChild::DispatchReleaseTextureClient(TextureClient* aClient)
// has already shut down, along with the TextureChild, which means no
// message will be sent and it is safe to run this code from any thread.
MOZ_ASSERT(aClient->GetIPDLActor() == nullptr);
aClient->Release();
RELEASE_MANUALLY(aClient);
return;
}

View File

@ -206,7 +206,7 @@ bool ImageBridgeParent::RecvWillStop()
static void
ReleaseImageBridgeParent(ImageBridgeParent* aImageBridgeParent)
{
aImageBridgeParent->Release();
RELEASE_MANUALLY(aImageBridgeParent);
}
bool ImageBridgeParent::RecvStop()
@ -218,7 +218,7 @@ bool ImageBridgeParent::RecvStop()
// the handling of this sync message can't race with the destruction of
// the ImageBridgeParent, which would trigger the dreaded "mismatched CxxStackFrames"
// assertion of MessageChannel.
AddRef();
ADDREF_MANUALLY(this);
MessageLoop::current()->PostTask(
FROM_HERE,
NewRunnableFunction(&ReleaseImageBridgeParent, this));

View File

@ -162,12 +162,12 @@ protected:
void AddIPDLReference() {
MOZ_ASSERT(mIPCOpen == false);
mIPCOpen = true;
AddRef();
ADDREF_MANUALLY(this);
}
void ReleaseIPDLReference() {
MOZ_ASSERT(mIPCOpen == true);
mIPCOpen = false;
Release();
RELEASE_MANUALLY(this);
}
friend class CompositorParent;
friend class CrossProcessCompositorParent;

View File

@ -65,7 +65,7 @@ struct SurfaceDescriptorDXGIYCbCr {
};
struct SurfaceDescriptorMacIOSurface {
uint32_t surface;
uint32_t surfaceId;
double scaleFactor;
bool isOpaque;
};
@ -79,6 +79,7 @@ struct EGLImageDescriptor {
uintptr_t image; // `EGLImage` is a `void*`.
uintptr_t fence;
IntSize size;
bool hasAlpha;
};
struct NewSurfaceDescriptorGralloc {
@ -92,10 +93,6 @@ struct NewSurfaceDescriptorGralloc {
bool isOpaque;
};
struct SharedSurfaceDescriptor {
uintptr_t surf;
};
/**
* Used for shmem-backed YCbCr and (flavors of) RGBA textures
*/
@ -107,7 +104,7 @@ struct SurfaceDescriptorShmem {
/**
* Used for "raw memory"-backed YCbCr and (flavors of) RGBA textures
*/
struct SurfaceDescriptorMemory {
struct SurfaceDescriptorMemory {
uintptr_t data;
SurfaceFormat format;
};
@ -125,7 +122,6 @@ union SurfaceDescriptor {
EGLImageDescriptor;
SurfaceDescriptorMacIOSurface;
NewSurfaceDescriptorGralloc;
SharedSurfaceDescriptor;
null_t;
};

View File

@ -111,6 +111,14 @@ parent:
// and so forth being interpolated. That's what we want to happen.
sync MakeSnapshot(SurfaceDescriptor inSnapshot, IntRect dirtyRect);
// Same as Makesnapshot(), except the snapshot is read from the underlying
// operating system desktop rather than the compositor's backbuffer. This
// is intended for testing whether hardware acceleration works.
//
// This call is part of IPDL, even though it simply wraps an nsIWidget
// call, to make sure it does not occur in the middle of a composite.
sync MakeWidgetSnapshot(SurfaceDescriptor inSnapshot);
// Make sure any pending composites are started immediately and
// block until they are completed.
sync FlushRendering();

View File

@ -37,7 +37,10 @@ SharedPlanarYCbCrImage::~SharedPlanarYCbCrImage() {
if (mCompositable->GetAsyncID() != 0 &&
!InImageBridgeChildThread()) {
ImageBridgeChild::DispatchReleaseTextureClient(mTextureClient.forget().take());
ADDREF_MANUALLY(mTextureClient);
ImageBridgeChild::DispatchReleaseTextureClient(mTextureClient);
mTextureClient = nullptr;
ImageBridgeChild::DispatchReleaseImageClient(mCompositable.forget().take());
}
}

View File

@ -69,7 +69,10 @@ SharedRGBImage::~SharedRGBImage()
if (mCompositable->GetAsyncID() != 0 &&
!InImageBridgeChildThread()) {
ImageBridgeChild::DispatchReleaseTextureClient(mTextureClient.forget().take());
ADDREF_MANUALLY(mTextureClient);
ImageBridgeChild::DispatchReleaseTextureClient(mTextureClient);
mTextureClient = nullptr;
ImageBridgeChild::DispatchReleaseImageClient(mCompositable.forget().take());
}
}

View File

@ -118,6 +118,7 @@ EXPORTS.mozilla.layers += [
'client/TextureClient.h',
'client/TextureClientPool.h',
'client/TextureClientRecycleAllocator.h',
'client/TextureClientSharedSurface.h',
'client/TiledContentClient.h',
'composite/AsyncCompositionManager.h',
'composite/CanvasLayerComposite.h',
@ -267,6 +268,7 @@ UNIFIED_SOURCES += [
'client/TextureClient.cpp',
'client/TextureClientPool.cpp',
'client/TextureClientRecycleAllocator.cpp',
'client/TextureClientSharedSurface.cpp',
'client/TiledContentClient.cpp',
'composite/AsyncCompositionManager.cpp',
'composite/CanvasLayerComposite.cpp',

View File

@ -19,6 +19,10 @@ class MediaBuffer;
};
namespace mozilla {
namespace gl {
class SharedSurface;
}
namespace layers {
/**

View File

@ -14,7 +14,7 @@ MacIOSurfaceTextureHostOGL::MacIOSurfaceTextureHostOGL(TextureFlags aFlags,
const SurfaceDescriptorMacIOSurface& aDescriptor)
: TextureHost(aFlags)
{
mSurface = MacIOSurface::LookupSurface(aDescriptor.surface(),
mSurface = MacIOSurface::LookupSurface(aDescriptor.surfaceId(),
aDescriptor.scaleFactor(),
!aDescriptor.isOpaque());
}

View File

@ -46,7 +46,9 @@ EGLImageTextureClient::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
MOZ_ASSERT(IsAllocated());
const EGLImageImage::Data* data = mImage->GetData();
aOutDescriptor = EGLImageDescriptor((uintptr_t)data->mImage, (uintptr_t)data->mSync, mSize);
const bool hasAlpha = true;
aOutDescriptor = EGLImageDescriptor((uintptr_t)data->mImage, (uintptr_t)data->mSync,
mSize, hasAlpha);
return true;
}

View File

@ -15,10 +15,6 @@
#include "mozilla/gfx/2D.h" // for DataSourceSurface
#include "mozilla/gfx/BaseSize.h" // for BaseSize
#include "mozilla/gfx/Logging.h" // for gfxCriticalError
#ifdef MOZ_WIDGET_GONK
# include "GrallocImages.h" // for GrallocImage
# include "EGLImageHelpers.h"
#endif
#include "mozilla/layers/ISurfaceAllocator.h"
#include "mozilla/layers/YCbCrImageDataSerializer.h"
#include "mozilla/layers/GrallocTextureHost.h"
@ -26,11 +22,17 @@
#include "AndroidSurfaceTexture.h"
#include "GfxTexturesReporter.h" // for GfxTexturesReporter
#include "GLBlitTextureImageHelper.h"
#include "GeckoProfiler.h"
#ifdef MOZ_WIDGET_GONK
# include "GrallocImages.h" // for GrallocImage
# include "EGLImageHelpers.h"
#endif
#ifdef XP_MACOSX
#include "SharedSurfaceIO.h"
#include "mozilla/layers/MacIOSurfaceTextureHostOGL.h"
#endif
#include "GeckoProfiler.h"
using namespace mozilla::gl;
using namespace mozilla::gfx;
@ -69,7 +71,8 @@ CreateTextureHostOGL(const SurfaceDescriptor& aDesc,
result = new EGLImageTextureHost(aFlags,
(EGLImage)desc.image(),
(EGLSync)desc.fence(),
desc.size());
desc.size(),
desc.hasAlpha());
break;
}
@ -494,6 +497,8 @@ EGLImageTextureSource::EGLImageTextureSource(CompositorOGL* aCompositor,
, mWrapMode(aWrapMode)
, mSize(aSize)
{
MOZ_ASSERT(mTextureTarget == LOCAL_GL_TEXTURE_2D ||
mTextureTarget == LOCAL_GL_TEXTURE_EXTERNAL);
}
void
@ -507,13 +512,12 @@ EGLImageTextureSource::BindTexture(GLenum aTextureUnit, gfx::Filter aFilter)
MOZ_ASSERT(DoesEGLContextSupportSharingWithEGLImage(gl()),
"EGLImage not supported or disabled in runtime");
GLuint tex = mCompositor->GetTemporaryTexture(GetTextureTarget(), aTextureUnit);
GLuint tex = mCompositor->GetTemporaryTexture(mTextureTarget, aTextureUnit);
gl()->fActiveTexture(aTextureUnit);
gl()->fBindTexture(mTextureTarget, tex);
MOZ_ASSERT(mTextureTarget == LOCAL_GL_TEXTURE_2D);
gl()->fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_2D, mImage);
gl()->fEGLImageTargetTexture2D(mTextureTarget, mImage);
ApplyFilterToBoundTexture(gl(), aFilter, mTextureTarget);
}
@ -549,18 +553,18 @@ EGLImageTextureSource::GetTextureTransform()
EGLImageTextureHost::EGLImageTextureHost(TextureFlags aFlags,
EGLImage aImage,
EGLSync aSync,
gfx::IntSize aSize)
gfx::IntSize aSize,
bool hasAlpha)
: TextureHost(aFlags)
, mImage(aImage)
, mSync(aSync)
, mSize(aSize)
, mHasAlpha(hasAlpha)
, mCompositor(nullptr)
{
}
{}
EGLImageTextureHost::~EGLImageTextureHost()
{
}
{}
gl::GLContext*
EGLImageTextureHost::gl() const
@ -575,14 +579,23 @@ EGLImageTextureHost::Lock()
return false;
}
EGLint status = sEGLLibrary.fClientWaitSync(EGL_DISPLAY(), mSync, 0, LOCAL_EGL_FOREVER);
EGLint status = LOCAL_EGL_CONDITION_SATISFIED;
if (mSync) {
MOZ_ASSERT(sEGLLibrary.IsExtensionSupported(GLLibraryEGL::KHR_fence_sync));
status = sEGLLibrary.fClientWaitSync(EGL_DISPLAY(), mSync, 0, LOCAL_EGL_FOREVER);
}
if (status != LOCAL_EGL_CONDITION_SATISFIED) {
MOZ_ASSERT(status != 0,
"ClientWaitSync generated an error. Has mSync already been destroyed?");
return false;
}
if (!mTextureSource) {
gfx::SurfaceFormat format = gfx::SurfaceFormat::R8G8B8A8;
GLenum target = LOCAL_GL_TEXTURE_2D;
gfx::SurfaceFormat format = mHasAlpha ? gfx::SurfaceFormat::R8G8B8A8
: gfx::SurfaceFormat::R8G8B8X8;
GLenum target = LOCAL_GL_TEXTURE_EXTERNAL;
GLenum wrapMode = LOCAL_GL_CLAMP_TO_EDGE;
mTextureSource = new EGLImageTextureSource(mCompositor,
mImage,

View File

@ -425,7 +425,8 @@ public:
EGLImageTextureHost(TextureFlags aFlags,
EGLImage aImage,
EGLSync aSync,
gfx::IntSize aSize);
gfx::IntSize aSize,
bool hasAlpha);
virtual ~EGLImageTextureHost();
@ -461,6 +462,7 @@ protected:
const EGLImage mImage;
const EGLSync mSync;
const gfx::IntSize mSize;
const bool mHasAlpha;
RefPtr<CompositorOGL> mCompositor;
RefPtr<EGLImageTextureSource> mTextureSource;
};

View File

@ -391,7 +391,7 @@ IsSafeImageTransformComponent(gfxFloat aValue)
return aValue >= -32768 && aValue <= 32767;
}
#if !defined(MOZ_GFX_OPTIMIZE_MOBILE) && !defined(MOZ_WIDGET_COCOA)
#ifndef MOZ_GFX_OPTIMIZE_MOBILE
/**
* This returns the fastest operator to use for solid surfaces which have no
* alpha channel or their alpha channel is uniformly opaque.
@ -457,7 +457,7 @@ CreateSamplingRestrictedDrawable(gfxDrawable* aDrawable,
nsRefPtr<gfxDrawable> drawable = new gfxSurfaceDrawable(surface, size, gfxMatrix::Translation(-needed.TopLeft()));
return drawable.forget();
}
#endif // !MOZ_GFX_OPTIMIZE_MOBILE && !MOZ_WIDGET_COCOA
#endif // !MOZ_GFX_OPTIMIZE_MOBILE
// working around cairo/pixman bug (bug 364968)
// Our device-space-to-image-space transform may not be acceptable to pixman.
@ -652,7 +652,7 @@ gfxUtils::DrawPixelSnapped(gfxContext* aContext,
// On Mobile, we don't ever want to do this; it has the potential for
// allocating very large temporary surfaces, especially since we'll
// do full-page snapshots often (see bug 749426).
#if !defined(MOZ_GFX_OPTIMIZE_MOBILE) && !defined(MOZ_WIDGET_COCOA)
#ifndef MOZ_GFX_OPTIMIZE_MOBILE
nsRefPtr<gfxDrawable> restrictedDrawable =
CreateSamplingRestrictedDrawable(aDrawable, aContext,
aRegion, aFormat);

View File

@ -701,11 +701,35 @@ js::CreateRegExpPrototype(JSContext* cx, JSProtoKey key)
return proto;
}
static bool
ReportLastIndexNonwritable(JSContext* cx)
{
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_READ_ONLY, "\"lastIndex\"");
return false;
}
static bool
SetLastIndex(JSContext* cx, Handle<RegExpObject*> reobj, double lastIndex)
{
if (!reobj->lookup(cx, cx->names().lastIndex)->writable())
return ReportLastIndexNonwritable(cx);
reobj->setLastIndex(lastIndex);
return true;
}
/* ES6 final draft 21.2.5.2.2. */
RegExpRunStatus
js::ExecuteRegExp(JSContext* cx, HandleObject regexp, HandleString string,
MatchPairs* matches, RegExpStaticsUpdate staticsUpdate)
{
/* Step 1 (b) was performed by CallNonGenericMethod. */
/*
* WARNING: Despite the presence of spec step comment numbers, this
* algorithm isn't consistent with any ES6 version, draft or
* otherwise. YOU HAVE BEEN WARNED.
*/
/* Steps 1-2 performed by the caller. */
Rooted<RegExpObject*> reobj(cx, &regexp->as<RegExpObject>());
RegExpGuard re(cx);
@ -721,16 +745,15 @@ js::ExecuteRegExp(JSContext* cx, HandleObject regexp, HandleString string,
res = nullptr;
}
/* Step 3. */
RootedLinearString input(cx, string->ensureLinear(cx));
if (!input)
return RegExpRunStatus_Error;
/* Step 4. */
RootedValue lastIndex(cx, reobj->getLastIndex());
/* Step 3. */
size_t length = input->length();
/* Step 5. */
/* Steps 4-5. */
RootedValue lastIndex(cx, reobj->getLastIndex());
int searchIndex;
if (lastIndex.isInt32()) {
/* Aggressively avoid doubles. */
@ -740,9 +763,13 @@ js::ExecuteRegExp(JSContext* cx, HandleObject regexp, HandleString string,
if (!ToInteger(cx, lastIndex, &d))
return RegExpRunStatus_Error;
/* Inlined steps 6, 7, 9a with doubles to detect failure case. */
/* Inlined steps 6-10, 15.a with doubles to detect failure case. */
if (reobj->needUpdateLastIndex() && (d < 0 || d > length)) {
reobj->zeroLastIndex();
/* Steps 15.a.i-ii. */
if (!SetLastIndex(cx, reobj, 0))
return RegExpRunStatus_Error;
/* Step 15.a.iii. */
return RegExpRunStatus_Success_NotFound;
}
@ -750,7 +777,7 @@ js::ExecuteRegExp(JSContext* cx, HandleObject regexp, HandleString string,
}
/*
* Steps 6-7 (with sticky extension).
* Steps 6-10.
*
* Also make sure that we have a MatchPairs for regexps which update their
* last index, as we won't compute the last index otherwise.
@ -763,22 +790,30 @@ js::ExecuteRegExp(JSContext* cx, HandleObject regexp, HandleString string,
matches = &alternateMatches.ref();
}
/* Step 9a. */
/* Step 15.a. */
if (searchIndex < 0 || size_t(searchIndex) > length) {
reobj->zeroLastIndex();
/* Steps 15.a.i-ii. */
if (!SetLastIndex(cx, reobj, 0))
return RegExpRunStatus_Error;
/* Step 15.a.iii. */
return RegExpRunStatus_Success_NotFound;
}
/* Steps 8-21. */
/* Step 14-29. */
RegExpRunStatus status = ExecuteRegExpImpl(cx, res, *re, input, searchIndex, matches);
if (status == RegExpRunStatus_Error)
return RegExpRunStatus_Error;
/* Steps 9a and 11 (with sticky extension). */
if (status == RegExpRunStatus_Success_NotFound)
reobj->zeroLastIndex();
else if (reobj->needUpdateLastIndex())
reobj->setLastIndex((*matches)[0].limit);
if (status == RegExpRunStatus_Success_NotFound) {
/* Steps 15.a.i-ii. */
if (!SetLastIndex(cx, reobj, 0))
return RegExpRunStatus_Error;
} else if (reobj->needUpdateLastIndex()) {
/* Steps 18.a-b. */
if (!SetLastIndex(cx, reobj, (*matches)[0].limit))
return RegExpRunStatus_Error;
}
return status;
}

View File

@ -66,6 +66,7 @@ var ignoreClasses = {
"XPCOMFunctions" : true, // I'm a little unsure of this one
"_MD_IOVector" : true,
"malloc_table_t": true, // replace_malloc
"malloc_hook_table_t": true, // replace_malloc
};
// Ignore calls through TYPE.FIELD, where TYPE is the class or struct name containing

View File

@ -367,7 +367,8 @@ Statistics::formatCompactSummaryMessage() const
"Max Pause: %.3fms; MMU 20ms: %.1f%%; MMU 50ms: %.1f%%; Total: %.3fms; ",
t(longest), mmu20 * 100., mmu50 * 100., t(total));
} else {
JS_snprintf(buffer, sizeof(buffer), "Non-Incremental: %.3fms; ", t(total));
JS_snprintf(buffer, sizeof(buffer), "Non-Incremental: %.3fms (%s); ",
t(total), nonincrementalReason_);
}
if (!fragments.append(make_string_copy(buffer)))
return UniqueChars(nullptr);

View File

@ -0,0 +1,27 @@
var BUGNUMBER = 1168416;
var summary = "Regexp.prototype.test/exec shouldn't change lastIndex if not writable.";
print(BUGNUMBER + ": " + summary);
var regex = /0/g;
Object.freeze(regex);
var str = "abc000";
var desc = Object.getOwnPropertyDescriptor(regex, "lastIndex");
assertEq(desc.writable, false);
assertEq(desc.value, 0);
assertThrowsInstanceOf(() => regex.test(str), TypeError);
desc = Object.getOwnPropertyDescriptor(regex, "lastIndex");
assertEq(desc.writable, false);
assertEq(desc.value, 0);
assertThrowsInstanceOf(() => regex.exec(str), TypeError);
desc = Object.getOwnPropertyDescriptor(regex, "lastIndex");
assertEq(desc.writable, false);
assertEq(desc.value, 0);
if (typeof reportCompare === "function")
reportCompare(true, true);

View File

@ -1560,9 +1560,8 @@ void XPCJSRuntime::DestroyJSContextStack()
void XPCJSRuntime::SystemIsBeingShutDown()
{
if (mDetachedWrappedNativeProtoMap)
mDetachedWrappedNativeProtoMap->
Enumerate(DetachedWrappedNativeProtoShutdownMarker, nullptr);
mDetachedWrappedNativeProtoMap->
Enumerate(DetachedWrappedNativeProtoShutdownMarker, nullptr);
}
#define JS_OPTIONS_DOT_STR "javascript.options."
@ -1644,51 +1643,33 @@ XPCJSRuntime::~XPCJSRuntime()
JS_SetRuntimePrivate(Runtime(), nullptr);
// clean up and destroy maps...
if (mWrappedJSMap) {
mWrappedJSMap->ShutdownMarker();
delete mWrappedJSMap;
mWrappedJSMap = nullptr;
}
mWrappedJSMap->ShutdownMarker();
delete mWrappedJSMap;
mWrappedJSMap = nullptr;
if (mWrappedJSClassMap) {
delete mWrappedJSClassMap;
mWrappedJSClassMap = nullptr;
}
delete mWrappedJSClassMap;
mWrappedJSClassMap = nullptr;
if (mIID2NativeInterfaceMap) {
delete mIID2NativeInterfaceMap;
mIID2NativeInterfaceMap = nullptr;
}
delete mIID2NativeInterfaceMap;
mIID2NativeInterfaceMap = nullptr;
if (mClassInfo2NativeSetMap) {
delete mClassInfo2NativeSetMap;
mClassInfo2NativeSetMap = nullptr;
}
delete mClassInfo2NativeSetMap;
mClassInfo2NativeSetMap = nullptr;
if (mNativeSetMap) {
delete mNativeSetMap;
mNativeSetMap = nullptr;
}
delete mNativeSetMap;
mNativeSetMap = nullptr;
if (mThisTranslatorMap) {
delete mThisTranslatorMap;
mThisTranslatorMap = nullptr;
}
delete mThisTranslatorMap;
mThisTranslatorMap = nullptr;
if (mNativeScriptableSharedMap) {
delete mNativeScriptableSharedMap;
mNativeScriptableSharedMap = nullptr;
}
delete mNativeScriptableSharedMap;
mNativeScriptableSharedMap = nullptr;
if (mDyingWrappedNativeProtoMap) {
delete mDyingWrappedNativeProtoMap;
mDyingWrappedNativeProtoMap = nullptr;
}
delete mDyingWrappedNativeProtoMap;
mDyingWrappedNativeProtoMap = nullptr;
if (mDetachedWrappedNativeProtoMap) {
delete mDetachedWrappedNativeProtoMap;
mDetachedWrappedNativeProtoMap = nullptr;
}
delete mDetachedWrappedNativeProtoMap;
mDetachedWrappedNativeProtoMap = nullptr;
#ifdef MOZ_ENABLE_PROFILER_SPS
// Tell the profiler that the runtime is gone
@ -3674,7 +3655,7 @@ XPCJSRuntime::DebugDump(int16_t depth)
XPC_LOG_INDENT();
XPC_LOG_ALWAYS(("mJSRuntime @ %x", Runtime()));
XPC_LOG_ALWAYS(("mWrappedJSToReleaseArray @ %x with %d wrappers(s)", \
XPC_LOG_ALWAYS(("mWrappedJSToReleaseArray @ %x with %d wrappers(s)",
&mWrappedJSToReleaseArray,
mWrappedJSToReleaseArray.Length()));
@ -3692,43 +3673,39 @@ XPCJSRuntime::DebugDump(int16_t depth)
XPC_LOG_OUTDENT();
}
XPC_LOG_ALWAYS(("mWrappedJSClassMap @ %x with %d wrapperclasses(s)", \
mWrappedJSClassMap, mWrappedJSClassMap ? \
mWrappedJSClassMap->Count() : 0));
XPC_LOG_ALWAYS(("mWrappedJSClassMap @ %x with %d wrapperclasses(s)",
mWrappedJSClassMap, mWrappedJSClassMap->Count()));
// iterate wrappersclasses...
if (depth && mWrappedJSClassMap && mWrappedJSClassMap->Count()) {
if (depth && mWrappedJSClassMap->Count()) {
XPC_LOG_INDENT();
mWrappedJSClassMap->Enumerate(WrappedJSClassMapDumpEnumerator, &depth);
XPC_LOG_OUTDENT();
}
XPC_LOG_ALWAYS(("mWrappedJSMap @ %x with %d wrappers(s)", \
mWrappedJSMap, mWrappedJSMap ? \
mWrappedJSMap->Count() : 0));
XPC_LOG_ALWAYS(("mWrappedJSMap @ %x with %d wrappers(s)",
mWrappedJSMap, mWrappedJSMap->Count()));
// iterate wrappers...
if (depth && mWrappedJSMap && mWrappedJSMap->Count()) {
if (depth && mWrappedJSMap->Count()) {
XPC_LOG_INDENT();
mWrappedJSMap->Dump(depth);
XPC_LOG_OUTDENT();
}
XPC_LOG_ALWAYS(("mIID2NativeInterfaceMap @ %x with %d interface(s)", \
mIID2NativeInterfaceMap, mIID2NativeInterfaceMap ? \
mIID2NativeInterfaceMap->Count() : 0));
XPC_LOG_ALWAYS(("mIID2NativeInterfaceMap @ %x with %d interface(s)",
mIID2NativeInterfaceMap,
mIID2NativeInterfaceMap->Count()));
XPC_LOG_ALWAYS(("mClassInfo2NativeSetMap @ %x with %d sets(s)", \
mClassInfo2NativeSetMap, mClassInfo2NativeSetMap ? \
mClassInfo2NativeSetMap->Count() : 0));
XPC_LOG_ALWAYS(("mClassInfo2NativeSetMap @ %x with %d sets(s)",
mClassInfo2NativeSetMap,
mClassInfo2NativeSetMap->Count()));
XPC_LOG_ALWAYS(("mThisTranslatorMap @ %x with %d translator(s)", \
mThisTranslatorMap, mThisTranslatorMap ? \
mThisTranslatorMap->Count() : 0));
XPC_LOG_ALWAYS(("mThisTranslatorMap @ %x with %d translator(s)",
mThisTranslatorMap, mThisTranslatorMap->Count()));
XPC_LOG_ALWAYS(("mNativeSetMap @ %x with %d sets(s)", \
mNativeSetMap, mNativeSetMap ? \
mNativeSetMap->Count() : 0));
XPC_LOG_ALWAYS(("mNativeSetMap @ %x with %d sets(s)",
mNativeSetMap, mNativeSetMap->Count()));
// iterate sets...
if (depth && mNativeSetMap && mNativeSetMap->Count()) {
if (depth && mNativeSetMap->Count()) {
XPC_LOG_INDENT();
mNativeSetMap->Enumerate(NativeSetDumpEnumerator, &depth);
XPC_LOG_OUTDENT();

View File

@ -173,8 +173,8 @@ Native2WrappedNativeMap::newMap(int length)
}
Native2WrappedNativeMap::Native2WrappedNativeMap(int length)
: mTable(new PLDHashTable(PL_DHashGetStubOps(), sizeof(Entry), length))
{
mTable = new PLDHashTable(PL_DHashGetStubOps(), sizeof(Entry), length);
}
Native2WrappedNativeMap::~Native2WrappedNativeMap()
@ -187,7 +187,7 @@ Native2WrappedNativeMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)
{
size_t n = 0;
n += mallocSizeOf(this);
n += mTable ? PL_DHashTableSizeOfIncludingThis(mTable, SizeOfEntryExcludingThis, mallocSizeOf) : 0;
n += PL_DHashTableSizeOfIncludingThis(mTable, SizeOfEntryExcludingThis, mallocSizeOf);
return n;
}
@ -213,16 +213,12 @@ const struct PLDHashTableOps IID2WrappedJSClassMap::Entry::sOps =
IID2WrappedJSClassMap*
IID2WrappedJSClassMap::newMap(int length)
{
IID2WrappedJSClassMap* map = new IID2WrappedJSClassMap(length);
if (map && map->mTable)
return map;
delete map;
return nullptr;
return new IID2WrappedJSClassMap(length);
}
IID2WrappedJSClassMap::IID2WrappedJSClassMap(int length)
: mTable(new PLDHashTable(&Entry::sOps, sizeof(Entry), length))
{
mTable = new PLDHashTable(&Entry::sOps, sizeof(Entry), length);
}
IID2WrappedJSClassMap::~IID2WrappedJSClassMap()
@ -230,7 +226,6 @@ IID2WrappedJSClassMap::~IID2WrappedJSClassMap()
delete mTable;
}
/***************************************************************************/
// implement IID2NativeInterfaceMap...
@ -246,16 +241,12 @@ const struct PLDHashTableOps IID2NativeInterfaceMap::Entry::sOps =
IID2NativeInterfaceMap*
IID2NativeInterfaceMap::newMap(int length)
{
IID2NativeInterfaceMap* map = new IID2NativeInterfaceMap(length);
if (map && map->mTable)
return map;
delete map;
return nullptr;
return new IID2NativeInterfaceMap(length);
}
IID2NativeInterfaceMap::IID2NativeInterfaceMap(int length)
: mTable(new PLDHashTable(&Entry::sOps, sizeof(Entry), length))
{
mTable = new PLDHashTable(&Entry::sOps, sizeof(Entry), length);
}
IID2NativeInterfaceMap::~IID2NativeInterfaceMap()
@ -268,7 +259,7 @@ IID2NativeInterfaceMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)
{
size_t n = 0;
n += mallocSizeOf(this);
n += mTable ? PL_DHashTableSizeOfIncludingThis(mTable, SizeOfEntryExcludingThis, mallocSizeOf) : 0;
n += PL_DHashTableSizeOfIncludingThis(mTable, SizeOfEntryExcludingThis, mallocSizeOf);
return n;
}
@ -287,16 +278,12 @@ IID2NativeInterfaceMap::SizeOfEntryExcludingThis(PLDHashEntryHdr* hdr,
ClassInfo2NativeSetMap*
ClassInfo2NativeSetMap::newMap(int length)
{
ClassInfo2NativeSetMap* map = new ClassInfo2NativeSetMap(length);
if (map && map->mTable)
return map;
delete map;
return nullptr;
return new ClassInfo2NativeSetMap(length);
}
ClassInfo2NativeSetMap::ClassInfo2NativeSetMap(int length)
: mTable(new PLDHashTable(PL_DHashGetStubOps(), sizeof(Entry), length))
{
mTable = new PLDHashTable(PL_DHashGetStubOps(), sizeof(Entry), length);
}
ClassInfo2NativeSetMap::~ClassInfo2NativeSetMap()
@ -310,7 +297,7 @@ ClassInfo2NativeSetMap::ShallowSizeOfIncludingThis(mozilla::MallocSizeOf mallocS
size_t n = 0;
n += mallocSizeOf(this);
// The second arg is nullptr because this is a "shallow" measurement of the map.
n += mTable ? PL_DHashTableSizeOfIncludingThis(mTable, nullptr, mallocSizeOf) : 0;
n += PL_DHashTableSizeOfIncludingThis(mTable, nullptr, mallocSizeOf);
return n;
}
@ -325,8 +312,8 @@ ClassInfo2WrappedNativeProtoMap::newMap(int length)
}
ClassInfo2WrappedNativeProtoMap::ClassInfo2WrappedNativeProtoMap(int length)
: mTable(new PLDHashTable(PL_DHashGetStubOps(), sizeof(Entry), length))
{
mTable = new PLDHashTable(PL_DHashGetStubOps(), sizeof(Entry), length);
}
ClassInfo2WrappedNativeProtoMap::~ClassInfo2WrappedNativeProtoMap()
@ -339,7 +326,7 @@ ClassInfo2WrappedNativeProtoMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallo
{
size_t n = 0;
n += mallocSizeOf(this);
n += mTable ? PL_DHashTableSizeOfIncludingThis(mTable, SizeOfEntryExcludingThis, mallocSizeOf) : 0;
n += PL_DHashTableSizeOfIncludingThis(mTable, SizeOfEntryExcludingThis, mallocSizeOf);
return n;
}
@ -437,16 +424,12 @@ const struct PLDHashTableOps NativeSetMap::Entry::sOps =
NativeSetMap*
NativeSetMap::newMap(int length)
{
NativeSetMap* map = new NativeSetMap(length);
if (map && map->mTable)
return map;
delete map;
return nullptr;
return new NativeSetMap(length);
}
NativeSetMap::NativeSetMap(int length)
: mTable(new PLDHashTable(&Entry::sOps, sizeof(Entry), length))
{
mTable = new PLDHashTable(&Entry::sOps, sizeof(Entry), length);
}
NativeSetMap::~NativeSetMap()
@ -459,7 +442,7 @@ NativeSetMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)
{
size_t n = 0;
n += mallocSizeOf(this);
n += mTable ? PL_DHashTableSizeOfIncludingThis(mTable, SizeOfEntryExcludingThis, mallocSizeOf) : 0;
n += PL_DHashTableSizeOfIncludingThis(mTable, SizeOfEntryExcludingThis, mallocSizeOf);
return n;
}
@ -500,16 +483,12 @@ const struct PLDHashTableOps IID2ThisTranslatorMap::Entry::sOps =
IID2ThisTranslatorMap*
IID2ThisTranslatorMap::newMap(int length)
{
IID2ThisTranslatorMap* map = new IID2ThisTranslatorMap(length);
if (map && map->mTable)
return map;
delete map;
return nullptr;
return new IID2ThisTranslatorMap(length);
}
IID2ThisTranslatorMap::IID2ThisTranslatorMap(int length)
: mTable(new PLDHashTable(&Entry::sOps, sizeof(Entry), length))
{
mTable = new PLDHashTable(&Entry::sOps, sizeof(Entry), length);
}
IID2ThisTranslatorMap::~IID2ThisTranslatorMap()
@ -575,17 +554,12 @@ const struct PLDHashTableOps XPCNativeScriptableSharedMap::Entry::sOps =
XPCNativeScriptableSharedMap*
XPCNativeScriptableSharedMap::newMap(int length)
{
XPCNativeScriptableSharedMap* map =
new XPCNativeScriptableSharedMap(length);
if (map && map->mTable)
return map;
delete map;
return nullptr;
return new XPCNativeScriptableSharedMap(length);
}
XPCNativeScriptableSharedMap::XPCNativeScriptableSharedMap(int length)
: mTable(new PLDHashTable(&Entry::sOps, sizeof(Entry), length))
{
mTable = new PLDHashTable(&Entry::sOps, sizeof(Entry), length);
}
XPCNativeScriptableSharedMap::~XPCNativeScriptableSharedMap()
@ -627,17 +601,13 @@ XPCNativeScriptableSharedMap::GetNewOrUsed(uint32_t flags,
XPCWrappedNativeProtoMap*
XPCWrappedNativeProtoMap::newMap(int length)
{
XPCWrappedNativeProtoMap* map = new XPCWrappedNativeProtoMap(length);
if (map && map->mTable)
return map;
delete map;
return nullptr;
return new XPCWrappedNativeProtoMap(length);
}
XPCWrappedNativeProtoMap::XPCWrappedNativeProtoMap(int length)
: mTable(new PLDHashTable(PL_DHashGetStubOps(), sizeof(PLDHashEntryStub),
length))
{
mTable = new PLDHashTable(PL_DHashGetStubOps(),
sizeof(PLDHashEntryStub), length);
}
XPCWrappedNativeProtoMap::~XPCWrappedNativeProtoMap()

View File

@ -32,10 +32,13 @@ class JSObject2WrappedJSMap
public:
static JSObject2WrappedJSMap* newMap(int length) {
JSObject2WrappedJSMap* map = new JSObject2WrappedJSMap();
if (map && map->mTable.init(length))
return map;
delete map;
return nullptr;
if (!map->mTable.init(length)) {
// This is a decent estimate of the size of the hash table's
// entry storage. The |2| is because on average the capacity is
// twice the requested length.
NS_ABORT_OOM(length * 2 * sizeof(Map::Entry));
}
return map;
}
inline nsXPCWrappedJS* Find(JSObject* Obj) {
@ -599,10 +602,13 @@ class JSObject2JSObjectMap
public:
static JSObject2JSObjectMap* newMap(int length) {
JSObject2JSObjectMap* map = new JSObject2JSObjectMap();
if (map && map->mTable.init(length))
return map;
delete map;
return nullptr;
if (!map->mTable.init(length)) {
// This is a decent estimate of the size of the hash table's
// entry storage. The |2| is because on average the capacity is
// twice the requested length.
NS_ABORT_OOM(length * 2 * sizeof(Map::Entry));
}
return map;
}
inline JSObject* Find(JSObject* key) {

View File

@ -428,15 +428,11 @@ XPCWrappedNativeScope::~XPCWrappedNativeScope()
// We can do additional cleanup assertions here...
if (mWrappedNativeMap) {
MOZ_ASSERT(0 == mWrappedNativeMap->Count(), "scope has non-empty map");
delete mWrappedNativeMap;
}
MOZ_ASSERT(0 == mWrappedNativeMap->Count(), "scope has non-empty map");
delete mWrappedNativeMap;
if (mWrappedNativeProtoMap) {
MOZ_ASSERT(0 == mWrappedNativeProtoMap->Count(), "scope has non-empty map");
delete mWrappedNativeProtoMap;
}
MOZ_ASSERT(0 == mWrappedNativeProtoMap->Count(), "scope has non-empty map");
delete mWrappedNativeProtoMap;
// This should not be necessary, since the Components object should die
// with the scope but just in case.
@ -833,21 +829,20 @@ XPCWrappedNativeScope::DebugDump(int16_t depth)
XPC_LOG_ALWAYS(("mComponents @ %x", mComponents.get()));
XPC_LOG_ALWAYS(("mGlobalJSObject @ %x", mGlobalJSObject.get()));
XPC_LOG_ALWAYS(("mWrappedNativeMap @ %x with %d wrappers(s)", \
mWrappedNativeMap, \
mWrappedNativeMap ? mWrappedNativeMap->Count() : 0));
XPC_LOG_ALWAYS(("mWrappedNativeMap @ %x with %d wrappers(s)",
mWrappedNativeMap, mWrappedNativeMap->Count()));
// iterate contexts...
if (depth && mWrappedNativeMap && mWrappedNativeMap->Count()) {
if (depth && mWrappedNativeMap->Count()) {
XPC_LOG_INDENT();
mWrappedNativeMap->Enumerate(WrappedNativeMapDumpEnumerator, &depth);
XPC_LOG_OUTDENT();
}
XPC_LOG_ALWAYS(("mWrappedNativeProtoMap @ %x with %d protos(s)", \
mWrappedNativeProtoMap, \
mWrappedNativeProtoMap ? mWrappedNativeProtoMap->Count() : 0));
XPC_LOG_ALWAYS(("mWrappedNativeProtoMap @ %x with %d protos(s)",
mWrappedNativeProtoMap,
mWrappedNativeProtoMap->Count()));
// iterate contexts...
if (depth && mWrappedNativeProtoMap && mWrappedNativeProtoMap->Count()) {
if (depth && mWrappedNativeProtoMap->Count()) {
XPC_LOG_INDENT();
mWrappedNativeProtoMap->Enumerate(WrappedNativeProtoMapDumpEnumerator, &depth);
XPC_LOG_OUTDENT();

View File

@ -87,7 +87,6 @@ WrapperFactory::CreateXrayWaiver(JSContext* cx, HandleObject obj)
if (!scope->mWaiverWrapperMap) {
scope->mWaiverWrapperMap =
JSObject2JSObjectMap::newMap(XPC_WRAPPER_MAP_LENGTH);
MOZ_ASSERT(scope->mWaiverWrapperMap);
}
if (!scope->mWaiverWrapperMap->Add(cx, obj, waiver))
return nullptr;

View File

@ -73,7 +73,7 @@ public:
}
/**
* Allocate a nsFrameList from the shell arena.
* Infallibly allocate a nsFrameList from the shell arena.
*/
void* operator new(size_t sz, nsIPresShell* aPresShell) CPP_THROW_NEW;

View File

@ -145,8 +145,6 @@ nsLineBox::NoteFramesMovedFrom(nsLineBox* aFromLine)
}
}
// Overloaded new operator. Uses an arena (which comes from the presShell)
// to perform the allocation.
void*
nsLineBox::operator new(size_t sz, nsIPresShell* aPresShell) CPP_THROW_NEW
{

View File

@ -206,8 +206,8 @@ private:
nsLineBox(nsIFrame* aFrame, int32_t aCount, bool aIsBlock);
~nsLineBox();
// Overloaded new operator. Uses an arena (which comes from the presShell)
// to perform the allocation.
// Infallible overloaded new operator. Uses an arena (which comes from the
// presShell) to perform the allocation.
void* operator new(size_t sz, nsIPresShell* aPresShell) CPP_THROW_NEW;
void operator delete(void* aPtr, size_t sz) = delete;

View File

@ -116,7 +116,7 @@ random-if(OSX==1010) == background-size-monster-rem.html background-size-monster
# the image aren't the issue, because they're being obscured to avoid sampling
# algorithm dependencies (at least assuming the sampling algorithm in use
# doesn't sample too far astray from the boundaries).
fails-if(supportsRepeatResampling) == background-size-zoom-repeat.html background-size-zoom-repeat-ref.html
fails == background-size-zoom-repeat.html background-size-zoom-repeat-ref.html
# -moz-default-background-color and -moz-default-color (bug 591341)
== background-moz-default-background-color.html background-moz-default-background-color-ref.html

View File

@ -1014,7 +1014,7 @@ skip-if(B2G||Mulet) == 421234-1.html 421234-1-ref.html # Initial mulet triage: p
== 421436-1b.html 421436-1-ref.html
== 421632-1.html 421632-1-ref.html
!= 421710-1.html about:blank
skip-if(B2G||Mulet) fails-if(Android) fails-if(!supportsRepeatResampling) == 421885-1.xml 421885-1-ref.xml # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet) fails-if(Android) == 421885-1.xml 421885-1-ref.xml # Initial mulet triage: parity with B2G/B2G Desktop
== 421955-1.html 421955-1-ref.html
skip-if(B2G||Mulet) == 422249-1.html 422249-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
== 422394-1.html 422394-1-ref.html
@ -1164,13 +1164,13 @@ random == 445004-1.html 445004-1-ref.html # bug 472268
== 445142-1c.html 445142-1-ref.html
== 445142-2a.html 445142-2-ref.html
== 445142-2b.html 445142-2-ref.html
fails-if(!supportsRepeatResampling) == 446100-1a.html about:blank
skip-if(B2G||Mulet) fails-if(Android) fails-if(!supportsRepeatResampling) == 446100-1b.html about:blank # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet) fails-if(Android) fails-if(!supportsRepeatResampling) == 446100-1c.html about:blank # Initial mulet triage: parity with B2G/B2G Desktop
fails-if(!supportsRepeatResampling) == 446100-1d.html about:blank
== 446100-1a.html about:blank
skip-if(B2G||Mulet) fails-if(Android) == 446100-1b.html about:blank # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet) fails-if(Android) == 446100-1c.html about:blank # Initial mulet triage: parity with B2G/B2G Desktop
== 446100-1d.html about:blank
== 446100-1e.html about:blank
== 446100-1f.html about:blank
skip-if(B2G||Mulet) fails-if(Android) fails-if(!supportsRepeatResampling) == 446100-1g.html about:blank # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet) fails-if(Android) == 446100-1g.html about:blank # Initial mulet triage: parity with B2G/B2G Desktop
== 446100-1h.html about:blank
skip-if(B2G||Mulet) == 447749-1.html 447749-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
fuzzy(127,2) == 448193.html 448193-ref.html

View File

@ -18,7 +18,7 @@ fuzzy-if(d2d&&/^Windows\x20NT\x206\.1/.test(http.oscpu),16,90) == element-paint-
== element-paint-transform-repeated.html element-paint-transform-repeated-ref.html
fuzzy-if(d2d,255,24) == element-paint-transform-03.html element-paint-transform-03-ref.html
== element-paint-native-widget.html element-paint-native-widget-ref.html
fails-if(!supportsRepeatResampling) == element-paint-subimage-sampling-restriction.html about:blank
== element-paint-subimage-sampling-restriction.html about:blank
== element-paint-clippath.html element-paint-clippath-ref.html
== element-paint-sharpness-01a.html element-paint-sharpness-01b.html
== element-paint-sharpness-01b.html element-paint-sharpness-01c.html

View File

@ -1394,7 +1394,6 @@ SetFactor(const nsCSSValue& aValue, float& aField, bool& aCanStoreInRuleTree,
NS_NOTREACHED("SetFactor: inappropriate unit");
}
// Overloaded new operator that allocates from a presShell arena.
void*
nsRuleNode::operator new(size_t sz, nsPresContext* aPresContext) CPP_THROW_NEW
{
@ -1554,20 +1553,11 @@ nsRuleNode::Transition(nsIStyleRule* aRule, uint8_t aLevel,
else {
next = entry->mRuleNode = new (mPresContext)
nsRuleNode(mPresContext, this, aRule, aLevel, aIsImportantRule);
if (!next) {
PL_DHashTableRawRemove(ChildrenHash(), entry);
NS_WARNING("out of memory");
return this;
}
}
} else if (!next) {
// Create the new entry in our list.
next = new (mPresContext)
nsRuleNode(mPresContext, this, aRule, aLevel, aIsImportantRule);
if (!next) {
NS_WARNING("out of memory");
return this;
}
next->mNextSibling = ChildrenList();
SetChildrenList(next);
}

View File

@ -394,7 +394,7 @@ private:
uint32_t mRefCnt;
public:
// Overloaded new operator that allocates from a presShell arena.
// Infallible overloaded new operator that allocates from a presShell arena.
void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW;
void Destroy() { DestroyInternal(nullptr); }
@ -651,6 +651,7 @@ private:
~nsRuleNode();
public:
// This is infallible; it will never return nullptr.
static nsRuleNode* CreateRootNode(nsPresContext* aPresContext);
static void EnsureBlockDisplay(uint8_t& display,

View File

@ -218,10 +218,7 @@ nsStyleSet::BeginReconstruct()
NS_ASSERTION(mRuleTree, "Reconstructing before first construction?");
// Create a new rule tree root
nsRuleNode* newTree =
nsRuleNode::CreateRootNode(mRuleTree->PresContext());
if (!newTree)
return NS_ERROR_OUT_OF_MEMORY;
nsRuleNode* newTree = nsRuleNode::CreateRootNode(mRuleTree->PresContext());
// Save the old rule tree so we can destroy it later
if (!mOldRuleTrees.AppendElement(mRuleTree)) {

View File

@ -755,9 +755,6 @@ function BuildConditionSandbox(aURL) {
dump("REFTEST INFO | " + JSON.stringify(CU.waiveXrays(sandbox)) + " \n");
gDumpedConditionSandbox = true;
}
// Graphics features
sandbox.supportsRepeatResampling = !sandbox.cocoaWidget;
return sandbox;
}

View File

@ -61,6 +61,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "nsServiceManagerUtils.h"
#include "ScopedNSSTypes.h"
#include "runnable_utils.h"
#include "nsIPrefService.h"
#include "nsIPrefBranch.h"
// nICEr includes
extern "C" {
@ -434,8 +436,29 @@ RefPtr<NrIceCtx> NrIceCtx::Create(const std::string& name,
NR_reg_set_uchar((char *)"ice.pref.interface.wlan0", 232);
}
NR_reg_set_uint4((char *)"stun.client.maximum_transmits",7);
NR_reg_set_uint4((char *)NR_ICE_REG_TRICKLE_GRACE_PERIOD, 5000);
int32_t stun_client_maximum_transmits = 7;
int32_t ice_trickle_grace_period = 5000;
#ifndef MOZILLA_XPCOMRT_API
nsresult res;
nsCOMPtr<nsIPrefService> prefs =
do_GetService("@mozilla.org/preferences-service;1", &res);
if (NS_SUCCEEDED(res)) {
nsCOMPtr<nsIPrefBranch> branch = do_QueryInterface(prefs);
if (branch) {
branch->GetIntPref(
"media.peerconnection.ice.stun_client_maximum_transmits",
&stun_client_maximum_transmits);
branch->GetIntPref(
"media.peerconnection.ice.trickle_grace_period",
&ice_trickle_grace_period);
}
}
#endif
NR_reg_set_uint4((char *)"stun.client.maximum_transmits",
stun_client_maximum_transmits);
NR_reg_set_uint4((char *)NR_ICE_REG_TRICKLE_GRACE_PERIOD,
ice_trickle_grace_period);
if (allow_loopback) {
NR_reg_set_char((char *)NR_STUN_REG_PREF_ALLOW_LOOPBACK_ADDRS, 1);

View File

@ -35,6 +35,10 @@ typedef MALLOC_USABLE_SIZE_CONST_PTR void * usable_ptr_t;
#endif
#ifdef MALLOC_DECL
# ifndef MALLOC_DECL_VOID
# define MALLOC_DECL_VOID(func, ...) MALLOC_DECL(func, void, __VA_ARGS__)
# endif
# if MALLOC_FUNCS & MALLOC_FUNCS_INIT
MALLOC_DECL(init, void, const malloc_table_t *)
# endif
@ -47,17 +51,19 @@ MALLOC_DECL(posix_memalign, int, void **, size_t, size_t)
MALLOC_DECL(aligned_alloc, void *, size_t, size_t)
MALLOC_DECL(calloc, void *, size_t, size_t)
MALLOC_DECL(realloc, void *, void *, size_t)
MALLOC_DECL(free, void, void *)
MALLOC_DECL_VOID(free, void *)
MALLOC_DECL(memalign, void *, size_t, size_t)
MALLOC_DECL(valloc, void *, size_t)
MALLOC_DECL(malloc_usable_size, size_t, usable_ptr_t)
MALLOC_DECL(malloc_good_size, size_t, size_t)
# endif
# if MALLOC_FUNCS & MALLOC_FUNCS_JEMALLOC
MALLOC_DECL(jemalloc_stats, void, jemalloc_stats_t *)
MALLOC_DECL(jemalloc_purge_freed_pages, void, void)
MALLOC_DECL(jemalloc_free_dirty_pages, void, void)
MALLOC_DECL_VOID(jemalloc_stats, jemalloc_stats_t *)
MALLOC_DECL_VOID(jemalloc_purge_freed_pages, void)
MALLOC_DECL_VOID(jemalloc_free_dirty_pages, void)
# endif
# undef MALLOC_DECL_VOID
#endif /* MALLOC_DECL */
#undef MALLOC_DECL

View File

@ -74,19 +74,6 @@
MOZ_BEGIN_EXTERN_C
#define MALLOC_DECL(name, return_type, ...) \
typedef return_type(name ## _impl_t)(__VA_ARGS__);
#include "malloc_decls.h"
#define MALLOC_DECL(name, return_type, ...) \
name ## _impl_t * name;
typedef struct {
#include "malloc_decls.h"
} malloc_table_t;
/* MOZ_NO_REPLACE_FUNC_DECL and MOZ_REPLACE_WEAK are only defined in
* replace_malloc.c. Normally including this header will add function
* definitions. */

View File

@ -48,15 +48,59 @@
struct ReplaceMallocBridge;
#ifdef __cplusplus
#include "mozilla/Types.h"
MOZ_BEGIN_EXTERN_C
#ifndef REPLACE_MALLOC_IMPL
/* Returns the replace-malloc bridge if there is one to be returned. */
extern "C" MFBT_API ReplaceMallocBridge* get_bridge();
MFBT_API ReplaceMallocBridge* get_bridge();
#endif
/* Table of malloc functions.
* e.g. void* (*malloc)(size_t), etc.
*/
#define MALLOC_DECL(name, return_type, ...) \
typedef return_type(name ## _impl_t)(__VA_ARGS__);
#include "malloc_decls.h"
#define MALLOC_DECL(name, return_type, ...) \
name ## _impl_t * name;
typedef struct {
#include "malloc_decls.h"
} malloc_table_t;
/* Table of malloc hook functions.
* Those functions are called with the arguments and results of malloc
* functions after they are called.
* e.g. void* (*malloc_hook)(void*, size_t), etc.
* They can either return the result they're given, or alter it before
* returning it.
* The hooks corresponding to functions, like free(void*), that return no
* value, don't take an extra argument.
* The table must at least contain a pointer for malloc_hook and free_hook
* functions. They will be used as fallback if no pointer is given for
* other allocation functions, like calloc_hook.
*/
#define MALLOC_DECL(name, return_type, ...) \
return_type (*name ## _hook)(return_type, __VA_ARGS__);
#define MALLOC_DECL_VOID(name, ...) \
void (*name ## _hook)(__VA_ARGS__);
typedef struct {
#include "malloc_decls.h"
/* Like free_hook, but called before realloc_hook. free_hook is called
* instead of not given. */
void (*realloc_hook_before)(void* aPtr);
} malloc_hook_table_t;
MOZ_END_EXTERN_C
#ifdef __cplusplus
namespace mozilla {
namespace dmd {
struct DMDFuncs;
@ -75,7 +119,7 @@ struct DebugFdRegistry
struct ReplaceMallocBridge
{
ReplaceMallocBridge() : mVersion(2) {}
ReplaceMallocBridge() : mVersion(3) {}
/* This method was added in version 1 of the bridge. */
virtual mozilla::dmd::DMDFuncs* GetDMDFuncs() { return nullptr; }
@ -86,6 +130,23 @@ struct ReplaceMallocBridge
* This method was added in version 2 of the bridge. */
virtual void InitDebugFd(mozilla::DebugFdRegistry&) {}
/* Register a list of malloc functions and hook functions to the
* replace-malloc library so that it can choose to dispatch to them
* when needed. The details of what is dispatched when is left to the
* replace-malloc library.
* Passing a nullptr for either table will unregister a previously
* registered table under the same name.
* Returns nullptr if registration failed.
* If registration succeeded, a table of "pure" malloc functions is
* returned. Those "pure" malloc functions won't call hooks.
* /!\ Do not rely on registration/unregistration to be instantaneous.
* Functions from a previously registered table may still be called for
* a brief time after RegisterHook returns.
* This method was added in version 3 of the bridge. */
virtual const malloc_table_t*
RegisterHook(const char* aName, const malloc_table_t* aTable,
const malloc_hook_table_t* aHookTable) { return nullptr; }
#ifndef REPLACE_MALLOC_IMPL
/* Returns the replace-malloc bridge if its version is at least the
* requested one. */
@ -124,6 +185,15 @@ struct ReplaceMalloc
singleton->InitDebugFd(aRegistry);
}
}
static const malloc_table_t*
RegisterHook(const char* aName, const malloc_table_t* aTable,
const malloc_hook_table_t* aHookTable)
{
auto singleton = ReplaceMallocBridge::Get(/* minimumVersion */ 3);
return singleton ? singleton->RegisterHook(aName, aTable, aHookTable)
: nullptr;
}
};
#endif

View File

@ -4,7 +4,10 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
DIRS += ['logalloc']
DIRS += [
'logalloc',
'replace',
]
# Build jemalloc3 as a replace-malloc lib when building with mozjemalloc
if not CONFIG['MOZ_JEMALLOC3']:

View File

@ -0,0 +1,255 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "replace_malloc.h"
#include <errno.h>
#include "mozilla/CheckedInt.h"
#include "mozilla/Atomics.h"
/* Replace-malloc library allowing different kinds of dispatch.
* The long term goal is to allow multiple replace-malloc libraries
* to be loaded and coexist properly.
* This is however a limited version to fulfil more immediate needs.
*/
static const malloc_table_t* gFuncs = nullptr;
/* This should normally be a mozilla::Atomic<const malloc_hook_table_t*>
* but MSVC 2013's atomic type doesn't like it. */
static mozilla::Atomic<malloc_hook_table_t*> gHookTable(nullptr);
class GenericReplaceMallocBridge : public ReplaceMallocBridge
{
virtual const malloc_table_t*
RegisterHook(const char* aName, const malloc_table_t* aTable,
const malloc_hook_table_t* aHookTable) override
{
// Can't register a hook before replace_init is called.
if (!gFuncs) {
return nullptr;
}
// Expect a name to be given.
if (!aName) {
return nullptr;
}
// Giving a malloc_table_t is not supported yet.
if (aTable) {
return nullptr;
}
if (aHookTable) {
// Expect at least a malloc and a free hook.
if (!aHookTable->malloc_hook || !aHookTable->free_hook) {
return nullptr;
}
gHookTable = const_cast<malloc_hook_table_t*>(aHookTable);
return gFuncs;
}
gHookTable = nullptr;
return nullptr;
}
};
void
replace_init(const malloc_table_t* aTable)
{
gFuncs = aTable;
}
ReplaceMallocBridge*
replace_get_bridge()
{
static GenericReplaceMallocBridge bridge;
return &bridge;
}
void*
replace_malloc(size_t aSize)
{
void* ptr = gFuncs->malloc(aSize);
const malloc_hook_table_t* hook_table = gHookTable;
if (hook_table) {
return hook_table->malloc_hook(ptr, aSize);
}
return ptr;
}
int
replace_posix_memalign(void** aPtr, size_t aAlignment, size_t aSize)
{
int ret = gFuncs->posix_memalign(aPtr, aAlignment, aSize);
const malloc_hook_table_t* hook_table = gHookTable;
if (hook_table) {
if (hook_table->posix_memalign_hook) {
return hook_table->posix_memalign_hook(ret, aPtr, aAlignment, aSize);
}
void* ptr = hook_table->malloc_hook(*aPtr, aSize);
if (!ptr && *aPtr) {
*aPtr = ptr;
ret = ENOMEM;
}
}
return ret;
}
void*
replace_aligned_alloc(size_t aAlignment, size_t aSize)
{
void* ptr = gFuncs->aligned_alloc(aAlignment, aSize);
const malloc_hook_table_t* hook_table = gHookTable;
if (hook_table) {
if (hook_table->aligned_alloc_hook) {
return hook_table->aligned_alloc_hook(ptr, aAlignment, aSize);
}
return hook_table->malloc_hook(ptr, aSize);
}
return ptr;
}
void*
replace_calloc(size_t aNum, size_t aSize)
{
void* ptr = gFuncs->calloc(aNum, aSize);
const malloc_hook_table_t* hook_table = gHookTable;
if (hook_table) {
if (hook_table->calloc_hook) {
return hook_table->calloc_hook(ptr, aNum, aSize);
}
mozilla::CheckedInt<size_t> size = mozilla::CheckedInt<size_t>(aNum) * aSize;
if (size.isValid()) {
return hook_table->malloc_hook(ptr, size.value());
}
/* If the multiplication above overflows, calloc will have failed, so ptr
* is null. But the hook might still be interested in knowing about the
* allocation attempt. The choice made is to indicate the overflow with
* the biggest value of a size_t, which is not that bad an indicator:
* there are only 5 prime factors to 2^32 - 1 and 7 prime factors to
* 2^64 - 1 and none of them is going to come directly out of sizeof().
* IOW, the likelyhood of aNum * aSize being exactly SIZE_MAX is low
* enough, and SIZE_MAX still conveys that the attempted allocation was
* too big anyways. */
return hook_table->malloc_hook(ptr, SIZE_MAX);
}
return ptr;
}
void*
replace_realloc(void* aPtr, size_t aSize)
{
const malloc_hook_table_t* hook_table = gHookTable;
if (hook_table) {
if (hook_table->realloc_hook_before) {
hook_table->realloc_hook_before(aPtr);
} else {
hook_table->free_hook(aPtr);
}
}
void* new_ptr = gFuncs->realloc(aPtr, aSize);
/* The hook table might have changed since before realloc was called,
* either because of unregistration or registration of a new table.
* We however go with consistency and use the same hook table as the
* one that was used before the call to realloc. */
if (hook_table) {
if (hook_table->realloc_hook) {
/* aPtr is likely invalid when reaching here, it is only given for
* tracking purposes, and should not be dereferenced. */
return hook_table->realloc_hook(new_ptr, aPtr, aSize);
}
return hook_table->malloc_hook(new_ptr, aSize);
}
return new_ptr;
}
void
replace_free(void* aPtr)
{
const malloc_hook_table_t* hook_table = gHookTable;
if (hook_table) {
hook_table->free_hook(aPtr);
}
gFuncs->free(aPtr);
}
void*
replace_memalign(size_t aAlignment, size_t aSize)
{
void* ptr = gFuncs->memalign(aAlignment, aSize);
const malloc_hook_table_t* hook_table = gHookTable;
if (hook_table) {
if (hook_table->memalign_hook) {
return hook_table->memalign_hook(ptr, aAlignment, aSize);
}
return hook_table->malloc_hook(ptr, aSize);
}
return ptr;
}
void*
replace_valloc(size_t aSize)
{
void* ptr = gFuncs->valloc(aSize);
const malloc_hook_table_t* hook_table = gHookTable;
if (hook_table) {
if (hook_table->valloc_hook) {
return hook_table->valloc_hook(ptr, aSize);
}
return hook_table->malloc_hook(ptr, aSize);
}
return ptr;
}
size_t
replace_malloc_usable_size(usable_ptr_t aPtr)
{
size_t ret = gFuncs->malloc_usable_size(aPtr);
const malloc_hook_table_t* hook_table = gHookTable;
if (hook_table && hook_table->malloc_usable_size_hook) {
return hook_table->malloc_usable_size_hook(ret, aPtr);
}
return ret;
}
size_t
replace_malloc_good_size(size_t aSize)
{
size_t ret = gFuncs->malloc_good_size(aSize);
const malloc_hook_table_t* hook_table = gHookTable;
if (hook_table && hook_table->malloc_good_size_hook) {
return hook_table->malloc_good_size_hook(ret, aSize);
}
return ret;
}
void
replace_jemalloc_stats(jemalloc_stats_t* aStats)
{
gFuncs->jemalloc_stats(aStats);
const malloc_hook_table_t* hook_table = gHookTable;
if (hook_table && hook_table->jemalloc_stats_hook) {
hook_table->jemalloc_stats_hook(aStats);
}
}
void
replace_jemalloc_purge_freed_pages(void)
{
gFuncs->jemalloc_purge_freed_pages();
const malloc_hook_table_t* hook_table = gHookTable;
if (hook_table && hook_table->jemalloc_purge_freed_pages_hook) {
hook_table->jemalloc_purge_freed_pages_hook();
}
}
void
replace_jemalloc_free_dirty_pages(void)
{
gFuncs->jemalloc_free_dirty_pages();
const malloc_hook_table_t* hook_table = gHookTable;
if (hook_table && hook_table->jemalloc_free_dirty_pages_hook) {
hook_table->jemalloc_free_dirty_pages_hook();
}
}

View File

@ -0,0 +1,13 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
SharedLibrary('replace_malloc')
SOURCES += [
'ReplaceMalloc.cpp',
]
DISABLE_STL_WRAPPING = True

View File

@ -523,8 +523,7 @@ Preferences::Init()
{
nsresult rv;
rv = PREF_Init();
NS_ENSURE_SUCCESS(rv, rv);
PREF_Init();
rv = pref_InitInitialObjects();
NS_ENSURE_SUCCESS(rv, rv);
@ -644,8 +643,7 @@ Preferences::ResetPrefs()
NotifyServiceObservers(NS_PREFSERVICE_RESET_TOPIC_ID);
PREF_CleanupPrefs();
nsresult rv = PREF_Init();
NS_ENSURE_SUCCESS(rv, rv);
PREF_Init();
return pref_InitInitialObjects();
}

View File

@ -375,7 +375,8 @@ pref("media.peerconnection.ice.loopback", false); // Set only for testing in off
pref("media.peerconnection.use_document_iceservers", true);
pref("media.peerconnection.identity.enabled", true);
pref("media.peerconnection.identity.timeout", 10000);
pref("media.peerconnection.ice.loopback", false); // Set only for testing in offline environments.
pref("media.peerconnection.ice.stun_client_maximum_transmits", 7);
pref("media.peerconnection.ice.trickle_grace_period", 5000);
// These values (aec, agc, and noice) are from media/webrtc/trunk/webrtc/common_types.h
// kXxxUnchanged = 0, kXxxDefault = 1, and higher values are specific to each
// setting (for Xxx = Ec, Agc, or Ns). Defaults are all set to kXxxDefault here.

View File

@ -147,7 +147,7 @@ static nsresult pref_HashPref(const char *key, PrefValue value, PrefType type, u
#define PREF_HASHTABLE_INITIAL_LENGTH 1024
nsresult PREF_Init()
void PREF_Init()
{
if (!gHashTable) {
gHashTable = new PLDHashTable(&pref_HashTableOps,
@ -157,7 +157,6 @@ nsresult PREF_Init()
PL_INIT_ARENA_POOL(&gPrefNameArena, "PrefNameArena",
PREFNAME_ARENA_SIZE);
}
return NS_OK;
}
/* Frees the callback list. */

View File

@ -42,7 +42,7 @@ struct PrefHashEntry : PLDHashEntryHdr
// the preference hashtable.
// </font>
*/
nsresult PREF_Init();
void PREF_Init();
/*
// Cleanup should be called at program exit to free the

View File

@ -130,10 +130,14 @@ function addCertFromFile(certdb, filename, trustString) {
function constructCertFromFile(filename) {
let certFile = do_get_file(filename, false);
let certDER = readFile(certFile);
let certBytes = readFile(certFile);
let certdb = Cc["@mozilla.org/security/x509certdb;1"]
.getService(Ci.nsIX509CertDB);
return certdb.constructX509(certDER, certDER.length);
.getService(Ci.nsIX509CertDB);
try {
return certdb.constructX509(certBytes, certBytes.length);
} catch (e) {}
// It might be PEM instead of DER.
return certdb.constructX509FromBase64(pemToBase64(certBytes));
}
function setCertTrust(cert, trustString) {

View File

@ -5,7 +5,10 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
DIRS += ['tlsserver']
TEST_DIRS += ['test_intermediate_basic_usage_constraints']
TEST_DIRS += [
'test_cert_keyUsage',
'test_intermediate_basic_usage_constraints',
]
if not CONFIG['MOZ_NO_SMART_CARDS']:
DIRS += ['pkcs11testmodule']

View File

@ -0,0 +1,61 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
do_get_profile(); // must be called before getting nsIX509CertDB
let certdb = Cc["@mozilla.org/security/x509certdb;1"]
.getService(Ci.nsIX509CertDB);
let caList = ["ca-no-keyUsage-extension", "ca-missing-keyCertSign",
"ca-all-usages"];
let eeList = ["ee-no-keyUsage-extension", "ee-keyCertSign-only",
"ee-keyEncipherment-only", "ee-keyCertSign-and-keyEncipherment"];
let caUsage = "SSL CA";
let allEEUsages = "Client,Server,Sign,Encrypt,Object Signer";
let serverEEUsages = "Server,Encrypt";
let expectedUsagesMap = {
"ca-no-keyUsage-extension": caUsage,
"ca-missing-keyCertSign": "",
"ca-all-usages": caUsage,
"ee-no-keyUsage-extension-ca-no-keyUsage-extension": allEEUsages,
"ee-no-keyUsage-extension-ca-missing-keyCertSign": "",
"ee-no-keyUsage-extension-ca-all-usages": allEEUsages,
"ee-keyCertSign-only-ca-no-keyUsage-extension": "",
"ee-keyCertSign-only-ca-missing-keyCertSign": "",
"ee-keyCertSign-only-ca-all-usages": "",
"ee-keyEncipherment-only-ca-no-keyUsage-extension": serverEEUsages,
"ee-keyEncipherment-only-ca-missing-keyCertSign": "",
"ee-keyEncipherment-only-ca-all-usages": serverEEUsages,
"ee-keyCertSign-and-keyEncipherment-ca-no-keyUsage-extension": serverEEUsages,
"ee-keyCertSign-and-keyEncipherment-ca-missing-keyCertSign": "",
"ee-keyCertSign-and-keyEncipherment-ca-all-usages": serverEEUsages,
};
function run_test() {
caList.forEach(function(ca) {
addCertFromFile(certdb, "test_cert_keyUsage/" + ca + ".pem",
"CTu,CTu,CTu");
let caCert = certdb.findCertByNickname(null, ca);
let usages = {};
caCert.getUsagesString(true, {}, usages); // true indicates local-only
equal(usages.value, expectedUsagesMap[ca],
"Actual and expected CA usages should match");
eeList.forEach(function(ee) {
let eeFullName = ee + "-" + ca;
let cert = constructCertFromFile(
"test_cert_keyUsage/" + eeFullName + ".pem");
cert.getUsagesString(true, {}, usages); // true indicates local-only
equal(usages.value, expectedUsagesMap[eeFullName],
"Actual and expected EE usages should match");
});
});
}

View File

@ -0,0 +1,4 @@
issuer:ca-all-usages
subject:ca-all-usages
extension:basicConstraints:cA,
extension:keyUsage:digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment,keyAgreement,keyCertSign,cRLSign

Some files were not shown because too many files have changed in this diff Show More