зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to b2g-inbound
This commit is contained in:
Коммит
73db77e9ab
|
@ -72,7 +72,7 @@ public:
|
|||
|
||||
virtual void OnReadMetadataCompleted() MOZ_FINAL MOZ_OVERRIDE;
|
||||
|
||||
virtual MediaDecoderOwner* GetOwner() MOZ_FINAL MOZ_OVERRIDE;
|
||||
virtual MediaDecoderOwner* GetOwner() MOZ_OVERRIDE;
|
||||
|
||||
virtual void NotifyWaitingForResourcesStatusChanged() MOZ_FINAL MOZ_OVERRIDE;
|
||||
|
||||
|
|
|
@ -258,7 +258,7 @@ MediaDecoderStateMachine::~MediaDecoderStateMachine()
|
|||
#endif
|
||||
}
|
||||
|
||||
bool MediaDecoderStateMachine::HasFutureAudio() const {
|
||||
bool MediaDecoderStateMachine::HasFutureAudio() {
|
||||
AssertCurrentThreadInMonitor();
|
||||
NS_ASSERTION(HasAudio(), "Should only call HasFutureAudio() when we have audio");
|
||||
// We've got audio ready to play if:
|
||||
|
@ -267,20 +267,20 @@ bool MediaDecoderStateMachine::HasFutureAudio() const {
|
|||
// we've completely decoded all audio (but not finished playing it yet
|
||||
// as per 1).
|
||||
return !mAudioCompleted &&
|
||||
(AudioDecodedUsecs() > LOW_AUDIO_USECS * mPlaybackRate || mReader->AudioQueue().IsFinished());
|
||||
(AudioDecodedUsecs() > LOW_AUDIO_USECS * mPlaybackRate || AudioQueue().IsFinished());
|
||||
}
|
||||
|
||||
bool MediaDecoderStateMachine::HaveNextFrameData() const {
|
||||
bool MediaDecoderStateMachine::HaveNextFrameData() {
|
||||
AssertCurrentThreadInMonitor();
|
||||
return (!HasAudio() || HasFutureAudio()) &&
|
||||
(!HasVideo() || mReader->VideoQueue().GetSize() > 0);
|
||||
(!HasVideo() || VideoQueue().GetSize() > 0);
|
||||
}
|
||||
|
||||
int64_t MediaDecoderStateMachine::GetDecodedAudioDuration() {
|
||||
NS_ASSERTION(OnDecodeThread() || OnStateMachineThread(),
|
||||
"Should be on decode thread or state machine thread");
|
||||
AssertCurrentThreadInMonitor();
|
||||
int64_t audioDecoded = mReader->AudioQueue().Duration();
|
||||
int64_t audioDecoded = AudioQueue().Duration();
|
||||
if (mAudioEndTime != -1) {
|
||||
audioDecoded += mAudioEndTime - GetMediaTime();
|
||||
}
|
||||
|
@ -381,8 +381,8 @@ void MediaDecoderStateMachine::SendStreamData()
|
|||
|
||||
int64_t minLastAudioPacketTime = INT64_MAX;
|
||||
bool finished =
|
||||
(!mInfo.HasAudio() || mReader->AudioQueue().IsFinished()) &&
|
||||
(!mInfo.HasVideo() || mReader->VideoQueue().IsFinished());
|
||||
(!mInfo.HasAudio() || AudioQueue().IsFinished()) &&
|
||||
(!mInfo.HasVideo() || VideoQueue().IsFinished());
|
||||
if (mDecoder->IsSameOriginMedia()) {
|
||||
SourceMediaStream* mediaStream = stream->mStream;
|
||||
StreamTime endPosition = 0;
|
||||
|
@ -407,7 +407,7 @@ void MediaDecoderStateMachine::SendStreamData()
|
|||
nsAutoTArray<AudioData*,10> audio;
|
||||
// It's OK to hold references to the AudioData because while audio
|
||||
// is captured, only the decoder thread pops from the queue (see below).
|
||||
mReader->AudioQueue().GetElementsAfter(stream->mLastAudioPacketTime, &audio);
|
||||
AudioQueue().GetElementsAfter(stream->mLastAudioPacketTime, &audio);
|
||||
AudioSegment output;
|
||||
for (uint32_t i = 0; i < audio.Length(); ++i) {
|
||||
SendStreamAudio(audio[i], stream, &output);
|
||||
|
@ -415,7 +415,7 @@ void MediaDecoderStateMachine::SendStreamData()
|
|||
if (output.GetDuration() > 0) {
|
||||
mediaStream->AppendToTrack(TRACK_AUDIO, &output);
|
||||
}
|
||||
if (mReader->AudioQueue().IsFinished() && !stream->mHaveSentFinishAudio) {
|
||||
if (AudioQueue().IsFinished() && !stream->mHaveSentFinishAudio) {
|
||||
mediaStream->EndTrack(TRACK_AUDIO);
|
||||
stream->mHaveSentFinishAudio = true;
|
||||
}
|
||||
|
@ -428,7 +428,7 @@ void MediaDecoderStateMachine::SendStreamData()
|
|||
nsAutoTArray<VideoData*,10> video;
|
||||
// It's OK to hold references to the VideoData only the decoder thread
|
||||
// pops from the queue.
|
||||
mReader->VideoQueue().GetElementsAfter(stream->mNextVideoTime, &video);
|
||||
VideoQueue().GetElementsAfter(stream->mNextVideoTime, &video);
|
||||
VideoSegment output;
|
||||
for (uint32_t i = 0; i < video.Length(); ++i) {
|
||||
VideoData* v = video[i];
|
||||
|
@ -459,7 +459,7 @@ void MediaDecoderStateMachine::SendStreamData()
|
|||
if (output.GetDuration() > 0) {
|
||||
mediaStream->AppendToTrack(TRACK_VIDEO, &output);
|
||||
}
|
||||
if (mReader->VideoQueue().IsFinished() && !stream->mHaveSentFinishVideo) {
|
||||
if (VideoQueue().IsFinished() && !stream->mHaveSentFinishVideo) {
|
||||
mediaStream->EndTrack(TRACK_VIDEO);
|
||||
stream->mHaveSentFinishVideo = true;
|
||||
}
|
||||
|
@ -480,7 +480,7 @@ void MediaDecoderStateMachine::SendStreamData()
|
|||
if (mAudioCaptured) {
|
||||
// Discard audio packets that are no longer needed.
|
||||
while (true) {
|
||||
const AudioData* a = mReader->AudioQueue().PeekFront();
|
||||
const AudioData* a = AudioQueue().PeekFront();
|
||||
// Packet times are not 100% reliable so this may discard packets that
|
||||
// actually contain data for mCurrentFrameTime. This means if someone might
|
||||
// create a new output stream and we actually don't have the audio for the
|
||||
|
@ -490,7 +490,7 @@ void MediaDecoderStateMachine::SendStreamData()
|
|||
if (!a || a->GetEndTime() >= minLastAudioPacketTime)
|
||||
break;
|
||||
mAudioEndTime = std::max(mAudioEndTime, a->GetEndTime());
|
||||
delete mReader->AudioQueue().PopFront();
|
||||
delete AudioQueue().PopFront();
|
||||
}
|
||||
|
||||
if (finished) {
|
||||
|
@ -515,7 +515,7 @@ bool MediaDecoderStateMachine::HaveEnoughDecodedAudio(int64_t aAmpleAudioUSecs)
|
|||
{
|
||||
AssertCurrentThreadInMonitor();
|
||||
|
||||
if (mReader->AudioQueue().GetSize() == 0 ||
|
||||
if (AudioQueue().GetSize() == 0 ||
|
||||
GetDecodedAudioDuration() < aAmpleAudioUSecs) {
|
||||
return false;
|
||||
}
|
||||
|
@ -539,7 +539,7 @@ bool MediaDecoderStateMachine::HaveEnoughDecodedVideo()
|
|||
{
|
||||
AssertCurrentThreadInMonitor();
|
||||
|
||||
if (static_cast<uint32_t>(mReader->VideoQueue().GetSize()) < mAmpleVideoFrames * mPlaybackRate) {
|
||||
if (static_cast<uint32_t>(VideoQueue().GetSize()) < mAmpleVideoFrames * mPlaybackRate) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -582,7 +582,7 @@ MediaDecoderStateMachine::DecodeVideo()
|
|||
// only just started up the decode loop, so wait until we've decoded
|
||||
// some frames before enabling the keyframe skip logic on video.
|
||||
if (mIsVideoPrerolling &&
|
||||
(static_cast<uint32_t>(mReader->VideoQueue().GetSize())
|
||||
(static_cast<uint32_t>(VideoQueue().GetSize())
|
||||
>= mVideoPrerollFrames * mPlaybackRate))
|
||||
{
|
||||
mIsVideoPrerolling = false;
|
||||
|
@ -603,7 +603,7 @@ MediaDecoderStateMachine::DecodeVideo()
|
|||
// don't skip frame when |clock time| <= |mVideoFrameEndTime| for
|
||||
// we are still in the safe range without underrunning video frames
|
||||
GetClock() > mVideoFrameEndTime &&
|
||||
(static_cast<uint32_t>(mReader->VideoQueue().GetSize())
|
||||
(static_cast<uint32_t>(VideoQueue().GetSize())
|
||||
< LOW_VIDEO_FRAMES * mPlaybackRate))) &&
|
||||
!HasLowUndecodedData())
|
||||
{
|
||||
|
@ -624,7 +624,7 @@ MediaDecoderStateMachine::DecodeVideo()
|
|||
}
|
||||
if (!mIsVideoDecoding) {
|
||||
// Playback ended for this stream, close the sample queue.
|
||||
mReader->VideoQueue().Finish();
|
||||
VideoQueue().Finish();
|
||||
CheckIfDecodeComplete();
|
||||
}
|
||||
|
||||
|
@ -686,7 +686,7 @@ MediaDecoderStateMachine::DecodeAudio()
|
|||
}
|
||||
if (!mIsAudioDecoding) {
|
||||
// Playback ended for this stream, close the sample queue.
|
||||
mReader->AudioQueue().Finish();
|
||||
AudioQueue().Finish();
|
||||
CheckIfDecodeComplete();
|
||||
}
|
||||
|
||||
|
@ -715,8 +715,8 @@ MediaDecoderStateMachine::CheckIfDecodeComplete()
|
|||
// since we don't want to abort the shutdown or seek processes.
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(!mReader->AudioQueue().IsFinished() || !mIsAudioDecoding);
|
||||
MOZ_ASSERT(!mReader->VideoQueue().IsFinished() || !mIsVideoDecoding);
|
||||
MOZ_ASSERT(!AudioQueue().IsFinished() || !mIsAudioDecoding);
|
||||
MOZ_ASSERT(!VideoQueue().IsFinished() || !mIsVideoDecoding);
|
||||
if (!mIsVideoDecoding && !mIsAudioDecoding) {
|
||||
// We've finished decoding all active streams,
|
||||
// so move to COMPLETED state.
|
||||
|
@ -822,8 +822,8 @@ void MediaDecoderStateMachine::AudioLoop()
|
|||
!mStopAudioThread &&
|
||||
(!IsPlaying() ||
|
||||
mState == DECODER_STATE_BUFFERING ||
|
||||
(mReader->AudioQueue().GetSize() == 0 &&
|
||||
!mReader->AudioQueue().AtEndOfStream())))
|
||||
(AudioQueue().GetSize() == 0 &&
|
||||
!AudioQueue().AtEndOfStream())))
|
||||
{
|
||||
if (!IsPlaying() && !mAudioStream->IsPaused()) {
|
||||
mAudioStream->Pause();
|
||||
|
@ -835,7 +835,7 @@ void MediaDecoderStateMachine::AudioLoop()
|
|||
// Also break out if audio is being captured.
|
||||
if (mState == DECODER_STATE_SHUTDOWN ||
|
||||
mStopAudioThread ||
|
||||
mReader->AudioQueue().AtEndOfStream())
|
||||
AudioQueue().AtEndOfStream())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
@ -873,11 +873,11 @@ void MediaDecoderStateMachine::AudioLoop()
|
|||
NS_WARNING("Setting the pitch preservation failed in AudioLoop.");
|
||||
}
|
||||
}
|
||||
NS_ASSERTION(mReader->AudioQueue().GetSize() > 0,
|
||||
NS_ASSERTION(AudioQueue().GetSize() > 0,
|
||||
"Should have data to play");
|
||||
// See if there's a gap in the audio. If there is, push silence into the
|
||||
// audio hardware, so we can play across the gap.
|
||||
const AudioData* s = mReader->AudioQueue().PeekFront();
|
||||
const AudioData* s = AudioQueue().PeekFront();
|
||||
|
||||
// Calculate the number of frames that have been pushed onto the audio
|
||||
// hardware.
|
||||
|
@ -918,7 +918,7 @@ void MediaDecoderStateMachine::AudioLoop()
|
|||
}
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
if (mReader->AudioQueue().AtEndOfStream() &&
|
||||
if (AudioQueue().AtEndOfStream() &&
|
||||
mState != DECODER_STATE_SHUTDOWN &&
|
||||
!mStopAudioThread)
|
||||
{
|
||||
|
@ -988,7 +988,7 @@ uint32_t MediaDecoderStateMachine::PlayFromAudioQueue(uint64_t aFrameOffset,
|
|||
{
|
||||
NS_ASSERTION(OnAudioThread(), "Only call on audio thread.");
|
||||
NS_ASSERTION(!mAudioStream->IsPaused(), "Don't play when paused");
|
||||
nsAutoPtr<AudioData> audio(mReader->AudioQueue().PopFront());
|
||||
nsAutoPtr<AudioData> audio(AudioQueue().PopFront());
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
NS_WARN_IF_FALSE(IsPlaying(), "Should be playing");
|
||||
|
@ -1325,8 +1325,8 @@ void MediaDecoderStateMachine::StartDecoding()
|
|||
|
||||
// Reset our "stream finished decoding" flags, so we try to decode all
|
||||
// streams that we have when we start decoding.
|
||||
mIsVideoDecoding = HasVideo() && !mReader->VideoQueue().IsFinished();
|
||||
mIsAudioDecoding = HasAudio() && !mReader->AudioQueue().IsFinished();
|
||||
mIsVideoDecoding = HasVideo() && !VideoQueue().IsFinished();
|
||||
mIsAudioDecoding = HasAudio() && !AudioQueue().IsFinished();
|
||||
|
||||
CheckIfDecodeComplete();
|
||||
if (mState == DECODER_STATE_COMPLETED) {
|
||||
|
@ -1519,7 +1519,7 @@ MediaDecoderStateMachine::SetReaderIdle()
|
|||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
DECODER_LOG(PR_LOG_DEBUG, "SetReaderIdle() audioQueue=%lld videoQueue=%lld",
|
||||
GetDecodedAudioDuration(),
|
||||
mReader->VideoQueue().Duration());
|
||||
VideoQueue().Duration());
|
||||
}
|
||||
#endif
|
||||
MOZ_ASSERT(OnDecodeThread());
|
||||
|
@ -1715,7 +1715,7 @@ MediaDecoderStateMachine::StartAudioThread()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
int64_t MediaDecoderStateMachine::AudioDecodedUsecs() const
|
||||
int64_t MediaDecoderStateMachine::AudioDecodedUsecs()
|
||||
{
|
||||
NS_ASSERTION(HasAudio(),
|
||||
"Should only call AudioDecodedUsecs() when we have audio");
|
||||
|
@ -1723,10 +1723,10 @@ int64_t MediaDecoderStateMachine::AudioDecodedUsecs() const
|
|||
// already decoded and pushed to the hardware, plus the amount of audio
|
||||
// data waiting to be pushed to the hardware.
|
||||
int64_t pushed = (mAudioEndTime != -1) ? (mAudioEndTime - GetMediaTime()) : 0;
|
||||
return pushed + mReader->AudioQueue().Duration();
|
||||
return pushed + AudioQueue().Duration();
|
||||
}
|
||||
|
||||
bool MediaDecoderStateMachine::HasLowDecodedData(int64_t aAudioUsecs) const
|
||||
bool MediaDecoderStateMachine::HasLowDecodedData(int64_t aAudioUsecs)
|
||||
{
|
||||
AssertCurrentThreadInMonitor();
|
||||
// We consider ourselves low on decoded data if we're low on audio,
|
||||
|
@ -1734,20 +1734,20 @@ bool MediaDecoderStateMachine::HasLowDecodedData(int64_t aAudioUsecs) const
|
|||
// if we're low on video frames, provided
|
||||
// we've not decoded to the end of the video stream.
|
||||
return ((HasAudio() &&
|
||||
!mReader->AudioQueue().IsFinished() &&
|
||||
!AudioQueue().IsFinished() &&
|
||||
AudioDecodedUsecs() < aAudioUsecs)
|
||||
||
|
||||
(HasVideo() &&
|
||||
!mReader->VideoQueue().IsFinished() &&
|
||||
static_cast<uint32_t>(mReader->VideoQueue().GetSize()) < LOW_VIDEO_FRAMES));
|
||||
!VideoQueue().IsFinished() &&
|
||||
static_cast<uint32_t>(VideoQueue().GetSize()) < LOW_VIDEO_FRAMES));
|
||||
}
|
||||
|
||||
bool MediaDecoderStateMachine::HasLowUndecodedData() const
|
||||
bool MediaDecoderStateMachine::HasLowUndecodedData()
|
||||
{
|
||||
return HasLowUndecodedData(mLowDataThresholdUsecs);
|
||||
}
|
||||
|
||||
bool MediaDecoderStateMachine::HasLowUndecodedData(double aUsecs) const
|
||||
bool MediaDecoderStateMachine::HasLowUndecodedData(double aUsecs)
|
||||
{
|
||||
AssertCurrentThreadInMonitor();
|
||||
NS_ASSERTION(mState > DECODER_STATE_DECODING_METADATA,
|
||||
|
@ -1886,12 +1886,12 @@ nsresult MediaDecoderStateMachine::DecodeMetadata()
|
|||
if (HasAudio()) {
|
||||
RefPtr<nsIRunnable> decodeTask(
|
||||
NS_NewRunnableMethod(this, &MediaDecoderStateMachine::DispatchAudioDecodeTaskIfNeeded));
|
||||
mReader->AudioQueue().AddPopListener(decodeTask, mDecodeTaskQueue);
|
||||
AudioQueue().AddPopListener(decodeTask, mDecodeTaskQueue);
|
||||
}
|
||||
if (HasVideo()) {
|
||||
RefPtr<nsIRunnable> decodeTask(
|
||||
NS_NewRunnableMethod(this, &MediaDecoderStateMachine::DispatchVideoDecodeTaskIfNeeded));
|
||||
mReader->VideoQueue().AddPopListener(decodeTask, mDecodeTaskQueue);
|
||||
VideoQueue().AddPopListener(decodeTask, mDecodeTaskQueue);
|
||||
}
|
||||
|
||||
if (mState == DECODER_STATE_DECODING_METADATA) {
|
||||
|
@ -1989,7 +1989,7 @@ void MediaDecoderStateMachine::DecodeSeek()
|
|||
if (seekTime == mEndTime) {
|
||||
newCurrentTime = mAudioStartTime = seekTime;
|
||||
} else if (HasAudio()) {
|
||||
AudioData* audio = mReader->AudioQueue().PeekFront();
|
||||
AudioData* audio = AudioQueue().PeekFront();
|
||||
newCurrentTime = mAudioStartTime = audio ? audio->mTime : seekTime;
|
||||
} else {
|
||||
newCurrentTime = video ? video->mTime : seekTime;
|
||||
|
@ -2128,8 +2128,8 @@ nsresult MediaDecoderStateMachine::RunStateMachine()
|
|||
// The reader's listeners hold references to the state machine,
|
||||
// creating a cycle which keeps the state machine and its shared
|
||||
// thread pools alive. So break it here.
|
||||
mReader->AudioQueue().ClearListeners();
|
||||
mReader->VideoQueue().ClearListeners();
|
||||
AudioQueue().ClearListeners();
|
||||
VideoQueue().ClearListeners();
|
||||
|
||||
{
|
||||
ReentrantMonitorAutoExit exitMon(mDecoder->GetReentrantMonitor());
|
||||
|
@ -2258,7 +2258,7 @@ nsresult MediaDecoderStateMachine::RunStateMachine()
|
|||
// Play the remaining media. We want to run AdvanceFrame() at least
|
||||
// once to ensure the current playback position is advanced to the
|
||||
// end of the media, and so that we update the readyState.
|
||||
if (mReader->VideoQueue().GetSize() > 0 ||
|
||||
if (VideoQueue().GetSize() > 0 ||
|
||||
(HasAudio() && !mAudioCompleted) ||
|
||||
(mDecoder->GetDecodedStream() && !mDecoder->GetDecodedStream()->IsFinished()))
|
||||
{
|
||||
|
@ -2424,8 +2424,8 @@ void MediaDecoderStateMachine::AdvanceFrame()
|
|||
#ifdef PR_LOGGING
|
||||
int32_t droppedFrames = 0;
|
||||
#endif
|
||||
if (mReader->VideoQueue().GetSize() > 0) {
|
||||
VideoData* frame = mReader->VideoQueue().PeekFront();
|
||||
if (VideoQueue().GetSize() > 0) {
|
||||
VideoData* frame = VideoQueue().PeekFront();
|
||||
while (mRealTime || clock_time >= frame->mTime) {
|
||||
mVideoFrameEndTime = frame->GetEndTime();
|
||||
currentFrame = frame;
|
||||
|
@ -2435,14 +2435,14 @@ void MediaDecoderStateMachine::AdvanceFrame()
|
|||
VERBOSE_LOG("discarding video frame %lld (%d so far)", frame->mTime, droppedFrames-1);
|
||||
}
|
||||
#endif
|
||||
mReader->VideoQueue().PopFront();
|
||||
VideoQueue().PopFront();
|
||||
// Notify the decode thread that the video queue's buffers may have
|
||||
// free'd up space for more frames.
|
||||
mDecoder->GetReentrantMonitor().NotifyAll();
|
||||
mDecoder->UpdatePlaybackOffset(frame->mOffset);
|
||||
if (mReader->VideoQueue().GetSize() == 0)
|
||||
if (VideoQueue().GetSize() == 0)
|
||||
break;
|
||||
frame = mReader->VideoQueue().PeekFront();
|
||||
frame = VideoQueue().PeekFront();
|
||||
}
|
||||
// Current frame has already been presented, wait until it's time to
|
||||
// present the next frame.
|
||||
|
@ -2463,7 +2463,7 @@ void MediaDecoderStateMachine::AdvanceFrame()
|
|||
!resource->IsSuspended()) {
|
||||
if (JustExitedQuickBuffering() || HasLowUndecodedData()) {
|
||||
if (currentFrame) {
|
||||
mReader->VideoQueue().PushFront(currentFrame.forget());
|
||||
VideoQueue().PushFront(currentFrame.forget());
|
||||
}
|
||||
StartBuffering();
|
||||
// Don't go straight back to the state machine loop since that might
|
||||
|
|
|
@ -241,7 +241,7 @@ public:
|
|||
}
|
||||
|
||||
// Should be called by main thread.
|
||||
bool HaveNextFrameData() const;
|
||||
bool HaveNextFrameData();
|
||||
|
||||
// Must be called with the decode monitor held.
|
||||
bool IsBuffering() const {
|
||||
|
@ -397,6 +397,9 @@ protected:
|
|||
};
|
||||
WakeDecoderRunnable* GetWakeDecoderRunnable();
|
||||
|
||||
MediaQueue<AudioData>& AudioQueue() { return mReader->AudioQueue(); }
|
||||
MediaQueue<VideoData>& VideoQueue() { return mReader->VideoQueue(); }
|
||||
|
||||
// True if our buffers of decoded audio are not full, and we should
|
||||
// decode more.
|
||||
bool NeedToDecodeAudio();
|
||||
|
@ -413,24 +416,24 @@ protected:
|
|||
|
||||
// Returns true if we've got less than aAudioUsecs microseconds of decoded
|
||||
// and playable data. The decoder monitor must be held.
|
||||
bool HasLowDecodedData(int64_t aAudioUsecs) const;
|
||||
bool HasLowDecodedData(int64_t aAudioUsecs);
|
||||
|
||||
// Returns true if we're running low on data which is not yet decoded.
|
||||
// The decoder monitor must be held.
|
||||
bool HasLowUndecodedData() const;
|
||||
bool HasLowUndecodedData();
|
||||
|
||||
// Returns true if we have less than aUsecs of undecoded data available.
|
||||
bool HasLowUndecodedData(double aUsecs) const;
|
||||
bool HasLowUndecodedData(double aUsecs);
|
||||
|
||||
// Returns the number of unplayed usecs of audio we've got decoded and/or
|
||||
// pushed to the hardware waiting to play. This is how much audio we can
|
||||
// play without having to run the audio decoder. The decoder monitor
|
||||
// must be held.
|
||||
int64_t AudioDecodedUsecs() const;
|
||||
int64_t AudioDecodedUsecs();
|
||||
|
||||
// Returns true when there's decoded audio waiting to play.
|
||||
// The decoder monitor must be held.
|
||||
bool HasFutureAudio() const;
|
||||
bool HasFutureAudio();
|
||||
|
||||
// Returns true if we recently exited "quick buffering" mode.
|
||||
bool JustExitedQuickBuffering();
|
||||
|
|
|
@ -480,6 +480,8 @@ MediaSourceReader::ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags)
|
|||
if (maxDuration != -1) {
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
mDecoder->SetMediaDuration(maxDuration);
|
||||
ErrorResult dummy;
|
||||
mMediaSource->SetDuration(maxDuration, dummy);
|
||||
}
|
||||
|
||||
*aInfo = mInfo;
|
||||
|
|
|
@ -96,6 +96,12 @@ SubBufferDecoder::GetImageContainer()
|
|||
return mParentDecoder->GetImageContainer();
|
||||
}
|
||||
|
||||
MediaDecoderOwner*
|
||||
SubBufferDecoder::GetOwner()
|
||||
{
|
||||
return mParentDecoder->GetOwner();
|
||||
}
|
||||
|
||||
int64_t
|
||||
SubBufferDecoder::ConvertToByteOffset(double aTime)
|
||||
{
|
||||
|
@ -493,10 +499,18 @@ SourceBuffer::Evict(double aStart, double aEnd)
|
|||
bool
|
||||
SourceBuffer::ContainsTime(double aTime)
|
||||
{
|
||||
double start = 0.0;
|
||||
double end = 0.0;
|
||||
GetBufferedStartEndTime(&start, &end);
|
||||
return aTime >= start && aTime <= end;
|
||||
ErrorResult dummy;
|
||||
nsRefPtr<TimeRanges> ranges = GetBuffered(dummy);
|
||||
if (!ranges || ranges->Length() == 0) {
|
||||
return false;
|
||||
}
|
||||
for (uint32_t i = 0; i < ranges->Length(); ++i) {
|
||||
if (aTime >= ranges->Start(i, dummy) &&
|
||||
aTime <= ranges->End(i, dummy)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(SourceBuffer, DOMEventTargetHelper,
|
||||
|
|
|
@ -105,7 +105,7 @@ SourceBufferResource::Seek(int32_t aWhence, int64_t aOffset)
|
|||
break;
|
||||
}
|
||||
|
||||
if (newOffset < 0 || newOffset > GetLength()) {
|
||||
if (newOffset < 0 || uint64_t(newOffset) < mInputBuffer.GetOffset() || newOffset > GetLength()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
|
|
@ -120,6 +120,7 @@ private:
|
|||
// no such resource exists, returns GetSize() and aOffset is
|
||||
// untouched.
|
||||
inline uint32_t GetAtOffset(uint64_t aOffset, uint32_t *aResourceOffset) {
|
||||
MOZ_ASSERT(aOffset >= mOffset);
|
||||
uint64_t offset = mOffset;
|
||||
for (uint32_t i = 0; i < GetSize(); ++i) {
|
||||
ResourceItem* item = ResourceAt(i);
|
||||
|
|
|
@ -44,6 +44,7 @@ public:
|
|||
virtual void SetMediaSeekable(bool aMediaSeekable) MOZ_OVERRIDE;
|
||||
virtual void SetTransportSeekable(bool aTransportSeekable) MOZ_OVERRIDE;
|
||||
virtual layers::ImageContainer* GetImageContainer() MOZ_OVERRIDE;
|
||||
virtual MediaDecoderOwner* GetOwner() MOZ_OVERRIDE;
|
||||
|
||||
void NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset)
|
||||
{
|
||||
|
|
|
@ -85,20 +85,13 @@ AudioChannelAgent::InitInternal(nsIDOMWindow* aWindow, int32_t aChannelType,
|
|||
|
||||
// We syncd the enum of channel type between nsIAudioChannelAgent.idl and
|
||||
// AudioChannelBinding.h the same.
|
||||
MOZ_ASSERT(static_cast<AudioChannel>(AUDIO_AGENT_CHANNEL_NORMAL) ==
|
||||
AudioChannel::Normal &&
|
||||
static_cast<AudioChannel>(AUDIO_AGENT_CHANNEL_CONTENT) ==
|
||||
AudioChannel::Content &&
|
||||
static_cast<AudioChannel>(AUDIO_AGENT_CHANNEL_NOTIFICATION) ==
|
||||
AudioChannel::Notification &&
|
||||
static_cast<AudioChannel>(AUDIO_AGENT_CHANNEL_ALARM) ==
|
||||
AudioChannel::Alarm &&
|
||||
static_cast<AudioChannel>(AUDIO_AGENT_CHANNEL_TELEPHONY) ==
|
||||
AudioChannel::Telephony &&
|
||||
static_cast<AudioChannel>(AUDIO_AGENT_CHANNEL_RINGER) ==
|
||||
AudioChannel::Ringer &&
|
||||
static_cast<AudioChannel>(AUDIO_AGENT_CHANNEL_PUBLICNOTIFICATION) ==
|
||||
AudioChannel::Publicnotification,
|
||||
MOZ_ASSERT(int(AUDIO_AGENT_CHANNEL_NORMAL) == int(AudioChannel::Normal) &&
|
||||
int(AUDIO_AGENT_CHANNEL_CONTENT) == int(AudioChannel::Content) &&
|
||||
int(AUDIO_AGENT_CHANNEL_NOTIFICATION) == int(AudioChannel::Notification) &&
|
||||
int(AUDIO_AGENT_CHANNEL_ALARM) == int(AudioChannel::Alarm) &&
|
||||
int(AUDIO_AGENT_CHANNEL_TELEPHONY) == int(AudioChannel::Telephony) &&
|
||||
int(AUDIO_AGENT_CHANNEL_RINGER) == int(AudioChannel::Ringer) &&
|
||||
int(AUDIO_AGENT_CHANNEL_PUBLICNOTIFICATION) == int(AudioChannel::Publicnotification),
|
||||
"Enum of channel on nsIAudioChannelAgent.idl should be the same with AudioChannelBinding.h");
|
||||
|
||||
if (mAudioChannelType != AUDIO_AGENT_CHANNEL_ERROR ||
|
||||
|
|
|
@ -2872,6 +2872,9 @@ EventStateManager::PostHandleEvent(nsPresContext* aPresContext,
|
|||
if (pointerEvent->inputSource == nsIDOMMouseEvent::MOZ_SOURCE_TOUCH) {
|
||||
mPointersEnterLeaveHelper.Remove(pointerEvent->pointerId);
|
||||
}
|
||||
if (pointerEvent->inputSource != nsIDOMMouseEvent::MOZ_SOURCE_MOUSE) {
|
||||
GenerateMouseEnterExit(pointerEvent);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NS_MOUSE_BUTTON_UP:
|
||||
|
@ -3928,6 +3931,25 @@ EventStateManager::GenerateMouseEnterExit(WidgetMouseEvent* aMouseEvent)
|
|||
}
|
||||
}
|
||||
break;
|
||||
case NS_POINTER_UP:
|
||||
{
|
||||
// Get the target content target (mousemove target == mouseover target)
|
||||
nsCOMPtr<nsIContent> targetElement = GetEventTargetContent(aMouseEvent);
|
||||
if (!targetElement) {
|
||||
// We're always over the document root, even if we're only
|
||||
// over dead space in a page (whose frame is not associated with
|
||||
// any content) or in print preview dead space
|
||||
targetElement = mDocument->GetRootElement();
|
||||
}
|
||||
if (targetElement) {
|
||||
OverOutElementsWrapper* helper = GetWrapperByEventID(aMouseEvent);
|
||||
if (helper) {
|
||||
helper->mLastOverElement = targetElement;
|
||||
}
|
||||
NotifyMouseOut(aMouseEvent, nullptr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NS_POINTER_LEAVE:
|
||||
case NS_POINTER_CANCEL:
|
||||
case NS_MOUSE_EXIT:
|
||||
|
|
|
@ -9207,437 +9207,449 @@
|
|||
< cookie/M
|
||||
---
|
||||
> cookie/SM
|
||||
18467a24277
|
||||
18375a24185,24186
|
||||
> corrigibility/IM
|
||||
> corrigible/I
|
||||
18389a24201
|
||||
> corruptibly/I
|
||||
18467a24280
|
||||
> could've
|
||||
18999a24810
|
||||
18999a24813
|
||||
> cryptologist/MS
|
||||
19000a24812
|
||||
19000a24815
|
||||
> cryptosystem/S
|
||||
19035a24848
|
||||
19035a24851
|
||||
> cul-de-sac
|
||||
19246c25059
|
||||
19246c25062
|
||||
< cysteine
|
||||
---
|
||||
> cysteine/M
|
||||
19935a25749
|
||||
19935a25752
|
||||
> dequeue/DSG
|
||||
20196,20197c26010,26011
|
||||
20196,20197c26013,26014
|
||||
< dialog/SM
|
||||
< dialogue/SM
|
||||
---
|
||||
> dialog/SMGD
|
||||
> dialogue/SMRGD
|
||||
20220a26035
|
||||
20220a26038
|
||||
> diatomaceous
|
||||
20481a26297
|
||||
20481a26300
|
||||
> disclose/DSG
|
||||
20830c26646
|
||||
20830c26649
|
||||
< dogie/M
|
||||
---
|
||||
> dogie/SM
|
||||
20895a26712
|
||||
20895a26715
|
||||
> donator/MS
|
||||
21820a27638
|
||||
21820a27641
|
||||
> elicitor/MS
|
||||
22071a27890
|
||||
22071a27893
|
||||
> encyclopaedia
|
||||
22196a28016
|
||||
22196a28019
|
||||
> enqueue/DSG
|
||||
22556a28377
|
||||
22556a28380
|
||||
> estoppel
|
||||
22638c28459
|
||||
22638c28462
|
||||
< euthanize
|
||||
---
|
||||
> euthanize/DSG
|
||||
22719a28541
|
||||
22719a28544
|
||||
> exabyte/MS
|
||||
22947a28770
|
||||
22947a28773
|
||||
> experimentalism
|
||||
23207,23208d29029
|
||||
23207,23208d29032
|
||||
< faecal
|
||||
< faeces/M
|
||||
23215c29036
|
||||
23215c29039
|
||||
< faggoting's
|
||||
---
|
||||
> faggot/SMG
|
||||
23701a29523
|
||||
23701a29526
|
||||
> filesystem/MS
|
||||
24155c29977
|
||||
24155c29980
|
||||
< fluidized
|
||||
---
|
||||
> fluidize/DSG
|
||||
24216a30039
|
||||
24216a30042
|
||||
> foci
|
||||
24736d30558
|
||||
24736d30561
|
||||
< frier/M
|
||||
24855,24856c30677,30678
|
||||
24855,24856c30680,30681
|
||||
< fucker/M!
|
||||
< fuckhead/S!
|
||||
---
|
||||
> fucker/SM!
|
||||
> fuckhead/SM!
|
||||
24953d30774
|
||||
24953d30777
|
||||
< furore/MS
|
||||
25125c30946
|
||||
25125c30949
|
||||
< gaolbird/S
|
||||
---
|
||||
> gaolbirds
|
||||
25180d31000
|
||||
25180d31003
|
||||
< gasolene/M
|
||||
25190a31011
|
||||
25190a31014
|
||||
> gastroenterologist/M
|
||||
25262c31083
|
||||
25262c31086
|
||||
< geezer/M
|
||||
---
|
||||
> geezer/MS
|
||||
25327c31148
|
||||
25327c31151
|
||||
< genomic
|
||||
---
|
||||
> genomic/S
|
||||
25462a31284
|
||||
25462a31287
|
||||
> gigabit/MS
|
||||
25464a31287,31289
|
||||
25464a31290,31292
|
||||
> gigajoule/MS
|
||||
> gigapixel/MS
|
||||
> gigawatt/MS
|
||||
25560d31384
|
||||
25560d31387
|
||||
< glamourize/DSG
|
||||
25674c31498
|
||||
25674c31501
|
||||
< glycerine's
|
||||
---
|
||||
> glycerine/M
|
||||
25905c31729
|
||||
25905c31732
|
||||
< gram/MS
|
||||
---
|
||||
> gram/KMS
|
||||
25909d31732
|
||||
25909d31735
|
||||
< gramme/SM
|
||||
26063c31886,31887
|
||||
26063c31889,31890
|
||||
< greybeard
|
||||
---
|
||||
> grey/MDRTGSP
|
||||
> greybeard/SM
|
||||
26066c31890
|
||||
26066c31893
|
||||
< greyness
|
||||
---
|
||||
> greyness/M
|
||||
26246,26247d32069
|
||||
26246,26247d32072
|
||||
< guerilla's
|
||||
< guerillas
|
||||
26432,26436d32253
|
||||
26432,26436d32256
|
||||
< haemoglobin's
|
||||
< haemophilia/M
|
||||
< haemorrhage/DSMG
|
||||
< haemorrhoid/S
|
||||
< haemorrhoids/M
|
||||
27167c32984
|
||||
27167c32987
|
||||
< hexane
|
||||
---
|
||||
> hexane/SM
|
||||
27273a33091
|
||||
27273a33094
|
||||
> hippopotami
|
||||
27875d33692
|
||||
27875d33695
|
||||
< hyaena/SM
|
||||
28017c33834
|
||||
28017c33837
|
||||
< iPod/M
|
||||
---
|
||||
> iPod/MS
|
||||
28105a33923
|
||||
28105a33926
|
||||
> idolator/SM
|
||||
28513c34331
|
||||
28513c34334
|
||||
< inbound
|
||||
---
|
||||
> inbound/s
|
||||
28650a34469
|
||||
28590,28591c34411
|
||||
< incorrigibility/M
|
||||
< incorrigible
|
||||
---
|
||||
> incorrigibleness
|
||||
28593d34412
|
||||
< incorruptibly
|
||||
28650a34470
|
||||
> indices
|
||||
28812d34630
|
||||
28812d34631
|
||||
< inflexion/SM
|
||||
29216a35035
|
||||
29216a35036
|
||||
> intern/GDL
|
||||
29266a35086
|
||||
29266a35087
|
||||
> interruptible/U
|
||||
29272a35093,35096
|
||||
29272a35094,35097
|
||||
> intersex
|
||||
> intersexual/MS
|
||||
> intersexualism
|
||||
> intersexuality
|
||||
29724c35548
|
||||
29724c35549
|
||||
< jewellery's
|
||||
---
|
||||
> jewellery/M
|
||||
29870a35695
|
||||
29870a35696
|
||||
> judgement/MS
|
||||
30066c35891
|
||||
30066c35892
|
||||
< kiddie/M
|
||||
---
|
||||
> kiddie/SM
|
||||
30262,30263c36087
|
||||
30262,30263c36088
|
||||
< kraut's
|
||||
< kraut/S!
|
||||
---
|
||||
> kraut/MS!
|
||||
30665a36490
|
||||
30665a36491
|
||||
> lector/MS
|
||||
31031c36856
|
||||
31031c36857
|
||||
< linguini's
|
||||
---
|
||||
> linguini/M
|
||||
31034c36859
|
||||
31034c36860
|
||||
< linguistically
|
||||
---
|
||||
> linguistical/Y
|
||||
31151,31152c36976
|
||||
31151,31152c36977
|
||||
< liver's
|
||||
< liver/S
|
||||
---
|
||||
> liver/MS
|
||||
32230c38054
|
||||
32230c38055
|
||||
< meanie/M
|
||||
---
|
||||
> meanie/MS
|
||||
32317,32318c38141
|
||||
32317,32318c38142
|
||||
< megadeath/M
|
||||
< megadeaths
|
||||
---
|
||||
> megadeath/SM
|
||||
32320c38143
|
||||
32320c38144
|
||||
< megajoules
|
||||
---
|
||||
> megajoule/SM
|
||||
32329c38152
|
||||
32329c38153
|
||||
< megapixel/S
|
||||
---
|
||||
> megapixel/MS
|
||||
32708a38532
|
||||
32708a38533
|
||||
> might've
|
||||
32717a38542
|
||||
32717a38543
|
||||
> migrator/SM
|
||||
32760a38586
|
||||
32760a38587
|
||||
> millennia
|
||||
32777d38602
|
||||
32777d38603
|
||||
< millionnaire/M
|
||||
32934a38760
|
||||
32934a38761
|
||||
> miscommunication/S
|
||||
32991a38818
|
||||
32991a38819
|
||||
> misjudgement/MS
|
||||
33784a39612
|
||||
33784a39613
|
||||
> must've
|
||||
33963c39791
|
||||
33963c39792
|
||||
< native/MS
|
||||
---
|
||||
> native/MSY
|
||||
34169,34171c39997,39998
|
||||
34169,34171c39998,39999
|
||||
< neurone/S
|
||||
< neurophysiology
|
||||
< neuroscience
|
||||
---
|
||||
> neurophysiology/M
|
||||
> neuroscience/MS
|
||||
34275c40102
|
||||
34275c40103
|
||||
< nightie/M
|
||||
---
|
||||
> nightie/SM
|
||||
35104a40932
|
||||
35104a40933
|
||||
> octopi
|
||||
35219d41046
|
||||
35219d41047
|
||||
< oleomargarin/M
|
||||
35226a41054
|
||||
35226a41055
|
||||
> oligo
|
||||
35913c41741
|
||||
35913c41742
|
||||
< oversize/D
|
||||
---
|
||||
> oversize
|
||||
36056,36059d41883
|
||||
36056,36059d41884
|
||||
< paederast/S
|
||||
< paediatrician's
|
||||
< paediatricians
|
||||
< paediatrics/M
|
||||
36291a42116
|
||||
36291a42117
|
||||
> paralyses
|
||||
36403d42227
|
||||
36403d42228
|
||||
< parrakeet/MS
|
||||
36449d42272
|
||||
36449d42273
|
||||
< partizan/SM
|
||||
37093a42917
|
||||
37093a42918
|
||||
> petabyte/MS
|
||||
37102c42926
|
||||
37102c42927
|
||||
< petitioner/M
|
||||
---
|
||||
> petitioner/MS
|
||||
37264a43089
|
||||
37264a43090
|
||||
> phosphorylate/DSGN
|
||||
37316d43140
|
||||
37316d43141
|
||||
< phrenetic
|
||||
37630a43455
|
||||
37630a43456
|
||||
> plaintext
|
||||
37796a43622
|
||||
37796a43623
|
||||
> plugin/MS
|
||||
37987c43813
|
||||
37987c43814
|
||||
< polypeptide/S
|
||||
---
|
||||
> polypeptide/MS
|
||||
38291d44116
|
||||
38291d44117
|
||||
< practise's
|
||||
38451a44277
|
||||
38451a44278
|
||||
> prejudgement/MS
|
||||
38805a44632
|
||||
38805a44633
|
||||
> profiler/SM
|
||||
38835a44663
|
||||
38835a44664
|
||||
> programmatically
|
||||
38891a44720,44721
|
||||
38891a44721,44722
|
||||
> pronate/DSGN
|
||||
> pronator/MS
|
||||
38951c44781
|
||||
38951c44782
|
||||
< proprietorship/M
|
||||
---
|
||||
> proprietorship/MS
|
||||
39039a44870
|
||||
39039a44871
|
||||
> provender/M
|
||||
39095a44927
|
||||
39095a44928
|
||||
> pseudorandom/Y
|
||||
39564a45397
|
||||
39564a45398
|
||||
> quinoa
|
||||
39873a45707,45708
|
||||
39873a45708,45709
|
||||
> rasterization/M
|
||||
> rasterize/SGDR
|
||||
40036a45872
|
||||
40036a45873
|
||||
> recency
|
||||
40140a45977
|
||||
40140a45978
|
||||
> recurse/DGSV
|
||||
40141a45979
|
||||
40141a45980
|
||||
> recuse/DGS
|
||||
40208a46047
|
||||
40208a46048
|
||||
> refactor/SMDG
|
||||
40244d46082
|
||||
40244d46083
|
||||
< reflexion/SM
|
||||
40659d46496
|
||||
40659d46497
|
||||
< resizing
|
||||
40829c46666
|
||||
40829c46667
|
||||
< reverie/M
|
||||
---
|
||||
> reverie/MS
|
||||
41415a47253
|
||||
41415a47254
|
||||
> sabre/MS
|
||||
41914c47752
|
||||
41914c47753
|
||||
< schnaps's
|
||||
---
|
||||
> schnaps/M
|
||||
41949c47787
|
||||
41949c47788
|
||||
< schrod's
|
||||
---
|
||||
> schrod/SM
|
||||
41998a47837
|
||||
41998a47838
|
||||
> scot-free
|
||||
42883,42885c48722
|
||||
42883,42885c48723
|
||||
< shit's
|
||||
< shit/S!
|
||||
< shite/S!
|
||||
---
|
||||
> shit/MS!
|
||||
42887,42888c48724,48725
|
||||
42887,42888c48725,48726
|
||||
< shithead/S!
|
||||
< shitload/!
|
||||
---
|
||||
> shithead/MS!
|
||||
> shitload/MS!
|
||||
42891c48728
|
||||
42891c48729
|
||||
< shitty/RT!
|
||||
---
|
||||
> shitty/TR!
|
||||
42976a48814
|
||||
42976a48815
|
||||
> should've
|
||||
43008c48846
|
||||
43008c48847
|
||||
< showtime
|
||||
---
|
||||
> showtime/MS
|
||||
43328c49166
|
||||
43328c49167
|
||||
< size/MGBDRS
|
||||
---
|
||||
> size/AMGBDRS
|
||||
43724,43726c49562
|
||||
43724,43726c49563
|
||||
< smoulder's
|
||||
< smouldered
|
||||
< smoulders
|
||||
---
|
||||
> smoulder/GSMD
|
||||
43766a49603,49604
|
||||
43766a49604,49605
|
||||
> snarkily
|
||||
> snarky/TR
|
||||
44062c49900
|
||||
44062c49901
|
||||
< sonofabitch
|
||||
---
|
||||
> sonofabitch/!
|
||||
44346a50185
|
||||
44346a50186
|
||||
> spelled
|
||||
44348a50188
|
||||
44348a50189
|
||||
> spelt
|
||||
44371a50212
|
||||
44371a50213
|
||||
> spick/S!
|
||||
44383c50224
|
||||
44383c50225
|
||||
< spik/S
|
||||
---
|
||||
> spik/S!
|
||||
46106a51948
|
||||
46106a51949
|
||||
> syllabi
|
||||
46160c52002
|
||||
46160c52003
|
||||
< synch/GMD
|
||||
---
|
||||
> synch/GMDS
|
||||
46167d52008
|
||||
46167d52009
|
||||
< synchs
|
||||
46203,46204c52044,52045
|
||||
46203,46204c52045,52046
|
||||
< sysadmin/S
|
||||
< sysop/S
|
||||
---
|
||||
> sysadmin/MS
|
||||
> sysop/MS
|
||||
46752a52594
|
||||
46752a52595
|
||||
> terabit/MS
|
||||
46753a52596,52597
|
||||
46753a52597,52598
|
||||
> terahertz/M
|
||||
> terapixel/MS
|
||||
46817a52662
|
||||
46817a52663
|
||||
> testcase/MS
|
||||
46831a52677
|
||||
46831a52678
|
||||
> testsuite/MS
|
||||
46925a52772
|
||||
46925a52773
|
||||
> theremin/MS
|
||||
47455c53302
|
||||
47455c53303
|
||||
< toolbar
|
||||
---
|
||||
> toolbar/MS
|
||||
47755a53603
|
||||
47755a53604
|
||||
> transfect/DSMG
|
||||
47774a53623,53624
|
||||
47774a53624,53625
|
||||
> transgenderism
|
||||
> transgene/MS
|
||||
47951c53801
|
||||
47951c53802
|
||||
< triage/M
|
||||
---
|
||||
> triage/MG
|
||||
48869a54720
|
||||
48869a54721
|
||||
> unlikeable
|
||||
49211c55062
|
||||
49211c55063
|
||||
< vagina/M
|
||||
---
|
||||
> vagina/MS
|
||||
49368,49369c55219
|
||||
49368,49369c55220
|
||||
< velour's
|
||||
< velours's
|
||||
---
|
||||
> velour/MS
|
||||
49478a55329
|
||||
49478a55330
|
||||
> vertices
|
||||
50148a56000
|
||||
50148a56001
|
||||
> weaponize/DSG
|
||||
50260,50261d56111
|
||||
50260,50261d56112
|
||||
< werwolf/M
|
||||
< werwolves
|
||||
50728c56578
|
||||
50728c56579
|
||||
< women
|
||||
---
|
||||
> women/M
|
||||
50794c56644
|
||||
50794c56645
|
||||
< wop/S!
|
||||
---
|
||||
> wop/MS!
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
57466
|
||||
57467
|
||||
0/nm
|
||||
0th/pt
|
||||
1/n1
|
||||
|
@ -24448,6 +24448,8 @@ corresponding/Y
|
|||
corridor/SM
|
||||
corrie/S
|
||||
corrigenda
|
||||
corrigibility/IM
|
||||
corrigible/I
|
||||
corroborate/GNVXDS
|
||||
corroborated/U
|
||||
corroboration/M
|
||||
|
@ -24462,6 +24464,7 @@ corrupt/DRYPSTG
|
|||
corrupted/U
|
||||
corruptibility/IM
|
||||
corruptible/I
|
||||
corruptibly/I
|
||||
corruption/SM
|
||||
corruptness/M
|
||||
corsage/MS
|
||||
|
@ -34696,10 +34699,8 @@ incorporated/U
|
|||
incorporation/AM
|
||||
incorporeal
|
||||
incorrect/Y
|
||||
incorrigibility/M
|
||||
incorrigible
|
||||
incorrigibleness
|
||||
incorrigibly
|
||||
incorruptibly
|
||||
increasing/Y
|
||||
increment/SMDG
|
||||
incremental/Y
|
||||
|
|
|
@ -1222,7 +1222,7 @@ DrawTargetD2D::OptimizeSourceSurface(SourceSurface *aSurface) const
|
|||
data->Unmap();
|
||||
|
||||
if (!success) {
|
||||
return nullptr;
|
||||
return data;
|
||||
}
|
||||
return newSurf;
|
||||
}
|
||||
|
|
|
@ -943,7 +943,7 @@ DrawTargetD2D1::OptimizeSourceSurface(SourceSurface* aSurface) const
|
|||
data->Unmap();
|
||||
|
||||
if (!bitmap) {
|
||||
return nullptr;
|
||||
return data;
|
||||
}
|
||||
|
||||
return new SourceSurfaceD2D1(bitmap.get(), mDC, data->GetFormat(), data->GetSize());
|
||||
|
|
|
@ -319,8 +319,6 @@ TextureClient::CreateTextureClientForDrawing(ISurfaceAllocator* aAllocator,
|
|||
result = new TextureClientX11(aFormat, aTextureFlags);
|
||||
}
|
||||
#ifdef GL_PROVIDER_GLX
|
||||
#if 0
|
||||
// Bug 977963: Disabled for black layers
|
||||
if (parentBackend == LayersBackend::LAYERS_OPENGL &&
|
||||
type == gfxSurfaceType::Xlib &&
|
||||
!(aTextureFlags & TEXTURE_ALLOC_FALLBACK) &&
|
||||
|
@ -331,7 +329,6 @@ TextureClient::CreateTextureClientForDrawing(ISurfaceAllocator* aAllocator,
|
|||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
if (!DisableGralloc(aFormat, aSizeHint)) {
|
||||
|
|
|
@ -54,7 +54,7 @@ X11TextureSourceOGL::BindTexture(GLenum aTextureUnit, gfx::Filter aFilter)
|
|||
gl::sGLXLibrary.UpdateTexImage(mSurface->XDisplay(), mSurface->GetGLXPixmap());
|
||||
}
|
||||
|
||||
ApplyFilterToBoundTexture(gl(), aFilter, LOCAL_GL_TEXTURE_RECTANGLE_ARB);
|
||||
ApplyFilterToBoundTexture(gl(), aFilter, LOCAL_GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
IntSize
|
||||
|
|
|
@ -754,76 +754,26 @@ gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget, gfxASurface *aSurfa
|
|||
if (!srcBuffer) {
|
||||
nsRefPtr<gfxImageSurface> imgSurface = aSurface->GetAsImageSurface();
|
||||
|
||||
RefPtr<DataSourceSurface> copy;
|
||||
if (!imgSurface) {
|
||||
copy = CopySurface(aSurface);
|
||||
RefPtr<DataSourceSurface> dataSurf;
|
||||
|
||||
if (!copy) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DataSourceSurface::MappedSurface map;
|
||||
DebugOnly<bool> result = copy->Map(DataSourceSurface::WRITE, &map);
|
||||
MOZ_ASSERT(result, "Should always succeed mapping raw data surfaces!");
|
||||
|
||||
imgSurface = new gfxImageSurface(map.mData, aSurface->GetSize(), map.mStride,
|
||||
SurfaceFormatToImageFormat(copy->GetFormat()));
|
||||
if (imgSurface) {
|
||||
dataSurf = GetWrappedDataSourceSurface(aSurface);
|
||||
} else {
|
||||
dataSurf = CopySurface(aSurface);
|
||||
}
|
||||
|
||||
gfxImageFormat cairoFormat = imgSurface->Format();
|
||||
switch(cairoFormat) {
|
||||
case gfxImageFormat::ARGB32:
|
||||
format = SurfaceFormat::B8G8R8A8;
|
||||
break;
|
||||
case gfxImageFormat::RGB24:
|
||||
format = SurfaceFormat::B8G8R8X8;
|
||||
break;
|
||||
case gfxImageFormat::A8:
|
||||
format = SurfaceFormat::A8;
|
||||
break;
|
||||
case gfxImageFormat::RGB16_565:
|
||||
format = SurfaceFormat::R5G6B5;
|
||||
break;
|
||||
default:
|
||||
NS_RUNTIMEABORT("Invalid surface format!");
|
||||
}
|
||||
|
||||
IntSize size = IntSize(imgSurface->GetSize().width, imgSurface->GetSize().height);
|
||||
srcBuffer = aTarget->CreateSourceSurfaceFromData(imgSurface->Data(),
|
||||
size,
|
||||
imgSurface->Stride(),
|
||||
format);
|
||||
|
||||
if (copy) {
|
||||
copy->Unmap();
|
||||
}
|
||||
|
||||
if (!srcBuffer) {
|
||||
// If we had to make a copy, then just return that. Otherwise aSurface
|
||||
// must have supported GetAsImageSurface, so we can just wrap that data.
|
||||
if (copy) {
|
||||
srcBuffer = copy;
|
||||
} else {
|
||||
return GetWrappedDataSourceSurface(aSurface);
|
||||
}
|
||||
}
|
||||
|
||||
if (!srcBuffer) {
|
||||
if (!dataSurf) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#if MOZ_TREE_CAIRO
|
||||
cairo_surface_t *nullSurf =
|
||||
cairo_null_surface_create(CAIRO_CONTENT_COLOR_ALPHA);
|
||||
cairo_surface_set_user_data(nullSurf,
|
||||
&kSourceSurface,
|
||||
imgSurface,
|
||||
nullptr);
|
||||
cairo_surface_attach_snapshot(imgSurface->CairoSurface(), nullSurf, SourceSnapshotDetached);
|
||||
cairo_surface_destroy(nullSurf);
|
||||
#else
|
||||
cairo_surface_set_mime_data(imgSurface->CairoSurface(), "mozilla/magic", (const unsigned char*) "data", 4, SourceSnapshotDetached, imgSurface.get());
|
||||
#endif
|
||||
srcBuffer = aTarget->OptimizeSourceSurface(dataSurf);
|
||||
|
||||
if (imgSurface && srcBuffer == dataSurf) {
|
||||
// Our wrapping surface will hold a reference to its image surface. We cause
|
||||
// a reference cycle if we add it to the cache. And caching it is pretty
|
||||
// pointless since we'll just wrap it again next use.
|
||||
return srcBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
// Add user data to aSurface so we can cache lookups in the future.
|
||||
|
|
|
@ -283,6 +283,15 @@ MessageChannel::Clear()
|
|||
mChannelErrorTask->Cancel();
|
||||
mChannelErrorTask = nullptr;
|
||||
}
|
||||
|
||||
// Free up any memory used by pending messages.
|
||||
mPending.clear();
|
||||
mPendingUrgentRequest = nullptr;
|
||||
mPendingRPCCall = nullptr;
|
||||
mOutOfTurnReplies.clear();
|
||||
while (!mDeferred.empty()) {
|
||||
mDeferred.pop();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -697,10 +697,12 @@ FrameIter::FrameIter(const Data &data)
|
|||
{
|
||||
JS_ASSERT(data.cx_);
|
||||
|
||||
#ifdef JS_ION
|
||||
if (data_.jitFrames_.isIonJS()) {
|
||||
while (ionInlineFrames_.frameNo() != data.ionInlineFrameNo_)
|
||||
++ionInlineFrames_;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef JS_ION
|
||||
|
@ -789,16 +791,17 @@ FrameIter::operator++()
|
|||
}
|
||||
popInterpreterFrame();
|
||||
break;
|
||||
case JIT:
|
||||
#ifdef JS_ION
|
||||
case JIT:
|
||||
popJitFrame();
|
||||
break;
|
||||
#else
|
||||
MOZ_ASSUME_UNREACHABLE("Unexpected state");
|
||||
#endif
|
||||
case ASMJS:
|
||||
popAsmJSFrame();
|
||||
break;
|
||||
#else
|
||||
default:
|
||||
MOZ_ASSUME_UNREACHABLE("Unexpected state");
|
||||
#endif
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
|
|
@ -9,40 +9,11 @@
|
|||
#ifndef mozilla_TypedEnum_h
|
||||
#define mozilla_TypedEnum_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/TypedEnumInternal.h"
|
||||
#include "mozilla/MacroArgs.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
|
||||
#if defined(__clang__)
|
||||
/*
|
||||
* Per Clang documentation, "Note that marketing version numbers should not
|
||||
* be used to check for language features, as different vendors use different
|
||||
* numbering schemes. Instead, use the feature checking macros."
|
||||
*/
|
||||
# ifndef __has_extension
|
||||
# define __has_extension __has_feature /* compatibility, for older versions of clang */
|
||||
# endif
|
||||
# if __has_extension(cxx_strong_enums)
|
||||
# define MOZ_HAVE_CXX11_ENUM_TYPE
|
||||
# define MOZ_HAVE_CXX11_STRONG_ENUMS
|
||||
# endif
|
||||
#elif defined(__GNUC__)
|
||||
# if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
|
||||
# if MOZ_GCC_VERSION_AT_LEAST(4, 6, 3)
|
||||
# define MOZ_HAVE_CXX11_ENUM_TYPE
|
||||
# define MOZ_HAVE_CXX11_STRONG_ENUMS
|
||||
# endif
|
||||
# endif
|
||||
#elif defined(_MSC_VER)
|
||||
# if _MSC_VER >= 1400
|
||||
# define MOZ_HAVE_CXX11_ENUM_TYPE
|
||||
# endif
|
||||
# if _MSC_VER >= 1700
|
||||
# define MOZ_HAVE_CXX11_STRONG_ENUMS
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MOZ_ENUM_TYPE specifies the underlying numeric type for an enum. It's
|
||||
* specified by placing MOZ_ENUM_TYPE(type) immediately after the enum name in
|
||||
|
@ -190,9 +161,13 @@
|
|||
# define MOZ_END_NESTED_ENUM_CLASS(Name) \
|
||||
}; \
|
||||
Name() {} \
|
||||
Name(Enum aEnum) : mEnum(aEnum) {} \
|
||||
explicit Name(int num) : mEnum((Enum)num) {} \
|
||||
operator Enum() const { return mEnum; } \
|
||||
MOZ_CONSTEXPR Name(Enum aEnum) : mEnum(aEnum) {} \
|
||||
template<typename Other> \
|
||||
explicit MOZ_CONSTEXPR Name(Other num) : mEnum((Enum)num) {} \
|
||||
MOZ_CONSTEXPR operator Enum() const { return mEnum; } \
|
||||
explicit MOZ_CONSTEXPR Name(const mozilla::CastableTypedEnumResult<Name>& aOther) \
|
||||
: mEnum(aOther.get()) \
|
||||
{} \
|
||||
private: \
|
||||
Enum mEnum; \
|
||||
};
|
||||
|
@ -230,7 +205,6 @@
|
|||
inline bool operator&&(const Name::Enum&, const bool&) MOZ_DELETE; \
|
||||
inline bool operator||(const bool&, const Name::Enum&) MOZ_DELETE; \
|
||||
inline bool operator||(const Name::Enum&, const bool&) MOZ_DELETE; \
|
||||
inline int operator~(const Name::Enum&) MOZ_DELETE; \
|
||||
inline int operator&(const int&, const Name::Enum&) MOZ_DELETE; \
|
||||
inline int operator&(const Name::Enum&, const int&) MOZ_DELETE; \
|
||||
inline int operator|(const int&, const Name::Enum&) MOZ_DELETE; \
|
||||
|
|
|
@ -0,0 +1,182 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
/* MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS allows using a typed enum as bit flags. */
|
||||
|
||||
#ifndef mozilla_TypedEnumBits_h
|
||||
#define mozilla_TypedEnumBits_h
|
||||
|
||||
#include "mozilla/IntegerTypeTraits.h"
|
||||
#include "mozilla/TypedEnumInternal.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
#define MOZ_CASTABLETYPEDENUMRESULT_BINOP(Op, OtherType, ReturnType) \
|
||||
template<typename E> \
|
||||
MOZ_CONSTEXPR ReturnType \
|
||||
operator Op(const OtherType& e, const CastableTypedEnumResult<E>& r) \
|
||||
{ \
|
||||
return ReturnType(e Op OtherType(r)); \
|
||||
} \
|
||||
template<typename E> \
|
||||
MOZ_CONSTEXPR ReturnType \
|
||||
operator Op(const CastableTypedEnumResult<E>& r, const OtherType& e) \
|
||||
{ \
|
||||
return ReturnType(OtherType(r) Op e); \
|
||||
} \
|
||||
template<typename E> \
|
||||
MOZ_CONSTEXPR ReturnType \
|
||||
operator Op(const CastableTypedEnumResult<E>& r1, \
|
||||
const CastableTypedEnumResult<E>& r2) \
|
||||
{ \
|
||||
return ReturnType(OtherType(r1) Op OtherType(r2)); \
|
||||
}
|
||||
|
||||
MOZ_CASTABLETYPEDENUMRESULT_BINOP(|, E, CastableTypedEnumResult<E>)
|
||||
MOZ_CASTABLETYPEDENUMRESULT_BINOP(&, E, CastableTypedEnumResult<E>)
|
||||
MOZ_CASTABLETYPEDENUMRESULT_BINOP(^, E, CastableTypedEnumResult<E>)
|
||||
MOZ_CASTABLETYPEDENUMRESULT_BINOP(==, E, bool)
|
||||
MOZ_CASTABLETYPEDENUMRESULT_BINOP(!=, E, bool)
|
||||
MOZ_CASTABLETYPEDENUMRESULT_BINOP(||, bool, bool)
|
||||
MOZ_CASTABLETYPEDENUMRESULT_BINOP(&&, bool, bool)
|
||||
|
||||
template <typename E>
|
||||
MOZ_CONSTEXPR CastableTypedEnumResult<E>
|
||||
operator ~(const CastableTypedEnumResult<E>& r)
|
||||
{
|
||||
return CastableTypedEnumResult<E>(~(E(r)));
|
||||
}
|
||||
|
||||
#define MOZ_CASTABLETYPEDENUMRESULT_COMPOUND_ASSIGN_OP(Op) \
|
||||
template<typename E> \
|
||||
E& \
|
||||
operator Op(E& r1, \
|
||||
const CastableTypedEnumResult<E>& r2) \
|
||||
{ \
|
||||
return r1 Op E(r2); \
|
||||
}
|
||||
|
||||
MOZ_CASTABLETYPEDENUMRESULT_COMPOUND_ASSIGN_OP(&=)
|
||||
MOZ_CASTABLETYPEDENUMRESULT_COMPOUND_ASSIGN_OP(|=)
|
||||
MOZ_CASTABLETYPEDENUMRESULT_COMPOUND_ASSIGN_OP(^=)
|
||||
|
||||
#undef MOZ_CASTABLETYPEDENUMRESULT_COMPOUND_ASSIGN_OP
|
||||
|
||||
#undef MOZ_CASTABLETYPEDENUMRESULT_BINOP
|
||||
|
||||
#ifndef MOZ_HAVE_CXX11_STRONG_ENUMS
|
||||
|
||||
#define MOZ_CASTABLETYPEDENUMRESULT_BINOP_EXTRA_NON_CXX11(Op, ReturnType) \
|
||||
template<typename E> \
|
||||
MOZ_CONSTEXPR ReturnType \
|
||||
operator Op(typename E::Enum e, const CastableTypedEnumResult<E>& r) \
|
||||
{ \
|
||||
return ReturnType(e Op E(r)); \
|
||||
} \
|
||||
template<typename E> \
|
||||
MOZ_CONSTEXPR ReturnType \
|
||||
operator Op(const CastableTypedEnumResult<E>& r, typename E::Enum e) \
|
||||
{ \
|
||||
return ReturnType(E(r) Op e); \
|
||||
}
|
||||
|
||||
MOZ_CASTABLETYPEDENUMRESULT_BINOP_EXTRA_NON_CXX11(|, CastableTypedEnumResult<E>)
|
||||
MOZ_CASTABLETYPEDENUMRESULT_BINOP_EXTRA_NON_CXX11(&, CastableTypedEnumResult<E>)
|
||||
MOZ_CASTABLETYPEDENUMRESULT_BINOP_EXTRA_NON_CXX11(^, CastableTypedEnumResult<E>)
|
||||
MOZ_CASTABLETYPEDENUMRESULT_BINOP_EXTRA_NON_CXX11(==, bool)
|
||||
MOZ_CASTABLETYPEDENUMRESULT_BINOP_EXTRA_NON_CXX11(!=, bool)
|
||||
|
||||
#undef MOZ_CASTABLETYPEDENUMRESULT_BINOP_EXTRA_NON_CXX11
|
||||
|
||||
#endif // not MOZ_HAVE_CXX11_STRONG_ENUMS
|
||||
|
||||
namespace detail {
|
||||
template<typename E>
|
||||
struct UnsignedIntegerTypeForEnum
|
||||
: UnsignedStdintTypeForSize<sizeof(E)>
|
||||
{};
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#define MOZ_MAKE_ENUM_CLASS_BINOP_IMPL(Name, Op) \
|
||||
inline MOZ_CONSTEXPR mozilla::CastableTypedEnumResult<Name> \
|
||||
operator Op(Name a, Name b) \
|
||||
{ \
|
||||
typedef mozilla::CastableTypedEnumResult<Name> Result; \
|
||||
typedef mozilla::detail::UnsignedIntegerTypeForEnum<Name>::Type U; \
|
||||
return Result(Name(U(a) Op U(b))); \
|
||||
} \
|
||||
\
|
||||
inline Name& \
|
||||
operator Op##=(Name& a, Name b) \
|
||||
{ \
|
||||
return a = a Op b; \
|
||||
}
|
||||
|
||||
#define MOZ_MAKE_ENUM_CLASS_OPS_IMPL(Name) \
|
||||
MOZ_MAKE_ENUM_CLASS_BINOP_IMPL(Name, |) \
|
||||
MOZ_MAKE_ENUM_CLASS_BINOP_IMPL(Name, &) \
|
||||
MOZ_MAKE_ENUM_CLASS_BINOP_IMPL(Name, ^) \
|
||||
inline MOZ_CONSTEXPR mozilla::CastableTypedEnumResult<Name> \
|
||||
operator~(Name a) \
|
||||
{ \
|
||||
typedef mozilla::CastableTypedEnumResult<Name> Result; \
|
||||
typedef mozilla::detail::UnsignedIntegerTypeForEnum<Name>::Type U; \
|
||||
return Result(Name(~(U(a)))); \
|
||||
}
|
||||
|
||||
#ifndef MOZ_HAVE_CXX11_STRONG_ENUMS
|
||||
# define MOZ_MAKE_ENUM_CLASS_BITWISE_BINOP_EXTRA_NON_CXX11(Name, Op) \
|
||||
inline MOZ_CONSTEXPR mozilla::CastableTypedEnumResult<Name> \
|
||||
operator Op(Name a, Name::Enum b) \
|
||||
{ \
|
||||
return a Op Name(b); \
|
||||
} \
|
||||
\
|
||||
inline MOZ_CONSTEXPR mozilla::CastableTypedEnumResult<Name> \
|
||||
operator Op(Name::Enum a, Name b) \
|
||||
{ \
|
||||
return Name(a) Op b; \
|
||||
} \
|
||||
\
|
||||
inline MOZ_CONSTEXPR mozilla::CastableTypedEnumResult<Name> \
|
||||
operator Op(Name::Enum a, Name::Enum b) \
|
||||
{ \
|
||||
return Name(a) Op Name(b); \
|
||||
} \
|
||||
\
|
||||
inline Name& \
|
||||
operator Op##=(Name& a, Name::Enum b) \
|
||||
{ \
|
||||
return a = a Op Name(b); \
|
||||
}
|
||||
|
||||
# define MOZ_MAKE_ENUM_CLASS_OPS_EXTRA_NON_CXX11(Name) \
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_BINOP_EXTRA_NON_CXX11(Name, |) \
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_BINOP_EXTRA_NON_CXX11(Name, &) \
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_BINOP_EXTRA_NON_CXX11(Name, ^) \
|
||||
inline MOZ_CONSTEXPR mozilla::CastableTypedEnumResult<Name> \
|
||||
operator~(Name::Enum a) \
|
||||
{ \
|
||||
return ~(Name(a)); \
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS generates standard bitwise operators
|
||||
* for the given enum type. Use this to enable using an enum type as bit-field.
|
||||
*/
|
||||
#ifdef MOZ_HAVE_CXX11_STRONG_ENUMS
|
||||
# define MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(Name) \
|
||||
MOZ_MAKE_ENUM_CLASS_OPS_IMPL(Name)
|
||||
#else
|
||||
# define MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(Name) \
|
||||
MOZ_MAKE_ENUM_CLASS_OPS_IMPL(Name) \
|
||||
MOZ_MAKE_ENUM_CLASS_OPS_EXTRA_NON_CXX11(Name)
|
||||
#endif
|
||||
|
||||
#endif // mozilla_TypedEnumBits_h
|
|
@ -0,0 +1,112 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
/* Internal stuff needed by TypedEnum.h and TypedEnumBits.h. */
|
||||
|
||||
// NOTE: When we can assume C++11 enum class support and TypedEnum.h goes away,
|
||||
// we should then consider folding TypedEnumInternal.h into TypedEnumBits.h.
|
||||
|
||||
#ifndef mozilla_TypedEnumInternal_h
|
||||
#define mozilla_TypedEnumInternal_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
|
||||
#if defined(__clang__)
|
||||
/*
|
||||
* Per Clang documentation, "Note that marketing version numbers should not
|
||||
* be used to check for language features, as different vendors use different
|
||||
* numbering schemes. Instead, use the feature checking macros."
|
||||
*/
|
||||
# ifndef __has_extension
|
||||
# define __has_extension __has_feature /* compatibility, for older versions of clang */
|
||||
# endif
|
||||
# if __has_extension(cxx_strong_enums)
|
||||
# define MOZ_HAVE_CXX11_ENUM_TYPE
|
||||
# define MOZ_HAVE_CXX11_STRONG_ENUMS
|
||||
# endif
|
||||
#elif defined(__GNUC__)
|
||||
# if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
|
||||
# if MOZ_GCC_VERSION_AT_LEAST(4, 6, 3)
|
||||
# define MOZ_HAVE_CXX11_ENUM_TYPE
|
||||
# define MOZ_HAVE_CXX11_STRONG_ENUMS
|
||||
# endif
|
||||
# endif
|
||||
#elif defined(_MSC_VER)
|
||||
# if _MSC_VER >= 1400
|
||||
# define MOZ_HAVE_CXX11_ENUM_TYPE
|
||||
# endif
|
||||
# if _MSC_VER >= 1700
|
||||
# define MOZ_HAVE_CXX11_STRONG_ENUMS
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/*
|
||||
* The problem that CastableTypedEnumResult aims to solve is that
|
||||
* typed enums are not convertible to bool, and there is no way to make them
|
||||
* be, yet user code wants to be able to write
|
||||
*
|
||||
* if (myFlags & Flags::SOME_PARTICULAR_FLAG) (1)
|
||||
*
|
||||
* There are different approaches to solving this. Most of them require
|
||||
* adapting user code. For example, we could implement operator! and have
|
||||
* the user write
|
||||
*
|
||||
* if (!!(myFlags & Flags::SOME_PARTICULAR_FLAG)) (2)
|
||||
*
|
||||
* Or we could supply a IsNonZero() or Any() function returning whether
|
||||
* an enum value is nonzero, and have the user write
|
||||
*
|
||||
* if (Any(Flags & Flags::SOME_PARTICULAR_FLAG)) (3)
|
||||
*
|
||||
* But instead, we choose to preserve the original user syntax (1) as it
|
||||
* is inherently more readable, and to ease porting existing code to typed
|
||||
* enums. We achieve this by having operator& and other binary bitwise
|
||||
* operators have as return type a class, CastableTypedEnumResult,
|
||||
* that wraps a typed enum but adds bool convertibility.
|
||||
*/
|
||||
template<typename E>
|
||||
class CastableTypedEnumResult
|
||||
{
|
||||
private:
|
||||
const E mValue;
|
||||
|
||||
public:
|
||||
explicit MOZ_CONSTEXPR CastableTypedEnumResult(E value)
|
||||
: mValue(value)
|
||||
{}
|
||||
|
||||
MOZ_CONSTEXPR operator E() const { return mValue; }
|
||||
|
||||
template<typename DestinationType>
|
||||
MOZ_EXPLICIT_CONVERSION MOZ_CONSTEXPR
|
||||
operator DestinationType() const {
|
||||
return DestinationType(mValue);
|
||||
}
|
||||
|
||||
MOZ_CONSTEXPR bool operator !() const { return !bool(mValue); }
|
||||
|
||||
#ifndef MOZ_HAVE_CXX11_STRONG_ENUMS
|
||||
// This get() method is used to implement a constructor in the
|
||||
// non-c++11 fallback path for MOZ_BEGIN_ENUM_CLASS, taking a
|
||||
// CastableTypedEnumResult. If we try to implement it using the
|
||||
// above conversion operator E(), then at least clang 3.3
|
||||
// (when forced to take the non-c++11 fallback path) compiles
|
||||
// this constructor to an infinite recursion. So we introduce this
|
||||
// get() method, that does exactly the same as the conversion operator,
|
||||
// to work around this.
|
||||
MOZ_CONSTEXPR E get() const { return mValue; }
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // mozilla_TypedEnumInternal_h
|
|
@ -61,6 +61,8 @@ EXPORTS.mozilla = [
|
|||
'TemplateLib.h',
|
||||
'ThreadLocal.h',
|
||||
'TypedEnum.h',
|
||||
'TypedEnumBits.h',
|
||||
'TypedEnumInternal.h',
|
||||
'Types.h',
|
||||
'TypeTraits.h',
|
||||
'Vector.h',
|
||||
|
|
|
@ -3,38 +3,568 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/TypedEnum.h"
|
||||
#include "mozilla/TypedEnumBits.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// A rough feature check for is_literal_type. Not very carefully checked.
|
||||
// Feel free to amend as needed.
|
||||
// We leave ANDROID out because it's using stlport which doesn't have std::is_literal_type.
|
||||
#if __cplusplus >= 201103L && !defined(ANDROID)
|
||||
# if defined(__clang__)
|
||||
/*
|
||||
* Per Clang documentation, "Note that marketing version numbers should not
|
||||
* be used to check for language features, as different vendors use different
|
||||
* numbering schemes. Instead, use the feature checking macros."
|
||||
*/
|
||||
# ifndef __has_extension
|
||||
# define __has_extension __has_feature /* compatibility, for older versions of clang */
|
||||
# endif
|
||||
# if __has_extension(is_literal) && __has_include(<type_traits>)
|
||||
# define MOZ_HAVE_IS_LITERAL
|
||||
# endif
|
||||
# elif defined(__GNUC__)
|
||||
# if defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
# if MOZ_GCC_VERSION_AT_LEAST(4, 6, 0)
|
||||
# define MOZ_HAVE_IS_LITERAL
|
||||
# endif
|
||||
# endif
|
||||
# elif defined(_MSC_VER)
|
||||
# if _MSC_VER >= 1700
|
||||
# define MOZ_HAVE_IS_LITERAL
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_HAVE_IS_LITERAL
|
||||
#include <type_traits>
|
||||
template<typename T>
|
||||
void
|
||||
RequireLiteralType()
|
||||
{
|
||||
static_assert(std::is_literal_type<T>::value, "Expected a literal type");
|
||||
}
|
||||
#else // not MOZ_HAVE_IS_LITERAL
|
||||
template<typename T>
|
||||
void
|
||||
RequireLiteralType()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
RequireLiteralType(const T&)
|
||||
{
|
||||
RequireLiteralType<T>();
|
||||
}
|
||||
|
||||
MOZ_BEGIN_ENUM_CLASS(AutoEnum)
|
||||
A,
|
||||
B
|
||||
B = -3,
|
||||
C
|
||||
MOZ_END_ENUM_CLASS(AutoEnum)
|
||||
|
||||
|
||||
MOZ_BEGIN_ENUM_CLASS(CharEnum, char)
|
||||
A,
|
||||
B
|
||||
B = 3,
|
||||
C
|
||||
MOZ_END_ENUM_CLASS(CharEnum)
|
||||
|
||||
MOZ_BEGIN_ENUM_CLASS(AutoEnumBitField)
|
||||
A = 0x10,
|
||||
B = 0x20,
|
||||
C
|
||||
MOZ_END_ENUM_CLASS(AutoEnumBitField)
|
||||
|
||||
MOZ_BEGIN_ENUM_CLASS(CharEnumBitField, char)
|
||||
A = 0x10,
|
||||
B,
|
||||
C = 0x40
|
||||
MOZ_END_ENUM_CLASS(CharEnumBitField)
|
||||
|
||||
struct Nested
|
||||
{
|
||||
MOZ_BEGIN_NESTED_ENUM_CLASS(AutoEnum)
|
||||
C
|
||||
A,
|
||||
B,
|
||||
C = -1
|
||||
MOZ_END_NESTED_ENUM_CLASS(AutoEnum)
|
||||
|
||||
MOZ_BEGIN_NESTED_ENUM_CLASS(CharEnum, char)
|
||||
D = 4,
|
||||
E
|
||||
A = 4,
|
||||
B,
|
||||
C = 1
|
||||
MOZ_END_NESTED_ENUM_CLASS(CharEnum)
|
||||
|
||||
MOZ_BEGIN_NESTED_ENUM_CLASS(AutoEnumBitField)
|
||||
A,
|
||||
B = 0x20,
|
||||
C
|
||||
MOZ_END_NESTED_ENUM_CLASS(AutoEnumBitField)
|
||||
|
||||
MOZ_BEGIN_NESTED_ENUM_CLASS(CharEnumBitField, char)
|
||||
A = 1,
|
||||
B = 1,
|
||||
C = 1
|
||||
MOZ_END_NESTED_ENUM_CLASS(CharEnumBitField)
|
||||
};
|
||||
|
||||
// Simply check that this compiles.
|
||||
const AutoEnum autoEnum = AutoEnum::A;
|
||||
const CharEnum charEnum = CharEnum::B;
|
||||
const Nested::AutoEnum nestedAutoEnum = Nested::AutoEnum::C;
|
||||
const Nested::CharEnum nestedCharEnum = Nested::CharEnum::D;
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(AutoEnumBitField)
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(CharEnumBitField)
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(Nested::AutoEnumBitField)
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(Nested::CharEnumBitField)
|
||||
|
||||
#define MAKE_STANDARD_BITFIELD_FOR_TYPE(IntType) \
|
||||
MOZ_BEGIN_ENUM_CLASS(BitFieldFor_##IntType, IntType) \
|
||||
A = 1, \
|
||||
B = 2, \
|
||||
C = 4, \
|
||||
MOZ_END_ENUM_CLASS(BitFieldFor_##IntType) \
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(BitFieldFor_##IntType)
|
||||
|
||||
MAKE_STANDARD_BITFIELD_FOR_TYPE(int8_t)
|
||||
MAKE_STANDARD_BITFIELD_FOR_TYPE(uint8_t)
|
||||
MAKE_STANDARD_BITFIELD_FOR_TYPE(int16_t)
|
||||
MAKE_STANDARD_BITFIELD_FOR_TYPE(uint16_t)
|
||||
MAKE_STANDARD_BITFIELD_FOR_TYPE(int32_t)
|
||||
MAKE_STANDARD_BITFIELD_FOR_TYPE(uint32_t)
|
||||
MAKE_STANDARD_BITFIELD_FOR_TYPE(int64_t)
|
||||
MAKE_STANDARD_BITFIELD_FOR_TYPE(uint64_t)
|
||||
MAKE_STANDARD_BITFIELD_FOR_TYPE(char)
|
||||
typedef signed char signed_char;
|
||||
MAKE_STANDARD_BITFIELD_FOR_TYPE(signed_char)
|
||||
typedef unsigned char unsigned_char;
|
||||
MAKE_STANDARD_BITFIELD_FOR_TYPE(unsigned_char)
|
||||
MAKE_STANDARD_BITFIELD_FOR_TYPE(short)
|
||||
typedef unsigned short unsigned_short;
|
||||
MAKE_STANDARD_BITFIELD_FOR_TYPE(unsigned_short)
|
||||
MAKE_STANDARD_BITFIELD_FOR_TYPE(int)
|
||||
typedef unsigned int unsigned_int;
|
||||
MAKE_STANDARD_BITFIELD_FOR_TYPE(unsigned_int)
|
||||
MAKE_STANDARD_BITFIELD_FOR_TYPE(long)
|
||||
typedef unsigned long unsigned_long;
|
||||
MAKE_STANDARD_BITFIELD_FOR_TYPE(unsigned_long)
|
||||
typedef long long long_long;
|
||||
MAKE_STANDARD_BITFIELD_FOR_TYPE(long_long)
|
||||
typedef unsigned long long unsigned_long_long;
|
||||
MAKE_STANDARD_BITFIELD_FOR_TYPE(unsigned_long_long)
|
||||
|
||||
#undef MAKE_STANDARD_BITFIELD_FOR_TYPE
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
TestNonConvertibilityForOneType()
|
||||
{
|
||||
using mozilla::IsConvertible;
|
||||
|
||||
#if defined(MOZ_HAVE_CXX11_STRONG_ENUMS) && defined(MOZ_HAVE_EXPLICIT_CONVERSION)
|
||||
static_assert(!IsConvertible<T, bool>::value, "should not be convertible");
|
||||
static_assert(!IsConvertible<T, int>::value, "should not be convertible");
|
||||
static_assert(!IsConvertible<T, uint64_t>::value, "should not be convertible");
|
||||
#endif
|
||||
|
||||
static_assert(!IsConvertible<bool, T>::value, "should not be convertible");
|
||||
static_assert(!IsConvertible<int, T>::value, "should not be convertible");
|
||||
static_assert(!IsConvertible<uint64_t, T>::value, "should not be convertible");
|
||||
}
|
||||
|
||||
template<typename TypedEnum>
|
||||
void
|
||||
TestTypedEnumBasics()
|
||||
{
|
||||
const TypedEnum a = TypedEnum::A;
|
||||
int unused = int(a);
|
||||
(void) unused;
|
||||
RequireLiteralType(TypedEnum::A);
|
||||
RequireLiteralType(a);
|
||||
TestNonConvertibilityForOneType<TypedEnum>();
|
||||
}
|
||||
|
||||
// Op wraps a bitwise binary operator, passed as a char template parameter,
|
||||
// and applies it to its arguments (t1, t2). For example,
|
||||
//
|
||||
// Op<'|'>(t1, t2)
|
||||
//
|
||||
// is the same as
|
||||
//
|
||||
// t1 | t2.
|
||||
//
|
||||
template<char o, typename T1, typename T2>
|
||||
auto Op(const T1& t1, const T2& t2)
|
||||
-> decltype(t1 | t2) // See the static_assert's below --- the return type
|
||||
// depends solely on the operands type, not on the
|
||||
// choice of operation.
|
||||
{
|
||||
using mozilla::IsSame;
|
||||
static_assert(IsSame<decltype(t1 | t2), decltype(t1 & t2)>::value,
|
||||
"binary ops should have the same result type");
|
||||
static_assert(IsSame<decltype(t1 | t2), decltype(t1 ^ t2)>::value,
|
||||
"binary ops should have the same result type");
|
||||
|
||||
static_assert(o == '|' ||
|
||||
o == '&' ||
|
||||
o == '^', "unexpected operator character");
|
||||
|
||||
return o == '|' ? t1 | t2
|
||||
: o == '&' ? t1 & t2
|
||||
: t1 ^ t2;
|
||||
}
|
||||
|
||||
// OpAssign wraps a bitwise binary operator, passed as a char template
|
||||
// parameter, and applies the corresponding compound-assignment operator to its
|
||||
// arguments (t1, t2). For example,
|
||||
//
|
||||
// OpAssign<'|'>(t1, t2)
|
||||
//
|
||||
// is the same as
|
||||
//
|
||||
// t1 |= t2.
|
||||
//
|
||||
template<char o, typename T1, typename T2>
|
||||
T1& OpAssign(T1& t1, const T2& t2)
|
||||
{
|
||||
static_assert(o == '|' ||
|
||||
o == '&' ||
|
||||
o == '^', "unexpected operator character");
|
||||
|
||||
switch (o) {
|
||||
case '|': return t1 |= t2;
|
||||
case '&': return t1 &= t2;
|
||||
case '^': return t1 ^= t2;
|
||||
default: MOZ_CRASH();
|
||||
}
|
||||
}
|
||||
|
||||
// Tests a single binary bitwise operator, using a single set of three operands.
|
||||
// The operations tested are:
|
||||
//
|
||||
// result = t1 Op t2;
|
||||
// result Op= t3;
|
||||
//
|
||||
// Where Op is the operator specified by the char template parameter 'o' and can
|
||||
// be any of '|', '&', '^'.
|
||||
//
|
||||
// Note that the operands t1, t2, t3 are intentionally passed with free types
|
||||
// (separate template parameters for each) because their type may actually be
|
||||
// different from TypedEnum:
|
||||
// 1) Their type could be CastableTypedEnumResult<TypedEnum> if they are
|
||||
// the result of a bitwise operation themselves;
|
||||
// 2) In the non-c++11 legacy path, the type of enum values is also
|
||||
// different from TypedEnum.
|
||||
//
|
||||
template<typename TypedEnum, char o, typename T1, typename T2, typename T3>
|
||||
void TestBinOp(const T1& t1, const T2& t2, const T3& t3)
|
||||
{
|
||||
typedef typename mozilla::detail::UnsignedIntegerTypeForEnum<TypedEnum>::Type
|
||||
UnsignedIntegerType;
|
||||
|
||||
// Part 1:
|
||||
// Test the bitwise binary operator i.e.
|
||||
// result = t1 Op t2;
|
||||
auto result = Op<o>(t1, t2);
|
||||
|
||||
typedef decltype(result) ResultType;
|
||||
|
||||
RequireLiteralType<ResultType>();
|
||||
TestNonConvertibilityForOneType<ResultType>();
|
||||
|
||||
UnsignedIntegerType unsignedIntegerResult
|
||||
= Op<o>(UnsignedIntegerType(t1), UnsignedIntegerType(t2));
|
||||
|
||||
MOZ_RELEASE_ASSERT(unsignedIntegerResult == UnsignedIntegerType(result));
|
||||
MOZ_RELEASE_ASSERT(unsignedIntegerResult == UnsignedIntegerType(TypedEnum(result)));
|
||||
MOZ_RELEASE_ASSERT((!unsignedIntegerResult) == (!result));
|
||||
MOZ_RELEASE_ASSERT((!!unsignedIntegerResult) == (!!result));
|
||||
MOZ_RELEASE_ASSERT(bool(unsignedIntegerResult) == bool(result));
|
||||
|
||||
// Part 2:
|
||||
// Test the compound-assignment operator, i.e.
|
||||
// result Op= t3;
|
||||
TypedEnum newResult = result;
|
||||
OpAssign<o>(newResult, t3);
|
||||
UnsignedIntegerType unsignedIntegerNewResult = unsignedIntegerResult;
|
||||
OpAssign<o>(unsignedIntegerNewResult, UnsignedIntegerType(t3));
|
||||
MOZ_RELEASE_ASSERT(unsignedIntegerNewResult == UnsignedIntegerType(newResult));
|
||||
|
||||
// Part 3:
|
||||
// Test additional boolean operators that we unfortunately had to add to
|
||||
// CastableTypedEnumResult at some point to please some compiler,
|
||||
// even though bool convertibility should have been enough.
|
||||
MOZ_RELEASE_ASSERT(result == TypedEnum(result));
|
||||
MOZ_RELEASE_ASSERT(!(result != TypedEnum(result)));
|
||||
MOZ_RELEASE_ASSERT((result && true) == bool(result));
|
||||
MOZ_RELEASE_ASSERT((result && false) == false);
|
||||
MOZ_RELEASE_ASSERT((true && result) == bool(result));
|
||||
MOZ_RELEASE_ASSERT((false && result && false) == false);
|
||||
MOZ_RELEASE_ASSERT((result || false) == bool(result));
|
||||
MOZ_RELEASE_ASSERT((result || true) == true);
|
||||
MOZ_RELEASE_ASSERT((false || result) == bool(result));
|
||||
MOZ_RELEASE_ASSERT((true || result) == true);
|
||||
}
|
||||
|
||||
// Similar to TestBinOp but testing the unary ~ operator.
|
||||
template<typename TypedEnum, typename T>
|
||||
void TestTilde(const T& t)
|
||||
{
|
||||
typedef typename mozilla::detail::UnsignedIntegerTypeForEnum<TypedEnum>::Type
|
||||
UnsignedIntegerType;
|
||||
|
||||
auto result = ~t;
|
||||
|
||||
typedef decltype(result) ResultType;
|
||||
|
||||
RequireLiteralType<ResultType>();
|
||||
TestNonConvertibilityForOneType<ResultType>();
|
||||
|
||||
UnsignedIntegerType unsignedIntegerResult = ~(UnsignedIntegerType(t));
|
||||
|
||||
MOZ_RELEASE_ASSERT(unsignedIntegerResult == UnsignedIntegerType(result));
|
||||
MOZ_RELEASE_ASSERT(unsignedIntegerResult == UnsignedIntegerType(TypedEnum(result)));
|
||||
MOZ_RELEASE_ASSERT((!unsignedIntegerResult) == (!result));
|
||||
MOZ_RELEASE_ASSERT((!!unsignedIntegerResult) == (!!result));
|
||||
MOZ_RELEASE_ASSERT(bool(unsignedIntegerResult) == bool(result));
|
||||
}
|
||||
|
||||
// Helper dispatching a given triple of operands to all operator-specific
|
||||
// testing functions.
|
||||
template<typename TypedEnum, typename T1, typename T2, typename T3>
|
||||
void TestAllOpsForGivenOperands(const T1& t1, const T2& t2, const T3& t3)
|
||||
{
|
||||
TestBinOp<TypedEnum, '|'>(t1, t2, t3);
|
||||
TestBinOp<TypedEnum, '&'>(t1, t2, t3);
|
||||
TestBinOp<TypedEnum, '^'>(t1, t2, t3);
|
||||
TestTilde<TypedEnum>(t1);
|
||||
}
|
||||
|
||||
// Helper building various triples of operands using a given operator,
|
||||
// and testing all operators with them.
|
||||
template<typename TypedEnum, char o>
|
||||
void TestAllOpsForOperandsBuiltUsingGivenOp()
|
||||
{
|
||||
// The type of enum values like TypedEnum::A may be different from
|
||||
// TypedEnum. That is the case in the legacy non-C++11 path. We want to
|
||||
// ensure good test coverage even when these two types are distinct.
|
||||
// To that effect, we have both 'auto' typed variables, preserving the
|
||||
// original type of enum values, and 'plain' typed variables, that
|
||||
// are plain TypedEnum's.
|
||||
|
||||
const TypedEnum a_plain = TypedEnum::A;
|
||||
const TypedEnum b_plain = TypedEnum::B;
|
||||
const TypedEnum c_plain = TypedEnum::C;
|
||||
|
||||
auto a_auto = TypedEnum::A;
|
||||
auto b_auto = TypedEnum::B;
|
||||
auto c_auto = TypedEnum::C;
|
||||
|
||||
auto ab_plain = Op<o>(a_plain, b_plain);
|
||||
auto bc_plain = Op<o>(b_plain, c_plain);
|
||||
auto ab_auto = Op<o>(a_auto, b_auto);
|
||||
auto bc_auto = Op<o>(b_auto, c_auto);
|
||||
|
||||
// On each row below, we pass a triple of operands. Keep in mind that this
|
||||
// is going to be received as (t1, t2, t3) and the actual tests performed
|
||||
// will be of the form
|
||||
//
|
||||
// result = t1 Op t2;
|
||||
// result Op= t3;
|
||||
//
|
||||
// For this reason, we carefully ensure that the values of (t1, t2)
|
||||
// systematically cover all types of such pairs; to limit complexity,
|
||||
// we are not so careful with t3, and we just try to pass t3's
|
||||
// that may lead to nontrivial bitwise operations.
|
||||
TestAllOpsForGivenOperands<TypedEnum>(a_plain, b_plain, c_plain);
|
||||
TestAllOpsForGivenOperands<TypedEnum>(a_plain, bc_plain, b_auto);
|
||||
TestAllOpsForGivenOperands<TypedEnum>(ab_plain, c_plain, a_plain);
|
||||
TestAllOpsForGivenOperands<TypedEnum>(ab_plain, bc_plain, a_auto);
|
||||
|
||||
TestAllOpsForGivenOperands<TypedEnum>(a_plain, b_auto, c_plain);
|
||||
TestAllOpsForGivenOperands<TypedEnum>(a_plain, bc_auto, b_auto);
|
||||
TestAllOpsForGivenOperands<TypedEnum>(ab_plain, c_auto, a_plain);
|
||||
TestAllOpsForGivenOperands<TypedEnum>(ab_plain, bc_auto, a_auto);
|
||||
|
||||
TestAllOpsForGivenOperands<TypedEnum>(a_auto, b_plain, c_plain);
|
||||
TestAllOpsForGivenOperands<TypedEnum>(a_auto, bc_plain, b_auto);
|
||||
TestAllOpsForGivenOperands<TypedEnum>(ab_auto, c_plain, a_plain);
|
||||
TestAllOpsForGivenOperands<TypedEnum>(ab_auto, bc_plain, a_auto);
|
||||
|
||||
TestAllOpsForGivenOperands<TypedEnum>(a_auto, b_auto, c_plain);
|
||||
TestAllOpsForGivenOperands<TypedEnum>(a_auto, bc_auto, b_auto);
|
||||
TestAllOpsForGivenOperands<TypedEnum>(ab_auto, c_auto, a_plain);
|
||||
TestAllOpsForGivenOperands<TypedEnum>(ab_auto, bc_auto, a_auto);
|
||||
}
|
||||
|
||||
// Tests all bitwise operations on a given TypedEnum bitfield.
|
||||
template<typename TypedEnum>
|
||||
void
|
||||
TestTypedEnumBitField()
|
||||
{
|
||||
TestTypedEnumBasics<TypedEnum>();
|
||||
|
||||
TestAllOpsForOperandsBuiltUsingGivenOp<TypedEnum, '|'>();
|
||||
TestAllOpsForOperandsBuiltUsingGivenOp<TypedEnum, '&'>();
|
||||
TestAllOpsForOperandsBuiltUsingGivenOp<TypedEnum, '^'>();
|
||||
}
|
||||
|
||||
// Checks that enum bitwise expressions have the same non-convertibility properties as
|
||||
// c++11 enum classes do, i.e. not implicitly convertible to anything
|
||||
// (though *explicitly* convertible).
|
||||
void TestNoConversionsBetweenUnrelatedTypes()
|
||||
{
|
||||
using mozilla::IsConvertible;
|
||||
|
||||
// Two typed enum classes having the same underlying integer type, to ensure that
|
||||
// we would catch bugs accidentally allowing conversions in that case.
|
||||
typedef CharEnumBitField T1;
|
||||
typedef Nested::CharEnumBitField T2;
|
||||
|
||||
static_assert(!IsConvertible<T1, T2>::value,
|
||||
"should not be convertible");
|
||||
static_assert(!IsConvertible<T1, decltype(T2::A)>::value,
|
||||
"should not be convertible");
|
||||
static_assert(!IsConvertible<T1, decltype(T2::A | T2::B)>::value,
|
||||
"should not be convertible");
|
||||
|
||||
static_assert(!IsConvertible<decltype(T1::A), T2>::value,
|
||||
"should not be convertible");
|
||||
static_assert(!IsConvertible<decltype(T1::A), decltype(T2::A)>::value,
|
||||
"should not be convertible");
|
||||
static_assert(!IsConvertible<decltype(T1::A), decltype(T2::A | T2::B)>::value,
|
||||
"should not be convertible");
|
||||
|
||||
// The following are #ifdef MOZ_HAVE_EXPLICIT_CONVERSION because
|
||||
// without support for explicit conversion operators, we can't easily have these
|
||||
// bad conversions completely removed. They still do fail to compile in practice,
|
||||
// but not in a way that we can static_assert on.
|
||||
#ifdef MOZ_HAVE_EXPLICIT_CONVERSION
|
||||
static_assert(!IsConvertible<decltype(T1::A | T1::B), T2>::value,
|
||||
"should not be convertible");
|
||||
static_assert(!IsConvertible<decltype(T1::A | T1::B), decltype(T2::A)>::value,
|
||||
"should not be convertible");
|
||||
static_assert(!IsConvertible<decltype(T1::A | T1::B), decltype(T2::A | T2::B)>::value,
|
||||
"should not be convertible");
|
||||
#endif
|
||||
}
|
||||
|
||||
MOZ_BEGIN_ENUM_CLASS(Int8EnumWithHighBits, int8_t)
|
||||
A = 0x20,
|
||||
B = 0x40
|
||||
MOZ_END_ENUM_CLASS(Int8EnumWithHighBits)
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(Int8EnumWithHighBits)
|
||||
|
||||
MOZ_BEGIN_ENUM_CLASS(Uint8EnumWithHighBits, uint8_t)
|
||||
A = 0x40,
|
||||
B = 0x80
|
||||
MOZ_END_ENUM_CLASS(Uint8EnumWithHighBits)
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(Uint8EnumWithHighBits)
|
||||
|
||||
MOZ_BEGIN_ENUM_CLASS(Int16EnumWithHighBits, int16_t)
|
||||
A = 0x2000,
|
||||
B = 0x4000
|
||||
MOZ_END_ENUM_CLASS(Int16EnumWithHighBits)
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(Int16EnumWithHighBits)
|
||||
|
||||
MOZ_BEGIN_ENUM_CLASS(Uint16EnumWithHighBits, uint16_t)
|
||||
A = 0x4000,
|
||||
B = 0x8000
|
||||
MOZ_END_ENUM_CLASS(Uint16EnumWithHighBits)
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(Uint16EnumWithHighBits)
|
||||
|
||||
MOZ_BEGIN_ENUM_CLASS(Int32EnumWithHighBits, int32_t)
|
||||
A = 0x20000000,
|
||||
B = 0x40000000
|
||||
MOZ_END_ENUM_CLASS(Int32EnumWithHighBits)
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(Int32EnumWithHighBits)
|
||||
|
||||
MOZ_BEGIN_ENUM_CLASS(Uint32EnumWithHighBits, uint32_t)
|
||||
A = 0x40000000u,
|
||||
B = 0x80000000u
|
||||
MOZ_END_ENUM_CLASS(Uint32EnumWithHighBits)
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(Uint32EnumWithHighBits)
|
||||
|
||||
MOZ_BEGIN_ENUM_CLASS(Int64EnumWithHighBits, int64_t)
|
||||
A = 0x2000000000000000ll,
|
||||
B = 0x4000000000000000ll
|
||||
MOZ_END_ENUM_CLASS(Int64EnumWithHighBits)
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(Int64EnumWithHighBits)
|
||||
|
||||
MOZ_BEGIN_ENUM_CLASS(Uint64EnumWithHighBits, uint64_t)
|
||||
A = 0x4000000000000000ull,
|
||||
B = 0x8000000000000000ull
|
||||
MOZ_END_ENUM_CLASS(Uint64EnumWithHighBits)
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(Uint64EnumWithHighBits)
|
||||
|
||||
// Checks that we don't accidentally truncate high bits by coercing to the wrong
|
||||
// integer type internally when implementing bitwise ops.
|
||||
template<typename EnumType, typename IntType>
|
||||
void TestIsNotTruncated()
|
||||
{
|
||||
EnumType a = EnumType::A;
|
||||
EnumType b = EnumType::B;
|
||||
MOZ_RELEASE_ASSERT(IntType(a));
|
||||
MOZ_RELEASE_ASSERT(IntType(b));
|
||||
MOZ_RELEASE_ASSERT(a | EnumType::B);
|
||||
MOZ_RELEASE_ASSERT(a | b);
|
||||
MOZ_RELEASE_ASSERT(EnumType::A | EnumType::B);
|
||||
EnumType c = EnumType::A | EnumType::B;
|
||||
MOZ_RELEASE_ASSERT(IntType(c));
|
||||
MOZ_RELEASE_ASSERT(c & c);
|
||||
MOZ_RELEASE_ASSERT(c | c);
|
||||
MOZ_RELEASE_ASSERT(c == (EnumType::A | EnumType::B));
|
||||
MOZ_RELEASE_ASSERT(a != (EnumType::A | EnumType::B));
|
||||
MOZ_RELEASE_ASSERT(b != (EnumType::A | EnumType::B));
|
||||
MOZ_RELEASE_ASSERT(c & EnumType::A);
|
||||
MOZ_RELEASE_ASSERT(c & EnumType::B);
|
||||
EnumType d = EnumType::A;
|
||||
d |= EnumType::B;
|
||||
MOZ_RELEASE_ASSERT(d == c);
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
TestTypedEnumBasics<AutoEnum>();
|
||||
TestTypedEnumBasics<CharEnum>();
|
||||
TestTypedEnumBasics<Nested::AutoEnum>();
|
||||
TestTypedEnumBasics<Nested::CharEnum>();
|
||||
|
||||
TestTypedEnumBitField<AutoEnumBitField>();
|
||||
TestTypedEnumBitField<CharEnumBitField>();
|
||||
TestTypedEnumBitField<Nested::AutoEnumBitField>();
|
||||
TestTypedEnumBitField<Nested::CharEnumBitField>();
|
||||
|
||||
TestTypedEnumBitField<BitFieldFor_uint8_t>();
|
||||
TestTypedEnumBitField<BitFieldFor_int8_t>();
|
||||
TestTypedEnumBitField<BitFieldFor_uint16_t>();
|
||||
TestTypedEnumBitField<BitFieldFor_int16_t>();
|
||||
TestTypedEnumBitField<BitFieldFor_uint32_t>();
|
||||
TestTypedEnumBitField<BitFieldFor_int32_t>();
|
||||
TestTypedEnumBitField<BitFieldFor_uint64_t>();
|
||||
TestTypedEnumBitField<BitFieldFor_int64_t>();
|
||||
TestTypedEnumBitField<BitFieldFor_char>();
|
||||
TestTypedEnumBitField<BitFieldFor_signed_char>();
|
||||
TestTypedEnumBitField<BitFieldFor_unsigned_char>();
|
||||
TestTypedEnumBitField<BitFieldFor_short>();
|
||||
TestTypedEnumBitField<BitFieldFor_unsigned_short>();
|
||||
TestTypedEnumBitField<BitFieldFor_int>();
|
||||
TestTypedEnumBitField<BitFieldFor_unsigned_int>();
|
||||
TestTypedEnumBitField<BitFieldFor_long>();
|
||||
TestTypedEnumBitField<BitFieldFor_unsigned_long>();
|
||||
TestTypedEnumBitField<BitFieldFor_long_long>();
|
||||
TestTypedEnumBitField<BitFieldFor_unsigned_long_long>();
|
||||
|
||||
TestNoConversionsBetweenUnrelatedTypes();
|
||||
|
||||
TestIsNotTruncated<Int8EnumWithHighBits, int8_t>();
|
||||
TestIsNotTruncated<Int16EnumWithHighBits, int16_t>();
|
||||
TestIsNotTruncated<Int32EnumWithHighBits, int32_t>();
|
||||
TestIsNotTruncated<Int64EnumWithHighBits, int64_t>();
|
||||
TestIsNotTruncated<Uint8EnumWithHighBits, uint8_t>();
|
||||
TestIsNotTruncated<Uint16EnumWithHighBits, uint16_t>();
|
||||
TestIsNotTruncated<Uint32EnumWithHighBits, uint32_t>();
|
||||
TestIsNotTruncated<Uint64EnumWithHighBits, uint64_t>();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
NSPR_4_10_5_BETA3
|
||||
NSPR_4_10_5_BETA4
|
||||
|
|
|
@ -10,4 +10,3 @@
|
|||
*/
|
||||
|
||||
#error "Do not include this header file."
|
||||
|
||||
|
|
|
@ -3128,8 +3128,7 @@ else
|
|||
fi
|
||||
|
||||
if test -z "$SKIP_COMPILER_CHECKS"; then
|
||||
|
||||
if test "$target" != "$host" -o -n "$CROSS_COMPILE"; then
|
||||
if test "$target" != "$host"; then
|
||||
echo "cross compiling from $host to $target"
|
||||
cross_compiling=yes
|
||||
|
||||
|
@ -3984,7 +3983,7 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
|
|||
ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
|
||||
|
||||
if test "$target" != "$host" -o -n "$CROSS_COMPILE"; then
|
||||
if test "$target" != "$host"; then
|
||||
if test -n "$USE_CPLUS"; then
|
||||
for ac_prog in $CXX "${target_alias}-g++" "${target}-g++"
|
||||
do
|
||||
|
|
|
@ -570,11 +570,7 @@ if test -z "$SKIP_COMPILER_CHECKS"; then
|
|||
dnl ========================================================
|
||||
dnl Checks for compilers.
|
||||
dnl ========================================================
|
||||
|
||||
dnl Explicitly honor $CROSS_COMPILE to allow cross-compiling
|
||||
dnl between toolkits on the same architecture, as when
|
||||
dnl targeting the iOS Simulator from OS X.
|
||||
if test "$target" != "$host" -o -n "$CROSS_COMPILE"; then
|
||||
if test "$target" != "$host"; then
|
||||
echo "cross compiling from $host to $target"
|
||||
cross_compiling=yes
|
||||
|
||||
|
@ -613,7 +609,7 @@ dnl and before invoking AC_TRY_COMPILE (which requires AC_PROG_CC).
|
|||
AC_PROG_CC
|
||||
|
||||
dnl Reenter the conditional blocks after invoking AC_PROG_CC.
|
||||
if test "$target" != "$host" -o -n "$CROSS_COMPILE"; then
|
||||
if test "$target" != "$host"; then
|
||||
if test -n "$USE_CPLUS"; then
|
||||
AC_CHECK_PROGS(CXX, $CXX "${target_alias}-g++" "${target}-g++", echo)
|
||||
unset ac_cv_prog_CXX
|
||||
|
|
|
@ -514,7 +514,7 @@ error2:
|
|||
pthread_mutex_destroy(&mon->lock);
|
||||
error1:
|
||||
PR_Free(mon);
|
||||
PR_SetError(PR_OPERATION_NOT_SUPPORTED_ERROR, 0);
|
||||
_PR_MD_MAP_DEFAULT_ERROR(rv);
|
||||
return NULL;
|
||||
} /* PR_NewMonitor */
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
NSS_3_16_1_BETA2
|
||||
NSS_3_16_1_BETA3
|
||||
|
|
|
@ -10,3 +10,4 @@
|
|||
*/
|
||||
|
||||
#error "Do not include this header file."
|
||||
|
||||
|
|
|
@ -135,9 +135,9 @@ else
|
|||
ifdef BUILD_OPT
|
||||
OPTIMIZER += -Ox # maximum optimization for freebl
|
||||
endif
|
||||
# The Intel AES assembly code requires Visual C++ 2010 (10.0). The _xgetbv
|
||||
# compiler intrinsic function requires Visual C++ 2010 (10.0) SP1.
|
||||
ifeq ($(_MSC_VER_GE_10SP1),1)
|
||||
# The Intel AES assembly code requires Visual C++ 2010.
|
||||
# if $(_MSC_VER) >= 1600 (Visual C++ 2010)
|
||||
ifeq ($(firstword $(sort $(_MSC_VER) 1600)),1600)
|
||||
DEFINES += -DUSE_HW_AES -DINTEL_GCM
|
||||
ASFILES += intel-aes-x86-masm.asm intel-gcm-x86-masm.asm
|
||||
EXTRA_SRCS += intel-gcm-wrap.c
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* blapi.h - public prototypes for the crypto library
|
||||
* blapi.h - public prototypes for the freebl library
|
||||
*
|
||||
* 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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* blapii.h - private data structures and prototypes for the crypto library
|
||||
* blapii.h - private data structures and prototypes for the freebl library
|
||||
*
|
||||
* 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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* blapit.h - public data structures for the crypto library
|
||||
* blapit.h - public data structures for the freebl library
|
||||
*
|
||||
* 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
|
||||
|
|
|
@ -972,13 +972,24 @@ AESContext * AES_AllocateContext(void)
|
|||
/*
|
||||
* Adapted from the example code in "How to detect New Instruction support in
|
||||
* the 4th generation Intel Core processor family" by Max Locktyukhin.
|
||||
*
|
||||
* XGETBV:
|
||||
* Reads an extended control register (XCR) specified by ECX into EDX:EAX.
|
||||
*/
|
||||
static PRBool
|
||||
check_xcr0_ymm()
|
||||
{
|
||||
PRUint32 xcr0;
|
||||
#if defined(_MSC_VER)
|
||||
#if defined(_M_IX86)
|
||||
__asm {
|
||||
mov ecx, 0
|
||||
xgetbv
|
||||
mov xcr0, eax
|
||||
}
|
||||
#else
|
||||
xcr0 = (PRUint32)_xgetbv(0); /* Requires VS2010 SP1 or later. */
|
||||
#endif
|
||||
#else
|
||||
__asm__ ("xgetbv" : "=a" (xcr0) : "c" (0) : "%edx");
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* secdig.h - public prototypes for digestinfos from the util lib
|
||||
* secdig.h - public prototypes for digest-info functions
|
||||
*
|
||||
* 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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* secdigt.h - public data structures for digestinfos from the util lib.
|
||||
* secdigt.h - public data structures for digest-info objects
|
||||
*
|
||||
* 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
|
||||
|
@ -23,6 +23,4 @@ struct SGNDigestInfoStr {
|
|||
};
|
||||
typedef struct SGNDigestInfoStr SGNDigestInfo;
|
||||
|
||||
|
||||
|
||||
#endif /* _SECDIGT_H_ */
|
||||
|
|
Загрузка…
Ссылка в новой задаче