diff options
author | Dirk Sigurdson <dirk.sigurdson@t-mobile.com> | 2010-02-07 01:49:14 -0800 |
---|---|---|
committer | Dirk Sigurdson <dirk.sigurdson@t-mobile.com> | 2010-02-07 01:49:14 -0800 |
commit | b95e715706d92e7c3225737115919c115c957de4 (patch) | |
tree | 60cb3c974e136d4a261510d8b36aa1c231a1d6bf /libs | |
parent | 5d29366790e8fe6239d66e1e662ab05068b0549b (diff) | |
parent | 6ff3f8add87358b8489fa3f1705cf3bbfa34bc38 (diff) | |
download | frameworks_base-b95e715706d92e7c3225737115919c115c957de4.zip frameworks_base-b95e715706d92e7c3225737115919c115c957de4.tar.gz frameworks_base-b95e715706d92e7c3225737115919c115c957de4.tar.bz2 |
Merge remote branch 'korg/eclair' into themes-eclair
Conflicts:
core/java/android/app/ActivityThread.java
core/java/android/content/pm/ActivityInfo.java
core/java/android/content/res/AssetManager.java
Diffstat (limited to 'libs')
32 files changed, 770 insertions, 435 deletions
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp index ebd470f..2024cc0 100644 --- a/libs/audioflinger/AudioFlinger.cpp +++ b/libs/audioflinger/AudioFlinger.cpp @@ -674,32 +674,13 @@ void AudioFlinger::binderDied(const wp<IBinder>& who) { } // audioConfigChanged_l() must be called with AudioFlinger::mLock held -void AudioFlinger::audioConfigChanged_l(int event, const sp<ThreadBase>& thread, void *param2) { - int ioHandle = 0; - - for (size_t i = 0; i < mPlaybackThreads.size(); i++) { - if (mPlaybackThreads.valueAt(i) == thread) { - ioHandle = mPlaybackThreads.keyAt(i); - break; - } - } - if (ioHandle == 0) { - for (size_t i = 0; i < mRecordThreads.size(); i++) { - if (mRecordThreads.valueAt(i) == thread) { - ioHandle = mRecordThreads.keyAt(i); - break; - } - } - } - - if (ioHandle != 0) { - size_t size = mNotificationClients.size(); - for (size_t i = 0; i < size; i++) { - sp<IBinder> binder = mNotificationClients.itemAt(i); - LOGV("audioConfigChanged_l() Notifying change to client %p", binder.get()); - sp<IAudioFlingerClient> client = interface_cast<IAudioFlingerClient> (binder); - client->ioConfigChanged(event, ioHandle, param2); - } +void AudioFlinger::audioConfigChanged_l(int event, int ioHandle, void *param2) { + size_t size = mNotificationClients.size(); + for (size_t i = 0; i < size; i++) { + sp<IBinder> binder = mNotificationClients.itemAt(i); + LOGV("audioConfigChanged_l() Notifying change to client %p", binder.get()); + sp<IAudioFlingerClient> client = interface_cast<IAudioFlingerClient> (binder); + client->ioConfigChanged(event, ioHandle, param2); } } @@ -712,10 +693,10 @@ void AudioFlinger::removeClient_l(pid_t pid) // ---------------------------------------------------------------------------- -AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger) +AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, int id) : Thread(false), mAudioFlinger(audioFlinger), mSampleRate(0), mFrameCount(0), mChannelCount(0), - mFormat(0), mFrameSize(1), mStandby(false) + mFormat(0), mFrameSize(1), mStandby(false), mId(id), mExiting(false) { } @@ -734,6 +715,7 @@ void AudioFlinger::ThreadBase::exit() LOGV("ThreadBase::exit"); { AutoMutex lock(&mLock); + mExiting = true; requestExit(); mWaitWorkCV.signal(); } @@ -870,8 +852,8 @@ status_t AudioFlinger::ThreadBase::dumpBase(int fd, const Vector<String16>& args // ---------------------------------------------------------------------------- -AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output) - : ThreadBase(audioFlinger), +AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id) + : ThreadBase(audioFlinger, id), mMixBuffer(0), mSuspended(0), mBytesWritten(0), mOutput(output), mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false) { @@ -1106,15 +1088,6 @@ status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track) { status_t status = ALREADY_EXISTS; - // here the track could be either new, or restarted - // in both cases "unstop" the track - if (track->isPaused()) { - track->mState = TrackBase::RESUMING; - LOGV("PAUSED => RESUMING (%d) on thread %p", track->name(), this); - } else { - track->mState = TrackBase::ACTIVE; - LOGV("? => ACTIVE (%d) on thread %p", track->name(), this); - } // set retry count for buffer fill track->mRetryCount = kMaxTrackStartupRetries; if (mActiveTracks.indexOf(track) < 0) { @@ -1138,7 +1111,6 @@ void AudioFlinger::PlaybackThread::destroyTrack_l(const sp<Track>& track) { track->mState = TrackBase::TERMINATED; if (mActiveTracks.indexOf(track) < 0) { - LOGV("remove track (%d) and delete from mixer", track->name()); mTracks.remove(track); deleteTrackName_l(track->name()); } @@ -1173,7 +1145,7 @@ void AudioFlinger::PlaybackThread::audioConfigChanged(int event, int param) { break; } Mutex::Autolock _l(mAudioFlinger->mLock); - mAudioFlinger->audioConfigChanged_l(event, this, param2); + mAudioFlinger->audioConfigChanged_l(event, mId, param2); } void AudioFlinger::PlaybackThread::readOutputParameters() @@ -1185,7 +1157,6 @@ void AudioFlinger::PlaybackThread::readOutputParameters() mFrameSize = mOutput->frameSize(); mFrameCount = mOutput->bufferSize() / mFrameSize; - mMinBytesToWrite = (mOutput->latency() * mSampleRate * mFrameSize) / 1000; // FIXME - Current mixer implementation only supports stereo output: Always // Allocate a stereo buffer even if HW output is mono. if (mMixBuffer != NULL) delete mMixBuffer; @@ -1195,8 +1166,8 @@ void AudioFlinger::PlaybackThread::readOutputParameters() // ---------------------------------------------------------------------------- -AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output) - : PlaybackThread(audioFlinger, output), +AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id) + : PlaybackThread(audioFlinger, output, id), mAudioMixer(0) { mType = PlaybackThread::MIXER; @@ -1215,23 +1186,25 @@ AudioFlinger::MixerThread::~MixerThread() bool AudioFlinger::MixerThread::threadLoop() { - uint32_t sleepTime = 1000; - uint32_t maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs(); int16_t* curBuf = mMixBuffer; Vector< sp<Track> > tracksToRemove; - size_t enabledTracks = 0; + uint32_t mixerStatus = MIXER_IDLE; nsecs_t standbyTime = systemTime(); size_t mixBufferSize = mFrameCount * mFrameSize; // FIXME: Relaxed timing because of a certain device that can't meet latency // Should be reduced to 2x after the vendor fixes the driver issue nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 3; nsecs_t lastWarning = 0; + bool longStandbyExit = false; + uint32_t activeSleepTime = activeSleepTimeUs(); + uint32_t idleSleepTime = idleSleepTimeUs(); + uint32_t sleepTime = idleSleepTime; while (!exitPending()) { processConfigEvents(); - enabledTracks = 0; + mixerStatus = MIXER_IDLE; { // scope for mLock Mutex::Autolock _l(mLock); @@ -1241,7 +1214,8 @@ bool AudioFlinger::MixerThread::threadLoop() // FIXME: Relaxed timing because of a certain device that can't meet latency // Should be reduced to 2x after the vendor fixes the driver issue maxPeriod = seconds(mFrameCount) / mSampleRate * 3; - maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs(); + activeSleepTime = activeSleepTimeUs(); + idleSleepTime = idleSleepTimeUs(); } const SortedVector< wp<Track> >& activeTracks = mActiveTracks; @@ -1277,15 +1251,15 @@ bool AudioFlinger::MixerThread::threadLoop() } standbyTime = systemTime() + kStandbyTimeInNsecs; - sleepTime = 1000; + sleepTime = idleSleepTime; continue; } } - enabledTracks = prepareTracks_l(activeTracks, &tracksToRemove); + mixerStatus = prepareTracks_l(activeTracks, &tracksToRemove); } - if (LIKELY(enabledTracks)) { + if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) { // mix buffers... mAudioMixer->process(curBuf); sleepTime = 0; @@ -1294,15 +1268,21 @@ bool AudioFlinger::MixerThread::threadLoop() // If no tracks are ready, sleep once for the duration of an output // buffer size, then write 0s to the output if (sleepTime == 0) { - sleepTime = maxBufferRecoveryInUsecs; - } else if (mBytesWritten != 0) { + if (mixerStatus == MIXER_TRACKS_ENABLED) { + sleepTime = activeSleepTime; + } else { + sleepTime = idleSleepTime; + } + } else if (mBytesWritten != 0 || + (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)) { memset (curBuf, 0, mixBufferSize); sleepTime = 0; + LOGV_IF((mBytesWritten == 0 && (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)), "anticipated start"); } } if (mSuspended) { - sleepTime = maxBufferRecoveryInUsecs; + sleepTime = idleSleepTime; } // sleepTime == 0 means we must write to audio hardware if (sleepTime == 0) { @@ -1312,7 +1292,6 @@ bool AudioFlinger::MixerThread::threadLoop() if (bytesWritten > 0) mBytesWritten += bytesWritten; mNumWrites++; mInWrite = false; - mStandby = false; nsecs_t now = systemTime(); nsecs_t delta = now - mLastWriteTime; if (delta > maxPeriod) { @@ -1322,7 +1301,11 @@ bool AudioFlinger::MixerThread::threadLoop() ns2ms(delta), mNumDelayedWrites, this); lastWarning = now; } + if (mStandby) { + longStandbyExit = true; + } } + mStandby = false; } else { usleep(sleepTime); } @@ -1342,10 +1325,10 @@ bool AudioFlinger::MixerThread::threadLoop() } // prepareTracks_l() must be called with ThreadBase::mLock held -size_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove) +uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove) { - size_t enabledTracks = 0; + uint32_t mixerStatus = MIXER_IDLE; // find out which tracks need to be processed size_t count = activeTracks.size(); for (size_t i=0 ; i<count ; i++) { @@ -1415,7 +1398,7 @@ size_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track> // reset retry count track->mRetryCount = kMaxTrackRetries; - enabledTracks++; + mixerStatus = MIXER_TRACKS_READY; } else { //LOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server); if (track->isStopped()) { @@ -1432,16 +1415,11 @@ size_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track> if (--(track->mRetryCount) <= 0) { LOGV("BUFFER TIMEOUT: remove(%d) from active list on thread %p", track->name(), this); tracksToRemove->add(track); + } else if (mixerStatus != MIXER_TRACKS_READY) { + mixerStatus = MIXER_TRACKS_ENABLED; } - // For tracks using static shared memory buffer, make sure that we have - // written enough data to audio hardware before disabling the track - // NOTE: this condition with arrive before track->mRetryCount <= 0 so we - // don't care about code removing track from active list above. - if ((track->mSharedBuffer == 0) || (mBytesWritten >= mMinBytesToWrite)) { - mAudioMixer->disable(AudioMixer::MIXING); - } else { - enabledTracks++; - } + + mAudioMixer->disable(AudioMixer::MIXING); } } } @@ -1459,7 +1437,7 @@ size_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track> } } - return enabledTracks; + return mixerStatus; } void AudioFlinger::MixerThread::getTracks( @@ -1532,6 +1510,7 @@ int AudioFlinger::MixerThread::getTrackName_l() // deleteTrackName_l() must be called with ThreadBase::mLock held void AudioFlinger::MixerThread::deleteTrackName_l(int name) { + LOGV("remove track (%d) and delete from mixer", name); mAudioMixer->deleteTrackName(name); } @@ -1621,19 +1600,19 @@ status_t AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16> return NO_ERROR; } -uint32_t AudioFlinger::MixerThread::getMaxBufferRecoveryInUsecs() +uint32_t AudioFlinger::MixerThread::activeSleepTimeUs() { - uint32_t time = ((mFrameCount * 1000) / mSampleRate) * 1000; - // Add some margin with regard to scheduling precision - if (time > 10000) { - time -= 10000; - } - return time; + return (uint32_t)(mOutput->latency() * 1000) / 2; +} + +uint32_t AudioFlinger::MixerThread::idleSleepTimeUs() +{ + return (uint32_t)((mFrameCount * 1000) / mSampleRate) * 1000; } // ---------------------------------------------------------------------------- -AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output) - : PlaybackThread(audioFlinger, output), +AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id) + : PlaybackThread(audioFlinger, output, id), mLeftVolume (1.0), mRightVolume(1.0) { mType = PlaybackThread::DIRECT; @@ -1646,25 +1625,31 @@ AudioFlinger::DirectOutputThread::~DirectOutputThread() bool AudioFlinger::DirectOutputThread::threadLoop() { - uint32_t sleepTime = 1000; - uint32_t maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs(); + uint32_t mixerStatus = MIXER_IDLE; sp<Track> trackToRemove; sp<Track> activeTrack; nsecs_t standbyTime = systemTime(); int8_t *curBuf; size_t mixBufferSize = mFrameCount*mFrameSize; + uint32_t activeSleepTime = activeSleepTimeUs(); + uint32_t idleSleepTime = idleSleepTimeUs(); + uint32_t sleepTime = idleSleepTime; + while (!exitPending()) { processConfigEvents(); + mixerStatus = MIXER_IDLE; + { // scope for the mLock Mutex::Autolock _l(mLock); if (checkForNewParameters_l()) { mixBufferSize = mFrameCount*mFrameSize; - maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs(); + activeSleepTime = activeSleepTimeUs(); + idleSleepTime = idleSleepTimeUs(); } // put audio hardware into standby after short delay @@ -1698,7 +1683,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop() } standbyTime = systemTime() + kStandbyTimeInNsecs; - sleepTime = 1000; + sleepTime = idleSleepTime; continue; } } @@ -1753,6 +1738,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop() // reset retry count track->mRetryCount = kMaxTrackRetries; activeTrack = t; + mixerStatus = MIXER_TRACKS_READY; } else { //LOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server); if (track->isStopped()) { @@ -1768,16 +1754,10 @@ bool AudioFlinger::DirectOutputThread::threadLoop() if (--(track->mRetryCount) <= 0) { LOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name()); trackToRemove = track; + } else { + mixerStatus = MIXER_TRACKS_ENABLED; } - - // For tracks using static shared memry buffer, make sure that we have - // written enough data to audio hardware before disabling the track - // NOTE: this condition with arrive before track->mRetryCount <= 0 so we - // don't care about code removing track from active list above. - if ((track->mSharedBuffer != 0) && (mBytesWritten < mMinBytesToWrite)) { - activeTrack = t; - } - } + } } } @@ -1791,7 +1771,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop() } } - if (activeTrack != 0) { + if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) { AudioBufferProvider::Buffer buffer; size_t frameCount = mFrameCount; curBuf = (int8_t *)mMixBuffer; @@ -1812,7 +1792,11 @@ bool AudioFlinger::DirectOutputThread::threadLoop() standbyTime = systemTime() + kStandbyTimeInNsecs; } else { if (sleepTime == 0) { - sleepTime = maxBufferRecoveryInUsecs; + if (mixerStatus == MIXER_TRACKS_ENABLED) { + sleepTime = activeSleepTime; + } else { + sleepTime = idleSleepTime; + } } else if (mBytesWritten != 0 && AudioSystem::isLinearPCM(mFormat)) { memset (mMixBuffer, 0, mFrameCount * mFrameSize); sleepTime = 0; @@ -1820,7 +1804,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop() } if (mSuspended) { - sleepTime = maxBufferRecoveryInUsecs; + sleepTime = idleSleepTime; } // sleepTime == 0 means we must write to audio hardware if (sleepTime == 0) { @@ -1905,15 +1889,22 @@ bool AudioFlinger::DirectOutputThread::checkForNewParameters_l() return reconfig; } -uint32_t AudioFlinger::DirectOutputThread::getMaxBufferRecoveryInUsecs() +uint32_t AudioFlinger::DirectOutputThread::activeSleepTimeUs() { uint32_t time; if (AudioSystem::isLinearPCM(mFormat)) { - time = ((mFrameCount * 1000) / mSampleRate) * 1000; - // Add some margin with regard to scheduling precision - if (time > 10000) { - time -= 10000; - } + time = (uint32_t)(mOutput->latency() * 1000) / 2; + } else { + time = 10000; + } + return time; +} + +uint32_t AudioFlinger::DirectOutputThread::idleSleepTimeUs() +{ + uint32_t time; + if (AudioSystem::isLinearPCM(mFormat)) { + time = (uint32_t)((mFrameCount * 1000) / mSampleRate) * 1000; } else { time = 10000; } @@ -1922,8 +1913,8 @@ uint32_t AudioFlinger::DirectOutputThread::getMaxBufferRecoveryInUsecs() // ---------------------------------------------------------------------------- -AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger, AudioFlinger::MixerThread* mainThread) - : MixerThread(audioFlinger, mainThread->getOutput()) +AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger, AudioFlinger::MixerThread* mainThread, int id) + : MixerThread(audioFlinger, mainThread->getOutput(), id) { mType = PlaybackThread::DUPLICATING; addOutputTrack(mainThread); @@ -1931,33 +1922,38 @@ AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audio AudioFlinger::DuplicatingThread::~DuplicatingThread() { + for (size_t i = 0; i < mOutputTracks.size(); i++) { + mOutputTracks[i]->destroy(); + } mOutputTracks.clear(); } bool AudioFlinger::DuplicatingThread::threadLoop() { - uint32_t sleepTime = 1000; - uint32_t maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs(); int16_t* curBuf = mMixBuffer; Vector< sp<Track> > tracksToRemove; - size_t enabledTracks = 0; + uint32_t mixerStatus = MIXER_IDLE; nsecs_t standbyTime = systemTime(); size_t mixBufferSize = mFrameCount*mFrameSize; SortedVector< sp<OutputTrack> > outputTracks; uint32_t writeFrames = 0; + uint32_t activeSleepTime = activeSleepTimeUs(); + uint32_t idleSleepTime = idleSleepTimeUs(); + uint32_t sleepTime = idleSleepTime; while (!exitPending()) { processConfigEvents(); - enabledTracks = 0; + mixerStatus = MIXER_IDLE; { // scope for the mLock Mutex::Autolock _l(mLock); if (checkForNewParameters_l()) { mixBufferSize = mFrameCount*mFrameSize; - maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs(); + activeSleepTime = activeSleepTimeUs(); + idleSleepTime = idleSleepTimeUs(); } const SortedVector< wp<Track> >& activeTracks = mActiveTracks; @@ -1997,22 +1993,26 @@ bool AudioFlinger::DuplicatingThread::threadLoop() } standbyTime = systemTime() + kStandbyTimeInNsecs; - sleepTime = 1000; + sleepTime = idleSleepTime; continue; } } - enabledTracks = prepareTracks_l(activeTracks, &tracksToRemove); + mixerStatus = prepareTracks_l(activeTracks, &tracksToRemove); } - if (LIKELY(enabledTracks)) { + if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) { // mix buffers... mAudioMixer->process(curBuf); sleepTime = 0; writeFrames = mFrameCount; } else { if (sleepTime == 0) { - sleepTime = maxBufferRecoveryInUsecs; + if (mixerStatus == MIXER_TRACKS_ENABLED) { + sleepTime = activeSleepTime; + } else { + sleepTime = idleSleepTime; + } } else if (mBytesWritten != 0) { // flush remaining overflow buffers in output tracks for (size_t i = 0; i < outputTracks.size(); i++) { @@ -2026,7 +2026,7 @@ bool AudioFlinger::DuplicatingThread::threadLoop() } if (mSuspended) { - sleepTime = maxBufferRecoveryInUsecs; + sleepTime = idleSleepTime; } // sleepTime == 0 means we must write to audio hardware if (sleepTime == 0) { @@ -2047,17 +2047,6 @@ bool AudioFlinger::DuplicatingThread::threadLoop() outputTracks.clear(); } - { // scope for the mLock - - Mutex::Autolock _l(mLock); - if (!mStandby) { - LOGV("DuplicatingThread() exiting out of standby"); - for (size_t i = 0; i < mOutputTracks.size(); i++) { - mOutputTracks[i]->destroy(); - } - } - } - return false; } @@ -2299,6 +2288,12 @@ void AudioFlinger::PlaybackThread::Track::destroy() { // scope for mLock sp<ThreadBase> thread = mThread.promote(); if (thread != 0) { + if (!isOutputTrack()) { + if (mState == ACTIVE || mState == RESUMING) { + AudioSystem::stopOutput(thread->id(), (AudioSystem::stream_type)mStreamType); + } + AudioSystem::releaseOutput(thread->id()); + } Mutex::Autolock _l(thread->mLock); PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); playbackThread->destroyTrack_l(this); @@ -2380,14 +2375,37 @@ bool AudioFlinger::PlaybackThread::Track::isReady() const { status_t AudioFlinger::PlaybackThread::Track::start() { + status_t status = NO_ERROR; LOGV("start(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid()); sp<ThreadBase> thread = mThread.promote(); if (thread != 0) { Mutex::Autolock _l(thread->mLock); - PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); - playbackThread->addTrack_l(this); + int state = mState; + // here the track could be either new, or restarted + // in both cases "unstop" the track + if (mState == PAUSED) { + mState = TrackBase::RESUMING; + LOGV("PAUSED => RESUMING (%d) on thread %p", mName, this); + } else { + mState = TrackBase::ACTIVE; + LOGV("? => ACTIVE (%d) on thread %p", mName, this); + } + + if (!isOutputTrack() && state != ACTIVE && state != RESUMING) { + thread->mLock.unlock(); + status = AudioSystem::startOutput(thread->id(), (AudioSystem::stream_type)mStreamType); + thread->mLock.lock(); + } + if (status == NO_ERROR) { + PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); + playbackThread->addTrack_l(this); + } else { + mState = state; + } + } else { + status = BAD_VALUE; } - return NO_ERROR; + return status; } void AudioFlinger::PlaybackThread::Track::stop() @@ -2396,6 +2414,7 @@ void AudioFlinger::PlaybackThread::Track::stop() sp<ThreadBase> thread = mThread.promote(); if (thread != 0) { Mutex::Autolock _l(thread->mLock); + int state = mState; if (mState > STOPPED) { mState = STOPPED; // If the track is not active (PAUSED and buffers full), flush buffers @@ -2405,6 +2424,11 @@ void AudioFlinger::PlaybackThread::Track::stop() } LOGV("(> STOPPED) => STOPPED (%d) on thread %p", mName, playbackThread); } + if (!isOutputTrack() && (state == ACTIVE || state == RESUMING)) { + thread->mLock.unlock(); + AudioSystem::stopOutput(thread->id(), (AudioSystem::stream_type)mStreamType); + thread->mLock.lock(); + } } } @@ -2417,6 +2441,11 @@ void AudioFlinger::PlaybackThread::Track::pause() if (mState == ACTIVE || mState == RESUMING) { mState = PAUSING; LOGV("ACTIVE/RESUMING => PAUSING (%d) on thread %p", mName, thread.get()); + if (!isOutputTrack()) { + thread->mLock.unlock(); + AudioSystem::stopOutput(thread->id(), (AudioSystem::stream_type)mStreamType); + thread->mLock.lock(); + } } } } @@ -2500,6 +2529,10 @@ AudioFlinger::RecordThread::RecordTrack::RecordTrack( AudioFlinger::RecordThread::RecordTrack::~RecordTrack() { + sp<ThreadBase> thread = mThread.promote(); + if (thread != 0) { + AudioSystem::releaseInput(thread->id()); + } } status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer) @@ -2547,8 +2580,9 @@ status_t AudioFlinger::RecordThread::RecordTrack::start() if (thread != 0) { RecordThread *recordThread = (RecordThread *)thread.get(); return recordThread->start(this); + } else { + return BAD_VALUE; } - return NO_INIT; } void AudioFlinger::RecordThread::RecordTrack::stop() @@ -2985,8 +3019,8 @@ status_t AudioFlinger::RecordHandle::onTransact( // ---------------------------------------------------------------------------- -AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, AudioStreamIn *input, uint32_t sampleRate, uint32_t channels) : - ThreadBase(audioFlinger), +AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, AudioStreamIn *input, uint32_t sampleRate, uint32_t channels, int id) : + ThreadBase(audioFlinger, id), mInput(input), mResampler(0), mRsmpOutBuffer(0), mRsmpInBuffer(0) { mReqChannelCount = AudioSystem::popCount(channels); @@ -3014,6 +3048,7 @@ void AudioFlinger::RecordThread::onFirstRef() run(buffer, PRIORITY_URGENT_AUDIO); } + bool AudioFlinger::RecordThread::threadLoop() { AudioBufferProvider::Buffer buffer; @@ -3043,22 +3078,37 @@ bool AudioFlinger::RecordThread::threadLoop() } if (mActiveTrack != 0) { if (mActiveTrack->mState == TrackBase::PAUSING) { + if (!mStandby) { + mInput->standby(); + mStandby = true; + } mActiveTrack.clear(); mStartStopCond.broadcast(); } else if (mActiveTrack->mState == TrackBase::RESUMING) { - mRsmpInIndex = mFrameCount; if (mReqChannelCount != mActiveTrack->channelCount()) { mActiveTrack.clear(); - } else { - mActiveTrack->mState = TrackBase::ACTIVE; + mStartStopCond.broadcast(); + } else if (mBytesRead != 0) { + // record start succeeds only if first read from audio input + // succeeds + if (mBytesRead > 0) { + mActiveTrack->mState = TrackBase::ACTIVE; + } else { + mActiveTrack.clear(); + } + mStartStopCond.broadcast(); } - mStartStopCond.broadcast(); + mStandby = false; } - mStandby = false; } } if (mActiveTrack != 0) { + if (mActiveTrack->mState != TrackBase::ACTIVE && + mActiveTrack->mState != TrackBase::RESUMING) { + usleep(5000); + continue; + } buffer.frameCount = mFrameCount; if (LIKELY(mActiveTrack->getNextBuffer(&buffer) == NO_ERROR)) { size_t framesOut = buffer.frameCount; @@ -3093,18 +3143,19 @@ bool AudioFlinger::RecordThread::threadLoop() } } if (framesOut && mFrameCount == mRsmpInIndex) { - ssize_t bytesRead; if (framesOut == mFrameCount && (mChannelCount == mReqChannelCount || mFormat != AudioSystem::PCM_16_BIT)) { - bytesRead = mInput->read(buffer.raw, mInputBytes); + mBytesRead = mInput->read(buffer.raw, mInputBytes); framesOut = 0; } else { - bytesRead = mInput->read(mRsmpInBuffer, mInputBytes); + mBytesRead = mInput->read(mRsmpInBuffer, mInputBytes); mRsmpInIndex = 0; } - if (bytesRead < 0) { + if (mBytesRead < 0) { LOGE("Error reading audio input"); - sleep(1); + if (mActiveTrack->mState == TrackBase::ACTIVE) { + sleep(1); + } mRsmpInIndex = mFrameCount; framesOut = 0; buffer.frameCount = 0; @@ -3156,6 +3207,8 @@ bool AudioFlinger::RecordThread::threadLoop() } mActiveTrack.clear(); + mStartStopCond.broadcast(); + LOGV("RecordThread %p exiting", this); return false; } @@ -3163,37 +3216,74 @@ bool AudioFlinger::RecordThread::threadLoop() status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack) { LOGV("RecordThread::start"); - AutoMutex lock(&mLock); - - if (mActiveTrack != 0) { - if (recordTrack != mActiveTrack.get()) return -EBUSY; - - if (mActiveTrack->mState == TrackBase::PAUSING) mActiveTrack->mState = TrackBase::RESUMING; - - return NO_ERROR; - } + sp <ThreadBase> strongMe = this; + status_t status = NO_ERROR; + { + AutoMutex lock(&mLock); + if (mActiveTrack != 0) { + if (recordTrack != mActiveTrack.get()) { + status = -EBUSY; + } else if (mActiveTrack->mState == TrackBase::PAUSING) { + mActiveTrack->mState = TrackBase::ACTIVE; + } + return status; + } - mActiveTrack = recordTrack; - mActiveTrack->mState = TrackBase::RESUMING; - // signal thread to start - LOGV("Signal record thread"); - mWaitWorkCV.signal(); - mStartStopCond.wait(mLock); - if (mActiveTrack != 0) { + recordTrack->mState = TrackBase::IDLE; + mActiveTrack = recordTrack; + mLock.unlock(); + status_t status = AudioSystem::startInput(mId); + mLock.lock(); + if (status != NO_ERROR) { + mActiveTrack.clear(); + return status; + } + mActiveTrack->mState = TrackBase::RESUMING; + mRsmpInIndex = mFrameCount; + mBytesRead = 0; + // signal thread to start + LOGV("Signal record thread"); + mWaitWorkCV.signal(); + // do not wait for mStartStopCond if exiting + if (mExiting) { + mActiveTrack.clear(); + status = INVALID_OPERATION; + goto startError; + } + mStartStopCond.wait(mLock); + if (mActiveTrack == 0) { + LOGV("Record failed to start"); + status = BAD_VALUE; + goto startError; + } LOGV("Record started OK"); - return NO_ERROR; - } else { - LOGV("Record failed to start"); - return BAD_VALUE; + return status; } +startError: + AudioSystem::stopInput(mId); + return status; } void AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) { LOGV("RecordThread::stop"); - AutoMutex lock(&mLock); - if (mActiveTrack != 0 && recordTrack == mActiveTrack.get()) { - mActiveTrack->mState = TrackBase::PAUSING; - mStartStopCond.wait(mLock); + sp <ThreadBase> strongMe = this; + { + AutoMutex lock(&mLock); + if (mActiveTrack != 0 && recordTrack == mActiveTrack.get()) { + mActiveTrack->mState = TrackBase::PAUSING; + // do not wait for mStartStopCond if exiting + if (mExiting) { + return; + } + mStartStopCond.wait(mLock); + // if we have been restarted, recordTrack == mActiveTrack.get() here + if (mActiveTrack == 0 || recordTrack != mActiveTrack.get()) { + mLock.unlock(); + AudioSystem::stopInput(mId); + mLock.lock(); + LOGV("Record stopped OK"); + } + } } } @@ -3242,10 +3332,12 @@ status_t AudioFlinger::RecordThread::getNextBuffer(AudioBufferProvider::Buffer* int channelCount; if (framesReady == 0) { - ssize_t bytesRead = mInput->read(mRsmpInBuffer, mInputBytes); - if (bytesRead < 0) { + mBytesRead = mInput->read(mRsmpInBuffer, mInputBytes); + if (mBytesRead < 0) { LOGE("RecordThread::getNextBuffer() Error reading audio input"); - sleep(1); + if (mActiveTrack->mState == TrackBase::ACTIVE) { + sleep(1); + } buffer->raw = 0; buffer->frameCount = 0; return NOT_ENOUGH_DATA; @@ -3363,7 +3455,7 @@ void AudioFlinger::RecordThread::audioConfigChanged(int event, int param) { break; } Mutex::Autolock _l(mAudioFlinger->mLock); - mAudioFlinger->audioConfigChanged_l(event, this, param2); + mAudioFlinger->audioConfigChanged_l(event, mId, param2); } void AudioFlinger::RecordThread::readInputParameters() @@ -3451,21 +3543,23 @@ int AudioFlinger::openOutput(uint32_t *pDevices, if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) || (format != AudioSystem::PCM_16_BIT) || (channels != AudioSystem::CHANNEL_OUT_STEREO)) { - thread = new DirectOutputThread(this, output); - LOGV("openOutput() created direct output: ID %d thread %p", (mNextThreadId + 1), thread); + thread = new DirectOutputThread(this, output, ++mNextThreadId); + LOGV("openOutput() created direct output: ID %d thread %p", mNextThreadId, thread); } else { - thread = new MixerThread(this, output); - LOGV("openOutput() created mixer output: ID %d thread %p", (mNextThreadId + 1), thread); + thread = new MixerThread(this, output, ++mNextThreadId); + LOGV("openOutput() created mixer output: ID %d thread %p", mNextThreadId, thread); } - mPlaybackThreads.add(++mNextThreadId, thread); + mPlaybackThreads.add(mNextThreadId, thread); if (pSamplingRate) *pSamplingRate = samplingRate; if (pFormat) *pFormat = format; if (pChannels) *pChannels = channels; if (pLatencyMs) *pLatencyMs = thread->latency(); + + return mNextThreadId; } - return mNextThreadId; + return 0; } int AudioFlinger::openDuplicateOutput(int output1, int output2) @@ -3480,9 +3574,9 @@ int AudioFlinger::openDuplicateOutput(int output1, int output2) } - DuplicatingThread *thread = new DuplicatingThread(this, thread1); + DuplicatingThread *thread = new DuplicatingThread(this, thread1, ++mNextThreadId); thread->addOutputTrack(thread2); - mPlaybackThreads.add(++mNextThreadId, thread); + mPlaybackThreads.add(mNextThreadId, thread); return mNextThreadId; } @@ -3509,7 +3603,7 @@ status_t AudioFlinger::closeOutput(int output) } } void *param2 = 0; - audioConfigChanged_l(AudioSystem::OUTPUT_CLOSED, thread, param2); + audioConfigChanged_l(AudioSystem::OUTPUT_CLOSED, output, param2); mPlaybackThreads.removeItem(output); } thread->exit(); @@ -3603,17 +3697,19 @@ int AudioFlinger::openInput(uint32_t *pDevices, if (input != 0) { // Start record thread - thread = new RecordThread(this, input, reqSamplingRate, reqChannels); - mRecordThreads.add(++mNextThreadId, thread); + thread = new RecordThread(this, input, reqSamplingRate, reqChannels, ++mNextThreadId); + mRecordThreads.add(mNextThreadId, thread); LOGV("openInput() created record thread: ID %d thread %p", mNextThreadId, thread); if (pSamplingRate) *pSamplingRate = reqSamplingRate; if (pFormat) *pFormat = format; if (pChannels) *pChannels = reqChannels; input->standby(); + + return mNextThreadId; } - return mNextThreadId; + return 0; } status_t AudioFlinger::closeInput(int input) @@ -3630,7 +3726,7 @@ status_t AudioFlinger::closeInput(int input) LOGV("closeInput() %d", input); void *param2 = 0; - audioConfigChanged_l(AudioSystem::INPUT_CLOSED, thread, param2); + audioConfigChanged_l(AudioSystem::INPUT_CLOSED, input, param2); mRecordThreads.removeItem(input); } thread->exit(); diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h index 22d15c9..8c29da8 100644 --- a/libs/audioflinger/AudioFlinger.h +++ b/libs/audioflinger/AudioFlinger.h @@ -213,7 +213,7 @@ private: class ThreadBase : public Thread { public: - ThreadBase (const sp<AudioFlinger>& audioFlinger); + ThreadBase (const sp<AudioFlinger>& audioFlinger, int id); virtual ~ThreadBase(); status_t dumpBase(int fd, const Vector<String16>& args); @@ -323,6 +323,7 @@ private: void sendConfigEvent(int event, int param = 0); void sendConfigEvent_l(int event, int param = 0); void processConfigEvents(); + int id() const { return mId;} mutable Mutex mLock; @@ -349,6 +350,8 @@ private: status_t mParamStatus; Vector<ConfigEvent *> mConfigEvents; bool mStandby; + int mId; + bool mExiting; }; // --- PlaybackThread --- @@ -361,6 +364,12 @@ private: DUPLICATING }; + enum mixer_state { + MIXER_IDLE, + MIXER_TRACKS_ENABLED, + MIXER_TRACKS_READY + }; + // playback track class Track : public TrackBase { public: @@ -415,6 +424,10 @@ private: void setPaused() { mState = PAUSED; } void reset(); + bool isOutputTrack() const { + return (mStreamType == AudioSystem::NUM_STREAM_TYPES); + } + // we don't really need a lock for these float mVolume[2]; volatile bool mMute; @@ -467,7 +480,7 @@ private: }; // end of OutputTrack - PlaybackThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output); + PlaybackThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id); virtual ~PlaybackThread(); virtual status_t dump(int fd, const Vector<String16>& args); @@ -530,7 +543,8 @@ private: virtual int getTrackName_l() = 0; virtual void deleteTrackName_l(int name) = 0; - virtual uint32_t getMaxBufferRecoveryInUsecs() = 0; + virtual uint32_t activeSleepTimeUs() = 0; + virtual uint32_t idleSleepTimeUs() = 0; private: @@ -562,12 +576,11 @@ private: int mNumWrites; int mNumDelayedWrites; bool mInWrite; - int mMinBytesToWrite; }; class MixerThread : public PlaybackThread { public: - MixerThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output); + MixerThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id); virtual ~MixerThread(); // Thread virtuals @@ -582,10 +595,11 @@ private: virtual status_t dumpInternals(int fd, const Vector<String16>& args); protected: - size_t prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove); + uint32_t prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove); virtual int getTrackName_l(); virtual void deleteTrackName_l(int name); - virtual uint32_t getMaxBufferRecoveryInUsecs(); + virtual uint32_t activeSleepTimeUs(); + virtual uint32_t idleSleepTimeUs(); AudioMixer* mAudioMixer; }; @@ -593,7 +607,7 @@ private: class DirectOutputThread : public PlaybackThread { public: - DirectOutputThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output); + DirectOutputThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id); ~DirectOutputThread(); // Thread virtuals @@ -604,7 +618,8 @@ private: protected: virtual int getTrackName_l(); virtual void deleteTrackName_l(int name); - virtual uint32_t getMaxBufferRecoveryInUsecs(); + virtual uint32_t activeSleepTimeUs(); + virtual uint32_t idleSleepTimeUs(); private: float mLeftVolume; @@ -613,7 +628,7 @@ private: class DuplicatingThread : public MixerThread { public: - DuplicatingThread (const sp<AudioFlinger>& audioFlinger, MixerThread* mainThread); + DuplicatingThread (const sp<AudioFlinger>& audioFlinger, MixerThread* mainThread, int id); ~DuplicatingThread(); // Thread virtuals @@ -629,7 +644,7 @@ private: MixerThread *checkMixerThread_l(int output) const; RecordThread *checkRecordThread_l(int input) const; float streamVolumeInternal(int stream) const { return mStreamTypes[stream].volume; } - void audioConfigChanged_l(int event, const sp<ThreadBase>& thread, void *param2); + void audioConfigChanged_l(int event, int ioHandle, void *param2); friend class AudioBuffer; @@ -697,7 +712,8 @@ private: RecordThread(const sp<AudioFlinger>& audioFlinger, AudioStreamIn *input, uint32_t sampleRate, - uint32_t channels); + uint32_t channels, + int id); ~RecordThread(); virtual bool threadLoop(); @@ -728,6 +744,7 @@ private: size_t mInputBytes; int mReqChannelCount; uint32_t mReqSampleRate; + ssize_t mBytesRead; }; class RecordHandle : public android::BnAudioRecord { diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp index d7daf73..2d4e10d 100644 --- a/libs/binder/ProcessState.cpp +++ b/libs/binder/ProcessState.cpp @@ -41,7 +41,7 @@ #include <sys/mman.h> #include <sys/stat.h> -#define BINDER_VM_SIZE (1*1024*1024) +#define BINDER_VM_SIZE ((1*1024*1024) - (4096 *2)) static bool gSingleProcess = false; diff --git a/libs/rs/RenderScript.h b/libs/rs/RenderScript.h index 9b04393..3ca8b15 100644 --- a/libs/rs/RenderScript.h +++ b/libs/rs/RenderScript.h @@ -55,7 +55,7 @@ RsDevice rsDeviceCreate(); void rsDeviceDestroy(RsDevice); void rsDeviceSetConfig(RsDevice, RsDeviceParam, int32_t value); -RsContext rsContextCreate(RsDevice, void *, uint32_t version, bool useDepth); +RsContext rsContextCreate(RsDevice, uint32_t version, bool useDepth); void rsContextDestroy(RsContext); void rsObjDestroyOOB(RsContext, void *); diff --git a/libs/rs/java/Fountain/src/com/android/fountain/FountainView.java b/libs/rs/java/Fountain/src/com/android/fountain/FountainView.java index cda005e..1e7c5a2 100644 --- a/libs/rs/java/Fountain/src/com/android/fountain/FountainView.java +++ b/libs/rs/java/Fountain/src/com/android/fountain/FountainView.java @@ -48,29 +48,25 @@ public class FountainView extends RSSurfaceView { private RenderScript mRS; private FountainRS mRender; - private void destroyRS() { - if(mRS != null) { - mRS = null; - destroyRenderScript(); - } - java.lang.System.gc(); - } - public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { super.surfaceChanged(holder, format, w, h); - destroyRS(); - mRS = createRenderScript(false, true); - mRender = new FountainRS(); - mRender.init(mRS, getResources(), w, h); + if (mRS == null) { + mRS = createRenderScript(false, true); + mRS.contextSetSurface(w, h, holder.getSurface()); + mRender = new FountainRS(); + mRender.init(mRS, getResources(), w, h); + } } - public void surfaceDestroyed(SurfaceHolder holder) { - // Surface will be destroyed when we return - destroyRS(); + @Override + protected void onDetachedFromWindow() { + if(mRS != null) { + mRS = null; + destroyRenderScript(); + } } - @Override public boolean onTouchEvent(MotionEvent ev) { diff --git a/libs/rs/java/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java b/libs/rs/java/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java index b1facfc..334fd9c 100644 --- a/libs/rs/java/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java +++ b/libs/rs/java/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java @@ -126,13 +126,14 @@ public class ImageProcessingActivity extends Activity implements SurfaceHolder.C } public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { + mRS.contextSetSurface(width, height, holder.getSurface()); } public void surfaceDestroyed(SurfaceHolder holder) { } private Script.Invokable createScript() { - mRS = new RenderScript(mSurfaceView.getHolder().getSurface(), false, false); + mRS = new RenderScript(false, false); mRS.mMessageCallback = new FilterCallback(); mParamsType = Type.createFromClass(mRS, Params.class, 1, "Parameters"); diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec index 865e435..a4e72d9 100644 --- a/libs/rs/rs.spec +++ b/libs/rs/rs.spec @@ -37,9 +37,19 @@ ContextResume { } ContextSetSurface { + param uint32_t width + param uint32_t height param void *sur } +ContextDump { + param int32_t bits +} + +ContextSetPriority { + param int32_t priority + } + AssignName { param void *obj param const char *name diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp index 16029a6..ff8d29f 100644 --- a/libs/rs/rsAllocation.cpp +++ b/libs/rs/rsAllocation.cpp @@ -88,7 +88,7 @@ bool Allocation::fixAllocation() return false; } -void Allocation::uploadToTexture(uint32_t lodOffset) +void Allocation::uploadToTexture(Context *rsc, uint32_t lodOffset) { //rsAssert(!mTextureId); rsAssert(lodOffset < mType->getLODCount()); @@ -102,6 +102,15 @@ void Allocation::uploadToTexture(uint32_t lodOffset) if (!mTextureID) { glGenTextures(1, &mTextureID); + + if (!mTextureID) { + // This should not happen, however, its likely the cause of the + // white sqare bug. + // Force a crash to 1: restart the app, 2: make sure we get a bugreport. + LOGE("Upload to texture failed to gen mTextureID"); + rsc->dumpDebug(); + ((char *)0)[0] = 0; + } } glBindTexture(GL_TEXTURE_2D, mTextureID); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); @@ -190,6 +199,24 @@ void Allocation::subData(uint32_t xoff, uint32_t yoff, uint32_t zoff, { } +void Allocation::dumpLOGV(const char *prefix) const +{ + ObjectBase::dumpLOGV(prefix); + + String8 s(prefix); + s.append(" type "); + if (mType.get()) { + mType->dumpLOGV(s.string()); + } + + LOGV("%s allocation ptr=%p mCpuWrite=%i, mCpuRead=%i, mGpuWrite=%i, mGpuRead=%i", + prefix, mPtr, mCpuWrite, mCpuRead, mGpuWrite, mGpuRead); + + LOGV("%s allocation mIsTexture=%i mTextureID=%i, mIsVertexBuffer=%i, mBufferID=%i", + prefix, mIsTexture, mTextureID, mIsVertexBuffer, mBufferID); + + +} ///////////////// @@ -220,7 +247,7 @@ RsAllocation rsi_AllocationCreateSized(Context *rsc, RsElement e, size_t count) void rsi_AllocationUploadToTexture(Context *rsc, RsAllocation va, uint32_t baseMipLevel) { Allocation *alloc = static_cast<Allocation *>(va); - alloc->uploadToTexture(baseMipLevel); + alloc->uploadToTexture(rsc, baseMipLevel); } void rsi_AllocationUploadToBufferObject(Context *rsc, RsAllocation va) @@ -382,7 +409,6 @@ RsAllocation rsi_AllocationCreateFromBitmap(Context *rsc, uint32_t w, uint32_t h LOGE("Memory allocation failure"); return NULL; } - texAlloc->incUserRef(); ElementConverter_t cvt = pickConverter(dst, src); cvt(texAlloc->getPtr(), data, w * h); diff --git a/libs/rs/rsAllocation.h b/libs/rs/rsAllocation.h index 1b83267..f54284a 100644 --- a/libs/rs/rsAllocation.h +++ b/libs/rs/rsAllocation.h @@ -46,7 +46,7 @@ public: void * getPtr() const {return mPtr;} const Type * getType() const {return mType.get();} - void uploadToTexture(uint32_t lodOffset = 0); + void uploadToTexture(Context *rsc, uint32_t lodOffset = 0); uint32_t getTextureID() const {return mTextureID;} void uploadToBufferObject(); @@ -65,6 +65,8 @@ public: void enableGLVertexBuffers() const; void setupGLIndexBuffers() const; + virtual void dumpLOGV(const char *prefix) const; + protected: ObjectBaseRef<const Type> mType; diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp index 3e4cc36..3652f0a 100644 --- a/libs/rs/rsContext.cpp +++ b/libs/rs/rsContext.cpp @@ -20,11 +20,16 @@ #include <ui/FramebufferNativeWindow.h> #include <ui/EGLUtils.h> +#include <sys/types.h> +#include <sys/resource.h> + #include <cutils/properties.h> #include <GLES/gl.h> #include <GLES/glext.h> +#include <cutils/sched_policy.h> + using namespace android; using namespace android::renderscript; @@ -92,38 +97,12 @@ void Context::initEGL() LOGE("eglCreateContext returned EGL_NO_CONTEXT"); } gGLContextCount++; - - if (mWndSurface) { - setSurface(mWndSurface); - } else { - setSurface((Surface *)android_createDisplaySurface()); - } - - eglQuerySurface(mEGL.mDisplay, mEGL.mSurface, EGL_WIDTH, &mEGL.mWidth); - eglQuerySurface(mEGL.mDisplay, mEGL.mSurface, EGL_HEIGHT, &mEGL.mHeight); - - - mGL.mVersion = glGetString(GL_VERSION); - mGL.mVendor = glGetString(GL_VENDOR); - mGL.mRenderer = glGetString(GL_RENDERER); - mGL.mExtensions = glGetString(GL_EXTENSIONS); - - LOGV("EGL Version %i %i", mEGL.mMajorVersion, mEGL.mMinorVersion); - LOGV("GL Version %s", mGL.mVersion); - LOGV("GL Vendor %s", mGL.mVendor); - LOGV("GL Renderer %s", mGL.mRenderer); - LOGV("GL Extensions %s", mGL.mExtensions); - - if ((strlen((const char *)mGL.mVersion) < 12) || memcmp(mGL.mVersion, "OpenGL ES-CM", 12)) { - LOGE("Error, OpenGL ES Lite not supported"); - } else { - sscanf((const char *)mGL.mVersion + 13, "%i.%i", &mGL.mMajorVersion, &mGL.mMinorVersion); - } } void Context::deinitEGL() { - setSurface(NULL); + LOGV("deinitEGL"); + setSurface(0, 0, NULL); eglDestroyContext(mEGL.mDisplay, mEGL.mContext); checkEglError("eglDestroyContext"); @@ -134,14 +113,14 @@ void Context::deinitEGL() } -bool Context::runScript(Script *s, uint32_t launchID) +uint32_t Context::runScript(Script *s, uint32_t launchID) { ObjectBaseRef<ProgramFragment> frag(mFragment); ObjectBaseRef<ProgramVertex> vtx(mVertex); ObjectBaseRef<ProgramFragmentStore> store(mFragmentStore); ObjectBaseRef<ProgramRaster> raster(mRaster); - bool ret = s->run(this, launchID); + uint32_t ret = s->run(this, launchID); mFragment.set(frag); mVertex.set(vtx); @@ -151,11 +130,9 @@ bool Context::runScript(Script *s, uint32_t launchID) } -bool Context::runRootScript() +uint32_t Context::runRootScript() { - if (props.mLogTimes) { - timerSet(RS_TIMER_CLEAR_SWAP); - } + timerSet(RS_TIMER_CLEAR_SWAP); rsAssert(mRootScript->mEnviroment.mIsRoot); eglQuerySurface(mEGL.mDisplay, mEGL.mSurface, EGL_WIDTH, &mEGL.mWidth); @@ -175,11 +152,9 @@ bool Context::runRootScript() glClear(GL_COLOR_BUFFER_BIT); } - if (this->props.mLogTimes) { - timerSet(RS_TIMER_SCRIPT); - } + timerSet(RS_TIMER_SCRIPT); mStateFragmentStore.mLast.clear(); - bool ret = runScript(mRootScript.get(), 0); + uint32_t ret = runScript(mRootScript.get(), 0); GLenum err = glGetError(); if (err != GL_NO_ERROR) { @@ -233,13 +208,19 @@ void Context::timerPrint() total += mTimers[ct]; } uint64_t frame = mTimeFrame - mTimeLastFrame; + mTimeMSLastFrame = frame / 1000000; + mTimeMSLastScript = mTimers[RS_TIMER_SCRIPT] / 1000000; + mTimeMSLastSwap = mTimers[RS_TIMER_CLEAR_SWAP] / 1000000; + - LOGV("RS: Frame (%lli), Script %2.1f (%lli), Clear & Swap %2.1f (%lli), Idle %2.1f (%lli), Internal %2.1f (%lli)", - frame / 1000000, - 100.0 * mTimers[RS_TIMER_SCRIPT] / total, mTimers[RS_TIMER_SCRIPT] / 1000000, - 100.0 * mTimers[RS_TIMER_CLEAR_SWAP] / total, mTimers[RS_TIMER_CLEAR_SWAP] / 1000000, - 100.0 * mTimers[RS_TIMER_IDLE] / total, mTimers[RS_TIMER_IDLE] / 1000000, - 100.0 * mTimers[RS_TIMER_INTERNAL] / total, mTimers[RS_TIMER_INTERNAL] / 1000000); + if (props.mLogTimes) { + LOGV("RS: Frame (%i), Script %2.1f (%i), Clear & Swap %2.1f (%i), Idle %2.1f (%lli), Internal %2.1f (%lli)", + mTimeMSLastFrame, + 100.0 * mTimers[RS_TIMER_SCRIPT] / total, mTimeMSLastScript, + 100.0 * mTimers[RS_TIMER_CLEAR_SWAP] / total, mTimeMSLastSwap, + 100.0 * mTimers[RS_TIMER_IDLE] / total, mTimers[RS_TIMER_IDLE] / 1000000, + 100.0 * mTimers[RS_TIMER_INTERNAL] / total, mTimers[RS_TIMER_INTERNAL] / 1000000); + } } void Context::setupCheck() @@ -260,14 +241,18 @@ static bool getProp(const char *str) void * Context::threadProc(void *vrsc) { Context *rsc = static_cast<Context *>(vrsc); + rsc->mNativeThreadId = gettid(); + + setpriority(PRIO_PROCESS, rsc->mNativeThreadId, ANDROID_PRIORITY_DISPLAY); + rsc->mThreadPriority = ANDROID_PRIORITY_DISPLAY; rsc->props.mLogTimes = getProp("debug.rs.profile"); rsc->props.mLogScripts = getProp("debug.rs.script"); rsc->props.mLogObjects = getProp("debug.rs.objects"); - pthread_mutex_lock(&gInitMutex); - rsc->initEGL(); - pthread_mutex_unlock(&gInitMutex); + //pthread_mutex_lock(&gInitMutex); + //rsc->initEGL(); + //pthread_mutex_unlock(&gInitMutex); ScriptTLSStruct *tlsStruct = new ScriptTLSStruct; if (!tlsStruct) { @@ -297,22 +282,26 @@ void * Context::threadProc(void *vrsc) mDraw &= (rsc->mRootScript.get() != NULL); mDraw &= (rsc->mWndSurface != NULL); + uint32_t targetTime = 0; if (mDraw) { - mDraw = rsc->runRootScript() && !rsc->mPaused; - if (rsc->props.mLogTimes) { - rsc->timerSet(RS_TIMER_CLEAR_SWAP); - } + targetTime = rsc->runRootScript(); + mDraw = targetTime && !rsc->mPaused; + rsc->timerSet(RS_TIMER_CLEAR_SWAP); eglSwapBuffers(rsc->mEGL.mDisplay, rsc->mEGL.mSurface); - if (rsc->props.mLogTimes) { - rsc->timerFrame(); - rsc->timerSet(RS_TIMER_INTERNAL); - rsc->timerPrint(); - rsc->timerReset(); - } + rsc->timerFrame(); + rsc->timerSet(RS_TIMER_INTERNAL); + rsc->timerPrint(); + rsc->timerReset(); } if (rsc->mObjDestroy.mNeedToEmpty) { rsc->objDestroyOOBRun(); } + if (rsc->mThreadPriority > 0 && targetTime) { + int32_t t = (targetTime - (int32_t)(rsc->mTimeMSLastScript + rsc->mTimeMSLastSwap)) * 1000; + if (t > 0) { + usleep(t); + } + } } LOGV("RS Thread exiting"); @@ -342,7 +331,27 @@ void * Context::threadProc(void *vrsc) return NULL; } -Context::Context(Device *dev, Surface *sur, bool useDepth) +void Context::setPriority(int32_t p) +{ + // Note: If we put this in the proper "background" policy + // the wallpapers can become completly unresponsive at times. + // This is probably not what we want for something the user is actively + // looking at. + mThreadPriority = p; +#if 0 + SchedPolicy pol = SP_FOREGROUND; + if (p > 0) { + pol = SP_BACKGROUND; + } + if (!set_sched_policy(mNativeThreadId, pol)) { + // success; reset the priority as well + } +#else + setpriority(PRIO_PROCESS, mNativeThreadId, p); +#endif +} + +Context::Context(Device *dev, bool useDepth) { pthread_mutex_lock(&gInitMutex); @@ -353,6 +362,7 @@ Context::Context(Device *dev, Surface *sur, bool useDepth) mUseDepth = useDepth; mPaused = false; mObjHead = NULL; + memset(&mEGL, 0, sizeof(mEGL)); int status; pthread_attr_t threadAttr; @@ -376,11 +386,7 @@ Context::Context(Device *dev, Surface *sur, bool useDepth) return; } - sched_param sparam; - sparam.sched_priority = ANDROID_PRIORITY_DISPLAY; - pthread_attr_setschedparam(&threadAttr, &sparam); - - mWndSurface = sur; + mWndSurface = NULL; objDestroyOOBInit(); timerInit(); @@ -426,8 +432,10 @@ Context::~Context() objDestroyOOBDestroy(); } -void Context::setSurface(Surface *sur) +void Context::setSurface(uint32_t w, uint32_t h, Surface *sur) { + LOGV("setSurface %i %i %p", w, h, sur); + EGLBoolean ret; if (mEGL.mSurface != NULL) { ret = eglMakeCurrent(mEGL.mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); @@ -437,10 +445,22 @@ void Context::setSurface(Surface *sur) checkEglError("eglDestroySurface", ret); mEGL.mSurface = NULL; + mEGL.mWidth = 0; + mEGL.mHeight = 0; + mWidth = 0; + mHeight = 0; } mWndSurface = sur; if (mWndSurface != NULL) { + bool first = false; + if (!mEGL.mContext) { + first = true; + pthread_mutex_lock(&gInitMutex); + initEGL(); + pthread_mutex_unlock(&gInitMutex); + } + mEGL.mSurface = eglCreateWindowSurface(mEGL.mDisplay, mEGL.mConfig, mWndSurface, NULL); checkEglError("eglCreateWindowSurface"); if (mEGL.mSurface == EGL_NO_SURFACE) { @@ -449,6 +469,36 @@ void Context::setSurface(Surface *sur) ret = eglMakeCurrent(mEGL.mDisplay, mEGL.mSurface, mEGL.mSurface, mEGL.mContext); checkEglError("eglMakeCurrent", ret); + + eglQuerySurface(mEGL.mDisplay, mEGL.mSurface, EGL_WIDTH, &mEGL.mWidth); + eglQuerySurface(mEGL.mDisplay, mEGL.mSurface, EGL_HEIGHT, &mEGL.mHeight); + mWidth = w; + mHeight = h; + mStateVertex.updateSize(this, w, h); + + if ((int)mWidth != mEGL.mWidth || (int)mHeight != mEGL.mHeight) { + LOGE("EGL/Surface mismatch EGL (%i x %i) SF (%i x %i)", mEGL.mWidth, mEGL.mHeight, mWidth, mHeight); + } + + if (first) { + mGL.mVersion = glGetString(GL_VERSION); + mGL.mVendor = glGetString(GL_VENDOR); + mGL.mRenderer = glGetString(GL_RENDERER); + mGL.mExtensions = glGetString(GL_EXTENSIONS); + + //LOGV("EGL Version %i %i", mEGL.mMajorVersion, mEGL.mMinorVersion); + LOGV("GL Version %s", mGL.mVersion); + LOGV("GL Vendor %s", mGL.mVendor); + LOGV("GL Renderer %s", mGL.mRenderer); + //LOGV("GL Extensions %s", mGL.mExtensions); + + if ((strlen((const char *)mGL.mVersion) < 12) || memcmp(mGL.mVersion, "OpenGL ES-CM", 12)) { + LOGE("Error, OpenGL ES Lite not supported"); + } else { + sscanf((const char *)mGL.mVersion + 13, "%i.%i", &mGL.mMajorVersion, &mGL.mMinorVersion); + } + } + } } @@ -684,6 +734,24 @@ void Context::deinitToClient() mIO.mToClient.shutdown(); } +void Context::dumpDebug() const +{ + LOGE("RS Context debug %p", this); + LOGE("RS Context debug"); + + LOGE(" EGL ver %i %i", mEGL.mMajorVersion, mEGL.mMinorVersion); + LOGE(" EGL context %p surface %p, w=%i h=%i Display=%p", mEGL.mContext, + mEGL.mSurface, mEGL.mWidth, mEGL.mHeight, mEGL.mDisplay); + LOGE(" GL vendor: %s", mGL.mVendor); + LOGE(" GL renderer: %s", mGL.mRenderer); + LOGE(" GL Version: %s", mGL.mVersion); + LOGE(" GL Extensions: %s", mGL.mExtensions); + LOGE(" GL int Versions %i %i", mGL.mMajorVersion, mGL.mMinorVersion); + LOGE(" RS width %i, height %i", mWidth, mHeight); + LOGE(" RS running %i, exit %i, useDepth %i, paused %i", mRunning, mExit, mUseDepth, mPaused); + LOGE(" RS pThreadID %li, nativeThreadID %i", mThreadId, mNativeThreadId); + +} /////////////////////////////////////////////////////////////////////////////////////////// // @@ -767,19 +835,29 @@ void rsi_ContextResume(Context *rsc) rsc->resume(); } -void rsi_ContextSetSurface(Context *rsc, void *sur) +void rsi_ContextSetSurface(Context *rsc, uint32_t w, uint32_t h, void *sur) +{ + rsc->setSurface(w, h, (Surface *)sur); +} + +void rsi_ContextSetPriority(Context *rsc, int32_t p) +{ + rsc->setPriority(p); +} + +void rsi_ContextDump(Context *rsc, int32_t bits) { - rsc->setSurface((Surface *)sur); + ObjectBase::dumpAll(rsc); } } } -RsContext rsContextCreate(RsDevice vdev, void *sur, uint32_t version, bool useDepth) +RsContext rsContextCreate(RsDevice vdev, uint32_t version, bool useDepth) { Device * dev = static_cast<Device *>(vdev); - Context *rsc = new Context(dev, (Surface *)sur, useDepth); + Context *rsc = new Context(dev, useDepth); return rsc; } diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h index bffc55b..1770ee6 100644 --- a/libs/rs/rsContext.h +++ b/libs/rs/rsContext.h @@ -49,7 +49,7 @@ namespace renderscript { class Context { public: - Context(Device *, Surface *, bool useDepth); + Context(Device *, bool useDepth); ~Context(); static pthread_key_t gThreadTLSKey; @@ -94,7 +94,8 @@ public: void pause(); void resume(); - void setSurface(Surface *sur); + void setSurface(uint32_t w, uint32_t h, Surface *sur); + void setPriority(int32_t p); void assignName(ObjectBase *obj, const char *name, uint32_t len); void removeName(ObjectBase *obj); @@ -104,7 +105,7 @@ public: uint32_t getMessageToClient(void *data, size_t *receiveLen, size_t bufferLen, bool wait); bool sendMessageToClient(void *data, uint32_t cmdID, size_t len, bool waitForSpace); - bool runScript(Script *s, uint32_t launchID); + uint32_t runScript(Script *s, uint32_t launchID); void initToClient(); void deinitToClient(); @@ -161,6 +162,8 @@ public: bool mLogObjects; } props; + void dumpDebug() const; + mutable const ObjectBase * mObjHead; protected: @@ -189,12 +192,17 @@ protected: } mGL; + uint32_t mWidth; + uint32_t mHeight; + int32_t mThreadPriority; + bool mRunning; bool mExit; bool mUseDepth; bool mPaused; pthread_t mThreadId; + pid_t mNativeThreadId; ObjectBaseRef<Script> mRootScript; ObjectBaseRef<ProgramFragment> mFragment; @@ -219,7 +227,7 @@ private: void initEGL(); void deinitEGL(); - bool runRootScript(); + uint32_t runRootScript(); static void * threadProc(void *); @@ -234,6 +242,9 @@ private: uint64_t mTimeLast; uint64_t mTimeFrame; uint64_t mTimeLastFrame; + uint32_t mTimeMSLastFrame; + uint32_t mTimeMSLastScript; + uint32_t mTimeMSLastSwap; }; } diff --git a/libs/rs/rsLocklessFifo.cpp b/libs/rs/rsLocklessFifo.cpp index 085a81e..c796520 100644 --- a/libs/rs/rsLocklessFifo.cpp +++ b/libs/rs/rsLocklessFifo.cpp @@ -57,7 +57,7 @@ bool LocklessCommandFifo::init(uint32_t sizeInBytes) mPut = mBuffer; mGet = mBuffer; mEnd = mBuffer + (sizeInBytes) - 1; - dumpState("init"); + //dumpState("init"); return true; } diff --git a/libs/rs/rsObjectBase.cpp b/libs/rs/rsObjectBase.cpp index b7d67cc..89c5b00 100644 --- a/libs/rs/rsObjectBase.cpp +++ b/libs/rs/rsObjectBase.cpp @@ -182,11 +182,17 @@ void ObjectBase::zeroAllUserRef(Context *rsc) if (rsc->props.mLogObjects) { LOGV("Objects remaining."); - o = rsc->mObjHead; - while (o) { - o->dumpLOGV(" "); - o = o->mNext; - } + dumpAll(rsc); + } +} + +void ObjectBase::dumpAll(Context *rsc) +{ + LOGV("Dumping all objects"); + const ObjectBase * o = rsc->mObjHead; + while (o) { + o->dumpLOGV(" "); + o = o->mNext; } } diff --git a/libs/rs/rsObjectBase.h b/libs/rs/rsObjectBase.h index dc85ac7..f247022 100644 --- a/libs/rs/rsObjectBase.h +++ b/libs/rs/rsObjectBase.h @@ -49,6 +49,7 @@ public: void setContext(Context *); static void zeroAllUserRef(Context *rsc); + static void dumpAll(Context *rsc); virtual void dumpLOGV(const char *prefix) const; diff --git a/libs/rs/rsProgramFragment.cpp b/libs/rs/rsProgramFragment.cpp index 708a0e0..5f2dfae 100644 --- a/libs/rs/rsProgramFragment.cpp +++ b/libs/rs/rsProgramFragment.cpp @@ -65,6 +65,20 @@ void ProgramFragment::setupGL(const Context *rsc, ProgramFragmentState *state) } glTexEnvi(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, mPointSpriteEnable); } + + rsAssert(mTextures[ct]->getTextureID() != 0); + if (mTextures[ct]->getTextureID() == 0) { + // This is a hack for eclair to try to fix the white squares bug. + Allocation *a = (Allocation *)mTextures[ct].get(); + a->uploadToTexture((Context *)rsc, 0); + if (mTextures[ct]->getTextureID() == 0) { + // At this point we are screwed. Crash to restart the app. + rsc->dumpDebug(); + LOGE("Multiple failures during texture upload. Driver appears wedged."); + ((char *)0)[0] = 0; + } + + } glBindTexture(GL_TEXTURE_2D, mTextures[ct]->getTextureID()); switch(mEnvModes[ct]) { diff --git a/libs/rs/rsProgramVertex.cpp b/libs/rs/rsProgramVertex.cpp index eea8b3b..68f589f 100644 --- a/libs/rs/rsProgramVertex.cpp +++ b/libs/rs/rsProgramVertex.cpp @@ -157,12 +157,17 @@ void ProgramVertexState::init(Context *rsc, int32_t w, int32_t h) pv->bindAllocation(alloc); + updateSize(rsc, w, h); +} + +void ProgramVertexState::updateSize(Context *rsc, int32_t w, int32_t h) +{ Matrix m; m.loadOrtho(0,w, h,0, -1,1); - alloc->subData(RS_PROGRAM_VERTEX_PROJECTION_OFFSET, 16, &m.m[0], 16*4); + mDefaultAlloc->subData(RS_PROGRAM_VERTEX_PROJECTION_OFFSET, 16, &m.m[0], 16*4); m.loadIdentity(); - alloc->subData(RS_PROGRAM_VERTEX_MODELVIEW_OFFSET, 16, &m.m[0], 16*4); + mDefaultAlloc->subData(RS_PROGRAM_VERTEX_MODELVIEW_OFFSET, 16, &m.m[0], 16*4); } void ProgramVertexState::deinit(Context *rsc) diff --git a/libs/rs/rsProgramVertex.h b/libs/rs/rsProgramVertex.h index 493668c..a97ba38 100644 --- a/libs/rs/rsProgramVertex.h +++ b/libs/rs/rsProgramVertex.h @@ -63,6 +63,7 @@ public: void init(Context *rsc, int32_t w, int32_t h); void deinit(Context *rsc); + void updateSize(Context *rsc, int32_t w, int32_t h); ObjectBaseRef<ProgramVertex> mDefault; ObjectBaseRef<ProgramVertex> mLast; diff --git a/libs/rs/rsScript.h b/libs/rs/rsScript.h index bc40854..5f4a536 100644 --- a/libs/rs/rsScript.h +++ b/libs/rs/rsScript.h @@ -70,7 +70,7 @@ public: virtual void setupScript() = 0; - virtual bool run(Context *, uint32_t launchID) = 0; + virtual uint32_t run(Context *, uint32_t launchID) = 0; }; diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp index 073d98b..f11b862 100644 --- a/libs/rs/rsScriptC.cpp +++ b/libs/rs/rsScriptC.cpp @@ -60,7 +60,7 @@ void ScriptC::setupScript() } -bool ScriptC::run(Context *rsc, uint32_t launchIndex) +uint32_t ScriptC::run(Context *rsc, uint32_t launchIndex) { Context::ScriptTLSStruct * tls = (Context::ScriptTLSStruct *)pthread_getspecific(Context::gThreadTLSKey); @@ -85,9 +85,9 @@ bool ScriptC::run(Context *rsc, uint32_t launchIndex) } setupScript(); - bool ret = false; + uint32_t ret = 0; tls->mScript = this; - ret = mProgram.mScript(launchIndex) != 0; + ret = mProgram.mScript(launchIndex); tls->mScript = NULL; return ret; } diff --git a/libs/rs/rsScriptC.h b/libs/rs/rsScriptC.h index 69afc18..35abadf 100644 --- a/libs/rs/rsScriptC.h +++ b/libs/rs/rsScriptC.h @@ -55,7 +55,7 @@ public: ACCscript* mAccScript; virtual void setupScript(); - virtual bool run(Context *, uint32_t launchID); + virtual uint32_t run(Context *, uint32_t launchID); }; class ScriptCState diff --git a/libs/rs/rsScriptC_Lib.cpp b/libs/rs/rsScriptC_Lib.cpp index 5aef56d..23888ff 100644 --- a/libs/rs/rsScriptC_Lib.cpp +++ b/libs/rs/rsScriptC_Lib.cpp @@ -28,7 +28,6 @@ #include <GLES/glext.h> #include <time.h> -#include <cutils/tztime.h> using namespace android; using namespace android::renderscript; @@ -444,15 +443,9 @@ static int32_t SC_second() time_t rawtime; time(&rawtime); - if (sc->mEnviroment.mTimeZone) { - struct tm timeinfo; - localtime_tz(&rawtime, &timeinfo, sc->mEnviroment.mTimeZone); - return timeinfo.tm_sec; - } else { - struct tm *timeinfo; - timeinfo = localtime(&rawtime); - return timeinfo->tm_sec; - } + struct tm *timeinfo; + timeinfo = localtime(&rawtime); + return timeinfo->tm_sec; } static int32_t SC_minute() @@ -462,15 +455,9 @@ static int32_t SC_minute() time_t rawtime; time(&rawtime); - if (sc->mEnviroment.mTimeZone) { - struct tm timeinfo; - localtime_tz(&rawtime, &timeinfo, sc->mEnviroment.mTimeZone); - return timeinfo.tm_min; - } else { - struct tm *timeinfo; - timeinfo = localtime(&rawtime); - return timeinfo->tm_min; - } + struct tm *timeinfo; + timeinfo = localtime(&rawtime); + return timeinfo->tm_min; } static int32_t SC_hour() @@ -480,15 +467,9 @@ static int32_t SC_hour() time_t rawtime; time(&rawtime); - if (sc->mEnviroment.mTimeZone) { - struct tm timeinfo; - localtime_tz(&rawtime, &timeinfo, sc->mEnviroment.mTimeZone); - return timeinfo.tm_hour; - } else { - struct tm *timeinfo; - timeinfo = localtime(&rawtime); - return timeinfo->tm_hour; - } + struct tm *timeinfo; + timeinfo = localtime(&rawtime); + return timeinfo->tm_hour; } static int32_t SC_day() @@ -498,15 +479,9 @@ static int32_t SC_day() time_t rawtime; time(&rawtime); - if (sc->mEnviroment.mTimeZone) { - struct tm timeinfo; - localtime_tz(&rawtime, &timeinfo, sc->mEnviroment.mTimeZone); - return timeinfo.tm_mday; - } else { - struct tm *timeinfo; - timeinfo = localtime(&rawtime); - return timeinfo->tm_mday; - } + struct tm *timeinfo; + timeinfo = localtime(&rawtime); + return timeinfo->tm_mday; } static int32_t SC_month() @@ -516,15 +491,9 @@ static int32_t SC_month() time_t rawtime; time(&rawtime); - if (sc->mEnviroment.mTimeZone) { - struct tm timeinfo; - localtime_tz(&rawtime, &timeinfo, sc->mEnviroment.mTimeZone); - return timeinfo.tm_mon; - } else { - struct tm *timeinfo; - timeinfo = localtime(&rawtime); - return timeinfo->tm_mon; - } + struct tm *timeinfo; + timeinfo = localtime(&rawtime); + return timeinfo->tm_mon; } static int32_t SC_year() @@ -534,15 +503,9 @@ static int32_t SC_year() time_t rawtime; time(&rawtime); - if (sc->mEnviroment.mTimeZone) { - struct tm timeinfo; - localtime_tz(&rawtime, &timeinfo, sc->mEnviroment.mTimeZone); - return timeinfo.tm_year; - } else { - struct tm *timeinfo; - timeinfo = localtime(&rawtime); - return timeinfo->tm_year; - } + struct tm *timeinfo; + timeinfo = localtime(&rawtime); + return timeinfo->tm_year; } static int32_t SC_uptimeMillis() diff --git a/libs/rs/rsUtils.h b/libs/rs/rsUtils.h index 63d73a1..07f8933 100644 --- a/libs/rs/rsUtils.h +++ b/libs/rs/rsUtils.h @@ -18,7 +18,7 @@ #define ANDROID_RS_UTILS_H #define LOG_NDEBUG 0 -#define LOG_TAG "rs" +#define LOG_TAG "RenderScript" #include <utils/Log.h> #include <utils/Vector.h> #include <utils/KeyedVector.h> diff --git a/libs/surfaceflinger/Android.mk b/libs/surfaceflinger/Android.mk index eb51c22..b3fed58 100644 --- a/libs/surfaceflinger/Android.mk +++ b/libs/surfaceflinger/Android.mk @@ -22,9 +22,6 @@ LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES ifeq ($(TARGET_BOARD_PLATFORM), msm7k) LOCAL_CFLAGS += -DDIM_WITH_TEXTURE endif -ifeq ($(TARGET_BOARD_PLATFORM), qsd8k) - LOCAL_CFLAGS += -DDIM_WITH_TEXTURE -endif # need "-lrt" on Linux simulator to pick up clock_gettime ifeq ($(TARGET_SIMULATOR),true) diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp index 1abfd68..d9d9bfe 100644 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp +++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp @@ -246,10 +246,11 @@ void DisplayHardware::init(uint32_t dpy) LOGI("version : %s", glGetString(GL_VERSION)); LOGI("extensions: %s", gl_extensions); - if (strstr(gl_renderer, "PowerVR SGX 530")) { + if (strstr(gl_renderer, "Adreno")) { LOGD("Assuming uncached graphics buffers."); mFlags &= ~CACHED_BUFFERS; } + if (strstr(gl_extensions, "GL_ARB_texture_non_power_of_two")) { mFlags |= NPOT_EXTENSION; } diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp index f5a5a0b..1870d3a 100644 --- a/libs/surfaceflinger/Layer.cpp +++ b/libs/surfaceflinger/Layer.cpp @@ -93,6 +93,7 @@ sp<LayerBaseClient::Surface> Layer::createSurface() const status_t Layer::ditch() { // the layer is not on screen anymore. free as much resources as possible + mFreezeLock.clear(); destroy(); return NO_ERROR; } @@ -134,7 +135,14 @@ void Layer::reloadTexture(const Region& dirty) { Mutex::Autolock _l(mLock); sp<GraphicBuffer> buffer(getFrontBufferLocked()); - int index = mFrontBufferIndex; + if (buffer == NULL) { + // this situation can happen if we ran out of memory for instance. + // not much we can do. continue to use whatever texture was bound + // to this context. + return; + } + + const int index = mFrontBufferIndex; // create the new texture name if needed if (UNLIKELY(mTextures[index].name == -1U)) { @@ -515,6 +523,11 @@ void Layer::unlockPageFlip( dirtyRegion.andSelf(visibleRegionScreen); outDirtyRegion.orSelf(dirtyRegion); } + if (visibleRegionScreen.isEmpty()) { + // an invisible layer should not hold a freeze-lock + // (because it may never be updated and thereore never release it) + mFreezeLock.clear(); + } } void Layer::finishPageFlip() diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp index a36304c..2ff6167 100644 --- a/libs/surfaceflinger/LayerBuffer.cpp +++ b/libs/surfaceflinger/LayerBuffer.cpp @@ -26,6 +26,8 @@ #include <ui/GraphicBuffer.h> #include <ui/PixelFormat.h> #include <ui/FramebufferNativeWindow.h> +#include <ui/Rect.h> +#include <ui/Region.h> #include <hardware/copybit.h> @@ -46,12 +48,15 @@ gralloc_module_t const* LayerBuffer::sGrallocModule = 0; LayerBuffer::LayerBuffer(SurfaceFlinger* flinger, DisplayID display, const sp<Client>& client, int32_t i) : LayerBaseClient(flinger, display, client, i), - mNeedsBlending(false) + mNeedsBlending(false), mBlitEngine(0) { } LayerBuffer::~LayerBuffer() { + if (mBlitEngine) { + copybit_close(mBlitEngine); + } } void LayerBuffer::onFirstRef() @@ -69,6 +74,10 @@ void LayerBuffer::onFirstRef() sGrallocModule = (gralloc_module_t const *)module; } } + + if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) { + copybit_open(module, &mBlitEngine); + } } sp<LayerBaseClient::Surface> LayerBuffer::createSurface() const @@ -109,7 +118,10 @@ uint32_t LayerBuffer::doTransaction(uint32_t flags) sp<Source> source(getSource()); if (source != 0) source->onTransaction(flags); - return LayerBase::doTransaction(flags); + uint32_t res = LayerBase::doTransaction(flags); + // we always want filtering for these surfaces + mUseLinearFiltering = !(mFlags & DisplayHardware::SLOW_CONFIG); + return res; } void LayerBuffer::unlockPageFlip(const Transform& planeTransform, @@ -252,7 +264,16 @@ LayerBuffer::Buffer::Buffer(const ISurface::BufferHeap& buffers, ssize_t offset) : mBufferHeap(buffers) { NativeBuffer& src(mNativeBuffer); - src.img.handle = 0; + src.crop.l = 0; + src.crop.t = 0; + src.crop.r = buffers.w; + src.crop.b = buffers.h; + + src.img.w = buffers.hor_stride ?: buffers.w; + src.img.h = buffers.ver_stride ?: buffers.h; + src.img.format = buffers.format; + src.img.base = (void*)(intptr_t(buffers.heap->base()) + offset); + src.img.handle = 0; gralloc_module_t const * module = LayerBuffer::getGrallocModule(); if (module && module->perform) { @@ -262,19 +283,12 @@ LayerBuffer::Buffer::Buffer(const ISurface::BufferHeap& buffers, ssize_t offset) offset, buffers.heap->base(), &src.img.handle); - if (err == NO_ERROR) { - src.crop.l = 0; - src.crop.t = 0; - src.crop.r = buffers.w; - src.crop.b = buffers.h; - - src.img.w = buffers.hor_stride ?: buffers.w; - src.img.h = buffers.ver_stride ?: buffers.h; - src.img.format = buffers.format; - src.img.base = (void*)(intptr_t(buffers.heap->base()) + offset); - } + LOGE_IF(err, "CREATE_HANDLE_FROM_BUFFER (heapId=%d, size=%d, " + "offset=%ld, base=%p) failed (%s)", + buffers.heap->heapID(), buffers.heap->getSize(), + offset, buffers.heap->base(), strerror(-err)); } -} + } LayerBuffer::Buffer::~Buffer() { @@ -438,15 +452,24 @@ void LayerBuffer::BufferSource::onDraw(const Region& clip) const #if defined(EGL_ANDROID_image_native_buffer) if (mLayer.mFlags & DisplayHardware::DIRECT_TEXTURE) { - // NOTE: Assume the buffer is allocated with the proper USAGE flags - sp<GraphicBuffer> graphicBuffer = new GraphicBuffer( - src.crop.r, src.crop.b, src.img.format, - GraphicBuffer::USAGE_HW_TEXTURE, - src.img.w, src.img.handle, false); - - graphicBuffer->setVerticalStride(src.img.h); + copybit_device_t* copybit = mLayer.mBlitEngine; + if (copybit) { + // create our EGLImageKHR the first time + err = initTempBuffer(); + if (err == NO_ERROR) { + // NOTE: Assume the buffer is allocated with the proper USAGE flags + const NativeBuffer& dst(mTempBuffer); + region_iterator clip(Region(Rect(dst.crop.r, dst.crop.b))); + copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0); + copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF); + copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE); + err = copybit->stretch(copybit, &dst.img, &src.img, + &dst.crop, &src.crop, &clip); - err = mLayer.initializeEglImage(graphicBuffer, &mTexture); + } + } else { + err = INVALID_OPERATION; + } } #endif else { @@ -471,6 +494,72 @@ void LayerBuffer::BufferSource::onDraw(const Region& clip) const mLayer.drawWithOpenGL(clip, mTexture); } +status_t LayerBuffer::BufferSource::initTempBuffer() const +{ + // figure out the size we need now + const ISurface::BufferHeap& buffers(mBufferHeap); + uint32_t w = mLayer.mTransformedBounds.width(); + uint32_t h = mLayer.mTransformedBounds.height(); + if (buffers.w * h != buffers.h * w) { + int t = w; w = h; h = t; + } + + if (mTexture.image != EGL_NO_IMAGE_KHR) { + // we have an EGLImage, make sure the needed size didn't change + if (w!=mTexture.width || h!= mTexture.height) { + // delete the EGLImage and texture + EGLDisplay dpy(mLayer.mFlinger->graphicPlane(0).getEGLDisplay()); + glDeleteTextures(1, &mTexture.name); + eglDestroyImageKHR(dpy, mTexture.image); + Texture defaultTexture; + mTexture = defaultTexture; + mTempGraphicBuffer.clear(); + } else { + // we're good, we have an EGLImageKHR and it's (still) the + // right size + return NO_ERROR; + } + } + + // figure out if we need linear filtering + if (buffers.w * h == buffers.h * w) { + // same pixel area, don't use filtering + mLayer.mUseLinearFiltering = false; + } + + // Allocate a temporary buffer and create the corresponding EGLImageKHR + + status_t err; + mTempGraphicBuffer.clear(); + mTempGraphicBuffer = new GraphicBuffer( + w, h, HAL_PIXEL_FORMAT_RGB_565, + GraphicBuffer::USAGE_HW_TEXTURE | + GraphicBuffer::USAGE_HW_2D); + + err = mTempGraphicBuffer->initCheck(); + if (err == NO_ERROR) { + NativeBuffer& dst(mTempBuffer); + dst.img.w = mTempGraphicBuffer->getStride(); + dst.img.h = h; + dst.img.format = mTempGraphicBuffer->getPixelFormat(); + dst.img.handle = (native_handle_t *)mTempGraphicBuffer->handle; + dst.img.base = 0; + dst.crop.l = 0; + dst.crop.t = 0; + dst.crop.r = w; + dst.crop.b = h; + + err = mLayer.initializeEglImage( + mTempGraphicBuffer, &mTexture); + // once the EGLImage has been created (whether it fails + // or not) we don't need the graphic buffer reference + // anymore. + mTempGraphicBuffer.clear(); + } + + return err; +} + // --------------------------------------------------------------------------- LayerBuffer::OverlaySource::OverlaySource(LayerBuffer& layer, diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h index 47482f4..2ca63ac 100644 --- a/libs/surfaceflinger/LayerBuffer.h +++ b/libs/surfaceflinger/LayerBuffer.h @@ -130,13 +130,15 @@ private: virtual bool transformed() const; virtual void destroy() { } private: + status_t initTempBuffer() const; mutable Mutex mBufferSourceLock; sp<Buffer> mBuffer; status_t mStatus; ISurface::BufferHeap mBufferHeap; size_t mBufferSize; - mutable sp<GraphicBuffer> mTempBitmap; mutable LayerBase::Texture mTexture; + mutable NativeBuffer mTempBuffer; + mutable sp<GraphicBuffer> mTempGraphicBuffer; }; class OverlaySource : public Source { @@ -205,6 +207,7 @@ private: sp<Surface> mSurface; bool mInvalidate; bool mNeedsBlending; + copybit_device_t* mBlitEngine; }; // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp index 9694cf1..965b7dd 100644 --- a/libs/surfaceflinger/SurfaceFlinger.cpp +++ b/libs/surfaceflinger/SurfaceFlinger.cpp @@ -417,9 +417,9 @@ void SurfaceFlinger::waitForEvent() { while (true) { nsecs_t timeout = -1; + const nsecs_t freezeDisplayTimeout = ms2ns(5000); if (UNLIKELY(isFrozen())) { // wait 5 seconds - const nsecs_t freezeDisplayTimeout = ms2ns(5000); const nsecs_t now = systemTime(); if (mFreezeDisplayTime == 0) { mFreezeDisplayTime = now; @@ -429,22 +429,26 @@ void SurfaceFlinger::waitForEvent() } MessageList::value_type msg = mEventQueue.waitMessage(timeout); - if (msg != 0) { - mFreezeDisplayTime = 0; - switch (msg->what) { - case MessageQueue::INVALIDATE: - // invalidate message, just return to the main loop - return; - } - } else { - // we timed out - if (isFrozen()) { + + // see if we timed out + if (isFrozen()) { + const nsecs_t now = systemTime(); + nsecs_t frozenTime = (now - mFreezeDisplayTime); + if (frozenTime >= freezeDisplayTimeout) { // we timed out and are still frozen LOGW("timeout expired mFreezeDisplay=%d, mFreezeCount=%d", mFreezeDisplay, mFreezeCount); + mFreezeDisplayTime = 0; mFreezeCount = 0; mFreezeDisplay = false; - return; + } + } + + if (msg != 0) { + switch (msg->what) { + case MessageQueue::INVALIDATE: + // invalidate message, just return to the main loop + return; } } } @@ -1646,6 +1650,7 @@ status_t SurfaceFlinger::onTransact( } case 1007: // set mFreezeCount mFreezeCount = data.readInt32(); + mFreezeDisplayTime = 0; return NO_ERROR; case 1010: // interrogate. reply->writeInt32(0); diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h index f9bfe6c..c0ab73d 100644 --- a/libs/surfaceflinger/SurfaceFlinger.h +++ b/libs/surfaceflinger/SurfaceFlinger.h @@ -291,7 +291,11 @@ private: friend class FreezeLock; sp<FreezeLock> getFreezeLock() const; - inline void incFreezeCount() { mFreezeCount++; } + inline void incFreezeCount() { + if (mFreezeCount == 0) + mFreezeDisplayTime = 0; + mFreezeCount++; + } inline void decFreezeCount() { if (mFreezeCount > 0) mFreezeCount--; } inline bool hasFreezeRequest() const { return mFreezeDisplay; } inline bool isFrozen() const { diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp index 0efba9c..c5e22e5 100644 --- a/libs/ui/FramebufferNativeWindow.cpp +++ b/libs/ui/FramebufferNativeWindow.cpp @@ -118,8 +118,6 @@ FramebufferNativeWindow::FramebufferNativeWindow() LOGE_IF(err, "fb buffer 1 allocation failed w=%d, h=%d, err=%s", fbDev->width, fbDev->height, strerror(-err)); - LOGE("xDpi %d", fbDev->xdpi); - LOGE("yDpi %d", fbDev->ydpi); const_cast<uint32_t&>(android_native_window_t::flags) = fbDev->flags; const_cast<float&>(android_native_window_t::xdpi) = fbDev->xdpi; const_cast<float&>(android_native_window_t::ydpi) = fbDev->ydpi; diff --git a/libs/ui/Surface.cpp b/libs/ui/Surface.cpp index f51ca7a..24ae27f 100644 --- a/libs/ui/Surface.cpp +++ b/libs/ui/Surface.cpp @@ -152,96 +152,85 @@ bool SurfaceControl::isSameSurface( status_t SurfaceControl::setLayer(int32_t layer) { const sp<SurfaceComposerClient>& client(mClient); - if (client == 0) return NO_INIT; - status_t err = validate(client->mControl); + status_t err = validate(); if (err < 0) return err; return client->setLayer(mToken, layer); } status_t SurfaceControl::setPosition(int32_t x, int32_t y) { const sp<SurfaceComposerClient>& client(mClient); - if (client == 0) return NO_INIT; - status_t err = validate(client->mControl); + status_t err = validate(); if (err < 0) return err; return client->setPosition(mToken, x, y); } status_t SurfaceControl::setSize(uint32_t w, uint32_t h) { const sp<SurfaceComposerClient>& client(mClient); - if (client == 0) return NO_INIT; - status_t err = validate(client->mControl); + status_t err = validate(); if (err < 0) return err; return client->setSize(mToken, w, h); } status_t SurfaceControl::hide() { const sp<SurfaceComposerClient>& client(mClient); - if (client == 0) return NO_INIT; - status_t err = validate(client->mControl); + status_t err = validate(); if (err < 0) return err; return client->hide(mToken); } status_t SurfaceControl::show(int32_t layer) { const sp<SurfaceComposerClient>& client(mClient); - if (client == 0) return NO_INIT; - status_t err = validate(client->mControl); + status_t err = validate(); if (err < 0) return err; return client->show(mToken, layer); } status_t SurfaceControl::freeze() { const sp<SurfaceComposerClient>& client(mClient); - if (client == 0) return NO_INIT; - status_t err = validate(client->mControl); + status_t err = validate(); if (err < 0) return err; return client->freeze(mToken); } status_t SurfaceControl::unfreeze() { const sp<SurfaceComposerClient>& client(mClient); - if (client == 0) return NO_INIT; - status_t err = validate(client->mControl); + status_t err = validate(); if (err < 0) return err; return client->unfreeze(mToken); } status_t SurfaceControl::setFlags(uint32_t flags, uint32_t mask) { const sp<SurfaceComposerClient>& client(mClient); - if (client == 0) return NO_INIT; - status_t err = validate(client->mControl); + status_t err = validate(); if (err < 0) return err; return client->setFlags(mToken, flags, mask); } status_t SurfaceControl::setTransparentRegionHint(const Region& transparent) { const sp<SurfaceComposerClient>& client(mClient); - if (client == 0) return NO_INIT; - status_t err = validate(client->mControl); + status_t err = validate(); if (err < 0) return err; return client->setTransparentRegionHint(mToken, transparent); } status_t SurfaceControl::setAlpha(float alpha) { const sp<SurfaceComposerClient>& client(mClient); - if (client == 0) return NO_INIT; - status_t err = validate(client->mControl); + status_t err = validate(); if (err < 0) return err; return client->setAlpha(mToken, alpha); } status_t SurfaceControl::setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) { const sp<SurfaceComposerClient>& client(mClient); - if (client == 0) return NO_INIT; - status_t err = validate(client->mControl); + status_t err = validate(); if (err < 0) return err; return client->setMatrix(mToken, dsdx, dtdx, dsdy, dtdy); } status_t SurfaceControl::setFreezeTint(uint32_t tint) { const sp<SurfaceComposerClient>& client(mClient); - if (client == 0) return NO_INIT; - status_t err = validate(client->mControl); + status_t err = validate(); if (err < 0) return err; return client->setFreezeTint(mToken, tint); } -status_t SurfaceControl::validate(SharedClient const* cblk) const +status_t SurfaceControl::validate() const { if (mToken<0 || mClient==0) { LOGE("invalid token (%d, identity=%u) or client (%p)", mToken, mIdentity, mClient.get()); return NO_INIT; } + SharedClient const* cblk = mClient->mControl; if (cblk == 0) { LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity); return NO_INIT; @@ -394,7 +383,7 @@ bool Surface::isValid() { return mToken>=0 && mClient!=0; } -status_t Surface::validate(SharedClient const* cblk) const +status_t Surface::validate() const { sp<SurfaceComposerClient> client(getClient()); if (mToken<0 || mClient==0) { @@ -402,6 +391,7 @@ status_t Surface::validate(SharedClient const* cblk) const mToken, mIdentity, client.get()); return NO_INIT; } + SharedClient const* cblk = mClient->mControl; if (cblk == 0) { LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity); return NO_INIT; @@ -488,7 +478,7 @@ status_t Surface::dequeueBuffer(sp<GraphicBuffer>* buffer) { int Surface::dequeueBuffer(android_native_buffer_t** buffer) { sp<SurfaceComposerClient> client(getClient()); - status_t err = validate(client->mControl); + status_t err = validate(); if (err != NO_ERROR) return err; @@ -533,7 +523,7 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer) int Surface::lockBuffer(android_native_buffer_t* buffer) { sp<SurfaceComposerClient> client(getClient()); - status_t err = validate(client->mControl); + status_t err = validate(); if (err != NO_ERROR) return err; @@ -546,7 +536,7 @@ int Surface::lockBuffer(android_native_buffer_t* buffer) int Surface::queueBuffer(android_native_buffer_t* buffer) { sp<SurfaceComposerClient> client(getClient()); - status_t err = validate(client->mControl); + status_t err = validate(); if (err != NO_ERROR) return err; diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp index 2816d10..697db9f 100644 --- a/libs/utils/ResourceTypes.cpp +++ b/libs/utils/ResourceTypes.cpp @@ -42,6 +42,7 @@ #define TABLE_GETENTRY(x) //x #define TABLE_SUPER_NOISY(x) //x #define LOAD_TABLE_NOISY(x) //x +#define TABLE_THEME(x) //x namespace android { @@ -1472,18 +1473,23 @@ ssize_t ResTable::Theme::getAttribute(uint32_t resID, Res_value* outValue, const uint32_t t = Res_GETTYPE(resID); const uint32_t e = Res_GETENTRY(resID); - TABLE_NOISY(LOGV("Looking up attr 0x%08x in theme %p", resID, this)); + TABLE_THEME(LOGI("Looking up attr 0x%08x in theme %p", resID, this)); if (p >= 0) { const package_info* const pi = mPackages[p]; + TABLE_THEME(LOGI("Found package: %p", pi)); if (pi != NULL) { + TABLE_THEME(LOGI("Desired type index is %ld in avail %d", t, pi->numTypes)); if (t < pi->numTypes) { const type_info& ti = pi->types[t]; + TABLE_THEME(LOGI("Desired entry index is %ld in avail %d", e, ti.numEntries)); if (e < ti.numEntries) { const theme_entry& te = ti.entries[e]; - if (outTypeSpecFlags != NULL) { - *outTypeSpecFlags |= te.typeSpecFlags; - } + if (outTypeSpecFlags != NULL) { + *outTypeSpecFlags |= te.typeSpecFlags; + } + TABLE_THEME(LOGI("Theme value: type=0x%x, data=0x%08x", + te.value.dataType, te.value.data)); const uint8_t type = te.value.dataType; if (type == Res_value::TYPE_ATTRIBUTE) { if (cnt > 0) { @@ -1517,6 +1523,8 @@ ssize_t ResTable::Theme::resolveAttributeReference(Res_value* inOutValue, if (inOutValue->dataType == Res_value::TYPE_ATTRIBUTE) { uint32_t newTypeSpecFlags; blockIndex = getAttribute(inOutValue->data, inOutValue, &newTypeSpecFlags); + TABLE_THEME(LOGI("Resolving attr reference: blockIndex=%d, type=0x%x, data=%p\n", + (int)blockIndex, (int)inOutValue->dataType, (void*)inOutValue->data)); if (inoutTypeSpecFlags != NULL) *inoutTypeSpecFlags |= newTypeSpecFlags; //printf("Retrieved attribute new type=0x%x\n", inOutValue->dataType); if (blockIndex < 0) { @@ -1936,8 +1944,8 @@ ssize_t ResTable::resolveReference(Res_value* value, ssize_t blockIndex, uint32_t newFlags = 0; const ssize_t newIndex = getResource(value->data, value, true, &newFlags, outConfig); - //LOGI("Resolving reference d=%p: newIndex=%d, t=0x%02x, d=%p\n", - // (void*)lastRef, (int)newIndex, (int)value->dataType, (void*)value->data); + TABLE_THEME(LOGI("Resolving reference %p: newIndex=%d, type=0x%x, data=%p\n", + (void*)lastRef, (int)newIndex, (int)value->dataType, (void*)value->data)); //printf("Getting reference 0x%08x: newIndex=%d\n", value->data, newIndex); if (inoutTypeSpecFlags != NULL) *inoutTypeSpecFlags |= newFlags; if (newIndex < 0) { |