Merge "Make sure Geolocation is robust to location providers being absent on the device."
diff --git a/include/private/surfaceflinger/SharedBufferStack.h b/include/private/surfaceflinger/SharedBufferStack.h
index c23832d..a1a02e0 100644
--- a/include/private/surfaceflinger/SharedBufferStack.h
+++ b/include/private/surfaceflinger/SharedBufferStack.h
@@ -295,7 +295,8 @@
friend class BufferList;
uint32_t mask, curr;
const_iterator(uint32_t mask) :
- mask(mask), curr(31 - __builtin_clz(mask)) { }
+ mask(mask), curr(__builtin_clz(mask)) {
+ }
public:
inline bool operator == (const const_iterator& rhs) const {
return mask == rhs.mask;
@@ -304,9 +305,9 @@
return mask != rhs.mask;
}
inline int operator *() const { return curr; }
- inline const const_iterator& operator ++(int) {
- mask &= ~curr;
- curr = 31 - __builtin_clz(mask);
+ inline const const_iterator& operator ++() {
+ mask &= ~(1<<(31-curr));
+ curr = __builtin_clz(mask);
return *this;
}
};
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index 58eb590..3b38d83 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -873,11 +873,12 @@
LOGV("processConfigEvents() remaining events %d", mConfigEvents.size());
ConfigEvent *configEvent = mConfigEvents[0];
mConfigEvents.removeAt(0);
- // release mLock because audioConfigChanged() will lock AudioFlinger mLock
- // before calling Audioflinger::audioConfigChanged_l() thus creating
- // potential cross deadlock between AudioFlinger::mLock and mLock
+ // release mLock before locking AudioFlinger mLock: lock order is always
+ // AudioFlinger then ThreadBase to avoid cross deadlock
mLock.unlock();
- audioConfigChanged(configEvent->mEvent, configEvent->mParam);
+ mAudioFlinger->mLock.lock();
+ audioConfigChanged_l(configEvent->mEvent, configEvent->mParam);
+ mAudioFlinger->mLock.unlock();
delete configEvent;
mLock.lock();
}
@@ -953,8 +954,6 @@
mStreamTypes[stream].volume = mAudioFlinger->streamVolumeInternal(stream);
mStreamTypes[stream].mute = mAudioFlinger->streamMute(stream);
}
- // notify client processes that a new input has been opened
- sendConfigEvent(AudioSystem::OUTPUT_OPENED);
}
AudioFlinger::PlaybackThread::~PlaybackThread()
@@ -1234,11 +1233,12 @@
return mOutput->getParameters(keys);
}
-void AudioFlinger::PlaybackThread::audioConfigChanged(int event, int param) {
+// destroyTrack_l() must be called with AudioFlinger::mLock held
+void AudioFlinger::PlaybackThread::audioConfigChanged_l(int event, int param) {
AudioSystem::OutputDescriptor desc;
void *param2 = 0;
- LOGV("PlaybackThread::audioConfigChanged, thread %p, event %d, param %d", this, event, param);
+ LOGV("PlaybackThread::audioConfigChanged_l, thread %p, event %d, param %d", this, event, param);
switch (event) {
case AudioSystem::OUTPUT_OPENED:
@@ -1257,7 +1257,6 @@
default:
break;
}
- Mutex::Autolock _l(mAudioFlinger->mLock);
mAudioFlinger->audioConfigChanged_l(event, mId, param2);
}
@@ -1614,66 +1613,22 @@
return mixerStatus;
}
-void AudioFlinger::MixerThread::getTracks(
- SortedVector < sp<Track> >& tracks,
- SortedVector < wp<Track> >& activeTracks,
- int streamType)
+void AudioFlinger::MixerThread::invalidateTracks(int streamType)
{
- LOGV ("MixerThread::getTracks() mixer %p, mTracks.size %d, mActiveTracks.size %d", this, mTracks.size(), mActiveTracks.size());
+ LOGV ("MixerThread::invalidateTracks() mixer %p, streamType %d, mTracks.size %d", this, streamType, mTracks.size());
Mutex::Autolock _l(mLock);
size_t size = mTracks.size();
for (size_t i = 0; i < size; i++) {
sp<Track> t = mTracks[i];
if (t->type() == streamType) {
- tracks.add(t);
- int j = mActiveTracks.indexOf(t);
- if (j >= 0) {
- t = mActiveTracks[j].promote();
- if (t != NULL) {
- activeTracks.add(t);
+ t->mCblk->lock.lock();
+ t->mCblk->flags |= CBLK_INVALID_ON;
+ t->mCblk->cv.signal();
+ t->mCblk->lock.unlock();
}
}
}
- }
- size = activeTracks.size();
- for (size_t i = 0; i < size; i++) {
- mActiveTracks.remove(activeTracks[i]);
- }
-
- size = tracks.size();
- for (size_t i = 0; i < size; i++) {
- sp<Track> t = tracks[i];
- mTracks.remove(t);
- deleteTrackName_l(t->name());
- }
-}
-
-void AudioFlinger::MixerThread::putTracks(
- SortedVector < sp<Track> >& tracks,
- SortedVector < wp<Track> >& activeTracks)
-{
- LOGV ("MixerThread::putTracks() mixer %p, tracks.size %d, activeTracks.size %d", this, tracks.size(), activeTracks.size());
- Mutex::Autolock _l(mLock);
- size_t size = tracks.size();
- for (size_t i = 0; i < size ; i++) {
- sp<Track> t = tracks[i];
- int name = getTrackName_l();
-
- if (name < 0) return;
-
- t->mName = name;
- t->mThread = this;
- mTracks.add(t);
-
- int j = activeTracks.indexOf(t);
- if (j >= 0) {
- mActiveTracks.add(t);
- // force buffer refilling and no ramp volume when the track is mixed for the first time
- t->mFillingUpStatus = Track::FS_FILLING;
- }
- }
-}
// getTrackName_l() must be called with ThreadBase::mLock held
int AudioFlinger::MixerThread::getTrackName_l()
@@ -2348,7 +2303,7 @@
memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
// Force underrun condition to avoid false underrun callback until first data is
// written to buffer
- mCblk->flowControlFlag = 1;
+ mCblk->flags = CBLK_UNDERRUN_ON;
} else {
mBuffer = sharedBuffer->pointer();
}
@@ -2371,7 +2326,7 @@
memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
// Force underrun condition to avoid false underrun callback until first data is
// written to buffer
- mCblk->flowControlFlag = 1;
+ mCblk->flags = CBLK_UNDERRUN_ON;
mBufferEnd = (uint8_t *)mBuffer + bufferSize;
}
}
@@ -2589,9 +2544,9 @@
if (mFillingUpStatus != FS_FILLING) return true;
if (mCblk->framesReady() >= mCblk->frameCount ||
- mCblk->forceReady) {
+ (mCblk->flags & CBLK_FORCEREADY_MSK)) {
mFillingUpStatus = FS_FILLED;
- mCblk->forceReady = 0;
+ mCblk->flags &= ~CBLK_FORCEREADY_MSK;
return true;
}
return false;
@@ -2706,8 +2661,8 @@
TrackBase::reset();
// Force underrun condition to avoid false underrun callback until first data is
// written to buffer
- mCblk->flowControlFlag = 1;
- mCblk->forceReady = 0;
+ mCblk->flags |= CBLK_UNDERRUN_ON;
+ mCblk->flags &= ~CBLK_FORCEREADY_MSK;
mFillingUpStatus = FS_FILLING;
mResetDone = true;
}
@@ -2818,7 +2773,7 @@
TrackBase::reset();
// Force overerrun condition to avoid false overrun callback until first data is
// read from buffer
- mCblk->flowControlFlag = 1;
+ mCblk->flags |= CBLK_UNDERRUN_ON;
}
}
@@ -2851,7 +2806,7 @@
PlaybackThread *playbackThread = (PlaybackThread *)thread.unsafe_get();
if (mCblk != NULL) {
- mCblk->out = 1;
+ mCblk->flags |= CBLK_DIRECTION_OUT;
mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
mCblk->volume[0] = mCblk->volume[1] = 0x1000;
mOutBuffer.frameCount = 0;
@@ -3274,7 +3229,6 @@
mReqChannelCount = AudioSystem::popCount(channels);
mReqSampleRate = sampleRate;
readInputParameters();
- sendConfigEvent(AudioSystem::INPUT_OPENED);
}
@@ -3689,7 +3643,7 @@
return mInput->getParameters(keys);
}
-void AudioFlinger::RecordThread::audioConfigChanged(int event, int param) {
+void AudioFlinger::RecordThread::audioConfigChanged_l(int event, int param) {
AudioSystem::OutputDescriptor desc;
void *param2 = 0;
@@ -3708,7 +3662,6 @@
default:
break;
}
- Mutex::Autolock _l(mAudioFlinger->mLock);
mAudioFlinger->audioConfigChanged_l(event, mId, param2);
}
@@ -3828,6 +3781,8 @@
if (pChannels) *pChannels = channels;
if (pLatencyMs) *pLatencyMs = thread->latency();
+ // notify client processes of the new output creation
+ thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
return mNextThreadId;
}
@@ -3849,6 +3804,8 @@
DuplicatingThread *thread = new DuplicatingThread(this, thread1, ++mNextThreadId);
thread->addOutputTrack(thread2);
mPlaybackThreads.add(mNextThreadId, thread);
+ // notify client processes of the new output creation
+ thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
return mNextThreadId;
}
@@ -3978,6 +3935,8 @@
input->standby();
+ // notify client processes of the new input creation
+ thread->audioConfigChanged_l(AudioSystem::INPUT_OPENED);
return mNextThreadId;
}
@@ -4018,22 +3977,16 @@
}
LOGV("setStreamOutput() stream %d to output %d", stream, output);
+ audioConfigChanged_l(AudioSystem::STREAM_CONFIG_CHANGED, output, &stream);
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
if (thread != dstThread &&
thread->type() != PlaybackThread::DIRECT) {
MixerThread *srcThread = (MixerThread *)thread;
- SortedVector < sp<MixerThread::Track> > tracks;
- SortedVector < wp<MixerThread::Track> > activeTracks;
- srcThread->getTracks(tracks, activeTracks, stream);
- if (tracks.size()) {
- dstThread->putTracks(tracks, activeTracks);
+ srcThread->invalidateTracks(stream);
}
}
- }
-
- dstThread->sendConfigEvent(AudioSystem::STREAM_CONFIG_CHANGED, stream);
return NO_ERROR;
}
diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h
index c4a5305..f35f38b 100644
--- a/libs/audioflinger/AudioFlinger.h
+++ b/libs/audioflinger/AudioFlinger.h
@@ -342,7 +342,7 @@
virtual bool checkForNewParameters_l() = 0;
virtual status_t setParameters(const String8& keyValuePairs);
virtual String8 getParameters(const String8& keys) = 0;
- virtual void audioConfigChanged(int event, int param = 0) = 0;
+ virtual void audioConfigChanged_l(int event, int param = 0) = 0;
void sendConfigEvent(int event, int param = 0);
void sendConfigEvent_l(int event, int param = 0);
void processConfigEvents();
@@ -547,7 +547,7 @@
void restore() { if (mSuspended) mSuspended--; }
bool isSuspended() { return (mSuspended != 0); }
virtual String8 getParameters(const String8& keys);
- virtual void audioConfigChanged(int event, int param = 0);
+ virtual void audioConfigChanged_l(int event, int param = 0);
virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames);
struct stream_type_t {
@@ -613,11 +613,7 @@
// Thread virtuals
virtual bool threadLoop();
- void getTracks(SortedVector < sp<Track> >& tracks,
- SortedVector < wp<Track> >& activeTracks,
- int streamType);
- void putTracks(SortedVector < sp<Track> >& tracks,
- SortedVector < wp<Track> >& activeTracks);
+ void invalidateTracks(int streamType);
virtual bool checkForNewParameters_l();
virtual status_t dumpInternals(int fd, const Vector<String16>& args);
@@ -764,7 +760,7 @@
virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer);
virtual bool checkForNewParameters_l();
virtual String8 getParameters(const String8& keys);
- virtual void audioConfigChanged(int event, int param = 0);
+ virtual void audioConfigChanged_l(int event, int param = 0);
void readInputParameters();
virtual unsigned int getInputFramesLost();
diff --git a/libs/audioflinger/AudioPolicyManagerBase.cpp b/libs/audioflinger/AudioPolicyManagerBase.cpp
index c8b3f48..381a958 100644
--- a/libs/audioflinger/AudioPolicyManagerBase.cpp
+++ b/libs/audioflinger/AudioPolicyManagerBase.cpp
@@ -1249,6 +1249,17 @@
LOGV("setDeviceConnectionState() closing A2DP and duplicated output!");
if (mDuplicatedOutput != 0) {
+ AudioOutputDescriptor *dupOutputDesc = mOutputs.valueFor(mDuplicatedOutput);
+ AudioOutputDescriptor *hwOutputDesc = mOutputs.valueFor(mHardwareOutput);
+ // As all active tracks on duplicated output will be deleted,
+ // and as they were also referenced on hardware output, the reference
+ // count for their stream type must be adjusted accordingly on
+ // hardware output.
+ for (int i = 0; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) {
+ int refCount = dupOutputDesc->mRefCount[i];
+ hwOutputDesc->changeRefCount((AudioSystem::stream_type)i,-refCount);
+ }
+
mpClientInterface->closeOutput(mDuplicatedOutput);
delete mOutputs.valueFor(mDuplicatedOutput);
mOutputs.removeItem(mDuplicatedOutput);
@@ -1288,11 +1299,6 @@
for (int i = 0; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) {
if (getStrategy((AudioSystem::stream_type)i) == strategy) {
mpClientInterface->setStreamOutput((AudioSystem::stream_type)i, mHardwareOutput);
- int refCount = a2dpOutputDesc->mRefCount[i];
- // in the case of duplicated output, the ref count is first incremented
- // and then decremented on hardware output tus keeping its value
- hwOutputDesc->changeRefCount((AudioSystem::stream_type)i, refCount);
- a2dpOutputDesc->changeRefCount((AudioSystem::stream_type)i,-refCount);
}
}
// do not change newDevice if it was already set before this call by a previous call to
@@ -1318,11 +1324,6 @@
for (int i = 0; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) {
if (getStrategy((AudioSystem::stream_type)i) == strategy) {
mpClientInterface->setStreamOutput((AudioSystem::stream_type)i, a2dpOutput);
- int refCount = hwOutputDesc->mRefCount[i];
- // in the case of duplicated output, the ref count is first incremented
- // and then decremented on hardware output tus keeping its value
- a2dpOutputDesc->changeRefCount((AudioSystem::stream_type)i, refCount);
- hwOutputDesc->changeRefCount((AudioSystem::stream_type)i,-refCount);
}
}
}
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index af89e9a..51de1da 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -73,7 +73,7 @@
DisplayHardware::DisplayHardware(
const sp<SurfaceFlinger>& flinger,
uint32_t dpy)
- : DisplayHardwareBase(flinger, dpy)
+ : DisplayHardwareBase(flinger, dpy), mFlags(0)
{
init(dpy);
}
diff --git a/libs/surfaceflinger_client/SharedBufferStack.cpp b/libs/surfaceflinger_client/SharedBufferStack.cpp
index 4a98026..dab8ed8 100644
--- a/libs/surfaceflinger_client/SharedBufferStack.cpp
+++ b/libs/surfaceflinger_client/SharedBufferStack.cpp
@@ -182,10 +182,22 @@
int tail = computeTail();
snprintf(buffer, SIZE,
"%s[ head=%2d, available=%2d, queued=%2d, tail=%2d ] "
- "reallocMask=%08x, inUse=%2d, identity=%d, status=%d\n",
+ "reallocMask=%08x, inUse=%2d, identity=%d, status=%d",
prefix, stack.head, stack.available, stack.queued, tail,
stack.reallocMask, stack.inUse, stack.identity, stack.status);
result.append(buffer);
+
+ snprintf(buffer, SIZE, " { ");
+ result.append(buffer);
+
+ for (int i=0 ; i<mNumBuffers ; i++) {
+ snprintf(buffer, SIZE, "%d ", stack.index[i]);
+ result.append(buffer);
+ }
+
+ snprintf(buffer, SIZE, " }\n");
+ result.append(buffer);
+
return result;
}
@@ -323,6 +335,7 @@
// lock the buffer before advancing head, which automatically unlocks
// the buffer we preventively locked upon entering this function
+
head = (head + 1) % numBuffers;
android_atomic_write(stack.index[head], &stack.inUse);
@@ -416,7 +429,7 @@
{
SharedBufferStack& stack( *mSharedStack );
- queued_head = ((queued_head+1 >= mNumBuffers) ? 0 : queued_head+1);
+ queued_head = (queued_head + 1) % mNumBuffers;
stack.index[queued_head] = buf;
QueueUpdate update(this);
@@ -449,9 +462,11 @@
status_t SharedBufferClient::setBufferCount(int bufferCount)
{
+ SharedBufferStack& stack( *mSharedStack );
if (uint32_t(bufferCount) >= NUM_BUFFER_MAX)
return BAD_VALUE;
mNumBuffers = bufferCount;
+ queued_head = (stack.head + stack.queued) % mNumBuffers;
return NO_ERROR;
}
@@ -560,6 +575,7 @@
int base = numBuffers;
int32_t avail = stack.available;
int tail = head - avail + 1;
+
if (tail >= 0) {
int8_t* const index = const_cast<int8_t*>(stack.index);
const int nb = numBuffers - head;
@@ -573,8 +589,9 @@
// fill the new free space with unused buffers
BufferList::const_iterator curr(mBufferList.free_begin());
for (int i=0 ; i<extra ; i++) {
- stack.index[base+i] = *curr++;
- mBufferList.add(stack.index[base+i]);
+ stack.index[base+i] = *curr;
+ mBufferList.add(*curr);
+ ++curr;
}
mNumBuffers = newNumBuffers;
diff --git a/libs/surfaceflinger_client/tests/SharedBufferStack/SharedBufferStackTest.cpp b/libs/surfaceflinger_client/tests/SharedBufferStack/SharedBufferStackTest.cpp
index 6732580..f490a65 100644
--- a/libs/surfaceflinger_client/tests/SharedBufferStack/SharedBufferStackTest.cpp
+++ b/libs/surfaceflinger_client/tests/SharedBufferStack/SharedBufferStackTest.cpp
@@ -24,6 +24,43 @@
using namespace android;
+void log(const char* prefix, int *b, size_t num);
+void test0(SharedBufferServer& s, SharedBufferClient& c, size_t num, int* list);
+
+// ----------------------------------------------------------------------------
+
+int main(int argc, char** argv)
+{
+ SharedClient client;
+ SharedBufferServer s(&client, 0, 4, 0);
+ SharedBufferClient c(&client, 0, 4, 0);
+
+ printf("basic test 0\n");
+ int list0[4] = {0, 1, 2, 3};
+ test0(s, c, 4, list0);
+
+ printf("basic test 1\n");
+ int list1[4] = {2, 1, 0, 3};
+ test0(s, c, 4, list1);
+
+ int b = c.dequeue();
+ c.lock(b);
+ c.queue(b);
+ s.retireAndLock();
+
+ printf("basic test 2\n");
+ int list2[4] = {1, 2, 3, 0};
+ test0(s, c, 4, list2);
+
+
+ printf("resize test\n");
+ s.resize(6);
+ c.setBufferCount(6);
+ int list3[6] = {3, 2, 1, 4, 5, 0};
+ test0(s, c, 6, list3);
+
+ return 0;
+}
void log(const char* prefix, int *b, size_t num)
{
@@ -34,18 +71,20 @@
printf("\n");
}
-int main(int argc, char** argv)
+// ----------------------------------------------------------------------------
+
+void test0(
+ SharedBufferServer& s,
+ SharedBufferClient& c,
+ size_t num,
+ int* list)
{
status_t err;
- const size_t num = 4;
- SharedClient client;
- SharedBufferServer s(&client, 0, num, 0);
- SharedBufferClient c(&client, 0, num, 0);
int b[num], u[num], r[num];
for (size_t i=0 ; i<num ; i++) {
b[i] = c.dequeue();
- assert(b[i]==i);
+ assert(b[i]==list[i]);
}
log("DQ", b, num);
@@ -64,7 +103,7 @@
for (size_t i=0 ; i<num-1 ; i++) {
r[i] = s.retireAndLock();
- assert(r[i]==i);
+ assert(r[i]==list[i]);
err = s.unlock(r[i]);
assert(err == 0);
}
@@ -79,7 +118,7 @@
log(" Q", b+num-1, 1);
r[num-1] = s.retireAndLock();
- assert(r[num-1]==num-1);
+ assert(r[num-1]==list[num-1]);
err = s.unlock(r[num-1]);
assert(err == 0);
log("RT", r+num-1, 1);
@@ -89,7 +128,7 @@
for (size_t i=0 ; i<num ; i++) {
b[i] = c.dequeue();
- assert(b[i]==i);
+ assert(b[i]==list[i]);
}
log("DQ", b, num);
@@ -102,7 +141,7 @@
for (size_t i=0 ; i<num-1 ; i++) {
u[i] = b[num-2-i];
}
- u[num-1] = num-1;
+ u[num-1] = b[num-1];
for (size_t i=0 ; i<num-1 ; i++) {
err = c.queue(u[i]);
@@ -127,7 +166,7 @@
log(" Q", b+num-1, 1);
r[num-1] = s.retireAndLock();
- assert(r[num-1]==num-1);
+ assert(r[num-1]==list[num-1]);
err = s.unlock(r[num-1]);
assert(err == 0);
log("RT", r+num-1, 1);
@@ -170,7 +209,7 @@
log(" Q", u+num-1, 1);
r[num-1] = s.retireAndLock();
- assert(r[num-1]==num-1);
+ assert(r[num-1]==u[num-1]);
err = s.unlock(r[num-1]);
assert(err == 0);
log("RT", r+num-1, 1);
@@ -224,10 +263,9 @@
log(" Q", u+num-1, 1);
r[num-1] = s.retireAndLock();
- assert(r[num-1]==num-1);
+ assert(r[num-1]==u[num-1]);
err = s.unlock(r[num-1]);
assert(err == 0);
log("RT", r+num-1, 1);
-
- return 0;
+ printf("\n");
}
diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp
index b6e0aae..7cb01d0 100644
--- a/opengl/libagl/egl.cpp
+++ b/opengl/libagl/egl.cpp
@@ -1525,8 +1525,13 @@
}
if (ggl_unlikely(attrib_list==0)) {
- *num_config = 0;
- return EGL_TRUE;
+ /*
+ * A NULL attrib_list should be treated as though it was an empty
+ * one (terminated with EGL_NONE) as defined in
+ * section 3.4.1 "Querying Configurations" in the EGL specification.
+ */
+ static const EGLint dummy = EGL_NONE;
+ attrib_list = &dummy;
}
int numAttributes = 0;
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index e6cf792..ba09d08 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -843,10 +843,12 @@
EGLint patch_index = -1;
GLint attr;
size_t size = 0;
- while ((attr=attrib_list[size]) != EGL_NONE) {
- if (attr == EGL_CONFIG_ID)
- patch_index = size;
- size += 2;
+ if (attrib_list) {
+ while ((attr=attrib_list[size]) != EGL_NONE) {
+ if (attr == EGL_CONFIG_ID)
+ patch_index = size;
+ size += 2;
+ }
}
if (patch_index >= 0) {
size += 2; // we need copy the sentinel as well