Merge changes Ic45929f3,Ic63f4f96,I1e703d36,I691f9507
* changes: make sure to reset the framenumber when a buffer is marked FREE Make ANW.setSwapInterval(0) work again BuffferQueue disconnect is now always asynchrnous BufferQueue improvements and APIs changes
This commit is contained in:
commit
bdce817047
@ -198,7 +198,7 @@ bool GLHelper::getShaderProgram(const char* name, GLuint* outPgm) {
|
|||||||
|
|
||||||
bool GLHelper::createNamedSurfaceTexture(GLuint name, uint32_t w, uint32_t h,
|
bool GLHelper::createNamedSurfaceTexture(GLuint name, uint32_t w, uint32_t h,
|
||||||
sp<GLConsumer>* glConsumer, EGLSurface* surface) {
|
sp<GLConsumer>* glConsumer, EGLSurface* surface) {
|
||||||
sp<BufferQueue> bq = new BufferQueue(true, mGraphicBufferAlloc);
|
sp<BufferQueue> bq = new BufferQueue(mGraphicBufferAlloc);
|
||||||
sp<GLConsumer> glc = new GLConsumer(bq, name,
|
sp<GLConsumer> glc = new GLConsumer(bq, name,
|
||||||
GL_TEXTURE_EXTERNAL_OES, false);
|
GL_TEXTURE_EXTERNAL_OES, false);
|
||||||
glc->setDefaultBufferSize(w, h);
|
glc->setDefaultBufferSize(w, h);
|
||||||
|
@ -51,9 +51,11 @@ class BufferItemConsumer: public ConsumerBase
|
|||||||
// the consumer usage flags passed to the graphics allocator. The
|
// the consumer usage flags passed to the graphics allocator. The
|
||||||
// bufferCount parameter specifies how many buffers can be locked for user
|
// bufferCount parameter specifies how many buffers can be locked for user
|
||||||
// access at the same time.
|
// access at the same time.
|
||||||
|
// controlledByApp tells whether this consumer is controlled by the
|
||||||
|
// application.
|
||||||
BufferItemConsumer(const sp<BufferQueue>& bq, uint32_t consumerUsage,
|
BufferItemConsumer(const sp<BufferQueue>& bq, uint32_t consumerUsage,
|
||||||
int bufferCount = BufferQueue::MIN_UNDEQUEUED_BUFFERS,
|
int bufferCount = BufferQueue::MIN_UNDEQUEUED_BUFFERS,
|
||||||
bool synchronousMode = false);
|
bool controlledByApp = false);
|
||||||
|
|
||||||
virtual ~BufferItemConsumer();
|
virtual ~BufferItemConsumer();
|
||||||
|
|
||||||
|
@ -97,11 +97,9 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
// BufferQueue manages a pool of gralloc memory slots to be used by
|
// BufferQueue manages a pool of gralloc memory slots to be used by
|
||||||
// producers and consumers. allowSynchronousMode specifies whether or not
|
// producers and consumers. allocator is used to allocate all the
|
||||||
// synchronous mode can be enabled by the producer. allocator is used to
|
// needed gralloc buffers.
|
||||||
// allocate all the needed gralloc buffers.
|
BufferQueue(const sp<IGraphicBufferAlloc>& allocator = NULL);
|
||||||
BufferQueue(bool allowSynchronousMode = true,
|
|
||||||
const sp<IGraphicBufferAlloc>& allocator = NULL);
|
|
||||||
virtual ~BufferQueue();
|
virtual ~BufferQueue();
|
||||||
|
|
||||||
// Query native window attributes. The "what" values are enumerated in
|
// Query native window attributes. The "what" values are enumerated in
|
||||||
@ -169,7 +167,7 @@ public:
|
|||||||
//
|
//
|
||||||
// In both cases, the producer will need to call requestBuffer to get a
|
// In both cases, the producer will need to call requestBuffer to get a
|
||||||
// GraphicBuffer handle for the returned slot.
|
// GraphicBuffer handle for the returned slot.
|
||||||
virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence,
|
virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence, bool async,
|
||||||
uint32_t width, uint32_t height, uint32_t format, uint32_t usage);
|
uint32_t width, uint32_t height, uint32_t format, uint32_t usage);
|
||||||
|
|
||||||
// queueBuffer returns a filled buffer to the BufferQueue.
|
// queueBuffer returns a filled buffer to the BufferQueue.
|
||||||
@ -197,15 +195,6 @@ public:
|
|||||||
// will usually be the one obtained from dequeueBuffer.
|
// will usually be the one obtained from dequeueBuffer.
|
||||||
virtual void cancelBuffer(int buf, const sp<Fence>& fence);
|
virtual void cancelBuffer(int buf, const sp<Fence>& fence);
|
||||||
|
|
||||||
// setSynchronousMode sets whether dequeueBuffer is synchronous or
|
|
||||||
// asynchronous. In synchronous mode, dequeueBuffer blocks until
|
|
||||||
// a buffer is available, the currently bound buffer can be dequeued and
|
|
||||||
// queued buffers will be acquired in order. In asynchronous mode,
|
|
||||||
// a queued buffer may be replaced by a subsequently queued buffer.
|
|
||||||
//
|
|
||||||
// The default mode is asynchronous.
|
|
||||||
virtual status_t setSynchronousMode(bool enabled);
|
|
||||||
|
|
||||||
// connect attempts to connect a producer API to the BufferQueue. This
|
// connect attempts to connect a producer API to the BufferQueue. This
|
||||||
// must be called before any other IGraphicBufferProducer methods are
|
// must be called before any other IGraphicBufferProducer methods are
|
||||||
// called except for getAllocator. A consumer must already be connected.
|
// called except for getAllocator. A consumer must already be connected.
|
||||||
@ -215,7 +204,7 @@ public:
|
|||||||
// it's still connected to a producer).
|
// it's still connected to a producer).
|
||||||
//
|
//
|
||||||
// APIs are enumerated in window.h (e.g. NATIVE_WINDOW_API_CPU).
|
// APIs are enumerated in window.h (e.g. NATIVE_WINDOW_API_CPU).
|
||||||
virtual status_t connect(int api, QueueBufferOutput* output);
|
virtual status_t connect(int api, bool producerControlledByApp, QueueBufferOutput* output);
|
||||||
|
|
||||||
// disconnect attempts to disconnect a producer API from the BufferQueue.
|
// disconnect attempts to disconnect a producer API from the BufferQueue.
|
||||||
// Calling this method will cause any subsequent calls to other
|
// Calling this method will cause any subsequent calls to other
|
||||||
@ -234,13 +223,13 @@ public:
|
|||||||
// public facing structure for BufferSlot
|
// public facing structure for BufferSlot
|
||||||
struct BufferItem {
|
struct BufferItem {
|
||||||
|
|
||||||
BufferItem()
|
BufferItem() :
|
||||||
:
|
|
||||||
mTransform(0),
|
mTransform(0),
|
||||||
mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
|
mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
|
||||||
mTimestamp(0),
|
mTimestamp(0),
|
||||||
mFrameNumber(0),
|
mFrameNumber(0),
|
||||||
mBuf(INVALID_BUFFER_SLOT),
|
mBuf(INVALID_BUFFER_SLOT),
|
||||||
|
mIsDroppable(false),
|
||||||
mAcquireCalled(false) {
|
mAcquireCalled(false) {
|
||||||
mCrop.makeInvalid();
|
mCrop.makeInvalid();
|
||||||
}
|
}
|
||||||
@ -271,6 +260,13 @@ public:
|
|||||||
// mFence is a fence that will signal when the buffer is idle.
|
// mFence is a fence that will signal when the buffer is idle.
|
||||||
sp<Fence> mFence;
|
sp<Fence> mFence;
|
||||||
|
|
||||||
|
// mIsDroppable whether this buffer was queued with the
|
||||||
|
// property that it can be replaced by a new buffer for the purpose of
|
||||||
|
// making sure dequeueBuffer() won't block.
|
||||||
|
// i.e.: was the BufferQueue in "mDequeueBufferCannotBlock" when this buffer
|
||||||
|
// was queued.
|
||||||
|
bool mIsDroppable;
|
||||||
|
|
||||||
// Indicates whether this buffer has been seen by a consumer yet
|
// Indicates whether this buffer has been seen by a consumer yet
|
||||||
bool mAcquireCalled;
|
bool mAcquireCalled;
|
||||||
};
|
};
|
||||||
@ -312,9 +308,11 @@ public:
|
|||||||
// consumer may be connected, and when that consumer disconnects the
|
// consumer may be connected, and when that consumer disconnects the
|
||||||
// BufferQueue is placed into the "abandoned" state, causing most
|
// BufferQueue is placed into the "abandoned" state, causing most
|
||||||
// interactions with the BufferQueue by the producer to fail.
|
// interactions with the BufferQueue by the producer to fail.
|
||||||
|
// controlledByApp indicates whether the consumer is controlled by
|
||||||
|
// the application.
|
||||||
//
|
//
|
||||||
// consumer may not be NULL.
|
// consumer may not be NULL.
|
||||||
status_t consumerConnect(const sp<ConsumerListener>& consumer);
|
status_t consumerConnect(const sp<ConsumerListener>& consumer, bool controlledByApp);
|
||||||
|
|
||||||
// consumerDisconnect disconnects a consumer from the BufferQueue. All
|
// consumerDisconnect disconnects a consumer from the BufferQueue. All
|
||||||
// buffers will be freed and the BufferQueue is placed in the "abandoned"
|
// buffers will be freed and the BufferQueue is placed in the "abandoned"
|
||||||
@ -347,10 +345,6 @@ public:
|
|||||||
// fail if a producer is connected to the BufferQueue.
|
// fail if a producer is connected to the BufferQueue.
|
||||||
status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers);
|
status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers);
|
||||||
|
|
||||||
// isSynchronousMode returns whether the BufferQueue is currently in
|
|
||||||
// synchronous mode.
|
|
||||||
bool isSynchronousMode() const;
|
|
||||||
|
|
||||||
// setConsumerName sets the name used in logging
|
// setConsumerName sets the name used in logging
|
||||||
void setConsumerName(const String8& name);
|
void setConsumerName(const String8& name);
|
||||||
|
|
||||||
@ -379,43 +373,35 @@ private:
|
|||||||
// all slots.
|
// all slots.
|
||||||
void freeAllBuffersLocked();
|
void freeAllBuffersLocked();
|
||||||
|
|
||||||
// drainQueueLocked waits for the buffer queue to empty if we're in
|
|
||||||
// synchronous mode, or returns immediately otherwise. It returns NO_INIT
|
|
||||||
// if the BufferQueue is abandoned (consumer disconnected) or disconnected
|
|
||||||
// (producer disconnected) during the call.
|
|
||||||
status_t drainQueueLocked();
|
|
||||||
|
|
||||||
// drainQueueAndFreeBuffersLocked drains the buffer queue if we're in
|
|
||||||
// synchronous mode and free all buffers. In asynchronous mode, all buffers
|
|
||||||
// are freed except the currently queued buffer (if it exists).
|
|
||||||
status_t drainQueueAndFreeBuffersLocked();
|
|
||||||
|
|
||||||
// setDefaultMaxBufferCountLocked sets the maximum number of buffer slots
|
// setDefaultMaxBufferCountLocked sets the maximum number of buffer slots
|
||||||
// that will be used if the producer does not override the buffer slot
|
// that will be used if the producer does not override the buffer slot
|
||||||
// count. The count must be between 2 and NUM_BUFFER_SLOTS, inclusive.
|
// count. The count must be between 2 and NUM_BUFFER_SLOTS, inclusive.
|
||||||
// The initial default is 2.
|
// The initial default is 2.
|
||||||
status_t setDefaultMaxBufferCountLocked(int count);
|
status_t setDefaultMaxBufferCountLocked(int count);
|
||||||
|
|
||||||
|
// getMinUndequeuedBufferCount returns the minimum number of buffers
|
||||||
|
// that must remain in a state other than DEQUEUED.
|
||||||
|
// The async parameter tells whether we're in asynchronous mode.
|
||||||
|
int getMinUndequeuedBufferCount(bool async) const;
|
||||||
|
|
||||||
// getMinBufferCountLocked returns the minimum number of buffers allowed
|
// getMinBufferCountLocked returns the minimum number of buffers allowed
|
||||||
// given the current BufferQueue state.
|
// given the current BufferQueue state.
|
||||||
int getMinMaxBufferCountLocked() const;
|
// The async parameter tells whether we're in asynchronous mode.
|
||||||
|
int getMinMaxBufferCountLocked(bool async) const;
|
||||||
// getMinUndequeuedBufferCountLocked returns the minimum number of buffers
|
|
||||||
// that must remain in a state other than DEQUEUED.
|
|
||||||
int getMinUndequeuedBufferCountLocked() const;
|
|
||||||
|
|
||||||
// getMaxBufferCountLocked returns the maximum number of buffers that can
|
// getMaxBufferCountLocked returns the maximum number of buffers that can
|
||||||
// be allocated at once. This value depends upon the following member
|
// be allocated at once. This value depends upon the following member
|
||||||
// variables:
|
// variables:
|
||||||
//
|
//
|
||||||
// mSynchronousMode
|
// mDequeueBufferCannotBlock
|
||||||
// mMaxAcquiredBufferCount
|
// mMaxAcquiredBufferCount
|
||||||
// mDefaultMaxBufferCount
|
// mDefaultMaxBufferCount
|
||||||
// mOverrideMaxBufferCount
|
// mOverrideMaxBufferCount
|
||||||
|
// async parameter
|
||||||
//
|
//
|
||||||
// Any time one of these member variables is changed while a producer is
|
// Any time one of these member variables is changed while a producer is
|
||||||
// connected, mDequeueCondition must be broadcast.
|
// connected, mDequeueCondition must be broadcast.
|
||||||
int getMaxBufferCountLocked() const;
|
int getMaxBufferCountLocked(bool async) const;
|
||||||
|
|
||||||
// stillTracking returns true iff the buffer item is still being tracked
|
// stillTracking returns true iff the buffer item is still being tracked
|
||||||
// in one of the slots.
|
// in one of the slots.
|
||||||
@ -568,12 +554,14 @@ private:
|
|||||||
// to NULL and is written by consumerConnect and consumerDisconnect.
|
// to NULL and is written by consumerConnect and consumerDisconnect.
|
||||||
sp<ConsumerListener> mConsumerListener;
|
sp<ConsumerListener> mConsumerListener;
|
||||||
|
|
||||||
// mSynchronousMode whether we're in synchronous mode or not
|
// mConsumerControlledByApp whether the connected consumer is controlled by the
|
||||||
bool mSynchronousMode;
|
// application.
|
||||||
|
bool mConsumerControlledByApp;
|
||||||
|
|
||||||
// mAllowSynchronousMode whether we allow synchronous mode or not. Set
|
// mDequeueBufferCannotBlock whether dequeueBuffer() isn't allowed to block.
|
||||||
// when the BufferQueue is created (by the consumer).
|
// this flag is set durring connect() when both consumer and producer are controlled
|
||||||
const bool mAllowSynchronousMode;
|
// by the application.
|
||||||
|
bool mDequeueBufferCannotBlock;
|
||||||
|
|
||||||
// mConnectedApi indicates the producer API that is currently connected
|
// mConnectedApi indicates the producer API that is currently connected
|
||||||
// to this BufferQueue. It defaults to NO_CONNECTED_API (= 0), and gets
|
// to this BufferQueue. It defaults to NO_CONNECTED_API (= 0), and gets
|
||||||
|
@ -87,7 +87,9 @@ protected:
|
|||||||
|
|
||||||
// ConsumerBase constructs a new ConsumerBase object to consume image
|
// ConsumerBase constructs a new ConsumerBase object to consume image
|
||||||
// buffers from the given BufferQueue.
|
// buffers from the given BufferQueue.
|
||||||
ConsumerBase(const sp<BufferQueue> &bufferQueue);
|
// The controlledByApp flag indicates that this consumer is under the application's
|
||||||
|
// control.
|
||||||
|
ConsumerBase(const sp<BufferQueue> &bufferQueue, bool controlledByApp = false);
|
||||||
|
|
||||||
// onLastStrongRef gets called by RefBase just before the dtor of the most
|
// onLastStrongRef gets called by RefBase just before the dtor of the most
|
||||||
// derived class. It is used to clean up the buffers so that ConsumerBase
|
// derived class. It is used to clean up the buffers so that ConsumerBase
|
||||||
|
@ -67,7 +67,7 @@ class CpuConsumer : public ConsumerBase
|
|||||||
// Create a new CPU consumer. The maxLockedBuffers parameter specifies
|
// Create a new CPU consumer. The maxLockedBuffers parameter specifies
|
||||||
// how many buffers can be locked for user access at the same time.
|
// how many buffers can be locked for user access at the same time.
|
||||||
CpuConsumer(const sp<BufferQueue>& bq,
|
CpuConsumer(const sp<BufferQueue>& bq,
|
||||||
uint32_t maxLockedBuffers, bool synchronousMode = true);
|
uint32_t maxLockedBuffers, bool controlledByApp = false);
|
||||||
|
|
||||||
virtual ~CpuConsumer();
|
virtual ~CpuConsumer();
|
||||||
|
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2012 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_GUI_DUMMYCONSUMER_H
|
|
||||||
#define ANDROID_GUI_DUMMYCONSUMER_H
|
|
||||||
|
|
||||||
#include <gui/BufferQueue.h>
|
|
||||||
|
|
||||||
namespace android {
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
// The DummyConsumer does not keep a reference to BufferQueue
|
|
||||||
// unlike GLConsumer. This prevents a circular reference from
|
|
||||||
// forming without having to use a ProxyConsumerListener
|
|
||||||
class DummyConsumer : public BufferQueue::ConsumerListener {
|
|
||||||
public:
|
|
||||||
DummyConsumer();
|
|
||||||
virtual ~DummyConsumer();
|
|
||||||
protected:
|
|
||||||
|
|
||||||
// Implementation of the BufferQueue::ConsumerListener interface. These
|
|
||||||
// calls are used to notify the GLConsumer of asynchronous events in the
|
|
||||||
// BufferQueue.
|
|
||||||
virtual void onFrameAvailable();
|
|
||||||
virtual void onBuffersReleased();
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
}; // namespace android
|
|
||||||
|
|
||||||
#endif // ANDROID_GUI_DUMMYCONSUMER_H
|
|
@ -87,7 +87,7 @@ public:
|
|||||||
// requirement that either of these methods be called.
|
// requirement that either of these methods be called.
|
||||||
GLConsumer(const sp<BufferQueue>& bq,
|
GLConsumer(const sp<BufferQueue>& bq,
|
||||||
GLuint tex, GLenum texTarget = GL_TEXTURE_EXTERNAL_OES,
|
GLuint tex, GLenum texTarget = GL_TEXTURE_EXTERNAL_OES,
|
||||||
bool useFenceSync = true);
|
bool useFenceSync = true, bool isControlledByApp = false);
|
||||||
|
|
||||||
// updateTexImage acquires the most recently queued buffer, and sets the
|
// updateTexImage acquires the most recently queued buffer, and sets the
|
||||||
// image contents of the target texture to it.
|
// image contents of the target texture to it.
|
||||||
@ -177,10 +177,6 @@ public:
|
|||||||
// current texture buffer.
|
// current texture buffer.
|
||||||
status_t doGLFenceWait() const;
|
status_t doGLFenceWait() const;
|
||||||
|
|
||||||
// isSynchronousMode returns whether the GLConsumer is currently in
|
|
||||||
// synchronous mode.
|
|
||||||
bool isSynchronousMode() const;
|
|
||||||
|
|
||||||
// set the name of the GLConsumer that will be used to identify it in
|
// set the name of the GLConsumer that will be used to identify it in
|
||||||
// log messages.
|
// log messages.
|
||||||
void setName(const String8& name);
|
void setName(const String8& name);
|
||||||
@ -190,7 +186,6 @@ public:
|
|||||||
status_t setDefaultBufferFormat(uint32_t defaultFormat);
|
status_t setDefaultBufferFormat(uint32_t defaultFormat);
|
||||||
status_t setConsumerUsageBits(uint32_t usage);
|
status_t setConsumerUsageBits(uint32_t usage);
|
||||||
status_t setTransformHint(uint32_t hint);
|
status_t setTransformHint(uint32_t hint);
|
||||||
virtual status_t setSynchronousMode(bool enabled);
|
|
||||||
|
|
||||||
// getBufferQueue returns the BufferQueue object to which this
|
// getBufferQueue returns the BufferQueue object to which this
|
||||||
// GLConsumer is connected.
|
// GLConsumer is connected.
|
||||||
|
@ -84,7 +84,10 @@ public:
|
|||||||
// the buffer. The contents of the buffer must not be overwritten until the
|
// the buffer. The contents of the buffer must not be overwritten until the
|
||||||
// fence signals. If the fence is NULL, the buffer may be written
|
// fence signals. If the fence is NULL, the buffer may be written
|
||||||
// immediately.
|
// immediately.
|
||||||
virtual status_t dequeueBuffer(int *slot, sp<Fence>* fence,
|
//
|
||||||
|
// The async parameter sets whether we're in asynchrnous mode for this
|
||||||
|
// deququeBuffer() call.
|
||||||
|
virtual status_t dequeueBuffer(int *slot, sp<Fence>* fence, bool async,
|
||||||
uint32_t w, uint32_t h, uint32_t format, uint32_t usage) = 0;
|
uint32_t w, uint32_t h, uint32_t format, uint32_t usage) = 0;
|
||||||
|
|
||||||
// queueBuffer indicates that the client has finished filling in the
|
// queueBuffer indicates that the client has finished filling in the
|
||||||
@ -96,6 +99,8 @@ public:
|
|||||||
// must be monotonically increasing. Its other properties (zero point, etc)
|
// must be monotonically increasing. Its other properties (zero point, etc)
|
||||||
// are client-dependent, and should be documented by the client.
|
// are client-dependent, and should be documented by the client.
|
||||||
//
|
//
|
||||||
|
// The async parameter sets whether we're queuing a buffer in asynchronous mode.
|
||||||
|
//
|
||||||
// outWidth, outHeight and outTransform are filled with the default width
|
// outWidth, outHeight and outTransform are filled with the default width
|
||||||
// and height of the window and current transform applied to buffers,
|
// and height of the window and current transform applied to buffers,
|
||||||
// respectively.
|
// respectively.
|
||||||
@ -103,17 +108,18 @@ public:
|
|||||||
struct QueueBufferInput : public Flattenable {
|
struct QueueBufferInput : public Flattenable {
|
||||||
inline QueueBufferInput(const Parcel& parcel);
|
inline QueueBufferInput(const Parcel& parcel);
|
||||||
inline QueueBufferInput(int64_t timestamp,
|
inline QueueBufferInput(int64_t timestamp,
|
||||||
const Rect& crop, int scalingMode, uint32_t transform,
|
const Rect& crop, int scalingMode, uint32_t transform, bool async,
|
||||||
sp<Fence> fence)
|
const sp<Fence>& fence)
|
||||||
: timestamp(timestamp), crop(crop), scalingMode(scalingMode),
|
: timestamp(timestamp), crop(crop), scalingMode(scalingMode),
|
||||||
transform(transform), fence(fence) { }
|
transform(transform), async(async), fence(fence) { }
|
||||||
inline void deflate(int64_t* outTimestamp, Rect* outCrop,
|
inline void deflate(int64_t* outTimestamp, Rect* outCrop,
|
||||||
int* outScalingMode, uint32_t* outTransform,
|
int* outScalingMode, uint32_t* outTransform, bool* outAsync,
|
||||||
sp<Fence>* outFence) const {
|
sp<Fence>* outFence) const {
|
||||||
*outTimestamp = timestamp;
|
*outTimestamp = timestamp;
|
||||||
*outCrop = crop;
|
*outCrop = crop;
|
||||||
*outScalingMode = scalingMode;
|
*outScalingMode = scalingMode;
|
||||||
*outTransform = transform;
|
*outTransform = transform;
|
||||||
|
*outAsync = bool(async);
|
||||||
*outFence = fence;
|
*outFence = fence;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,6 +136,7 @@ public:
|
|||||||
Rect crop;
|
Rect crop;
|
||||||
int scalingMode;
|
int scalingMode;
|
||||||
uint32_t transform;
|
uint32_t transform;
|
||||||
|
int async;
|
||||||
sp<Fence> fence;
|
sp<Fence> fence;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -171,13 +178,6 @@ public:
|
|||||||
// 'what' tokens allowed are that of android_natives.h
|
// 'what' tokens allowed are that of android_natives.h
|
||||||
virtual int query(int what, int* value) = 0;
|
virtual int query(int what, int* value) = 0;
|
||||||
|
|
||||||
// setSynchronousMode set whether dequeueBuffer is synchronous or
|
|
||||||
// asynchronous. In synchronous mode, dequeueBuffer blocks until
|
|
||||||
// a buffer is available, the currently bound buffer can be dequeued and
|
|
||||||
// queued buffers will be retired in order.
|
|
||||||
// The default mode is asynchronous.
|
|
||||||
virtual status_t setSynchronousMode(bool enabled) = 0;
|
|
||||||
|
|
||||||
// connect attempts to connect a client API to the IGraphicBufferProducer.
|
// connect attempts to connect a client API to the IGraphicBufferProducer.
|
||||||
// This must be called before any other IGraphicBufferProducer methods are
|
// This must be called before any other IGraphicBufferProducer methods are
|
||||||
// called except for getAllocator.
|
// called except for getAllocator.
|
||||||
@ -188,7 +188,7 @@ public:
|
|||||||
// outWidth, outHeight and outTransform are filled with the default width
|
// outWidth, outHeight and outTransform are filled with the default width
|
||||||
// and height of the window and current transform applied to buffers,
|
// and height of the window and current transform applied to buffers,
|
||||||
// respectively.
|
// respectively.
|
||||||
virtual status_t connect(int api, QueueBufferOutput* output) = 0;
|
virtual status_t connect(int api, bool producerControlledByApp, QueueBufferOutput* output) = 0;
|
||||||
|
|
||||||
// disconnect attempts to disconnect a client API from the
|
// disconnect attempts to disconnect a client API from the
|
||||||
// IGraphicBufferProducer. Calling this method will cause any subsequent
|
// IGraphicBufferProducer. Calling this method will cause any subsequent
|
||||||
|
@ -61,8 +61,11 @@ public:
|
|||||||
* However, once a Surface is connected, it'll prevent other Surfaces
|
* However, once a Surface is connected, it'll prevent other Surfaces
|
||||||
* referring to the same IGraphicBufferProducer to become connected and
|
* referring to the same IGraphicBufferProducer to become connected and
|
||||||
* therefore prevent them to be used as actual producers of buffers.
|
* therefore prevent them to be used as actual producers of buffers.
|
||||||
|
*
|
||||||
|
* the controlledByApp flag indicates that this Surface (producer) is
|
||||||
|
* controlled by the application. This flag is used at connect time.
|
||||||
*/
|
*/
|
||||||
Surface(const sp<IGraphicBufferProducer>& bufferProducer);
|
Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controlledByApp = false);
|
||||||
|
|
||||||
/* getIGraphicBufferProducer() returns the IGraphicBufferProducer this
|
/* getIGraphicBufferProducer() returns the IGraphicBufferProducer this
|
||||||
* Surface was created with. Usually it's an error to use the
|
* Surface was created with. Usually it's an error to use the
|
||||||
@ -228,6 +231,14 @@ private:
|
|||||||
// window. this is only a hint, actual transform may differ.
|
// window. this is only a hint, actual transform may differ.
|
||||||
uint32_t mTransformHint;
|
uint32_t mTransformHint;
|
||||||
|
|
||||||
|
// mProducerControlledByApp whether this buffer producer is controlled
|
||||||
|
// by the application
|
||||||
|
bool mProducerControlledByApp;
|
||||||
|
|
||||||
|
// mSwapIntervalZero set if we should drop buffers at queue() time to
|
||||||
|
// achieve an asynchronous swap interval
|
||||||
|
bool mSwapIntervalZero;
|
||||||
|
|
||||||
// mConsumerRunningBehind whether the consumer is running more than
|
// mConsumerRunningBehind whether the consumer is running more than
|
||||||
// one buffer behind the producer.
|
// one buffer behind the producer.
|
||||||
mutable bool mConsumerRunningBehind;
|
mutable bool mConsumerRunningBehind;
|
||||||
|
@ -8,7 +8,6 @@ LOCAL_SRC_FILES:= \
|
|||||||
ConsumerBase.cpp \
|
ConsumerBase.cpp \
|
||||||
CpuConsumer.cpp \
|
CpuConsumer.cpp \
|
||||||
DisplayEventReceiver.cpp \
|
DisplayEventReceiver.cpp \
|
||||||
DummyConsumer.cpp \
|
|
||||||
GLConsumer.cpp \
|
GLConsumer.cpp \
|
||||||
GraphicBufferAlloc.cpp \
|
GraphicBufferAlloc.cpp \
|
||||||
GuiConfig.cpp \
|
GuiConfig.cpp \
|
||||||
|
@ -30,11 +30,10 @@
|
|||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
BufferItemConsumer::BufferItemConsumer(const sp<BufferQueue>& bq,
|
BufferItemConsumer::BufferItemConsumer(const sp<BufferQueue>& bq,
|
||||||
uint32_t consumerUsage, int bufferCount, bool synchronousMode) :
|
uint32_t consumerUsage, int bufferCount, bool controlledByApp) :
|
||||||
ConsumerBase(bq)
|
ConsumerBase(bq, controlledByApp)
|
||||||
{
|
{
|
||||||
mBufferQueue->setConsumerUsageBits(consumerUsage);
|
mBufferQueue->setConsumerUsageBits(consumerUsage);
|
||||||
mBufferQueue->setSynchronousMode(synchronousMode);
|
|
||||||
mBufferQueue->setMaxAcquiredBufferCount(bufferCount);
|
mBufferQueue->setMaxAcquiredBufferCount(bufferCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
|
|
||||||
#include <utils/Log.h>
|
#include <utils/Log.h>
|
||||||
#include <utils/Trace.h>
|
#include <utils/Trace.h>
|
||||||
|
#include <utils/CallStack.h>
|
||||||
|
|
||||||
// Macros for including the BufferQueue name in log messages
|
// Macros for including the BufferQueue name in log messages
|
||||||
#define ST_LOGV(x, ...) ALOGV("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
|
#define ST_LOGV(x, ...) ALOGV("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
|
||||||
@ -63,15 +64,14 @@ static const char* scalingModeName(int scalingMode) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferQueue::BufferQueue(bool allowSynchronousMode,
|
BufferQueue::BufferQueue(const sp<IGraphicBufferAlloc>& allocator) :
|
||||||
const sp<IGraphicBufferAlloc>& allocator) :
|
|
||||||
mDefaultWidth(1),
|
mDefaultWidth(1),
|
||||||
mDefaultHeight(1),
|
mDefaultHeight(1),
|
||||||
mMaxAcquiredBufferCount(1),
|
mMaxAcquiredBufferCount(1),
|
||||||
mDefaultMaxBufferCount(2),
|
mDefaultMaxBufferCount(2),
|
||||||
mOverrideMaxBufferCount(0),
|
mOverrideMaxBufferCount(0),
|
||||||
mSynchronousMode(false),
|
mConsumerControlledByApp(false),
|
||||||
mAllowSynchronousMode(allowSynchronousMode),
|
mDequeueBufferCannotBlock(false),
|
||||||
mConnectedApi(NO_CONNECTED_API),
|
mConnectedApi(NO_CONNECTED_API),
|
||||||
mAbandoned(false),
|
mAbandoned(false),
|
||||||
mFrameCounter(0),
|
mFrameCounter(0),
|
||||||
@ -109,11 +109,6 @@ status_t BufferQueue::setDefaultMaxBufferCountLocked(int count) {
|
|||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BufferQueue::isSynchronousMode() const {
|
|
||||||
Mutex::Autolock lock(mMutex);
|
|
||||||
return mSynchronousMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BufferQueue::setConsumerName(const String8& name) {
|
void BufferQueue::setConsumerName(const String8& name) {
|
||||||
Mutex::Autolock lock(mMutex);
|
Mutex::Autolock lock(mMutex);
|
||||||
mConsumerName = name;
|
mConsumerName = name;
|
||||||
@ -156,21 +151,21 @@ status_t BufferQueue::setBufferCount(int bufferCount) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Error out if the user has dequeued buffers
|
// Error out if the user has dequeued buffers
|
||||||
int maxBufferCount = getMaxBufferCountLocked();
|
for (int i=0 ; i<NUM_BUFFER_SLOTS; i++) {
|
||||||
for (int i=0 ; i<maxBufferCount; i++) {
|
|
||||||
if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) {
|
if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) {
|
||||||
ST_LOGE("setBufferCount: client owns some buffers");
|
ST_LOGE("setBufferCount: client owns some buffers");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const int minBufferSlots = getMinMaxBufferCountLocked();
|
|
||||||
if (bufferCount == 0) {
|
if (bufferCount == 0) {
|
||||||
mOverrideMaxBufferCount = 0;
|
mOverrideMaxBufferCount = 0;
|
||||||
mDequeueCondition.broadcast();
|
mDequeueCondition.broadcast();
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fine to assume async to false before we're setting the buffer count
|
||||||
|
const int minBufferSlots = getMinMaxBufferCountLocked(false);
|
||||||
if (bufferCount < minBufferSlots) {
|
if (bufferCount < minBufferSlots) {
|
||||||
ST_LOGE("setBufferCount: requested buffer count (%d) is less than "
|
ST_LOGE("setBufferCount: requested buffer count (%d) is less than "
|
||||||
"minimum (%d)", bufferCount, minBufferSlots);
|
"minimum (%d)", bufferCount, minBufferSlots);
|
||||||
@ -215,7 +210,7 @@ int BufferQueue::query(int what, int* outValue)
|
|||||||
value = mDefaultBufferFormat;
|
value = mDefaultBufferFormat;
|
||||||
break;
|
break;
|
||||||
case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
|
case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
|
||||||
value = getMinUndequeuedBufferCountLocked();
|
value = getMinUndequeuedBufferCount(false);
|
||||||
break;
|
break;
|
||||||
case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
|
case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
|
||||||
value = (mQueue.size() >= 2);
|
value = (mQueue.size() >= 2);
|
||||||
@ -235,15 +230,11 @@ status_t BufferQueue::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
|
|||||||
ST_LOGE("requestBuffer: BufferQueue has been abandoned!");
|
ST_LOGE("requestBuffer: BufferQueue has been abandoned!");
|
||||||
return NO_INIT;
|
return NO_INIT;
|
||||||
}
|
}
|
||||||
int maxBufferCount = getMaxBufferCountLocked();
|
if (slot < 0 || slot >= NUM_BUFFER_SLOTS) {
|
||||||
if (slot < 0 || maxBufferCount <= slot) {
|
|
||||||
ST_LOGE("requestBuffer: slot index out of range [0, %d]: %d",
|
ST_LOGE("requestBuffer: slot index out of range [0, %d]: %d",
|
||||||
maxBufferCount, slot);
|
NUM_BUFFER_SLOTS, slot);
|
||||||
return BAD_VALUE;
|
return BAD_VALUE;
|
||||||
} else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
|
} else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
|
||||||
// XXX: I vaguely recall there was some reason this can be valid, but
|
|
||||||
// for the life of me I can't recall under what circumstances that's
|
|
||||||
// the case.
|
|
||||||
ST_LOGE("requestBuffer: slot %d is not owned by the client (state=%d)",
|
ST_LOGE("requestBuffer: slot %d is not owned by the client (state=%d)",
|
||||||
slot, mSlots[slot].mBufferState);
|
slot, mSlots[slot].mBufferState);
|
||||||
return BAD_VALUE;
|
return BAD_VALUE;
|
||||||
@ -253,7 +244,7 @@ status_t BufferQueue::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
|
|||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence,
|
status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence, bool async,
|
||||||
uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
|
uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
|
||||||
ATRACE_CALL();
|
ATRACE_CALL();
|
||||||
ST_LOGV("dequeueBuffer: w=%d h=%d fmt=%#x usage=%#x", w, h, format, usage);
|
ST_LOGV("dequeueBuffer: w=%d h=%d fmt=%#x usage=%#x", w, h, format, usage);
|
||||||
@ -285,7 +276,16 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence,
|
|||||||
return NO_INIT;
|
return NO_INIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int maxBufferCount = getMaxBufferCountLocked();
|
const int maxBufferCount = getMaxBufferCountLocked(async);
|
||||||
|
if (async && mOverrideMaxBufferCount) {
|
||||||
|
// FIXME: some drivers are manually setting the buffer-count (which they
|
||||||
|
// shouldn't), so we do this extra test here to handle that case.
|
||||||
|
// This is TEMPORARY, until we get this fixed.
|
||||||
|
if (mOverrideMaxBufferCount < maxBufferCount) {
|
||||||
|
ST_LOGE("dequeueBuffer: async mode is invalid with buffercount override");
|
||||||
|
return BAD_VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Free up any buffers that are in slots beyond the max buffer
|
// Free up any buffers that are in slots beyond the max buffer
|
||||||
// count.
|
// count.
|
||||||
@ -334,7 +334,7 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence,
|
|||||||
// make sure the client is not trying to dequeue more buffers
|
// make sure the client is not trying to dequeue more buffers
|
||||||
// than allowed.
|
// than allowed.
|
||||||
const int newUndequeuedCount = maxBufferCount - (dequeuedCount+1);
|
const int newUndequeuedCount = maxBufferCount - (dequeuedCount+1);
|
||||||
const int minUndequeuedCount = getMinUndequeuedBufferCountLocked();
|
const int minUndequeuedCount = getMinUndequeuedBufferCount(async);
|
||||||
if (newUndequeuedCount < minUndequeuedCount) {
|
if (newUndequeuedCount < minUndequeuedCount) {
|
||||||
ST_LOGE("dequeueBuffer: min undequeued buffer count (%d) "
|
ST_LOGE("dequeueBuffer: min undequeued buffer count (%d) "
|
||||||
"exceeded (dequeued=%d undequeudCount=%d)",
|
"exceeded (dequeued=%d undequeudCount=%d)",
|
||||||
@ -348,6 +348,10 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence,
|
|||||||
// the max buffer count to change.
|
// the max buffer count to change.
|
||||||
tryAgain = found == INVALID_BUFFER_SLOT;
|
tryAgain = found == INVALID_BUFFER_SLOT;
|
||||||
if (tryAgain) {
|
if (tryAgain) {
|
||||||
|
if (mDequeueBufferCannotBlock) {
|
||||||
|
ST_LOGE("dequeueBuffer: would block! returning an error instead.");
|
||||||
|
return WOULD_BLOCK;
|
||||||
|
}
|
||||||
mDequeueCondition.wait(mMutex);
|
mDequeueCondition.wait(mMutex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -441,38 +445,6 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence,
|
|||||||
return returnFlags;
|
return returnFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t BufferQueue::setSynchronousMode(bool enabled) {
|
|
||||||
ATRACE_CALL();
|
|
||||||
ST_LOGV("setSynchronousMode: enabled=%d", enabled);
|
|
||||||
Mutex::Autolock lock(mMutex);
|
|
||||||
|
|
||||||
if (mAbandoned) {
|
|
||||||
ST_LOGE("setSynchronousMode: BufferQueue has been abandoned!");
|
|
||||||
return NO_INIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t err = OK;
|
|
||||||
if (!mAllowSynchronousMode && enabled)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
if (!enabled) {
|
|
||||||
// going to asynchronous mode, drain the queue
|
|
||||||
err = drainQueueLocked();
|
|
||||||
if (err != NO_ERROR)
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mSynchronousMode != enabled) {
|
|
||||||
// - if we're going to asynchronous mode, the queue is guaranteed to be
|
|
||||||
// empty here
|
|
||||||
// - if the client set the number of buffers, we're guaranteed that
|
|
||||||
// we have at least 3 (because we don't allow less)
|
|
||||||
mSynchronousMode = enabled;
|
|
||||||
mDequeueCondition.broadcast();
|
|
||||||
}
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t BufferQueue::queueBuffer(int buf,
|
status_t BufferQueue::queueBuffer(int buf,
|
||||||
const QueueBufferInput& input, QueueBufferOutput* output) {
|
const QueueBufferInput& input, QueueBufferOutput* output) {
|
||||||
ATRACE_CALL();
|
ATRACE_CALL();
|
||||||
@ -482,9 +454,10 @@ status_t BufferQueue::queueBuffer(int buf,
|
|||||||
uint32_t transform;
|
uint32_t transform;
|
||||||
int scalingMode;
|
int scalingMode;
|
||||||
int64_t timestamp;
|
int64_t timestamp;
|
||||||
|
bool async;
|
||||||
sp<Fence> fence;
|
sp<Fence> fence;
|
||||||
|
|
||||||
input.deflate(×tamp, &crop, &scalingMode, &transform, &fence);
|
input.deflate(×tamp, &crop, &scalingMode, &transform, &async, &fence);
|
||||||
|
|
||||||
if (fence == NULL) {
|
if (fence == NULL) {
|
||||||
ST_LOGE("queueBuffer: fence is NULL");
|
ST_LOGE("queueBuffer: fence is NULL");
|
||||||
@ -511,7 +484,17 @@ status_t BufferQueue::queueBuffer(int buf,
|
|||||||
ST_LOGE("queueBuffer: BufferQueue has been abandoned!");
|
ST_LOGE("queueBuffer: BufferQueue has been abandoned!");
|
||||||
return NO_INIT;
|
return NO_INIT;
|
||||||
}
|
}
|
||||||
int maxBufferCount = getMaxBufferCountLocked();
|
|
||||||
|
const int maxBufferCount = getMaxBufferCountLocked(async);
|
||||||
|
if (async && mOverrideMaxBufferCount) {
|
||||||
|
// FIXME: some drivers are manually setting the buffer-count (which they
|
||||||
|
// shouldn't), so we do this extra test here to handle that case.
|
||||||
|
// This is TEMPORARY, until we get this fixed.
|
||||||
|
if (mOverrideMaxBufferCount < maxBufferCount) {
|
||||||
|
ST_LOGE("queueBuffer: async mode is invalid with buffercount override");
|
||||||
|
return BAD_VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (buf < 0 || buf >= maxBufferCount) {
|
if (buf < 0 || buf >= maxBufferCount) {
|
||||||
ST_LOGE("queueBuffer: slot index out of range [0, %d]: %d",
|
ST_LOGE("queueBuffer: slot index out of range [0, %d]: %d",
|
||||||
maxBufferCount, buf);
|
maxBufferCount, buf);
|
||||||
@ -557,31 +540,30 @@ status_t BufferQueue::queueBuffer(int buf,
|
|||||||
item.mFrameNumber = mFrameCounter;
|
item.mFrameNumber = mFrameCounter;
|
||||||
item.mBuf = buf;
|
item.mBuf = buf;
|
||||||
item.mFence = fence;
|
item.mFence = fence;
|
||||||
|
item.mIsDroppable = mDequeueBufferCannotBlock || async;
|
||||||
|
|
||||||
if (mSynchronousMode) {
|
if (mQueue.empty()) {
|
||||||
// In synchronous mode we queue all buffers in a FIFO.
|
// when the queue is empty, we can ignore "mDequeueBufferCannotBlock", and
|
||||||
|
// simply queue this buffer.
|
||||||
mQueue.push_back(item);
|
mQueue.push_back(item);
|
||||||
|
|
||||||
// Synchronous mode always signals that an additional frame should
|
|
||||||
// be consumed.
|
|
||||||
listener = mConsumerListener;
|
listener = mConsumerListener;
|
||||||
} else {
|
} else {
|
||||||
// In asynchronous mode we only keep the most recent buffer.
|
// when the queue is not empty, we need to look at the front buffer
|
||||||
if (mQueue.empty()) {
|
// state and see if we need to replace it.
|
||||||
mQueue.push_back(item);
|
Fifo::iterator front(mQueue.begin());
|
||||||
|
if (front->mIsDroppable) {
|
||||||
// Asynchronous mode only signals that a frame should be
|
|
||||||
// consumed if no previous frame was pending. If a frame were
|
|
||||||
// pending then the consumer would have already been notified.
|
|
||||||
listener = mConsumerListener;
|
|
||||||
} else {
|
|
||||||
Fifo::iterator front(mQueue.begin());
|
|
||||||
// buffer slot currently queued is marked free if still tracked
|
// buffer slot currently queued is marked free if still tracked
|
||||||
if (stillTracking(front)) {
|
if (stillTracking(front)) {
|
||||||
mSlots[front->mBuf].mBufferState = BufferSlot::FREE;
|
mSlots[front->mBuf].mBufferState = BufferSlot::FREE;
|
||||||
|
// reset the frame number of the freed buffer so that it is the first in
|
||||||
|
// line to be dequeued again.
|
||||||
|
mSlots[front->mBuf].mFrameNumber = 0;
|
||||||
}
|
}
|
||||||
// and we record the new buffer index in the queued list
|
// and we record the new buffer in the queued list
|
||||||
*front = item;
|
*front = item;
|
||||||
|
} else {
|
||||||
|
mQueue.push_back(item);
|
||||||
|
listener = mConsumerListener;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -611,10 +593,9 @@ void BufferQueue::cancelBuffer(int buf, const sp<Fence>& fence) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int maxBufferCount = getMaxBufferCountLocked();
|
if (buf < 0 || buf >= NUM_BUFFER_SLOTS) {
|
||||||
if (buf < 0 || buf >= maxBufferCount) {
|
|
||||||
ST_LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
|
ST_LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
|
||||||
maxBufferCount, buf);
|
NUM_BUFFER_SLOTS, buf);
|
||||||
return;
|
return;
|
||||||
} else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
|
} else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
|
||||||
ST_LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
|
ST_LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
|
||||||
@ -630,7 +611,7 @@ void BufferQueue::cancelBuffer(int buf, const sp<Fence>& fence) {
|
|||||||
mDequeueCondition.broadcast();
|
mDequeueCondition.broadcast();
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t BufferQueue::connect(int api, QueueBufferOutput* output) {
|
status_t BufferQueue::connect(int api, bool producerControlledByApp, QueueBufferOutput* output) {
|
||||||
ATRACE_CALL();
|
ATRACE_CALL();
|
||||||
ST_LOGV("connect: api=%d", api);
|
ST_LOGV("connect: api=%d", api);
|
||||||
Mutex::Autolock lock(mMutex);
|
Mutex::Autolock lock(mMutex);
|
||||||
@ -667,6 +648,7 @@ status_t BufferQueue::connect(int api, QueueBufferOutput* output) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mBufferHasBeenQueued = false;
|
mBufferHasBeenQueued = false;
|
||||||
|
mDequeueBufferCannotBlock = mConsumerControlledByApp && producerControlledByApp;
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -693,7 +675,7 @@ status_t BufferQueue::disconnect(int api) {
|
|||||||
case NATIVE_WINDOW_API_MEDIA:
|
case NATIVE_WINDOW_API_MEDIA:
|
||||||
case NATIVE_WINDOW_API_CAMERA:
|
case NATIVE_WINDOW_API_CAMERA:
|
||||||
if (mConnectedApi == api) {
|
if (mConnectedApi == api) {
|
||||||
drainQueueAndFreeBuffersLocked();
|
freeAllBuffersLocked();
|
||||||
mConnectedApi = NO_CONNECTED_API;
|
mConnectedApi = NO_CONNECTED_API;
|
||||||
mDequeueCondition.broadcast();
|
mDequeueCondition.broadcast();
|
||||||
listener = mConsumerListener;
|
listener = mConsumerListener;
|
||||||
@ -739,12 +721,11 @@ void BufferQueue::dump(String8& result, const char* prefix) const {
|
|||||||
fifoSize++;
|
fifoSize++;
|
||||||
}
|
}
|
||||||
|
|
||||||
int maxBufferCount = getMaxBufferCountLocked();
|
|
||||||
|
|
||||||
result.appendFormat(
|
result.appendFormat(
|
||||||
"%s-BufferQueue maxBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], "
|
"%s-BufferQueue mMaxAcquiredBufferCount=%d, mDequeueBufferCannotBlock=%d, default-size=[%dx%d], "
|
||||||
"default-format=%d, transform-hint=%02x, FIFO(%d)={%s}\n",
|
"default-format=%d, transform-hint=%02x, FIFO(%d)={%s}\n",
|
||||||
prefix, maxBufferCount, mSynchronousMode, mDefaultWidth,
|
prefix, mMaxAcquiredBufferCount, mDequeueBufferCannotBlock, mDefaultWidth,
|
||||||
mDefaultHeight, mDefaultBufferFormat, mTransformHint,
|
mDefaultHeight, mDefaultBufferFormat, mTransformHint,
|
||||||
fifoSize, fifo.string());
|
fifoSize, fifo.string());
|
||||||
|
|
||||||
@ -760,16 +741,25 @@ void BufferQueue::dump(String8& result, const char* prefix) const {
|
|||||||
}
|
}
|
||||||
} stateName;
|
} stateName;
|
||||||
|
|
||||||
|
// just trim the free buffers to not spam the dump
|
||||||
|
int maxBufferCount = 0;
|
||||||
|
for (int i=NUM_BUFFER_SLOTS-1 ; i>=0 ; i--) {
|
||||||
|
const BufferSlot& slot(mSlots[i]);
|
||||||
|
if ((slot.mBufferState != BufferSlot::FREE) || (slot.mGraphicBuffer != NULL)) {
|
||||||
|
maxBufferCount = i+1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (int i=0 ; i<maxBufferCount ; i++) {
|
for (int i=0 ; i<maxBufferCount ; i++) {
|
||||||
const BufferSlot& slot(mSlots[i]);
|
const BufferSlot& slot(mSlots[i]);
|
||||||
|
const sp<GraphicBuffer>& buf(slot.mGraphicBuffer);
|
||||||
result.appendFormat(
|
result.appendFormat(
|
||||||
"%s%s[%02d:%p] state=%-8s",
|
"%s%s[%02d:%p] state=%-8s",
|
||||||
prefix, (slot.mBufferState == BufferSlot::ACQUIRED)?">":" ", i,
|
prefix, (slot.mBufferState == BufferSlot::ACQUIRED)?">":" ", i, buf.get(),
|
||||||
slot.mGraphicBuffer.get(),
|
|
||||||
stateName(slot.mBufferState)
|
stateName(slot.mBufferState)
|
||||||
);
|
);
|
||||||
|
|
||||||
const sp<GraphicBuffer>& buf(slot.mGraphicBuffer);
|
|
||||||
if (buf != NULL) {
|
if (buf != NULL) {
|
||||||
result.appendFormat(
|
result.appendFormat(
|
||||||
", %p [%4ux%4u:%4u,%3X]",
|
", %p [%4ux%4u:%4u,%3X]",
|
||||||
@ -799,8 +789,6 @@ void BufferQueue::freeBufferLocked(int slot) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BufferQueue::freeAllBuffersLocked() {
|
void BufferQueue::freeAllBuffersLocked() {
|
||||||
ALOGD_IF(!mQueue.isEmpty(),
|
|
||||||
"freeAllBuffersLocked called with non-empty mQueue");
|
|
||||||
mBufferHasBeenQueued = false;
|
mBufferHasBeenQueued = false;
|
||||||
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
|
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
|
||||||
freeBufferLocked(i);
|
freeBufferLocked(i);
|
||||||
@ -950,7 +938,8 @@ status_t BufferQueue::releaseBuffer(
|
|||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t BufferQueue::consumerConnect(const sp<ConsumerListener>& consumerListener) {
|
status_t BufferQueue::consumerConnect(const sp<ConsumerListener>& consumerListener,
|
||||||
|
bool controlledByApp) {
|
||||||
ST_LOGV("consumerConnect");
|
ST_LOGV("consumerConnect");
|
||||||
Mutex::Autolock lock(mMutex);
|
Mutex::Autolock lock(mMutex);
|
||||||
|
|
||||||
@ -964,6 +953,7 @@ status_t BufferQueue::consumerConnect(const sp<ConsumerListener>& consumerListen
|
|||||||
}
|
}
|
||||||
|
|
||||||
mConsumerListener = consumerListener;
|
mConsumerListener = consumerListener;
|
||||||
|
mConsumerControlledByApp = controlledByApp;
|
||||||
|
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
@ -1053,40 +1043,17 @@ status_t BufferQueue::setMaxAcquiredBufferCount(int maxAcquiredBuffers) {
|
|||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t BufferQueue::drainQueueLocked() {
|
int BufferQueue::getMinUndequeuedBufferCount(bool async) const {
|
||||||
while (mSynchronousMode && mQueue.size() > 1) {
|
return (mDequeueBufferCannotBlock || async) ?
|
||||||
mDequeueCondition.wait(mMutex);
|
mMaxAcquiredBufferCount+1 : mMaxAcquiredBufferCount;
|
||||||
if (mAbandoned) {
|
|
||||||
ST_LOGE("drainQueueLocked: BufferQueue has been abandoned!");
|
|
||||||
return NO_INIT;
|
|
||||||
}
|
|
||||||
if (mConnectedApi == NO_CONNECTED_API) {
|
|
||||||
ST_LOGE("drainQueueLocked: BufferQueue is not connected!");
|
|
||||||
return NO_INIT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NO_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t BufferQueue::drainQueueAndFreeBuffersLocked() {
|
int BufferQueue::getMinMaxBufferCountLocked(bool async) const {
|
||||||
status_t err = drainQueueLocked();
|
return getMinUndequeuedBufferCount(async) + 1;
|
||||||
if (err == NO_ERROR) {
|
|
||||||
freeAllBuffersLocked();
|
|
||||||
}
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int BufferQueue::getMinMaxBufferCountLocked() const {
|
int BufferQueue::getMaxBufferCountLocked(bool async) const {
|
||||||
return getMinUndequeuedBufferCountLocked() + 1;
|
int minMaxBufferCount = getMinMaxBufferCountLocked(async);
|
||||||
}
|
|
||||||
|
|
||||||
int BufferQueue::getMinUndequeuedBufferCountLocked() const {
|
|
||||||
return mSynchronousMode ? mMaxAcquiredBufferCount :
|
|
||||||
mMaxAcquiredBufferCount + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int BufferQueue::getMaxBufferCountLocked() const {
|
|
||||||
int minMaxBufferCount = getMinMaxBufferCountLocked();
|
|
||||||
|
|
||||||
int maxBufferCount = mDefaultMaxBufferCount;
|
int maxBufferCount = mDefaultMaxBufferCount;
|
||||||
if (maxBufferCount < minMaxBufferCount) {
|
if (maxBufferCount < minMaxBufferCount) {
|
||||||
|
@ -51,7 +51,7 @@ static int32_t createProcessUniqueId() {
|
|||||||
return android_atomic_inc(&globalCounter);
|
return android_atomic_inc(&globalCounter);
|
||||||
}
|
}
|
||||||
|
|
||||||
ConsumerBase::ConsumerBase(const sp<BufferQueue>& bufferQueue) :
|
ConsumerBase::ConsumerBase(const sp<BufferQueue>& bufferQueue, bool controlledByApp) :
|
||||||
mAbandoned(false),
|
mAbandoned(false),
|
||||||
mBufferQueue(bufferQueue) {
|
mBufferQueue(bufferQueue) {
|
||||||
// Choose a name using the PID and a process-unique ID.
|
// Choose a name using the PID and a process-unique ID.
|
||||||
@ -66,7 +66,7 @@ ConsumerBase::ConsumerBase(const sp<BufferQueue>& bufferQueue) :
|
|||||||
listener = static_cast<BufferQueue::ConsumerListener*>(this);
|
listener = static_cast<BufferQueue::ConsumerListener*>(this);
|
||||||
proxy = new BufferQueue::ProxyConsumerListener(listener);
|
proxy = new BufferQueue::ProxyConsumerListener(listener);
|
||||||
|
|
||||||
status_t err = mBufferQueue->consumerConnect(proxy);
|
status_t err = mBufferQueue->consumerConnect(proxy, controlledByApp);
|
||||||
if (err != NO_ERROR) {
|
if (err != NO_ERROR) {
|
||||||
CB_LOGE("ConsumerBase: error connecting to BufferQueue: %s (%d)",
|
CB_LOGE("ConsumerBase: error connecting to BufferQueue: %s (%d)",
|
||||||
strerror(-err), err);
|
strerror(-err), err);
|
||||||
|
@ -31,15 +31,14 @@
|
|||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
CpuConsumer::CpuConsumer(const sp<BufferQueue>& bq,
|
CpuConsumer::CpuConsumer(const sp<BufferQueue>& bq,
|
||||||
uint32_t maxLockedBuffers, bool synchronousMode) :
|
uint32_t maxLockedBuffers, bool controlledByApp) :
|
||||||
ConsumerBase(bq),
|
ConsumerBase(bq, controlledByApp),
|
||||||
mMaxLockedBuffers(maxLockedBuffers),
|
mMaxLockedBuffers(maxLockedBuffers),
|
||||||
mCurrentLockedBuffers(0)
|
mCurrentLockedBuffers(0)
|
||||||
{
|
{
|
||||||
// Create tracking entries for locked buffers
|
// Create tracking entries for locked buffers
|
||||||
mAcquiredBuffers.insertAt(0, maxLockedBuffers);
|
mAcquiredBuffers.insertAt(0, maxLockedBuffers);
|
||||||
|
|
||||||
mBufferQueue->setSynchronousMode(synchronousMode);
|
|
||||||
mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_SW_READ_OFTEN);
|
mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_SW_READ_OFTEN);
|
||||||
mBufferQueue->setMaxAcquiredBufferCount(maxLockedBuffers);
|
mBufferQueue->setMaxAcquiredBufferCount(maxLockedBuffers);
|
||||||
}
|
}
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2012 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define LOG_TAG "DummyConsumer"
|
|
||||||
// #define LOG_NDEBUG 0
|
|
||||||
|
|
||||||
#include <gui/DummyConsumer.h>
|
|
||||||
|
|
||||||
#include <utils/Log.h>
|
|
||||||
#include <utils/String8.h>
|
|
||||||
|
|
||||||
namespace android {
|
|
||||||
|
|
||||||
DummyConsumer::DummyConsumer() {
|
|
||||||
ALOGV("DummyConsumer");
|
|
||||||
}
|
|
||||||
|
|
||||||
DummyConsumer::~DummyConsumer() {
|
|
||||||
ALOGV("~DummyConsumer");
|
|
||||||
}
|
|
||||||
|
|
||||||
void DummyConsumer::onFrameAvailable() {
|
|
||||||
ALOGV("onFrameAvailable");
|
|
||||||
}
|
|
||||||
|
|
||||||
void DummyConsumer::onBuffersReleased() {
|
|
||||||
ALOGV("onBuffersReleased");
|
|
||||||
}
|
|
||||||
|
|
||||||
}; // namespace android
|
|
@ -79,8 +79,8 @@ static void mtxMul(float out[16], const float a[16], const float b[16]);
|
|||||||
|
|
||||||
|
|
||||||
GLConsumer::GLConsumer(const sp<BufferQueue>& bq, GLuint tex,
|
GLConsumer::GLConsumer(const sp<BufferQueue>& bq, GLuint tex,
|
||||||
GLenum texTarget, bool useFenceSync) :
|
GLenum texTarget, bool useFenceSync, bool isControlledByApp) :
|
||||||
ConsumerBase(bq),
|
ConsumerBase(bq, isControlledByApp),
|
||||||
mCurrentTransform(0),
|
mCurrentTransform(0),
|
||||||
mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
|
mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
|
||||||
mCurrentFence(Fence::NO_FENCE),
|
mCurrentFence(Fence::NO_FENCE),
|
||||||
@ -844,11 +844,6 @@ status_t GLConsumer::doGLFenceWaitLocked() const {
|
|||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLConsumer::isSynchronousMode() const {
|
|
||||||
Mutex::Autolock lock(mMutex);
|
|
||||||
return mBufferQueue->isSynchronousMode();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLConsumer::freeBufferLocked(int slotIndex) {
|
void GLConsumer::freeBufferLocked(int slotIndex) {
|
||||||
ST_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
|
ST_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
|
||||||
if (slotIndex == mCurrentTexture) {
|
if (slotIndex == mCurrentTexture) {
|
||||||
@ -891,13 +886,6 @@ status_t GLConsumer::setTransformHint(uint32_t hint) {
|
|||||||
return mBufferQueue->setTransformHint(hint);
|
return mBufferQueue->setTransformHint(hint);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used for refactoring BufferQueue from GLConsumer
|
|
||||||
// Should not be in final interface once users of GLConsumer are clean up.
|
|
||||||
status_t GLConsumer::setSynchronousMode(bool enabled) {
|
|
||||||
Mutex::Autolock lock(mMutex);
|
|
||||||
return mBufferQueue->setSynchronousMode(enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLConsumer::dumpLocked(String8& result, const char* prefix) const
|
void GLConsumer::dumpLocked(String8& result, const char* prefix) const
|
||||||
{
|
{
|
||||||
result.appendFormat(
|
result.appendFormat(
|
||||||
|
@ -37,7 +37,6 @@ enum {
|
|||||||
QUEUE_BUFFER,
|
QUEUE_BUFFER,
|
||||||
CANCEL_BUFFER,
|
CANCEL_BUFFER,
|
||||||
QUERY,
|
QUERY,
|
||||||
SET_SYNCHRONOUS_MODE,
|
|
||||||
CONNECT,
|
CONNECT,
|
||||||
DISCONNECT,
|
DISCONNECT,
|
||||||
};
|
};
|
||||||
@ -81,10 +80,11 @@ public:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence,
|
virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence, bool async,
|
||||||
uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
|
uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
|
||||||
Parcel data, reply;
|
Parcel data, reply;
|
||||||
data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
|
data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
|
||||||
|
data.writeInt32(async);
|
||||||
data.writeInt32(w);
|
data.writeInt32(w);
|
||||||
data.writeInt32(h);
|
data.writeInt32(h);
|
||||||
data.writeInt32(format);
|
data.writeInt32(format);
|
||||||
@ -142,22 +142,11 @@ public:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual status_t setSynchronousMode(bool enabled) {
|
virtual status_t connect(int api, bool producerControlledByApp, QueueBufferOutput* output) {
|
||||||
Parcel data, reply;
|
|
||||||
data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
|
|
||||||
data.writeInt32(enabled);
|
|
||||||
status_t result = remote()->transact(SET_SYNCHRONOUS_MODE, data, &reply);
|
|
||||||
if (result != NO_ERROR) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result = reply.readInt32();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual status_t connect(int api, QueueBufferOutput* output) {
|
|
||||||
Parcel data, reply;
|
Parcel data, reply;
|
||||||
data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
|
data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
|
||||||
data.writeInt32(api);
|
data.writeInt32(api);
|
||||||
|
data.writeInt32(producerControlledByApp);
|
||||||
status_t result = remote()->transact(CONNECT, data, &reply);
|
status_t result = remote()->transact(CONNECT, data, &reply);
|
||||||
if (result != NO_ERROR) {
|
if (result != NO_ERROR) {
|
||||||
return result;
|
return result;
|
||||||
@ -209,13 +198,14 @@ status_t BnGraphicBufferProducer::onTransact(
|
|||||||
} break;
|
} break;
|
||||||
case DEQUEUE_BUFFER: {
|
case DEQUEUE_BUFFER: {
|
||||||
CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
|
CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
|
||||||
|
bool async = data.readInt32();
|
||||||
uint32_t w = data.readInt32();
|
uint32_t w = data.readInt32();
|
||||||
uint32_t h = data.readInt32();
|
uint32_t h = data.readInt32();
|
||||||
uint32_t format = data.readInt32();
|
uint32_t format = data.readInt32();
|
||||||
uint32_t usage = data.readInt32();
|
uint32_t usage = data.readInt32();
|
||||||
int buf;
|
int buf;
|
||||||
sp<Fence> fence;
|
sp<Fence> fence;
|
||||||
int result = dequeueBuffer(&buf, &fence, w, h, format, usage);
|
int result = dequeueBuffer(&buf, &fence, async, w, h, format, usage);
|
||||||
reply->writeInt32(buf);
|
reply->writeInt32(buf);
|
||||||
reply->writeInt32(fence != NULL);
|
reply->writeInt32(fence != NULL);
|
||||||
if (fence != NULL) {
|
if (fence != NULL) {
|
||||||
@ -252,20 +242,14 @@ status_t BnGraphicBufferProducer::onTransact(
|
|||||||
reply->writeInt32(res);
|
reply->writeInt32(res);
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
} break;
|
} break;
|
||||||
case SET_SYNCHRONOUS_MODE: {
|
|
||||||
CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
|
|
||||||
bool enabled = data.readInt32();
|
|
||||||
status_t res = setSynchronousMode(enabled);
|
|
||||||
reply->writeInt32(res);
|
|
||||||
return NO_ERROR;
|
|
||||||
} break;
|
|
||||||
case CONNECT: {
|
case CONNECT: {
|
||||||
CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
|
CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
|
||||||
int api = data.readInt32();
|
int api = data.readInt32();
|
||||||
|
bool producerControlledByApp = data.readInt32();
|
||||||
QueueBufferOutput* const output =
|
QueueBufferOutput* const output =
|
||||||
reinterpret_cast<QueueBufferOutput *>(
|
reinterpret_cast<QueueBufferOutput *>(
|
||||||
reply->writeInplace(sizeof(QueueBufferOutput)));
|
reply->writeInplace(sizeof(QueueBufferOutput)));
|
||||||
status_t res = connect(api, output);
|
status_t res = connect(api, producerControlledByApp, output);
|
||||||
reply->writeInt32(res);
|
reply->writeInt32(res);
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
} break;
|
} break;
|
||||||
@ -292,6 +276,7 @@ size_t IGraphicBufferProducer::QueueBufferInput::getFlattenedSize() const
|
|||||||
+ sizeof(crop)
|
+ sizeof(crop)
|
||||||
+ sizeof(scalingMode)
|
+ sizeof(scalingMode)
|
||||||
+ sizeof(transform)
|
+ sizeof(transform)
|
||||||
|
+ sizeof(async)
|
||||||
+ fence->getFlattenedSize();
|
+ fence->getFlattenedSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -309,6 +294,7 @@ status_t IGraphicBufferProducer::QueueBufferInput::flatten(void* buffer, size_t
|
|||||||
memcpy(p, &crop, sizeof(crop)); p += sizeof(crop);
|
memcpy(p, &crop, sizeof(crop)); p += sizeof(crop);
|
||||||
memcpy(p, &scalingMode, sizeof(scalingMode)); p += sizeof(scalingMode);
|
memcpy(p, &scalingMode, sizeof(scalingMode)); p += sizeof(scalingMode);
|
||||||
memcpy(p, &transform, sizeof(transform)); p += sizeof(transform);
|
memcpy(p, &transform, sizeof(transform)); p += sizeof(transform);
|
||||||
|
memcpy(p, &async, sizeof(async)); p += sizeof(async);
|
||||||
err = fence->flatten(p, size - (p - (char*)buffer), fds, count);
|
err = fence->flatten(p, size - (p - (char*)buffer), fds, count);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -322,6 +308,7 @@ status_t IGraphicBufferProducer::QueueBufferInput::unflatten(void const* buffer,
|
|||||||
memcpy(&crop, p, sizeof(crop)); p += sizeof(crop);
|
memcpy(&crop, p, sizeof(crop)); p += sizeof(crop);
|
||||||
memcpy(&scalingMode, p, sizeof(scalingMode)); p += sizeof(scalingMode);
|
memcpy(&scalingMode, p, sizeof(scalingMode)); p += sizeof(scalingMode);
|
||||||
memcpy(&transform, p, sizeof(transform)); p += sizeof(transform);
|
memcpy(&transform, p, sizeof(transform)); p += sizeof(transform);
|
||||||
|
memcpy(&async, p, sizeof(async)); p += sizeof(async);
|
||||||
fence = new Fence();
|
fence = new Fence();
|
||||||
err = fence->unflatten(p, size - (p - (const char*)buffer), fds, count);
|
err = fence->unflatten(p, size - (p - (const char*)buffer), fds, count);
|
||||||
return err;
|
return err;
|
||||||
|
@ -37,7 +37,8 @@
|
|||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
Surface::Surface(
|
Surface::Surface(
|
||||||
const sp<IGraphicBufferProducer>& bufferProducer)
|
const sp<IGraphicBufferProducer>& bufferProducer,
|
||||||
|
bool controlledByApp)
|
||||||
: mGraphicBufferProducer(bufferProducer)
|
: mGraphicBufferProducer(bufferProducer)
|
||||||
{
|
{
|
||||||
// Initialize the ANativeWindow function pointers.
|
// Initialize the ANativeWindow function pointers.
|
||||||
@ -71,6 +72,8 @@ Surface::Surface(
|
|||||||
mTransformHint = 0;
|
mTransformHint = 0;
|
||||||
mConsumerRunningBehind = false;
|
mConsumerRunningBehind = false;
|
||||||
mConnectedToCpu = false;
|
mConnectedToCpu = false;
|
||||||
|
mProducerControlledByApp = true;
|
||||||
|
mSwapIntervalZero = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Surface::~Surface() {
|
Surface::~Surface() {
|
||||||
@ -160,7 +163,6 @@ int Surface::setSwapInterval(int interval) {
|
|||||||
// EGL specification states:
|
// EGL specification states:
|
||||||
// interval is silently clamped to minimum and maximum implementation
|
// interval is silently clamped to minimum and maximum implementation
|
||||||
// dependent values before being stored.
|
// dependent values before being stored.
|
||||||
// Although we don't have to, we apply the same logic here.
|
|
||||||
|
|
||||||
if (interval < minSwapInterval)
|
if (interval < minSwapInterval)
|
||||||
interval = minSwapInterval;
|
interval = minSwapInterval;
|
||||||
@ -168,9 +170,9 @@ int Surface::setSwapInterval(int interval) {
|
|||||||
if (interval > maxSwapInterval)
|
if (interval > maxSwapInterval)
|
||||||
interval = maxSwapInterval;
|
interval = maxSwapInterval;
|
||||||
|
|
||||||
status_t res = mGraphicBufferProducer->setSynchronousMode(interval ? true : false);
|
mSwapIntervalZero = (interval == 0);
|
||||||
|
|
||||||
return res;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Surface::dequeueBuffer(android_native_buffer_t** buffer,
|
int Surface::dequeueBuffer(android_native_buffer_t** buffer,
|
||||||
@ -182,7 +184,7 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer,
|
|||||||
int reqW = mReqWidth ? mReqWidth : mUserWidth;
|
int reqW = mReqWidth ? mReqWidth : mUserWidth;
|
||||||
int reqH = mReqHeight ? mReqHeight : mUserHeight;
|
int reqH = mReqHeight ? mReqHeight : mUserHeight;
|
||||||
sp<Fence> fence;
|
sp<Fence> fence;
|
||||||
status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence,
|
status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, mSwapIntervalZero,
|
||||||
reqW, reqH, mReqFormat, mReqUsage);
|
reqW, reqH, mReqFormat, mReqUsage);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
ALOGV("dequeueBuffer: IGraphicBufferProducer::dequeueBuffer(%d, %d, %d, %d)"
|
ALOGV("dequeueBuffer: IGraphicBufferProducer::dequeueBuffer(%d, %d, %d, %d)"
|
||||||
@ -278,7 +280,7 @@ int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {
|
|||||||
sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE);
|
sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE);
|
||||||
IGraphicBufferProducer::QueueBufferOutput output;
|
IGraphicBufferProducer::QueueBufferOutput output;
|
||||||
IGraphicBufferProducer::QueueBufferInput input(timestamp, crop, mScalingMode,
|
IGraphicBufferProducer::QueueBufferInput input(timestamp, crop, mScalingMode,
|
||||||
mTransform, fence);
|
mTransform, mSwapIntervalZero, fence);
|
||||||
status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output);
|
status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output);
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err);
|
ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err);
|
||||||
@ -486,7 +488,7 @@ int Surface::connect(int api) {
|
|||||||
ALOGV("Surface::connect");
|
ALOGV("Surface::connect");
|
||||||
Mutex::Autolock lock(mMutex);
|
Mutex::Autolock lock(mMutex);
|
||||||
IGraphicBufferProducer::QueueBufferOutput output;
|
IGraphicBufferProducer::QueueBufferOutput output;
|
||||||
int err = mGraphicBufferProducer->connect(api, &output);
|
int err = mGraphicBufferProducer->connect(api, mProducerControlledByApp, &output);
|
||||||
if (err == NO_ERROR) {
|
if (err == NO_ERROR) {
|
||||||
uint32_t numPendingBuffers = 0;
|
uint32_t numPendingBuffers = 0;
|
||||||
output.deflate(&mDefaultWidth, &mDefaultHeight, &mTransformHint,
|
output.deflate(&mDefaultWidth, &mDefaultHeight, &mTransformHint,
|
||||||
|
@ -62,21 +62,21 @@ struct DummyConsumer : public BufferQueue::ConsumerListener {
|
|||||||
|
|
||||||
TEST_F(BufferQueueTest, AcquireBuffer_ExceedsMaxAcquireCount_Fails) {
|
TEST_F(BufferQueueTest, AcquireBuffer_ExceedsMaxAcquireCount_Fails) {
|
||||||
sp<DummyConsumer> dc(new DummyConsumer);
|
sp<DummyConsumer> dc(new DummyConsumer);
|
||||||
mBQ->consumerConnect(dc);
|
mBQ->consumerConnect(dc, false);
|
||||||
IGraphicBufferProducer::QueueBufferOutput qbo;
|
IGraphicBufferProducer::QueueBufferOutput qbo;
|
||||||
mBQ->connect(NATIVE_WINDOW_API_CPU, &qbo);
|
mBQ->connect(NATIVE_WINDOW_API_CPU, false, &qbo);
|
||||||
mBQ->setBufferCount(4);
|
mBQ->setBufferCount(4);
|
||||||
|
|
||||||
int slot;
|
int slot;
|
||||||
sp<Fence> fence;
|
sp<Fence> fence;
|
||||||
sp<GraphicBuffer> buf;
|
sp<GraphicBuffer> buf;
|
||||||
IGraphicBufferProducer::QueueBufferInput qbi(0, Rect(0, 0, 1, 1),
|
IGraphicBufferProducer::QueueBufferInput qbi(0, Rect(0, 0, 1, 1),
|
||||||
NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
|
NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE);
|
||||||
BufferQueue::BufferItem item;
|
BufferQueue::BufferItem item;
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
|
ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
|
||||||
mBQ->dequeueBuffer(&slot, &fence, 1, 1, 0,
|
mBQ->dequeueBuffer(&slot, &fence, false, 1, 1, 0,
|
||||||
GRALLOC_USAGE_SW_READ_OFTEN));
|
GRALLOC_USAGE_SW_READ_OFTEN));
|
||||||
ASSERT_EQ(OK, mBQ->requestBuffer(slot, &buf));
|
ASSERT_EQ(OK, mBQ->requestBuffer(slot, &buf));
|
||||||
ASSERT_EQ(OK, mBQ->queueBuffer(slot, qbi, &qbo));
|
ASSERT_EQ(OK, mBQ->queueBuffer(slot, qbi, &qbo));
|
||||||
@ -84,7 +84,7 @@ TEST_F(BufferQueueTest, AcquireBuffer_ExceedsMaxAcquireCount_Fails) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
|
ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
|
||||||
mBQ->dequeueBuffer(&slot, &fence, 1, 1, 0,
|
mBQ->dequeueBuffer(&slot, &fence, false, 1, 1, 0,
|
||||||
GRALLOC_USAGE_SW_READ_OFTEN));
|
GRALLOC_USAGE_SW_READ_OFTEN));
|
||||||
ASSERT_EQ(OK, mBQ->requestBuffer(slot, &buf));
|
ASSERT_EQ(OK, mBQ->requestBuffer(slot, &buf));
|
||||||
ASSERT_EQ(OK, mBQ->queueBuffer(slot, qbi, &qbo));
|
ASSERT_EQ(OK, mBQ->queueBuffer(slot, qbi, &qbo));
|
||||||
@ -95,7 +95,7 @@ TEST_F(BufferQueueTest, AcquireBuffer_ExceedsMaxAcquireCount_Fails) {
|
|||||||
|
|
||||||
TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithIllegalValues_ReturnsError) {
|
TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithIllegalValues_ReturnsError) {
|
||||||
sp<DummyConsumer> dc(new DummyConsumer);
|
sp<DummyConsumer> dc(new DummyConsumer);
|
||||||
mBQ->consumerConnect(dc);
|
mBQ->consumerConnect(dc, false);
|
||||||
|
|
||||||
ASSERT_EQ(BAD_VALUE, mBQ->setMaxAcquiredBufferCount(0));
|
ASSERT_EQ(BAD_VALUE, mBQ->setMaxAcquiredBufferCount(0));
|
||||||
ASSERT_EQ(BAD_VALUE, mBQ->setMaxAcquiredBufferCount(-3));
|
ASSERT_EQ(BAD_VALUE, mBQ->setMaxAcquiredBufferCount(-3));
|
||||||
@ -106,7 +106,7 @@ TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithIllegalValues_ReturnsError)
|
|||||||
|
|
||||||
TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithLegalValues_Succeeds) {
|
TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithLegalValues_Succeeds) {
|
||||||
sp<DummyConsumer> dc(new DummyConsumer);
|
sp<DummyConsumer> dc(new DummyConsumer);
|
||||||
mBQ->consumerConnect(dc);
|
mBQ->consumerConnect(dc, false);
|
||||||
|
|
||||||
ASSERT_EQ(OK, mBQ->setMaxAcquiredBufferCount(1));
|
ASSERT_EQ(OK, mBQ->setMaxAcquiredBufferCount(1));
|
||||||
ASSERT_EQ(OK, mBQ->setMaxAcquiredBufferCount(2));
|
ASSERT_EQ(OK, mBQ->setMaxAcquiredBufferCount(2));
|
||||||
|
@ -338,7 +338,7 @@ TEST_F(SurfaceTextureClientTest, SurfaceTextureSetDefaultSizeVsGeometry) {
|
|||||||
|
|
||||||
TEST_F(SurfaceTextureClientTest, SurfaceTextureTooManyUpdateTexImage) {
|
TEST_F(SurfaceTextureClientTest, SurfaceTextureTooManyUpdateTexImage) {
|
||||||
android_native_buffer_t* buf[3];
|
android_native_buffer_t* buf[3];
|
||||||
ASSERT_EQ(OK, mST->setSynchronousMode(false));
|
ASSERT_EQ(OK, mANW->setSwapInterval(mANW.get(), 0));
|
||||||
ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
|
ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
|
||||||
|
|
||||||
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
|
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
|
||||||
@ -346,7 +346,7 @@ TEST_F(SurfaceTextureClientTest, SurfaceTextureTooManyUpdateTexImage) {
|
|||||||
EXPECT_EQ(OK, mST->updateTexImage());
|
EXPECT_EQ(OK, mST->updateTexImage());
|
||||||
EXPECT_EQ(OK, mST->updateTexImage());
|
EXPECT_EQ(OK, mST->updateTexImage());
|
||||||
|
|
||||||
ASSERT_EQ(OK, mST->setSynchronousMode(true));
|
ASSERT_EQ(OK, mANW->setSwapInterval(mANW.get(), 1));
|
||||||
ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
|
ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
|
||||||
|
|
||||||
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
|
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
|
||||||
@ -361,7 +361,6 @@ TEST_F(SurfaceTextureClientTest, SurfaceTextureTooManyUpdateTexImage) {
|
|||||||
|
|
||||||
TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeSlowRetire) {
|
TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeSlowRetire) {
|
||||||
android_native_buffer_t* buf[3];
|
android_native_buffer_t* buf[3];
|
||||||
ASSERT_EQ(OK, mST->setSynchronousMode(true));
|
|
||||||
ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
|
ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
|
||||||
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
|
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
|
||||||
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
|
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
|
||||||
@ -382,7 +381,6 @@ TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeSlowRetire) {
|
|||||||
|
|
||||||
TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeFastRetire) {
|
TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeFastRetire) {
|
||||||
android_native_buffer_t* buf[3];
|
android_native_buffer_t* buf[3];
|
||||||
ASSERT_EQ(OK, mST->setSynchronousMode(true));
|
|
||||||
ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
|
ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
|
||||||
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
|
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
|
||||||
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
|
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
|
||||||
@ -403,7 +401,6 @@ TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeFastRetire) {
|
|||||||
|
|
||||||
TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeDQQR) {
|
TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeDQQR) {
|
||||||
android_native_buffer_t* buf[3];
|
android_native_buffer_t* buf[3];
|
||||||
ASSERT_EQ(OK, mST->setSynchronousMode(true));
|
|
||||||
ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
|
ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
|
||||||
|
|
||||||
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
|
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
|
||||||
@ -429,7 +426,6 @@ TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeDQQR) {
|
|||||||
TEST_F(SurfaceTextureClientTest, DISABLED_SurfaceTextureSyncModeDequeueCurrent) {
|
TEST_F(SurfaceTextureClientTest, DISABLED_SurfaceTextureSyncModeDequeueCurrent) {
|
||||||
android_native_buffer_t* buf[3];
|
android_native_buffer_t* buf[3];
|
||||||
android_native_buffer_t* firstBuf;
|
android_native_buffer_t* firstBuf;
|
||||||
ASSERT_EQ(OK, mST->setSynchronousMode(true));
|
|
||||||
ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
|
ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
|
||||||
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &firstBuf));
|
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &firstBuf));
|
||||||
ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), firstBuf, -1));
|
ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), firstBuf, -1));
|
||||||
@ -449,7 +445,6 @@ TEST_F(SurfaceTextureClientTest, DISABLED_SurfaceTextureSyncModeDequeueCurrent)
|
|||||||
|
|
||||||
TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeMinUndequeued) {
|
TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeMinUndequeued) {
|
||||||
android_native_buffer_t* buf[3];
|
android_native_buffer_t* buf[3];
|
||||||
ASSERT_EQ(OK, mST->setSynchronousMode(true));
|
|
||||||
ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
|
ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
|
||||||
|
|
||||||
// We should be able to dequeue all the buffers before we've queued mANWy.
|
// We should be able to dequeue all the buffers before we've queued mANWy.
|
||||||
@ -528,7 +523,6 @@ TEST_F(SurfaceTextureClientTest, DISABLED_SurfaceTextureSyncModeWaitRetire) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
android_native_buffer_t* buf[3];
|
android_native_buffer_t* buf[3];
|
||||||
ASSERT_EQ(OK, mST->setSynchronousMode(true));
|
|
||||||
ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
|
ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
|
||||||
// dequeue/queue/update so we have a current buffer
|
// dequeue/queue/update so we have a current buffer
|
||||||
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
|
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
|
||||||
|
@ -944,7 +944,6 @@ TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BuffersRepeatedly) {
|
|||||||
enum { texHeight = 16 };
|
enum { texHeight = 16 };
|
||||||
enum { numFrames = 1024 };
|
enum { numFrames = 1024 };
|
||||||
|
|
||||||
ASSERT_EQ(NO_ERROR, mST->setSynchronousMode(true));
|
|
||||||
ASSERT_EQ(NO_ERROR, mST->setDefaultMaxBufferCount(2));
|
ASSERT_EQ(NO_ERROR, mST->setDefaultMaxBufferCount(2));
|
||||||
ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
|
ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
|
||||||
texWidth, texHeight, HAL_PIXEL_FORMAT_YV12));
|
texWidth, texHeight, HAL_PIXEL_FORMAT_YV12));
|
||||||
@ -1211,10 +1210,8 @@ TEST_F(SurfaceTextureGLTest, DisconnectStressTest) {
|
|||||||
sp<ANativeWindow> mANW;
|
sp<ANativeWindow> mANW;
|
||||||
};
|
};
|
||||||
|
|
||||||
ASSERT_EQ(OK, mST->setSynchronousMode(true));
|
|
||||||
|
|
||||||
sp<DisconnectWaiter> dw(new DisconnectWaiter());
|
sp<DisconnectWaiter> dw(new DisconnectWaiter());
|
||||||
mST->getBufferQueue()->consumerConnect(dw);
|
mST->getBufferQueue()->consumerConnect(dw, false);
|
||||||
|
|
||||||
|
|
||||||
sp<Thread> pt(new ProducerThread(mANW));
|
sp<Thread> pt(new ProducerThread(mANW));
|
||||||
@ -1237,8 +1234,6 @@ TEST_F(SurfaceTextureGLTest, DisconnectStressTest) {
|
|||||||
// when it is disconnected and reconnected. Otherwise it will
|
// when it is disconnected and reconnected. Otherwise it will
|
||||||
// attempt to release a buffer that it does not owned
|
// attempt to release a buffer that it does not owned
|
||||||
TEST_F(SurfaceTextureGLTest, DisconnectClearsCurrentTexture) {
|
TEST_F(SurfaceTextureGLTest, DisconnectClearsCurrentTexture) {
|
||||||
ASSERT_EQ(OK, mST->setSynchronousMode(true));
|
|
||||||
|
|
||||||
ASSERT_EQ(OK, native_window_api_connect(mANW.get(),
|
ASSERT_EQ(OK, native_window_api_connect(mANW.get(),
|
||||||
NATIVE_WINDOW_API_EGL));
|
NATIVE_WINDOW_API_EGL));
|
||||||
|
|
||||||
@ -1258,8 +1253,6 @@ TEST_F(SurfaceTextureGLTest, DisconnectClearsCurrentTexture) {
|
|||||||
ASSERT_EQ(OK, native_window_api_connect(mANW.get(),
|
ASSERT_EQ(OK, native_window_api_connect(mANW.get(),
|
||||||
NATIVE_WINDOW_API_EGL));
|
NATIVE_WINDOW_API_EGL));
|
||||||
|
|
||||||
ASSERT_EQ(OK, mST->setSynchronousMode(true));
|
|
||||||
|
|
||||||
EXPECT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb));
|
EXPECT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb));
|
||||||
EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1));
|
EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1));
|
||||||
|
|
||||||
@ -1272,8 +1265,6 @@ TEST_F(SurfaceTextureGLTest, DisconnectClearsCurrentTexture) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SurfaceTextureGLTest, ScaleToWindowMode) {
|
TEST_F(SurfaceTextureGLTest, ScaleToWindowMode) {
|
||||||
ASSERT_EQ(OK, mST->setSynchronousMode(true));
|
|
||||||
|
|
||||||
ASSERT_EQ(OK, native_window_set_scaling_mode(mANW.get(),
|
ASSERT_EQ(OK, native_window_set_scaling_mode(mANW.get(),
|
||||||
NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW));
|
NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW));
|
||||||
|
|
||||||
@ -1306,8 +1297,6 @@ TEST_F(SurfaceTextureGLTest, ScaleToWindowMode) {
|
|||||||
// the image such that it has the same aspect ratio as the
|
// the image such that it has the same aspect ratio as the
|
||||||
// default buffer size
|
// default buffer size
|
||||||
TEST_F(SurfaceTextureGLTest, CroppedScalingMode) {
|
TEST_F(SurfaceTextureGLTest, CroppedScalingMode) {
|
||||||
ASSERT_EQ(OK, mST->setSynchronousMode(true));
|
|
||||||
|
|
||||||
ASSERT_EQ(OK, native_window_set_scaling_mode(mANW.get(),
|
ASSERT_EQ(OK, native_window_set_scaling_mode(mANW.get(),
|
||||||
NATIVE_WINDOW_SCALING_MODE_SCALE_CROP));
|
NATIVE_WINDOW_SCALING_MODE_SCALE_CROP));
|
||||||
|
|
||||||
@ -1417,7 +1406,6 @@ TEST_F(SurfaceTextureGLTest, AbandonUnblocksDequeueBuffer) {
|
|||||||
Mutex mMutex;
|
Mutex mMutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
ASSERT_EQ(OK, mST->setSynchronousMode(true));
|
|
||||||
ASSERT_EQ(OK, mST->setDefaultMaxBufferCount(2));
|
ASSERT_EQ(OK, mST->setDefaultMaxBufferCount(2));
|
||||||
|
|
||||||
sp<Thread> pt(new ProducerThread(mANW));
|
sp<Thread> pt(new ProducerThread(mANW));
|
||||||
@ -1810,32 +1798,6 @@ TEST_F(SurfaceTextureGLToGLTest, EglMakeCurrentAfterConsumerDeathUnrefsBuffers)
|
|||||||
EXPECT_EQ(1, buffer->getStrongCount());
|
EXPECT_EQ(1, buffer->getStrongCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_F(SurfaceTextureGLToGLTest, EglSurfaceDefaultsToSynchronousMode) {
|
|
||||||
// This test requires 3 buffers to run on a single thread.
|
|
||||||
mST->setDefaultMaxBufferCount(3);
|
|
||||||
|
|
||||||
ASSERT_TRUE(mST->isSynchronousMode());
|
|
||||||
|
|
||||||
for (int i = 0; i < 10; i++) {
|
|
||||||
// Produce a frame
|
|
||||||
EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
|
|
||||||
mProducerEglSurface, mProducerEglContext));
|
|
||||||
ASSERT_EQ(EGL_SUCCESS, eglGetError());
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
|
||||||
EXPECT_TRUE(eglSwapBuffers(mEglDisplay, mProducerEglSurface));
|
|
||||||
ASSERT_EQ(EGL_SUCCESS, eglGetError());
|
|
||||||
|
|
||||||
// Consume a frame
|
|
||||||
EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
|
|
||||||
mEglContext));
|
|
||||||
ASSERT_EQ(EGL_SUCCESS, eglGetError());
|
|
||||||
ASSERT_EQ(NO_ERROR, mST->updateTexImage());
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT_TRUE(mST->isSynchronousMode());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(SurfaceTextureGLToGLTest, TexturingFromUserSizedGLFilledBuffer) {
|
TEST_F(SurfaceTextureGLToGLTest, TexturingFromUserSizedGLFilledBuffer) {
|
||||||
enum { texWidth = 64 };
|
enum { texWidth = 64 };
|
||||||
enum { texHeight = 64 };
|
enum { texHeight = 64 };
|
||||||
@ -2285,7 +2247,6 @@ TEST_F(SurfaceTextureGLThreadToGLTest,
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ASSERT_EQ(OK, mST->setSynchronousMode(true));
|
|
||||||
ASSERT_EQ(OK, mST->setDefaultMaxBufferCount(2));
|
ASSERT_EQ(OK, mST->setDefaultMaxBufferCount(2));
|
||||||
|
|
||||||
runProducerThread(new PT());
|
runProducerThread(new PT());
|
||||||
@ -2826,7 +2787,6 @@ TEST_F(SurfaceTextureMultiContextGLTest,
|
|||||||
|
|
||||||
TEST_F(SurfaceTextureMultiContextGLTest,
|
TEST_F(SurfaceTextureMultiContextGLTest,
|
||||||
UpdateTexImageSucceedsForBufferConsumedBeforeDetach) {
|
UpdateTexImageSucceedsForBufferConsumedBeforeDetach) {
|
||||||
ASSERT_EQ(NO_ERROR, mST->setSynchronousMode(true));
|
|
||||||
ASSERT_EQ(NO_ERROR, mST->setDefaultMaxBufferCount(2));
|
ASSERT_EQ(NO_ERROR, mST->setDefaultMaxBufferCount(2));
|
||||||
|
|
||||||
// produce two frames and consume them both on the primary context
|
// produce two frames and consume them both on the primary context
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
|
|
||||||
#include <EGL/egl.h>
|
#include <EGL/egl.h>
|
||||||
#include <gui/Surface.h>
|
#include <gui/Surface.h>
|
||||||
#include <gui/DummyConsumer.h>
|
|
||||||
|
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
@ -101,9 +100,14 @@ TEST_F(EGLTest, EGLTerminateSucceedsWithRemainingObjects) {
|
|||||||
};
|
};
|
||||||
EXPECT_TRUE(eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs));
|
EXPECT_TRUE(eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs));
|
||||||
|
|
||||||
|
struct DummyConsumer : public BufferQueue::ConsumerListener {
|
||||||
|
virtual void onFrameAvailable() {}
|
||||||
|
virtual void onBuffersReleased() {}
|
||||||
|
};
|
||||||
|
|
||||||
// Create a EGLSurface
|
// Create a EGLSurface
|
||||||
sp<BufferQueue> bq = new BufferQueue();
|
sp<BufferQueue> bq = new BufferQueue();
|
||||||
bq->consumerConnect(new DummyConsumer());
|
bq->consumerConnect(new DummyConsumer, false);
|
||||||
sp<Surface> mSTC = new Surface(static_cast<sp<IGraphicBufferProducer> >( bq));
|
sp<Surface> mSTC = new Surface(static_cast<sp<IGraphicBufferProducer> >( bq));
|
||||||
sp<ANativeWindow> mANW = mSTC;
|
sp<ANativeWindow> mANW = mSTC;
|
||||||
|
|
||||||
|
@ -36,7 +36,6 @@ ifeq ($(TARGET_BOARD_PLATFORM),omap4)
|
|||||||
endif
|
endif
|
||||||
ifeq ($(TARGET_BOARD_PLATFORM),s5pc110)
|
ifeq ($(TARGET_BOARD_PLATFORM),s5pc110)
|
||||||
LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY
|
LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY
|
||||||
LOCAL_CFLAGS += -DNEVER_DEFAULT_TO_ASYNC_MODE
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(TARGET_DISABLE_TRIPLE_BUFFERING),true)
|
ifeq ($(TARGET_DISABLE_TRIPLE_BUFFERING),true)
|
||||||
|
@ -51,7 +51,7 @@ namespace android {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
FramebufferSurface::FramebufferSurface(HWComposer& hwc, int disp) :
|
FramebufferSurface::FramebufferSurface(HWComposer& hwc, int disp) :
|
||||||
ConsumerBase(new BufferQueue(true, new GraphicBufferAlloc())),
|
ConsumerBase(new BufferQueue(new GraphicBufferAlloc())),
|
||||||
mDisplayType(disp),
|
mDisplayType(disp),
|
||||||
mCurrentBufferSlot(-1),
|
mCurrentBufferSlot(-1),
|
||||||
mCurrentBuffer(0),
|
mCurrentBuffer(0),
|
||||||
@ -64,7 +64,6 @@ FramebufferSurface::FramebufferSurface(HWComposer& hwc, int disp) :
|
|||||||
GRALLOC_USAGE_HW_COMPOSER);
|
GRALLOC_USAGE_HW_COMPOSER);
|
||||||
mBufferQueue->setDefaultBufferFormat(mHwc.getFormat(disp));
|
mBufferQueue->setDefaultBufferFormat(mHwc.getFormat(disp));
|
||||||
mBufferQueue->setDefaultBufferSize(mHwc.getWidth(disp), mHwc.getHeight(disp));
|
mBufferQueue->setDefaultBufferSize(mHwc.getWidth(disp), mHwc.getHeight(disp));
|
||||||
mBufferQueue->setSynchronousMode(true);
|
|
||||||
mBufferQueue->setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS);
|
mBufferQueue->setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ static const char* dbgCompositionTypeStr(DisplaySurface::CompositionType type) {
|
|||||||
|
|
||||||
VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int32_t dispId,
|
VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int32_t dispId,
|
||||||
const sp<IGraphicBufferProducer>& sink, const String8& name)
|
const sp<IGraphicBufferProducer>& sink, const String8& name)
|
||||||
: ConsumerBase(new BufferQueue(true)),
|
: ConsumerBase(new BufferQueue()),
|
||||||
mHwc(hwc),
|
mHwc(hwc),
|
||||||
mDisplayId(dispId),
|
mDisplayId(dispId),
|
||||||
mDisplayName(name),
|
mDisplayName(name),
|
||||||
@ -126,7 +126,7 @@ status_t VirtualDisplaySurface::advanceFrame() {
|
|||||||
mQueueBufferOutput.deflate(&mSinkBufferWidth, &mSinkBufferHeight,
|
mQueueBufferOutput.deflate(&mSinkBufferWidth, &mSinkBufferHeight,
|
||||||
&transformHint, &numPendingBuffers);
|
&transformHint, &numPendingBuffers);
|
||||||
int sslot;
|
int sslot;
|
||||||
result = dequeueBuffer(SOURCE_SINK, 0, &sslot, &outFence);
|
result = dequeueBuffer(SOURCE_SINK, 0, &sslot, &outFence, false);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
return result;
|
return result;
|
||||||
mOutputProducerSlot = mapSource2ProducerSlot(SOURCE_SINK, sslot);
|
mOutputProducerSlot = mapSource2ProducerSlot(SOURCE_SINK, sslot);
|
||||||
@ -196,7 +196,7 @@ void VirtualDisplaySurface::onFrameCommitted() {
|
|||||||
status_t result = mSource[SOURCE_SINK]->queueBuffer(sslot,
|
status_t result = mSource[SOURCE_SINK]->queueBuffer(sslot,
|
||||||
QueueBufferInput(systemTime(),
|
QueueBufferInput(systemTime(),
|
||||||
Rect(mSinkBufferWidth, mSinkBufferHeight),
|
Rect(mSinkBufferWidth, mSinkBufferHeight),
|
||||||
NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, outFence),
|
NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, outFence),
|
||||||
&qbo);
|
&qbo);
|
||||||
if (result == NO_ERROR) {
|
if (result == NO_ERROR) {
|
||||||
updateQueueBufferOutput(qbo);
|
updateQueueBufferOutput(qbo);
|
||||||
@ -224,8 +224,8 @@ status_t VirtualDisplaySurface::setBufferCount(int bufferCount) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
status_t VirtualDisplaySurface::dequeueBuffer(Source source,
|
status_t VirtualDisplaySurface::dequeueBuffer(Source source,
|
||||||
uint32_t format, int* sslot, sp<Fence>* fence) {
|
uint32_t format, int* sslot, sp<Fence>* fence, bool async) {
|
||||||
status_t result = mSource[source]->dequeueBuffer(sslot, fence,
|
status_t result = mSource[source]->dequeueBuffer(sslot, fence, async,
|
||||||
mSinkBufferWidth, mSinkBufferHeight, format, mProducerUsage);
|
mSinkBufferWidth, mSinkBufferHeight, format, mProducerUsage);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
return result;
|
return result;
|
||||||
@ -257,7 +257,7 @@ status_t VirtualDisplaySurface::dequeueBuffer(Source source,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t VirtualDisplaySurface::dequeueBuffer(int* pslot, sp<Fence>* fence,
|
status_t VirtualDisplaySurface::dequeueBuffer(int* pslot, sp<Fence>* fence, bool async,
|
||||||
uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
|
uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
|
||||||
VDS_LOGW_IF(mDbgState != DBG_STATE_PREPARED,
|
VDS_LOGW_IF(mDbgState != DBG_STATE_PREPARED,
|
||||||
"Unexpected dequeueBuffer() in %s state", dbgStateStr());
|
"Unexpected dequeueBuffer() in %s state", dbgStateStr());
|
||||||
@ -273,7 +273,7 @@ status_t VirtualDisplaySurface::dequeueBuffer(int* pslot, sp<Fence>* fence,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int sslot;
|
int sslot;
|
||||||
status_t result = dequeueBuffer(source, format, &sslot, fence);
|
status_t result = dequeueBuffer(source, format, &sslot, fence, async);
|
||||||
if (result >= 0) {
|
if (result >= 0) {
|
||||||
*pslot = mapSource2ProducerSlot(source, sslot);
|
*pslot = mapSource2ProducerSlot(source, sslot);
|
||||||
}
|
}
|
||||||
@ -321,8 +321,9 @@ status_t VirtualDisplaySurface::queueBuffer(int pslot,
|
|||||||
Rect crop;
|
Rect crop;
|
||||||
int scalingMode;
|
int scalingMode;
|
||||||
uint32_t transform;
|
uint32_t transform;
|
||||||
|
bool async;
|
||||||
input.deflate(×tamp, &crop, &scalingMode, &transform,
|
input.deflate(×tamp, &crop, &scalingMode, &transform,
|
||||||
&mFbFence);
|
&async, &mFbFence);
|
||||||
|
|
||||||
mFbProducerSlot = pslot;
|
mFbProducerSlot = pslot;
|
||||||
}
|
}
|
||||||
@ -345,13 +346,10 @@ int VirtualDisplaySurface::query(int what, int* value) {
|
|||||||
return mSource[SOURCE_SINK]->query(what, value);
|
return mSource[SOURCE_SINK]->query(what, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t VirtualDisplaySurface::setSynchronousMode(bool enabled) {
|
status_t VirtualDisplaySurface::connect(int api, bool producerControlledByApp,
|
||||||
return mSource[SOURCE_SINK]->setSynchronousMode(enabled);
|
QueueBufferOutput* output) {
|
||||||
}
|
|
||||||
|
|
||||||
status_t VirtualDisplaySurface::connect(int api, QueueBufferOutput* output) {
|
|
||||||
QueueBufferOutput qbo;
|
QueueBufferOutput qbo;
|
||||||
status_t result = mSource[SOURCE_SINK]->connect(api, &qbo);
|
status_t result = mSource[SOURCE_SINK]->connect(api, producerControlledByApp, &qbo);
|
||||||
if (result == NO_ERROR) {
|
if (result == NO_ERROR) {
|
||||||
updateQueueBufferOutput(qbo);
|
updateQueueBufferOutput(qbo);
|
||||||
*output = mQueueBufferOutput;
|
*output = mQueueBufferOutput;
|
||||||
|
@ -95,14 +95,13 @@ private:
|
|||||||
//
|
//
|
||||||
virtual status_t requestBuffer(int pslot, sp<GraphicBuffer>* outBuf);
|
virtual status_t requestBuffer(int pslot, sp<GraphicBuffer>* outBuf);
|
||||||
virtual status_t setBufferCount(int bufferCount);
|
virtual status_t setBufferCount(int bufferCount);
|
||||||
virtual status_t dequeueBuffer(int* pslot, sp<Fence>* fence,
|
virtual status_t dequeueBuffer(int* pslot, sp<Fence>* fence, bool async,
|
||||||
uint32_t w, uint32_t h, uint32_t format, uint32_t usage);
|
uint32_t w, uint32_t h, uint32_t format, uint32_t usage);
|
||||||
virtual status_t queueBuffer(int pslot,
|
virtual status_t queueBuffer(int pslot,
|
||||||
const QueueBufferInput& input, QueueBufferOutput* output);
|
const QueueBufferInput& input, QueueBufferOutput* output);
|
||||||
virtual void cancelBuffer(int pslot, const sp<Fence>& fence);
|
virtual void cancelBuffer(int pslot, const sp<Fence>& fence);
|
||||||
virtual int query(int what, int* value);
|
virtual int query(int what, int* value);
|
||||||
virtual status_t setSynchronousMode(bool enabled);
|
virtual status_t connect(int api, bool producerControlledByApp, QueueBufferOutput* output);
|
||||||
virtual status_t connect(int api, QueueBufferOutput* output);
|
|
||||||
virtual status_t disconnect(int api);
|
virtual status_t disconnect(int api);
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -110,7 +109,7 @@ private:
|
|||||||
//
|
//
|
||||||
static Source fbSourceForCompositionType(CompositionType type);
|
static Source fbSourceForCompositionType(CompositionType type);
|
||||||
status_t dequeueBuffer(Source source, uint32_t format,
|
status_t dequeueBuffer(Source source, uint32_t format,
|
||||||
int* sslot, sp<Fence>* fence);
|
int* sslot, sp<Fence>* fence, bool async);
|
||||||
void updateQueueBufferOutput(const QueueBufferOutput& qbo);
|
void updateQueueBufferOutput(const QueueBufferOutput& qbo);
|
||||||
void resetPerFrameState();
|
void resetPerFrameState();
|
||||||
|
|
||||||
|
@ -115,7 +115,6 @@ void Layer::onFirstRef()
|
|||||||
|
|
||||||
mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
|
mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
|
||||||
mSurfaceFlingerConsumer->setFrameAvailableListener(this);
|
mSurfaceFlingerConsumer->setFrameAvailableListener(this);
|
||||||
mSurfaceFlingerConsumer->setSynchronousMode(true);
|
|
||||||
mSurfaceFlingerConsumer->setName(mName);
|
mSurfaceFlingerConsumer->setName(mName);
|
||||||
|
|
||||||
#ifdef TARGET_DISABLE_TRIPLE_BUFFERING
|
#ifdef TARGET_DISABLE_TRIPLE_BUFFERING
|
||||||
|
@ -28,7 +28,7 @@ namespace android {
|
|||||||
|
|
||||||
|
|
||||||
SurfaceTextureLayer::SurfaceTextureLayer(const sp<SurfaceFlinger>& flinger)
|
SurfaceTextureLayer::SurfaceTextureLayer(const sp<SurfaceFlinger>& flinger)
|
||||||
: BufferQueue(true), flinger(flinger) {
|
: BufferQueue(), flinger(flinger) {
|
||||||
}
|
}
|
||||||
|
|
||||||
SurfaceTextureLayer::~SurfaceTextureLayer() {
|
SurfaceTextureLayer::~SurfaceTextureLayer() {
|
||||||
@ -51,32 +51,5 @@ SurfaceTextureLayer::~SurfaceTextureLayer() {
|
|||||||
flinger->postMessageAsync( new MessageCleanUpList(flinger, this) );
|
flinger->postMessageAsync( new MessageCleanUpList(flinger, this) );
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t SurfaceTextureLayer::connect(int api, QueueBufferOutput* output) {
|
|
||||||
status_t err = BufferQueue::connect(api, output);
|
|
||||||
if (err == NO_ERROR) {
|
|
||||||
switch(api) {
|
|
||||||
case NATIVE_WINDOW_API_MEDIA:
|
|
||||||
case NATIVE_WINDOW_API_CAMERA:
|
|
||||||
// Camera preview and videos are rate-limited on the producer
|
|
||||||
// side. If enabled for this build, we use async mode to always
|
|
||||||
// show the most recent frame at the cost of requiring an
|
|
||||||
// additional buffer.
|
|
||||||
#ifndef NEVER_DEFAULT_TO_ASYNC_MODE
|
|
||||||
err = setSynchronousMode(false);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
// fall through to set synchronous mode when not defaulting to
|
|
||||||
// async mode.
|
|
||||||
default:
|
|
||||||
err = setSynchronousMode(true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (err != NO_ERROR) {
|
|
||||||
disconnect(api);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
}; // namespace android
|
}; // namespace android
|
||||||
|
@ -38,10 +38,6 @@ class SurfaceTextureLayer : public BufferQueue {
|
|||||||
public:
|
public:
|
||||||
SurfaceTextureLayer(const sp<SurfaceFlinger>& flinger);
|
SurfaceTextureLayer(const sp<SurfaceFlinger>& flinger);
|
||||||
virtual ~SurfaceTextureLayer();
|
virtual ~SurfaceTextureLayer();
|
||||||
|
|
||||||
// After calling the superclass connect(), set or clear synchronous
|
|
||||||
// mode appropriately for the specified API.
|
|
||||||
virtual status_t connect(int api, QueueBufferOutput* output);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
Loading…
Reference in New Issue
Block a user