summaryrefslogtreecommitdiffstats
path: root/libs
diff options
context:
space:
mode:
authorDirk Sigurdson <dirk.sigurdson@t-mobile.com>2010-02-07 01:49:14 -0800
committerDirk Sigurdson <dirk.sigurdson@t-mobile.com>2010-02-07 01:49:14 -0800
commitb95e715706d92e7c3225737115919c115c957de4 (patch)
tree60cb3c974e136d4a261510d8b36aa1c231a1d6bf /libs
parent5d29366790e8fe6239d66e1e662ab05068b0549b (diff)
parent6ff3f8add87358b8489fa3f1705cf3bbfa34bc38 (diff)
downloadframeworks_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')
-rw-r--r--libs/audioflinger/AudioFlinger.cpp456
-rw-r--r--libs/audioflinger/AudioFlinger.h41
-rw-r--r--libs/binder/ProcessState.cpp2
-rw-r--r--libs/rs/RenderScript.h2
-rw-r--r--libs/rs/java/Fountain/src/com/android/fountain/FountainView.java28
-rw-r--r--libs/rs/java/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java3
-rw-r--r--libs/rs/rs.spec10
-rw-r--r--libs/rs/rsAllocation.cpp32
-rw-r--r--libs/rs/rsAllocation.h4
-rw-r--r--libs/rs/rsContext.cpp214
-rw-r--r--libs/rs/rsContext.h19
-rw-r--r--libs/rs/rsLocklessFifo.cpp2
-rw-r--r--libs/rs/rsObjectBase.cpp16
-rw-r--r--libs/rs/rsObjectBase.h1
-rw-r--r--libs/rs/rsProgramFragment.cpp14
-rw-r--r--libs/rs/rsProgramVertex.cpp9
-rw-r--r--libs/rs/rsProgramVertex.h1
-rw-r--r--libs/rs/rsScript.h2
-rw-r--r--libs/rs/rsScriptC.cpp6
-rw-r--r--libs/rs/rsScriptC.h2
-rw-r--r--libs/rs/rsScriptC_Lib.cpp73
-rw-r--r--libs/rs/rsUtils.h2
-rw-r--r--libs/surfaceflinger/Android.mk3
-rw-r--r--libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp3
-rw-r--r--libs/surfaceflinger/Layer.cpp15
-rw-r--r--libs/surfaceflinger/LayerBuffer.cpp135
-rw-r--r--libs/surfaceflinger/LayerBuffer.h5
-rw-r--r--libs/surfaceflinger/SurfaceFlinger.cpp29
-rw-r--r--libs/surfaceflinger/SurfaceFlinger.h6
-rw-r--r--libs/ui/FramebufferNativeWindow.cpp2
-rw-r--r--libs/ui/Surface.cpp48
-rw-r--r--libs/utils/ResourceTypes.cpp20
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) {