6b9454d1fe
Currently, SurfaceFlinger is very dumb about how it handles buffer updates at less than 60fps. If there is a new frame pending, but its timestamp says not to present it until later SurfaceFlinger will wake up every vsync until it is time to present it. Even worse, if SurfaceFlinger has woken up but nothing has changed, it still goes through the entire composition process. This change (mostly) fixes that inefficiency. SurfaceFlinger will still wake up every refresh period while there is a new frame pending, but if there is no work to do, it will almost immediately go back to sleep. Bug: 18111837 Change-Id: I7825bacd37f40bf26edcc6a5e0f051dce45291fb
87 lines
3.0 KiB
C++
87 lines
3.0 KiB
C++
/*
|
|
* Copyright (C) 2012 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#ifndef ANDROID_SURFACEFLINGERCONSUMER_H
|
|
#define ANDROID_SURFACEFLINGERCONSUMER_H
|
|
|
|
#include "DispSync.h"
|
|
#include <gui/GLConsumer.h>
|
|
|
|
namespace android {
|
|
// ----------------------------------------------------------------------------
|
|
|
|
/*
|
|
* This is a thin wrapper around GLConsumer.
|
|
*/
|
|
class SurfaceFlingerConsumer : public GLConsumer {
|
|
public:
|
|
struct ContentsChangedListener: public FrameAvailableListener {
|
|
virtual void onSidebandStreamChanged() = 0;
|
|
};
|
|
|
|
SurfaceFlingerConsumer(const sp<IGraphicBufferConsumer>& consumer,
|
|
uint32_t tex)
|
|
: GLConsumer(consumer, tex, GLConsumer::TEXTURE_EXTERNAL, false, false),
|
|
mTransformToDisplayInverse(false)
|
|
{}
|
|
|
|
class BufferRejecter {
|
|
friend class SurfaceFlingerConsumer;
|
|
virtual bool reject(const sp<GraphicBuffer>& buf,
|
|
const IGraphicBufferConsumer::BufferItem& item) = 0;
|
|
|
|
protected:
|
|
virtual ~BufferRejecter() { }
|
|
};
|
|
|
|
virtual status_t acquireBufferLocked(BufferQueue::BufferItem *item, nsecs_t presentWhen);
|
|
|
|
// This version of updateTexImage() takes a functor that may be used to
|
|
// reject the newly acquired buffer. Unlike the GLConsumer version,
|
|
// this does not guarantee that the buffer has been bound to the GL
|
|
// texture.
|
|
status_t updateTexImage(BufferRejecter* rejecter, const DispSync& dispSync);
|
|
|
|
// See GLConsumer::bindTextureImageLocked().
|
|
status_t bindTextureImage();
|
|
|
|
// must be called from SF main thread
|
|
bool getTransformToDisplayInverse() const;
|
|
|
|
// Sets the contents changed listener. This should be used instead of
|
|
// ConsumerBase::setFrameAvailableListener().
|
|
void setContentsChangedListener(const wp<ContentsChangedListener>& listener);
|
|
|
|
sp<NativeHandle> getSidebandStream() const;
|
|
|
|
nsecs_t computeExpectedPresent(const DispSync& dispSync);
|
|
|
|
private:
|
|
virtual void onSidebandStreamChanged();
|
|
|
|
wp<ContentsChangedListener> mContentsChangedListener;
|
|
|
|
// Indicates this buffer must be transformed by the inverse transform of the screen
|
|
// it is displayed onto. This is applied after GLConsumer::mCurrentTransform.
|
|
// This must be set/read from SurfaceFlinger's main thread.
|
|
bool mTransformToDisplayInverse;
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------
|
|
}; // namespace android
|
|
|
|
#endif // ANDROID_SURFACEFLINGERCONSUMER_H
|