mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge mozilla-central and mozilla-inbound
This commit is contained in:
commit
c0ac5a1f10
@ -74,7 +74,7 @@ static const NSString* AXRoles [] = {
|
||||
NSAccessibilityGroupRole, // ROLE_CELL
|
||||
@"AXLink", // ROLE_LINK. 10.4+ the attr first define in SDK 10.4, so we define it here too. ROLE_LINK
|
||||
@"AXHelpTag", // ROLE_HELPBALLOON
|
||||
NSAccessibilityUnknownRole, // ROLE_CHARACTER. unusued on OS X
|
||||
NSAccessibilityUnknownRole, // ROLE_CHARACTER. unused on OS X
|
||||
NSAccessibilityListRole, // ROLE_LIST
|
||||
NSAccessibilityRowRole, // ROLE_LISTITEM
|
||||
NSAccessibilityOutlineRole, // ROLE_OUTLINE
|
||||
|
@ -932,6 +932,8 @@ xpicleanup@BIN_SUFFIX@
|
||||
#endif
|
||||
components/txEXSLTRegExFunctions.js
|
||||
components/Weave.js
|
||||
components/Webapps.js
|
||||
components/Webapps.manifest
|
||||
components/WebContentConverter.js
|
||||
defaults/autoconfig/platform.js
|
||||
defaults/autoconfig/prefcalls.js
|
||||
@ -1057,6 +1059,7 @@ xpicleanup@BIN_SUFFIX@
|
||||
modules/tabview/AllTabs.jsm
|
||||
modules/tabview/groups.jsm
|
||||
modules/tabview/utils.jsm
|
||||
modules/Webapps.jsm
|
||||
modules/WindowDraggingUtils.jsm
|
||||
#ifdef XP_WIN
|
||||
modules/WindowsJumpLists.jsm
|
||||
@ -1147,6 +1150,7 @@ xpicleanup@BIN_SUFFIX@
|
||||
components/directory.xpt
|
||||
components/docshell.xpt
|
||||
components/dom.xpt
|
||||
components/dom_apps.xpt
|
||||
components/dom_base.xpt
|
||||
#ifdef MOZ_B2G_RIL
|
||||
components/dom_telephony.xpt
|
||||
|
@ -1999,6 +1999,7 @@ nsresult nsHTMLMediaElement::InitializeDecoderAsClone(nsMediaDecoder* aOriginal)
|
||||
LOG(PR_LOG_DEBUG, ("%p Cloned decoder %p from %p", this, decoder.get(), aOriginal));
|
||||
|
||||
if (!decoder->Init(this)) {
|
||||
LOG(PR_LOG_DEBUG, ("%p Failed to init cloned decoder %p", this, decoder.get()));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
@ -2010,6 +2011,7 @@ nsresult nsHTMLMediaElement::InitializeDecoderAsClone(nsMediaDecoder* aOriginal)
|
||||
|
||||
nsMediaStream* stream = originalStream->CloneData(decoder);
|
||||
if (!stream) {
|
||||
LOG(PR_LOG_DEBUG, ("%p Failed to cloned stream for decoder %p", this, decoder.get()));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
@ -2017,6 +2019,7 @@ nsresult nsHTMLMediaElement::InitializeDecoderAsClone(nsMediaDecoder* aOriginal)
|
||||
|
||||
nsresult rv = decoder->Load(stream, nsnull, aOriginal);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(PR_LOG_DEBUG, ("%p Failed to load decoder/stream for decoder %p", this, decoder.get()));
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -193,6 +193,7 @@ nsresult nsBuiltinDecoder::Load(nsMediaStream* aStream,
|
||||
|
||||
nsresult rv = aStream->Open(aStreamListener);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(PR_LOG_DEBUG, ("%p Failed to open stream!", this));
|
||||
delete aStream;
|
||||
return rv;
|
||||
}
|
||||
@ -245,6 +246,7 @@ nsresult nsBuiltinDecoder::ScheduleStateMachineThread()
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
|
||||
NS_ASSERTION(mDecoderStateMachine,
|
||||
"Must have state machine to start state machine thread");
|
||||
NS_ENSURE_STATE(mDecoderStateMachine);
|
||||
|
||||
if (mShuttingDown)
|
||||
return NS_OK;
|
||||
@ -258,6 +260,7 @@ nsresult nsBuiltinDecoder::Play()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
NS_ASSERTION(mDecoderStateMachine != nsnull, "Should have state machine.");
|
||||
nsresult res = ScheduleStateMachineThread();
|
||||
NS_ENSURE_SUCCESS(res,res);
|
||||
if (mPlayState == PLAY_STATE_SEEKING) {
|
||||
@ -832,29 +835,19 @@ void nsBuiltinDecoder::ChangeState(PlayState aState)
|
||||
}
|
||||
|
||||
mPlayState = aState;
|
||||
switch (aState) {
|
||||
case PLAY_STATE_PAUSED:
|
||||
/* No action needed */
|
||||
break;
|
||||
case PLAY_STATE_PLAYING:
|
||||
mDecoderStateMachine->Play();
|
||||
break;
|
||||
case PLAY_STATE_SEEKING:
|
||||
mDecoderStateMachine->Seek(mRequestedSeekTime);
|
||||
mRequestedSeekTime = -1.0;
|
||||
break;
|
||||
case PLAY_STATE_LOADING:
|
||||
/* No action needed */
|
||||
break;
|
||||
case PLAY_STATE_START:
|
||||
/* No action needed */
|
||||
break;
|
||||
case PLAY_STATE_ENDED:
|
||||
/* No action needed */
|
||||
break;
|
||||
case PLAY_STATE_SHUTDOWN:
|
||||
/* No action needed */
|
||||
break;
|
||||
if (mDecoderStateMachine) {
|
||||
switch (aState) {
|
||||
case PLAY_STATE_PLAYING:
|
||||
mDecoderStateMachine->Play();
|
||||
break;
|
||||
case PLAY_STATE_SEEKING:
|
||||
mDecoderStateMachine->Seek(mRequestedSeekTime);
|
||||
mRequestedSeekTime = -1.0;
|
||||
break;
|
||||
default:
|
||||
/* No action needed */
|
||||
break;
|
||||
}
|
||||
}
|
||||
mReentrantMonitor.NotifyAll();
|
||||
}
|
||||
@ -973,7 +966,9 @@ void nsBuiltinDecoder::Resume(bool aForceBuffering)
|
||||
}
|
||||
if (aForceBuffering) {
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
mDecoderStateMachine->StartBuffering();
|
||||
if (mDecoderStateMachine) {
|
||||
mDecoderStateMachine->StartBuffering();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "mozilla/mozalloc.h"
|
||||
#include "VideoUtils.h"
|
||||
#include "nsTimeRanges.h"
|
||||
#include "nsDeque.h"
|
||||
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/StdInt.h"
|
||||
@ -229,6 +230,17 @@ public:
|
||||
return mStateMachineThread;
|
||||
}
|
||||
|
||||
// Requests that a decode thread be created for aStateMachine. The thread
|
||||
// may be created immediately, or after some delay, once a thread becomes
|
||||
// available. The request can be cancelled using CancelCreateDecodeThread().
|
||||
// It's the callers responsibility to not call this more than once for any
|
||||
// given state machine.
|
||||
nsresult RequestCreateDecodeThread(nsBuiltinDecoderStateMachine* aStateMachine);
|
||||
|
||||
// Cancels a request made by RequestCreateDecodeThread to create a decode
|
||||
// thread for aStateMachine.
|
||||
nsresult CancelCreateDecodeThread(nsBuiltinDecoderStateMachine* aStateMachine);
|
||||
|
||||
// Maximum number of active decode threads allowed. When more
|
||||
// than this number are active the thread creation will fail.
|
||||
static const PRUint32 MAX_DECODE_THREADS = 25;
|
||||
@ -238,16 +250,17 @@ public:
|
||||
// call with any other monitor held to avoid deadlock.
|
||||
PRUint32 GetDecodeThreadCount();
|
||||
|
||||
// Keep track of the fact that a decode thread was created.
|
||||
// Call on any thread. Holds the internal monitor so don't
|
||||
// call with any other monitor held to avoid deadlock.
|
||||
void NoteDecodeThreadCreated();
|
||||
|
||||
// Keep track of the fact that a decode thread was destroyed.
|
||||
// Call on any thread. Holds the internal monitor so don't
|
||||
// call with any other monitor held to avoid deadlock.
|
||||
void NoteDecodeThreadDestroyed();
|
||||
|
||||
#ifdef DEBUG
|
||||
// Returns true if aStateMachine has a pending request for a
|
||||
// decode thread.
|
||||
bool IsQueued(nsBuiltinDecoderStateMachine* aStateMachine);
|
||||
#endif
|
||||
|
||||
private:
|
||||
// Holds global instance of StateMachineTracker.
|
||||
// Writable on main thread only.
|
||||
@ -271,6 +284,10 @@ private:
|
||||
// only, read from the decoder threads. Synchronized via
|
||||
// the mMonitor.
|
||||
nsIThread* mStateMachineThread;
|
||||
|
||||
// Queue of state machines waiting for decode threads. Entries at the front
|
||||
// get their threads first.
|
||||
nsDeque mPending;
|
||||
};
|
||||
|
||||
StateMachineTracker* StateMachineTracker::mInstance = nsnull;
|
||||
@ -296,7 +313,23 @@ void StateMachineTracker::EnsureGlobalStateMachine()
|
||||
}
|
||||
mStateMachineCount++;
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
bool StateMachineTracker::IsQueued(nsBuiltinDecoderStateMachine* aStateMachine)
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mMonitor);
|
||||
PRInt32 size = mPending.GetSize();
|
||||
for (int i = 0; i < size; ++i) {
|
||||
nsBuiltinDecoderStateMachine* m =
|
||||
static_cast<nsBuiltinDecoderStateMachine*>(mPending.ObjectAt(i));
|
||||
if (m == aStateMachine) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
void StateMachineTracker::CleanupGlobalStateMachine()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
|
||||
@ -305,6 +338,7 @@ void StateMachineTracker::CleanupGlobalStateMachine()
|
||||
mStateMachineCount--;
|
||||
if (mStateMachineCount == 0) {
|
||||
LOG(PR_LOG_DEBUG, ("Destroying media state machine thread"));
|
||||
NS_ASSERTION(mPending.GetSize() == 0, "Shouldn't all requests be handled by now?");
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mMonitor);
|
||||
nsCOMPtr<nsIRunnable> event = new ShutdownThreadEvent(mStateMachineThread);
|
||||
@ -319,16 +353,22 @@ void StateMachineTracker::CleanupGlobalStateMachine()
|
||||
}
|
||||
}
|
||||
|
||||
void StateMachineTracker::NoteDecodeThreadCreated()
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mMonitor);
|
||||
++mDecodeThreadCount;
|
||||
}
|
||||
|
||||
void StateMachineTracker::NoteDecodeThreadDestroyed()
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mMonitor);
|
||||
--mDecodeThreadCount;
|
||||
while (mDecodeThreadCount < MAX_DECODE_THREADS && mPending.GetSize() > 0) {
|
||||
nsBuiltinDecoderStateMachine* m =
|
||||
static_cast<nsBuiltinDecoderStateMachine*>(mPending.PopFront());
|
||||
nsresult rv;
|
||||
{
|
||||
ReentrantMonitorAutoExit exitMon(mMonitor);
|
||||
rv = m->StartDecodeThread();
|
||||
}
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
++mDecodeThreadCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PRUint32 StateMachineTracker::GetDecodeThreadCount()
|
||||
@ -337,6 +377,45 @@ PRUint32 StateMachineTracker::GetDecodeThreadCount()
|
||||
return mDecodeThreadCount;
|
||||
}
|
||||
|
||||
nsresult StateMachineTracker::CancelCreateDecodeThread(nsBuiltinDecoderStateMachine* aStateMachine) {
|
||||
ReentrantMonitorAutoEnter mon(mMonitor);
|
||||
PRInt32 size = mPending.GetSize();
|
||||
for (PRInt32 i = 0; i < size; ++i) {
|
||||
void* m = static_cast<nsBuiltinDecoderStateMachine*>(mPending.ObjectAt(i));
|
||||
if (m == aStateMachine) {
|
||||
mPending.RemoveObjectAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
NS_ASSERTION(!IsQueued(aStateMachine), "State machine should no longer have queued request.");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult StateMachineTracker::RequestCreateDecodeThread(nsBuiltinDecoderStateMachine* aStateMachine)
|
||||
{
|
||||
NS_ENSURE_STATE(aStateMachine);
|
||||
ReentrantMonitorAutoEnter mon(mMonitor);
|
||||
if (mPending.GetSize() > 0 || mDecodeThreadCount + 1 >= MAX_DECODE_THREADS) {
|
||||
// If there's already state machines in the queue, or we've exceeded the
|
||||
// limit, append the state machine to the queue of state machines waiting
|
||||
// for a decode thread. This ensures state machines already waiting get
|
||||
// their threads first.
|
||||
mPending.Push(aStateMachine);
|
||||
return NS_OK;
|
||||
}
|
||||
nsresult rv;
|
||||
{
|
||||
ReentrantMonitorAutoExit exitMon(mMonitor);
|
||||
rv = aStateMachine->StartDecodeThread();
|
||||
}
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
++mDecodeThreadCount;
|
||||
}
|
||||
NS_ASSERTION(mDecodeThreadCount <= MAX_DECODE_THREADS,
|
||||
"Should keep to thread limit!");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsBuiltinDecoderStateMachine::nsBuiltinDecoderStateMachine(nsBuiltinDecoder* aDecoder,
|
||||
nsBuiltinDecoderReader* aReader,
|
||||
bool aRealTime) :
|
||||
@ -367,6 +446,7 @@ nsBuiltinDecoderStateMachine::nsBuiltinDecoderStateMachine(nsBuiltinDecoder* aDe
|
||||
mDispatchedRunEvent(false),
|
||||
mDecodeThreadWaiting(false),
|
||||
mRealTime(aRealTime),
|
||||
mRequestedNewDecodeThread(false),
|
||||
mEventManager(aDecoder)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsBuiltinDecoderStateMachine);
|
||||
@ -386,6 +466,10 @@ nsBuiltinDecoderStateMachine::~nsBuiltinDecoderStateMachine()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
|
||||
MOZ_COUNT_DTOR(nsBuiltinDecoderStateMachine);
|
||||
NS_ASSERTION(!StateMachineTracker::Instance().IsQueued(this),
|
||||
"Should not have a pending request for a new decode thread");
|
||||
NS_ASSERTION(!mRequestedNewDecodeThread,
|
||||
"Should not have (or flagged) a pending request for a new decode thread");
|
||||
if (mTimer)
|
||||
mTimer->Cancel();
|
||||
mTimer = nsnull;
|
||||
@ -1191,6 +1275,14 @@ void nsBuiltinDecoderStateMachine::StopDecodeThread()
|
||||
{
|
||||
NS_ASSERTION(OnStateMachineThread(), "Should be on state machine thread.");
|
||||
mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
|
||||
if (mRequestedNewDecodeThread) {
|
||||
// We've requested that the decode be created, but it hasn't been yet.
|
||||
// Cancel that request.
|
||||
NS_ASSERTION(!mDecodeThread,
|
||||
"Shouldn't have a decode thread until after request processed");
|
||||
StateMachineTracker::Instance().CancelCreateDecodeThread(this);
|
||||
mRequestedNewDecodeThread = false;
|
||||
}
|
||||
mStopDecodeThread = true;
|
||||
mDecoder->GetReentrantMonitor().NotifyAll();
|
||||
if (mDecodeThread) {
|
||||
@ -1203,6 +1295,10 @@ void nsBuiltinDecoderStateMachine::StopDecodeThread()
|
||||
mDecodeThread = nsnull;
|
||||
mDecodeThreadIdle = false;
|
||||
}
|
||||
NS_ASSERTION(!mRequestedNewDecodeThread,
|
||||
"Any pending requests for decode threads must be canceled and unflagged");
|
||||
NS_ASSERTION(!StateMachineTracker::Instance().IsQueued(this),
|
||||
"Any pending requests for decode threads must be canceled");
|
||||
}
|
||||
|
||||
void nsBuiltinDecoderStateMachine::StopAudioThread()
|
||||
@ -1221,52 +1317,68 @@ void nsBuiltinDecoderStateMachine::StopAudioThread()
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsBuiltinDecoderStateMachine::StartDecodeThread()
|
||||
nsBuiltinDecoderStateMachine::ScheduleDecodeThread()
|
||||
{
|
||||
NS_ASSERTION(OnStateMachineThread(), "Should be on state machine thread.");
|
||||
mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
|
||||
PRUint32 count = 0;
|
||||
bool created = false;
|
||||
{
|
||||
ReentrantMonitorAutoExit mon(mDecoder->GetReentrantMonitor());
|
||||
count = StateMachineTracker::Instance().GetDecodeThreadCount();
|
||||
}
|
||||
|
||||
|
||||
mStopDecodeThread = false;
|
||||
if ((mDecodeThread && !mDecodeThreadIdle) || mState >= DECODER_STATE_COMPLETED)
|
||||
if (mState >= DECODER_STATE_COMPLETED) {
|
||||
return NS_OK;
|
||||
|
||||
if (!mDecodeThread && count > StateMachineTracker::MAX_DECODE_THREADS) {
|
||||
// Have to run one iteration of the state machine loop to ensure the
|
||||
// shutdown state is processed.
|
||||
ScheduleStateMachine();
|
||||
mState = DECODER_STATE_SHUTDOWN;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (!mDecodeThread) {
|
||||
nsresult rv = NS_NewThread(getter_AddRefs(mDecodeThread),
|
||||
nsnull,
|
||||
MEDIA_THREAD_STACK_SIZE);
|
||||
if (NS_FAILED(rv)) {
|
||||
// Have to run one iteration of the state machine loop to ensure the
|
||||
// shutdown state is processed.
|
||||
ScheduleStateMachine();
|
||||
mState = DECODER_STATE_SHUTDOWN;
|
||||
return rv;
|
||||
if (mDecodeThread) {
|
||||
NS_ASSERTION(!mRequestedNewDecodeThread,
|
||||
"Shouldn't have requested new decode thread when we have a decode thread");
|
||||
// We already have a decode thread...
|
||||
if (mDecodeThreadIdle) {
|
||||
// ... and it's not been shutdown yet, wake it up.
|
||||
nsCOMPtr<nsIRunnable> event =
|
||||
NS_NewRunnableMethod(this, &nsBuiltinDecoderStateMachine::DecodeThreadRun);
|
||||
mDecodeThread->Dispatch(event, NS_DISPATCH_NORMAL);
|
||||
mDecodeThreadIdle = false;
|
||||
}
|
||||
created = true;
|
||||
return NS_OK;
|
||||
} else if (!mRequestedNewDecodeThread) {
|
||||
// We don't already have a decode thread, request a new one.
|
||||
mRequestedNewDecodeThread = true;
|
||||
ReentrantMonitorAutoExit mon(mDecoder->GetReentrantMonitor());
|
||||
StateMachineTracker::Instance().RequestCreateDecodeThread(this);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsBuiltinDecoderStateMachine::StartDecodeThread()
|
||||
{
|
||||
NS_ASSERTION(StateMachineTracker::Instance().GetDecodeThreadCount() <
|
||||
StateMachineTracker::MAX_DECODE_THREADS,
|
||||
"Should not have reached decode thread limit");
|
||||
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
NS_ASSERTION(!StateMachineTracker::Instance().IsQueued(this),
|
||||
"Should not already have a pending request for a new decode thread.");
|
||||
NS_ASSERTION(OnStateMachineThread(), "Should be on state machine thread.");
|
||||
NS_ASSERTION(!mDecodeThread, "Should not have decode thread yet");
|
||||
NS_ASSERTION(mRequestedNewDecodeThread, "Should have requested this...");
|
||||
|
||||
mRequestedNewDecodeThread = false;
|
||||
|
||||
nsresult rv = NS_NewThread(getter_AddRefs(mDecodeThread),
|
||||
nsnull,
|
||||
MEDIA_THREAD_STACK_SIZE);
|
||||
if (NS_FAILED(rv)) {
|
||||
// Give up, report error to media element.
|
||||
nsCOMPtr<nsIRunnable> event =
|
||||
NS_NewRunnableMethod(mDecoder, &nsBuiltinDecoder::DecodeError);
|
||||
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRunnable> event =
|
||||
NS_NewRunnableMethod(this, &nsBuiltinDecoderStateMachine::DecodeThreadRun);
|
||||
mDecodeThread->Dispatch(event, NS_DISPATCH_NORMAL);
|
||||
mDecodeThreadIdle = false;
|
||||
|
||||
if (created) {
|
||||
ReentrantMonitorAutoExit mon(mDecoder->GetReentrantMonitor());
|
||||
StateMachineTracker::Instance().NoteDecodeThreadCreated();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1282,6 +1394,7 @@ nsBuiltinDecoderStateMachine::StartAudioThread()
|
||||
nsnull,
|
||||
MEDIA_THREAD_STACK_SIZE);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(PR_LOG_DEBUG, ("%p Changed state to SHUTDOWN because failed to create audio thread", mDecoder.get()));
|
||||
mState = DECODER_STATE_SHUTDOWN;
|
||||
return rv;
|
||||
}
|
||||
@ -1639,7 +1752,7 @@ nsresult nsBuiltinDecoderStateMachine::RunStateMachine()
|
||||
|
||||
case DECODER_STATE_DECODING_METADATA: {
|
||||
// Ensure we have a decode thread to decode metadata.
|
||||
return StartDecodeThread();
|
||||
return ScheduleDecodeThread();
|
||||
}
|
||||
|
||||
case DECODER_STATE_DECODING: {
|
||||
@ -1663,7 +1776,7 @@ nsresult nsBuiltinDecoderStateMachine::RunStateMachine()
|
||||
|
||||
// We're playing and/or our decode buffers aren't full. Ensure we have
|
||||
// an active decode thread.
|
||||
if (NS_FAILED(StartDecodeThread())) {
|
||||
if (NS_FAILED(ScheduleDecodeThread())) {
|
||||
NS_WARNING("Failed to start media decode thread!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
@ -1728,7 +1841,7 @@ nsresult nsBuiltinDecoderStateMachine::RunStateMachine()
|
||||
|
||||
case DECODER_STATE_SEEKING: {
|
||||
// Ensure we have a decode thread to perform the seek.
|
||||
return StartDecodeThread();
|
||||
return ScheduleDecodeThread();
|
||||
}
|
||||
|
||||
case DECODER_STATE_COMPLETED: {
|
||||
|
@ -253,6 +253,12 @@ public:
|
||||
// earlier, in which case the request is discarded.
|
||||
nsresult ScheduleStateMachine(PRInt64 aUsecs);
|
||||
|
||||
// Creates and starts a new decode thread. Don't call this directly,
|
||||
// request a new decode thread by calling
|
||||
// StateMachineTracker::RequestCreateDecodeThread().
|
||||
// The decoder monitor must not be held. Called on the state machine thread.
|
||||
nsresult StartDecodeThread();
|
||||
|
||||
// Timer function to implement ScheduleStateMachine(aUsecs).
|
||||
void TimeoutExpired();
|
||||
|
||||
@ -352,7 +358,8 @@ protected:
|
||||
// here. Called on the audio thread.
|
||||
PRUint32 PlayFromAudioQueue(PRUint64 aFrameOffset, PRUint32 aChannels);
|
||||
|
||||
// Stops the decode thread. The decoder monitor must be held with exactly
|
||||
// Stops the decode thread, and if we have a pending request for a new
|
||||
// decode thread it is canceled. The decoder monitor must be held with exactly
|
||||
// one lock count. Called on the state machine thread.
|
||||
void StopDecodeThread();
|
||||
|
||||
@ -360,9 +367,11 @@ protected:
|
||||
// one lock count. Called on the state machine thread.
|
||||
void StopAudioThread();
|
||||
|
||||
// Starts the decode thread. The decoder monitor must be held with exactly
|
||||
// one lock count. Called on the state machine thread.
|
||||
nsresult StartDecodeThread();
|
||||
// Ensures the decode thread is running if it already exists, or requests
|
||||
// a new decode thread be started if there currently is no decode thread.
|
||||
// The decoder monitor must be held with exactly one lock count. Called on
|
||||
// the state machine thread.
|
||||
nsresult ScheduleDecodeThread();
|
||||
|
||||
// Starts the audio thread. The decoder monitor must be held with exactly
|
||||
// one lock count. Called on the state machine thread.
|
||||
@ -625,6 +634,10 @@ protected:
|
||||
|
||||
// True is we are decoding a realtime stream, like a camera stream
|
||||
bool mRealTime;
|
||||
|
||||
// True if we've requested a new decode thread, but it has not yet been
|
||||
// created. Synchronized by the decoder monitor.
|
||||
bool mRequestedNewDecodeThread;
|
||||
|
||||
PRUint32 mBufferingWait;
|
||||
PRInt64 mLowDataThresholdUsecs;
|
||||
|
@ -150,6 +150,7 @@ _TEST_FILES = \
|
||||
test_source_write.html \
|
||||
test_standalone.html \
|
||||
test_timeupdate_small_files.html \
|
||||
test_too_many_elements.html \
|
||||
test_volume.html \
|
||||
test_video_to_canvas.html \
|
||||
use_large_cache.js \
|
||||
|
@ -8,4 +8,4 @@ load 493915-1.html
|
||||
skip-if(Android) load 495794-1.html
|
||||
load 492286-1.xhtml
|
||||
load 576612-1.html
|
||||
load 691096-1.html
|
||||
skip-if(Android) load 691096-1.html # Android sound API can't handle playing large number of sounds at once.
|
||||
|
@ -5,9 +5,9 @@
|
||||
// These are small test files, good for just seeing if something loads. We
|
||||
// really only need one test file per backend here.
|
||||
var gSmallTests = [
|
||||
{ name:"small-shot.ogg", type:"audio/ogg", duration:0.276 },
|
||||
{ name:"r11025_s16_c1.wav", type:"audio/x-wav", duration:1.0 },
|
||||
{ name:"320x240.ogv", type:"video/ogg", width:320, height:240, duration:0.233 },
|
||||
{ name:"small-shot.ogg", type:"audio/ogg", duration:0.276 },
|
||||
{ name:"seek.webm", type:"video/webm", duration:3.966 },
|
||||
{ name:"bogus.duh", type:"bogus/duh" }
|
||||
];
|
||||
@ -299,6 +299,14 @@ function getPlayableVideo(candidates) {
|
||||
return null;
|
||||
}
|
||||
|
||||
function getPlayableAudio(candidates) {
|
||||
var v = document.createElement("audio");
|
||||
var resources = candidates.filter(function(x){return /^audio/.test(x.type) && v.canPlayType(x.type);});
|
||||
if (resources.length > 0)
|
||||
return resources[0];
|
||||
return null;
|
||||
}
|
||||
|
||||
// Number of tests to run in parallel. Warning: Each media element requires
|
||||
// at least 3 threads (4 on Linux), and on Linux each thread uses 10MB of
|
||||
// virtual address space. Beware!
|
||||
|
68
content/media/test/test_too_many_elements.html
Normal file
68
content/media/test/test_too_many_elements.html
Normal file
@ -0,0 +1,68 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=713381
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 713381</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="text/javascript" src="manifest.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=713381">Mozilla Bug 713381</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
|
||||
<p>Received loadeddata event for <span id="result">0</span> <span id="expected"></span>audio elements.</p>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 713381 **/
|
||||
|
||||
const num = 500;
|
||||
var loadeddata = 0;
|
||||
|
||||
var result = document.getElementById("result");
|
||||
document.getElementById("expected").innerHTML = " of " + num + " ";
|
||||
|
||||
var finish = function(testNum) {
|
||||
return function() {
|
||||
ok(true, "Received loadeddata event for instance " + testNum );
|
||||
loadeddata++;
|
||||
if (loadeddata == num) {
|
||||
ok(true, "Should receive loadeddata events for all " + num + " elements.");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var resource = getPlayableAudio(gSmallTests);
|
||||
|
||||
if (resource == null) {
|
||||
todo(false, "No types supported");
|
||||
} else {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
// Load the resource, and play it to ensure it's entirely downloaded.
|
||||
// Once it's played through, create a large number of audio elements which
|
||||
// are the same resource. These will share data with the other resource, and
|
||||
// so be really cheap to create.
|
||||
var res = new Audio(resource.name);
|
||||
res.addEventListener("ended",
|
||||
function() {
|
||||
for (var i=0; i<num; ++i) {
|
||||
var a = new Audio(resource.name);
|
||||
a.addEventListener("loadeddata", finish(i), false);
|
||||
}
|
||||
}, false);
|
||||
res.play();
|
||||
}
|
||||
|
||||
setInterval(function() { result.innerHTML = loadeddata; }, 1000);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -66,8 +66,13 @@ DIRS = \
|
||||
interfaces/notification \
|
||||
interfaces/svg \
|
||||
interfaces/smil \
|
||||
$(NULL)
|
||||
|
||||
ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
|
||||
DIRS += \
|
||||
interfaces/apps \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
DIRS += \
|
||||
base \
|
||||
|
@ -79,6 +79,11 @@ LOCAL_INCLUDES += -I$(topsrcdir)/dom/system/android \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),gonk)
|
||||
LOCAL_INCLUDES += -I$(topsrcdir)/dom/system/b2g \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
EXPORTS += nsGeoPositionIPCSerialiser.h
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
@ -88,6 +88,10 @@
|
||||
#include "AndroidLocationProvider.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
#include "GonkGPSGeolocationProvider.h"
|
||||
#endif
|
||||
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDocument.h"
|
||||
|
||||
@ -577,6 +581,13 @@ nsresult nsGeolocationService::Init()
|
||||
if (provider)
|
||||
mProviders.AppendObject(provider);
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
provider = GonkGPSGeolocationProvider::GetSingleton();
|
||||
if (provider)
|
||||
mProviders.AppendObject(provider);
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
185
dom/system/b2g/GonkGPSGeolocationProvider.cpp
Normal file
185
dom/system/b2g/GonkGPSGeolocationProvider.cpp
Normal file
@ -0,0 +1,185 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2012
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Kan-Ru Chen <kchen@mozilla.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <pthread.h>
|
||||
#include <hardware/gps.h>
|
||||
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsGeoPosition.h"
|
||||
#include "GonkGPSGeolocationProvider.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
NS_IMPL_ISUPPORTS1(GonkGPSGeolocationProvider, nsIGeolocationProvider)
|
||||
|
||||
GonkGPSGeolocationProvider* GonkGPSGeolocationProvider::sSingleton;
|
||||
|
||||
static void
|
||||
LocationCallback(GpsLocation* location)
|
||||
{
|
||||
nsRefPtr<GonkGPSGeolocationProvider> provider =
|
||||
GonkGPSGeolocationProvider::GetSingleton();
|
||||
nsCOMPtr<nsIGeolocationUpdate> callback = provider->GetLocationCallback();
|
||||
|
||||
if (!callback)
|
||||
return;
|
||||
|
||||
nsRefPtr<nsGeoPosition> somewhere = new nsGeoPosition(location->latitude,
|
||||
location->longitude,
|
||||
location->altitude,
|
||||
location->accuracy,
|
||||
location->accuracy,
|
||||
location->bearing,
|
||||
location->speed,
|
||||
location->timestamp);
|
||||
callback->Update(somewhere);
|
||||
}
|
||||
|
||||
typedef void *(*pthread_func)(void *);
|
||||
|
||||
/** Callback for creating a thread that can call into the JS codes.
|
||||
*/
|
||||
static pthread_t
|
||||
CreateThreadCallback(const char* name, void (*start)(void *), void* arg)
|
||||
{
|
||||
pthread_t thread;
|
||||
pthread_attr_t attr;
|
||||
|
||||
pthread_attr_init(&attr);
|
||||
|
||||
/* Unfortunately pthread_create and the callback disagreed on what
|
||||
* start function should return.
|
||||
*/
|
||||
pthread_create(&thread, &attr, reinterpret_cast<pthread_func>(start), arg);
|
||||
|
||||
return thread;
|
||||
}
|
||||
|
||||
static GpsCallbacks gCallbacks = {
|
||||
sizeof(GpsCallbacks),
|
||||
LocationCallback,
|
||||
NULL, /* StatusCallback */
|
||||
NULL, /* SvStatusCallback */
|
||||
NULL, /* NmeaCallback */
|
||||
NULL, /* SetCapabilitiesCallback */
|
||||
NULL, /* AcquireWakelockCallback */
|
||||
NULL, /* ReleaseWakelockCallback */
|
||||
CreateThreadCallback,
|
||||
};
|
||||
|
||||
GonkGPSGeolocationProvider::GonkGPSGeolocationProvider()
|
||||
: mStarted(false)
|
||||
{
|
||||
mGpsInterface = GetGPSInterface();
|
||||
}
|
||||
|
||||
GonkGPSGeolocationProvider::~GonkGPSGeolocationProvider()
|
||||
{
|
||||
Shutdown();
|
||||
sSingleton = NULL;
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<GonkGPSGeolocationProvider>
|
||||
GonkGPSGeolocationProvider::GetSingleton()
|
||||
{
|
||||
if (!sSingleton)
|
||||
sSingleton = new GonkGPSGeolocationProvider();
|
||||
|
||||
NS_ADDREF(sSingleton);
|
||||
return sSingleton;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIGeolocationUpdate>
|
||||
GonkGPSGeolocationProvider::GetLocationCallback()
|
||||
{
|
||||
nsCOMPtr<nsIGeolocationUpdate> callback = mLocationCallback;
|
||||
return callback.forget();
|
||||
}
|
||||
|
||||
const GpsInterface*
|
||||
GonkGPSGeolocationProvider::GetGPSInterface()
|
||||
{
|
||||
hw_module_t* module;
|
||||
|
||||
if (hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module))
|
||||
return NULL;
|
||||
|
||||
hw_device_t* device;
|
||||
if (module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device))
|
||||
return NULL;
|
||||
|
||||
gps_device_t* gps_device = (gps_device_t *)device;
|
||||
return gps_device->get_gps_interface(gps_device);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GonkGPSGeolocationProvider::Startup()
|
||||
{
|
||||
if (mStarted)
|
||||
return NS_OK;
|
||||
|
||||
NS_ENSURE_TRUE(mGpsInterface, NS_ERROR_FAILURE);
|
||||
|
||||
PRInt32 update = Preferences::GetInt("geo.default.update", 1000);
|
||||
|
||||
mGpsInterface->init(&gCallbacks);
|
||||
mGpsInterface->start();
|
||||
mGpsInterface->set_position_mode(GPS_POSITION_MODE_STANDALONE,
|
||||
GPS_POSITION_RECURRENCE_PERIODIC,
|
||||
update, 0, 0);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GonkGPSGeolocationProvider::Watch(nsIGeolocationUpdate* aCallback)
|
||||
{
|
||||
mLocationCallback = aCallback;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GonkGPSGeolocationProvider::Shutdown()
|
||||
{
|
||||
if (!mStarted)
|
||||
return NS_OK;
|
||||
|
||||
mGpsInterface->stop();
|
||||
mGpsInterface->cleanup();
|
||||
|
||||
return NS_OK;
|
||||
}
|
70
dom/system/b2g/GonkGPSGeolocationProvider.h
Normal file
70
dom/system/b2g/GonkGPSGeolocationProvider.h
Normal file
@ -0,0 +1,70 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2012
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Kan-Ru Chen <kchen@mozilla.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
#ifndef GonkGPSGeolocationProvider_h
|
||||
#define GonkGPSGeolocationProvider_h
|
||||
|
||||
#include <hardware/gps.h> // for GpsInterface
|
||||
#include "nsIGeolocationProvider.h"
|
||||
|
||||
class GonkGPSGeolocationProvider : public nsIGeolocationProvider
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIGEOLOCATIONPROVIDER
|
||||
|
||||
static already_AddRefed<GonkGPSGeolocationProvider> GetSingleton();
|
||||
|
||||
already_AddRefed<nsIGeolocationUpdate> GetLocationCallback();
|
||||
|
||||
private:
|
||||
|
||||
/* Client should use GetSingleton() to get the provider instance. */
|
||||
GonkGPSGeolocationProvider();
|
||||
GonkGPSGeolocationProvider(const GonkGPSGeolocationProvider &);
|
||||
GonkGPSGeolocationProvider & operator = (const GonkGPSGeolocationProvider &);
|
||||
~GonkGPSGeolocationProvider();
|
||||
|
||||
const GpsInterface* GetGPSInterface();
|
||||
|
||||
static GonkGPSGeolocationProvider* sSingleton;
|
||||
|
||||
bool mStarted;
|
||||
const GpsInterface* mGpsInterface;
|
||||
nsCOMPtr<nsIGeolocationUpdate> mLocationCallback;
|
||||
};
|
||||
|
||||
#endif /* GonkGPSGeolocationProvider_h */
|
@ -55,7 +55,10 @@ CPPSRCS = \
|
||||
$(NULL)
|
||||
|
||||
ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
|
||||
CPPSRCS += AudioManager.cpp
|
||||
CPPSRCS += \
|
||||
AudioManager.cpp \
|
||||
GonkGPSGeolocationProvider.cpp \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
XPIDLSRCS = \
|
||||
@ -65,6 +68,7 @@ XPIDLSRCS = \
|
||||
|
||||
LOCAL_INCLUDES = \
|
||||
-I$(topsrcdir)/dom/base \
|
||||
-I$(topsrcdir)/dom/src/geolocation \
|
||||
-I$(topsrcdir)/dom/telephony \
|
||||
-I$(topsrcdir)/dom/wifi \
|
||||
-I$(topsrcdir)/content/events/src \
|
||||
|
@ -14,8 +14,8 @@ SimpleTest.waitForFocus(function () opener.framesetWindowLoaded(window));
|
||||
<frame src="data:text/html,<html id='f7'><body id='framebody4'><input id='f8'><body></html>">
|
||||
</frameset>
|
||||
<noframes>
|
||||
<input id="unusued1"/>
|
||||
<input id="unusued2" tabindex="1"/>
|
||||
<input id="unused1"/>
|
||||
<input id="unused2" tabindex="1"/>
|
||||
</noframes>
|
||||
</frameset>
|
||||
|
||||
|
@ -116,6 +116,7 @@ DrawTargetCG::~DrawTargetCG()
|
||||
CGColorSpaceRelease(mColorSpace);
|
||||
if (mCg)
|
||||
CGContextRelease(mCg);
|
||||
free(mData);
|
||||
}
|
||||
|
||||
TemporaryRef<SourceSurface>
|
||||
@ -845,7 +846,6 @@ DrawTargetCG::Init(const IntSize &aSize, SurfaceFormat &)
|
||||
// XXX: currently we allocate ourselves so that we can easily return a gfxImageSurface
|
||||
// we might not need to later if once we don't need to support gfxImageSurface
|
||||
//XXX: currently Init implicitly clears, that can often be a waste of time
|
||||
// XXX: leaked
|
||||
mData = calloc(mSize.height * stride, 1);
|
||||
// XXX: what should we do if this fails?
|
||||
mCg = CGBitmapContextCreate (mData,
|
||||
|
@ -131,12 +131,19 @@ endif
|
||||
EXPORTS_NAMESPACES = gfxipc mozilla/layers
|
||||
EXPORTS_gfxipc = ShadowLayerUtils.h
|
||||
EXPORTS_mozilla/layers =\
|
||||
CompositorCocoaWidgetHelper.h \
|
||||
CompositorChild.h \
|
||||
CompositorParent.h \
|
||||
ShadowLayers.h \
|
||||
ShadowLayersChild.h \
|
||||
ShadowLayersParent.h \
|
||||
ShadowLayersManager.h \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS += \
|
||||
CompositorCocoaWidgetHelper.cpp \
|
||||
CompositorChild.cpp \
|
||||
CompositorParent.cpp \
|
||||
ShadowLayers.cpp \
|
||||
ShadowLayerChild.cpp \
|
||||
ShadowLayersChild.cpp \
|
||||
|
@ -50,7 +50,11 @@ SurfaceToTexture(ID3D10Device *aDevice,
|
||||
gfxASurface *aSurface,
|
||||
const gfxIntSize &aSize)
|
||||
{
|
||||
if (aSurface && aSurface->GetType() == gfxASurface::SurfaceTypeD2D) {
|
||||
if (!aSurface) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (aSurface->GetType() == gfxASurface::SurfaceTypeD2D) {
|
||||
void *data = aSurface->GetData(&gKeyD3D10Texture);
|
||||
if (data) {
|
||||
nsRefPtr<ID3D10Texture2D> texture = static_cast<ID3D10Texture2D*>(data);
|
||||
@ -67,7 +71,7 @@ SurfaceToTexture(ID3D10Device *aDevice,
|
||||
if (!imageSurface) {
|
||||
imageSurface = new gfxImageSurface(aSize,
|
||||
gfxASurface::ImageFormatARGB32);
|
||||
|
||||
|
||||
nsRefPtr<gfxContext> context = new gfxContext(imageSurface);
|
||||
context->SetSource(aSurface);
|
||||
context->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
@ -75,13 +79,13 @@ SurfaceToTexture(ID3D10Device *aDevice,
|
||||
}
|
||||
|
||||
D3D10_SUBRESOURCE_DATA data;
|
||||
|
||||
|
||||
CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
imageSurface->GetSize().width,
|
||||
imageSurface->GetSize().height,
|
||||
1, 1);
|
||||
desc.Usage = D3D10_USAGE_IMMUTABLE;
|
||||
|
||||
|
||||
data.pSysMem = imageSurface->Data();
|
||||
data.SysMemPitch = imageSurface->Stride();
|
||||
|
||||
|
93
gfx/layers/ipc/CompositorChild.cpp
Normal file
93
gfx/layers/ipc/CompositorChild.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set sw=2 ts=2 et tw=80 : */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Content App.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Benoit Girard <bgirard@mozilla.com>
|
||||
* Ali Juma <ajuma@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "CompositorChild.h"
|
||||
#include "CompositorParent.h"
|
||||
#include "LayerManagerOGL.h"
|
||||
#include "mozilla/layers/ShadowLayersChild.h"
|
||||
|
||||
using mozilla::layers::ShadowLayersChild;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
CompositorChild::CompositorChild(LayerManager *aLayerManager)
|
||||
: mLayerManager(aLayerManager)
|
||||
{
|
||||
MOZ_COUNT_CTOR(CompositorChild);
|
||||
}
|
||||
|
||||
CompositorChild::~CompositorChild()
|
||||
{
|
||||
MOZ_COUNT_DTOR(CompositorChild);
|
||||
}
|
||||
|
||||
void
|
||||
CompositorChild::Destroy()
|
||||
{
|
||||
mLayerManager = NULL;
|
||||
size_t numChildren = ManagedPLayersChild().Length();
|
||||
NS_ABORT_IF_FALSE(0 == numChildren || 1 == numChildren,
|
||||
"compositor must only have 0 or 1 layer forwarder");
|
||||
|
||||
if (numChildren) {
|
||||
ShadowLayersChild* layers =
|
||||
static_cast<ShadowLayersChild*>(ManagedPLayersChild()[0]);
|
||||
layers->Destroy();
|
||||
}
|
||||
SendStop();
|
||||
}
|
||||
|
||||
PLayersChild*
|
||||
CompositorChild::AllocPLayers(const LayersBackend &backend)
|
||||
{
|
||||
return new ShadowLayersChild();
|
||||
}
|
||||
|
||||
bool
|
||||
CompositorChild::DeallocPLayers(PLayersChild* actor)
|
||||
{
|
||||
delete actor;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
73
gfx/layers/ipc/CompositorChild.h
Normal file
73
gfx/layers/ipc/CompositorChild.h
Normal file
@ -0,0 +1,73 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set sw=4 ts=8 et tw=80 : */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Content App.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Benoit Girard <bgirard@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef mozilla_layers_CompositorChild_h
|
||||
#define mozilla_layers_CompositorChild_h
|
||||
|
||||
#include "mozilla/layers/PCompositorChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class LayerManager;
|
||||
class CompositorParent;
|
||||
|
||||
class CompositorChild : public PCompositorChild
|
||||
{
|
||||
NS_INLINE_DECL_REFCOUNTING(CompositorChild)
|
||||
public:
|
||||
CompositorChild(LayerManager *aLayerManager);
|
||||
virtual ~CompositorChild();
|
||||
|
||||
void Destroy();
|
||||
|
||||
protected:
|
||||
virtual PLayersChild* AllocPLayers(const LayersBackend &aBackend);
|
||||
virtual bool DeallocPLayers(PLayersChild *aChild);
|
||||
|
||||
private:
|
||||
nsRefPtr<LayerManager> mLayerManager;
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(CompositorChild);
|
||||
};
|
||||
|
||||
} // layers
|
||||
} // mozilla
|
||||
|
||||
#endif // mozilla_layers_CompositorChild_h
|
58
gfx/layers/ipc/CompositorCocoaWidgetHelper.cpp
Normal file
58
gfx/layers/ipc/CompositorCocoaWidgetHelper.cpp
Normal file
@ -0,0 +1,58 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=2 et tw=80 : */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Content App.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Benoit Girard <bgirard@mozilla.com>
|
||||
* Ali Juma <ajuma@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "CompositorParent.h"
|
||||
#include "CompositorCocoaWidgetHelper.h"
|
||||
#include "nsDebug.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
namespace compositor {
|
||||
|
||||
LayerManager*
|
||||
GetLayerManager(CompositorParent* aParent)
|
||||
{
|
||||
return aParent->GetLayerManager();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
63
gfx/layers/ipc/CompositorCocoaWidgetHelper.h
Normal file
63
gfx/layers/ipc/CompositorCocoaWidgetHelper.h
Normal file
@ -0,0 +1,63 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set sw=4 ts=8 et tw=80 : */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Content App.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Benoit Girard <bgirard@mozilla.com>
|
||||
* Ali Juma <ajuma@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef mozilla_layers_CompositorCocoaWidgetHelper_h
|
||||
#define mozilla_layers_CompositorCocoaWidgetHelper_h
|
||||
|
||||
// Note we can't include IPDL-generated headers here, since this file is being
|
||||
// used as a workaround for Bug 719036.
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class CompositorParent;
|
||||
class LayerManager;
|
||||
|
||||
namespace compositor {
|
||||
|
||||
// Needed when we cannot directly include CompositorParent.h since it includes
|
||||
// an IPDL-generated header (e.g. in widget/cocoa/nsChildView.mm; see Bug 719036).
|
||||
LayerManager* GetLayerManager(CompositorParent* aParent);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // mozilla_layers_CompositorCocoaWidgetHelper_h
|
||||
|
159
gfx/layers/ipc/CompositorParent.cpp
Normal file
159
gfx/layers/ipc/CompositorParent.cpp
Normal file
@ -0,0 +1,159 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set sw=2 ts=2 et tw=80 : */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Content App.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Benoit Girard <bgirard@mozilla.com>
|
||||
* Ali Juma <ajuma@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "CompositorParent.h"
|
||||
#include "ShadowLayersParent.h"
|
||||
#include "LayerManagerOGL.h"
|
||||
#include "nsIWidget.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
CompositorParent::CompositorParent(nsIWidget* aWidget)
|
||||
: mStopped(false), mWidget(aWidget)
|
||||
{
|
||||
MOZ_COUNT_CTOR(CompositorParent);
|
||||
}
|
||||
|
||||
CompositorParent::~CompositorParent()
|
||||
{
|
||||
MOZ_COUNT_DTOR(CompositorParent);
|
||||
}
|
||||
|
||||
void
|
||||
CompositorParent::Destroy()
|
||||
{
|
||||
NS_ABORT_IF_FALSE(ManagedPLayersParent().Length() == 0,
|
||||
"CompositorParent destroyed before managed PLayersParent");
|
||||
|
||||
// Ensure that the layer manager is destroyed on the compositor thread.
|
||||
mLayerManager = NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
CompositorParent::RecvStop()
|
||||
{
|
||||
mStopped = true;
|
||||
Destroy();
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CompositorParent::ScheduleComposition()
|
||||
{
|
||||
CancelableTask *composeTask = NewRunnableMethod(this, &CompositorParent::Composite);
|
||||
MessageLoop::current()->PostTask(FROM_HERE, composeTask);
|
||||
}
|
||||
|
||||
void
|
||||
CompositorParent::Composite()
|
||||
{
|
||||
if (mStopped || !mLayerManager) {
|
||||
return;
|
||||
}
|
||||
|
||||
mLayerManager->EndEmptyTransaction();
|
||||
}
|
||||
|
||||
// Go down shadow layer tree, setting properties to match their non-shadow
|
||||
// counterparts.
|
||||
static void
|
||||
SetShadowProperties(Layer* aLayer)
|
||||
{
|
||||
// FIXME: Bug 717688 -- Do these updates in ShadowLayersParent::RecvUpdate.
|
||||
ShadowLayer* shadow = aLayer->AsShadowLayer();
|
||||
shadow->SetShadowTransform(aLayer->GetTransform());
|
||||
shadow->SetShadowVisibleRegion(aLayer->GetVisibleRegion());
|
||||
shadow->SetShadowClipRect(aLayer->GetClipRect());
|
||||
|
||||
for (Layer* child = aLayer->GetFirstChild();
|
||||
child; child = child->GetNextSibling()) {
|
||||
SetShadowProperties(child);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CompositorParent::ShadowLayersUpdated()
|
||||
{
|
||||
const nsTArray<PLayersParent*>& shadowParents = ManagedPLayersParent();
|
||||
NS_ABORT_IF_FALSE(shadowParents.Length() <= 1,
|
||||
"can only support at most 1 ShadowLayersParent");
|
||||
if (shadowParents.Length()) {
|
||||
Layer* root = static_cast<ShadowLayersParent*>(shadowParents[0])->GetRoot();
|
||||
mLayerManager->SetRoot(root);
|
||||
SetShadowProperties(root);
|
||||
}
|
||||
ScheduleComposition();
|
||||
}
|
||||
|
||||
PLayersParent*
|
||||
CompositorParent::AllocPLayers(const LayersBackend &backendType)
|
||||
{
|
||||
if (backendType == LayerManager::LAYERS_OPENGL) {
|
||||
nsRefPtr<LayerManagerOGL> layerManager = new LayerManagerOGL(mWidget);
|
||||
mWidget = NULL;
|
||||
mLayerManager = layerManager;
|
||||
|
||||
if (!layerManager->Initialize()) {
|
||||
NS_ERROR("Failed to init OGL Layers");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ShadowLayerManager* slm = layerManager->AsShadowManager();
|
||||
if (!slm) {
|
||||
return NULL;
|
||||
}
|
||||
return new ShadowLayersParent(slm, this);
|
||||
} else {
|
||||
NS_ERROR("Unsupported backend selected for Async Compositor");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
CompositorParent::DeallocPLayers(PLayersParent* actor)
|
||||
{
|
||||
delete actor;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
88
gfx/layers/ipc/CompositorParent.h
Normal file
88
gfx/layers/ipc/CompositorParent.h
Normal file
@ -0,0 +1,88 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set sw=4 ts=8 et tw=80 : */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Content App.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Benoit Girard <bgirard@mozilla.com>
|
||||
* Ali Juma <ajuma@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef mozilla_layers_CompositorParent_h
|
||||
#define mozilla_layers_CompositorParent_h
|
||||
|
||||
#include "mozilla/layers/PCompositorParent.h"
|
||||
#include "mozilla/layers/PLayersParent.h"
|
||||
#include "ShadowLayersManager.h"
|
||||
|
||||
class nsIWidget;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class LayerManager;
|
||||
|
||||
class CompositorParent : public PCompositorParent,
|
||||
public ShadowLayersManager
|
||||
{
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorParent)
|
||||
public:
|
||||
CompositorParent(nsIWidget* aWidget);
|
||||
virtual ~CompositorParent();
|
||||
|
||||
virtual bool RecvStop() MOZ_OVERRIDE;
|
||||
|
||||
virtual void ShadowLayersUpdated() MOZ_OVERRIDE;
|
||||
void Destroy();
|
||||
|
||||
LayerManager* GetLayerManager() { return mLayerManager; }
|
||||
|
||||
protected:
|
||||
virtual PLayersParent* AllocPLayers(const LayersBackend &backendType);
|
||||
virtual bool DeallocPLayers(PLayersParent* aLayers);
|
||||
|
||||
private:
|
||||
void ScheduleComposition();
|
||||
void Composite();
|
||||
|
||||
nsRefPtr<LayerManager> mLayerManager;
|
||||
bool mStopped;
|
||||
nsIWidget* mWidget;
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(CompositorParent);
|
||||
};
|
||||
|
||||
} // layers
|
||||
} // mozilla
|
||||
|
||||
#endif // mozilla_layers_CompositorParent_h
|
71
gfx/layers/ipc/PCompositor.ipdl
Normal file
71
gfx/layers/ipc/PCompositor.ipdl
Normal file
@ -0,0 +1,71 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=8 et :
|
||||
*/
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at:
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Benoit Girard <bgirard@mozilla.com>
|
||||
* Ali Juma <ajuma@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
include protocol PLayers;
|
||||
|
||||
using mozilla::LayersBackend;
|
||||
using mozilla::null_t;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
/**
|
||||
* The PCompositor protocol is used to manage communication between
|
||||
* the main thread and the compositor thread context. It's primary
|
||||
* purpose is to manage the PLayers sub protocol.
|
||||
*/
|
||||
// This should really be 'sync', but we're using 'rpc' as a workaround
|
||||
// for Bug 716631.
|
||||
rpc protocol PCompositor
|
||||
{
|
||||
// A Compositor manages a single Layer Manager (PLayers)
|
||||
manages PLayers;
|
||||
|
||||
parent:
|
||||
|
||||
// Clean up in preparation for destruction.
|
||||
sync Stop();
|
||||
|
||||
sync PLayers(LayersBackend backend);
|
||||
};
|
||||
|
||||
} // layers
|
||||
} // mozilla
|
@ -38,7 +38,7 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
//include protocol PCompositor;
|
||||
include protocol PCompositor;
|
||||
include protocol PLayer;
|
||||
include protocol PRenderFrame;
|
||||
|
||||
@ -226,7 +226,7 @@ union EditReply {
|
||||
|
||||
|
||||
sync protocol PLayers {
|
||||
manager PRenderFrame /*or PCompositor or PMedia or PPlugin*/;
|
||||
manager PRenderFrame or PCompositor;
|
||||
manages PLayer;
|
||||
|
||||
parent:
|
||||
|
63
gfx/layers/ipc/ShadowLayersManager.h
Normal file
63
gfx/layers/ipc/ShadowLayersManager.h
Normal file
@ -0,0 +1,63 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set sw=4 ts=8 et tw=80 : */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Content App.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ali Juma <ajuma@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef mozilla_layers_ShadowLayersManager_h
|
||||
#define mozilla_layers_ShadowLayersManager_h
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace layout {
|
||||
class RenderFrameParent;
|
||||
}
|
||||
|
||||
namespace layers {
|
||||
|
||||
class CompositorParent;
|
||||
|
||||
class ShadowLayersManager
|
||||
{
|
||||
|
||||
public:
|
||||
virtual void ShadowLayersUpdated() = 0;
|
||||
};
|
||||
|
||||
} // layers
|
||||
} // mozilla
|
||||
|
||||
#endif // mozilla_layers_ShadowLayersManager_h
|
@ -47,6 +47,7 @@
|
||||
#include "mozilla/unused.h"
|
||||
|
||||
#include "mozilla/layout/RenderFrameParent.h"
|
||||
#include "CompositorParent.h"
|
||||
|
||||
#include "gfxSharedImageSurface.h"
|
||||
|
||||
@ -121,11 +122,11 @@ ShadowChild(const OpRemoveChild& op)
|
||||
|
||||
//--------------------------------------------------
|
||||
// ShadowLayersParent
|
||||
ShadowLayersParent::ShadowLayersParent(ShadowLayerManager* aManager)
|
||||
: mDestroyed(false)
|
||||
ShadowLayersParent::ShadowLayersParent(ShadowLayerManager* aManager,
|
||||
ShadowLayersManager* aLayersManager)
|
||||
: mLayerManager(aManager), mShadowLayersManager(aLayersManager), mDestroyed(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(ShadowLayersParent);
|
||||
mLayerManager = aManager;
|
||||
}
|
||||
|
||||
ShadowLayersParent::~ShadowLayersParent()
|
||||
@ -382,7 +383,7 @@ ShadowLayersParent::RecvUpdate(const InfallibleTArray<Edit>& cset,
|
||||
// other's buffer contents.
|
||||
ShadowLayerManager::PlatformSyncBeforeReplyUpdate();
|
||||
|
||||
Frame()->ShadowLayersUpdated();
|
||||
mShadowLayersManager->ShadowLayersUpdated();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -400,12 +401,6 @@ ShadowLayersParent::DeallocPLayer(PLayerParent* actor)
|
||||
return true;
|
||||
}
|
||||
|
||||
RenderFrameParent*
|
||||
ShadowLayersParent::Frame()
|
||||
{
|
||||
return static_cast<RenderFrameParent*>(Manager());
|
||||
}
|
||||
|
||||
void
|
||||
ShadowLayersParent::DestroySharedSurface(gfxSharedImageSurface* aSurface)
|
||||
{
|
||||
|
@ -43,6 +43,7 @@
|
||||
|
||||
#include "mozilla/layers/PLayersParent.h"
|
||||
#include "ShadowLayers.h"
|
||||
#include "ShadowLayersManager.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@ -63,7 +64,7 @@ class ShadowLayersParent : public PLayersParent,
|
||||
typedef InfallibleTArray<EditReply> EditReplyArray;
|
||||
|
||||
public:
|
||||
ShadowLayersParent(ShadowLayerManager* aManager);
|
||||
ShadowLayersParent(ShadowLayerManager* aManager, ShadowLayersManager* aLayersManager);
|
||||
~ShadowLayersParent();
|
||||
|
||||
void Destroy();
|
||||
@ -83,9 +84,8 @@ protected:
|
||||
NS_OVERRIDE virtual bool DeallocPLayer(PLayerParent* actor);
|
||||
|
||||
private:
|
||||
RenderFrameParent* Frame();
|
||||
|
||||
nsRefPtr<ShadowLayerManager> mLayerManager;
|
||||
ShadowLayersManager* mShadowLayersManager;
|
||||
// Hold the root because it might be grafted under various
|
||||
// containers in the "real" layer tree
|
||||
nsRefPtr<ContainerLayer> mRoot;
|
||||
|
@ -1,4 +1,5 @@
|
||||
IPDLSRCS = \
|
||||
PCompositor.ipdl \
|
||||
PLayer.ipdl \
|
||||
PLayers.ipdl \
|
||||
$(NULL)
|
||||
|
@ -648,7 +648,7 @@ RenderFrameParent::AllocPLayers(LayerManager::LayersBackend* aBackendType)
|
||||
return nsnull;
|
||||
}
|
||||
*aBackendType = lm->GetBackendType();
|
||||
return new ShadowLayersParent(slm);
|
||||
return new ShadowLayersParent(slm, this);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -42,6 +42,7 @@
|
||||
#define mozilla_layout_RenderFrameParent_h
|
||||
|
||||
#include "mozilla/layout/PRenderFrameParent.h"
|
||||
#include "mozilla/layers/ShadowLayersManager.h"
|
||||
|
||||
#include <map>
|
||||
#include "nsDisplayList.h"
|
||||
@ -59,7 +60,8 @@ class ShadowLayersParent;
|
||||
|
||||
namespace layout {
|
||||
|
||||
class RenderFrameParent : public PRenderFrameParent
|
||||
class RenderFrameParent : public PRenderFrameParent,
|
||||
public mozilla::layers::ShadowLayersManager
|
||||
{
|
||||
typedef mozilla::layers::FrameMetrics FrameMetrics;
|
||||
typedef mozilla::layers::ContainerLayer ContainerLayer;
|
||||
@ -84,7 +86,7 @@ public:
|
||||
|
||||
void ContentViewScaleChanged(nsContentView* aView);
|
||||
|
||||
void ShadowLayersUpdated();
|
||||
virtual void ShadowLayersUpdated() MOZ_OVERRIDE;
|
||||
|
||||
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
nsSubDocumentFrame* aFrame,
|
||||
|
@ -173,7 +173,7 @@ public class AboutHomeContent extends ScrollView {
|
||||
activity.stopManagingCursor(mCursor);
|
||||
|
||||
ContentResolver resolver = GeckoApp.mAppContext.getContentResolver();
|
||||
mCursor = BrowserDB.filter(resolver, "", NUMBER_OF_TOP_SITES_PORTRAIT, "about:%");
|
||||
mCursor = BrowserDB.getTopSites(resolver, NUMBER_OF_TOP_SITES_PORTRAIT);
|
||||
activity.startManagingCursor(mCursor);
|
||||
|
||||
mTopSitesAdapter = new TopSitesCursorAdapter(activity,
|
||||
|
@ -63,13 +63,9 @@ public class AndroidBrowserDB implements BrowserDB.BrowserDBIface {
|
||||
|
||||
private static final Uri BOOKMARKS_CONTENT_URI_POST_11 = Uri.parse("content://com.android.browser/bookmarks");
|
||||
|
||||
public Cursor filter(ContentResolver cr, CharSequence constraint, int limit, CharSequence urlFilter) {
|
||||
private Cursor filterAllSites(ContentResolver cr, String[] projection, CharSequence constraint, int limit, CharSequence urlFilter) {
|
||||
Cursor c = cr.query(Browser.BOOKMARKS_URI,
|
||||
new String[] { URL_COLUMN_ID,
|
||||
BookmarkColumns.URL,
|
||||
BookmarkColumns.TITLE,
|
||||
BookmarkColumns.FAVICON,
|
||||
URL_COLUMN_THUMBNAIL },
|
||||
projection,
|
||||
// The length restriction on URL is for the same reason as in the general bookmark query
|
||||
// (see comment earlier in this file).
|
||||
(urlFilter != null ? "(" + Browser.BookmarkColumns.URL + " NOT LIKE ? ) AND " : "" ) +
|
||||
@ -86,6 +82,28 @@ public class AndroidBrowserDB implements BrowserDB.BrowserDBIface {
|
||||
return new AndroidDBCursor(c);
|
||||
}
|
||||
|
||||
public Cursor filter(ContentResolver cr, CharSequence constraint, int limit) {
|
||||
return filterAllSites(cr,
|
||||
new String[] { URL_COLUMN_ID,
|
||||
BookmarkColumns.URL,
|
||||
BookmarkColumns.TITLE,
|
||||
BookmarkColumns.FAVICON },
|
||||
constraint,
|
||||
limit,
|
||||
null);
|
||||
}
|
||||
|
||||
public Cursor getTopSites(ContentResolver cr, int limit) {
|
||||
return filterAllSites(cr,
|
||||
new String[] { URL_COLUMN_ID,
|
||||
BookmarkColumns.URL,
|
||||
BookmarkColumns.TITLE,
|
||||
URL_COLUMN_THUMBNAIL },
|
||||
"",
|
||||
limit,
|
||||
BrowserDB.ABOUT_PAGES_URL_FILTER);
|
||||
}
|
||||
|
||||
public void updateVisitedHistory(ContentResolver cr, String uri) {
|
||||
Browser.updateVisitedHistory(cr, uri, true);
|
||||
}
|
||||
|
@ -42,6 +42,8 @@ import android.database.Cursor;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
|
||||
public class BrowserDB {
|
||||
public static String ABOUT_PAGES_URL_FILTER = "about:%";
|
||||
|
||||
public static interface URLColumns {
|
||||
public static String URL = "url";
|
||||
public static String TITLE = "title";
|
||||
@ -53,7 +55,9 @@ public class BrowserDB {
|
||||
private static BrowserDBIface sDb;
|
||||
|
||||
public interface BrowserDBIface {
|
||||
public Cursor filter(ContentResolver cr, CharSequence constraint, int limit, CharSequence urlFilter);
|
||||
public Cursor filter(ContentResolver cr, CharSequence constraint, int limit);
|
||||
|
||||
public Cursor getTopSites(ContentResolver cr, int limit);
|
||||
|
||||
public void updateVisitedHistory(ContentResolver cr, String uri);
|
||||
|
||||
@ -87,12 +91,12 @@ public class BrowserDB {
|
||||
sDb = new LocalBrowserDB(BrowserContract.DEFAULT_PROFILE);
|
||||
}
|
||||
|
||||
public static Cursor filter(ContentResolver cr, CharSequence constraint, int limit, CharSequence urlFilter) {
|
||||
return sDb.filter(cr, constraint, limit, urlFilter);
|
||||
public static Cursor filter(ContentResolver cr, CharSequence constraint, int limit) {
|
||||
return sDb.filter(cr, constraint, limit);
|
||||
}
|
||||
|
||||
public static Cursor filter(ContentResolver cr, CharSequence constraint, int limit) {
|
||||
return sDb.filter(cr, constraint, limit, null);
|
||||
public static Cursor getTopSites(ContentResolver cr, int limit) {
|
||||
return sDb.getTopSites(cr, limit);
|
||||
}
|
||||
|
||||
public static void updateVisitedHistory(ContentResolver cr, String uri) {
|
||||
|
@ -80,13 +80,9 @@ public class LocalBrowserDB implements BrowserDB.BrowserDBIface {
|
||||
return uri.buildUpon().appendQueryParameter(BrowserContract.PARAM_PROFILE, mProfile).build();
|
||||
}
|
||||
|
||||
public Cursor filter(ContentResolver cr, CharSequence constraint, int limit, CharSequence urlFilter) {
|
||||
private Cursor filterAllSites(ContentResolver cr, String[] projection, CharSequence constraint, int limit, CharSequence urlFilter) {
|
||||
Cursor c = cr.query(appendProfileAndLimit(History.CONTENT_URI, limit),
|
||||
new String[] { History._ID,
|
||||
History.URL,
|
||||
History.TITLE,
|
||||
History.FAVICON,
|
||||
History.THUMBNAIL },
|
||||
projection,
|
||||
(urlFilter != null ? "(" + History.URL + " NOT LIKE ? ) AND " : "" ) +
|
||||
"(" + History.URL + " LIKE ? OR " + History.TITLE + " LIKE ?)",
|
||||
urlFilter == null ? new String[] {"%" + constraint.toString() + "%", "%" + constraint.toString() + "%"} :
|
||||
@ -100,6 +96,28 @@ public class LocalBrowserDB implements BrowserDB.BrowserDBIface {
|
||||
return new LocalDBCursor(c);
|
||||
}
|
||||
|
||||
public Cursor filter(ContentResolver cr, CharSequence constraint, int limit) {
|
||||
return filterAllSites(cr,
|
||||
new String[] { History._ID,
|
||||
History.URL,
|
||||
History.TITLE,
|
||||
History.FAVICON },
|
||||
constraint,
|
||||
limit,
|
||||
null);
|
||||
}
|
||||
|
||||
public Cursor getTopSites(ContentResolver cr, int limit) {
|
||||
return filterAllSites(cr,
|
||||
new String[] { History._ID,
|
||||
History.URL,
|
||||
History.TITLE,
|
||||
History.THUMBNAIL },
|
||||
"",
|
||||
limit,
|
||||
BrowserDB.ABOUT_PAGES_URL_FILTER);
|
||||
}
|
||||
|
||||
private void truncateHistory(ContentResolver cr) {
|
||||
Cursor cursor = null;
|
||||
|
||||
|
@ -424,6 +424,7 @@ OS_LIBS += \
|
||||
-lui \
|
||||
-lmedia \
|
||||
-lhardware_legacy \
|
||||
-lhardware \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
|
@ -48,9 +48,13 @@ LPCTSTR UACHelper::PrivsToDisable[] = {
|
||||
SE_ASSIGNPRIMARYTOKEN_NAME,
|
||||
SE_AUDIT_NAME,
|
||||
SE_BACKUP_NAME,
|
||||
// From testing ReadDirectoryChanges still succeeds even with a low
|
||||
// integrity process with the following privilege disabled.
|
||||
SE_CHANGE_NOTIFY_NAME,
|
||||
// CreateProcess will succeed but the app will fail to launch on some WinXP
|
||||
// machines if SE_CHANGE_NOTIFY_NAME is disabled. In particular this happens
|
||||
// for limited user accounts on those machines. The define is kept here as a
|
||||
// reminder that it should never be re-added.
|
||||
// This permission is for directory watching but also from MSDN: "This
|
||||
// privilege also causes the system to skip all traversal access checks."
|
||||
// SE_CHANGE_NOTIFY_NAME,
|
||||
SE_CREATE_GLOBAL_NAME,
|
||||
SE_CREATE_PAGEFILE_NAME,
|
||||
SE_CREATE_PERMANENT_NAME,
|
||||
|
@ -248,6 +248,77 @@ NS_IMETHODIMP nsOSHelperAppService::GetFromTypeAndExtension(const nsACString& aT
|
||||
return nsExternalHelperAppService::GetFromTypeAndExtension(aType, aFileExt, aMIMEInfo);
|
||||
}
|
||||
|
||||
// Returns the MIME types an application bundle explicitly claims to handle.
|
||||
// Returns NULL if aAppRef doesn't explicitly claim to handle any MIME types.
|
||||
// If the return value is non-NULL, the caller is responsible for freeing it.
|
||||
// This isn't necessarily the same as the MIME types the application bundle
|
||||
// is registered to handle in the Launch Services database. (For example
|
||||
// the Preview application is normally registered to handle the application/pdf
|
||||
// MIME type, even though it doesn't explicitly claim to handle *any* MIME
|
||||
// types in its Info.plist. This is probably because Preview does explicitly
|
||||
// claim to handle the com.adobe.pdf UTI, and Launch Services somehow
|
||||
// translates this into a claim to support the application/pdf MIME type.
|
||||
// Launch Services doesn't provide any APIs (documented or undocumented) to
|
||||
// query which MIME types a given application is registered to handle. So any
|
||||
// app that wants this information (e.g. the Default Apps pref pane) needs to
|
||||
// iterate through the entire Launch Services database -- a process which can
|
||||
// take several seconds.)
|
||||
static CFArrayRef GetMIMETypesHandledByApp(FSRef *aAppRef)
|
||||
{
|
||||
CFURLRef appURL = ::CFURLCreateFromFSRef(kCFAllocatorDefault, aAppRef);
|
||||
if (!appURL) {
|
||||
return NULL;
|
||||
}
|
||||
CFDictionaryRef infoDict = ::CFBundleCopyInfoDictionaryForURL(appURL);
|
||||
::CFRelease(appURL);
|
||||
if (!infoDict) {
|
||||
return NULL;
|
||||
}
|
||||
CFTypeRef cfObject = ::CFDictionaryGetValue(infoDict, CFSTR("CFBundleDocumentTypes"));
|
||||
::CFRelease(infoDict);
|
||||
if (!cfObject || (::CFGetTypeID(cfObject) != ::CFArrayGetTypeID())) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CFArrayRef docTypes = static_cast<CFArrayRef>(cfObject);
|
||||
CFIndex docTypesCount = ::CFArrayGetCount(docTypes);
|
||||
if (docTypesCount == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CFMutableArrayRef mimeTypes =
|
||||
::CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
|
||||
for (CFIndex i = 0; i < docTypesCount; ++i) {
|
||||
cfObject = ::CFArrayGetValueAtIndex(docTypes, i);
|
||||
if (!cfObject || (::CFGetTypeID(cfObject) != ::CFDictionaryGetTypeID())) {
|
||||
continue;
|
||||
}
|
||||
CFDictionaryRef typeDict = static_cast<CFDictionaryRef>(cfObject);
|
||||
|
||||
// When this key is present (on OS X 10.5 and later), its contents
|
||||
// take precedence over CFBundleTypeMIMETypes (and CFBundleTypeExtensions
|
||||
// and CFBundleTypeOSTypes).
|
||||
cfObject = ::CFDictionaryGetValue(typeDict, CFSTR("LSItemContentTypes"));
|
||||
if (cfObject && (::CFGetTypeID(cfObject) == ::CFArrayGetTypeID())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cfObject = ::CFDictionaryGetValue(typeDict, CFSTR("CFBundleTypeMIMETypes"));
|
||||
if (!cfObject || (::CFGetTypeID(cfObject) != ::CFArrayGetTypeID())) {
|
||||
continue;
|
||||
}
|
||||
CFArrayRef mimeTypeHolder = static_cast<CFArrayRef>(cfObject);
|
||||
CFArrayAppendArray(mimeTypes, mimeTypeHolder,
|
||||
::CFRangeMake(0, ::CFArrayGetCount(mimeTypeHolder)));
|
||||
}
|
||||
|
||||
if (!::CFArrayGetCount(mimeTypes)) {
|
||||
::CFRelease(mimeTypes);
|
||||
mimeTypes = NULL;
|
||||
}
|
||||
return mimeTypes;
|
||||
}
|
||||
|
||||
// aMIMEType and aFileExt might not match, If they don't we set *aFound to
|
||||
// false and return a minimal nsIMIMEInfo structure.
|
||||
already_AddRefed<nsIMIMEInfo>
|
||||
@ -281,22 +352,25 @@ nsOSHelperAppService::GetMIMEInfoFromOS(const nsACString& aMIMEType,
|
||||
FSRef typeAppFSRef;
|
||||
FSRef extAppFSRef;
|
||||
|
||||
CFStringRef cfMIMEType = NULL;
|
||||
|
||||
if (!aMIMEType.IsEmpty()) {
|
||||
CFURLRef appURL = NULL;
|
||||
// CFStringCreateWithCString() can fail even if we're not out of memory --
|
||||
// for example if the 'cStr' parameter is something very wierd (like "ÿÿ~"
|
||||
// aka "\xFF\xFF~"), or possibly if it can't be interpreted as using what's
|
||||
// specified in the 'encoding' parameter. See bug 548719.
|
||||
CFStringRef CFType = ::CFStringCreateWithCString(NULL, flatType.get(), kCFStringEncodingUTF8);
|
||||
if (CFType) {
|
||||
err = ::LSCopyApplicationForMIMEType(CFType, kLSRolesAll, &appURL);
|
||||
cfMIMEType = ::CFStringCreateWithCString(NULL, flatType.get(),
|
||||
kCFStringEncodingUTF8);
|
||||
if (cfMIMEType) {
|
||||
err = ::LSCopyApplicationForMIMEType(cfMIMEType, kLSRolesAll, &appURL);
|
||||
if ((err == noErr) && appURL && ::CFURLGetFSRef(appURL, &typeAppFSRef)) {
|
||||
haveAppForType = true;
|
||||
PR_LOG(mLog, PR_LOG_DEBUG, ("LSCopyApplicationForMIMEType found a default application\n"));
|
||||
}
|
||||
if (appURL)
|
||||
if (appURL) {
|
||||
::CFRelease(appURL);
|
||||
::CFRelease(CFType);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!aFileExt.IsEmpty()) {
|
||||
@ -304,15 +378,15 @@ nsOSHelperAppService::GetMIMEInfoFromOS(const nsACString& aMIMEType,
|
||||
// for example if the 'cStr' parameter is something very wierd (like "ÿÿ~"
|
||||
// aka "\xFF\xFF~"), or possibly if it can't be interpreted as using what's
|
||||
// specified in the 'encoding' parameter. See bug 548719.
|
||||
CFStringRef CFExt = ::CFStringCreateWithCString(NULL, flatExt.get(), kCFStringEncodingUTF8);
|
||||
if (CFExt) {
|
||||
err = ::LSGetApplicationForInfo(kLSUnknownType, kLSUnknownCreator, CFExt,
|
||||
CFStringRef cfExt = ::CFStringCreateWithCString(NULL, flatExt.get(), kCFStringEncodingUTF8);
|
||||
if (cfExt) {
|
||||
err = ::LSGetApplicationForInfo(kLSUnknownType, kLSUnknownCreator, cfExt,
|
||||
kLSRolesAll, &extAppFSRef, nsnull);
|
||||
if (err == noErr) {
|
||||
haveAppForExt = true;
|
||||
PR_LOG(mLog, PR_LOG_DEBUG, ("LSGetApplicationForInfo found a default application\n"));
|
||||
}
|
||||
::CFRelease(CFExt);
|
||||
::CFRelease(cfExt);
|
||||
}
|
||||
}
|
||||
|
||||
@ -329,13 +403,52 @@ nsOSHelperAppService::GetMIMEInfoFromOS(const nsACString& aMIMEType,
|
||||
*aFound = true;
|
||||
}
|
||||
} else if (haveAppForExt) {
|
||||
// If aMIMEType isn't empty, it doesn't match aFileExt.
|
||||
// If aMIMEType isn't empty, it doesn't match aFileExt, which should mean
|
||||
// that we haven't found a matching app. But make an exception for an app
|
||||
// that also explicitly claims to handle aMIMEType, or which doesn't claim
|
||||
// to handle any MIME types. This helps work around the following Apple
|
||||
// design flaw:
|
||||
//
|
||||
// Launch Services is somewhat unreliable about registering Apple apps to
|
||||
// handle MIME types. Probably this is because Apple has officially
|
||||
// deprecated support for MIME types (in favor of UTIs). As a result,
|
||||
// most of Apple's own apps don't explicitly claim to handle any MIME
|
||||
// types (instead they claim to handle one or more UTIs). So Launch
|
||||
// Services must contain logic to translate support for a given UTI into
|
||||
// support for one or more MIME types, and it doesn't always do this
|
||||
// correctly. For example DiskImageMounter isn't (by default) registered
|
||||
// to handle the application/x-apple-diskimage MIME type. See bug 675356.
|
||||
//
|
||||
// Apple has also deprecated support for file extensions, and Apple apps
|
||||
// also don't register to handle them. But for some reason Launch Services
|
||||
// is (apparently) better about translating support for a given UTI into
|
||||
// support for one or more file extensions. It's not at all clear why.
|
||||
if (aMIMEType.IsEmpty()) {
|
||||
extAppIsDefault = true;
|
||||
*aFound = true;
|
||||
} else {
|
||||
CFArrayRef extAppMIMETypes = GetMIMETypesHandledByApp(&extAppFSRef);
|
||||
if (extAppMIMETypes) {
|
||||
if (cfMIMEType) {
|
||||
if (::CFArrayContainsValue(extAppMIMETypes,
|
||||
::CFRangeMake(0, ::CFArrayGetCount(extAppMIMETypes)),
|
||||
cfMIMEType)) {
|
||||
extAppIsDefault = true;
|
||||
*aFound = true;
|
||||
}
|
||||
}
|
||||
::CFRelease(extAppMIMETypes);
|
||||
} else {
|
||||
extAppIsDefault = true;
|
||||
*aFound = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cfMIMEType) {
|
||||
::CFRelease(cfMIMEType);
|
||||
}
|
||||
|
||||
if (aMIMEType.IsEmpty()) {
|
||||
if (haveAppForExt) {
|
||||
// If aMIMEType is empty and we've found a default app for aFileExt, try
|
||||
@ -382,26 +495,26 @@ nsOSHelperAppService::GetMIMEInfoFromOS(const nsACString& aMIMEType,
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
CFStringRef CFAppName = NULL;
|
||||
CFStringRef cfAppName = NULL;
|
||||
if (typeAppIsDefault) {
|
||||
app->InitWithFSRef(&typeAppFSRef);
|
||||
::LSCopyItemAttribute((const FSRef *) &typeAppFSRef, kLSRolesAll,
|
||||
kLSItemDisplayName, (CFTypeRef *) &CFAppName);
|
||||
kLSItemDisplayName, (CFTypeRef *) &cfAppName);
|
||||
} else {
|
||||
app->InitWithFSRef(&extAppFSRef);
|
||||
::LSCopyItemAttribute((const FSRef *) &extAppFSRef, kLSRolesAll,
|
||||
kLSItemDisplayName, (CFTypeRef *) &CFAppName);
|
||||
kLSItemDisplayName, (CFTypeRef *) &cfAppName);
|
||||
}
|
||||
if (CFAppName) {
|
||||
if (cfAppName) {
|
||||
nsAutoTArray<UniChar, 255> buffer;
|
||||
CFIndex appNameLength = ::CFStringGetLength(CFAppName);
|
||||
CFIndex appNameLength = ::CFStringGetLength(cfAppName);
|
||||
buffer.SetLength(appNameLength);
|
||||
::CFStringGetCharacters(CFAppName, CFRangeMake(0, appNameLength),
|
||||
::CFStringGetCharacters(cfAppName, CFRangeMake(0, appNameLength),
|
||||
buffer.Elements());
|
||||
nsAutoString appName;
|
||||
appName.Assign(buffer.Elements(), appNameLength);
|
||||
mimeInfoMac->SetDefaultDescription(appName);
|
||||
::CFRelease(CFAppName);
|
||||
::CFRelease(cfAppName);
|
||||
}
|
||||
|
||||
mimeInfoMac->SetDefaultApplication(app);
|
||||
@ -424,21 +537,22 @@ nsOSHelperAppService::GetMIMEInfoFromOS(const nsACString& aMIMEType,
|
||||
mimeInfoMac->AppendExtension(preferredExt);
|
||||
}
|
||||
|
||||
CFStringRef CFType = ::CFStringCreateWithCString(NULL, mimeType.get(), kCFStringEncodingUTF8);
|
||||
CFStringRef CFTypeDesc = NULL;
|
||||
if (::LSCopyKindStringForMIMEType(CFType, &CFTypeDesc) == noErr) {
|
||||
CFStringRef cfType = ::CFStringCreateWithCString(NULL, mimeType.get(), kCFStringEncodingUTF8);
|
||||
CFStringRef cfTypeDesc = NULL;
|
||||
if (::LSCopyKindStringForMIMEType(cfType, &cfTypeDesc) == noErr) {
|
||||
nsAutoTArray<UniChar, 255> buffer;
|
||||
CFIndex typeDescLength = ::CFStringGetLength(CFTypeDesc);
|
||||
CFIndex typeDescLength = ::CFStringGetLength(cfTypeDesc);
|
||||
buffer.SetLength(typeDescLength);
|
||||
::CFStringGetCharacters(CFTypeDesc, CFRangeMake(0, typeDescLength),
|
||||
::CFStringGetCharacters(cfTypeDesc, CFRangeMake(0, typeDescLength),
|
||||
buffer.Elements());
|
||||
nsAutoString typeDesc;
|
||||
typeDesc.Assign(buffer.Elements(), typeDescLength);
|
||||
mimeInfoMac->SetDescription(typeDesc);
|
||||
}
|
||||
if (CFTypeDesc)
|
||||
::CFRelease(CFTypeDesc);
|
||||
::CFRelease(CFType);
|
||||
if (cfTypeDesc) {
|
||||
::CFRelease(cfTypeDesc);
|
||||
}
|
||||
::CFRelease(cfType);
|
||||
}
|
||||
|
||||
PR_LOG(mLog, PR_LOG_DEBUG, ("OS gave us: type '%s' found '%i'\n", mimeType.get(), *aFound));
|
||||
|
@ -119,6 +119,10 @@ namespace mozilla {
|
||||
namespace gl {
|
||||
class TextureImage;
|
||||
}
|
||||
|
||||
namespace layers {
|
||||
class LayerManagerOGL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NP_NO_CARBON
|
||||
@ -295,6 +299,9 @@ typedef NSInteger NSEventGestureAxis;
|
||||
#ifdef __LP64__
|
||||
BOOL *mSwipeAnimationCancelled;
|
||||
#endif
|
||||
|
||||
// Whether this uses off-main-thread compositing.
|
||||
BOOL mUsingOMTCompositor;
|
||||
}
|
||||
|
||||
// class initialization
|
||||
@ -327,6 +334,8 @@ typedef NSInteger NSEventGestureAxis;
|
||||
// If so, we shouldn't focus or unfocus a plugin.
|
||||
- (BOOL)isInFailingLeftClickThrough;
|
||||
|
||||
- (void)setGLContext:(NSOpenGLContext *)aGLContext;
|
||||
|
||||
// Simple gestures support
|
||||
//
|
||||
// XXX - The swipeWithEvent, beginGestureWithEvent, magnifyWithEvent,
|
||||
@ -348,6 +357,8 @@ typedef NSInteger NSEventGestureAxis;
|
||||
- (void)maybeTrackScrollEventAsSwipe:(NSEvent *)anEvent
|
||||
scrollOverflow:(PRInt32)overflow;
|
||||
#endif
|
||||
|
||||
- (void)setUsingOMTCompositor:(BOOL)aUseOMTC;
|
||||
@end
|
||||
|
||||
class ChildViewMouseTracker {
|
||||
@ -433,7 +444,7 @@ public:
|
||||
|
||||
NS_IMETHOD SetCursor(nsCursor aCursor);
|
||||
NS_IMETHOD SetCursor(imgIContainer* aCursor, PRUint32 aHotspotX, PRUint32 aHotspotY);
|
||||
|
||||
|
||||
NS_IMETHOD CaptureRollupEvents(nsIRollupListener * aListener, bool aDoCapture, bool aConsumeRollupEvent);
|
||||
NS_IMETHOD SetTitle(const nsAString& title);
|
||||
|
||||
@ -486,6 +497,7 @@ public:
|
||||
already_AddRefed<nsAccessible> GetDocumentAccessible();
|
||||
#endif
|
||||
|
||||
virtual void CreateCompositor();
|
||||
virtual gfxASurface* GetThebesSurface();
|
||||
virtual void DrawOver(LayerManager* aManager, nsIntRect aRect);
|
||||
|
||||
|
@ -87,6 +87,7 @@
|
||||
#include "Layers.h"
|
||||
#include "LayerManagerOGL.h"
|
||||
#include "GLContext.h"
|
||||
#include "mozilla/layers/CompositorCocoaWidgetHelper.h"
|
||||
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
@ -1772,6 +1773,22 @@ NSView<mozView>* nsChildView::GetEditorView()
|
||||
|
||||
#pragma mark -
|
||||
|
||||
void
|
||||
nsChildView::CreateCompositor()
|
||||
{
|
||||
nsBaseWidget::CreateCompositor();
|
||||
if (mCompositorChild) {
|
||||
LayerManagerOGL *manager =
|
||||
static_cast<LayerManagerOGL*>(compositor::GetLayerManager(mCompositorParent));
|
||||
|
||||
NSOpenGLContext *glContext =
|
||||
(NSOpenGLContext *) manager->gl()->GetNativeData(GLContext::NativeGLContext);
|
||||
|
||||
[(ChildView *)mView setGLContext:glContext];
|
||||
[(ChildView *)mView setUsingOMTCompositor:true];
|
||||
}
|
||||
}
|
||||
|
||||
gfxASurface*
|
||||
nsChildView::GetThebesSurface()
|
||||
{
|
||||
@ -2096,6 +2113,16 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
}
|
||||
|
||||
- (void)setGLContext:(NSOpenGLContext *)aGLContext
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||
|
||||
mGLContext = aGLContext;
|
||||
[mGLContext retain];
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||
@ -2546,13 +2573,18 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mGeckoChild->GetLayerManager(nsnull)->GetBackendType() == LayerManager::LAYERS_OPENGL) {
|
||||
LayerManagerOGL *manager = static_cast<LayerManagerOGL*>(mGeckoChild->GetLayerManager(nsnull));
|
||||
manager->SetClippingRegion(paintEvent.region);
|
||||
LayerManager *layerManager = mGeckoChild->GetLayerManager(nsnull);
|
||||
if (layerManager->GetBackendType() == LayerManager::LAYERS_OPENGL) {
|
||||
NSOpenGLContext *glContext;
|
||||
|
||||
LayerManagerOGL *manager = static_cast<LayerManagerOGL*>(layerManager);
|
||||
manager->SetClippingRegion(paintEvent.region);
|
||||
glContext = (NSOpenGLContext *)manager->gl()->GetNativeData(mozilla::gl::GLContext::NativeGLContext);
|
||||
|
||||
if (!mGLContext) {
|
||||
mGLContext = (NSOpenGLContext *)manager->gl()->GetNativeData(mozilla::gl::GLContext::NativeGLContext);
|
||||
[mGLContext retain];
|
||||
[self setGLContext:glContext];
|
||||
}
|
||||
|
||||
mGeckoChild->DispatchWindowEvent(paintEvent);
|
||||
|
||||
// Force OpenGL to refresh the very first time we draw. This works around a
|
||||
@ -2592,6 +2624,16 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
||||
painted = mGeckoChild->DispatchWindowEvent(paintEvent);
|
||||
}
|
||||
|
||||
// Force OpenGL to refresh the very first time we draw. This works around a
|
||||
// Mac OS X bug that stops windows updating on OS X when we use OpenGL.
|
||||
if (painted && !mDidForceRefreshOpenGL &&
|
||||
layerManager->AsShadowManager() && mUsingOMTCompositor) {
|
||||
if (!mDidForceRefreshOpenGL) {
|
||||
[self performSelector:@selector(forceRefreshOpenGL) withObject:nil afterDelay:0];
|
||||
mDidForceRefreshOpenGL = YES;
|
||||
}
|
||||
}
|
||||
|
||||
if (!painted && [self isOpaque]) {
|
||||
// Gecko refused to draw, but we've claimed to be opaque, so we have to
|
||||
// draw something--fill with white.
|
||||
@ -3129,6 +3171,12 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
||||
}
|
||||
#endif // #ifdef __LP64__
|
||||
|
||||
- (void)setUsingOMTCompositor:(BOOL)aUseOMTC
|
||||
{
|
||||
mUsingOMTCompositor = aUseOMTC;
|
||||
}
|
||||
|
||||
|
||||
// Returning NO from this method only disallows ordering on mousedown - in order
|
||||
// to prevent it for mouseup too, we need to call [NSApp preventWindowOrdering]
|
||||
// when handling the mousedown event.
|
||||
|
@ -38,6 +38,8 @@
|
||||
|
||||
#include "mozilla/Util.h"
|
||||
|
||||
#include "mozilla/layers/CompositorChild.h"
|
||||
#include "mozilla/layers/CompositorParent.h"
|
||||
#include "nsBaseWidget.h"
|
||||
#include "nsDeviceContext.h"
|
||||
#include "nsCOMPtr.h"
|
||||
@ -55,6 +57,7 @@
|
||||
#include "nsIXULRuntime.h"
|
||||
#include "nsIGfxInfo.h"
|
||||
#include "npapi.h"
|
||||
#include "base/thread.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#include "nsIObserver.h"
|
||||
@ -70,6 +73,8 @@ static PRInt32 gNumWidgets;
|
||||
|
||||
using namespace mozilla::layers;
|
||||
using namespace mozilla;
|
||||
using base::Thread;
|
||||
using mozilla::ipc::AsyncChannel;
|
||||
|
||||
nsIContent* nsBaseWidget::mLastRollup = nsnull;
|
||||
|
||||
@ -104,6 +109,7 @@ nsBaseWidget::nsBaseWidget()
|
||||
, mEventCallback(nsnull)
|
||||
, mViewCallback(nsnull)
|
||||
, mContext(nsnull)
|
||||
, mCompositorThread(nsnull)
|
||||
, mCursor(eCursor_standard)
|
||||
, mWindowType(eWindowType_child)
|
||||
, mBorderStyle(eBorderStyle_none)
|
||||
@ -142,6 +148,12 @@ nsBaseWidget::~nsBaseWidget()
|
||||
|
||||
if (mLayerManager) {
|
||||
mLayerManager->Destroy();
|
||||
mLayerManager = nsnull;
|
||||
}
|
||||
|
||||
if (mCompositorChild) {
|
||||
mCompositorChild->Destroy();
|
||||
delete mCompositorThread;
|
||||
}
|
||||
|
||||
#ifdef NOISY_WIDGET_LEAKS
|
||||
@ -814,6 +826,38 @@ nsBaseWidget::GetShouldAccelerate()
|
||||
return mUseAcceleratedRendering;
|
||||
}
|
||||
|
||||
void nsBaseWidget::CreateCompositor()
|
||||
{
|
||||
mCompositorParent = new CompositorParent(this);
|
||||
mCompositorThread = new Thread("CompositorThread");
|
||||
if (mCompositorThread->Start()) {
|
||||
LayerManager* lm = CreateBasicLayerManager();
|
||||
MessageLoop *childMessageLoop = mCompositorThread->message_loop();
|
||||
mCompositorChild = new CompositorChild(lm);
|
||||
AsyncChannel *parentChannel = mCompositorParent->GetIPCChannel();
|
||||
AsyncChannel::Side childSide = mozilla::ipc::AsyncChannel::Child;
|
||||
mCompositorChild->Open(parentChannel, childMessageLoop, childSide);
|
||||
PLayersChild* shadowManager =
|
||||
mCompositorChild->SendPLayersConstructor(LayerManager::LAYERS_OPENGL);
|
||||
|
||||
if (shadowManager) {
|
||||
ShadowLayerForwarder* lf = lm->AsShadowForwarder();
|
||||
if (!lf) {
|
||||
delete lm;
|
||||
mCompositorChild = nsnull;
|
||||
}
|
||||
lf->SetShadowManager(shadowManager);
|
||||
lf->SetParentBackendType(LayerManager::LAYERS_OPENGL);
|
||||
|
||||
mLayerManager = lm;
|
||||
} else {
|
||||
NS_WARNING("fail to construct LayersChild");
|
||||
delete lm;
|
||||
mCompositorChild = nsnull;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LayerManager* nsBaseWidget::GetLayerManager(PLayersChild* aShadowManager,
|
||||
LayersBackend aBackendHint,
|
||||
LayerManagerPersistence aPersistence,
|
||||
@ -824,16 +868,29 @@ LayerManager* nsBaseWidget::GetLayerManager(PLayersChild* aShadowManager,
|
||||
mUseAcceleratedRendering = GetShouldAccelerate();
|
||||
|
||||
if (mUseAcceleratedRendering) {
|
||||
nsRefPtr<LayerManagerOGL> layerManager = new LayerManagerOGL(this);
|
||||
/**
|
||||
* XXX - On several OSes initialization is expected to fail for now.
|
||||
* If we'd get a none-basic layer manager they'd crash. This is ok though
|
||||
* since on those platforms it will fail. Anyone implementing new
|
||||
* platforms on LayerManagerOGL should ensure their widget is able to
|
||||
* deal with it though!
|
||||
*/
|
||||
if (layerManager->Initialize()) {
|
||||
mLayerManager = layerManager;
|
||||
|
||||
// Try to use an async compositor first, if possible
|
||||
bool useCompositor =
|
||||
Preferences::GetBool("layers.offmainthreadcomposition.enabled", false);
|
||||
if (useCompositor) {
|
||||
// e10s uses the parameter to pass in the shadow manager from the TabChild
|
||||
// so we don't expect to see it there since this doesn't support e10s.
|
||||
NS_ASSERTION(aShadowManager == nsnull, "Async Compositor not supported with e10s");
|
||||
CreateCompositor();
|
||||
}
|
||||
|
||||
if (!mLayerManager) {
|
||||
nsRefPtr<LayerManagerOGL> layerManager = new LayerManagerOGL(this);
|
||||
/**
|
||||
* XXX - On several OSes initialization is expected to fail for now.
|
||||
* If we'd get a non-basic layer manager they'd crash. This is ok though
|
||||
* since on those platforms it will fail. Anyone implementing new
|
||||
* platforms on LayerManagerOGL should ensure their widget is able to
|
||||
* deal with it though!
|
||||
*/
|
||||
if (layerManager->Initialize()) {
|
||||
mLayerManager = layerManager;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!mLayerManager) {
|
||||
|
@ -51,6 +51,17 @@ class nsIContent;
|
||||
class nsAutoRollup;
|
||||
class gfxContext;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
class CompositorChild;
|
||||
class CompositorParent;
|
||||
}
|
||||
}
|
||||
|
||||
namespace base {
|
||||
class Thread;
|
||||
}
|
||||
|
||||
/**
|
||||
* Common widget implementation used as base class for native
|
||||
* or crossplatform implementations of Widgets.
|
||||
@ -66,6 +77,9 @@ class nsBaseWidget : public nsIWidget
|
||||
|
||||
protected:
|
||||
typedef mozilla::layers::BasicLayerManager BasicLayerManager;
|
||||
typedef mozilla::layers::CompositorChild CompositorChild;
|
||||
typedef mozilla::layers::CompositorParent CompositorParent;
|
||||
typedef base::Thread Thread;
|
||||
|
||||
public:
|
||||
nsBaseWidget();
|
||||
@ -117,6 +131,7 @@ public:
|
||||
LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT,
|
||||
bool* aAllowRetaining = nsnull);
|
||||
|
||||
virtual void CreateCompositor();
|
||||
virtual void DrawOver(LayerManager* aManager, nsIntRect aRect) {}
|
||||
virtual void UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries) {}
|
||||
virtual gfxASurface* GetThebesSurface();
|
||||
@ -268,6 +283,9 @@ protected:
|
||||
nsDeviceContext* mContext;
|
||||
nsRefPtr<LayerManager> mLayerManager;
|
||||
nsRefPtr<LayerManager> mBasicLayerManager;
|
||||
nsRefPtr<CompositorChild> mCompositorChild;
|
||||
nsRefPtr<CompositorParent> mCompositorParent;
|
||||
Thread* mCompositorThread;
|
||||
nscolor mBackground;
|
||||
nscolor mForeground;
|
||||
nsCursor mCursor;
|
||||
|
@ -350,6 +350,22 @@ void* nsDeque::ObjectAt(PRInt32 aIndex) const {
|
||||
return result;
|
||||
}
|
||||
|
||||
void* nsDeque::RemoveObjectAt(PRInt32 aIndex) {
|
||||
if ((aIndex<0) || (aIndex>=mSize)) {
|
||||
return 0;
|
||||
}
|
||||
void* result=mData[modulus(mOrigin + aIndex, mCapacity)];
|
||||
|
||||
// "Shuffle down" all elements in the array by 1, overwritting the element
|
||||
// being removed.
|
||||
for (PRInt32 i=aIndex; i<mSize; i++) {
|
||||
mData[modulus(mOrigin + i, mCapacity)] = mData[modulus(mOrigin + i + 1, mCapacity)];
|
||||
}
|
||||
mSize--;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return an iterator pointing to
|
||||
* the beginning of the queue. Note that this
|
||||
|
@ -152,6 +152,14 @@ class NS_COM_GLUE nsDeque {
|
||||
*/
|
||||
void* ObjectAt(int aIndex) const;
|
||||
|
||||
/**
|
||||
* Removes and returns the i'th member from the deque.
|
||||
*
|
||||
* @param index of desired item
|
||||
* @return the element which was removed
|
||||
*/
|
||||
void* RemoveObjectAt(int aIndex);
|
||||
|
||||
/**
|
||||
* Remove all items from container without destroying them.
|
||||
*
|
||||
|
@ -223,6 +223,39 @@ private:
|
||||
nsCOMPtr<nsISupports> mSupports;
|
||||
};
|
||||
|
||||
/**
|
||||
* hashkey wrapper using refcounted * KeyType
|
||||
*
|
||||
* @see nsTHashtable::EntryType for specification
|
||||
*/
|
||||
template<class T>
|
||||
class nsRefPtrHashKey : public PLDHashEntryHdr
|
||||
{
|
||||
public:
|
||||
typedef T* KeyType;
|
||||
typedef const T* KeyTypePointer;
|
||||
|
||||
nsRefPtrHashKey(const T* key) :
|
||||
mKey(const_cast<T*>(key)) { }
|
||||
nsRefPtrHashKey(const nsRefPtrHashKey& toCopy) :
|
||||
mKey(toCopy.mKey) { }
|
||||
~nsRefPtrHashKey() { }
|
||||
|
||||
KeyType GetKey() const { return mKey; }
|
||||
|
||||
bool KeyEquals(KeyTypePointer aKey) const { return aKey == mKey; }
|
||||
|
||||
static KeyTypePointer KeyToPointer(KeyType aKey) { return aKey; }
|
||||
static PLDHashNumber HashKey(KeyTypePointer aKey)
|
||||
{
|
||||
return NS_PTR_TO_INT32(aKey) >>2;
|
||||
}
|
||||
enum { ALLOW_MEMMOVE = true };
|
||||
|
||||
private:
|
||||
nsRefPtr<T> mKey;
|
||||
};
|
||||
|
||||
/**
|
||||
* hashkey wrapper using T* KeyType
|
||||
*
|
||||
|
@ -89,6 +89,7 @@ CPP_UNIT_TESTS = \
|
||||
TestCOMArray.cpp \
|
||||
TestCOMPtr.cpp \
|
||||
TestCOMPtrEq.cpp \
|
||||
TestDeque.cpp \
|
||||
TestFile.cpp \
|
||||
TestHashtables.cpp \
|
||||
TestID.cpp \
|
||||
@ -109,7 +110,6 @@ endif
|
||||
#CPP_UNIT_TESTS += \
|
||||
# TestArray.cpp \
|
||||
# TestCRT.cpp \
|
||||
# TestDeque.cpp \
|
||||
# TestEncoding.cpp \
|
||||
# TestExpirationTracker.cpp \
|
||||
# TestPipes.cpp \
|
||||
|
@ -35,6 +35,7 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "TestHarness.h"
|
||||
#include "nsDeque.h"
|
||||
#include "nsCRT.h"
|
||||
#include <stdio.h>
|
||||
@ -44,13 +45,12 @@
|
||||
**************************************************************/
|
||||
class _TestDeque {
|
||||
public:
|
||||
_TestDeque() {
|
||||
SelfTest();
|
||||
}
|
||||
int SelfTest();
|
||||
nsresult OriginalTest();
|
||||
nsresult OriginalFlaw();
|
||||
nsresult AssignFlaw();
|
||||
int Test();
|
||||
private:
|
||||
int OriginalTest();
|
||||
int OriginalFlaw();
|
||||
int AssignFlaw();
|
||||
int TestRemove();
|
||||
};
|
||||
static _TestDeque sTestDeque;
|
||||
|
||||
@ -60,96 +60,214 @@ class _Dealloc: public nsDequeFunctor {
|
||||
}
|
||||
};
|
||||
|
||||
#define TEST(aCondition, aMsg) \
|
||||
if (!(aCondition)) { fail("TestDeque: "#aMsg); return 1; }
|
||||
|
||||
|
||||
/**
|
||||
* conduct automated self test for this class
|
||||
*
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
int _TestDeque::SelfTest() {
|
||||
int _TestDeque::Test() {
|
||||
/* the old deque should have failed a bunch of these tests */
|
||||
int results=0;
|
||||
results+=OriginalTest();
|
||||
results+=OriginalFlaw();
|
||||
results+=AssignFlaw();
|
||||
results+=TestRemove();
|
||||
return results;
|
||||
}
|
||||
|
||||
nsresult _TestDeque::OriginalTest() {
|
||||
int ints[200];
|
||||
int count=sizeof(ints)/sizeof(int);
|
||||
int _TestDeque::OriginalTest() {
|
||||
const int size = 200;
|
||||
int ints[size];
|
||||
int i=0;
|
||||
int* temp;
|
||||
int temp;
|
||||
nsDeque theDeque(new _Dealloc); //construct a simple one...
|
||||
|
||||
for (i=0;i<count;i++) { //initialize'em
|
||||
ints[i]=10*(1+i);
|
||||
// ints = [0...199]
|
||||
for (i=0;i<size;i++) { //initialize'em
|
||||
ints[i]=i;
|
||||
}
|
||||
// queue = [0...69]
|
||||
for (i=0;i<70;i++) {
|
||||
theDeque.Push(&ints[i]);
|
||||
temp=*(int*)theDeque.Peek();
|
||||
TEST(temp == i, "Verify end after push #1");
|
||||
TEST(theDeque.GetSize() == i + 1, "Verify size after push #1");
|
||||
}
|
||||
for (i=0;i<56;i++) {
|
||||
temp=(int*)theDeque.Pop();
|
||||
TEST(theDeque.GetSize() == 70, "Verify overall size after pushes #1");
|
||||
// queue = [0...14]
|
||||
for (i=1;i<=55;i++) {
|
||||
temp=*(int*)theDeque.Pop();
|
||||
TEST(temp == 70-i, "Verify end after pop # 1");
|
||||
TEST(theDeque.GetSize() == 70 - i, "Verify size after pop # 1");
|
||||
}
|
||||
TEST(theDeque.GetSize() == 15, "Verify overall size after pops");
|
||||
|
||||
// queue = [0...14,0...54]
|
||||
for (i=0;i<55;i++) {
|
||||
theDeque.Push(&ints[i]);
|
||||
temp=*(int*)theDeque.Peek();
|
||||
TEST(temp == i, "Verify end after push #2");
|
||||
TEST(theDeque.GetSize() == i + 15 + 1, "Verify size after push # 2");
|
||||
}
|
||||
for (i=0;i<35;i++) {
|
||||
temp=(int*)theDeque.Pop();
|
||||
TEST(theDeque.GetSize() == 70, "Verify size after end of all pushes #2");
|
||||
|
||||
// queue = [0...14,0...19]
|
||||
for (i=1;i<=35;i++) {
|
||||
temp=*(int*)theDeque.Pop();
|
||||
TEST(temp == 55-i, "Verify end after pop # 2");
|
||||
TEST(theDeque.GetSize() == 70 - i, "Verify size after pop #2");
|
||||
}
|
||||
TEST(theDeque.GetSize() == 35, "Verify overall size after end of all pops #2");
|
||||
|
||||
// queue = [0...14,0...19,0...34]
|
||||
for (i=0;i<35;i++) {
|
||||
theDeque.Push(&ints[i]);
|
||||
temp = *(int*)theDeque.Peek();
|
||||
TEST(temp == i, "Verify end after push # 3");
|
||||
TEST(theDeque.GetSize() == 35 + 1 + i, "Verify size after push #3");
|
||||
}
|
||||
for (i=0;i<38;i++) {
|
||||
temp=(int*)theDeque.Pop();
|
||||
|
||||
// queue = [0...14,0...19]
|
||||
for (i=0;i<35;i++) {
|
||||
temp=*(int*)theDeque.Pop();
|
||||
TEST(temp == 34 - i, "Verify end after pop # 3");
|
||||
}
|
||||
return NS_OK;
|
||||
|
||||
// queue = [0...14]
|
||||
for (i=0;i<20;i++) {
|
||||
temp=*(int*)theDeque.Pop();
|
||||
TEST(temp == 19 - i, "Verify end after pop # 4");
|
||||
}
|
||||
|
||||
// queue = []
|
||||
for (i=0;i<15;i++) {
|
||||
temp=*(int*)theDeque.Pop();
|
||||
TEST(temp == 14 - i, "Verify end after pop # 5");
|
||||
}
|
||||
|
||||
TEST(theDeque.GetSize() == 0, "Deque should finish empty.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
nsresult _TestDeque::OriginalFlaw() {
|
||||
int _TestDeque::OriginalFlaw() {
|
||||
int ints[200];
|
||||
int i=0;
|
||||
int* temp;
|
||||
nsDeque secondDeque(new _Dealloc);
|
||||
int temp;
|
||||
nsDeque d(new _Dealloc);
|
||||
/**
|
||||
* Test 1. Origin near end, semi full, call Peek().
|
||||
* you start, mCapacity is 8
|
||||
*/
|
||||
printf("fill array\n");
|
||||
for (i=32; i; --i)
|
||||
ints[i]=i*3+10;
|
||||
printf("push 6 times\n");
|
||||
for (i=0; i<6; i++)
|
||||
secondDeque.Push(&ints[i]);
|
||||
printf("popfront 4 times:\n");
|
||||
for (i=4; i; --i) {
|
||||
temp=(int*)secondDeque.PopFront();
|
||||
printf("%d\t",*temp);
|
||||
for (i=0; i<30; i++)
|
||||
ints[i]=i;
|
||||
|
||||
for (i=0; i<6; i++) {
|
||||
d.Push(&ints[i]);
|
||||
temp = *(int*)d.Peek();
|
||||
TEST(temp == i, "OriginalFlaw push #1");
|
||||
}
|
||||
printf("push 4 times\n");
|
||||
for (int j=4; j; --j)
|
||||
secondDeque.Push(&ints[++i]);
|
||||
printf("origin should now be about 4\n");
|
||||
printf("and size should be 6\n");
|
||||
printf("origin+size>capacity\n");
|
||||
TEST(d.GetSize() == 6, "OriginalFlaw size check #1");
|
||||
|
||||
/*<akk> Oh, I see ... it's a circular buffer */
|
||||
printf("but the old code wasn't behaving accordingly.\n");
|
||||
for (i=0; i<4; i++) {
|
||||
temp=*(int*)d.PopFront();
|
||||
TEST(temp == i, "PopFront test");
|
||||
}
|
||||
// d = [4,5]
|
||||
TEST(d.GetSize() == 2, "OriginalFlaw size check #2");
|
||||
|
||||
/*right*/
|
||||
printf("we shouldn't crash or anything interesting, ");
|
||||
for (i=0; i<4; i++) {
|
||||
d.Push(&ints[6 + i]);
|
||||
}
|
||||
// d = [4...9]
|
||||
|
||||
temp=(int*)secondDeque.Peek();
|
||||
printf("peek: %d\n",*temp);
|
||||
return NS_OK;
|
||||
for (i=4; i<=9; i++) {
|
||||
temp=*(int*)d.PopFront();
|
||||
TEST(temp == i, "OriginalFlaw empty check");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
nsresult _TestDeque::AssignFlaw() {
|
||||
int _TestDeque::AssignFlaw() {
|
||||
nsDeque src(new _Dealloc),dest(new _Dealloc);
|
||||
return NS_OK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool VerifyContents(const nsDeque& aDeque, const int* aContents, int aLength) {
|
||||
for (int i=0; i<aLength; ++i) {
|
||||
if (*(int*)aDeque.ObjectAt(i) != aContents[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int _TestDeque::TestRemove() {
|
||||
nsDeque d;
|
||||
const int count = 10;
|
||||
int ints[count];
|
||||
for (int i=0; i<count; i++) {
|
||||
ints[i] = i;
|
||||
}
|
||||
|
||||
for (int i=0; i<6; i++) {
|
||||
d.Push(&ints[i]);
|
||||
}
|
||||
// d = [0...5]
|
||||
d.PopFront();
|
||||
d.PopFront();
|
||||
|
||||
// d = [2,5]
|
||||
for (int i=2; i<=5; i++) {
|
||||
int t = *(int*)d.ObjectAt(i-2);
|
||||
TEST(t == i, "Verify ObjectAt()");
|
||||
}
|
||||
|
||||
d.RemoveObjectAt(1);
|
||||
// d == [2,4,5]
|
||||
static const int t1[] = {2,4,5};
|
||||
TEST(VerifyContents(d, t1, 3), "verify contents t1");
|
||||
|
||||
d.PushFront(&ints[1]);
|
||||
d.PushFront(&ints[0]);
|
||||
d.PushFront(&ints[7]);
|
||||
d.PushFront(&ints[6]);
|
||||
// d == [6,7,0,1,2,4,5] // (0==mOrigin)
|
||||
static const int t2[] = {6,7,0,1,2,4,5};
|
||||
TEST(VerifyContents(d, t2, 7), "verify contents t2");
|
||||
|
||||
d.RemoveObjectAt(1);
|
||||
// d == [6,0,1,2,4,5] // (1==mOrigin)
|
||||
static const int t3[] = {6,0,1,2,4,5};
|
||||
TEST(VerifyContents(d, t3, 6), "verify contents t3");
|
||||
|
||||
d.RemoveObjectAt(5);
|
||||
// d == [6,0,1,2,4] // (1==mOrigin)
|
||||
static const int t4[] = {6,0,1,2,4};
|
||||
TEST(VerifyContents(d, t4, 5), "verify contents t4");
|
||||
|
||||
d.RemoveObjectAt(0);
|
||||
// d == [0,1,2,4] // (2==mOrigin)
|
||||
static const int t5[] = {0,1,2,4};
|
||||
TEST(VerifyContents(d, t5, 4), "verify contents t5");
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main (void) {
|
||||
ScopedXPCOM xpcom("TestTimers");
|
||||
NS_ENSURE_FALSE(xpcom.failed(), 1);
|
||||
|
||||
_TestDeque test;
|
||||
int result = test.Test();
|
||||
TEST(result == 0, "All tests pass");
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user