29a3e90879
This adds an allocateBuffers method to BufferQueue, which instructs it to allocate up to the maximum number of buffers allowed by the current configuration. The goal is that this method can be called ahead of render time, which will prevent dequeueBuffers from blocking in allocation and inducing jank. This interface is also plumbed up to the native Surface (and, in another change, up to the Java Surface and ThreadedRenderer). Bug: 11792166 Change-Id: I4aa96b4351ea1c95ed5db228ca3ef98303229c74
462 lines
22 KiB
C++
462 lines
22 KiB
C++
/*
|
|
* Copyright (C) 2010 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#ifndef ANDROID_GUI_IGRAPHICBUFFERPRODUCER_H
|
|
#define ANDROID_GUI_IGRAPHICBUFFERPRODUCER_H
|
|
|
|
#include <stdint.h>
|
|
#include <sys/types.h>
|
|
|
|
#include <utils/Errors.h>
|
|
#include <utils/RefBase.h>
|
|
|
|
#include <binder/IInterface.h>
|
|
|
|
#include <ui/Fence.h>
|
|
#include <ui/GraphicBuffer.h>
|
|
#include <ui/Rect.h>
|
|
|
|
namespace android {
|
|
// ----------------------------------------------------------------------------
|
|
|
|
class IProducerListener;
|
|
class NativeHandle;
|
|
class Surface;
|
|
|
|
/*
|
|
* This class defines the Binder IPC interface for the producer side of
|
|
* a queue of graphics buffers. It's used to send graphics data from one
|
|
* component to another. For example, a class that decodes video for
|
|
* playback might use this to provide frames. This is typically done
|
|
* indirectly, through Surface.
|
|
*
|
|
* The underlying mechanism is a BufferQueue, which implements
|
|
* BnGraphicBufferProducer. In normal operation, the producer calls
|
|
* dequeueBuffer() to get an empty buffer, fills it with data, then
|
|
* calls queueBuffer() to make it available to the consumer.
|
|
*
|
|
* This class was previously called ISurfaceTexture.
|
|
*/
|
|
class IGraphicBufferProducer : public IInterface
|
|
{
|
|
public:
|
|
DECLARE_META_INTERFACE(GraphicBufferProducer);
|
|
|
|
enum {
|
|
// A flag returned by dequeueBuffer when the client needs to call
|
|
// requestBuffer immediately thereafter.
|
|
BUFFER_NEEDS_REALLOCATION = 0x1,
|
|
// A flag returned by dequeueBuffer when all mirrored slots should be
|
|
// released by the client. This flag should always be processed first.
|
|
RELEASE_ALL_BUFFERS = 0x2,
|
|
};
|
|
|
|
// requestBuffer requests a new buffer for the given index. The server (i.e.
|
|
// the IGraphicBufferProducer implementation) assigns the newly created
|
|
// buffer to the given slot index, and the client is expected to mirror the
|
|
// slot->buffer mapping so that it's not necessary to transfer a
|
|
// GraphicBuffer for every dequeue operation.
|
|
//
|
|
// The slot must be in the range of [0, NUM_BUFFER_SLOTS).
|
|
//
|
|
// Return of a value other than NO_ERROR means an error has occurred:
|
|
// * NO_INIT - the buffer queue has been abandoned.
|
|
// * BAD_VALUE - one of the two conditions occurred:
|
|
// * slot was out of range (see above)
|
|
// * buffer specified by the slot is not dequeued
|
|
virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) = 0;
|
|
|
|
// setBufferCount sets the number of buffer slots available. Calling this
|
|
// will also cause all buffer slots to be emptied. The caller should empty
|
|
// its mirrored copy of the buffer slots when calling this method.
|
|
//
|
|
// This function should not be called when there are any dequeued buffer
|
|
// slots, doing so will result in a BAD_VALUE error returned.
|
|
//
|
|
// The buffer count should be at most NUM_BUFFER_SLOTS (inclusive), but at least
|
|
// the minimum undequeued buffer count (exclusive). The minimum value
|
|
// can be obtained by calling query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS).
|
|
// In particular the range is (minUndequeudBuffers, NUM_BUFFER_SLOTS].
|
|
//
|
|
// The buffer count may also be set to 0 (the default), to indicate that
|
|
// the producer does not wish to set a value.
|
|
//
|
|
// Return of a value other than NO_ERROR means an error has occurred:
|
|
// * NO_INIT - the buffer queue has been abandoned.
|
|
// * BAD_VALUE - one of the below conditions occurred:
|
|
// * bufferCount was out of range (see above)
|
|
// * client has one or more buffers dequeued
|
|
virtual status_t setBufferCount(int bufferCount) = 0;
|
|
|
|
// dequeueBuffer requests a new buffer slot for the client to use. Ownership
|
|
// of the slot is transfered to the client, meaning that the server will not
|
|
// use the contents of the buffer associated with that slot.
|
|
//
|
|
// The slot index returned may or may not contain a buffer (client-side).
|
|
// If the slot is empty the client should call requestBuffer to assign a new
|
|
// buffer to that slot.
|
|
//
|
|
// Once the client is done filling this buffer, it is expected to transfer
|
|
// buffer ownership back to the server with either cancelBuffer on
|
|
// the dequeued slot or to fill in the contents of its associated buffer
|
|
// contents and call queueBuffer.
|
|
//
|
|
// If dequeueBuffer returns the BUFFER_NEEDS_REALLOCATION flag, the client is
|
|
// expected to call requestBuffer immediately.
|
|
//
|
|
// If dequeueBuffer returns the RELEASE_ALL_BUFFERS flag, the client is
|
|
// expected to release all of the mirrored slot->buffer mappings.
|
|
//
|
|
// The fence parameter will be updated to hold the fence associated with
|
|
// the buffer. The contents of the buffer must not be overwritten until the
|
|
// fence signals. If the fence is Fence::NO_FENCE, the buffer may be written
|
|
// immediately.
|
|
//
|
|
// The async parameter sets whether we're in asynchronous mode for this
|
|
// dequeueBuffer() call.
|
|
//
|
|
// The width and height parameters must be no greater than the minimum of
|
|
// GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see: glGetIntegerv).
|
|
// An error due to invalid dimensions might not be reported until
|
|
// updateTexImage() is called. If width and height are both zero, the
|
|
// default values specified by setDefaultBufferSize() are used instead.
|
|
//
|
|
// The pixel formats are enumerated in <graphics.h>, e.g.
|
|
// HAL_PIXEL_FORMAT_RGBA_8888. If the format is 0, the default format
|
|
// will be used.
|
|
//
|
|
// The usage argument specifies gralloc buffer usage flags. The values
|
|
// are enumerated in <gralloc.h>, e.g. GRALLOC_USAGE_HW_RENDER. These
|
|
// will be merged with the usage flags specified by
|
|
// IGraphicBufferConsumer::setConsumerUsageBits.
|
|
//
|
|
// This call will block until a buffer is available to be dequeued. If
|
|
// both the producer and consumer are controlled by the app, then this call
|
|
// can never block and will return WOULD_BLOCK if no buffer is available.
|
|
//
|
|
// A non-negative value with flags set (see above) will be returned upon
|
|
// success.
|
|
//
|
|
// Return of a negative means an error has occurred:
|
|
// * NO_INIT - the buffer queue has been abandoned.
|
|
// * BAD_VALUE - both in async mode and buffer count was less than the
|
|
// max numbers of buffers that can be allocated at once.
|
|
// * INVALID_OPERATION - cannot attach the buffer because it would cause
|
|
// too many buffers to be dequeued, either because
|
|
// the producer already has a single buffer dequeued
|
|
// and did not set a buffer count, or because a
|
|
// buffer count was set and this call would cause
|
|
// it to be exceeded.
|
|
// * WOULD_BLOCK - no buffer is currently available, and blocking is disabled
|
|
// since both the producer/consumer are controlled by app
|
|
// * NO_MEMORY - out of memory, cannot allocate the graphics buffer.
|
|
//
|
|
// All other negative values are an unknown error returned downstream
|
|
// from the graphics allocator (typically errno).
|
|
virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence, bool async,
|
|
uint32_t w, uint32_t h, uint32_t format, uint32_t usage) = 0;
|
|
|
|
// detachBuffer attempts to remove all ownership of the buffer in the given
|
|
// slot from the buffer queue. If this call succeeds, the slot will be
|
|
// freed, and there will be no way to obtain the buffer from this interface.
|
|
// The freed slot will remain unallocated until either it is selected to
|
|
// hold a freshly allocated buffer in dequeueBuffer or a buffer is attached
|
|
// to the slot. The buffer must have already been dequeued, and the caller
|
|
// must already possesses the sp<GraphicBuffer> (i.e., must have called
|
|
// requestBuffer).
|
|
//
|
|
// Return of a value other than NO_ERROR means an error has occurred:
|
|
// * NO_INIT - the buffer queue has been abandoned.
|
|
// * BAD_VALUE - the given slot number is invalid, either because it is
|
|
// out of the range [0, NUM_BUFFER_SLOTS), or because the slot
|
|
// it refers to is not currently dequeued and requested.
|
|
virtual status_t detachBuffer(int slot) = 0;
|
|
|
|
// detachNextBuffer is equivalent to calling dequeueBuffer, requestBuffer,
|
|
// and detachBuffer in sequence, except for two things:
|
|
//
|
|
// 1) It is unnecessary to know the dimensions, format, or usage of the
|
|
// next buffer.
|
|
// 2) It will not block, since if it cannot find an appropriate buffer to
|
|
// return, it will return an error instead.
|
|
//
|
|
// Only slots that are free but still contain a GraphicBuffer will be
|
|
// considered, and the oldest of those will be returned. outBuffer is
|
|
// equivalent to outBuffer from the requestBuffer call, and outFence is
|
|
// equivalent to fence from the dequeueBuffer call.
|
|
//
|
|
// Return of a value other than NO_ERROR means an error has occurred:
|
|
// * NO_INIT - the buffer queue has been abandoned.
|
|
// * BAD_VALUE - either outBuffer or outFence were NULL.
|
|
// * NO_MEMORY - no slots were found that were both free and contained a
|
|
// GraphicBuffer.
|
|
virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer,
|
|
sp<Fence>* outFence) = 0;
|
|
|
|
// attachBuffer attempts to transfer ownership of a buffer to the buffer
|
|
// queue. If this call succeeds, it will be as if this buffer was dequeued
|
|
// from the returned slot number. As such, this call will fail if attaching
|
|
// this buffer would cause too many buffers to be simultaneously dequeued.
|
|
//
|
|
// If attachBuffer returns the RELEASE_ALL_BUFFERS flag, the caller is
|
|
// expected to release all of the mirrored slot->buffer mappings.
|
|
//
|
|
// A non-negative value with flags set (see above) will be returned upon
|
|
// success.
|
|
//
|
|
// Return of a negative value means an error has occurred:
|
|
// * NO_INIT - the buffer queue has been abandoned.
|
|
// * BAD_VALUE - outSlot or buffer were NULL or invalid combination of
|
|
// async mode and buffer count override.
|
|
// * INVALID_OPERATION - cannot attach the buffer because it would cause
|
|
// too many buffers to be dequeued, either because
|
|
// the producer already has a single buffer dequeued
|
|
// and did not set a buffer count, or because a
|
|
// buffer count was set and this call would cause
|
|
// it to be exceeded.
|
|
// * WOULD_BLOCK - no buffer slot is currently available, and blocking is
|
|
// disabled since both the producer/consumer are
|
|
// controlled by the app.
|
|
virtual status_t attachBuffer(int* outSlot,
|
|
const sp<GraphicBuffer>& buffer) = 0;
|
|
|
|
// queueBuffer indicates that the client has finished filling in the
|
|
// contents of the buffer associated with slot and transfers ownership of
|
|
// that slot back to the server.
|
|
//
|
|
// It is not valid to call queueBuffer on a slot that is not owned
|
|
// by the client or one for which a buffer associated via requestBuffer
|
|
// (an attempt to do so will fail with a return value of BAD_VALUE).
|
|
//
|
|
// In addition, the input must be described by the client (as documented
|
|
// below). Any other properties (zero point, etc)
|
|
// are client-dependent, and should be documented by the client.
|
|
//
|
|
// The slot must be in the range of [0, NUM_BUFFER_SLOTS).
|
|
//
|
|
// Upon success, the output will be filled with meaningful values
|
|
// (refer to the documentation below).
|
|
//
|
|
// Return of a value other than NO_ERROR means an error has occurred:
|
|
// * NO_INIT - the buffer queue has been abandoned.
|
|
// * BAD_VALUE - one of the below conditions occurred:
|
|
// * fence was NULL
|
|
// * scaling mode was unknown
|
|
// * both in async mode and buffer count was less than the
|
|
// max numbers of buffers that can be allocated at once
|
|
// * slot index was out of range (see above).
|
|
// * the slot was not in the dequeued state
|
|
// * the slot was enqueued without requesting a buffer
|
|
// * crop rect is out of bounds of the buffer dimensions
|
|
|
|
struct QueueBufferInput : public Flattenable<QueueBufferInput> {
|
|
friend class Flattenable<QueueBufferInput>;
|
|
inline QueueBufferInput(const Parcel& parcel);
|
|
// timestamp - a monotonically increasing value in nanoseconds
|
|
// isAutoTimestamp - if the timestamp was synthesized at queue time
|
|
// crop - a crop rectangle that's used as a hint to the consumer
|
|
// scalingMode - a set of flags from NATIVE_WINDOW_SCALING_* in <window.h>
|
|
// transform - a set of flags from NATIVE_WINDOW_TRANSFORM_* in <window.h>
|
|
// async - if the buffer is queued in asynchronous mode
|
|
// fence - a fence that the consumer must wait on before reading the buffer,
|
|
// set this to Fence::NO_FENCE if the buffer is ready immediately
|
|
inline QueueBufferInput(int64_t timestamp, bool isAutoTimestamp,
|
|
const Rect& crop, int scalingMode, uint32_t transform, bool async,
|
|
const sp<Fence>& fence)
|
|
: timestamp(timestamp), isAutoTimestamp(isAutoTimestamp), crop(crop),
|
|
scalingMode(scalingMode), transform(transform), async(async),
|
|
fence(fence) { }
|
|
inline void deflate(int64_t* outTimestamp, bool* outIsAutoTimestamp,
|
|
Rect* outCrop, int* outScalingMode, uint32_t* outTransform,
|
|
bool* outAsync, sp<Fence>* outFence) const {
|
|
*outTimestamp = timestamp;
|
|
*outIsAutoTimestamp = bool(isAutoTimestamp);
|
|
*outCrop = crop;
|
|
*outScalingMode = scalingMode;
|
|
*outTransform = transform;
|
|
*outAsync = bool(async);
|
|
*outFence = fence;
|
|
}
|
|
|
|
// Flattenable protocol
|
|
size_t getFlattenedSize() const;
|
|
size_t getFdCount() const;
|
|
status_t flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const;
|
|
status_t unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count);
|
|
|
|
private:
|
|
int64_t timestamp;
|
|
int isAutoTimestamp;
|
|
Rect crop;
|
|
int scalingMode;
|
|
uint32_t transform;
|
|
int async;
|
|
sp<Fence> fence;
|
|
};
|
|
|
|
// QueueBufferOutput must be a POD structure
|
|
struct __attribute__ ((__packed__)) QueueBufferOutput {
|
|
inline QueueBufferOutput() { }
|
|
// outWidth - filled with default width applied to the buffer
|
|
// outHeight - filled with default height applied to the buffer
|
|
// outTransformHint - filled with default transform applied to the buffer
|
|
// outNumPendingBuffers - num buffers queued that haven't yet been acquired
|
|
// (counting the currently queued buffer)
|
|
inline void deflate(uint32_t* outWidth,
|
|
uint32_t* outHeight,
|
|
uint32_t* outTransformHint,
|
|
uint32_t* outNumPendingBuffers) const {
|
|
*outWidth = width;
|
|
*outHeight = height;
|
|
*outTransformHint = transformHint;
|
|
*outNumPendingBuffers = numPendingBuffers;
|
|
}
|
|
inline void inflate(uint32_t inWidth, uint32_t inHeight,
|
|
uint32_t inTransformHint, uint32_t inNumPendingBuffers) {
|
|
width = inWidth;
|
|
height = inHeight;
|
|
transformHint = inTransformHint;
|
|
numPendingBuffers = inNumPendingBuffers;
|
|
}
|
|
private:
|
|
uint32_t width;
|
|
uint32_t height;
|
|
uint32_t transformHint;
|
|
uint32_t numPendingBuffers;
|
|
};
|
|
|
|
virtual status_t queueBuffer(int slot,
|
|
const QueueBufferInput& input, QueueBufferOutput* output) = 0;
|
|
|
|
// cancelBuffer indicates that the client does not wish to fill in the
|
|
// buffer associated with slot and transfers ownership of the slot back to
|
|
// the server.
|
|
//
|
|
// The buffer is not queued for use by the consumer.
|
|
//
|
|
// The buffer will not be overwritten until the fence signals. The fence
|
|
// will usually be the one obtained from dequeueBuffer.
|
|
virtual void cancelBuffer(int slot, const sp<Fence>& fence) = 0;
|
|
|
|
// query retrieves some information for this surface
|
|
// 'what' tokens allowed are that of NATIVE_WINDOW_* in <window.h>
|
|
//
|
|
// Return of a value other than NO_ERROR means an error has occurred:
|
|
// * NO_INIT - the buffer queue has been abandoned.
|
|
// * BAD_VALUE - what was out of range
|
|
virtual int query(int what, int* value) = 0;
|
|
|
|
// connect attempts to connect a client API to the IGraphicBufferProducer.
|
|
// This must be called before any other IGraphicBufferProducer methods are
|
|
// called except for getAllocator. A consumer must be already connected.
|
|
//
|
|
// This method will fail if the connect was previously called on the
|
|
// IGraphicBufferProducer and no corresponding disconnect call was made.
|
|
//
|
|
// The listener is an optional binder callback object that can be used if
|
|
// the producer wants to be notified when the consumer releases a buffer
|
|
// back to the BufferQueue. It is also used to detect the death of the
|
|
// producer. If only the latter functionality is desired, there is a
|
|
// DummyProducerListener class in IProducerListener.h that can be used.
|
|
//
|
|
// The api should be one of the NATIVE_WINDOW_API_* values in <window.h>
|
|
//
|
|
// The producerControlledByApp should be set to true if the producer is hosted
|
|
// by an untrusted process (typically app_process-forked processes). If both
|
|
// the producer and the consumer are app-controlled then all buffer queues
|
|
// will operate in async mode regardless of the async flag.
|
|
//
|
|
// Upon success, the output will be filled with meaningful data
|
|
// (refer to QueueBufferOutput documentation above).
|
|
//
|
|
// Return of a value other than NO_ERROR means an error has occurred:
|
|
// * NO_INIT - one of the following occurred:
|
|
// * the buffer queue was abandoned
|
|
// * no consumer has yet connected
|
|
// * BAD_VALUE - one of the following has occurred:
|
|
// * the producer is already connected
|
|
// * api was out of range (see above).
|
|
// * output was NULL.
|
|
// * DEAD_OBJECT - the token is hosted by an already-dead process
|
|
//
|
|
// Additional negative errors may be returned by the internals, they
|
|
// should be treated as opaque fatal unrecoverable errors.
|
|
virtual status_t connect(const sp<IProducerListener>& listener,
|
|
int api, bool producerControlledByApp, QueueBufferOutput* output) = 0;
|
|
|
|
// disconnect attempts to disconnect a client API from the
|
|
// IGraphicBufferProducer. Calling this method will cause any subsequent
|
|
// calls to other IGraphicBufferProducer methods to fail except for
|
|
// getAllocator and connect. Successfully calling connect after this will
|
|
// allow the other methods to succeed again.
|
|
//
|
|
// This method will fail if the the IGraphicBufferProducer is not currently
|
|
// connected to the specified client API.
|
|
//
|
|
// The api should be one of the NATIVE_WINDOW_API_* values in <window.h>
|
|
//
|
|
// Disconnecting from an abandoned IGraphicBufferProducer is legal and
|
|
// is considered a no-op.
|
|
//
|
|
// Return of a value other than NO_ERROR means an error has occurred:
|
|
// * BAD_VALUE - one of the following has occurred:
|
|
// * the api specified does not match the one that was connected
|
|
// * api was out of range (see above).
|
|
// * DEAD_OBJECT - the token is hosted by an already-dead process
|
|
virtual status_t disconnect(int api) = 0;
|
|
|
|
// Attaches a sideband buffer stream to the IGraphicBufferProducer.
|
|
//
|
|
// A sideband stream is a device-specific mechanism for passing buffers
|
|
// from the producer to the consumer without using dequeueBuffer/
|
|
// queueBuffer. If a sideband stream is present, the consumer can choose
|
|
// whether to acquire buffers from the sideband stream or from the queued
|
|
// buffers.
|
|
//
|
|
// Passing NULL or a different stream handle will detach the previous
|
|
// handle if any.
|
|
virtual status_t setSidebandStream(const sp<NativeHandle>& stream) = 0;
|
|
|
|
// Allocates buffers based on the given dimensions/format.
|
|
//
|
|
// This function will allocate up to the maximum number of buffers
|
|
// permitted by the current BufferQueue configuration. It will use the
|
|
// given format, dimensions, and usage bits, which are interpreted in the
|
|
// same way as for dequeueBuffer, and the async flag must be set the same
|
|
// way as for dequeueBuffer to ensure that the correct number of buffers are
|
|
// allocated. This is most useful to avoid an allocation delay during
|
|
// dequeueBuffer. If there are already the maximum number of buffers
|
|
// allocated, this function has no effect.
|
|
virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,
|
|
uint32_t format, uint32_t usage) = 0;
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
class BnGraphicBufferProducer : public BnInterface<IGraphicBufferProducer>
|
|
{
|
|
public:
|
|
virtual status_t onTransact( uint32_t code,
|
|
const Parcel& data,
|
|
Parcel* reply,
|
|
uint32_t flags = 0);
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------
|
|
}; // namespace android
|
|
|
|
#endif // ANDROID_GUI_IGRAPHICBUFFERPRODUCER_H
|