Merge commit '1ee45c2d2d816ee912624d81ff1b0aaa98e8fa74' into HEAD
This commit is contained in:
commit
de8c80692b
@ -101,6 +101,7 @@ public:
|
||||
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);
|
||||
|
@ -35,6 +35,7 @@ public:
|
||||
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;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -617,6 +617,16 @@ status_t Parcel::writeInt32(int32_t val)
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
@ -644,6 +644,7 @@ status_t BufferQueue::connect(const sp<IBinder>& token,
|
||||
producerControlledByApp ? "true" : "false");
|
||||
Mutex::Autolock lock(mMutex);
|
||||
|
||||
retry:
|
||||
if (mAbandoned) {
|
||||
ST_LOGE("connect: BufferQueue has been abandoned!");
|
||||
return NO_INIT;
|
||||
@ -654,29 +655,41 @@ status_t BufferQueue::connect(const sp<IBinder>& token,
|
||||
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;
|
||||
|
@ -511,14 +511,17 @@ status_t InputConsumer::consumeBatch(InputEventFactoryInterface* factory,
|
||||
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 @@ status_t InputConsumer::consumeBatch(InputEventFactoryInterface* factory,
|
||||
} else {
|
||||
next = &batch.samples.itemAt(0);
|
||||
}
|
||||
if (!result) {
|
||||
if (!result && mResampleTouch) {
|
||||
resampleTouchState(sampleTime, static_cast<MotionEvent*>(*outEvent), next);
|
||||
}
|
||||
return result;
|
||||
|
@ -435,7 +435,7 @@ EGLAPI gl_hooks_t gHooksSystrace = {
|
||||
if (error) { \
|
||||
CallStack s; \
|
||||
s.update(); \
|
||||
s.dump("glGetError:" #_api); \
|
||||
s.log("glGetError:" #_api); \
|
||||
} \
|
||||
|
||||
#define TRACE_GL_VOID(_api, _args, _argList, ...) \
|
||||
|
@ -32,6 +32,7 @@ enum {
|
||||
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 @@ public:
|
||||
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");
|
||||
|
@ -480,6 +480,11 @@ String8 SensorService::getSensorName(int handle) const {
|
||||
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 @@ status_t SensorService::SensorEventConnection::sendEvents(
|
||||
}
|
||||
}
|
||||
|
||||
// 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 @@ status_t SensorService::SensorEventConnection::flush() {
|
||||
// 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);
|
||||
|
@ -130,6 +130,7 @@ class SensorService :
|
||||
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);
|
||||
|
@ -51,6 +51,10 @@ ifeq ($(TARGET_DISABLE_TRIPLE_BUFFERING),true)
|
||||
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
|
||||
|
@ -605,7 +605,7 @@ status_t HWComposer::prepare() {
|
||||
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
|
||||
|
@ -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 @@ VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int32_t dispId,
|
||||
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 @@ VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int32_t dispId,
|
||||
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 @@ status_t VirtualDisplaySurface::prepareFrame(CompositionType compositionType) {
|
||||
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 @@ status_t VirtualDisplaySurface::prepareFrame(CompositionType compositionType) {
|
||||
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 @@ status_t VirtualDisplaySurface::advanceFrame() {
|
||||
}
|
||||
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 @@ status_t VirtualDisplaySurface::advanceFrame() {
|
||||
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 @@ status_t VirtualDisplaySurface::advanceFrame() {
|
||||
// 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::setBufferCount(int bufferCount) {
|
||||
}
|
||||
|
||||
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 @@ status_t VirtualDisplaySurface::dequeueBuffer(Source source,
|
||||
}
|
||||
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 @@ status_t VirtualDisplaySurface::dequeueBuffer(int* pslot, sp<Fence>* fence, bool
|
||||
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 @@ status_t VirtualDisplaySurface::dequeueBuffer(int* pslot, sp<Fence>* fence, bool
|
||||
// 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 @@ status_t VirtualDisplaySurface::dequeueBuffer(int* pslot, sp<Fence>* fence, bool
|
||||
*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 @@ void VirtualDisplaySurface::resetPerFrameState() {
|
||||
mCompositionType = COMPOSITION_UNKNOWN;
|
||||
mSinkBufferWidth = 0;
|
||||
mSinkBufferHeight = 0;
|
||||
mFbFence = Fence::NO_FENCE;
|
||||
mOutputFence = Fence::NO_FENCE;
|
||||
mFbProducerSlot = -1;
|
||||
mOutputProducerSlot = -1;
|
||||
}
|
||||
|
||||
@ -414,7 +470,8 @@ status_t VirtualDisplaySurface::refreshOutputBuffer() {
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -110,7 +110,7 @@ private:
|
||||
// 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 @@ private:
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user