Merge "Fix a bug in sp<> and wp<> which could cause memory corruptions" into gingerbread
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index 1860793..48c04a6 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -51,7 +51,7 @@
#include "lifevibes.h"
#endif
-#include <media/EffectFactoryApi.h>
+#include <media/EffectsFactoryApi.h>
// ----------------------------------------------------------------------------
// the sim build doesn't have gettid
@@ -126,7 +126,8 @@
AudioFlinger::AudioFlinger()
: BnAudioFlinger(),
- mAudioHardware(0), mMasterVolume(1.0f), mMasterMute(false), mNextUniqueId(1)
+ mAudioHardware(0), mMasterVolume(1.0f), mMasterMute(false), mNextUniqueId(1),
+ mTotalEffectsCpuLoad(0), mTotalEffectsMemory(0)
{
mHardwareStatus = AUDIO_HW_IDLE;
@@ -135,8 +136,8 @@
mHardwareStatus = AUDIO_HW_INIT;
if (mAudioHardware->initCheck() == NO_ERROR) {
// open 16-bit output stream for s/w mixer
-
- setMode(AudioSystem::MODE_NORMAL);
+ mMode = AudioSystem::MODE_NORMAL;
+ setMode(mMode);
setMasterVolume(1.0f);
setMasterMute(false);
@@ -431,6 +432,8 @@
status_t AudioFlinger::setMode(int mode)
{
+ status_t ret;
+
// check calling permissions
if (!settingsAllowed()) {
return PERMISSION_DENIED;
@@ -440,15 +443,23 @@
return BAD_VALUE;
}
- AutoMutex lock(mHardwareLock);
- mHardwareStatus = AUDIO_HW_SET_MODE;
- status_t ret = mAudioHardware->setMode(mode);
-#ifdef LVMX
- if (NO_ERROR == ret) {
- LifeVibes::setMode(mode);
+ { // scope for the lock
+ AutoMutex lock(mHardwareLock);
+ mHardwareStatus = AUDIO_HW_SET_MODE;
+ ret = mAudioHardware->setMode(mode);
+ mHardwareStatus = AUDIO_HW_IDLE;
}
+
+ if (NO_ERROR == ret) {
+ Mutex::Autolock _l(mLock);
+ mMode = mode;
+ for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
+ mPlaybackThreads.valueAt(i)->setMode(mode);
+#ifdef LVMX
+ LifeVibes::setMode(mode);
#endif
- mHardwareStatus = AUDIO_HW_IDLE;
+ }
+
return ret;
}
@@ -1385,6 +1396,15 @@
return chain;
}
+void AudioFlinger::PlaybackThread::setMode(uint32_t mode)
+{
+ Mutex::Autolock _l(mLock);
+ size_t size = mEffectChains.size();
+ for (size_t i = 0; i < size; i++) {
+ mEffectChains[i]->setMode(mode);
+ }
+}
+
// ----------------------------------------------------------------------------
AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device)
@@ -1803,9 +1823,9 @@
t->mCblk->flags |= CBLK_INVALID_ON;
t->mCblk->cv.signal();
t->mCblk->lock.unlock();
- }
- }
}
+ }
+}
// getTrackName_l() must be called with ThreadBase::mLock held
@@ -4466,10 +4486,10 @@
return EffectQueryNumberEffects(numEffects);
}
-status_t AudioFlinger::queryNextEffect(effect_descriptor_t *descriptor)
+status_t AudioFlinger::queryEffect(uint32_t index, effect_descriptor_t *descriptor)
{
Mutex::Autolock _l(mLock);
- return EffectQueryNext(descriptor);
+ return EffectQueryEffect(index, descriptor);
}
status_t AudioFlinger::getEffectDescriptor(effect_uuid_t *pUuid, effect_descriptor_t *descriptor)
@@ -4529,10 +4549,10 @@
LOGW("createEffect() error %d from EffectQueryNumberEffects", lStatus);
goto Exit;
}
- for (; numEffects > 0; numEffects--) {
- lStatus = EffectQueryNext(&desc);
+ for (uint32_t i = 0; i < numEffects; i++) {
+ lStatus = EffectQueryEffect(i, &desc);
if (lStatus < 0) {
- LOGW("createEffect() error %d from EffectQueryNext", lStatus);
+ LOGW("createEffect() error %d from EffectQueryEffect", lStatus);
continue;
}
if (memcmp(&desc.type, &pDesc->type, sizeof(effect_uuid_t)) == 0) {
@@ -4567,6 +4587,13 @@
goto Exit;
}
+ // Session -1 is reserved for output stage effects that can only be created
+ // by audio policy manager (running in same process)
+ if (sessionId == -1 && getpid() != IPCThreadState::self()->getCallingPid()) {
+ lStatus = INVALID_OPERATION;
+ goto Exit;
+ }
+
// return effect descriptor
memcpy(pDesc, &desc, sizeof(effect_descriptor_t));
@@ -4574,7 +4601,7 @@
// output threads.
// TODO: allow attachment of effect to inputs
if (output == 0) {
- if (sessionId == 0) {
+ if (sessionId <= 0) {
// default to first output
// TODO: define criteria to choose output when not specified. Or
// receive output from audio policy manager
@@ -4621,6 +4648,33 @@
return handle;
}
+status_t AudioFlinger::registerEffectResource_l(effect_descriptor_t *desc) {
+ if (mTotalEffectsCpuLoad + desc->cpuLoad > MAX_EFFECTS_CPU_LOAD) {
+ LOGW("registerEffectResource() CPU Load limit exceeded for Fx %s, CPU %f MIPS",
+ desc->name, (float)desc->cpuLoad/10);
+ return INVALID_OPERATION;
+ }
+ if (mTotalEffectsMemory + desc->memoryUsage > MAX_EFFECTS_MEMORY) {
+ LOGW("registerEffectResource() memory limit exceeded for Fx %s, Memory %d KB",
+ desc->name, desc->memoryUsage);
+ return INVALID_OPERATION;
+ }
+ mTotalEffectsCpuLoad += desc->cpuLoad;
+ mTotalEffectsMemory += desc->memoryUsage;
+ LOGV("registerEffectResource_l() effect %s, CPU %d, memory %d",
+ desc->name, desc->cpuLoad, desc->memoryUsage);
+ LOGV(" total CPU %d, total memory %d", mTotalEffectsCpuLoad, mTotalEffectsMemory);
+ return NO_ERROR;
+}
+
+void AudioFlinger::unregisterEffectResource_l(effect_descriptor_t *desc) {
+ mTotalEffectsCpuLoad -= desc->cpuLoad;
+ mTotalEffectsMemory -= desc->memoryUsage;
+ LOGV("unregisterEffectResource_l() effect %s, CPU %d, memory %d",
+ desc->name, desc->cpuLoad, desc->memoryUsage);
+ LOGV(" total CPU %d, total memory %d", mTotalEffectsCpuLoad, mTotalEffectsMemory);
+}
+
// PlaybackThread::createEffect_l() must be called with AudioFlinger::mLock held
sp<AudioFlinger::EffectHandle> AudioFlinger::PlaybackThread::createEffect_l(
const sp<AudioFlinger::Client>& client,
@@ -4638,6 +4692,7 @@
sp<Track> track;
sp<EffectChain> chain;
bool effectCreated = false;
+ bool effectRegistered = false;
if (mOutput == 0) {
LOGW("createEffect_l() Audio driver not initialized.");
@@ -4680,20 +4735,26 @@
LOGV("createEffect_l() got effect %p on chain %p", effect == 0 ? 0 : effect.get(), chain.get());
if (effect == 0) {
+ // Check CPU and memory usage
+ lStatus = mAudioFlinger->registerEffectResource_l(desc);
+ if (lStatus != NO_ERROR) {
+ goto Exit;
+ }
+ effectRegistered = true;
// create a new effect module if none present in the chain
- effectCreated = true;
effect = new EffectModule(this, chain, desc, mAudioFlinger->nextUniqueId(), sessionId);
lStatus = effect->status();
if (lStatus != NO_ERROR) {
goto Exit;
}
- //TODO: handle CPU load and memory usage here
lStatus = chain->addEffect(effect);
if (lStatus != NO_ERROR) {
goto Exit;
}
+ effectCreated = true;
effect->setDevice(mDevice);
+ effect->setMode(mAudioFlinger->getMode());
}
// create effect handle and connect it to effect module
handle = new EffectHandle(effect, client, effectClient, priority);
@@ -4705,11 +4766,14 @@
Exit:
if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
- if (chain != 0 && effectCreated) {
+ if (effectCreated) {
if (chain->removeEffect(effect) == 0) {
removeEffectChain_l(chain);
}
}
+ if (effectRegistered) {
+ mAudioFlinger->unregisterEffectResource_l(desc);
+ }
handle.clear();
}
@@ -4719,21 +4783,37 @@
return handle;
}
+void AudioFlinger::PlaybackThread::disconnectEffect(const sp< EffectModule>& effect,
+ const wp<EffectHandle>& handle) {
+ effect_descriptor_t desc = effect->desc();
+ Mutex::Autolock _l(mLock);
+ // delete the effect module if removing last handle on it
+ if (effect->removeHandle(handle) == 0) {
+ if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
+ detachAuxEffect_l(effect->id());
+ }
+ sp<EffectChain> chain = effect->chain().promote();
+ if (chain != 0) {
+ // remove effect chain if remove last effect
+ if (chain->removeEffect(effect) == 0) {
+ removeEffectChain_l(chain);
+ }
+ }
+ mLock.unlock();
+ mAudioFlinger->mLock.lock();
+ mAudioFlinger->unregisterEffectResource_l(&desc);
+ mAudioFlinger->mLock.unlock();
+ }
+}
+
status_t AudioFlinger::PlaybackThread::addEffectChain_l(const sp<EffectChain>& chain)
{
int session = chain->sessionId();
int16_t *buffer = mMixBuffer;
+ bool ownsBuffer = false;
LOGV("addEffectChain_l() %p on thread %p for session %d", chain.get(), this, session);
- if (session == 0) {
- chain->setInBuffer(buffer, false);
- chain->setOutBuffer(buffer);
- // Effect chain for session 0 is inserted at end of effect chains list
- // to be processed last as it contains output mix effects to apply after
- // all track specific effects
- mEffectChains.add(chain);
- } else {
- bool ownsBuffer = false;
+ if (session > 0) {
// Only one effect chain can be present in direct output thread and it uses
// the mix buffer as input
if (mType != DIRECT) {
@@ -4743,32 +4823,42 @@
LOGV("addEffectChain_l() creating new input buffer %p session %d", buffer, session);
ownsBuffer = true;
}
- chain->setInBuffer(buffer, ownsBuffer);
- chain->setOutBuffer(mMixBuffer);
- // Effect chain for session other than 0 is inserted at beginning of effect
- // chains list to be processed before output mix effects. Relative order between
- // sessions other than 0 is not important
- mEffectChains.insertAt(chain, 0);
- }
- // Attach all tracks with same session ID to this chain.
- for (size_t i = 0; i < mTracks.size(); ++i) {
- sp<Track> track = mTracks[i];
- if (session == track->sessionId()) {
- LOGV("addEffectChain_l() track->setMainBuffer track %p buffer %p", track.get(), buffer);
- track->setMainBuffer(buffer);
+ // Attach all tracks with same session ID to this chain.
+ for (size_t i = 0; i < mTracks.size(); ++i) {
+ sp<Track> track = mTracks[i];
+ if (session == track->sessionId()) {
+ LOGV("addEffectChain_l() track->setMainBuffer track %p buffer %p", track.get(), buffer);
+ track->setMainBuffer(buffer);
+ }
+ }
+
+ // indicate all active tracks in the chain
+ for (size_t i = 0 ; i < mActiveTracks.size() ; ++i) {
+ sp<Track> track = mActiveTracks[i].promote();
+ if (track == 0) continue;
+ if (session == track->sessionId()) {
+ LOGV("addEffectChain_l() activating track %p on session %d", track.get(), session);
+ chain->startTrack();
+ }
}
}
- // indicate all active tracks in the chain
- for (size_t i = 0 ; i < mActiveTracks.size() ; ++i) {
- sp<Track> track = mActiveTracks[i].promote();
- if (track == 0) continue;
- if (session == track->sessionId()) {
- LOGV("addEffectChain_l() activating track %p on session %d", track.get(), session);
- chain->startTrack();
- }
+ chain->setInBuffer(buffer, ownsBuffer);
+ chain->setOutBuffer(mMixBuffer);
+ // Effect chain for session -1 is inserted at end of effect chains list
+ // in order to be processed last as it contains output stage effects
+ // Effect chain for session 0 is inserted before session -1 to be processed
+ // after track specific effects and before output stage
+ // Effect chain for session other than 0 is inserted at beginning of effect
+ // chains list to be processed before output mix effects. Relative order between
+ // sessions other than 0 is not important
+ size_t size = mEffectChains.size();
+ size_t i = 0;
+ for (i = 0; i < size; i++) {
+ if (mEffectChains[i]->sessionId() < session) break;
}
+ mEffectChains.insertAt(chain, i);
return NO_ERROR;
}
@@ -4884,7 +4974,8 @@
memcpy(&mDescriptor, desc, sizeof(effect_descriptor_t));
// create effect engine from effect factory
- mStatus = EffectCreate(&desc->uuid, &mEffectInterface);
+ mStatus = EffectCreate(&desc->uuid, sessionId, p->id(), &mEffectInterface);
+
if (mStatus != NO_ERROR) {
return;
}
@@ -4969,22 +5060,11 @@
// keep a strong reference on this EffectModule to avoid calling the
// destructor before we exit
sp<EffectModule> keep(this);
- sp<ThreadBase> thread = mThread.promote();
- if (thread != 0) {
- Mutex::Autolock _l(thread->mLock);
- // delete the effect module if removing last handle on it
- if (removeHandle(handle) == 0) {
+ {
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread != 0) {
PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
- if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
- playbackThread->detachAuxEffect_l(mId);
- }
- sp<EffectChain> chain = mChain.promote();
- if (chain != 0) {
- // remove effect chain if remove last effect
- if (chain->removeEffect(keep) == 0) {
- playbackThread->removeEffectChain_l(chain);
- }
- }
+ playbackThread->disconnectEffect(keep, handle);
}
}
}
@@ -5007,88 +5087,25 @@
// TODO: handle effects with buffer provider
if (mState != ACTIVE) {
- uint32_t count = mConfig.inputCfg.buffer.frameCount;
- int32_t amp = 32767L << 16;
- int32_t step = amp / count;
- int16_t *pIn = mConfig.inputCfg.buffer.s16;
- int16_t *pOut = mConfig.outputCfg.buffer.s16;
- int inChannels;
- int outChannels;
-
- if (mConfig.inputCfg.channels == CHANNEL_MONO) {
- inChannels = 1;
- } else {
- inChannels = 2;
- }
- if (mConfig.outputCfg.channels == CHANNEL_MONO) {
- outChannels = 1;
- } else {
- outChannels = 2;
- }
-
switch (mState) {
case RESET:
reset();
+ mState = STARTING;
// clear auxiliary effect input buffer for next accumulation
if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
memset(mConfig.inputCfg.buffer.raw, 0, mConfig.inputCfg.buffer.frameCount*sizeof(int32_t));
}
- step = -step;
- mState = STARTING;
- break;
+ return;
case STARTING:
start();
- amp = 0;
- pOut = mConfig.inputCfg.buffer.s16;
- outChannels = inChannels;
mState = ACTIVE;
break;
case STOPPING:
- step = -step;
- pOut = mConfig.inputCfg.buffer.s16;
- outChannels = inChannels;
mState = STOPPED;
break;
case STOPPED:
stop();
- amp = 0;
mState = IDLE;
- break;
- }
-
- // ramp volume down or up before activating or deactivating the effect
- if (inChannels == 1) {
- if (outChannels == 1) {
- while (count--) {
- *pOut++ = (int16_t)(((int32_t)*pIn++ * (amp >> 16)) >> 15);
- amp += step;
- }
- } else {
- while (count--) {
- int32_t smp = (int16_t)(((int32_t)*pIn++ * (amp >> 16)) >> 15);
- *pOut++ = smp;
- *pOut++ = smp;
- amp += step;
- }
- }
- } else {
- if (outChannels == 1) {
- while (count--) {
- int32_t smp = (((int32_t)*pIn * (amp >> 16)) >> 16) +
- (((int32_t)*(pIn + 1) * (amp >> 16)) >> 16);
- pIn += 2;
- *pOut++ = (int16_t)smp;
- amp += step;
- }
- } else {
- while (count--) {
- *pOut++ = (int16_t)((int32_t)*pIn++ * (amp >> 16)) >> 15;
- *pOut++ = (int16_t)((int32_t)*pIn++ * (amp >> 16)) >> 15;
- amp += step;
- }
- }
- }
- if (mState == STARTING || mState == IDLE) {
return;
}
}
@@ -5148,8 +5165,8 @@
mConfig.inputCfg.channels = channels;
}
mConfig.outputCfg.channels = channels;
- mConfig.inputCfg.format = PCM_FORMAT_S15;
- mConfig.outputCfg.format = PCM_FORMAT_S15;
+ mConfig.inputCfg.format = SAMPLE_FORMAT_PCM_S15;
+ mConfig.outputCfg.format = SAMPLE_FORMAT_PCM_S15;
mConfig.inputCfg.samplingRate = thread->sampleRate();
mConfig.outputCfg.samplingRate = mConfig.inputCfg.samplingRate;
mConfig.inputCfg.bufferProvider.cookie = NULL;
@@ -5160,7 +5177,7 @@
mConfig.outputCfg.bufferProvider.releaseBuffer = NULL;
mConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
// Insert effect:
- // - in session 0, always overwrites output buffer: input buffer == output buffer
+ // - in session 0 or -1, always overwrites output buffer: input buffer == output buffer
// - in other sessions:
// last effect in the chain accumulates in output buffer: input buffer != output buffer
// other effect: overwrites output buffer: input buffer == output buffer
@@ -5331,7 +5348,12 @@
status_t AudioFlinger::EffectModule::setDevice(uint32_t device)
{
status_t status = NO_ERROR;
- if ((mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_MASK) {
+ if ((mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_IND) {
+ // convert device bit field from AudioSystem to EffectApi format.
+ device = deviceAudioSystemToEffectApi(device);
+ if (device == 0) {
+ return BAD_VALUE;
+ }
status_t cmdStatus;
int size = sizeof(status_t);
status = (*mEffectInterface)->command(mEffectInterface, EFFECT_CMD_SET_DEVICE, sizeof(uint32_t), &device, &size, &cmdStatus);
@@ -5342,6 +5364,70 @@
return status;
}
+status_t AudioFlinger::EffectModule::setMode(uint32_t mode)
+{
+ status_t status = NO_ERROR;
+ if ((mDescriptor.flags & EFFECT_FLAG_AUDIO_MODE_MASK) == EFFECT_FLAG_AUDIO_MODE_IND) {
+ // convert audio mode from AudioSystem to EffectApi format.
+ int effectMode = modeAudioSystemToEffectApi(mode);
+ if (effectMode < 0) {
+ return BAD_VALUE;
+ }
+ status_t cmdStatus;
+ int size = sizeof(status_t);
+ status = (*mEffectInterface)->command(mEffectInterface, EFFECT_CMD_SET_AUDIO_MODE, sizeof(int), &effectMode, &size, &cmdStatus);
+ if (status == NO_ERROR) {
+ status = cmdStatus;
+ }
+ }
+ return status;
+}
+
+// update this table when AudioSystem::audio_devices or audio_device_e (in EffectApi.h) are modified
+const uint32_t AudioFlinger::EffectModule::sDeviceConvTable[] = {
+ DEVICE_EARPIECE, // AudioSystem::DEVICE_OUT_EARPIECE
+ DEVICE_SPEAKER, // AudioSystem::DEVICE_OUT_SPEAKER
+ DEVICE_WIRED_HEADSET, // case AudioSystem::DEVICE_OUT_WIRED_HEADSET
+ DEVICE_WIRED_HEADPHONE, // AudioSystem::DEVICE_OUT_WIRED_HEADPHONE
+ DEVICE_BLUETOOTH_SCO, // AudioSystem::DEVICE_OUT_BLUETOOTH_SCO
+ DEVICE_BLUETOOTH_SCO_HEADSET, // AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET
+ DEVICE_BLUETOOTH_SCO_CARKIT, // AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT
+ DEVICE_BLUETOOTH_A2DP, // AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP
+ DEVICE_BLUETOOTH_A2DP_HEADPHONES, // AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES
+ DEVICE_BLUETOOTH_A2DP_SPEAKER, // AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER
+ DEVICE_AUX_DIGITAL // AudioSystem::DEVICE_OUT_AUX_DIGITAL
+};
+
+uint32_t AudioFlinger::EffectModule::deviceAudioSystemToEffectApi(uint32_t device)
+{
+ uint32_t deviceOut = 0;
+ while (device) {
+ const uint32_t i = 31 - __builtin_clz(device);
+ device &= ~(1 << i);
+ if (i >= sizeof(sDeviceConvTable)/sizeof(uint32_t)) {
+ LOGE("device convertion error for AudioSystem device 0x%08x", device);
+ return 0;
+ }
+ deviceOut |= (uint32_t)sDeviceConvTable[i];
+ }
+ return deviceOut;
+}
+
+// update this table when AudioSystem::audio_mode or audio_mode_e (in EffectApi.h) are modified
+const uint32_t AudioFlinger::EffectModule::sModeConvTable[] = {
+ AUDIO_MODE_NORMAL, // AudioSystem::MODE_NORMAL
+ AUDIO_MODE_RINGTONE, // AudioSystem::MODE_RINGTONE
+ AUDIO_MODE_IN_CALL // AudioSystem::MODE_IN_CALL
+};
+
+int AudioFlinger::EffectModule::modeAudioSystemToEffectApi(uint32_t mode)
+{
+ int modeOut = -1;
+ if (mode < sizeof(sModeConvTable) / sizeof(uint32_t)) {
+ modeOut = (int)sModeConvTable[mode];
+ }
+ return modeOut;
+}
status_t AudioFlinger::EffectModule::dump(int fd, const Vector<String16>& args)
{
@@ -5525,7 +5611,16 @@
int rsize = sizeof(int);
int *p = (int *)(mBuffer + mCblk->serverIndex);
int size = *p++;
+ if (((uint8_t *)p + size) > mBuffer + mCblk->clientIndex) {
+ LOGW("command(): invalid parameter block size");
+ break;
+ }
effect_param_t *param = (effect_param_t *)p;
+ if (param->psize == 0 || param->vsize == 0) {
+ LOGW("command(): null parameter or value size");
+ mCblk->serverIndex += size;
+ continue;
+ }
int psize = sizeof(effect_param_t) + ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) + param->vsize;
status_t ret = mEffect->command(EFFECT_CMD_SET_PARAM, psize, p, &rsize, &reply);
if (ret == NO_ERROR) {
@@ -5659,7 +5754,7 @@
}
// if no track is active, input buffer must be cleared here as the mixer process
// will not do it
- if (mSessionId != 0 && activeTracks() == 0) {
+ if (mSessionId > 0 && activeTracks() == 0) {
sp<ThreadBase> thread = mThread.promote();
if (thread != 0) {
size_t numSamples = thread->frameCount() * thread->channelCount();
@@ -5697,15 +5792,16 @@
} else {
// Insert effects are inserted at the end of mEffects vector as they are processed
// after track and auxiliary effects.
- // Insert effect order:
- // if EFFECT_FLAG_INSERT_FIRST or EFFECT_FLAG_INSERT_EXCLUSIVE insert as first insert effect
+ // Insert effect order as a function of indicated preference:
+ // if EFFECT_FLAG_INSERT_EXCLUSIVE, insert in first position or reject if
+ // another effect is present
+ // else if EFFECT_FLAG_INSERT_FIRST, insert in first position or after the
+ // last effect claiming first position
+ // else if EFFECT_FLAG_INSERT_LAST, insert in last position or before the
+ // first effect claiming last position
// else if EFFECT_FLAG_INSERT_ANY insert after first or before last
- // else insert as last insert effect
- // Reject insertion if:
- // - EFFECT_FLAG_INSERT_EXCLUSIVE and another effect is present
- // - an effect with EFFECT_FLAG_INSERT_EXCLUSIVE is present
- // - EFFECT_FLAG_INSERT_FIRST or EFFECT_FLAG_INSERT_LAST and an effect with same
- // preference is present
+ // Reject insertion if an effect with EFFECT_FLAG_INSERT_EXCLUSIVE is
+ // already present
int size = (int)mEffects.size();
int idx_insert = size;
@@ -5719,35 +5815,40 @@
if (iMode == EFFECT_FLAG_TYPE_INSERT) {
// check invalid effect chaining combinations
if (insertPref == EFFECT_FLAG_INSERT_EXCLUSIVE ||
- iPref == EFFECT_FLAG_INSERT_EXCLUSIVE ||
- (insertPref != EFFECT_FLAG_INSERT_ANY
- && insertPref == iPref)) {
+ iPref == EFFECT_FLAG_INSERT_EXCLUSIVE) {
+ LOGW("addEffect() could not insert effect %s: exclusive conflict with %s", desc.name, d.name);
return INVALID_OPERATION;
}
- // remember position of first insert effect
+ // remember position of first insert effect and by default
+ // select this as insert position for new effect
if (idx_insert == size) {
idx_insert = i;
}
- // remember position of insert effect claiming
- // first place
+ // remember position of last insert effect claiming
+ // first position
if (iPref == EFFECT_FLAG_INSERT_FIRST) {
idx_insert_first = i;
}
- // remember position of insert effect claiming
- // last place
- if (iPref == EFFECT_FLAG_INSERT_LAST) {
+ // remember position of first insert effect claiming
+ // last position
+ if (iPref == EFFECT_FLAG_INSERT_LAST &&
+ idx_insert_last == -1) {
idx_insert_last = i;
}
}
}
- // modify idx_insert from first place if needed
- if (idx_insert_first != -1) {
- idx_insert = idx_insert_first + 1;
- } else if (idx_insert_last != -1) {
- idx_insert = idx_insert_last;
- } else if (insertPref == EFFECT_FLAG_INSERT_LAST) {
- idx_insert = size;
+ // modify idx_insert from first position if needed
+ if (insertPref == EFFECT_FLAG_INSERT_LAST) {
+ if (idx_insert_last != -1) {
+ idx_insert = idx_insert_last;
+ } else {
+ idx_insert = size;
+ }
+ } else {
+ if (idx_insert_first != -1) {
+ idx_insert = idx_insert_first + 1;
+ }
}
// always read samples from chain input buffer
@@ -5764,14 +5865,14 @@
} else {
effect->setOutBuffer(mInBuffer);
}
- status_t status = mEffects.insertAt(effect, idx_insert);
+ mEffects.insertAt(effect, idx_insert);
// Always give volume control to last effect in chain with volume control capability
if (((desc.flags & EFFECT_FLAG_VOLUME_MASK) & EFFECT_FLAG_VOLUME_CTRL) &&
mVolumeCtrlIdx < idx_insert) {
mVolumeCtrlIdx = idx_insert;
}
- LOGV("addEffect() effect %p, added in chain %p at rank %d status %d", effect.get(), this, idx_insert, status);
+ LOGV("addEffect() effect %p, added in chain %p at rank %d", effect.get(), this, idx_insert);
}
effect->configure();
return NO_ERROR;
@@ -5823,6 +5924,14 @@
}
}
+void AudioFlinger::EffectChain::setMode(uint32_t mode)
+{
+ size_t size = mEffects.size();
+ for (size_t i = 0; i < size; i++) {
+ mEffects[i]->setMode(mode);
+ }
+}
+
bool AudioFlinger::EffectChain::setVolume(uint32_t *left, uint32_t *right)
{
uint32_t newLeft = *left;
diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h
index e543334..42dca4c 100644
--- a/libs/audioflinger/AudioFlinger.h
+++ b/libs/audioflinger/AudioFlinger.h
@@ -149,7 +149,7 @@
virtual status_t queryNumberEffects(uint32_t *numEffects);
- virtual status_t queryNextEffect(effect_descriptor_t *descriptor);
+ virtual status_t queryEffect(uint32_t index, effect_descriptor_t *descriptor);
virtual status_t getEffectDescriptor(effect_uuid_t *pUuid, effect_descriptor_t *descriptor);
@@ -163,6 +163,9 @@
int *id,
int *enabled);
+ status_t registerEffectResource_l(effect_descriptor_t *desc);
+ void unregisterEffectResource_l(effect_descriptor_t *desc);
+
enum hardware_call_state {
AUDIO_HW_IDLE = 0,
AUDIO_HW_INIT,
@@ -200,6 +203,8 @@
Parcel* reply,
uint32_t flags);
+ uint32_t getMode() { return mMode; }
+
private:
AudioFlinger();
virtual ~AudioFlinger();
@@ -601,6 +606,8 @@
effect_descriptor_t *desc,
int *enabled,
status_t *status);
+ void disconnectEffect(const sp< EffectModule>& effect,
+ const wp<EffectHandle>& handle);
bool hasAudioSession(int sessionId);
sp<EffectChain> getEffectChain(int sessionId);
@@ -614,6 +621,7 @@
void detachAuxEffect_l(int effectId);
status_t attachAuxEffect(const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId);
status_t attachAuxEffect_l(const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId);
+ void setMode(uint32_t mode);
struct stream_type_t {
stream_type_t()
@@ -930,9 +938,11 @@
size_t removeHandle (const wp<EffectHandle>& handle);
effect_descriptor_t& desc() { return mDescriptor; }
+ wp<EffectChain>& chain() { return mChain; }
status_t setDevice(uint32_t device);
status_t setVolume(uint32_t *left, uint32_t *right, bool controller);
+ status_t setMode(uint32_t mode);
status_t dump(int fd, const Vector<String16>& args);
@@ -944,6 +954,14 @@
status_t start();
status_t stop();
+ // update this table when AudioSystem::audio_devices or audio_device_e (in EffectApi.h) are modified
+ static const uint32_t sDeviceConvTable[];
+ static uint32_t deviceAudioSystemToEffectApi(uint32_t device);
+
+ // update this table when AudioSystem::audio_mode or audio_mode_e (in EffectApi.h) are modified
+ static const uint32_t sModeConvTable[];
+ static int modeAudioSystemToEffectApi(uint32_t mode);
+
Mutex mLock; // mutex for process, commands and handles list protection
wp<ThreadBase> mThread; // parent thread
wp<EffectChain> mChain; // parent effect chain
@@ -1042,6 +1060,8 @@
sp<EffectModule> getVolumeController();
bool setVolume(uint32_t *left, uint32_t *right);
void setDevice(uint32_t device);
+ void setMode(uint32_t mode);
+
void setInBuffer(int16_t *buffer, bool ownsBuffer = false) {
mInBuffer = buffer;
@@ -1104,6 +1124,14 @@
#ifdef LVMX
int mLifeVibesClientPid;
#endif
+ uint32_t mMode;
+
+ // Maximum CPU load allocated to audio effects in 0.1 MIPS (ARMv5TE, 0 WS memory) units
+ static const uint32_t MAX_EFFECTS_CPU_LOAD = 1000;
+ // Maximum memory allocated to audio effects in KB
+ static const uint32_t MAX_EFFECTS_MEMORY = 512;
+ uint32_t mTotalEffectsCpuLoad; // current CPU load used by effects
+ uint32_t mTotalEffectsMemory; // current memory used by effects
};
// ----------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/Android.mk b/libs/surfaceflinger/Android.mk
index b0229c0..0879a66 100644
--- a/libs/surfaceflinger/Android.mk
+++ b/libs/surfaceflinger/Android.mk
@@ -6,7 +6,6 @@
DisplayHardware/DisplayHardware.cpp \
DisplayHardware/DisplayHardwareBase.cpp \
BlurFilter.cpp.arm \
- GLExtensions.cpp \
Layer.cpp \
LayerBase.cpp \
LayerBuffer.cpp \
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index 2eac0a8..51de1da 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -40,8 +40,6 @@
#include <hardware/overlay.h>
#include <hardware/gralloc.h>
-#include "GLExtensions.h"
-
using namespace android;
@@ -75,8 +73,7 @@
DisplayHardware::DisplayHardware(
const sp<SurfaceFlinger>& flinger,
uint32_t dpy)
- : DisplayHardwareBase(flinger, dpy),
- mFlags(0)
+ : DisplayHardwareBase(flinger, dpy), mFlags(0)
{
init(dpy);
}
@@ -100,9 +97,6 @@
{
mNativeWindow = new FramebufferNativeWindow();
framebuffer_device_t const * fbDev = mNativeWindow->getDevice();
- mDpiX = mNativeWindow->xdpi;
- mDpiY = mNativeWindow->ydpi;
- mRefreshRate = fbDev->fps;
mOverlayEngine = NULL;
hw_module_t const* module;
@@ -110,11 +104,6 @@
overlay_control_open(module, &mOverlayEngine);
}
- EGLint w, h, dummy;
- EGLint numConfigs=0;
- EGLSurface surface;
- EGLContext context;
-
// initialize EGL
EGLint attribs[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
@@ -132,6 +121,11 @@
}
}
+ EGLint w, h, dummy;
+ EGLint numConfigs=0;
+ EGLSurface surface;
+ EGLContext context;
+
// TODO: all the extensions below should be queried through
// eglGetProcAddress().
@@ -150,6 +144,22 @@
eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &b);
eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a);
+ /*
+ * Gather EGL extensions
+ */
+
+ const char* const egl_extensions = eglQueryString(
+ display, EGL_EXTENSIONS);
+
+ LOGI("EGL informations:");
+ LOGI("# of configs : %d", numConfigs);
+ LOGI("vendor : %s", eglQueryString(display, EGL_VENDOR));
+ LOGI("version : %s", eglQueryString(display, EGL_VERSION));
+ LOGI("extensions: %s", egl_extensions);
+ LOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported");
+ LOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config);
+
+
if (mNativeWindow->isUpdateOnDemand()) {
mFlags |= PARTIAL_UPDATES;
}
@@ -164,8 +174,6 @@
*/
surface = eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL);
- eglQuerySurface(display, surface, EGL_WIDTH, &mWidth);
- eglQuerySurface(display, surface, EGL_HEIGHT, &mHeight);
if (mFlags & PARTIAL_UPDATES) {
// if we have partial updates, we definitely don't need to
@@ -179,6 +187,31 @@
mFlags |= BUFFER_PRESERVED;
}
}
+
+ eglQuerySurface(display, surface, EGL_WIDTH, &mWidth);
+ eglQuerySurface(display, surface, EGL_HEIGHT, &mHeight);
+
+#ifdef EGL_ANDROID_swap_rectangle
+ if (strstr(egl_extensions, "EGL_ANDROID_swap_rectangle")) {
+ if (eglSetSwapRectangleANDROID(display, surface,
+ 0, 0, mWidth, mHeight) == EGL_TRUE) {
+ // This could fail if this extension is not supported by this
+ // specific surface (of config)
+ mFlags |= SWAP_RECTANGLE;
+ }
+ }
+ // when we have the choice between PARTIAL_UPDATES and SWAP_RECTANGLE
+ // choose PARTIAL_UPDATES, which should be more efficient
+ if (mFlags & PARTIAL_UPDATES)
+ mFlags &= ~SWAP_RECTANGLE;
+#endif
+
+
+ LOGI("flags : %08x", mFlags);
+
+ mDpiX = mNativeWindow->xdpi;
+ mDpiY = mNativeWindow->ydpi;
+ mRefreshRate = fbDev->fps;
/* Read density from build-specific ro.sf.lcd_density property
* except if it is overridden by qemu.sf.lcd_density.
@@ -201,67 +234,49 @@
context = eglCreateContext(display, config, NULL, NULL);
+ /*
+ * Gather OpenGL ES extensions
+ */
+
+ eglMakeCurrent(display, surface, surface, context);
+ const char* const gl_extensions = (const char*)glGetString(GL_EXTENSIONS);
+ const char* const gl_renderer = (const char*)glGetString(GL_RENDERER);
+ LOGI("OpenGL informations:");
+ LOGI("vendor : %s", glGetString(GL_VENDOR));
+ LOGI("renderer : %s", gl_renderer);
+ LOGI("version : %s", glGetString(GL_VERSION));
+ LOGI("extensions: %s", gl_extensions);
+
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
+ glGetIntegerv(GL_MAX_VIEWPORT_DIMS, &mMaxViewportDims);
+ LOGI("GL_MAX_TEXTURE_SIZE = %d", mMaxTextureSize);
+ LOGI("GL_MAX_VIEWPORT_DIMS = %d", mMaxViewportDims);
+
+
+ if (strstr(gl_extensions, "GL_ARB_texture_non_power_of_two")) {
+ mFlags |= NPOT_EXTENSION;
+ }
+#ifdef EGL_ANDROID_image_native_buffer
+ if (strstr( gl_extensions, "GL_OES_EGL_image") &&
+ (strstr(egl_extensions, "EGL_KHR_image_base") ||
+ strstr(egl_extensions, "EGL_KHR_image")) &&
+ strstr(egl_extensions, "EGL_ANDROID_image_native_buffer")) {
+ mFlags |= DIRECT_TEXTURE;
+ }
+#else
+#warning "EGL_ANDROID_image_native_buffer not supported"
+#endif
+
+
+ // Unbind the context from this thread
+ eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+
mDisplay = display;
mConfig = config;
mSurface = surface;
mContext = context;
mFormat = fbDev->format;
mPageFlipCount = 0;
-
- /*
- * Gather OpenGL ES extensions
- */
-
- eglMakeCurrent(display, surface, surface, context);
-
- GLExtensions& extensions(GLExtensions::getInstance());
- extensions.initWithGLStrings(
- glGetString(GL_VENDOR),
- glGetString(GL_RENDERER),
- glGetString(GL_VERSION),
- glGetString(GL_EXTENSIONS),
- eglQueryString(display, EGL_VENDOR),
- eglQueryString(display, EGL_VERSION),
- eglQueryString(display, EGL_EXTENSIONS));
-
- glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
- glGetIntegerv(GL_MAX_VIEWPORT_DIMS, &mMaxViewportDims);
-
-
-#ifdef EGL_ANDROID_swap_rectangle
- if (extensions.hasExtension("EGL_ANDROID_swap_rectangle")) {
- if (eglSetSwapRectangleANDROID(display, surface,
- 0, 0, mWidth, mHeight) == EGL_TRUE) {
- // This could fail if this extension is not supported by this
- // specific surface (of config)
- mFlags |= SWAP_RECTANGLE;
- }
- }
- // when we have the choice between PARTIAL_UPDATES and SWAP_RECTANGLE
- // choose PARTIAL_UPDATES, which should be more efficient
- if (mFlags & PARTIAL_UPDATES)
- mFlags &= ~SWAP_RECTANGLE;
-#endif
-
- LOGI("EGL informations:");
- LOGI("# of configs : %d", numConfigs);
- LOGI("vendor : %s", extensions.getEglVendor());
- LOGI("version : %s", extensions.getEglVersion());
- LOGI("extensions: %s", extensions.getEglExtension());
- LOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported");
- LOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config);
-
- LOGI("OpenGL informations:");
- LOGI("vendor : %s", extensions.getVendor());
- LOGI("renderer : %s", extensions.getRenderer());
- LOGI("version : %s", extensions.getVersion());
- LOGI("extensions: %s", extensions.getExtension());
- LOGI("GL_MAX_TEXTURE_SIZE = %d", mMaxTextureSize);
- LOGI("GL_MAX_VIEWPORT_DIMS = %d", mMaxViewportDims);
- LOGI("flags = %08x", mFlags);
-
- // Unbind the context from this thread
- eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
}
/*
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h
index 66bf521..ebd7c42 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h
@@ -29,8 +29,6 @@
#include <pixelflinger/pixelflinger.h>
-#include "GLExtensions.h"
-
#include "DisplayHardware/DisplayHardwareBase.h"
struct overlay_control_device_t;
@@ -45,11 +43,13 @@
{
public:
enum {
- COPY_BITS_EXTENSION = 0x00000008,
- BUFFER_PRESERVED = 0x00010000,
- PARTIAL_UPDATES = 0x00020000, // video driver feature
- SLOW_CONFIG = 0x00040000, // software
- SWAP_RECTANGLE = 0x00080000,
+ DIRECT_TEXTURE = 0x00000002,
+ COPY_BITS_EXTENSION = 0x00000008,
+ NPOT_EXTENSION = 0x00000100,
+ BUFFER_PRESERVED = 0x00010000,
+ PARTIAL_UPDATES = 0x00020000, // video driver feature
+ SLOW_CONFIG = 0x00040000, // software
+ SWAP_RECTANGLE = 0x00080000,
};
DisplayHardware(
diff --git a/libs/surfaceflinger/GLExtensions.cpp b/libs/surfaceflinger/GLExtensions.cpp
deleted file mode 100644
index 7f4f9fc..0000000
--- a/libs/surfaceflinger/GLExtensions.cpp
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdint.h>
-
-#include "GLExtensions.h"
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-ANDROID_SINGLETON_STATIC_INSTANCE( GLExtensions )
-
-GLExtensions::GLExtensions()
- : mHaveTextureExternal(false),
- mHaveNpot(false),
- mHaveDirectTexture(false)
-{
-}
-
-void GLExtensions::initWithGLStrings(
- GLubyte const* vendor,
- GLubyte const* renderer,
- GLubyte const* version,
- GLubyte const* extensions,
- char const* egl_vendor,
- char const* egl_version,
- char const* egl_extensions)
-{
- mVendor = (char const*)vendor;
- mRenderer = (char const*)renderer;
- mVersion = (char const*)version;
- mExtensions = (char const*)extensions;
- mEglVendor = egl_vendor;
- mEglVersion = egl_version;
- mEglExtensions = egl_extensions;
-
- char const* curr = (char const*)extensions;
- char const* head = curr;
- do {
- head = strchr(curr, ' ');
- String8 s(curr, head ? head-curr : strlen(curr));
- if (s.length()) {
- mExtensionList.add(s);
- }
- curr = head+1;
- } while (head);
-
- curr = egl_extensions;
- head = curr;
- do {
- head = strchr(curr, ' ');
- String8 s(curr, head ? head-curr : strlen(curr));
- if (s.length()) {
- mExtensionList.add(s);
- }
- curr = head+1;
- } while (head);
-
-#ifdef EGL_ANDROID_image_native_buffer
- if (hasExtension("GL_OES_EGL_image") &&
- (hasExtension("EGL_KHR_image_base") || hasExtension("EGL_KHR_image")) &&
- hasExtension("EGL_ANDROID_image_native_buffer"))
- {
- mHaveDirectTexture = true;
- }
-#else
-#warning "EGL_ANDROID_image_native_buffer not supported"
-#endif
-
- if (hasExtension("GL_ARB_texture_non_power_of_two")) {
- mHaveNpot = true;
- }
-
- if (hasExtension("GL_OES_texture_external")) {
- mHaveTextureExternal = true;
- } else if (strstr(mRenderer.string(), "Adreno")) {
- // hack for Adreno 200
- mHaveTextureExternal = true;
- }
-}
-
-bool GLExtensions::hasExtension(char const* extension) const
-{
- const String8 s(extension);
- return mExtensionList.indexOf(s) >= 0;
-}
-
-char const* GLExtensions::getVendor() const {
- return mVendor.string();
-}
-
-char const* GLExtensions::getRenderer() const {
- return mRenderer.string();
-}
-
-char const* GLExtensions::getVersion() const {
- return mVersion.string();
-}
-
-char const* GLExtensions::getExtension() const {
- return mExtensions.string();
-}
-
-char const* GLExtensions::getEglVendor() const {
- return mEglVendor.string();
-}
-
-char const* GLExtensions::getEglVersion() const {
- return mEglVersion.string();
-}
-
-char const* GLExtensions::getEglExtension() const {
- return mEglExtensions.string();
-}
-
-
-// ---------------------------------------------------------------------------
-}; // namespace android
diff --git a/libs/surfaceflinger/GLExtensions.h b/libs/surfaceflinger/GLExtensions.h
deleted file mode 100644
index bbb284e..0000000
--- a/libs/surfaceflinger/GLExtensions.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_SF_GLEXTENSION_H
-#define ANDROID_SF_GLEXTENSION_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/String8.h>
-#include <utils/SortedVector.h>
-#include <utils/Singleton.h>
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GLES/gl.h>
-#include <GLES/glext.h>
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-class GLExtensions : public Singleton<GLExtensions>
-{
- friend class Singleton<GLExtensions>;
-
- bool mHaveTextureExternal : 1;
- bool mHaveNpot : 1;
- bool mHaveDirectTexture : 1;
-
- String8 mVendor;
- String8 mRenderer;
- String8 mVersion;
- String8 mExtensions;
- String8 mEglVendor;
- String8 mEglVersion;
- String8 mEglExtensions;
- SortedVector<String8> mExtensionList;
-
- GLExtensions(const GLExtensions&);
- GLExtensions& operator = (const GLExtensions&);
-
-protected:
- GLExtensions();
-
-public:
- inline bool haveTextureExternal() const {
- return mHaveTextureExternal;
- }
- inline bool haveNpot() const {
- return mHaveNpot;
- }
- inline bool haveDirectTexture() const {
- return mHaveDirectTexture;
- }
-
- void initWithGLStrings(
- GLubyte const* vendor,
- GLubyte const* renderer,
- GLubyte const* version,
- GLubyte const* extensions,
- char const* egl_vendor,
- char const* egl_version,
- char const* egl_extensions);
-
- char const* getVendor() const;
- char const* getRenderer() const;
- char const* getVersion() const;
- char const* getExtension() const;
-
- char const* getEglVendor() const;
- char const* getEglVersion() const;
- char const* getEglExtension() const;
-
- bool hasExtension(char const* extension) const;
-};
-
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_SF_GLEXTENSION_H
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index 758da4e..e606f71 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -31,7 +31,6 @@
#include <surfaceflinger/Surface.h>
#include "clz.h"
-#include "GLExtensions.h"
#include "Layer.h"
#include "SurfaceFlinger.h"
#include "DisplayHardware/DisplayHardware.h"
@@ -51,11 +50,10 @@
Layer::Layer(SurfaceFlinger* flinger,
DisplayID display, const sp<Client>& client)
: LayerBaseClient(flinger, display, client),
- mGLExtensions(GLExtensions::getInstance()),
mNeedsBlending(true),
mNeedsDithering(false),
mSecure(false),
- mTextureManager(),
+ mTextureManager(mFlags),
mBufferManager(mTextureManager),
mWidth(0), mHeight(0), mFixedSize(false)
{
@@ -187,13 +185,17 @@
return;
}
- if (mGLExtensions.haveDirectTexture()) {
+#ifdef EGL_ANDROID_image_native_buffer
+ if (mFlags & DisplayHardware::DIRECT_TEXTURE) {
EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
if (mBufferManager.initEglImage(dpy, buffer) != NO_ERROR) {
// not sure what we can do here...
+ mFlags &= ~DisplayHardware::DIRECT_TEXTURE;
goto slowpath;
}
- } else {
+ } else
+#endif
+ {
slowpath:
GGLSurface t;
status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_OFTEN);
@@ -784,24 +786,19 @@
status_t err = NO_INIT;
ssize_t index = mActiveBuffer;
if (index >= 0) {
- if (!mFailover) {
- Image& texture(mBufferData[index].texture);
- err = mTextureManager.initEglImage(&texture, dpy, buffer);
- // if EGLImage fails, we switch to regular texture mode, and we
- // free all resources associated with using EGLImages.
- if (err == NO_ERROR) {
- mFailover = false;
- destroyTexture(&mFailoverTexture, dpy);
- } else {
- mFailover = true;
- const size_t num = mNumBuffers;
- for (size_t i=0 ; i<num ; i++) {
- destroyTexture(&mBufferData[i].texture, dpy);
- }
- }
+ Image& texture(mBufferData[index].texture);
+ err = mTextureManager.initEglImage(&texture, dpy, buffer);
+ // if EGLImage fails, we switch to regular texture mode, and we
+ // free all resources associated with using EGLImages.
+ if (err == NO_ERROR) {
+ mFailover = false;
+ destroyTexture(&mFailoverTexture, dpy);
} else {
- // we failed once, don't try again
- err = BAD_VALUE;
+ mFailover = true;
+ const size_t num = mNumBuffers;
+ for (size_t i=0 ; i<num ; i++) {
+ destroyTexture(&mBufferData[i].texture, dpy);
+ }
}
}
return err;
diff --git a/libs/surfaceflinger/Layer.h b/libs/surfaceflinger/Layer.h
index e1d283b..dcb27a0 100644
--- a/libs/surfaceflinger/Layer.h
+++ b/libs/surfaceflinger/Layer.h
@@ -37,10 +37,9 @@
// ---------------------------------------------------------------------------
-class FreezeLock;
class Client;
-class GLExtensions;
class UserClient;
+class FreezeLock;
// ---------------------------------------------------------------------------
@@ -207,7 +206,6 @@
// constants
sp<Surface> mSurface;
PixelFormat mFormat;
- const GLExtensions& mGLExtensions;
bool mNeedsBlending;
bool mNeedsDithering;
diff --git a/libs/surfaceflinger/LayerBlur.cpp b/libs/surfaceflinger/LayerBlur.cpp
index 64a43c7..c1c440b 100644
--- a/libs/surfaceflinger/LayerBlur.cpp
+++ b/libs/surfaceflinger/LayerBlur.cpp
@@ -147,9 +147,7 @@
Region::const_iterator const end = clip.end();
if (it != end) {
#if defined(GL_OES_texture_external)
- if (GLExtensions::getInstance().haveTextureExternal()) {
- glDisable(GL_TEXTURE_EXTERNAL_OES);
- }
+ glDisable(GL_TEXTURE_EXTERNAL_OES);
#endif
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, mTextureName);
@@ -183,7 +181,7 @@
bl.data = (GGLubyte*)pixels;
blurFilter(&bl, 8, 2);
- if (GLExtensions::getInstance().haveNpot()) {
+ if (mFlags & (DisplayHardware::NPOT_EXTENSION)) {
glTexImage2D(GL_TEXTURE_2D, 0, mReadFormat, w, h, 0,
mReadFormat, mReadType, pixels);
mWidthScale = 1.0f / w;
diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp
index 5f83636..732a4ec 100644
--- a/libs/surfaceflinger/LayerBuffer.cpp
+++ b/libs/surfaceflinger/LayerBuffer.cpp
@@ -315,7 +315,8 @@
LayerBuffer::BufferSource::BufferSource(LayerBuffer& layer,
const ISurface::BufferHeap& buffers)
- : Source(layer), mStatus(NO_ERROR), mBufferSize(0)
+ : Source(layer), mStatus(NO_ERROR), mBufferSize(0),
+ mTextureManager(layer.mFlags)
{
if (buffers.heap == NULL) {
// this is allowed, but in this case, it is illegal to receive
@@ -373,11 +374,11 @@
if (mTexture.name != -1U) {
// GL textures can only be destroyed from the GL thread
- getFlinger()->mEventQueue.postMessage(
- new MessageDestroyTexture(getFlinger(), mTexture.name) );
+ mLayer.mFlinger->mEventQueue.postMessage(
+ new MessageDestroyTexture(mLayer.mFlinger.get(), mTexture.name) );
}
if (mTexture.image != EGL_NO_IMAGE_KHR) {
- EGLDisplay dpy(getFlinger()->graphicPlane(0).getEGLDisplay());
+ EGLDisplay dpy(mLayer.mFlinger->graphicPlane(0).getEGLDisplay());
eglDestroyImageKHR(dpy, mTexture.image);
}
}
@@ -443,7 +444,7 @@
const Rect transformedBounds(mLayer.getTransformedBounds());
#if defined(EGL_ANDROID_image_native_buffer)
- if (GLExtensions::getInstance().haveDirectTexture()) {
+ if (mLayer.mFlags & DisplayHardware::DIRECT_TEXTURE) {
err = INVALID_OPERATION;
if (ourBuffer->supportsCopybit()) {
copybit_device_t* copybit = mLayer.mBlitEngine;
@@ -548,7 +549,7 @@
dst.crop.r = w;
dst.crop.b = h;
- EGLDisplay dpy(getFlinger()->graphicPlane(0).getEGLDisplay());
+ EGLDisplay dpy(mLayer.mFlinger->graphicPlane(0).getEGLDisplay());
err = mTextureManager.initEglImage(&mTexture, dpy, buffer);
}
@@ -558,7 +559,7 @@
void LayerBuffer::BufferSource::clearTempBufferImage() const
{
// delete the image
- EGLDisplay dpy(getFlinger()->graphicPlane(0).getEGLDisplay());
+ EGLDisplay dpy(mLayer.mFlinger->graphicPlane(0).getEGLDisplay());
eglDestroyImageKHR(dpy, mTexture.image);
// and the associated texture (recreate a name)
@@ -575,7 +576,7 @@
: Source(layer), mVisibilityChanged(false),
mOverlay(0), mOverlayHandle(0), mOverlayDevice(0), mOrientation(orientation)
{
- overlay_control_device_t* overlay_dev = getFlinger()->getOverlayEngine();
+ overlay_control_device_t* overlay_dev = mLayer.mFlinger->getOverlayEngine();
if (overlay_dev == NULL) {
// overlays not supported
return;
@@ -606,7 +607,7 @@
*overlayRef = new OverlayRef(mOverlayHandle, channel,
mWidth, mHeight, mFormat, mWidthStride, mHeightStride);
- getFlinger()->signalEvent();
+ mLayer.mFlinger->signalEvent();
}
LayerBuffer::OverlaySource::~OverlaySource()
diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h
index 1c0bf83..413b8a4 100644
--- a/libs/surfaceflinger/LayerBuffer.h
+++ b/libs/surfaceflinger/LayerBuffer.h
@@ -47,7 +47,6 @@
virtual void postBuffer(ssize_t offset);
virtual void unregisterBuffers();
virtual void destroy() { }
- SurfaceFlinger* getFlinger() const { return mLayer.mFlinger.get(); }
protected:
LayerBuffer& mLayer;
};
diff --git a/libs/surfaceflinger/LayerDim.cpp b/libs/surfaceflinger/LayerDim.cpp
index c13b4b3..906a583 100644
--- a/libs/surfaceflinger/LayerDim.cpp
+++ b/libs/surfaceflinger/LayerDim.cpp
@@ -112,17 +112,15 @@
Region::const_iterator const end = clip.end();
if (s.alpha>0 && (it != end)) {
const DisplayHardware& hw(graphicPlane(0).displayHardware());
- const GLfloat alpha = s.alpha/255.0f;
+ const GGLfixed alpha = (s.alpha << 16)/255;
const uint32_t fbHeight = hw.getHeight();
glDisable(GL_DITHER);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- glColor4f(0, 0, 0, alpha);
-
+ glColor4x(0, 0, 0, alpha);
+
#if defined(GL_OES_texture_external)
- if (GLExtensions::getInstance().haveTextureExternal()) {
- glDisable(GL_TEXTURE_EXTERNAL_OES);
- }
+ glDisable(GL_TEXTURE_EXTERNAL_OES);
#endif
#if defined(DIM_WITH_TEXTURE) && defined(EGL_ANDROID_image_native_buffer)
if (sUseTexture) {
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index 23efd16..96a5411 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -44,7 +44,6 @@
#include <GLES/gl.h>
#include "clz.h"
-#include "GLExtensions.h"
#include "Layer.h"
#include "LayerBlur.h"
#include "LayerBuffer.h"
@@ -994,9 +993,7 @@
glTexCoordPointer(2, GL_SHORT, 0, tcoords);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
#if defined(GL_OES_texture_external)
- if (GLExtensions::getInstance().haveTextureExternal()) {
- glDisable(GL_TEXTURE_EXTERNAL_OES);
- }
+ glDisable(GL_TEXTURE_EXTERNAL_OES);
#endif
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, mWormholeTexName);
diff --git a/libs/surfaceflinger/TextureManager.cpp b/libs/surfaceflinger/TextureManager.cpp
index e4dd42f..d9bdc6a 100644
--- a/libs/surfaceflinger/TextureManager.cpp
+++ b/libs/surfaceflinger/TextureManager.cpp
@@ -30,15 +30,14 @@
#include "clz.h"
#include "DisplayHardware/DisplayHardware.h"
-#include "GLExtensions.h"
#include "TextureManager.h"
namespace android {
// ---------------------------------------------------------------------------
-TextureManager::TextureManager()
- : mGLExtensions(GLExtensions::getInstance())
+TextureManager::TextureManager(uint32_t flags)
+ : mFlags(flags)
{
}
@@ -86,11 +85,9 @@
GLenum target = GL_TEXTURE_2D;
#if defined(GL_OES_texture_external)
- if (GLExtensions::getInstance().haveTextureExternal()) {
- if (format && isSupportedYuvFormat(format)) {
- target = GL_TEXTURE_EXTERNAL_OES;
- pImage->target = Texture::TEXTURE_EXTERNAL;
- }
+ if (format && isSupportedYuvFormat(format)) {
+ target = GL_TEXTURE_EXTERNAL_OES;
+ pImage->target = Texture::TEXTURE_EXTERNAL;
}
#endif
@@ -211,7 +208,7 @@
/*
* round to POT if needed
*/
- if (!mGLExtensions.haveNpot()) {
+ if (!(mFlags & DisplayHardware::NPOT_EXTENSION)) {
texture->NPOTAdjust = true;
}
@@ -297,19 +294,14 @@
void TextureManager::activateTexture(const Texture& texture, bool filter)
{
const GLenum target = getTextureTarget(&texture);
- if (target == Texture::TEXTURE_2D) {
- glBindTexture(GL_TEXTURE_2D, texture.name);
- glEnable(GL_TEXTURE_2D);
+
+ glBindTexture(target, texture.name);
+ glEnable(target);
+
#if defined(GL_OES_texture_external)
- if (GLExtensions::getInstance().haveTextureExternal()) {
- glDisable(GL_TEXTURE_EXTERNAL_OES);
- }
-#endif
- }
-#if defined(GL_OES_texture_external)
- else {
- glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture.name);
- glEnable(GL_TEXTURE_EXTERNAL_OES);
+ if (texture.target == Texture::TEXTURE_2D) {
+ glDisable(GL_TEXTURE_EXTERNAL_OES);
+ } else {
glDisable(GL_TEXTURE_2D);
}
#endif
@@ -327,9 +319,7 @@
{
glDisable(GL_TEXTURE_2D);
#if defined(GL_OES_texture_external)
- if (GLExtensions::getInstance().haveTextureExternal()) {
- glDisable(GL_TEXTURE_EXTERNAL_OES);
- }
+ glDisable(GL_TEXTURE_EXTERNAL_OES);
#endif
}
diff --git a/libs/surfaceflinger/TextureManager.h b/libs/surfaceflinger/TextureManager.h
index c7c14e7..1f7fe3f 100644
--- a/libs/surfaceflinger/TextureManager.h
+++ b/libs/surfaceflinger/TextureManager.h
@@ -32,7 +32,6 @@
// ---------------------------------------------------------------------------
-class GLExtensions;
class GraphicBuffer;
// ---------------------------------------------------------------------------
@@ -62,7 +61,7 @@
// ---------------------------------------------------------------------------
class TextureManager {
- const GLExtensions& mGLExtensions;
+ uint32_t mFlags;
static status_t initTexture(Image* texture, int32_t format);
static status_t initTexture(Texture* texture);
static bool isSupportedYuvFormat(int format);
@@ -70,7 +69,7 @@
static GLenum getTextureTarget(const Image* pImage);
public:
- TextureManager();
+ TextureManager(uint32_t flags);
// load bitmap data into the active buffer
status_t loadTexture(Texture* texture,