fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2007 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 "SharedBufferStack"
|
|
|
|
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
|
|
|
#include <utils/Debug.h>
|
|
|
|
#include <utils/Log.h>
|
|
|
|
#include <utils/threads.h>
|
|
|
|
|
2010-02-10 01:46:37 +00:00
|
|
|
#include <private/surfaceflinger/SharedBufferStack.h>
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
|
|
|
|
#include <ui/Rect.h>
|
|
|
|
#include <ui/Region.h>
|
|
|
|
|
|
|
|
#define DEBUG_ATOMICS 0
|
|
|
|
|
|
|
|
namespace android {
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
SharedClient::SharedClient()
|
2010-03-19 23:14:13 +00:00
|
|
|
: lock(Mutex::SHARED), cv(Condition::SHARED)
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
SharedClient::~SharedClient() {
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// these functions are used by the clients
|
|
|
|
status_t SharedClient::validate(size_t i) const {
|
2010-05-19 00:06:55 +00:00
|
|
|
if (uint32_t(i) >= uint32_t(SharedBufferStack::NUM_LAYERS_MAX))
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
return BAD_INDEX;
|
|
|
|
return surfaces[i].status;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
SharedBufferStack::SharedBufferStack()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2009-09-11 02:41:18 +00:00
|
|
|
void SharedBufferStack::init(int32_t i)
|
|
|
|
{
|
|
|
|
status = NO_ERROR;
|
|
|
|
identity = i;
|
|
|
|
}
|
|
|
|
|
2010-04-16 01:48:26 +00:00
|
|
|
status_t SharedBufferStack::setCrop(int buffer, const Rect& crop)
|
|
|
|
{
|
|
|
|
if (uint32_t(buffer) >= NUM_BUFFER_MAX)
|
|
|
|
return BAD_INDEX;
|
|
|
|
|
|
|
|
buffers[buffer].crop.l = uint16_t(crop.left);
|
|
|
|
buffers[buffer].crop.t = uint16_t(crop.top);
|
|
|
|
buffers[buffer].crop.r = uint16_t(crop.right);
|
|
|
|
buffers[buffer].crop.b = uint16_t(crop.bottom);
|
|
|
|
return NO_ERROR;
|
|
|
|
}
|
|
|
|
|
2010-08-20 00:01:19 +00:00
|
|
|
status_t SharedBufferStack::setTransform(int buffer, uint8_t transform)
|
|
|
|
{
|
|
|
|
if (uint32_t(buffer) >= NUM_BUFFER_MAX)
|
|
|
|
return BAD_INDEX;
|
|
|
|
buffers[buffer].transform = transform;
|
|
|
|
return NO_ERROR;
|
|
|
|
}
|
|
|
|
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
status_t SharedBufferStack::setDirtyRegion(int buffer, const Region& dirty)
|
|
|
|
{
|
|
|
|
if (uint32_t(buffer) >= NUM_BUFFER_MAX)
|
|
|
|
return BAD_INDEX;
|
|
|
|
|
2010-04-21 22:24:11 +00:00
|
|
|
FlatRegion& reg(buffers[buffer].dirtyRegion);
|
|
|
|
if (dirty.isEmpty()) {
|
|
|
|
reg.count = 0;
|
|
|
|
return NO_ERROR;
|
|
|
|
}
|
|
|
|
|
2010-04-05 23:21:53 +00:00
|
|
|
size_t count;
|
|
|
|
Rect const* r = dirty.getArray(&count);
|
|
|
|
if (count > FlatRegion::NUM_RECT_MAX) {
|
|
|
|
const Rect bounds(dirty.getBounds());
|
|
|
|
reg.count = 1;
|
2010-04-16 01:48:26 +00:00
|
|
|
reg.rects[0].l = uint16_t(bounds.left);
|
|
|
|
reg.rects[0].t = uint16_t(bounds.top);
|
|
|
|
reg.rects[0].r = uint16_t(bounds.right);
|
|
|
|
reg.rects[0].b = uint16_t(bounds.bottom);
|
2010-04-05 23:21:53 +00:00
|
|
|
} else {
|
|
|
|
reg.count = count;
|
|
|
|
for (size_t i=0 ; i<count ; i++) {
|
2010-04-16 01:48:26 +00:00
|
|
|
reg.rects[i].l = uint16_t(r[i].left);
|
|
|
|
reg.rects[i].t = uint16_t(r[i].top);
|
|
|
|
reg.rects[i].r = uint16_t(r[i].right);
|
|
|
|
reg.rects[i].b = uint16_t(r[i].bottom);
|
2010-04-05 23:21:53 +00:00
|
|
|
}
|
|
|
|
}
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
return NO_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
Region SharedBufferStack::getDirtyRegion(int buffer) const
|
|
|
|
{
|
|
|
|
Region res;
|
|
|
|
if (uint32_t(buffer) >= NUM_BUFFER_MAX)
|
|
|
|
return res;
|
|
|
|
|
2010-04-16 01:48:26 +00:00
|
|
|
const FlatRegion& reg(buffers[buffer].dirtyRegion);
|
2010-04-05 23:21:53 +00:00
|
|
|
if (reg.count > FlatRegion::NUM_RECT_MAX)
|
|
|
|
return res;
|
|
|
|
|
|
|
|
if (reg.count == 1) {
|
2010-04-16 01:48:26 +00:00
|
|
|
const Rect r(
|
|
|
|
reg.rects[0].l,
|
|
|
|
reg.rects[0].t,
|
|
|
|
reg.rects[0].r,
|
|
|
|
reg.rects[0].b);
|
|
|
|
res.set(r);
|
2010-04-05 23:21:53 +00:00
|
|
|
} else {
|
|
|
|
for (size_t i=0 ; i<reg.count ; i++) {
|
|
|
|
const Rect r(
|
2010-04-16 01:48:26 +00:00
|
|
|
reg.rects[i].l,
|
|
|
|
reg.rects[i].t,
|
|
|
|
reg.rects[i].r,
|
|
|
|
reg.rects[i].b);
|
2010-04-05 23:21:53 +00:00
|
|
|
res.orSelf(r);
|
|
|
|
}
|
|
|
|
}
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2010-08-20 00:01:19 +00:00
|
|
|
Rect SharedBufferStack::getCrop(int buffer) const
|
|
|
|
{
|
|
|
|
Rect res(-1, -1);
|
|
|
|
if (uint32_t(buffer) >= NUM_BUFFER_MAX)
|
|
|
|
return res;
|
|
|
|
res.left = buffers[buffer].crop.l;
|
|
|
|
res.top = buffers[buffer].crop.t;
|
|
|
|
res.right = buffers[buffer].crop.r;
|
|
|
|
res.bottom = buffers[buffer].crop.b;
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t SharedBufferStack::getTransform(int buffer) const
|
|
|
|
{
|
|
|
|
if (uint32_t(buffer) >= NUM_BUFFER_MAX)
|
|
|
|
return 0;
|
|
|
|
return buffers[buffer].transform;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
SharedBufferBase::SharedBufferBase(SharedClient* sharedClient,
|
2010-05-19 00:06:55 +00:00
|
|
|
int surface, int32_t identity)
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
: mSharedClient(sharedClient),
|
|
|
|
mSharedStack(sharedClient->surfaces + surface),
|
2010-05-19 00:06:55 +00:00
|
|
|
mIdentity(identity)
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
SharedBufferBase::~SharedBufferBase()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2009-10-03 01:12:30 +00:00
|
|
|
status_t SharedBufferBase::getStatus() const
|
|
|
|
{
|
|
|
|
SharedBufferStack& stack( *mSharedStack );
|
|
|
|
return stack.status;
|
|
|
|
}
|
|
|
|
|
2010-05-28 21:22:23 +00:00
|
|
|
int32_t SharedBufferBase::getIdentity() const
|
|
|
|
{
|
|
|
|
SharedBufferStack& stack( *mSharedStack );
|
|
|
|
return stack.identity;
|
|
|
|
}
|
|
|
|
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
String8 SharedBufferBase::dump(char const* prefix) const
|
|
|
|
{
|
|
|
|
const size_t SIZE = 1024;
|
|
|
|
char buffer[SIZE];
|
|
|
|
String8 result;
|
|
|
|
SharedBufferStack& stack( *mSharedStack );
|
|
|
|
snprintf(buffer, SIZE,
|
2010-05-19 00:06:55 +00:00
|
|
|
"%s[ head=%2d, available=%2d, queued=%2d ] "
|
2011-01-20 02:02:20 +00:00
|
|
|
"reallocMask=%08x, identity=%d, status=%d",
|
2010-05-19 00:06:55 +00:00
|
|
|
prefix, stack.head, stack.available, stack.queued,
|
2011-01-20 02:02:20 +00:00
|
|
|
stack.reallocMask, stack.identity, stack.status);
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
result.append(buffer);
|
2010-05-19 00:06:55 +00:00
|
|
|
result.append("\n");
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2010-04-27 23:41:19 +00:00
|
|
|
status_t SharedBufferBase::waitForCondition(const ConditionBase& condition)
|
|
|
|
{
|
|
|
|
const SharedBufferStack& stack( *mSharedStack );
|
|
|
|
SharedClient& client( *mSharedClient );
|
|
|
|
const nsecs_t TIMEOUT = s2ns(1);
|
|
|
|
const int identity = mIdentity;
|
|
|
|
|
|
|
|
Mutex::Autolock _l(client.lock);
|
|
|
|
while ((condition()==false) &&
|
|
|
|
(stack.identity == identity) &&
|
|
|
|
(stack.status == NO_ERROR))
|
|
|
|
{
|
|
|
|
status_t err = client.cv.waitRelative(client.lock, TIMEOUT);
|
|
|
|
// handle errors and timeouts
|
|
|
|
if (CC_UNLIKELY(err != NO_ERROR)) {
|
|
|
|
if (err == TIMED_OUT) {
|
|
|
|
if (condition()) {
|
|
|
|
LOGE("waitForCondition(%s) timed out (identity=%d), "
|
|
|
|
"but condition is true! We recovered but it "
|
|
|
|
"shouldn't happen." , condition.name(), stack.identity);
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
LOGW("waitForCondition(%s) timed out "
|
|
|
|
"(identity=%d, status=%d). "
|
|
|
|
"CPU may be pegged. trying again.", condition.name(),
|
|
|
|
stack.identity, stack.status);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
LOGE("waitForCondition(%s) error (%s) ",
|
|
|
|
condition.name(), strerror(-err));
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (stack.identity != mIdentity) ? status_t(BAD_INDEX) : stack.status;
|
|
|
|
}
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
// ============================================================================
|
|
|
|
// conditions and updates
|
|
|
|
// ============================================================================
|
|
|
|
|
|
|
|
SharedBufferClient::DequeueCondition::DequeueCondition(
|
|
|
|
SharedBufferClient* sbc) : ConditionBase(sbc) {
|
|
|
|
}
|
2010-04-27 23:41:19 +00:00
|
|
|
bool SharedBufferClient::DequeueCondition::operator()() const {
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
return stack.available > 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
SharedBufferClient::LockCondition::LockCondition(
|
|
|
|
SharedBufferClient* sbc, int buf) : ConditionBase(sbc), buf(buf) {
|
|
|
|
}
|
2010-04-27 23:41:19 +00:00
|
|
|
bool SharedBufferClient::LockCondition::operator()() const {
|
2010-04-30 19:59:21 +00:00
|
|
|
// NOTE: if stack.head is messed up, we could crash the client
|
|
|
|
// or cause some drawing artifacts. This is okay, as long as it is
|
|
|
|
// limited to the client.
|
fix [3361121] hang in glClear() - device unresponsive, OTA fails
Generally we never want to lock a buffer for write access if it is at
the "head" on the surfaceflinger side. The only exception (1) is when
the buffer is not currently in use AND there is at least one queued
buffer -- in which case, SurfaceFlinger will never use said buffer
anymore, because on the next composition around, it will be able to
retire the first queued buffer.
The logic above relies on SurfaceFlinger always retiring
and locking a buffer before composition -- unfortunately this
didn't happen during a screenshot.
This could leave us in a situation where a buffer is locked by the
application for write, and used by SurfaceFlinger for texturing,
causing a hang.
Here, we fix this issue by never assuming the exception (1), it was
intended as an optimization allowing ANativeWindow::lockBuffer() to
return sooner and was justified when most of SF composition was
done in software. The actual buffer locking is now ensured by
gralloc. We could have handled screenshots in a similar way to
a regular composition, but it could have caused glitches on screen,
essentially, taking a screenshot could cause to skip a frame.
Change-Id: I1f226b1ebdf6918439b687c2723955d55b842c55
2011-01-18 23:51:30 +00:00
|
|
|
return (buf != stack.index[stack.head]);
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
}
|
|
|
|
|
2010-11-02 18:51:32 +00:00
|
|
|
SharedBufferServer::BuffersAvailableCondition::BuffersAvailableCondition(
|
|
|
|
SharedBufferServer* sbs, int numBuffers) : ConditionBase(sbs),
|
|
|
|
mNumBuffers(numBuffers) {
|
|
|
|
}
|
|
|
|
bool SharedBufferServer::BuffersAvailableCondition::operator()() const {
|
|
|
|
return stack.available == mNumBuffers;
|
|
|
|
}
|
|
|
|
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
SharedBufferClient::QueueUpdate::QueueUpdate(SharedBufferBase* sbb)
|
|
|
|
: UpdateBase(sbb) {
|
|
|
|
}
|
|
|
|
ssize_t SharedBufferClient::QueueUpdate::operator()() {
|
|
|
|
android_atomic_inc(&stack.queued);
|
|
|
|
return NO_ERROR;
|
|
|
|
}
|
|
|
|
|
2010-08-27 00:42:27 +00:00
|
|
|
SharedBufferClient::DequeueUpdate::DequeueUpdate(SharedBufferBase* sbb)
|
|
|
|
: UpdateBase(sbb) {
|
|
|
|
}
|
|
|
|
ssize_t SharedBufferClient::DequeueUpdate::operator()() {
|
|
|
|
if (android_atomic_dec(&stack.available) == 0) {
|
|
|
|
LOGW("dequeue probably called from multiple threads!");
|
|
|
|
}
|
|
|
|
return NO_ERROR;
|
|
|
|
}
|
|
|
|
|
2010-10-01 23:22:41 +00:00
|
|
|
SharedBufferClient::CancelUpdate::CancelUpdate(SharedBufferBase* sbb,
|
|
|
|
int tail, int buf)
|
|
|
|
: UpdateBase(sbb), tail(tail), buf(buf) {
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
}
|
2010-10-01 23:22:41 +00:00
|
|
|
ssize_t SharedBufferClient::CancelUpdate::operator()() {
|
|
|
|
stack.index[tail] = buf;
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
android_atomic_inc(&stack.available);
|
|
|
|
return NO_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
SharedBufferServer::RetireUpdate::RetireUpdate(
|
|
|
|
SharedBufferBase* sbb, int numBuffers)
|
|
|
|
: UpdateBase(sbb), numBuffers(numBuffers) {
|
|
|
|
}
|
|
|
|
ssize_t SharedBufferServer::RetireUpdate::operator()() {
|
|
|
|
int32_t head = stack.head;
|
2010-05-19 00:06:55 +00:00
|
|
|
if (uint32_t(head) >= SharedBufferStack::NUM_BUFFER_MAX)
|
2010-04-30 19:59:21 +00:00
|
|
|
return BAD_VALUE;
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
|
|
|
|
// Decrement the number of queued buffers
|
|
|
|
int32_t queued;
|
|
|
|
do {
|
|
|
|
queued = stack.queued;
|
|
|
|
if (queued == 0) {
|
|
|
|
return NOT_ENOUGH_DATA;
|
|
|
|
}
|
|
|
|
} while (android_atomic_cmpxchg(queued, queued-1, &stack.queued));
|
|
|
|
|
|
|
|
// lock the buffer before advancing head, which automatically unlocks
|
|
|
|
// the buffer we preventively locked upon entering this function
|
2010-05-18 01:54:19 +00:00
|
|
|
|
2010-05-07 22:58:44 +00:00
|
|
|
head = (head + 1) % numBuffers;
|
2010-10-01 23:22:41 +00:00
|
|
|
const int8_t headBuf = stack.index[head];
|
|
|
|
stack.headBuf = headBuf;
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
|
2010-05-07 22:58:44 +00:00
|
|
|
// head is only modified here, so we don't need to use cmpxchg
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
android_atomic_write(head, &stack.head);
|
2010-05-07 22:58:44 +00:00
|
|
|
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
// now that head has moved, we can increment the number of available buffers
|
|
|
|
android_atomic_inc(&stack.available);
|
|
|
|
return head;
|
|
|
|
}
|
|
|
|
|
2009-09-10 23:55:13 +00:00
|
|
|
SharedBufferServer::StatusUpdate::StatusUpdate(
|
|
|
|
SharedBufferBase* sbb, status_t status)
|
|
|
|
: UpdateBase(sbb), status(status) {
|
|
|
|
}
|
|
|
|
|
|
|
|
ssize_t SharedBufferServer::StatusUpdate::operator()() {
|
|
|
|
android_atomic_write(status, &stack.status);
|
|
|
|
return NO_ERROR;
|
|
|
|
}
|
|
|
|
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
// ============================================================================
|
|
|
|
|
|
|
|
SharedBufferClient::SharedBufferClient(SharedClient* sharedClient,
|
2009-10-07 02:00:57 +00:00
|
|
|
int surface, int num, int32_t identity)
|
2010-05-19 00:06:55 +00:00
|
|
|
: SharedBufferBase(sharedClient, surface, identity),
|
2010-10-01 23:22:41 +00:00
|
|
|
mNumBuffers(num), tail(0)
|
2009-09-14 22:48:42 +00:00
|
|
|
{
|
2010-04-28 04:08:20 +00:00
|
|
|
SharedBufferStack& stack( *mSharedStack );
|
2009-09-14 22:48:42 +00:00
|
|
|
tail = computeTail();
|
2010-04-28 04:08:20 +00:00
|
|
|
queued_head = stack.head;
|
2009-09-14 22:48:42 +00:00
|
|
|
}
|
|
|
|
|
2010-05-19 00:06:55 +00:00
|
|
|
int32_t SharedBufferClient::computeTail() const
|
|
|
|
{
|
|
|
|
SharedBufferStack& stack( *mSharedStack );
|
|
|
|
return (mNumBuffers + stack.head - stack.available + 1) % mNumBuffers;
|
|
|
|
}
|
|
|
|
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
ssize_t SharedBufferClient::dequeue()
|
|
|
|
{
|
2009-09-12 02:18:20 +00:00
|
|
|
SharedBufferStack& stack( *mSharedStack );
|
|
|
|
|
2010-05-19 00:06:55 +00:00
|
|
|
RWLock::AutoRLock _rd(mLock);
|
|
|
|
|
2009-09-17 08:35:28 +00:00
|
|
|
const nsecs_t dequeueTime = systemTime(SYSTEM_TIME_THREAD);
|
2009-09-12 02:18:20 +00:00
|
|
|
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
//LOGD("[%d] about to dequeue a buffer",
|
|
|
|
// mSharedStack->identity);
|
|
|
|
DequeueCondition condition(this);
|
|
|
|
status_t err = waitForCondition(condition);
|
|
|
|
if (err != NO_ERROR)
|
|
|
|
return ssize_t(err);
|
|
|
|
|
2010-08-27 00:42:27 +00:00
|
|
|
DequeueUpdate update(this);
|
|
|
|
updateCondition( update );
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
|
2010-04-28 04:08:20 +00:00
|
|
|
int dequeued = stack.index[tail];
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
tail = ((tail+1 >= mNumBuffers) ? 0 : tail+1);
|
2010-04-28 04:08:20 +00:00
|
|
|
LOGD_IF(DEBUG_ATOMICS, "dequeued=%d, tail++=%d, %s",
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
dequeued, tail, dump("").string());
|
2009-09-12 02:18:20 +00:00
|
|
|
|
2009-09-17 08:35:28 +00:00
|
|
|
mDequeueTime[dequeued] = dequeueTime;
|
|
|
|
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
return dequeued;
|
|
|
|
}
|
|
|
|
|
|
|
|
status_t SharedBufferClient::undoDequeue(int buf)
|
2010-10-01 23:22:41 +00:00
|
|
|
{
|
|
|
|
return cancel(buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
status_t SharedBufferClient::cancel(int buf)
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
{
|
2010-05-19 00:06:55 +00:00
|
|
|
RWLock::AutoRLock _rd(mLock);
|
|
|
|
|
2010-10-01 23:22:41 +00:00
|
|
|
// calculate the new position of the tail index (essentially tail--)
|
|
|
|
int localTail = (tail + mNumBuffers - 1) % mNumBuffers;
|
|
|
|
CancelUpdate update(this, localTail, buf);
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
status_t err = updateCondition( update );
|
2009-09-14 22:48:42 +00:00
|
|
|
if (err == NO_ERROR) {
|
2010-10-01 23:22:41 +00:00
|
|
|
tail = localTail;
|
2009-09-14 22:48:42 +00:00
|
|
|
}
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
status_t SharedBufferClient::lock(int buf)
|
|
|
|
{
|
2010-05-19 00:06:55 +00:00
|
|
|
RWLock::AutoRLock _rd(mLock);
|
|
|
|
|
2010-04-28 04:08:20 +00:00
|
|
|
SharedBufferStack& stack( *mSharedStack );
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
LockCondition condition(this, buf);
|
2009-09-17 08:35:28 +00:00
|
|
|
status_t err = waitForCondition(condition);
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
status_t SharedBufferClient::queue(int buf)
|
|
|
|
{
|
2010-05-19 00:06:55 +00:00
|
|
|
RWLock::AutoRLock _rd(mLock);
|
|
|
|
|
2010-04-28 04:08:20 +00:00
|
|
|
SharedBufferStack& stack( *mSharedStack );
|
|
|
|
|
2010-05-18 01:54:19 +00:00
|
|
|
queued_head = (queued_head + 1) % mNumBuffers;
|
2010-04-28 04:08:20 +00:00
|
|
|
stack.index[queued_head] = buf;
|
|
|
|
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
QueueUpdate update(this);
|
|
|
|
status_t err = updateCondition( update );
|
|
|
|
LOGD_IF(DEBUG_ATOMICS, "queued=%d, %s", buf, dump("").string());
|
2010-04-28 04:08:20 +00:00
|
|
|
|
2009-09-17 08:35:28 +00:00
|
|
|
const nsecs_t now = systemTime(SYSTEM_TIME_THREAD);
|
|
|
|
stack.stats.totalTime = ns2us(now - mDequeueTime[buf]);
|
2010-11-02 18:51:32 +00:00
|
|
|
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2010-04-28 04:08:20 +00:00
|
|
|
bool SharedBufferClient::needNewBuffer(int buf) const
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
{
|
|
|
|
SharedBufferStack& stack( *mSharedStack );
|
2010-05-21 21:51:33 +00:00
|
|
|
const uint32_t mask = 1<<(31-buf);
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
return (android_atomic_and(~mask, &stack.reallocMask) & mask) != 0;
|
|
|
|
}
|
|
|
|
|
2010-04-28 04:08:20 +00:00
|
|
|
status_t SharedBufferClient::setCrop(int buf, const Rect& crop)
|
2010-04-16 01:48:26 +00:00
|
|
|
{
|
|
|
|
SharedBufferStack& stack( *mSharedStack );
|
2010-04-28 04:08:20 +00:00
|
|
|
return stack.setCrop(buf, crop);
|
2010-04-16 01:48:26 +00:00
|
|
|
}
|
|
|
|
|
2010-08-20 00:01:19 +00:00
|
|
|
status_t SharedBufferClient::setTransform(int buf, uint32_t transform)
|
|
|
|
{
|
|
|
|
SharedBufferStack& stack( *mSharedStack );
|
|
|
|
return stack.setTransform(buf, uint8_t(transform));
|
|
|
|
}
|
|
|
|
|
2010-04-28 04:08:20 +00:00
|
|
|
status_t SharedBufferClient::setDirtyRegion(int buf, const Region& reg)
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
{
|
|
|
|
SharedBufferStack& stack( *mSharedStack );
|
2010-04-28 04:08:20 +00:00
|
|
|
return stack.setDirtyRegion(buf, reg);
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
}
|
|
|
|
|
2010-05-19 00:06:55 +00:00
|
|
|
status_t SharedBufferClient::setBufferCount(
|
|
|
|
int bufferCount, const SetBufferCountCallback& ipc)
|
2010-05-07 22:58:44 +00:00
|
|
|
{
|
2010-05-18 01:54:19 +00:00
|
|
|
SharedBufferStack& stack( *mSharedStack );
|
2010-05-19 00:06:55 +00:00
|
|
|
if (uint32_t(bufferCount) >= SharedBufferStack::NUM_BUFFER_MAX)
|
2010-05-07 22:58:44 +00:00
|
|
|
return BAD_VALUE;
|
2010-05-19 00:06:55 +00:00
|
|
|
|
2010-05-21 21:19:50 +00:00
|
|
|
if (uint32_t(bufferCount) < SharedBufferStack::NUM_BUFFER_MIN)
|
|
|
|
return BAD_VALUE;
|
|
|
|
|
2010-05-19 00:06:55 +00:00
|
|
|
RWLock::AutoWLock _wr(mLock);
|
|
|
|
|
|
|
|
status_t err = ipc(bufferCount);
|
|
|
|
if (err == NO_ERROR) {
|
|
|
|
mNumBuffers = bufferCount;
|
|
|
|
queued_head = (stack.head + stack.queued) % mNumBuffers;
|
2010-11-02 18:51:32 +00:00
|
|
|
tail = computeTail();
|
2010-05-19 00:06:55 +00:00
|
|
|
}
|
|
|
|
return err;
|
2010-05-07 22:58:44 +00:00
|
|
|
}
|
|
|
|
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
SharedBufferServer::SharedBufferServer(SharedClient* sharedClient,
|
2009-09-11 02:41:18 +00:00
|
|
|
int surface, int num, int32_t identity)
|
2010-05-19 00:06:55 +00:00
|
|
|
: SharedBufferBase(sharedClient, surface, identity),
|
|
|
|
mNumBuffers(num)
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
{
|
2009-09-11 02:41:18 +00:00
|
|
|
mSharedStack->init(identity);
|
2010-06-01 22:12:58 +00:00
|
|
|
mSharedStack->token = surface;
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
mSharedStack->head = num-1;
|
|
|
|
mSharedStack->available = num;
|
|
|
|
mSharedStack->queued = 0;
|
|
|
|
mSharedStack->reallocMask = 0;
|
2010-04-16 01:48:26 +00:00
|
|
|
memset(mSharedStack->buffers, 0, sizeof(mSharedStack->buffers));
|
2010-04-28 04:08:20 +00:00
|
|
|
for (int i=0 ; i<num ; i++) {
|
2010-05-07 22:58:44 +00:00
|
|
|
mBufferList.add(i);
|
2010-04-28 04:08:20 +00:00
|
|
|
mSharedStack->index[i] = i;
|
|
|
|
}
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
}
|
|
|
|
|
2010-06-09 02:54:15 +00:00
|
|
|
SharedBufferServer::~SharedBufferServer()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
ssize_t SharedBufferServer::retireAndLock()
|
|
|
|
{
|
2010-05-19 00:06:55 +00:00
|
|
|
RWLock::AutoRLock _l(mLock);
|
|
|
|
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
RetireUpdate update(this, mNumBuffers);
|
|
|
|
ssize_t buf = updateCondition( update );
|
2010-04-28 04:08:20 +00:00
|
|
|
if (buf >= 0) {
|
2010-05-19 00:06:55 +00:00
|
|
|
if (uint32_t(buf) >= SharedBufferStack::NUM_BUFFER_MAX)
|
2010-04-30 19:59:21 +00:00
|
|
|
return BAD_VALUE;
|
2010-04-28 04:08:20 +00:00
|
|
|
SharedBufferStack& stack( *mSharedStack );
|
|
|
|
buf = stack.index[buf];
|
|
|
|
LOGD_IF(DEBUG_ATOMICS && buf>=0, "retire=%d, %s",
|
|
|
|
int(buf), dump("").string());
|
|
|
|
}
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
2009-09-10 23:55:13 +00:00
|
|
|
void SharedBufferServer::setStatus(status_t status)
|
|
|
|
{
|
2009-10-03 01:12:30 +00:00
|
|
|
if (status < NO_ERROR) {
|
|
|
|
StatusUpdate update(this, status);
|
|
|
|
updateCondition( update );
|
|
|
|
}
|
2009-09-10 23:55:13 +00:00
|
|
|
}
|
|
|
|
|
2010-05-22 00:24:35 +00:00
|
|
|
status_t SharedBufferServer::reallocateAll()
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
{
|
2010-05-19 00:06:55 +00:00
|
|
|
RWLock::AutoRLock _l(mLock);
|
|
|
|
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
SharedBufferStack& stack( *mSharedStack );
|
2010-05-21 21:51:33 +00:00
|
|
|
uint32_t mask = mBufferList.getMask();
|
2010-05-22 00:24:35 +00:00
|
|
|
android_atomic_or(mask, &stack.reallocMask);
|
|
|
|
return NO_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
status_t SharedBufferServer::reallocateAllExcept(int buffer)
|
|
|
|
{
|
|
|
|
RWLock::AutoRLock _l(mLock);
|
|
|
|
|
|
|
|
SharedBufferStack& stack( *mSharedStack );
|
|
|
|
BufferList temp(mBufferList);
|
|
|
|
temp.remove(buffer);
|
|
|
|
uint32_t mask = temp.getMask();
|
|
|
|
android_atomic_or(mask, &stack.reallocMask);
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
return NO_ERROR;
|
|
|
|
}
|
|
|
|
|
2009-10-07 23:44:10 +00:00
|
|
|
int32_t SharedBufferServer::getQueuedCount() const
|
|
|
|
{
|
|
|
|
SharedBufferStack& stack( *mSharedStack );
|
|
|
|
return stack.queued;
|
|
|
|
}
|
|
|
|
|
2010-04-28 04:08:20 +00:00
|
|
|
Region SharedBufferServer::getDirtyRegion(int buf) const
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
{
|
|
|
|
SharedBufferStack& stack( *mSharedStack );
|
2010-04-28 04:08:20 +00:00
|
|
|
return stack.getDirtyRegion(buf);
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
}
|
|
|
|
|
2010-08-20 00:01:19 +00:00
|
|
|
Rect SharedBufferServer::getCrop(int buf) const
|
|
|
|
{
|
|
|
|
SharedBufferStack& stack( *mSharedStack );
|
|
|
|
return stack.getCrop(buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t SharedBufferServer::getTransform(int buf) const
|
|
|
|
{
|
|
|
|
SharedBufferStack& stack( *mSharedStack );
|
|
|
|
return stack.getTransform(buf);
|
|
|
|
}
|
|
|
|
|
2010-05-07 22:58:44 +00:00
|
|
|
/*
|
|
|
|
* NOTE: this is not thread-safe on the server-side, meaning
|
|
|
|
* 'head' cannot move during this operation. The client-side
|
|
|
|
* can safely operate an usual.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
status_t SharedBufferServer::resize(int newNumBuffers)
|
|
|
|
{
|
2010-11-02 18:51:32 +00:00
|
|
|
if ((unsigned int)(newNumBuffers) < SharedBufferStack::NUM_BUFFER_MIN ||
|
|
|
|
(unsigned int)(newNumBuffers) > SharedBufferStack::NUM_BUFFER_MAX) {
|
2010-05-07 22:58:44 +00:00
|
|
|
return BAD_VALUE;
|
2010-11-02 18:51:32 +00:00
|
|
|
}
|
2010-05-07 22:58:44 +00:00
|
|
|
|
2010-05-19 00:06:55 +00:00
|
|
|
RWLock::AutoWLock _l(mLock);
|
|
|
|
|
2010-11-02 18:51:32 +00:00
|
|
|
if (newNumBuffers < mNumBuffers) {
|
|
|
|
return shrink(newNumBuffers);
|
|
|
|
} else {
|
|
|
|
return grow(newNumBuffers);
|
|
|
|
}
|
|
|
|
}
|
2010-05-07 22:58:44 +00:00
|
|
|
|
2010-11-02 18:51:32 +00:00
|
|
|
status_t SharedBufferServer::grow(int newNumBuffers)
|
|
|
|
{
|
2010-05-07 22:58:44 +00:00
|
|
|
SharedBufferStack& stack( *mSharedStack );
|
2010-11-02 18:51:32 +00:00
|
|
|
const int numBuffers = mNumBuffers;
|
2010-05-07 22:58:44 +00:00
|
|
|
const int extra = newNumBuffers - numBuffers;
|
|
|
|
|
|
|
|
// read the head, make sure it's valid
|
|
|
|
int32_t head = stack.head;
|
2010-05-19 00:06:55 +00:00
|
|
|
if (uint32_t(head) >= SharedBufferStack::NUM_BUFFER_MAX)
|
2010-05-07 22:58:44 +00:00
|
|
|
return BAD_VALUE;
|
|
|
|
|
|
|
|
int base = numBuffers;
|
|
|
|
int32_t avail = stack.available;
|
|
|
|
int tail = head - avail + 1;
|
2010-05-18 00:27:26 +00:00
|
|
|
|
2010-05-07 22:58:44 +00:00
|
|
|
if (tail >= 0) {
|
|
|
|
int8_t* const index = const_cast<int8_t*>(stack.index);
|
|
|
|
const int nb = numBuffers - head;
|
|
|
|
memmove(&index[head + extra], &index[head], nb);
|
|
|
|
base = head;
|
|
|
|
// move head 'extra' ahead, this doesn't impact stack.index[head];
|
|
|
|
stack.head = head + extra;
|
|
|
|
}
|
|
|
|
stack.available += extra;
|
|
|
|
|
|
|
|
// fill the new free space with unused buffers
|
|
|
|
BufferList::const_iterator curr(mBufferList.free_begin());
|
|
|
|
for (int i=0 ; i<extra ; i++) {
|
2010-05-18 00:27:26 +00:00
|
|
|
stack.index[base+i] = *curr;
|
|
|
|
mBufferList.add(*curr);
|
|
|
|
++curr;
|
2010-05-07 22:58:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
mNumBuffers = newNumBuffers;
|
|
|
|
return NO_ERROR;
|
|
|
|
}
|
|
|
|
|
2010-11-02 18:51:32 +00:00
|
|
|
status_t SharedBufferServer::shrink(int newNumBuffers)
|
|
|
|
{
|
|
|
|
SharedBufferStack& stack( *mSharedStack );
|
|
|
|
|
|
|
|
// Shrinking is only supported if there are no buffers currently dequeued.
|
|
|
|
int32_t avail = stack.available;
|
|
|
|
int32_t queued = stack.queued;
|
|
|
|
if (avail + queued != mNumBuffers) {
|
|
|
|
return INVALID_OPERATION;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Wait for any queued buffers to be displayed.
|
|
|
|
BuffersAvailableCondition condition(this, mNumBuffers);
|
|
|
|
status_t err = waitForCondition(condition);
|
|
|
|
if (err < 0) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reset head to index 0 and make it refer to buffer 0. The same renaming
|
|
|
|
// (head -> 0) is done in the BufferManager.
|
|
|
|
int32_t head = stack.head;
|
|
|
|
int8_t* index = const_cast<int8_t*>(stack.index);
|
|
|
|
for (int8_t i = 0; i < newNumBuffers; i++) {
|
|
|
|
index[i] = i;
|
|
|
|
}
|
|
|
|
stack.head = 0;
|
|
|
|
stack.headBuf = 0;
|
|
|
|
|
|
|
|
// Free the buffers from the end of the list that are no longer needed.
|
|
|
|
for (int i = newNumBuffers; i < mNumBuffers; i++) {
|
|
|
|
mBufferList.remove(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Tell the client to reallocate all the buffers.
|
|
|
|
reallocateAll();
|
|
|
|
|
|
|
|
mNumBuffers = newNumBuffers;
|
|
|
|
stack.available = newNumBuffers;
|
|
|
|
|
|
|
|
return NO_ERROR;
|
|
|
|
}
|
|
|
|
|
2009-09-17 08:35:28 +00:00
|
|
|
SharedBufferStack::Statistics SharedBufferServer::getStats() const
|
|
|
|
{
|
|
|
|
SharedBufferStack& stack( *mSharedStack );
|
|
|
|
return stack.stats;
|
|
|
|
}
|
|
|
|
|
2010-05-07 22:58:44 +00:00
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
status_t SharedBufferServer::BufferList::add(int value)
|
|
|
|
{
|
|
|
|
if (uint32_t(value) >= mCapacity)
|
|
|
|
return BAD_VALUE;
|
|
|
|
uint32_t mask = 1<<(31-value);
|
|
|
|
if (mList & mask)
|
|
|
|
return ALREADY_EXISTS;
|
|
|
|
mList |= mask;
|
|
|
|
return NO_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
status_t SharedBufferServer::BufferList::remove(int value)
|
|
|
|
{
|
|
|
|
if (uint32_t(value) >= mCapacity)
|
|
|
|
return BAD_VALUE;
|
|
|
|
uint32_t mask = 1<<(31-value);
|
|
|
|
if (!(mList & mask))
|
|
|
|
return NAME_NOT_FOUND;
|
|
|
|
mList &= ~mask;
|
|
|
|
return NO_ERROR;
|
|
|
|
}
|
|
|
|
|
2009-09-17 08:35:28 +00:00
|
|
|
|
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up.
The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice.
The main new feature is to be able to dequeue all buffers at once (very important when there are only two).
A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued.
The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time.
eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q
eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
2009-09-07 23:32:45 +00:00
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
}; // namespace android
|