Merge commit '1ee45c2d2d816ee912624d81ff1b0aaa98e8fa74' into HEAD
diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h
index 7a782f5..c95f297 100644
--- a/include/binder/Parcel.h
+++ b/include/binder/Parcel.h
@@ -101,6 +101,7 @@
     status_t            writeString16(const char16_t* str, size_t len);
     status_t            writeStrongBinder(const sp<IBinder>& val);
     status_t            writeWeakBinder(const wp<IBinder>& val);
+    status_t            writeInt32Array(size_t len, const int32_t *val);
 
     template<typename T>
     status_t            write(const Flattenable<T>& val);
diff --git a/include/powermanager/IPowerManager.h b/include/powermanager/IPowerManager.h
index 2f4c3c4..d85003f 100644
--- a/include/powermanager/IPowerManager.h
+++ b/include/powermanager/IPowerManager.h
@@ -35,6 +35,7 @@
     virtual status_t acquireWakeLockWithUid(int flags, const sp<IBinder>& lock, const String16& tag,
             const String16& packageName, int uid) = 0;
     virtual status_t releaseWakeLock(const sp<IBinder>& lock, int flags) = 0;
+    virtual status_t updateWakeLockUids(const sp<IBinder>& lock, int len, const int *uids) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 7a5919f..38e019c 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -617,6 +617,16 @@
 {
     return writeAligned(val);
 }
+status_t Parcel::writeInt32Array(size_t len, const int32_t *val) {
+    if (!val) {
+        return writeAligned(-1);
+    }
+    status_t ret = writeAligned(len);
+    if (ret == NO_ERROR) {
+        ret = write(val, len * sizeof(*val));
+    }
+    return ret;
+}
 
 status_t Parcel::writeInt64(int64_t val)
 {
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index c165a68..2aecb67 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -644,6 +644,7 @@
             producerControlledByApp ? "true" : "false");
     Mutex::Autolock lock(mMutex);
 
+retry:
     if (mAbandoned) {
         ST_LOGE("connect: BufferQueue has been abandoned!");
         return NO_INIT;
@@ -654,29 +655,41 @@
         return NO_INIT;
     }
 
+    if (mConnectedApi != NO_CONNECTED_API) {
+        ST_LOGE("connect: already connected (cur=%d, req=%d)",
+                mConnectedApi, api);
+        return -EINVAL;
+    }
+
+    // If we disconnect and reconnect quickly, we can be in a state where our slots are
+    // empty but we have many buffers in the queue.  This can cause us to run out of
+    // memory if we outrun the consumer.  Wait here if it looks like we have too many
+    // buffers queued up.
+    int maxBufferCount = getMaxBufferCountLocked(false);    // worst-case, i.e. largest value
+    if (mQueue.size() > (size_t) maxBufferCount) {
+        // TODO: make this bound tighter?
+        ST_LOGV("queue size is %d, waiting", mQueue.size());
+        mDequeueCondition.wait(mMutex);
+        goto retry;
+    }
+
     int err = NO_ERROR;
     switch (api) {
         case NATIVE_WINDOW_API_EGL:
         case NATIVE_WINDOW_API_CPU:
         case NATIVE_WINDOW_API_MEDIA:
         case NATIVE_WINDOW_API_CAMERA:
-            if (mConnectedApi != NO_CONNECTED_API) {
-                ST_LOGE("connect: already connected (cur=%d, req=%d)",
-                        mConnectedApi, api);
-                err = -EINVAL;
-            } else {
-                mConnectedApi = api;
-                output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint, mQueue.size());
+            mConnectedApi = api;
+            output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint, mQueue.size());
 
-                // set-up a death notification so that we can disconnect
-                // automatically when/if the remote producer dies.
-                if (token != NULL && token->remoteBinder() != NULL) {
-                    status_t err = token->linkToDeath(static_cast<IBinder::DeathRecipient*>(this));
-                    if (err == NO_ERROR) {
-                        mConnectedProducerToken = token;
-                    } else {
-                        ALOGE("linkToDeath failed: %s (%d)", strerror(-err), err);
-                    }
+            // set-up a death notification so that we can disconnect
+            // automatically when/if the remote producer dies.
+            if (token != NULL && token->remoteBinder() != NULL) {
+                status_t err = token->linkToDeath(static_cast<IBinder::DeathRecipient*>(this));
+                if (err == NO_ERROR) {
+                    mConnectedProducerToken = token;
+                } else {
+                    ALOGE("linkToDeath failed: %s (%d)", strerror(-err), err);
                 }
             }
             break;
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 9bd7fc6..09b2e7c 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -511,14 +511,17 @@
     status_t result;
     for (size_t i = mBatches.size(); i-- > 0; ) {
         Batch& batch = mBatches.editItemAt(i);
-        if (frameTime < 0 || !mResampleTouch) {
+        if (frameTime < 0) {
             result = consumeSamples(factory, batch, batch.samples.size(),
                     outSeq, outEvent);
             mBatches.removeAt(i);
             return result;
         }
 
-        nsecs_t sampleTime = frameTime - RESAMPLE_LATENCY;
+        nsecs_t sampleTime = frameTime;
+        if (mResampleTouch) {
+            sampleTime -= RESAMPLE_LATENCY;
+        }
         ssize_t split = findSampleNoLaterThan(batch, sampleTime);
         if (split < 0) {
             continue;
@@ -532,7 +535,7 @@
         } else {
             next = &batch.samples.itemAt(0);
         }
-        if (!result) {
+        if (!result && mResampleTouch) {
             resampleTouchState(sampleTime, static_cast<MotionEvent*>(*outEvent), next);
         }
         return result;
diff --git a/opengl/libs/EGL/trace.cpp b/opengl/libs/EGL/trace.cpp
index bac6ba8..3e228e4 100644
--- a/opengl/libs/EGL/trace.cpp
+++ b/opengl/libs/EGL/trace.cpp
@@ -435,7 +435,7 @@
     if (error) {                                                          \
         CallStack s;                                                      \
         s.update();                                                       \
-        s.dump("glGetError:" #_api);                                      \
+        s.log("glGetError:" #_api);                                       \
     }                                                                     \
 
 #define TRACE_GL_VOID(_api, _args, _argList, ...)                         \
diff --git a/services/powermanager/IPowerManager.cpp b/services/powermanager/IPowerManager.cpp
index 9f60e75..5ecd299 100644
--- a/services/powermanager/IPowerManager.cpp
+++ b/services/powermanager/IPowerManager.cpp
@@ -32,6 +32,7 @@
     ACQUIRE_WAKE_LOCK = IBinder::FIRST_CALL_TRANSACTION,
     ACQUIRE_WAKE_LOCK_UID = IBinder::FIRST_CALL_TRANSACTION + 1,
     RELEASE_WAKE_LOCK = IBinder::FIRST_CALL_TRANSACTION + 2,
+    UPDATE_WAKE_LOCK_UIDS = IBinder::FIRST_CALL_TRANSACTION + 3,
 };
 
 class BpPowerManager : public BpInterface<IPowerManager>
@@ -78,6 +79,16 @@
         data.writeInt32(flags);
         return remote()->transact(RELEASE_WAKE_LOCK, data, &reply);
     }
+
+    virtual status_t updateWakeLockUids(const sp<IBinder>& lock, int len, const int *uids) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IPowerManager::getInterfaceDescriptor());
+        data.writeStrongBinder(lock);
+        data.writeInt32Array(len, uids);
+        // We don't really care too much if this succeeds (there's nothing we can do if it doesn't)
+        // but it should return ASAP
+        return remote()->transact(UPDATE_WAKE_LOCK_UIDS, data, &reply, IBinder::FLAG_ONEWAY);
+    }
 };
 
 IMPLEMENT_META_INTERFACE(PowerManager, "android.os.IPowerManager");
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 555d843..a2f4332 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -480,6 +480,11 @@
     return result;
 }
 
+bool SensorService::isVirtualSensor(int handle) const {
+    SensorInterface* sensor = mSensorMap.valueFor(handle);
+    return sensor->isVirtual();
+}
+
 Vector<Sensor> SensorService::getSensorList()
 {
     char value[PROPERTY_VALUE_MAX];
@@ -858,6 +863,11 @@
         }
     }
 
+    // Early return if there are no events for this connection.
+    if (count == 0) {
+        return status_t(NO_ERROR);
+    }
+
     // NOTE: ASensorEvent and sensors_event_t are the same type
     ssize_t size = SensorEventQueue::write(mChannel,
             reinterpret_cast<ASensorEvent const*>(scratch), count);
@@ -922,7 +932,7 @@
     // Loop through all sensors for this connection and call flush on each of them.
     for (size_t i = 0; i < mSensorInfo.size(); ++i) {
         const int handle = mSensorInfo.keyAt(i);
-        if (halVersion < SENSORS_DEVICE_API_VERSION_1_1) {
+        if (halVersion < SENSORS_DEVICE_API_VERSION_1_1 || mService->isVirtualSensor(handle)) {
             // For older devices just increment pending flush count which will send a trivial
             // flush complete event.
             FlushInfo& flushInfo = mSensorInfo.editValueFor(handle);
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 6c1691a..c968319 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -130,6 +130,7 @@
     DefaultKeyedVector<int, SensorInterface*> getActiveVirtualSensors() const;
 
     String8 getSensorName(int handle) const;
+    bool isVirtualSensor(int handle) const;
     void recordLastValue(sensors_event_t const * buffer, size_t count);
     static void sortEventBuffer(sensors_event_t* buffer, size_t count);
     Sensor registerSensor(SensorInterface* sensor);
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index c3daa64..b2bc550 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -51,6 +51,10 @@
 	LOCAL_CFLAGS += -DTARGET_DISABLE_TRIPLE_BUFFERING
 endif
 
+ifeq ($(TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS),true)
+    LOCAL_CFLAGS += -DFORCE_HWC_COPY_FOR_VIRTUAL_DISPLAYS
+endif
+
 ifneq ($(NUM_FRAMEBUFFER_SURFACE_BUFFERS),)
   LOCAL_CFLAGS += -DNUM_FRAMEBUFFER_SURFACE_BUFFERS=$(NUM_FRAMEBUFFER_SURFACE_BUFFERS)
 endif
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 2469f0c..c7d1a90 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -605,7 +605,7 @@
         mLists[i] = disp.list;
         if (mLists[i]) {
             if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
-                mLists[i]->outbuf = NULL;
+                mLists[i]->outbuf = disp.outbufHandle;
                 mLists[i]->outbufAcquireFenceFd = -1;
             } else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
                 // garbage data to catch improper use
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index c5a14b0..be5cf4a 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -22,6 +22,12 @@
 namespace android {
 // ---------------------------------------------------------------------------
 
+#if defined(FORCE_HWC_COPY_FOR_VIRTUAL_DISPLAYS)
+static const bool sForceHwcCopy = true;
+#else
+static const bool sForceHwcCopy = false;
+#endif
+
 #define VDS_LOGE(msg, ...) ALOGE("[%s] "msg, \
         mDisplayName.string(), ##__VA_ARGS__)
 #define VDS_LOGW_IF(cond, msg, ...) ALOGW_IF(cond, "[%s] "msg, \
@@ -47,7 +53,7 @@
     mHwc(hwc),
     mDisplayId(dispId),
     mDisplayName(name),
-    mProducerUsage(GRALLOC_USAGE_HW_COMPOSER),
+    mOutputUsage(GRALLOC_USAGE_HW_COMPOSER),
     mProducerSlotSource(0),
     mDbgState(DBG_STATE_IDLE),
     mDbgLastCompositionType(COMPOSITION_UNKNOWN)
@@ -58,8 +64,23 @@
     resetPerFrameState();
 
     int sinkWidth, sinkHeight;
-    mSource[SOURCE_SINK]->query(NATIVE_WINDOW_WIDTH, &sinkWidth);
-    mSource[SOURCE_SINK]->query(NATIVE_WINDOW_HEIGHT, &sinkHeight);
+    sink->query(NATIVE_WINDOW_WIDTH, &sinkWidth);
+    sink->query(NATIVE_WINDOW_HEIGHT, &sinkHeight);
+
+    // Pick the buffer format to request from the sink when not rendering to it
+    // with GLES. If the consumer needs CPU access, use the default format
+    // set by the consumer. Otherwise allow gralloc to decide the format based
+    // on usage bits.
+    int sinkUsage;
+    sink->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &sinkUsage);
+    if (sinkUsage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) {
+        int sinkFormat;
+        sink->query(NATIVE_WINDOW_FORMAT, &sinkFormat);
+        mDefaultOutputFormat = sinkFormat;
+    } else {
+        mDefaultOutputFormat = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
+    }
+    mOutputFormat = mDefaultOutputFormat;
 
     ConsumerBase::mName = String8::format("VDS: %s", mDisplayName.string());
     mConsumer->setConsumerName(ConsumerBase::mName);
@@ -95,6 +116,17 @@
     mDbgState = DBG_STATE_PREPARED;
 
     mCompositionType = compositionType;
+    if (sForceHwcCopy && mCompositionType == COMPOSITION_GLES) {
+        // Some hardware can do RGB->YUV conversion more efficiently in hardware
+        // controlled by HWC than in hardware controlled by the video encoder.
+        // Forcing GLES-composed frames to go through an extra copy by the HWC
+        // allows the format conversion to happen there, rather than passing RGB
+        // directly to the consumer.
+        //
+        // On the other hand, when the consumer prefers RGB or can consume RGB
+        // inexpensively, this forces an unnecessary copy.
+        mCompositionType = COMPOSITION_MIXED;
+    }
 
     if (mCompositionType != mDbgLastCompositionType) {
         VDS_LOGV("prepareFrame: composition type changed to %s",
@@ -102,6 +134,24 @@
         mDbgLastCompositionType = mCompositionType;
     }
 
+    if (mCompositionType != COMPOSITION_GLES &&
+            (mOutputFormat != mDefaultOutputFormat ||
+             mOutputUsage != GRALLOC_USAGE_HW_COMPOSER)) {
+        // We must have just switched from GLES-only to MIXED or HWC
+        // composition. Stop using the format and usage requested by the GLES
+        // driver; they may be suboptimal when HWC is writing to the output
+        // buffer. For example, if the output is going to a video encoder, and
+        // HWC can write directly to YUV, some hardware can skip a
+        // memory-to-memory RGB-to-YUV conversion step.
+        //
+        // If we just switched *to* GLES-only mode, we'll change the
+        // format/usage and get a new buffer when the GLES driver calls
+        // dequeueBuffer().
+        mOutputFormat = mDefaultOutputFormat;
+        mOutputUsage = GRALLOC_USAGE_HW_COMPOSER;
+        refreshOutputBuffer();
+    }
+
     return NO_ERROR;
 }
 
@@ -124,14 +174,8 @@
     }
     mDbgState = DBG_STATE_HWC;
 
-    if (mCompositionType == COMPOSITION_HWC) {
-        // Use the output buffer for the FB as well, though conceptually the
-        // FB is unused on this frame.
-        mFbProducerSlot = mOutputProducerSlot;
-        mFbFence = mOutputFence;
-    }
-
-    if (mFbProducerSlot < 0 || mOutputProducerSlot < 0) {
+    if (mOutputProducerSlot < 0 ||
+            (mCompositionType != COMPOSITION_HWC && mFbProducerSlot < 0)) {
         // Last chance bailout if something bad happened earlier. For example,
         // in a GLES configuration, if the sink disappears then dequeueBuffer
         // will fail, the GLES driver won't queue a buffer, but SurfaceFlinger
@@ -141,7 +185,8 @@
         return NO_MEMORY;
     }
 
-    sp<GraphicBuffer> fbBuffer = mProducerBuffers[mFbProducerSlot];
+    sp<GraphicBuffer> fbBuffer = mFbProducerSlot >= 0 ?
+            mProducerBuffers[mFbProducerSlot] : sp<GraphicBuffer>(NULL);
     sp<GraphicBuffer> outBuffer = mProducerBuffers[mOutputProducerSlot];
     VDS_LOGV("advanceFrame: fb=%d(%p) out=%d(%p)",
             mFbProducerSlot, fbBuffer.get(),
@@ -151,7 +196,12 @@
     // so update HWC state with it.
     mHwc.setOutputBuffer(mDisplayId, mOutputFence, outBuffer);
 
-    return mHwc.fbPost(mDisplayId, mFbFence, fbBuffer);
+    status_t result = NO_ERROR;
+    if (fbBuffer != NULL) {
+        result = mHwc.fbPost(mDisplayId, mFbFence, fbBuffer);
+    }
+
+    return result;
 }
 
 void VirtualDisplaySurface::onFrameCommitted() {
@@ -212,12 +262,12 @@
 }
 
 status_t VirtualDisplaySurface::dequeueBuffer(Source source,
-        uint32_t format, int* sslot, sp<Fence>* fence) {
+        uint32_t format, uint32_t usage, int* sslot, sp<Fence>* fence) {
     // Don't let a slow consumer block us
     bool async = (source == SOURCE_SINK);
 
     status_t result = mSource[source]->dequeueBuffer(sslot, fence, async,
-            mSinkBufferWidth, mSinkBufferHeight, format, mProducerUsage);
+            mSinkBufferWidth, mSinkBufferHeight, format, usage);
     if (result < 0)
         return result;
     int pslot = mapSource2ProducerSlot(source, *sslot);
@@ -241,8 +291,10 @@
     }
     if (result & BUFFER_NEEDS_REALLOCATION) {
         mSource[source]->requestBuffer(*sslot, &mProducerBuffers[pslot]);
-        VDS_LOGV("dequeueBuffer(%s): buffers[%d]=%p",
-                dbgSourceStr(source), pslot, mProducerBuffers[pslot].get());
+        VDS_LOGV("dequeueBuffer(%s): buffers[%d]=%p fmt=%d usage=%#x",
+                dbgSourceStr(source), pslot, mProducerBuffers[pslot].get(),
+                mProducerBuffers[pslot]->getPixelFormat(),
+                mProducerBuffers[pslot]->getUsage());
     }
 
     return result;
@@ -258,7 +310,6 @@
     VDS_LOGV("dequeueBuffer %dx%d fmt=%d usage=%#x", w, h, format, usage);
 
     status_t result = NO_ERROR;
-    mProducerUsage = usage | GRALLOC_USAGE_HW_COMPOSER;
     Source source = fbSourceForCompositionType(mCompositionType);
 
     if (source == SOURCE_SINK) {
@@ -279,13 +330,20 @@
         // prepare and set, but since we're in GLES-only mode already it
         // shouldn't matter.
 
+        usage |= GRALLOC_USAGE_HW_COMPOSER;
         const sp<GraphicBuffer>& buf = mProducerBuffers[mOutputProducerSlot];
-        if ((mProducerUsage & ~buf->getUsage()) != 0 ||
+        if ((usage & ~buf->getUsage()) != 0 ||
                 (format != 0 && format != (uint32_t)buf->getPixelFormat()) ||
                 (w != 0 && w != mSinkBufferWidth) ||
                 (h != 0 && h != mSinkBufferHeight)) {
-            VDS_LOGV("dequeueBuffer: output buffer doesn't satisfy GLES "
-                    "request, getting a new buffer");
+            VDS_LOGV("dequeueBuffer: dequeueing new output buffer: "
+                    "want %dx%d fmt=%d use=%#x, "
+                    "have %dx%d fmt=%d use=%#x",
+                    w, h, format, usage,
+                    mSinkBufferWidth, mSinkBufferHeight,
+                    buf->getPixelFormat(), buf->getUsage());
+            mOutputFormat = format;
+            mOutputUsage = usage;
             result = refreshOutputBuffer();
             if (result < 0)
                 return result;
@@ -297,7 +355,7 @@
         *fence = mOutputFence;
     } else {
         int sslot;
-        result = dequeueBuffer(source, format, &sslot, fence);
+        result = dequeueBuffer(source, format, usage, &sslot, fence);
         if (result >= 0) {
             *pslot = mapSource2ProducerSlot(source, sslot);
         }
@@ -400,9 +458,7 @@
     mCompositionType = COMPOSITION_UNKNOWN;
     mSinkBufferWidth = 0;
     mSinkBufferHeight = 0;
-    mFbFence = Fence::NO_FENCE;
     mOutputFence = Fence::NO_FENCE;
-    mFbProducerSlot = -1;
     mOutputProducerSlot = -1;
 }
 
@@ -414,7 +470,8 @@
     }
 
     int sslot;
-    status_t result = dequeueBuffer(SOURCE_SINK, 0, &sslot, &mOutputFence);
+    status_t result = dequeueBuffer(SOURCE_SINK, mOutputFormat, mOutputUsage,
+            &sslot, &mOutputFence);
     if (result < 0)
         return result;
     mOutputProducerSlot = mapSource2ProducerSlot(SOURCE_SINK, sslot);
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index 18fb5a7..1e85ac4 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -110,7 +110,7 @@
     // Utility methods
     //
     static Source fbSourceForCompositionType(CompositionType type);
-    status_t dequeueBuffer(Source source, uint32_t format,
+    status_t dequeueBuffer(Source source, uint32_t format, uint32_t usage,
             int* sslot, sp<Fence>* fence);
     void updateQueueBufferOutput(const QueueBufferOutput& qbo);
     void resetPerFrameState();
@@ -132,15 +132,18 @@
     const int32_t mDisplayId;
     const String8 mDisplayName;
     sp<IGraphicBufferProducer> mSource[2]; // indexed by SOURCE_*
+    uint32_t mDefaultOutputFormat;
 
     //
     // Inter-frame state
     //
 
-    // To avoid buffer reallocations, we track the buffer usage requested by
-    // the GLES driver in dequeueBuffer so we can use the same flags on
-    // HWC-only frames.
-    uint32_t mProducerUsage;
+    // To avoid buffer reallocations, we track the buffer usage and format
+    // we used on the previous frame and use it again on the new frame. If
+    // the composition type changes or the GLES driver starts requesting
+    // different usage/format, we'll get a new buffer.
+    uint32_t mOutputFormat;
+    uint32_t mOutputUsage;
 
     // Since we present a single producer interface to the GLES driver, but
     // are internally muxing between the sink and scratch producers, we have