am 438ca07b
: Merge changes I66511c08,Ia051949f,Ic7451365,I5b571a4c into jb-mr2-dev
* commit '438ca07b6ba74235e87bfbd78c94874d8bbde391': Get rid of LayerBase. Make LayerDim a regular Layer instead of a LayerBase fold LayerBaseClient into LayerBase Remove support for ScreenshotLayer
This commit is contained in:
commit
dad8bd33d2
@ -48,9 +48,7 @@ public:
|
||||
eProtectedByDRM = 0x00001000,
|
||||
|
||||
eFXSurfaceNormal = 0x00000000,
|
||||
eFXSurfaceBlur = 0x00010000, // deprecated, same as Dim
|
||||
eFXSurfaceDim = 0x00020000,
|
||||
eFXSurfaceScreenshot= 0x00030000,
|
||||
eFXSurfaceMask = 0x000F0000,
|
||||
};
|
||||
|
||||
|
@ -7,9 +7,7 @@ LOCAL_SRC_FILES:= \
|
||||
EventThread.cpp \
|
||||
FrameTracker.cpp \
|
||||
Layer.cpp \
|
||||
LayerBase.cpp \
|
||||
LayerDim.cpp \
|
||||
LayerScreenshot.cpp \
|
||||
DisplayHardware/FramebufferSurface.cpp \
|
||||
DisplayHardware/HWComposer.cpp \
|
||||
DisplayHardware/PowerHAL.cpp \
|
||||
|
@ -23,7 +23,6 @@
|
||||
|
||||
#include "Client.h"
|
||||
#include "Layer.h"
|
||||
#include "LayerBase.h"
|
||||
#include "SurfaceFlinger.h"
|
||||
|
||||
namespace android {
|
||||
@ -43,7 +42,7 @@ Client::~Client()
|
||||
{
|
||||
const size_t count = mLayers.size();
|
||||
for (size_t i=0 ; i<count ; i++) {
|
||||
sp<LayerBaseClient> layer(mLayers.valueAt(i).promote());
|
||||
sp<Layer> layer(mLayers.valueAt(i).promote());
|
||||
if (layer != 0) {
|
||||
mFlinger->removeLayer(layer);
|
||||
}
|
||||
@ -54,13 +53,13 @@ status_t Client::initCheck() const {
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
void Client::attachLayer(const sp<IBinder>& handle, const sp<LayerBaseClient>& layer)
|
||||
void Client::attachLayer(const sp<IBinder>& handle, const sp<Layer>& layer)
|
||||
{
|
||||
Mutex::Autolock _l(mLock);
|
||||
mLayers.add(handle, layer);
|
||||
}
|
||||
|
||||
void Client::detachLayer(const LayerBaseClient* layer)
|
||||
void Client::detachLayer(const Layer* layer)
|
||||
{
|
||||
Mutex::Autolock _l(mLock);
|
||||
// we do a linear search here, because this doesn't happen often
|
||||
@ -72,11 +71,11 @@ void Client::detachLayer(const LayerBaseClient* layer)
|
||||
}
|
||||
}
|
||||
}
|
||||
sp<LayerBaseClient> Client::getLayerUser(const sp<IBinder>& handle) const
|
||||
sp<Layer> Client::getLayerUser(const sp<IBinder>& handle) const
|
||||
{
|
||||
Mutex::Autolock _l(mLock);
|
||||
sp<LayerBaseClient> lbc;
|
||||
wp<LayerBaseClient> layer(mLayers.valueFor(handle));
|
||||
sp<Layer> lbc;
|
||||
wp<Layer> layer(mLayers.valueFor(handle));
|
||||
if (layer != 0) {
|
||||
lbc = layer.promote();
|
||||
ALOGE_IF(lbc==0, "getLayerUser(name=%p) is dead", handle.get());
|
||||
|
@ -30,7 +30,7 @@ namespace android {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class LayerBaseClient;
|
||||
class Layer;
|
||||
class SurfaceFlinger;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@ -44,11 +44,11 @@ public:
|
||||
status_t initCheck() const;
|
||||
|
||||
// protected by SurfaceFlinger::mStateLock
|
||||
void attachLayer(const sp<IBinder>& handle, const sp<LayerBaseClient>& layer);
|
||||
void attachLayer(const sp<IBinder>& handle, const sp<Layer>& layer);
|
||||
|
||||
void detachLayer(const LayerBaseClient* layer);
|
||||
void detachLayer(const Layer* layer);
|
||||
|
||||
sp<LayerBaseClient> getLayerUser(const sp<IBinder>& handle) const;
|
||||
sp<Layer> getLayerUser(const sp<IBinder>& handle) const;
|
||||
|
||||
private:
|
||||
// ISurfaceComposerClient interface
|
||||
@ -66,7 +66,7 @@ private:
|
||||
sp<SurfaceFlinger> mFlinger;
|
||||
|
||||
// protected by mLock
|
||||
DefaultKeyedVector< wp<IBinder>, wp<LayerBaseClient> > mLayers;
|
||||
DefaultKeyedVector< wp<IBinder>, wp<Layer> > mLayers;
|
||||
|
||||
// thread-safe
|
||||
mutable Mutex mLock;
|
||||
|
@ -42,7 +42,7 @@
|
||||
#include "DisplayDevice.h"
|
||||
#include "GLExtensions.h"
|
||||
#include "SurfaceFlinger.h"
|
||||
#include "LayerBase.h"
|
||||
#include "Layer.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
using namespace android;
|
||||
@ -282,19 +282,19 @@ void DisplayDevice::setViewportAndProjection(const sp<const DisplayDevice>& hw)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void DisplayDevice::setVisibleLayersSortedByZ(const Vector< sp<LayerBase> >& layers) {
|
||||
void DisplayDevice::setVisibleLayersSortedByZ(const Vector< sp<Layer> >& layers) {
|
||||
mVisibleLayersSortedByZ = layers;
|
||||
mSecureLayerVisible = false;
|
||||
size_t count = layers.size();
|
||||
for (size_t i=0 ; i<count ; i++) {
|
||||
const sp<LayerBase>& layer(layers[i]);
|
||||
const sp<Layer>& layer(layers[i]);
|
||||
if (layer->isSecure()) {
|
||||
mSecureLayerVisible = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Vector< sp<LayerBase> >& DisplayDevice::getVisibleLayersSortedByZ() const {
|
||||
const Vector< sp<Layer> >& DisplayDevice::getVisibleLayersSortedByZ() const {
|
||||
return mVisibleLayersSortedByZ;
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,7 @@ namespace android {
|
||||
|
||||
class DisplayInfo;
|
||||
class FramebufferSurface;
|
||||
class LayerBase;
|
||||
class Layer;
|
||||
class SurfaceFlinger;
|
||||
class HWComposer;
|
||||
|
||||
@ -99,8 +99,8 @@ public:
|
||||
|
||||
EGLSurface getEGLSurface() const;
|
||||
|
||||
void setVisibleLayersSortedByZ(const Vector< sp<LayerBase> >& layers);
|
||||
const Vector< sp<LayerBase> >& getVisibleLayersSortedByZ() const;
|
||||
void setVisibleLayersSortedByZ(const Vector< sp<Layer> >& layers);
|
||||
const Vector< sp<Layer> >& getVisibleLayersSortedByZ() const;
|
||||
bool getSecureLayerVisible() const;
|
||||
Region getDirtyRegion(bool repaintEverything) const;
|
||||
|
||||
@ -186,7 +186,7 @@ private:
|
||||
*/
|
||||
|
||||
// list of visible layers on that display
|
||||
Vector< sp<LayerBase> > mVisibleLayersSortedByZ;
|
||||
Vector< sp<Layer> > mVisibleLayersSortedByZ;
|
||||
|
||||
// Whether we have a visible secure layer on this display
|
||||
bool mSecureLayerVisible;
|
||||
|
@ -41,7 +41,6 @@
|
||||
#include <cutils/properties.h>
|
||||
|
||||
#include "Layer.h" // needed only for debugging
|
||||
#include "LayerBase.h"
|
||||
#include "HWComposer.h"
|
||||
#include "SurfaceFlinger.h"
|
||||
#include <utils/CallStack.h>
|
||||
@ -925,7 +924,7 @@ void HWComposer::dump(String8& result, char* buffer, size_t SIZE) const {
|
||||
for (size_t i=0 ; i<mNumDisplays ; i++) {
|
||||
const DisplayData& disp(mDisplayData[i]);
|
||||
|
||||
const Vector< sp<LayerBase> >& visibleLayersSortedByZ =
|
||||
const Vector< sp<Layer> >& visibleLayersSortedByZ =
|
||||
mFlinger->getLayerSortedByZForHwcDisplay(i);
|
||||
|
||||
if (disp.connected) {
|
||||
@ -949,13 +948,11 @@ void HWComposer::dump(String8& result, char* buffer, size_t SIZE) const {
|
||||
String8 name("unknown");
|
||||
|
||||
if (i < visibleLayersSortedByZ.size()) {
|
||||
const sp<LayerBase>& layer(visibleLayersSortedByZ[i]);
|
||||
if (layer->getLayer() != NULL) {
|
||||
const sp<GraphicBuffer>& buffer(
|
||||
layer->getLayer()->getActiveBuffer());
|
||||
if (buffer != NULL) {
|
||||
format = buffer->getPixelFormat();
|
||||
}
|
||||
const sp<Layer>& layer(visibleLayersSortedByZ[i]);
|
||||
const sp<GraphicBuffer>& buffer(
|
||||
layer->getActiveBuffer());
|
||||
if (buffer != NULL) {
|
||||
format = buffer->getPixelFormat();
|
||||
}
|
||||
name = layer->getName();
|
||||
}
|
||||
|
@ -47,7 +47,6 @@ namespace android {
|
||||
|
||||
class GraphicBuffer;
|
||||
class Fence;
|
||||
class LayerBase;
|
||||
class Region;
|
||||
class String8;
|
||||
class SurfaceFlinger;
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <cutils/compiler.h>
|
||||
#include <cutils/native_handle.h>
|
||||
@ -49,37 +50,39 @@ namespace android {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
int32_t Layer::sSequence = 1;
|
||||
|
||||
Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client)
|
||||
: LayerBaseClient(flinger, client),
|
||||
: contentDirty(false),
|
||||
sequence(uint32_t(android_atomic_inc(&sSequence))),
|
||||
mFlinger(flinger),
|
||||
mTextureName(-1U),
|
||||
mPremultipliedAlpha(true),
|
||||
mName("unnamed"),
|
||||
mDebug(false),
|
||||
mFormat(PIXEL_FORMAT_NONE),
|
||||
mGLExtensions(GLExtensions::getInstance()),
|
||||
mOpaqueLayer(true),
|
||||
mTransactionFlags(0),
|
||||
mQueuedFrames(0),
|
||||
mCurrentTransform(0),
|
||||
mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
|
||||
mCurrentOpacity(true),
|
||||
mRefreshPending(false),
|
||||
mFrameLatencyNeeded(false),
|
||||
mFormat(PIXEL_FORMAT_NONE),
|
||||
mGLExtensions(GLExtensions::getInstance()),
|
||||
mOpaqueLayer(true),
|
||||
mFiltering(false),
|
||||
mNeedsFiltering(false),
|
||||
mSecure(false),
|
||||
mProtectedByApp(false)
|
||||
mProtectedByApp(false),
|
||||
mHasSurface(false),
|
||||
mClientRef(client)
|
||||
{
|
||||
mCurrentCrop.makeInvalid();
|
||||
glGenTextures(1, &mTextureName);
|
||||
}
|
||||
|
||||
void Layer::onLayerDisplayed(const sp<const DisplayDevice>& hw,
|
||||
HWComposer::HWCLayerInterface* layer) {
|
||||
LayerBaseClient::onLayerDisplayed(hw, layer);
|
||||
if (layer) {
|
||||
mSurfaceFlingerConsumer->setReleaseFence(layer->getAndResetReleaseFenceFd());
|
||||
}
|
||||
}
|
||||
|
||||
void Layer::onFirstRef()
|
||||
{
|
||||
LayerBaseClient::onFirstRef();
|
||||
|
||||
// Creates a custom BufferQueue for SurfaceFlingerConsumer to use
|
||||
sp<BufferQueue> bq = new SurfaceTextureLayer();
|
||||
mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(mTextureName, true,
|
||||
@ -102,9 +105,25 @@ void Layer::onFirstRef()
|
||||
|
||||
Layer::~Layer()
|
||||
{
|
||||
sp<Client> c(mClientRef.promote());
|
||||
if (c != 0) {
|
||||
c->detachLayer(this);
|
||||
}
|
||||
mFlinger->deleteTextureAsync(mTextureName);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// callbacks
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
void Layer::onLayerDisplayed(const sp<const DisplayDevice>& hw,
|
||||
HWComposer::HWCLayerInterface* layer) {
|
||||
if (layer) {
|
||||
layer->onDisplayed();
|
||||
mSurfaceFlingerConsumer->setReleaseFence(layer->getAndResetReleaseFenceFd());
|
||||
}
|
||||
}
|
||||
|
||||
void Layer::onFrameAvailable() {
|
||||
android_atomic_inc(&mQueuedFrames);
|
||||
mFlinger->signalLayerUpdate();
|
||||
@ -112,56 +131,45 @@ void Layer::onFrameAvailable() {
|
||||
|
||||
// called with SurfaceFlinger::mStateLock as soon as the layer is entered
|
||||
// in the purgatory list
|
||||
void Layer::onRemoved()
|
||||
{
|
||||
void Layer::onRemoved() {
|
||||
mSurfaceFlingerConsumer->abandon();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// set-up
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
void Layer::setName(const String8& name) {
|
||||
LayerBase::setName(name);
|
||||
mName = name;
|
||||
mSurfaceFlingerConsumer->setName(name);
|
||||
}
|
||||
|
||||
sp<ISurface> Layer::createSurface()
|
||||
{
|
||||
/*
|
||||
* This class provides an implementation of BnSurface (the "native" or
|
||||
* "remote" side of the Binder IPC interface ISurface), and mixes in
|
||||
* LayerCleaner to ensure that mFlinger->onLayerDestroyed() is called for
|
||||
* this layer when the BSurface is destroyed.
|
||||
*
|
||||
* The idea is to provide a handle to the Layer through ISurface that
|
||||
* is cleaned up automatically when the last reference to the ISurface
|
||||
* goes away. (The references will be held on the "proxy" side, while
|
||||
* the Layer exists on the "native" side.)
|
||||
*
|
||||
* The Layer has a reference to an instance of SurfaceFlinger's variant
|
||||
* of GLConsumer, which holds a reference to the BufferQueue. The
|
||||
* getSurfaceTexture() call returns a Binder interface reference for
|
||||
* the producer interface of the buffer queue associated with the Layer.
|
||||
*/
|
||||
class BSurface : public BnSurface, public LayerCleaner {
|
||||
wp<const Layer> mOwner;
|
||||
virtual sp<IGraphicBufferProducer> getSurfaceTexture() const {
|
||||
sp<IGraphicBufferProducer> res;
|
||||
sp<const Layer> that( mOwner.promote() );
|
||||
if (that != NULL) {
|
||||
res = that->mSurfaceFlingerConsumer->getBufferQueue();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
public:
|
||||
BSurface(const sp<SurfaceFlinger>& flinger,
|
||||
const sp<Layer>& layer)
|
||||
: LayerCleaner(flinger, layer), mOwner(layer) { }
|
||||
};
|
||||
sp<ISurface> sur(new BSurface(mFlinger, this));
|
||||
return sur;
|
||||
String8 Layer::getName() const {
|
||||
return mName;
|
||||
}
|
||||
|
||||
wp<IBinder> Layer::getSurfaceTextureBinder() const
|
||||
void Layer::initStates(uint32_t w, uint32_t h, uint32_t flags)
|
||||
{
|
||||
return mSurfaceFlingerConsumer->getBufferQueue()->asBinder();
|
||||
uint32_t layerFlags = 0;
|
||||
if (flags & ISurfaceComposerClient::eHidden)
|
||||
layerFlags = layer_state_t::eLayerHidden;
|
||||
|
||||
if (flags & ISurfaceComposerClient::eNonPremultiplied)
|
||||
mPremultipliedAlpha = false;
|
||||
|
||||
mCurrentState.active.w = w;
|
||||
mCurrentState.active.h = h;
|
||||
mCurrentState.active.crop.makeInvalid();
|
||||
mCurrentState.z = 0;
|
||||
mCurrentState.alpha = 0xFF;
|
||||
mCurrentState.layerStack = 0;
|
||||
mCurrentState.flags = layerFlags;
|
||||
mCurrentState.sequence = 0;
|
||||
mCurrentState.transform.set(0, 0);
|
||||
mCurrentState.requested = mCurrentState.active;
|
||||
|
||||
// drawing state & current state are identical
|
||||
mDrawingState = mCurrentState;
|
||||
}
|
||||
|
||||
status_t Layer::setBuffers( uint32_t w, uint32_t h,
|
||||
@ -199,6 +207,63 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h,
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
sp<ISurface> Layer::createSurface() {
|
||||
/*
|
||||
* This class provides an implementation of BnSurface (the "native" or
|
||||
* "remote" side of the Binder IPC interface ISurface), and mixes in
|
||||
* LayerCleaner to ensure that mFlinger->onLayerDestroyed() is called for
|
||||
* this layer when the BSurface is destroyed.
|
||||
*
|
||||
* The idea is to provide a handle to the Layer through ISurface that
|
||||
* is cleaned up automatically when the last reference to the ISurface
|
||||
* goes away. (The references will be held on the "proxy" side, while
|
||||
* the Layer exists on the "native" side.)
|
||||
*
|
||||
* The Layer has a reference to an instance of SurfaceFlinger's variant
|
||||
* of GLConsumer, which holds a reference to the BufferQueue. The
|
||||
* getSurfaceTexture() call returns a Binder interface reference for
|
||||
* the producer interface of the buffer queue associated with the Layer.
|
||||
*/
|
||||
class BSurface : public BnSurface, public LayerCleaner {
|
||||
wp<const Layer> mOwner;
|
||||
virtual sp<IGraphicBufferProducer> getSurfaceTexture() const {
|
||||
sp<IGraphicBufferProducer> res;
|
||||
sp<const Layer> that( mOwner.promote() );
|
||||
if (that != NULL) {
|
||||
res = that->mSurfaceFlingerConsumer->getBufferQueue();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
public:
|
||||
BSurface(const sp<SurfaceFlinger>& flinger,
|
||||
const sp<Layer>& layer)
|
||||
: LayerCleaner(flinger, layer), mOwner(layer) { }
|
||||
};
|
||||
sp<ISurface> sur(new BSurface(mFlinger, this));
|
||||
return sur;
|
||||
}
|
||||
|
||||
wp<IBinder> Layer::getSurfaceTextureBinder() const {
|
||||
return mSurfaceFlingerConsumer->getBufferQueue()->asBinder();
|
||||
}
|
||||
|
||||
sp<ISurface> Layer::getSurface()
|
||||
{
|
||||
sp<ISurface> s;
|
||||
Mutex::Autolock _l(mLock);
|
||||
|
||||
LOG_ALWAYS_FATAL_IF(mHasSurface,
|
||||
"Layer::getSurface() has already been called");
|
||||
|
||||
mHasSurface = true;
|
||||
s = createSurface();
|
||||
return s;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// h/w composer set-up
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Rect Layer::getContentCrop() const {
|
||||
// this is the crop rectangle that applies to the buffer
|
||||
// itself (as opposed to the window)
|
||||
@ -220,11 +285,85 @@ uint32_t Layer::getContentTransform() const {
|
||||
return mCurrentTransform;
|
||||
}
|
||||
|
||||
Rect Layer::computeBounds() const {
|
||||
const Layer::State& s(drawingState());
|
||||
Rect win(s.active.w, s.active.h);
|
||||
if (!s.active.crop.isEmpty()) {
|
||||
win.intersect(s.active.crop, &win);
|
||||
}
|
||||
return win;
|
||||
}
|
||||
|
||||
Rect Layer::computeCrop(const sp<const DisplayDevice>& hw) const {
|
||||
/*
|
||||
* The way we compute the crop (aka. texture coordinates when we have a
|
||||
* Layer) produces a different output from the GL code in
|
||||
* drawWithOpenGL() due to HWC being limited to integers. The difference
|
||||
* can be large if getContentTransform() contains a large scale factor.
|
||||
* See comments in drawWithOpenGL() for more details.
|
||||
*/
|
||||
|
||||
// the content crop is the area of the content that gets scaled to the
|
||||
// layer's size.
|
||||
Rect crop(getContentCrop());
|
||||
|
||||
// the active.crop is the area of the window that gets cropped, but not
|
||||
// scaled in any ways.
|
||||
const State& s(drawingState());
|
||||
|
||||
// apply the projection's clipping to the window crop in
|
||||
// layerstack space, and convert-back to layer space.
|
||||
// if there are no window scaling (or content scaling) involved,
|
||||
// this operation will map to full pixels in the buffer.
|
||||
// NOTE: should we revert to GL composition if a scaling is involved
|
||||
// since it cannot be represented in the HWC API?
|
||||
Rect activeCrop(s.transform.transform(s.active.crop));
|
||||
activeCrop.intersect(hw->getViewport(), &activeCrop);
|
||||
activeCrop = s.transform.inverse().transform(activeCrop);
|
||||
|
||||
// paranoia: make sure the window-crop is constrained in the
|
||||
// window's bounds
|
||||
activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop);
|
||||
|
||||
if (!activeCrop.isEmpty()) {
|
||||
// Transform the window crop to match the buffer coordinate system,
|
||||
// which means using the inverse of the current transform set on the
|
||||
// SurfaceFlingerConsumer.
|
||||
uint32_t invTransform = getContentTransform();
|
||||
int winWidth = s.active.w;
|
||||
int winHeight = s.active.h;
|
||||
if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
|
||||
invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
|
||||
NATIVE_WINDOW_TRANSFORM_FLIP_H;
|
||||
winWidth = s.active.h;
|
||||
winHeight = s.active.w;
|
||||
}
|
||||
const Rect winCrop = activeCrop.transform(
|
||||
invTransform, s.active.w, s.active.h);
|
||||
|
||||
// the code below essentially performs a scaled intersection
|
||||
// of crop and winCrop
|
||||
float xScale = float(crop.width()) / float(winWidth);
|
||||
float yScale = float(crop.height()) / float(winHeight);
|
||||
|
||||
int insetL = int(ceilf( winCrop.left * xScale));
|
||||
int insetT = int(ceilf( winCrop.top * yScale));
|
||||
int insetR = int(ceilf((winWidth - winCrop.right ) * xScale));
|
||||
int insetB = int(ceilf((winHeight - winCrop.bottom) * yScale));
|
||||
|
||||
crop.left += insetL;
|
||||
crop.top += insetT;
|
||||
crop.right -= insetR;
|
||||
crop.bottom -= insetB;
|
||||
}
|
||||
return crop;
|
||||
}
|
||||
|
||||
void Layer::setGeometry(
|
||||
const sp<const DisplayDevice>& hw,
|
||||
HWComposer::HWCLayerInterface& layer)
|
||||
{
|
||||
LayerBaseClient::setGeometry(hw, layer);
|
||||
layer.setDefaultState();
|
||||
|
||||
// enable this layer
|
||||
layer.setSkip(false);
|
||||
@ -233,7 +372,21 @@ void Layer::setGeometry(
|
||||
layer.setSkip(true);
|
||||
}
|
||||
|
||||
// this gives us only the "orientation" component of the transform
|
||||
const State& s(drawingState());
|
||||
if (!isOpaque() || s.alpha != 0xFF) {
|
||||
layer.setBlending(mPremultipliedAlpha ?
|
||||
HWC_BLENDING_PREMULT :
|
||||
HWC_BLENDING_COVERAGE);
|
||||
}
|
||||
|
||||
// apply the layer's transform, followed by the display's global transform
|
||||
// here we're guaranteed that the layer's transform preserves rects
|
||||
Rect frame(s.transform.transform(computeBounds()));
|
||||
frame.intersect(hw->getViewport(), &frame);
|
||||
const Transform& tr(hw->getTransform());
|
||||
layer.setFrame(tr.transform(frame));
|
||||
layer.setCrop(computeCrop(hw));
|
||||
layer.setPlaneAlpha(s.alpha);
|
||||
|
||||
/*
|
||||
@ -245,22 +398,29 @@ void Layer::setGeometry(
|
||||
*/
|
||||
|
||||
const Transform bufferOrientation(mCurrentTransform);
|
||||
const Transform tr(hw->getTransform() * s.transform * bufferOrientation);
|
||||
const Transform transform(tr * s.transform * bufferOrientation);
|
||||
|
||||
// this gives us only the "orientation" component of the transform
|
||||
const uint32_t finalTransform = tr.getOrientation();
|
||||
|
||||
// we can only handle simple transformation
|
||||
if (finalTransform & Transform::ROT_INVALID) {
|
||||
const uint32_t orientation = transform.getOrientation();
|
||||
if (orientation & Transform::ROT_INVALID) {
|
||||
// we can only handle simple transformation
|
||||
layer.setSkip(true);
|
||||
} else {
|
||||
layer.setTransform(finalTransform);
|
||||
layer.setTransform(orientation);
|
||||
}
|
||||
}
|
||||
|
||||
void Layer::setPerFrameData(const sp<const DisplayDevice>& hw,
|
||||
HWComposer::HWCLayerInterface& layer) {
|
||||
LayerBaseClient::setPerFrameData(hw, layer);
|
||||
// we have to set the visible region on every frame because
|
||||
// we currently free it during onLayerDisplayed(), which is called
|
||||
// after HWComposer::commit() -- every frame.
|
||||
// Apply this display's projection's viewport to the visible region
|
||||
// before giving it to the HWC HAL.
|
||||
const Transform& tr = hw->getTransform();
|
||||
Region visible = tr.transform(visibleRegion.intersect(hw->getViewport()));
|
||||
layer.setVisibleRegionScreen(visible);
|
||||
|
||||
// NOTE: buffer can be NULL if the client never drew into this
|
||||
// layer yet, or if we ran out of memory
|
||||
layer.setBuffer(mActiveBuffer);
|
||||
@ -285,6 +445,18 @@ void Layer::setAcquireFence(const sp<const DisplayDevice>& hw,
|
||||
layer.setAcquireFenceFd(fenceFd);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// drawing...
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
void Layer::draw(const sp<const DisplayDevice>& hw, const Region& clip) const {
|
||||
onDraw(hw, clip);
|
||||
}
|
||||
|
||||
void Layer::draw(const sp<const DisplayDevice>& hw) {
|
||||
onDraw( hw, Region(hw->bounds()) );
|
||||
}
|
||||
|
||||
void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const
|
||||
{
|
||||
ATRACE_CALL();
|
||||
@ -304,8 +476,8 @@ void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const
|
||||
mFlinger->mDrawingState.layersSortedByZ);
|
||||
const size_t count = drawingLayers.size();
|
||||
for (size_t i=0 ; i<count ; ++i) {
|
||||
const sp<LayerBase>& layer(drawingLayers[i]);
|
||||
if (layer.get() == static_cast<LayerBase const*>(this))
|
||||
const sp<Layer>& layer(drawingLayers[i]);
|
||||
if (layer.get() == static_cast<Layer const*>(this))
|
||||
break;
|
||||
under.orSelf( hw->getTransform().transform(layer->visibleRegion) );
|
||||
}
|
||||
@ -365,6 +537,119 @@ void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
|
||||
void Layer::clearWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip,
|
||||
GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) const
|
||||
{
|
||||
const uint32_t fbHeight = hw->getHeight();
|
||||
glColor4f(red,green,blue,alpha);
|
||||
|
||||
glDisable(GL_TEXTURE_EXTERNAL_OES);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
LayerMesh mesh;
|
||||
computeGeometry(hw, &mesh);
|
||||
|
||||
glVertexPointer(2, GL_FLOAT, 0, mesh.getVertices());
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, mesh.getVertexCount());
|
||||
}
|
||||
|
||||
void Layer::clearWithOpenGL(
|
||||
const sp<const DisplayDevice>& hw, const Region& clip) const {
|
||||
clearWithOpenGL(hw, clip, 0,0,0,0);
|
||||
}
|
||||
|
||||
void Layer::drawWithOpenGL(
|
||||
const sp<const DisplayDevice>& hw, const Region& clip) const {
|
||||
const uint32_t fbHeight = hw->getHeight();
|
||||
const State& s(drawingState());
|
||||
|
||||
GLenum src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;
|
||||
if (CC_UNLIKELY(s.alpha < 0xFF)) {
|
||||
const GLfloat alpha = s.alpha * (1.0f/255.0f);
|
||||
if (mPremultipliedAlpha) {
|
||||
glColor4f(alpha, alpha, alpha, alpha);
|
||||
} else {
|
||||
glColor4f(1, 1, 1, alpha);
|
||||
}
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
} else {
|
||||
glColor4f(1, 1, 1, 1);
|
||||
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
if (!isOpaque()) {
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
|
||||
} else {
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
}
|
||||
|
||||
LayerMesh mesh;
|
||||
computeGeometry(hw, &mesh);
|
||||
|
||||
// TODO: we probably want to generate the texture coords with the mesh
|
||||
// here we assume that we only have 4 vertices
|
||||
|
||||
struct TexCoords {
|
||||
GLfloat u;
|
||||
GLfloat v;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* NOTE: the way we compute the texture coordinates here produces
|
||||
* different results than when we take the HWC path -- in the later case
|
||||
* the "source crop" is rounded to texel boundaries.
|
||||
* This can produce significantly different results when the texture
|
||||
* is scaled by a large amount.
|
||||
*
|
||||
* The GL code below is more logical (imho), and the difference with
|
||||
* HWC is due to a limitation of the HWC API to integers -- a question
|
||||
* is suspend is wether we should ignore this problem or revert to
|
||||
* GL composition when a buffer scaling is applied (maybe with some
|
||||
* minimal value)? Or, we could make GL behave like HWC -- but this feel
|
||||
* like more of a hack.
|
||||
*/
|
||||
const Rect win(computeBounds());
|
||||
|
||||
GLfloat left = GLfloat(win.left) / GLfloat(s.active.w);
|
||||
GLfloat top = GLfloat(win.top) / GLfloat(s.active.h);
|
||||
GLfloat right = GLfloat(win.right) / GLfloat(s.active.w);
|
||||
GLfloat bottom = GLfloat(win.bottom) / GLfloat(s.active.h);
|
||||
|
||||
TexCoords texCoords[4];
|
||||
texCoords[0].u = left;
|
||||
texCoords[0].v = top;
|
||||
texCoords[1].u = left;
|
||||
texCoords[1].v = bottom;
|
||||
texCoords[2].u = right;
|
||||
texCoords[2].v = bottom;
|
||||
texCoords[3].u = right;
|
||||
texCoords[3].v = top;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
texCoords[i].v = 1.0f - texCoords[i].v;
|
||||
}
|
||||
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
|
||||
glVertexPointer(2, GL_FLOAT, 0, mesh.getVertices());
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, mesh.getVertexCount());
|
||||
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
void Layer::setFiltering(bool filtering) {
|
||||
mFiltering = filtering;
|
||||
}
|
||||
|
||||
bool Layer::getFiltering() const {
|
||||
return mFiltering;
|
||||
}
|
||||
|
||||
// As documented in libhardware header, formats in the range
|
||||
// 0x100 - 0x1FF are specific to the HAL implementation, and
|
||||
// are known to have no alpha channel
|
||||
@ -383,6 +668,29 @@ bool Layer::getOpacityForFormat(uint32_t format)
|
||||
return (err || info.h_alpha <= info.l_alpha);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// local state
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void Layer::computeGeometry(const sp<const DisplayDevice>& hw, LayerMesh* mesh) const
|
||||
{
|
||||
const Layer::State& s(drawingState());
|
||||
const Transform tr(hw->getTransform() * s.transform);
|
||||
const uint32_t hw_h = hw->getHeight();
|
||||
Rect win(s.active.w, s.active.h);
|
||||
if (!s.active.crop.isEmpty()) {
|
||||
win.intersect(s.active.crop, &win);
|
||||
}
|
||||
if (mesh) {
|
||||
tr.transform(mesh->mVertices[0], win.left, win.top);
|
||||
tr.transform(mesh->mVertices[1], win.left, win.bottom);
|
||||
tr.transform(mesh->mVertices[2], win.right, win.bottom);
|
||||
tr.transform(mesh->mVertices[3], win.right, win.top);
|
||||
for (size_t i=0 ; i<4 ; i++) {
|
||||
mesh->mVertices[i][1] = hw_h - mesh->mVertices[i][1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Layer::isOpaque() const
|
||||
{
|
||||
@ -404,8 +712,39 @@ bool Layer::isProtected() const
|
||||
(activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED);
|
||||
}
|
||||
|
||||
uint32_t Layer::doTransaction(uint32_t flags)
|
||||
{
|
||||
bool Layer::isFixedSize() const {
|
||||
return mCurrentScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
|
||||
}
|
||||
|
||||
bool Layer::isCropped() const {
|
||||
return !mCurrentCrop.isEmpty();
|
||||
}
|
||||
|
||||
bool Layer::needsFiltering(const sp<const DisplayDevice>& hw) const {
|
||||
return mNeedsFiltering || hw->needsFiltering();
|
||||
}
|
||||
|
||||
void Layer::setVisibleRegion(const Region& visibleRegion) {
|
||||
// always called from main thread
|
||||
this->visibleRegion = visibleRegion;
|
||||
}
|
||||
|
||||
void Layer::setCoveredRegion(const Region& coveredRegion) {
|
||||
// always called from main thread
|
||||
this->coveredRegion = coveredRegion;
|
||||
}
|
||||
|
||||
void Layer::setVisibleNonTransparentRegion(const Region&
|
||||
setVisibleNonTransparentRegion) {
|
||||
// always called from main thread
|
||||
this->visibleNonTransparentRegion = setVisibleNonTransparentRegion;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// transaction
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
uint32_t Layer::doTransaction(uint32_t flags) {
|
||||
ATRACE_CALL();
|
||||
|
||||
const Layer::State& front(drawingState());
|
||||
@ -464,7 +803,7 @@ uint32_t Layer::doTransaction(uint32_t flags)
|
||||
(temp.requested.h != temp.active.h);
|
||||
|
||||
if (resizePending) {
|
||||
// don't let LayerBase::doTransaction update the drawing state
|
||||
// don't let Layer::doTransaction update the drawing state
|
||||
// if we have a pending resize, unless we are in fixed-size mode.
|
||||
// the drawing state will be updated only once we receive a buffer
|
||||
// with the correct size.
|
||||
@ -477,15 +816,117 @@ uint32_t Layer::doTransaction(uint32_t flags)
|
||||
}
|
||||
}
|
||||
|
||||
return LayerBase::doTransaction(flags);
|
||||
// always set active to requested, unless we're asked not to
|
||||
// this is used by Layer, which special cases resizes.
|
||||
if (flags & eDontUpdateGeometryState) {
|
||||
} else {
|
||||
Layer::State& editTemp(currentState());
|
||||
editTemp.active = temp.requested;
|
||||
}
|
||||
|
||||
if (front.active != temp.active) {
|
||||
// invalidate and recompute the visible regions if needed
|
||||
flags |= Layer::eVisibleRegion;
|
||||
}
|
||||
|
||||
if (temp.sequence != front.sequence) {
|
||||
// invalidate and recompute the visible regions if needed
|
||||
flags |= eVisibleRegion;
|
||||
this->contentDirty = true;
|
||||
|
||||
// we may use linear filtering, if the matrix scales us
|
||||
const uint8_t type = temp.transform.getType();
|
||||
mNeedsFiltering = (!temp.transform.preserveRects() ||
|
||||
(type >= Transform::SCALE));
|
||||
}
|
||||
|
||||
// Commit the transaction
|
||||
commitTransaction();
|
||||
return flags;
|
||||
}
|
||||
|
||||
bool Layer::isFixedSize() const {
|
||||
return mCurrentScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
|
||||
void Layer::commitTransaction() {
|
||||
mDrawingState = mCurrentState;
|
||||
}
|
||||
|
||||
bool Layer::isCropped() const {
|
||||
return !mCurrentCrop.isEmpty();
|
||||
uint32_t Layer::getTransactionFlags(uint32_t flags) {
|
||||
return android_atomic_and(~flags, &mTransactionFlags) & flags;
|
||||
}
|
||||
|
||||
uint32_t Layer::setTransactionFlags(uint32_t flags) {
|
||||
return android_atomic_or(flags, &mTransactionFlags);
|
||||
}
|
||||
|
||||
bool Layer::setPosition(float x, float y) {
|
||||
if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y)
|
||||
return false;
|
||||
mCurrentState.sequence++;
|
||||
mCurrentState.transform.set(x, y);
|
||||
setTransactionFlags(eTransactionNeeded);
|
||||
return true;
|
||||
}
|
||||
bool Layer::setLayer(uint32_t z) {
|
||||
if (mCurrentState.z == z)
|
||||
return false;
|
||||
mCurrentState.sequence++;
|
||||
mCurrentState.z = z;
|
||||
setTransactionFlags(eTransactionNeeded);
|
||||
return true;
|
||||
}
|
||||
bool Layer::setSize(uint32_t w, uint32_t h) {
|
||||
if (mCurrentState.requested.w == w && mCurrentState.requested.h == h)
|
||||
return false;
|
||||
mCurrentState.requested.w = w;
|
||||
mCurrentState.requested.h = h;
|
||||
setTransactionFlags(eTransactionNeeded);
|
||||
return true;
|
||||
}
|
||||
bool Layer::setAlpha(uint8_t alpha) {
|
||||
if (mCurrentState.alpha == alpha)
|
||||
return false;
|
||||
mCurrentState.sequence++;
|
||||
mCurrentState.alpha = alpha;
|
||||
setTransactionFlags(eTransactionNeeded);
|
||||
return true;
|
||||
}
|
||||
bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix) {
|
||||
mCurrentState.sequence++;
|
||||
mCurrentState.transform.set(
|
||||
matrix.dsdx, matrix.dsdy, matrix.dtdx, matrix.dtdy);
|
||||
setTransactionFlags(eTransactionNeeded);
|
||||
return true;
|
||||
}
|
||||
bool Layer::setTransparentRegionHint(const Region& transparent) {
|
||||
mCurrentState.sequence++;
|
||||
mCurrentState.transparentRegion = transparent;
|
||||
setTransactionFlags(eTransactionNeeded);
|
||||
return true;
|
||||
}
|
||||
bool Layer::setFlags(uint8_t flags, uint8_t mask) {
|
||||
const uint32_t newFlags = (mCurrentState.flags & ~mask) | (flags & mask);
|
||||
if (mCurrentState.flags == newFlags)
|
||||
return false;
|
||||
mCurrentState.sequence++;
|
||||
mCurrentState.flags = newFlags;
|
||||
setTransactionFlags(eTransactionNeeded);
|
||||
return true;
|
||||
}
|
||||
bool Layer::setCrop(const Rect& crop) {
|
||||
if (mCurrentState.requested.crop == crop)
|
||||
return false;
|
||||
mCurrentState.sequence++;
|
||||
mCurrentState.requested.crop = crop;
|
||||
setTransactionFlags(eTransactionNeeded);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Layer::setLayerStack(uint32_t layerStack) {
|
||||
if (mCurrentState.layerStack == layerStack)
|
||||
return false;
|
||||
mCurrentState.sequence++;
|
||||
mCurrentState.layerStack = layerStack;
|
||||
setTransactionFlags(eTransactionNeeded);
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -528,7 +969,9 @@ void Layer::onPostComposition() {
|
||||
}
|
||||
|
||||
bool Layer::isVisible() const {
|
||||
return LayerBaseClient::isVisible() && (mActiveBuffer != NULL);
|
||||
const Layer::State& s(mDrawingState);
|
||||
return !(s.flags & layer_state_t::eLayerHidden) && s.alpha
|
||||
&& (mActiveBuffer != NULL);
|
||||
}
|
||||
|
||||
Region Layer::latchBuffer(bool& recomputeVisibleRegions)
|
||||
@ -702,44 +1145,6 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions)
|
||||
return outDirtyRegion;
|
||||
}
|
||||
|
||||
void Layer::dump(String8& result, char* buffer, size_t SIZE) const
|
||||
{
|
||||
LayerBaseClient::dump(result, buffer, SIZE);
|
||||
|
||||
sp<const GraphicBuffer> buf0(mActiveBuffer);
|
||||
uint32_t w0=0, h0=0, s0=0, f0=0;
|
||||
if (buf0 != 0) {
|
||||
w0 = buf0->getWidth();
|
||||
h0 = buf0->getHeight();
|
||||
s0 = buf0->getStride();
|
||||
f0 = buf0->format;
|
||||
}
|
||||
snprintf(buffer, SIZE,
|
||||
" "
|
||||
"format=%2d, activeBuffer=[%4ux%4u:%4u,%3X],"
|
||||
" queued-frames=%d, mRefreshPending=%d\n",
|
||||
mFormat, w0, h0, s0,f0,
|
||||
mQueuedFrames, mRefreshPending);
|
||||
|
||||
result.append(buffer);
|
||||
|
||||
if (mSurfaceFlingerConsumer != 0) {
|
||||
mSurfaceFlingerConsumer->dump(result, " ", buffer, SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const
|
||||
{
|
||||
LayerBaseClient::dumpStats(result, buffer, SIZE);
|
||||
mFrameTracker.dump(result);
|
||||
}
|
||||
|
||||
void Layer::clearStats()
|
||||
{
|
||||
LayerBaseClient::clearStats();
|
||||
mFrameTracker.clear();
|
||||
}
|
||||
|
||||
uint32_t Layer::getEffectiveUsage(uint32_t usage) const
|
||||
{
|
||||
// TODO: should we do something special if mSecure is set?
|
||||
@ -766,6 +1171,86 @@ void Layer::updateTransformHint(const sp<const DisplayDevice>& hw) const {
|
||||
mSurfaceFlingerConsumer->setTransformHint(orientation);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// debugging
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void Layer::dump(String8& result, char* buffer, size_t SIZE) const
|
||||
{
|
||||
const Layer::State& s(drawingState());
|
||||
|
||||
snprintf(buffer, SIZE,
|
||||
"+ %s %p (%s)\n",
|
||||
getTypeId(), this, getName().string());
|
||||
result.append(buffer);
|
||||
|
||||
s.transparentRegion.dump(result, "transparentRegion");
|
||||
visibleRegion.dump(result, "visibleRegion");
|
||||
sp<Client> client(mClientRef.promote());
|
||||
|
||||
snprintf(buffer, SIZE,
|
||||
" "
|
||||
"layerStack=%4d, z=%9d, pos=(%g,%g), size=(%4d,%4d), crop=(%4d,%4d,%4d,%4d), "
|
||||
"isOpaque=%1d, invalidate=%1d, "
|
||||
"alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n"
|
||||
" client=%p\n",
|
||||
s.layerStack, s.z, s.transform.tx(), s.transform.ty(), s.active.w, s.active.h,
|
||||
s.active.crop.left, s.active.crop.top,
|
||||
s.active.crop.right, s.active.crop.bottom,
|
||||
isOpaque(), contentDirty,
|
||||
s.alpha, s.flags,
|
||||
s.transform[0][0], s.transform[0][1],
|
||||
s.transform[1][0], s.transform[1][1],
|
||||
client.get());
|
||||
result.append(buffer);
|
||||
|
||||
sp<const GraphicBuffer> buf0(mActiveBuffer);
|
||||
uint32_t w0=0, h0=0, s0=0, f0=0;
|
||||
if (buf0 != 0) {
|
||||
w0 = buf0->getWidth();
|
||||
h0 = buf0->getHeight();
|
||||
s0 = buf0->getStride();
|
||||
f0 = buf0->format;
|
||||
}
|
||||
snprintf(buffer, SIZE,
|
||||
" "
|
||||
"format=%2d, activeBuffer=[%4ux%4u:%4u,%3X],"
|
||||
" queued-frames=%d, mRefreshPending=%d\n",
|
||||
mFormat, w0, h0, s0,f0,
|
||||
mQueuedFrames, mRefreshPending);
|
||||
|
||||
result.append(buffer);
|
||||
|
||||
if (mSurfaceFlingerConsumer != 0) {
|
||||
mSurfaceFlingerConsumer->dump(result, " ", buffer, SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Layer::shortDump(String8& result, char* scratch, size_t size) const {
|
||||
Layer::dump(result, scratch, size);
|
||||
}
|
||||
|
||||
void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const {
|
||||
mFrameTracker.dump(result);
|
||||
}
|
||||
|
||||
void Layer::clearStats() {
|
||||
mFrameTracker.clear();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Layer::LayerCleaner::LayerCleaner(const sp<SurfaceFlinger>& flinger,
|
||||
const sp<Layer>& layer)
|
||||
: mFlinger(flinger), mLayer(layer) {
|
||||
}
|
||||
|
||||
Layer::LayerCleaner::~LayerCleaner() {
|
||||
// destroy client resources
|
||||
mFlinger->onLayerDestroyed(mLayer);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
@ -20,118 +20,356 @@
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <utils/Timers.h>
|
||||
|
||||
#include <ui/GraphicBuffer.h>
|
||||
#include <ui/PixelFormat.h>
|
||||
|
||||
#include <gui/ISurfaceComposerClient.h>
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
#include <GLES/gl.h>
|
||||
#include <GLES/glext.h>
|
||||
|
||||
#include "SurfaceFlingerConsumer.h"
|
||||
#include <utils/RefBase.h>
|
||||
#include <utils/String8.h>
|
||||
#include <utils/Timers.h>
|
||||
|
||||
#include <ui/GraphicBuffer.h>
|
||||
#include <ui/PixelFormat.h>
|
||||
#include <ui/Region.h>
|
||||
|
||||
#include <gui/ISurfaceComposerClient.h>
|
||||
|
||||
#include <private/gui/LayerState.h>
|
||||
|
||||
#include "FrameTracker.h"
|
||||
#include "LayerBase.h"
|
||||
#include "Client.h"
|
||||
#include "SurfaceFlinger.h"
|
||||
#include "SurfaceFlingerConsumer.h"
|
||||
#include "SurfaceTextureLayer.h"
|
||||
#include "Transform.h"
|
||||
|
||||
#include "DisplayHardware/HWComposer.h"
|
||||
|
||||
namespace android {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class Client;
|
||||
class DisplayDevice;
|
||||
class GraphicBuffer;
|
||||
class SurfaceFlinger;
|
||||
class GLExtensions;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* The Layer class is essentially a LayerBase combined with a BufferQueue.
|
||||
* A new BufferQueue and a new SurfaceFlingerConsumer are created when the
|
||||
* Layer is first referenced.
|
||||
*
|
||||
* This also implements onFrameAvailable(), which notifies SurfaceFlinger
|
||||
* that new data has arrived.
|
||||
*/
|
||||
class Layer : public LayerBaseClient,
|
||||
public SurfaceFlingerConsumer::FrameAvailableListener
|
||||
{
|
||||
class Layer : public SurfaceFlingerConsumer::FrameAvailableListener {
|
||||
static int32_t sSequence;
|
||||
|
||||
public:
|
||||
mutable bool contentDirty;
|
||||
// regions below are in window-manager space
|
||||
Region visibleRegion;
|
||||
Region coveredRegion;
|
||||
Region visibleNonTransparentRegion;
|
||||
int32_t sequence;
|
||||
|
||||
enum { // flags for doTransaction()
|
||||
eDontUpdateGeometryState = 0x00000001,
|
||||
eVisibleRegion = 0x00000002,
|
||||
};
|
||||
|
||||
struct Geometry {
|
||||
uint32_t w;
|
||||
uint32_t h;
|
||||
Rect crop;
|
||||
inline bool operator ==(const Geometry& rhs) const {
|
||||
return (w == rhs.w && h == rhs.h && crop == rhs.crop);
|
||||
}
|
||||
inline bool operator !=(const Geometry& rhs) const {
|
||||
return !operator ==(rhs);
|
||||
}
|
||||
};
|
||||
|
||||
struct State {
|
||||
Geometry active;
|
||||
Geometry requested;
|
||||
uint32_t z;
|
||||
uint32_t layerStack;
|
||||
uint8_t alpha;
|
||||
uint8_t flags;
|
||||
uint8_t reserved[2];
|
||||
int32_t sequence; // changes when visible regions can change
|
||||
Transform transform;
|
||||
Region transparentRegion;
|
||||
};
|
||||
|
||||
class LayerMesh {
|
||||
friend class Layer;
|
||||
GLfloat mVertices[4][2];
|
||||
size_t mNumVertices;
|
||||
public:
|
||||
LayerMesh() :
|
||||
mNumVertices(4) {
|
||||
}
|
||||
GLfloat const* getVertices() const {
|
||||
return &mVertices[0][0];
|
||||
}
|
||||
size_t getVertexCount() const {
|
||||
return mNumVertices;
|
||||
}
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
Layer(SurfaceFlinger* flinger, const sp<Client>& client);
|
||||
virtual ~Layer();
|
||||
|
||||
virtual const char* getTypeId() const { return "Layer"; }
|
||||
|
||||
// the this layer's size and format
|
||||
status_t setBuffers(uint32_t w, uint32_t h,
|
||||
PixelFormat format, uint32_t flags=0);
|
||||
|
||||
bool isFixedSize() const;
|
||||
// Creates an ISurface associated with this object. This may only be
|
||||
// called once. to provide your own ISurface, override createSurface().
|
||||
sp<ISurface> getSurface();
|
||||
|
||||
// modify current state
|
||||
bool setPosition(float x, float y);
|
||||
bool setLayer(uint32_t z);
|
||||
bool setSize(uint32_t w, uint32_t h);
|
||||
bool setAlpha(uint8_t alpha);
|
||||
bool setMatrix(const layer_state_t::matrix22_t& matrix);
|
||||
bool setTransparentRegionHint(const Region& transparent);
|
||||
bool setFlags(uint8_t flags, uint8_t mask);
|
||||
bool setCrop(const Rect& crop);
|
||||
bool setLayerStack(uint32_t layerStack);
|
||||
|
||||
void commitTransaction();
|
||||
|
||||
uint32_t getTransactionFlags(uint32_t flags);
|
||||
uint32_t setTransactionFlags(uint32_t flags);
|
||||
|
||||
void computeGeometry(const sp<const DisplayDevice>& hw, LayerMesh* mesh) const;
|
||||
Rect computeBounds() const;
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* initStates - called just after construction
|
||||
*/
|
||||
virtual void initStates(uint32_t w, uint32_t h, uint32_t flags);
|
||||
|
||||
virtual const char* getTypeId() const { return "Layer"; }
|
||||
|
||||
virtual void setName(const String8& name);
|
||||
String8 getName() const;
|
||||
|
||||
// LayerBase interface
|
||||
virtual void setGeometry(const sp<const DisplayDevice>& hw,
|
||||
HWComposer::HWCLayerInterface& layer);
|
||||
virtual void setPerFrameData(const sp<const DisplayDevice>& hw,
|
||||
HWComposer::HWCLayerInterface& layer);
|
||||
virtual void setAcquireFence(const sp<const DisplayDevice>& hw,
|
||||
HWComposer::HWCLayerInterface& layer);
|
||||
|
||||
/*
|
||||
* called after page-flip
|
||||
*/
|
||||
virtual void onLayerDisplayed(const sp<const DisplayDevice>& hw,
|
||||
HWComposer::HWCLayerInterface* layer);
|
||||
|
||||
/*
|
||||
* called before composition.
|
||||
* returns true if the layer has pending updates.
|
||||
*/
|
||||
virtual bool onPreComposition();
|
||||
|
||||
/*
|
||||
* called after composition.
|
||||
*/
|
||||
virtual void onPostComposition();
|
||||
|
||||
/*
|
||||
* draw - performs some global clipping optimizations
|
||||
* and calls onDraw().
|
||||
* Typically this method is not overridden, instead implement onDraw()
|
||||
* to perform the actual drawing.
|
||||
*/
|
||||
virtual void draw(const sp<const DisplayDevice>& hw, const Region& clip) const;
|
||||
virtual void draw(const sp<const DisplayDevice>& hw);
|
||||
|
||||
/*
|
||||
* onDraw - draws the surface.
|
||||
*/
|
||||
virtual void onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const;
|
||||
|
||||
/*
|
||||
* needsLinearFiltering - true if this surface's state requires filtering
|
||||
*/
|
||||
virtual bool needsFiltering(const sp<const DisplayDevice>& hw) const;
|
||||
|
||||
/*
|
||||
* doTransaction - process the transaction. This is a good place to figure
|
||||
* out which attributes of the surface have changed.
|
||||
*/
|
||||
virtual uint32_t doTransaction(uint32_t transactionFlags);
|
||||
|
||||
/*
|
||||
* setVisibleRegion - called to set the new visible region. This gives
|
||||
* a chance to update the new visible region or record the fact it changed.
|
||||
*/
|
||||
virtual void setVisibleRegion(const Region& visibleRegion);
|
||||
|
||||
/*
|
||||
* setCoveredRegion - called when the covered region changes. The covered
|
||||
* region corresponds to any area of the surface that is covered
|
||||
* (transparently or not) by another surface.
|
||||
*/
|
||||
virtual void setCoveredRegion(const Region& coveredRegion);
|
||||
|
||||
/*
|
||||
* setVisibleNonTransparentRegion - called when the visible and
|
||||
* non-transparent region changes.
|
||||
*/
|
||||
virtual void setVisibleNonTransparentRegion(const Region&
|
||||
visibleNonTransparentRegion);
|
||||
|
||||
/*
|
||||
* latchBuffer - called each time the screen is redrawn and returns whether
|
||||
* the visible regions need to be recomputed (this is a fairly heavy
|
||||
* operation, so this should be set only if needed). Typically this is used
|
||||
* to figure out if the content or size of a surface has changed.
|
||||
*/
|
||||
virtual Region latchBuffer(bool& recomputeVisibleRegions);
|
||||
|
||||
/*
|
||||
* isOpaque - true if this surface is opaque
|
||||
*/
|
||||
virtual bool isOpaque() const;
|
||||
|
||||
/*
|
||||
* isSecure - true if this surface is secure, that is if it prevents
|
||||
* screenshots or VNC servers.
|
||||
*/
|
||||
virtual bool isSecure() const { return mSecure; }
|
||||
|
||||
/*
|
||||
* isProtected - true if the layer may contain protected content in the
|
||||
* GRALLOC_USAGE_PROTECTED sense.
|
||||
*/
|
||||
virtual bool isProtected() const;
|
||||
virtual void onRemoved();
|
||||
virtual sp<Layer> getLayer() const { return const_cast<Layer*>(this); }
|
||||
virtual void setName(const String8& name);
|
||||
|
||||
/*
|
||||
* isVisible - true if this layer is visible, false otherwise
|
||||
*/
|
||||
virtual bool isVisible() const;
|
||||
|
||||
// LayerBaseClient interface
|
||||
virtual wp<IBinder> getSurfaceTextureBinder() const;
|
||||
/*
|
||||
* isFixedSize - true if content has a fixed size
|
||||
*/
|
||||
virtual bool isFixedSize() const;
|
||||
|
||||
// only for debugging
|
||||
inline const sp<GraphicBuffer>& getActiveBuffer() const { return mActiveBuffer; }
|
||||
/*
|
||||
* called with the state lock when the surface is removed from the
|
||||
* current list
|
||||
*/
|
||||
virtual void onRemoved();
|
||||
|
||||
|
||||
virtual wp<IBinder> getSurfaceTextureBinder() const;
|
||||
|
||||
// Updates the transform hint in our SurfaceFlingerConsumer to match
|
||||
// the current orientation of the display device.
|
||||
virtual void updateTransformHint(const sp<const DisplayDevice>& hw) const;
|
||||
|
||||
/*
|
||||
* returns the rectangle that crops the content of the layer and scales it
|
||||
* to the layer's size.
|
||||
*/
|
||||
virtual Rect getContentCrop() const;
|
||||
|
||||
/*
|
||||
* returns the transform bits (90 rotation / h-flip / v-flip) of the
|
||||
* layer's content
|
||||
*/
|
||||
virtual uint32_t getContentTransform() const;
|
||||
|
||||
protected:
|
||||
virtual void onFirstRef();
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
void clearWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip) const;
|
||||
void setFiltering(bool filtering);
|
||||
bool getFiltering() const;
|
||||
|
||||
// only for debugging
|
||||
inline const sp<GraphicBuffer>& getActiveBuffer() const { return mActiveBuffer; }
|
||||
|
||||
inline const State& drawingState() const { return mDrawingState; }
|
||||
inline const State& currentState() const { return mCurrentState; }
|
||||
inline State& currentState() { return mCurrentState; }
|
||||
|
||||
|
||||
/* always call base class first */
|
||||
virtual void dump(String8& result, char* scratch, size_t size) const;
|
||||
virtual void shortDump(String8& result, char* scratch, size_t size) const;
|
||||
virtual void dumpStats(String8& result, char* buffer, size_t SIZE) const;
|
||||
virtual void clearStats();
|
||||
|
||||
sp<SurfaceFlingerConsumer> getConsumer() const {
|
||||
return mSurfaceFlingerConsumer;
|
||||
}
|
||||
protected:
|
||||
// constant
|
||||
sp<SurfaceFlinger> mFlinger;
|
||||
|
||||
virtual void onFirstRef();
|
||||
|
||||
/*
|
||||
* Trivial class, used to ensure that mFlinger->onLayerDestroyed(mLayer)
|
||||
* is called.
|
||||
*/
|
||||
class LayerCleaner {
|
||||
sp<SurfaceFlinger> mFlinger;
|
||||
wp<Layer> mLayer;
|
||||
protected:
|
||||
~LayerCleaner();
|
||||
public:
|
||||
LayerCleaner(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer);
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
// Creates an instance of ISurface for this Layer.
|
||||
virtual sp<ISurface> createSurface();
|
||||
|
||||
// Interface implementation for SurfaceFlingerConsumer::FrameAvailableListener
|
||||
virtual void onFrameAvailable();
|
||||
|
||||
|
||||
uint32_t getEffectiveUsage(uint32_t usage) const;
|
||||
Rect computeCrop(const sp<const DisplayDevice>& hw) const;
|
||||
bool isCropped() const;
|
||||
static bool getOpacityForFormat(uint32_t format);
|
||||
|
||||
// Interface implementation for SurfaceFlingerConsumer::FrameAvailableListener
|
||||
virtual void onFrameAvailable();
|
||||
// drawing
|
||||
void clearWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip,
|
||||
GLclampf r, GLclampf g, GLclampf b, GLclampf alpha) const;
|
||||
void drawWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip) const;
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
// constants
|
||||
sp<SurfaceFlingerConsumer> mSurfaceFlingerConsumer;
|
||||
GLuint mTextureName;
|
||||
bool mPremultipliedAlpha;
|
||||
String8 mName;
|
||||
mutable bool mDebug;
|
||||
PixelFormat mFormat;
|
||||
const GLExtensions& mGLExtensions;
|
||||
bool mOpaqueLayer;
|
||||
|
||||
// these are protected by an external lock
|
||||
State mCurrentState;
|
||||
State mDrawingState;
|
||||
volatile int32_t mTransactionFlags;
|
||||
|
||||
// thread-safe
|
||||
volatile int32_t mQueuedFrames;
|
||||
@ -145,15 +383,20 @@ private:
|
||||
bool mCurrentOpacity;
|
||||
bool mRefreshPending;
|
||||
bool mFrameLatencyNeeded;
|
||||
|
||||
// constants
|
||||
PixelFormat mFormat;
|
||||
const GLExtensions& mGLExtensions;
|
||||
bool mOpaqueLayer;
|
||||
// Whether filtering is forced on or not
|
||||
bool mFiltering;
|
||||
// Whether filtering is needed b/c of the drawingstate
|
||||
bool mNeedsFiltering;
|
||||
|
||||
// page-flip thread (currently main thread)
|
||||
bool mSecure; // no screenshots
|
||||
bool mSecure; // no screenshots
|
||||
bool mProtectedByApp; // application requires protected path to external sink
|
||||
|
||||
// protected by mLock
|
||||
mutable Mutex mLock;
|
||||
// Set to true if an ISurface has been associated with this object.
|
||||
mutable bool mHasSurface;
|
||||
const wp<Client> mClientRef;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
@ -1,660 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/Log.h>
|
||||
#include <binder/IPCThreadState.h>
|
||||
#include <binder/IServiceManager.h>
|
||||
|
||||
#include <GLES/gl.h>
|
||||
#include <GLES/glext.h>
|
||||
|
||||
#include <hardware/hardware.h>
|
||||
|
||||
#include "clz.h"
|
||||
#include "Client.h"
|
||||
#include "LayerBase.h"
|
||||
#include "Layer.h"
|
||||
#include "SurfaceFlinger.h"
|
||||
#include "DisplayDevice.h"
|
||||
|
||||
namespace android {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
int32_t LayerBase::sSequence = 1;
|
||||
|
||||
LayerBase::LayerBase(SurfaceFlinger* flinger)
|
||||
: contentDirty(false),
|
||||
sequence(uint32_t(android_atomic_inc(&sSequence))),
|
||||
mFlinger(flinger), mFiltering(false),
|
||||
mNeedsFiltering(false),
|
||||
mTransactionFlags(0),
|
||||
mPremultipliedAlpha(true), mName("unnamed"), mDebug(false)
|
||||
{
|
||||
}
|
||||
|
||||
LayerBase::~LayerBase()
|
||||
{
|
||||
}
|
||||
|
||||
void LayerBase::setName(const String8& name) {
|
||||
mName = name;
|
||||
}
|
||||
|
||||
String8 LayerBase::getName() const {
|
||||
return mName;
|
||||
}
|
||||
|
||||
void LayerBase::initStates(uint32_t w, uint32_t h, uint32_t flags)
|
||||
{
|
||||
uint32_t layerFlags = 0;
|
||||
if (flags & ISurfaceComposerClient::eHidden)
|
||||
layerFlags = layer_state_t::eLayerHidden;
|
||||
|
||||
if (flags & ISurfaceComposerClient::eNonPremultiplied)
|
||||
mPremultipliedAlpha = false;
|
||||
|
||||
mCurrentState.active.w = w;
|
||||
mCurrentState.active.h = h;
|
||||
mCurrentState.active.crop.makeInvalid();
|
||||
mCurrentState.z = 0;
|
||||
mCurrentState.alpha = 0xFF;
|
||||
mCurrentState.layerStack = 0;
|
||||
mCurrentState.flags = layerFlags;
|
||||
mCurrentState.sequence = 0;
|
||||
mCurrentState.transform.set(0, 0);
|
||||
mCurrentState.requested = mCurrentState.active;
|
||||
|
||||
// drawing state & current state are identical
|
||||
mDrawingState = mCurrentState;
|
||||
}
|
||||
|
||||
bool LayerBase::needsFiltering(const sp<const DisplayDevice>& hw) const {
|
||||
return mNeedsFiltering || hw->needsFiltering();
|
||||
}
|
||||
|
||||
void LayerBase::commitTransaction() {
|
||||
mDrawingState = mCurrentState;
|
||||
}
|
||||
void LayerBase::forceVisibilityTransaction() {
|
||||
// this can be called without SurfaceFlinger.mStateLock, but if we
|
||||
// can atomically increment the sequence number, it doesn't matter.
|
||||
android_atomic_inc(&mCurrentState.sequence);
|
||||
requestTransaction();
|
||||
}
|
||||
bool LayerBase::requestTransaction() {
|
||||
int32_t old = setTransactionFlags(eTransactionNeeded);
|
||||
return ((old & eTransactionNeeded) == 0);
|
||||
}
|
||||
uint32_t LayerBase::getTransactionFlags(uint32_t flags) {
|
||||
return android_atomic_and(~flags, &mTransactionFlags) & flags;
|
||||
}
|
||||
uint32_t LayerBase::setTransactionFlags(uint32_t flags) {
|
||||
return android_atomic_or(flags, &mTransactionFlags);
|
||||
}
|
||||
|
||||
bool LayerBase::setPosition(float x, float y) {
|
||||
if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y)
|
||||
return false;
|
||||
mCurrentState.sequence++;
|
||||
mCurrentState.transform.set(x, y);
|
||||
requestTransaction();
|
||||
return true;
|
||||
}
|
||||
bool LayerBase::setLayer(uint32_t z) {
|
||||
if (mCurrentState.z == z)
|
||||
return false;
|
||||
mCurrentState.sequence++;
|
||||
mCurrentState.z = z;
|
||||
requestTransaction();
|
||||
return true;
|
||||
}
|
||||
bool LayerBase::setSize(uint32_t w, uint32_t h) {
|
||||
if (mCurrentState.requested.w == w && mCurrentState.requested.h == h)
|
||||
return false;
|
||||
mCurrentState.requested.w = w;
|
||||
mCurrentState.requested.h = h;
|
||||
requestTransaction();
|
||||
return true;
|
||||
}
|
||||
bool LayerBase::setAlpha(uint8_t alpha) {
|
||||
if (mCurrentState.alpha == alpha)
|
||||
return false;
|
||||
mCurrentState.sequence++;
|
||||
mCurrentState.alpha = alpha;
|
||||
requestTransaction();
|
||||
return true;
|
||||
}
|
||||
bool LayerBase::setMatrix(const layer_state_t::matrix22_t& matrix) {
|
||||
mCurrentState.sequence++;
|
||||
mCurrentState.transform.set(
|
||||
matrix.dsdx, matrix.dsdy, matrix.dtdx, matrix.dtdy);
|
||||
requestTransaction();
|
||||
return true;
|
||||
}
|
||||
bool LayerBase::setTransparentRegionHint(const Region& transparent) {
|
||||
mCurrentState.sequence++;
|
||||
mCurrentState.transparentRegion = transparent;
|
||||
requestTransaction();
|
||||
return true;
|
||||
}
|
||||
bool LayerBase::setFlags(uint8_t flags, uint8_t mask) {
|
||||
const uint32_t newFlags = (mCurrentState.flags & ~mask) | (flags & mask);
|
||||
if (mCurrentState.flags == newFlags)
|
||||
return false;
|
||||
mCurrentState.sequence++;
|
||||
mCurrentState.flags = newFlags;
|
||||
requestTransaction();
|
||||
return true;
|
||||
}
|
||||
bool LayerBase::setCrop(const Rect& crop) {
|
||||
if (mCurrentState.requested.crop == crop)
|
||||
return false;
|
||||
mCurrentState.sequence++;
|
||||
mCurrentState.requested.crop = crop;
|
||||
requestTransaction();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LayerBase::setLayerStack(uint32_t layerStack) {
|
||||
if (mCurrentState.layerStack == layerStack)
|
||||
return false;
|
||||
mCurrentState.sequence++;
|
||||
mCurrentState.layerStack = layerStack;
|
||||
requestTransaction();
|
||||
return true;
|
||||
}
|
||||
|
||||
void LayerBase::setVisibleRegion(const Region& visibleRegion) {
|
||||
// always called from main thread
|
||||
this->visibleRegion = visibleRegion;
|
||||
}
|
||||
|
||||
void LayerBase::setCoveredRegion(const Region& coveredRegion) {
|
||||
// always called from main thread
|
||||
this->coveredRegion = coveredRegion;
|
||||
}
|
||||
|
||||
void LayerBase::setVisibleNonTransparentRegion(const Region&
|
||||
setVisibleNonTransparentRegion) {
|
||||
// always called from main thread
|
||||
this->visibleNonTransparentRegion = setVisibleNonTransparentRegion;
|
||||
}
|
||||
|
||||
uint32_t LayerBase::doTransaction(uint32_t flags)
|
||||
{
|
||||
const Layer::State& front(drawingState());
|
||||
const Layer::State& temp(currentState());
|
||||
|
||||
// always set active to requested, unless we're asked not to
|
||||
// this is used by Layer, which special cases resizes.
|
||||
if (flags & eDontUpdateGeometryState) {
|
||||
} else {
|
||||
Layer::State& editTemp(currentState());
|
||||
editTemp.active = temp.requested;
|
||||
}
|
||||
|
||||
if (front.active != temp.active) {
|
||||
// invalidate and recompute the visible regions if needed
|
||||
flags |= Layer::eVisibleRegion;
|
||||
}
|
||||
|
||||
if (temp.sequence != front.sequence) {
|
||||
// invalidate and recompute the visible regions if needed
|
||||
flags |= eVisibleRegion;
|
||||
this->contentDirty = true;
|
||||
|
||||
// we may use linear filtering, if the matrix scales us
|
||||
const uint8_t type = temp.transform.getType();
|
||||
mNeedsFiltering = (!temp.transform.preserveRects() ||
|
||||
(type >= Transform::SCALE));
|
||||
}
|
||||
|
||||
// Commit the transaction
|
||||
commitTransaction();
|
||||
return flags;
|
||||
}
|
||||
|
||||
void LayerBase::computeGeometry(const sp<const DisplayDevice>& hw, LayerMesh* mesh) const
|
||||
{
|
||||
const Layer::State& s(drawingState());
|
||||
const Transform tr(hw->getTransform() * s.transform);
|
||||
const uint32_t hw_h = hw->getHeight();
|
||||
Rect win(s.active.w, s.active.h);
|
||||
if (!s.active.crop.isEmpty()) {
|
||||
win.intersect(s.active.crop, &win);
|
||||
}
|
||||
if (mesh) {
|
||||
tr.transform(mesh->mVertices[0], win.left, win.top);
|
||||
tr.transform(mesh->mVertices[1], win.left, win.bottom);
|
||||
tr.transform(mesh->mVertices[2], win.right, win.bottom);
|
||||
tr.transform(mesh->mVertices[3], win.right, win.top);
|
||||
for (size_t i=0 ; i<4 ; i++) {
|
||||
mesh->mVertices[i][1] = hw_h - mesh->mVertices[i][1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rect LayerBase::computeBounds() const {
|
||||
const Layer::State& s(drawingState());
|
||||
Rect win(s.active.w, s.active.h);
|
||||
if (!s.active.crop.isEmpty()) {
|
||||
win.intersect(s.active.crop, &win);
|
||||
}
|
||||
return win;
|
||||
}
|
||||
|
||||
Region LayerBase::latchBuffer(bool& recomputeVisibleRegions) {
|
||||
Region result;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Rect LayerBase::getContentCrop() const {
|
||||
// regular layers just use their active area as the content crop
|
||||
const State& s(drawingState());
|
||||
return Rect(s.active.w, s.active.h);
|
||||
}
|
||||
|
||||
uint32_t LayerBase::getContentTransform() const {
|
||||
// regular layers don't have a content transform
|
||||
return 0;
|
||||
}
|
||||
|
||||
Rect LayerBase::computeCrop(const sp<const DisplayDevice>& hw) const {
|
||||
/*
|
||||
* The way we compute the crop (aka. texture coordinates when we have a
|
||||
* Layer) produces a different output from the GL code in
|
||||
* drawWithOpenGL() due to HWC being limited to integers. The difference
|
||||
* can be large if getContentTransform() contains a large scale factor.
|
||||
* See comments in drawWithOpenGL() for more details.
|
||||
*/
|
||||
|
||||
// the content crop is the area of the content that gets scaled to the
|
||||
// layer's size.
|
||||
Rect crop(getContentCrop());
|
||||
|
||||
// the active.crop is the area of the window that gets cropped, but not
|
||||
// scaled in any ways.
|
||||
const State& s(drawingState());
|
||||
|
||||
// apply the projection's clipping to the window crop in
|
||||
// layerstack space, and convert-back to layer space.
|
||||
// if there are no window scaling (or content scaling) involved,
|
||||
// this operation will map to full pixels in the buffer.
|
||||
// NOTE: should we revert to GL composition if a scaling is involved
|
||||
// since it cannot be represented in the HWC API?
|
||||
Rect activeCrop(s.transform.transform(s.active.crop));
|
||||
activeCrop.intersect(hw->getViewport(), &activeCrop);
|
||||
activeCrop = s.transform.inverse().transform(activeCrop);
|
||||
|
||||
// paranoia: make sure the window-crop is constrained in the
|
||||
// window's bounds
|
||||
activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop);
|
||||
|
||||
if (!activeCrop.isEmpty()) {
|
||||
// Transform the window crop to match the buffer coordinate system,
|
||||
// which means using the inverse of the current transform set on the
|
||||
// SurfaceFlingerConsumer.
|
||||
uint32_t invTransform = getContentTransform();
|
||||
int winWidth = s.active.w;
|
||||
int winHeight = s.active.h;
|
||||
if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
|
||||
invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
|
||||
NATIVE_WINDOW_TRANSFORM_FLIP_H;
|
||||
winWidth = s.active.h;
|
||||
winHeight = s.active.w;
|
||||
}
|
||||
const Rect winCrop = activeCrop.transform(
|
||||
invTransform, s.active.w, s.active.h);
|
||||
|
||||
// the code below essentially performs a scaled intersection
|
||||
// of crop and winCrop
|
||||
float xScale = float(crop.width()) / float(winWidth);
|
||||
float yScale = float(crop.height()) / float(winHeight);
|
||||
|
||||
int insetL = int(ceilf( winCrop.left * xScale));
|
||||
int insetT = int(ceilf( winCrop.top * yScale));
|
||||
int insetR = int(ceilf((winWidth - winCrop.right ) * xScale));
|
||||
int insetB = int(ceilf((winHeight - winCrop.bottom) * yScale));
|
||||
|
||||
crop.left += insetL;
|
||||
crop.top += insetT;
|
||||
crop.right -= insetR;
|
||||
crop.bottom -= insetB;
|
||||
}
|
||||
return crop;
|
||||
}
|
||||
|
||||
void LayerBase::setGeometry(
|
||||
const sp<const DisplayDevice>& hw,
|
||||
HWComposer::HWCLayerInterface& layer)
|
||||
{
|
||||
layer.setDefaultState();
|
||||
|
||||
// this gives us only the "orientation" component of the transform
|
||||
const State& s(drawingState());
|
||||
const uint32_t finalTransform = s.transform.getOrientation();
|
||||
// we can only handle simple transformation
|
||||
if (finalTransform & Transform::ROT_INVALID) {
|
||||
layer.setTransform(0);
|
||||
} else {
|
||||
layer.setTransform(finalTransform);
|
||||
}
|
||||
|
||||
if (!isOpaque() || s.alpha != 0xFF) {
|
||||
layer.setBlending(mPremultipliedAlpha ?
|
||||
HWC_BLENDING_PREMULT :
|
||||
HWC_BLENDING_COVERAGE);
|
||||
}
|
||||
|
||||
|
||||
// apply the layer's transform, followed by the display's global transform
|
||||
// here we're guaranteed that the layer's transform preserves rects
|
||||
|
||||
Rect frame(s.transform.transform(computeBounds()));
|
||||
frame.intersect(hw->getViewport(), &frame);
|
||||
const Transform& tr(hw->getTransform());
|
||||
layer.setFrame(tr.transform(frame));
|
||||
layer.setCrop(computeCrop(hw));
|
||||
}
|
||||
|
||||
void LayerBase::setPerFrameData(const sp<const DisplayDevice>& hw,
|
||||
HWComposer::HWCLayerInterface& layer) {
|
||||
// we have to set the visible region on every frame because
|
||||
// we currently free it during onLayerDisplayed(), which is called
|
||||
// after HWComposer::commit() -- every frame.
|
||||
// Apply this display's projection's viewport to the visible region
|
||||
// before giving it to the HWC HAL.
|
||||
const Transform& tr = hw->getTransform();
|
||||
Region visible = tr.transform(visibleRegion.intersect(hw->getViewport()));
|
||||
layer.setVisibleRegionScreen(visible);
|
||||
}
|
||||
|
||||
void LayerBase::setAcquireFence(const sp<const DisplayDevice>& hw,
|
||||
HWComposer::HWCLayerInterface& layer) {
|
||||
layer.setAcquireFenceFd(-1);
|
||||
}
|
||||
|
||||
void LayerBase::onLayerDisplayed(const sp<const DisplayDevice>& hw,
|
||||
HWComposer::HWCLayerInterface* layer) {
|
||||
if (layer) {
|
||||
layer->onDisplayed();
|
||||
}
|
||||
}
|
||||
|
||||
void LayerBase::setFiltering(bool filtering)
|
||||
{
|
||||
mFiltering = filtering;
|
||||
}
|
||||
|
||||
bool LayerBase::getFiltering() const
|
||||
{
|
||||
return mFiltering;
|
||||
}
|
||||
|
||||
bool LayerBase::isVisible() const {
|
||||
const Layer::State& s(mDrawingState);
|
||||
return !(s.flags & layer_state_t::eLayerHidden) && s.alpha;
|
||||
}
|
||||
|
||||
void LayerBase::draw(const sp<const DisplayDevice>& hw, const Region& clip) const
|
||||
{
|
||||
onDraw(hw, clip);
|
||||
}
|
||||
|
||||
void LayerBase::draw(const sp<const DisplayDevice>& hw)
|
||||
{
|
||||
onDraw( hw, Region(hw->bounds()) );
|
||||
}
|
||||
|
||||
void LayerBase::clearWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip,
|
||||
GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) const
|
||||
{
|
||||
const uint32_t fbHeight = hw->getHeight();
|
||||
glColor4f(red,green,blue,alpha);
|
||||
|
||||
glDisable(GL_TEXTURE_EXTERNAL_OES);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
LayerMesh mesh;
|
||||
computeGeometry(hw, &mesh);
|
||||
|
||||
glVertexPointer(2, GL_FLOAT, 0, mesh.getVertices());
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, mesh.getVertexCount());
|
||||
}
|
||||
|
||||
void LayerBase::clearWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip) const
|
||||
{
|
||||
clearWithOpenGL(hw, clip, 0,0,0,0);
|
||||
}
|
||||
|
||||
void LayerBase::drawWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip) const
|
||||
{
|
||||
const uint32_t fbHeight = hw->getHeight();
|
||||
const State& s(drawingState());
|
||||
|
||||
GLenum src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;
|
||||
if (CC_UNLIKELY(s.alpha < 0xFF)) {
|
||||
const GLfloat alpha = s.alpha * (1.0f/255.0f);
|
||||
if (mPremultipliedAlpha) {
|
||||
glColor4f(alpha, alpha, alpha, alpha);
|
||||
} else {
|
||||
glColor4f(1, 1, 1, alpha);
|
||||
}
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
} else {
|
||||
glColor4f(1, 1, 1, 1);
|
||||
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
if (!isOpaque()) {
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
|
||||
} else {
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
}
|
||||
|
||||
LayerMesh mesh;
|
||||
computeGeometry(hw, &mesh);
|
||||
|
||||
// TODO: we probably want to generate the texture coords with the mesh
|
||||
// here we assume that we only have 4 vertices
|
||||
|
||||
struct TexCoords {
|
||||
GLfloat u;
|
||||
GLfloat v;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* NOTE: the way we compute the texture coordinates here produces
|
||||
* different results than when we take the HWC path -- in the later case
|
||||
* the "source crop" is rounded to texel boundaries.
|
||||
* This can produce significantly different results when the texture
|
||||
* is scaled by a large amount.
|
||||
*
|
||||
* The GL code below is more logical (imho), and the difference with
|
||||
* HWC is due to a limitation of the HWC API to integers -- a question
|
||||
* is suspend is wether we should ignore this problem or revert to
|
||||
* GL composition when a buffer scaling is applied (maybe with some
|
||||
* minimal value)? Or, we could make GL behave like HWC -- but this feel
|
||||
* like more of a hack.
|
||||
*/
|
||||
const Rect win(computeBounds());
|
||||
|
||||
GLfloat left = GLfloat(win.left) / GLfloat(s.active.w);
|
||||
GLfloat top = GLfloat(win.top) / GLfloat(s.active.h);
|
||||
GLfloat right = GLfloat(win.right) / GLfloat(s.active.w);
|
||||
GLfloat bottom = GLfloat(win.bottom) / GLfloat(s.active.h);
|
||||
|
||||
TexCoords texCoords[4];
|
||||
texCoords[0].u = left;
|
||||
texCoords[0].v = top;
|
||||
texCoords[1].u = left;
|
||||
texCoords[1].v = bottom;
|
||||
texCoords[2].u = right;
|
||||
texCoords[2].v = bottom;
|
||||
texCoords[3].u = right;
|
||||
texCoords[3].v = top;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
texCoords[i].v = 1.0f - texCoords[i].v;
|
||||
}
|
||||
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
|
||||
glVertexPointer(2, GL_FLOAT, 0, mesh.getVertices());
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, mesh.getVertexCount());
|
||||
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const
|
||||
{
|
||||
const Layer::State& s(drawingState());
|
||||
|
||||
snprintf(buffer, SIZE,
|
||||
"+ %s %p (%s)\n",
|
||||
getTypeId(), this, getName().string());
|
||||
result.append(buffer);
|
||||
|
||||
s.transparentRegion.dump(result, "transparentRegion");
|
||||
visibleRegion.dump(result, "visibleRegion");
|
||||
|
||||
snprintf(buffer, SIZE,
|
||||
" "
|
||||
"layerStack=%4d, z=%9d, pos=(%g,%g), size=(%4d,%4d), crop=(%4d,%4d,%4d,%4d), "
|
||||
"isOpaque=%1d, needsDithering=%1d, invalidate=%1d, "
|
||||
"alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n",
|
||||
s.layerStack, s.z, s.transform.tx(), s.transform.ty(), s.active.w, s.active.h,
|
||||
s.active.crop.left, s.active.crop.top,
|
||||
s.active.crop.right, s.active.crop.bottom,
|
||||
isOpaque(), needsDithering(), contentDirty,
|
||||
s.alpha, s.flags,
|
||||
s.transform[0][0], s.transform[0][1],
|
||||
s.transform[1][0], s.transform[1][1]);
|
||||
result.append(buffer);
|
||||
}
|
||||
|
||||
void LayerBase::shortDump(String8& result, char* scratch, size_t size) const {
|
||||
LayerBase::dump(result, scratch, size);
|
||||
}
|
||||
|
||||
void LayerBase::dumpStats(String8& result, char* scratch, size_t SIZE) const {
|
||||
}
|
||||
|
||||
void LayerBase::clearStats() {
|
||||
}
|
||||
|
||||
sp<LayerBaseClient> LayerBase::getLayerBaseClient() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
sp<Layer> LayerBase::getLayer() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger,
|
||||
const sp<Client>& client)
|
||||
: LayerBase(flinger),
|
||||
mHasSurface(false),
|
||||
mClientRef(client)
|
||||
{
|
||||
}
|
||||
|
||||
LayerBaseClient::~LayerBaseClient()
|
||||
{
|
||||
sp<Client> c(mClientRef.promote());
|
||||
if (c != 0) {
|
||||
c->detachLayer(this);
|
||||
}
|
||||
}
|
||||
|
||||
sp<ISurface> LayerBaseClient::createSurface()
|
||||
{
|
||||
class BSurface : public BnSurface, public LayerCleaner {
|
||||
virtual sp<IGraphicBufferProducer> getSurfaceTexture() const { return 0; }
|
||||
public:
|
||||
BSurface(const sp<SurfaceFlinger>& flinger,
|
||||
const sp<LayerBaseClient>& layer)
|
||||
: LayerCleaner(flinger, layer) { }
|
||||
};
|
||||
sp<ISurface> sur(new BSurface(mFlinger, this));
|
||||
return sur;
|
||||
}
|
||||
|
||||
sp<ISurface> LayerBaseClient::getSurface()
|
||||
{
|
||||
sp<ISurface> s;
|
||||
Mutex::Autolock _l(mLock);
|
||||
|
||||
LOG_ALWAYS_FATAL_IF(mHasSurface,
|
||||
"LayerBaseClient::getSurface() has already been called");
|
||||
|
||||
mHasSurface = true;
|
||||
s = createSurface();
|
||||
mClientSurfaceBinder = s->asBinder();
|
||||
return s;
|
||||
}
|
||||
|
||||
wp<IBinder> LayerBaseClient::getSurfaceBinder() const {
|
||||
return mClientSurfaceBinder;
|
||||
}
|
||||
|
||||
wp<IBinder> LayerBaseClient::getSurfaceTextureBinder() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LayerBaseClient::dump(String8& result, char* buffer, size_t SIZE) const
|
||||
{
|
||||
LayerBase::dump(result, buffer, SIZE);
|
||||
sp<Client> client(mClientRef.promote());
|
||||
snprintf(buffer, SIZE, " client=%p\n", client.get());
|
||||
result.append(buffer);
|
||||
}
|
||||
|
||||
|
||||
void LayerBaseClient::shortDump(String8& result, char* scratch, size_t size) const
|
||||
{
|
||||
LayerBaseClient::dump(result, scratch, size);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
LayerBaseClient::LayerCleaner::LayerCleaner(const sp<SurfaceFlinger>& flinger,
|
||||
const sp<LayerBaseClient>& layer)
|
||||
: mFlinger(flinger), mLayer(layer) {
|
||||
}
|
||||
|
||||
LayerBaseClient::LayerCleaner::~LayerCleaner() {
|
||||
// destroy client resources
|
||||
mFlinger->onLayerDestroyed(mLayer);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
}; // namespace android
|
@ -1,401 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef ANDROID_LAYER_BASE_H
|
||||
#define ANDROID_LAYER_BASE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
#include <GLES/gl.h>
|
||||
|
||||
#include <utils/RefBase.h>
|
||||
#include <utils/String8.h>
|
||||
|
||||
#include <ui/Region.h>
|
||||
|
||||
#include <gui/ISurfaceComposerClient.h>
|
||||
|
||||
#include <private/gui/LayerState.h>
|
||||
|
||||
#include "Transform.h"
|
||||
#include "DisplayHardware/HWComposer.h"
|
||||
|
||||
namespace android {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class Client;
|
||||
class DisplayDevice;
|
||||
class GraphicBuffer;
|
||||
class Layer;
|
||||
class LayerBaseClient;
|
||||
class SurfaceFlinger;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* Layers are rectangular graphic entities, internal to SurfaceFlinger.
|
||||
* They have properties including width, height, Z-depth, and 2D
|
||||
* transformations (chiefly translation and 90-degree rotations).
|
||||
*
|
||||
* Layers are organized into "layer stacks". Each layer is a member of
|
||||
* exactly one layer stack, identified by an integer in Layer::State. A
|
||||
* given layer stack may appear on more than one display.
|
||||
*
|
||||
* Notable subclasses (below LayerBaseClient) include Layer, LayerDim, and
|
||||
* LayerScreenshot.
|
||||
*/
|
||||
class LayerBase : virtual public RefBase
|
||||
{
|
||||
static int32_t sSequence;
|
||||
|
||||
public:
|
||||
LayerBase(SurfaceFlinger* flinger);
|
||||
|
||||
mutable bool contentDirty;
|
||||
// regions below are in window-manager space
|
||||
Region visibleRegion;
|
||||
Region coveredRegion;
|
||||
Region visibleNonTransparentRegion;
|
||||
int32_t sequence;
|
||||
|
||||
struct Geometry {
|
||||
uint32_t w;
|
||||
uint32_t h;
|
||||
Rect crop;
|
||||
inline bool operator == (const Geometry& rhs) const {
|
||||
return (w==rhs.w && h==rhs.h && crop==rhs.crop);
|
||||
}
|
||||
inline bool operator != (const Geometry& rhs) const {
|
||||
return !operator == (rhs);
|
||||
}
|
||||
};
|
||||
|
||||
struct State {
|
||||
Geometry active;
|
||||
Geometry requested;
|
||||
uint32_t z;
|
||||
uint32_t layerStack;
|
||||
uint8_t alpha;
|
||||
uint8_t flags;
|
||||
uint8_t reserved[2];
|
||||
int32_t sequence; // changes when visible regions can change
|
||||
Transform transform;
|
||||
Region transparentRegion;
|
||||
};
|
||||
|
||||
class LayerMesh {
|
||||
friend class LayerBase;
|
||||
GLfloat mVertices[4][2];
|
||||
size_t mNumVertices;
|
||||
public:
|
||||
LayerMesh() : mNumVertices(4) { }
|
||||
GLfloat const* getVertices() const {
|
||||
return &mVertices[0][0];
|
||||
}
|
||||
size_t getVertexCount() const {
|
||||
return mNumVertices;
|
||||
}
|
||||
};
|
||||
|
||||
virtual void setName(const String8& name);
|
||||
String8 getName() const;
|
||||
|
||||
// modify current state
|
||||
bool setPosition(float x, float y);
|
||||
bool setLayer(uint32_t z);
|
||||
bool setSize(uint32_t w, uint32_t h);
|
||||
bool setAlpha(uint8_t alpha);
|
||||
bool setMatrix(const layer_state_t::matrix22_t& matrix);
|
||||
bool setTransparentRegionHint(const Region& transparent);
|
||||
bool setFlags(uint8_t flags, uint8_t mask);
|
||||
bool setCrop(const Rect& crop);
|
||||
bool setLayerStack(uint32_t layerStack);
|
||||
|
||||
void commitTransaction();
|
||||
bool requestTransaction();
|
||||
void forceVisibilityTransaction();
|
||||
|
||||
uint32_t getTransactionFlags(uint32_t flags);
|
||||
uint32_t setTransactionFlags(uint32_t flags);
|
||||
|
||||
void computeGeometry(const sp<const DisplayDevice>& hw, LayerMesh* mesh) const;
|
||||
Rect computeBounds() const;
|
||||
|
||||
|
||||
virtual sp<LayerBaseClient> getLayerBaseClient() const;
|
||||
virtual sp<Layer> getLayer() const;
|
||||
|
||||
virtual const char* getTypeId() const { return "LayerBase"; }
|
||||
|
||||
virtual void setGeometry(const sp<const DisplayDevice>& hw,
|
||||
HWComposer::HWCLayerInterface& layer);
|
||||
virtual void setPerFrameData(const sp<const DisplayDevice>& hw,
|
||||
HWComposer::HWCLayerInterface& layer);
|
||||
virtual void setAcquireFence(const sp<const DisplayDevice>& hw,
|
||||
HWComposer::HWCLayerInterface& layer);
|
||||
|
||||
/**
|
||||
* draw - performs some global clipping optimizations
|
||||
* and calls onDraw().
|
||||
* Typically this method is not overridden, instead implement onDraw()
|
||||
* to perform the actual drawing.
|
||||
*/
|
||||
virtual void draw(const sp<const DisplayDevice>& hw, const Region& clip) const;
|
||||
virtual void draw(const sp<const DisplayDevice>& hw);
|
||||
|
||||
/**
|
||||
* onDraw - draws the surface.
|
||||
*/
|
||||
virtual void onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const = 0;
|
||||
|
||||
/**
|
||||
* initStates - called just after construction
|
||||
*/
|
||||
virtual void initStates(uint32_t w, uint32_t h, uint32_t flags);
|
||||
|
||||
/**
|
||||
* doTransaction - process the transaction. This is a good place to figure
|
||||
* out which attributes of the surface have changed.
|
||||
*/
|
||||
virtual uint32_t doTransaction(uint32_t transactionFlags);
|
||||
|
||||
/**
|
||||
* setVisibleRegion - called to set the new visible region. This gives
|
||||
* a chance to update the new visible region or record the fact it changed.
|
||||
*/
|
||||
virtual void setVisibleRegion(const Region& visibleRegion);
|
||||
|
||||
/**
|
||||
* setCoveredRegion - called when the covered region changes. The covered
|
||||
* region corresponds to any area of the surface that is covered
|
||||
* (transparently or not) by another surface.
|
||||
*/
|
||||
virtual void setCoveredRegion(const Region& coveredRegion);
|
||||
|
||||
/**
|
||||
* setVisibleNonTransparentRegion - called when the visible and
|
||||
* non-transparent region changes.
|
||||
*/
|
||||
virtual void setVisibleNonTransparentRegion(const Region&
|
||||
visibleNonTransparentRegion);
|
||||
|
||||
/**
|
||||
* latchBuffer - called each time the screen is redrawn and returns whether
|
||||
* the visible regions need to be recomputed (this is a fairly heavy
|
||||
* operation, so this should be set only if needed). Typically this is used
|
||||
* to figure out if the content or size of a surface has changed.
|
||||
*/
|
||||
virtual Region latchBuffer(bool& recomputeVisibleRegions);
|
||||
|
||||
/**
|
||||
* isOpaque - true if this surface is opaque
|
||||
*/
|
||||
virtual bool isOpaque() const { return true; }
|
||||
|
||||
/**
|
||||
* needsDithering - true if this surface needs dithering
|
||||
*/
|
||||
virtual bool needsDithering() const { return false; }
|
||||
|
||||
/**
|
||||
* needsLinearFiltering - true if this surface's state requires filtering
|
||||
*/
|
||||
virtual bool needsFiltering(const sp<const DisplayDevice>& hw) const;
|
||||
|
||||
/**
|
||||
* isSecure - true if this surface is secure, that is if it prevents
|
||||
* screenshots or VNC servers.
|
||||
*/
|
||||
virtual bool isSecure() const { return false; }
|
||||
|
||||
/**
|
||||
* isProtected - true if the layer may contain protected content in the
|
||||
* GRALLOC_USAGE_PROTECTED sense.
|
||||
*/
|
||||
virtual bool isProtected() const { return false; }
|
||||
|
||||
/*
|
||||
* isVisible - true if this layer is visibile, false otherwise
|
||||
*/
|
||||
virtual bool isVisible() const;
|
||||
|
||||
/** called with the state lock when the surface is removed from the
|
||||
* current list */
|
||||
virtual void onRemoved() { }
|
||||
|
||||
/** called after page-flip
|
||||
*/
|
||||
virtual void onLayerDisplayed(const sp<const DisplayDevice>& hw,
|
||||
HWComposer::HWCLayerInterface* layer);
|
||||
|
||||
/** called before composition.
|
||||
* returns true if the layer has pending updates.
|
||||
*/
|
||||
virtual bool onPreComposition() { return false; }
|
||||
|
||||
/** called before composition.
|
||||
*/
|
||||
virtual void onPostComposition() { }
|
||||
|
||||
/**
|
||||
* Updates the GLConsumer's transform hint, for layers that have
|
||||
* a GLConsumer.
|
||||
*/
|
||||
virtual void updateTransformHint(const sp<const DisplayDevice>& hw) const { }
|
||||
|
||||
/**
|
||||
* returns the rectangle that crops the content of the layer and scales it
|
||||
* to the layer's size.
|
||||
*/
|
||||
virtual Rect getContentCrop() const;
|
||||
|
||||
/*
|
||||
* returns the transform bits (90 rotation / h-flip / v-flip) of the
|
||||
* layer's content
|
||||
*/
|
||||
virtual uint32_t getContentTransform() const;
|
||||
|
||||
/** always call base class first */
|
||||
virtual void dump(String8& result, char* scratch, size_t size) const;
|
||||
virtual void shortDump(String8& result, char* scratch, size_t size) const;
|
||||
virtual void dumpStats(String8& result, char* buffer, size_t SIZE) const;
|
||||
virtual void clearStats();
|
||||
|
||||
|
||||
enum { // flags for doTransaction()
|
||||
eDontUpdateGeometryState = 0x00000001,
|
||||
eVisibleRegion = 0x00000002,
|
||||
};
|
||||
|
||||
|
||||
inline const State& drawingState() const { return mDrawingState; }
|
||||
inline const State& currentState() const { return mCurrentState; }
|
||||
inline State& currentState() { return mCurrentState; }
|
||||
|
||||
void clearWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip) const;
|
||||
|
||||
void setFiltering(bool filtering);
|
||||
bool getFiltering() const;
|
||||
|
||||
private:
|
||||
Rect computeCrop(const sp<const DisplayDevice>& hw) const;
|
||||
|
||||
protected:
|
||||
void clearWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip,
|
||||
GLclampf r, GLclampf g, GLclampf b, GLclampf alpha) const;
|
||||
void drawWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip) const;
|
||||
|
||||
sp<SurfaceFlinger> mFlinger;
|
||||
|
||||
private:
|
||||
// accessed only in the main thread
|
||||
// Whether filtering is forced on or not
|
||||
bool mFiltering;
|
||||
|
||||
// Whether filtering is needed b/c of the drawingstate
|
||||
bool mNeedsFiltering;
|
||||
|
||||
protected:
|
||||
// these are protected by an external lock
|
||||
State mCurrentState;
|
||||
State mDrawingState;
|
||||
volatile int32_t mTransactionFlags;
|
||||
|
||||
// don't change, don't need a lock
|
||||
bool mPremultipliedAlpha;
|
||||
String8 mName;
|
||||
mutable bool mDebug;
|
||||
|
||||
|
||||
public:
|
||||
// called from class SurfaceFlinger
|
||||
virtual ~LayerBase();
|
||||
|
||||
private:
|
||||
LayerBase(const LayerBase& rhs);
|
||||
};
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* This adds some additional fields and methods to support some Binder IPC
|
||||
* interactions. In particular, the LayerBaseClient's lifetime can be
|
||||
* managed by references to an ISurface object in another process.
|
||||
*/
|
||||
class LayerBaseClient : public LayerBase
|
||||
{
|
||||
public:
|
||||
LayerBaseClient(SurfaceFlinger* flinger, const sp<Client>& client);
|
||||
|
||||
virtual ~LayerBaseClient();
|
||||
|
||||
// Creates an ISurface associated with this object. This may only be
|
||||
// called once (see also getSurfaceBinder()).
|
||||
sp<ISurface> getSurface();
|
||||
|
||||
// Returns the Binder object for the ISurface associated with
|
||||
// this object.
|
||||
wp<IBinder> getSurfaceBinder() const;
|
||||
|
||||
virtual wp<IBinder> getSurfaceTextureBinder() const;
|
||||
|
||||
virtual sp<LayerBaseClient> getLayerBaseClient() const {
|
||||
return const_cast<LayerBaseClient*>(this); }
|
||||
|
||||
virtual const char* getTypeId() const { return "LayerBaseClient"; }
|
||||
|
||||
protected:
|
||||
virtual void dump(String8& result, char* scratch, size_t size) const;
|
||||
virtual void shortDump(String8& result, char* scratch, size_t size) const;
|
||||
|
||||
/*
|
||||
* Trivial class, used to ensure that mFlinger->onLayerDestroyed(mLayer)
|
||||
* is called.
|
||||
*/
|
||||
class LayerCleaner {
|
||||
sp<SurfaceFlinger> mFlinger;
|
||||
wp<LayerBaseClient> mLayer;
|
||||
protected:
|
||||
~LayerCleaner();
|
||||
public:
|
||||
LayerCleaner(const sp<SurfaceFlinger>& flinger,
|
||||
const sp<LayerBaseClient>& layer);
|
||||
};
|
||||
|
||||
private:
|
||||
virtual sp<ISurface> createSurface();
|
||||
|
||||
mutable Mutex mLock;
|
||||
|
||||
// Set to true if an ISurface has been associated with this object.
|
||||
mutable bool mHasSurface;
|
||||
|
||||
// The ISurface's Binder object, set by getSurface().
|
||||
wp<IBinder> mClientSurfaceBinder;
|
||||
|
||||
const wp<Client> mClientRef;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
}; // namespace android
|
||||
|
||||
#endif // ANDROID_LAYER_BASE_H
|
@ -34,12 +34,10 @@ namespace android {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
LayerDim::LayerDim(SurfaceFlinger* flinger, const sp<Client>& client)
|
||||
: LayerBaseClient(flinger, client)
|
||||
{
|
||||
: Layer(flinger, client) {
|
||||
}
|
||||
|
||||
LayerDim::~LayerDim()
|
||||
{
|
||||
LayerDim::~LayerDim() {
|
||||
}
|
||||
|
||||
void LayerDim::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const
|
||||
@ -71,6 +69,25 @@ void LayerDim::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) con
|
||||
}
|
||||
}
|
||||
|
||||
sp<ISurface> LayerDim::createSurface()
|
||||
{
|
||||
class BSurface : public BnSurface, public LayerCleaner {
|
||||
virtual sp<IGraphicBufferProducer> getSurfaceTexture() const { return 0; }
|
||||
public:
|
||||
BSurface(const sp<SurfaceFlinger>& flinger,
|
||||
const sp<Layer>& layer)
|
||||
: LayerCleaner(flinger, layer) { }
|
||||
};
|
||||
sp<ISurface> sur(new BSurface(mFlinger, this));
|
||||
return sur;
|
||||
}
|
||||
|
||||
bool LayerDim::isVisible() const {
|
||||
const Layer::State& s(drawingState());
|
||||
return !(s.flags & layer_state_t::eLayerHidden) && s.alpha;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
}; // namespace android
|
||||
|
@ -23,13 +23,13 @@
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
|
||||
#include "LayerBase.h"
|
||||
#include "Layer.h"
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
namespace android {
|
||||
|
||||
class LayerDim : public LayerBaseClient
|
||||
class LayerDim : public Layer
|
||||
{
|
||||
public:
|
||||
LayerDim(SurfaceFlinger* flinger, const sp<Client>& client);
|
||||
@ -41,6 +41,10 @@ public:
|
||||
virtual bool isProtectedByApp() const { return false; }
|
||||
virtual bool isProtectedByDRM() const { return false; }
|
||||
virtual const char* getTypeId() const { return "LayerDim"; }
|
||||
|
||||
virtual bool isFixedSize() const { return true; }
|
||||
virtual bool isVisible() const;
|
||||
virtual sp<ISurface> createSurface();
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2011 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.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "LayerScreenshot.h"
|
||||
#include "SurfaceFlinger.h"
|
||||
#include "DisplayDevice.h"
|
||||
|
||||
namespace android {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
LayerScreenshot::LayerScreenshot(SurfaceFlinger* flinger,
|
||||
const sp<Client>& client)
|
||||
: Layer(flinger, client)
|
||||
{
|
||||
}
|
||||
|
||||
void LayerScreenshot::onFirstRef()
|
||||
{
|
||||
Layer::onFirstRef();
|
||||
|
||||
// FIXME: we currently hardcode the default display
|
||||
// it's unclear what should we do instead.
|
||||
sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
|
||||
mFlinger->captureScreenImplLocked(hw, getConsumer()->getBufferQueue(),
|
||||
0, 0, 0, 0x7FFFFFFF);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
}; // namespace android
|
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2011 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_LAYER_SCREENSHOT_H
|
||||
#define ANDROID_LAYER_SCREENSHOT_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "Layer.h"
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
namespace android {
|
||||
|
||||
class LayerScreenshot : public Layer
|
||||
{
|
||||
public:
|
||||
LayerScreenshot(SurfaceFlinger* flinger, const sp<Client>& client);
|
||||
protected:
|
||||
virtual void onFirstRef();
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
}; // namespace android
|
||||
|
||||
#endif // ANDROID_LAYER_SCREENSHOT_H
|
@ -62,7 +62,6 @@
|
||||
#include "GLExtensions.h"
|
||||
#include "Layer.h"
|
||||
#include "LayerDim.h"
|
||||
#include "LayerScreenshot.h"
|
||||
#include "SurfaceFlinger.h"
|
||||
|
||||
#include "DisplayHardware/FramebufferSurface.h"
|
||||
@ -581,17 +580,14 @@ bool SurfaceFlinger::authenticateSurfaceTexture(
|
||||
const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
|
||||
size_t count = currentLayers.size();
|
||||
for (size_t i=0 ; i<count ; i++) {
|
||||
const sp<LayerBase>& layer(currentLayers[i]);
|
||||
sp<LayerBaseClient> lbc(layer->getLayerBaseClient());
|
||||
if (lbc != NULL) {
|
||||
// If this is an instance of Layer (as opposed to, say, LayerDim),
|
||||
// we will get the consumer interface of SurfaceFlingerConsumer's
|
||||
// BufferQueue. If it's the same Binder object as the graphic
|
||||
// buffer producer interface, return success.
|
||||
wp<IBinder> lbcBinder = lbc->getSurfaceTextureBinder();
|
||||
if (lbcBinder == surfaceTextureBinder) {
|
||||
return true;
|
||||
}
|
||||
const sp<Layer>& layer(currentLayers[i]);
|
||||
// If this is an instance of Layer (as opposed to, say, LayerDim),
|
||||
// we will get the consumer interface of SurfaceFlingerConsumer's
|
||||
// BufferQueue. If it's the same Binder object as the graphic
|
||||
// buffer producer interface, return success.
|
||||
wp<IBinder> lbcBinder = layer->getSurfaceTextureBinder();
|
||||
if (lbcBinder == surfaceTextureBinder) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -604,13 +600,10 @@ bool SurfaceFlinger::authenticateSurfaceTexture(
|
||||
// should not cause any harm.
|
||||
size_t purgatorySize = mLayerPurgatory.size();
|
||||
for (size_t i=0 ; i<purgatorySize ; i++) {
|
||||
const sp<LayerBase>& layer(mLayerPurgatory.itemAt(i));
|
||||
sp<LayerBaseClient> lbc(layer->getLayerBaseClient());
|
||||
if (lbc != NULL) {
|
||||
wp<IBinder> lbcBinder = lbc->getSurfaceTextureBinder();
|
||||
if (lbcBinder == surfaceTextureBinder) {
|
||||
return true;
|
||||
}
|
||||
const sp<Layer>& layer(mLayerPurgatory.itemAt(i));
|
||||
wp<IBinder> lbcBinder = layer->getSurfaceTextureBinder();
|
||||
if (lbcBinder == surfaceTextureBinder) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -915,7 +908,7 @@ void SurfaceFlinger::rebuildLayerStacks() {
|
||||
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
|
||||
Region opaqueRegion;
|
||||
Region dirtyRegion;
|
||||
Vector< sp<LayerBase> > layersSortedByZ;
|
||||
Vector< sp<Layer> > layersSortedByZ;
|
||||
const sp<DisplayDevice>& hw(mDisplays[dpy]);
|
||||
const Transform& tr(hw->getTransform());
|
||||
const Rect bounds(hw->getBounds());
|
||||
@ -925,7 +918,7 @@ void SurfaceFlinger::rebuildLayerStacks() {
|
||||
|
||||
const size_t count = currentLayers.size();
|
||||
for (size_t i=0 ; i<count ; i++) {
|
||||
const sp<LayerBase>& layer(currentLayers[i]);
|
||||
const sp<Layer>& layer(currentLayers[i]);
|
||||
const Layer::State& s(layer->drawingState());
|
||||
if (s.layerStack == hw->getLayerStack()) {
|
||||
Region drawRegion(tr.transform(
|
||||
@ -955,14 +948,14 @@ void SurfaceFlinger::setUpHWComposer() {
|
||||
sp<const DisplayDevice> hw(mDisplays[dpy]);
|
||||
const int32_t id = hw->getHwcDisplayId();
|
||||
if (id >= 0) {
|
||||
const Vector< sp<LayerBase> >& currentLayers(
|
||||
const Vector< sp<Layer> >& currentLayers(
|
||||
hw->getVisibleLayersSortedByZ());
|
||||
const size_t count = currentLayers.size();
|
||||
if (hwc.createWorkList(id, count) == NO_ERROR) {
|
||||
HWComposer::LayerListIterator cur = hwc.begin(id);
|
||||
const HWComposer::LayerListIterator end = hwc.end(id);
|
||||
for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
|
||||
const sp<LayerBase>& layer(currentLayers[i]);
|
||||
const sp<Layer>& layer(currentLayers[i]);
|
||||
layer->setGeometry(hw, *cur);
|
||||
if (mDebugDisableHWC || mDebugRegion) {
|
||||
cur->setSkip(true);
|
||||
@ -978,7 +971,7 @@ void SurfaceFlinger::setUpHWComposer() {
|
||||
sp<const DisplayDevice> hw(mDisplays[dpy]);
|
||||
const int32_t id = hw->getHwcDisplayId();
|
||||
if (id >= 0) {
|
||||
const Vector< sp<LayerBase> >& currentLayers(
|
||||
const Vector< sp<Layer> >& currentLayers(
|
||||
hw->getVisibleLayersSortedByZ());
|
||||
const size_t count = currentLayers.size();
|
||||
HWComposer::LayerListIterator cur = hwc.begin(id);
|
||||
@ -988,7 +981,7 @@ void SurfaceFlinger::setUpHWComposer() {
|
||||
* update the per-frame h/w composer data for each layer
|
||||
* and build the transparent region of the FB
|
||||
*/
|
||||
const sp<LayerBase>& layer(currentLayers[i]);
|
||||
const sp<Layer>& layer(currentLayers[i]);
|
||||
layer->setPerFrameData(hw, *cur);
|
||||
}
|
||||
}
|
||||
@ -1042,7 +1035,7 @@ void SurfaceFlinger::postFramebuffer()
|
||||
|
||||
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
|
||||
sp<const DisplayDevice> hw(mDisplays[dpy]);
|
||||
const Vector< sp<LayerBase> >& currentLayers(hw->getVisibleLayersSortedByZ());
|
||||
const Vector< sp<Layer> >& currentLayers(hw->getVisibleLayersSortedByZ());
|
||||
hw->onSwapBuffersCompleted(hwc);
|
||||
const size_t count = currentLayers.size();
|
||||
int32_t id = hw->getHwcDisplayId();
|
||||
@ -1098,7 +1091,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
|
||||
|
||||
if (transactionFlags & eTraversalNeeded) {
|
||||
for (size_t i=0 ; i<count ; i++) {
|
||||
const sp<LayerBase>& layer(currentLayers[i]);
|
||||
const sp<Layer>& layer(currentLayers[i]);
|
||||
uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
|
||||
if (!trFlags) continue;
|
||||
|
||||
@ -1245,8 +1238,8 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
|
||||
// NOTE: we rely on the fact that layers are sorted by
|
||||
// layerStack first (so we don't have to traverse the list
|
||||
// of displays for every layer).
|
||||
const sp<LayerBase>& layerBase(currentLayers[i]);
|
||||
uint32_t layerStack = layerBase->drawingState().layerStack;
|
||||
const sp<Layer>& layer(currentLayers[i]);
|
||||
uint32_t layerStack = layer->drawingState().layerStack;
|
||||
if (i==0 || currentlayerStack != layerStack) {
|
||||
currentlayerStack = layerStack;
|
||||
// figure out if this layerstack is mirrored
|
||||
@ -1268,7 +1261,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
|
||||
if (disp != NULL) {
|
||||
// presumably this means this layer is using a layerStack
|
||||
// that is not visible on any display
|
||||
layerBase->updateTransformHint(disp);
|
||||
layer->updateTransformHint(disp);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1291,7 +1284,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
|
||||
mVisibleRegionsDirty = true;
|
||||
const size_t count = previousLayers.size();
|
||||
for (size_t i=0 ; i<count ; i++) {
|
||||
const sp<LayerBase>& layer(previousLayers[i]);
|
||||
const sp<Layer>& layer(previousLayers[i]);
|
||||
if (currentLayers.indexOf(layer) < 0) {
|
||||
// this layer is not visible anymore
|
||||
// TODO: we could traverse the tree from front to back and
|
||||
@ -1342,7 +1335,7 @@ void SurfaceFlinger::computeVisibleRegions(
|
||||
|
||||
size_t i = currentLayers.size();
|
||||
while (i--) {
|
||||
const sp<LayerBase>& layer = currentLayers[i];
|
||||
const sp<Layer>& layer = currentLayers[i];
|
||||
|
||||
// start with the whole surface at its current location
|
||||
const Layer::State& s(layer->drawingState());
|
||||
@ -1485,7 +1478,7 @@ void SurfaceFlinger::handlePageFlip()
|
||||
const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
|
||||
const size_t count = currentLayers.size();
|
||||
for (size_t i=0 ; i<count ; i++) {
|
||||
const sp<LayerBase>& layer(currentLayers[i]);
|
||||
const sp<Layer>& layer(currentLayers[i]);
|
||||
const Region dirty(layer->latchBuffer(visibleRegions));
|
||||
const Layer::State& s(layer->drawingState());
|
||||
invalidateLayerStack(s.layerStack, dirty);
|
||||
@ -1607,13 +1600,13 @@ void SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const
|
||||
* and then, render the layers targeted at the framebuffer
|
||||
*/
|
||||
|
||||
const Vector< sp<LayerBase> >& layers(hw->getVisibleLayersSortedByZ());
|
||||
const Vector< sp<Layer> >& layers(hw->getVisibleLayersSortedByZ());
|
||||
const size_t count = layers.size();
|
||||
const Transform& tr = hw->getTransform();
|
||||
if (cur != end) {
|
||||
// we're using h/w composer
|
||||
for (size_t i=0 ; i<count && cur!=end ; ++i, ++cur) {
|
||||
const sp<LayerBase>& layer(layers[i]);
|
||||
const sp<Layer>& layer(layers[i]);
|
||||
const Region clip(dirty.intersect(tr.transform(layer->visibleRegion)));
|
||||
if (!clip.isEmpty()) {
|
||||
switch (cur->getCompositionType()) {
|
||||
@ -1645,7 +1638,7 @@ void SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const
|
||||
} else {
|
||||
// we're not using h/w composer
|
||||
for (size_t i=0 ; i<count ; ++i) {
|
||||
const sp<LayerBase>& layer(layers[i]);
|
||||
const sp<Layer>& layer(layers[i]);
|
||||
const Region clip(dirty.intersect(
|
||||
tr.transform(layer->visibleRegion)));
|
||||
if (!clip.isEmpty()) {
|
||||
@ -1684,7 +1677,7 @@ void SurfaceFlinger::drawWormhole(const sp<const DisplayDevice>& hw,
|
||||
|
||||
void SurfaceFlinger::addClientLayer(const sp<Client>& client,
|
||||
const sp<IBinder>& handle,
|
||||
const sp<LayerBaseClient>& lbc)
|
||||
const sp<Layer>& lbc)
|
||||
{
|
||||
// attach this layer to the client
|
||||
client->attachLayer(handle, lbc);
|
||||
@ -1694,7 +1687,7 @@ void SurfaceFlinger::addClientLayer(const sp<Client>& client,
|
||||
mCurrentState.layersSortedByZ.add(lbc);
|
||||
}
|
||||
|
||||
status_t SurfaceFlinger::removeLayer(const sp<LayerBase>& layer)
|
||||
status_t SurfaceFlinger::removeLayer(const sp<Layer>& layer)
|
||||
{
|
||||
Mutex::Autolock _l(mStateLock);
|
||||
status_t err = purgatorizeLayer_l(layer);
|
||||
@ -1703,9 +1696,9 @@ status_t SurfaceFlinger::removeLayer(const sp<LayerBase>& layer)
|
||||
return err;
|
||||
}
|
||||
|
||||
status_t SurfaceFlinger::removeLayer_l(const sp<LayerBase>& layerBase)
|
||||
status_t SurfaceFlinger::removeLayer_l(const sp<Layer>& layer)
|
||||
{
|
||||
ssize_t index = mCurrentState.layersSortedByZ.remove(layerBase);
|
||||
ssize_t index = mCurrentState.layersSortedByZ.remove(layer);
|
||||
if (index >= 0) {
|
||||
mLayersRemoved = true;
|
||||
return NO_ERROR;
|
||||
@ -1713,16 +1706,16 @@ status_t SurfaceFlinger::removeLayer_l(const sp<LayerBase>& layerBase)
|
||||
return status_t(index);
|
||||
}
|
||||
|
||||
status_t SurfaceFlinger::purgatorizeLayer_l(const sp<LayerBase>& layerBase)
|
||||
status_t SurfaceFlinger::purgatorizeLayer_l(const sp<Layer>& layer)
|
||||
{
|
||||
// First add the layer to the purgatory list, which makes sure it won't
|
||||
// go away, then remove it from the main list (through a transaction).
|
||||
ssize_t err = removeLayer_l(layerBase);
|
||||
ssize_t err = removeLayer_l(layer);
|
||||
if (err >= 0) {
|
||||
mLayerPurgatory.add(layerBase);
|
||||
mLayerPurgatory.add(layer);
|
||||
}
|
||||
|
||||
mLayersPendingRemoval.push(layerBase);
|
||||
mLayersPendingRemoval.push(layer);
|
||||
|
||||
// it's possible that we don't find a layer, because it might
|
||||
// have been destroyed already -- this is not technically an error
|
||||
@ -1873,7 +1866,7 @@ uint32_t SurfaceFlinger::setClientStateLocked(
|
||||
const layer_state_t& s)
|
||||
{
|
||||
uint32_t flags = 0;
|
||||
sp<LayerBaseClient> layer(client->getLayerUser(s.surface));
|
||||
sp<Layer> layer(client->getLayerUser(s.surface));
|
||||
if (layer != 0) {
|
||||
const uint32_t what = s.what;
|
||||
if (what & layer_state_t::ePositionChanged) {
|
||||
@ -1937,7 +1930,7 @@ sp<ISurface> SurfaceFlinger::createLayer(
|
||||
uint32_t w, uint32_t h, PixelFormat format,
|
||||
uint32_t flags)
|
||||
{
|
||||
sp<LayerBaseClient> layer;
|
||||
sp<Layer> layer;
|
||||
sp<ISurface> surfaceHandle;
|
||||
|
||||
if (int32_t(w|h) < 0) {
|
||||
@ -1951,13 +1944,9 @@ sp<ISurface> SurfaceFlinger::createLayer(
|
||||
case ISurfaceComposerClient::eFXSurfaceNormal:
|
||||
layer = createNormalLayer(client, w, h, flags, format);
|
||||
break;
|
||||
case ISurfaceComposerClient::eFXSurfaceBlur:
|
||||
case ISurfaceComposerClient::eFXSurfaceDim:
|
||||
layer = createDimLayer(client, w, h, flags);
|
||||
break;
|
||||
case ISurfaceComposerClient::eFXSurfaceScreenshot:
|
||||
layer = createScreenshotLayer(client, w, h, flags);
|
||||
break;
|
||||
}
|
||||
|
||||
if (layer != 0) {
|
||||
@ -2015,15 +2004,6 @@ sp<LayerDim> SurfaceFlinger::createDimLayer(
|
||||
return layer;
|
||||
}
|
||||
|
||||
sp<LayerScreenshot> SurfaceFlinger::createScreenshotLayer(
|
||||
const sp<Client>& client,
|
||||
uint32_t w, uint32_t h, uint32_t flags)
|
||||
{
|
||||
sp<LayerScreenshot> layer = new LayerScreenshot(this, client);
|
||||
layer->setBuffers(w, h, PIXEL_FORMAT_RGBA_8888, flags);
|
||||
return layer;
|
||||
}
|
||||
|
||||
status_t SurfaceFlinger::onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle)
|
||||
{
|
||||
/*
|
||||
@ -2037,7 +2017,7 @@ status_t SurfaceFlinger::onLayerRemoved(const sp<Client>& client, const sp<IBind
|
||||
|
||||
status_t err = NAME_NOT_FOUND;
|
||||
Mutex::Autolock _l(mStateLock);
|
||||
sp<LayerBaseClient> layer = client->getLayerUser(handle);
|
||||
sp<Layer> layer = client->getLayerUser(handle);
|
||||
|
||||
if (layer != 0) {
|
||||
err = purgatorizeLayer_l(layer);
|
||||
@ -2048,11 +2028,11 @@ status_t SurfaceFlinger::onLayerRemoved(const sp<Client>& client, const sp<IBind
|
||||
return err;
|
||||
}
|
||||
|
||||
status_t SurfaceFlinger::onLayerDestroyed(const wp<LayerBaseClient>& layer)
|
||||
status_t SurfaceFlinger::onLayerDestroyed(const wp<Layer>& layer)
|
||||
{
|
||||
// called by ~ISurface() when all references are gone
|
||||
status_t err = NO_ERROR;
|
||||
sp<LayerBaseClient> l(layer.promote());
|
||||
sp<Layer> l(layer.promote());
|
||||
if (l != NULL) {
|
||||
Mutex::Autolock _l(mStateLock);
|
||||
err = removeLayer_l(l);
|
||||
@ -2269,7 +2249,7 @@ void SurfaceFlinger::listLayersLocked(const Vector<String16>& args, size_t& inde
|
||||
const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
|
||||
const size_t count = currentLayers.size();
|
||||
for (size_t i=0 ; i<count ; i++) {
|
||||
const sp<LayerBase>& layer(currentLayers[i]);
|
||||
const sp<Layer>& layer(currentLayers[i]);
|
||||
snprintf(buffer, SIZE, "%s\n", layer->getName().string());
|
||||
result.append(buffer);
|
||||
}
|
||||
@ -2294,7 +2274,7 @@ void SurfaceFlinger::dumpStatsLocked(const Vector<String16>& args, size_t& index
|
||||
const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
|
||||
const size_t count = currentLayers.size();
|
||||
for (size_t i=0 ; i<count ; i++) {
|
||||
const sp<LayerBase>& layer(currentLayers[i]);
|
||||
const sp<Layer>& layer(currentLayers[i]);
|
||||
if (name == layer->getName()) {
|
||||
layer->dumpStats(result, buffer, SIZE);
|
||||
}
|
||||
@ -2314,7 +2294,7 @@ void SurfaceFlinger::clearStatsLocked(const Vector<String16>& args, size_t& inde
|
||||
const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
|
||||
const size_t count = currentLayers.size();
|
||||
for (size_t i=0 ; i<count ; i++) {
|
||||
const sp<LayerBase>& layer(currentLayers[i]);
|
||||
const sp<Layer>& layer(currentLayers[i]);
|
||||
if (name.isEmpty() || (name == layer->getName())) {
|
||||
layer->clearStats();
|
||||
}
|
||||
@ -2370,7 +2350,7 @@ void SurfaceFlinger::dumpAllLocked(
|
||||
snprintf(buffer, SIZE, "Visible layers (count = %d)\n", count);
|
||||
result.append(buffer);
|
||||
for (size_t i=0 ; i<count ; i++) {
|
||||
const sp<LayerBase>& layer(currentLayers[i]);
|
||||
const sp<Layer>& layer(currentLayers[i]);
|
||||
layer->dump(result, buffer, SIZE);
|
||||
}
|
||||
|
||||
@ -2382,7 +2362,7 @@ void SurfaceFlinger::dumpAllLocked(
|
||||
snprintf(buffer, SIZE, "Purgatory state (%d entries)\n", purgatorySize);
|
||||
result.append(buffer);
|
||||
for (size_t i=0 ; i<purgatorySize ; i++) {
|
||||
const sp<LayerBase>& layer(mLayerPurgatory.itemAt(i));
|
||||
const sp<Layer>& layer(mLayerPurgatory.itemAt(i));
|
||||
layer->shortDump(result, buffer, SIZE);
|
||||
}
|
||||
|
||||
@ -2471,7 +2451,7 @@ void SurfaceFlinger::dumpAllLocked(
|
||||
alloc.dump(result);
|
||||
}
|
||||
|
||||
const Vector< sp<LayerBase> >&
|
||||
const Vector< sp<Layer> >&
|
||||
SurfaceFlinger::getLayerSortedByZForHwcDisplay(int disp) {
|
||||
// Note: mStateLock is held here
|
||||
return getDisplayDevice( getBuiltInDisplay(disp) )->getVisibleLayersSortedByZ();
|
||||
@ -2728,10 +2708,10 @@ status_t SurfaceFlinger::captureScreenImplLocked(
|
||||
glClearColor(0,0,0,1);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
const Vector< sp<LayerBase> >& layers(hw->getVisibleLayersSortedByZ());
|
||||
const Vector< sp<Layer> >& layers(hw->getVisibleLayersSortedByZ());
|
||||
const size_t count = layers.size();
|
||||
for (size_t i=0 ; i<count ; ++i) {
|
||||
const sp<LayerBase>& layer(layers[i]);
|
||||
const sp<Layer>& layer(layers[i]);
|
||||
const uint32_t z = layer->drawingState().z;
|
||||
if (z >= minLayerZ && z <= maxLayerZ) {
|
||||
if (filtering) layer->setFiltering(true);
|
||||
@ -2896,15 +2876,15 @@ SurfaceFlinger::LayerVector::LayerVector() {
|
||||
}
|
||||
|
||||
SurfaceFlinger::LayerVector::LayerVector(const LayerVector& rhs)
|
||||
: SortedVector<sp<LayerBase> >(rhs) {
|
||||
: SortedVector<sp<Layer> >(rhs) {
|
||||
}
|
||||
|
||||
int SurfaceFlinger::LayerVector::do_compare(const void* lhs,
|
||||
const void* rhs) const
|
||||
{
|
||||
// sort layers per layer-stack, then by z-order and finally by sequence
|
||||
const sp<LayerBase>& l(*reinterpret_cast<const sp<LayerBase>*>(lhs));
|
||||
const sp<LayerBase>& r(*reinterpret_cast<const sp<LayerBase>*>(rhs));
|
||||
const sp<Layer>& l(*reinterpret_cast<const sp<Layer>*>(lhs));
|
||||
const sp<Layer>& r(*reinterpret_cast<const sp<Layer>*>(rhs));
|
||||
|
||||
uint32_t ls = l->currentState().layerStack;
|
||||
uint32_t rs = r->currentState().layerStack;
|
||||
|
@ -60,10 +60,7 @@ class DisplayEventConnection;
|
||||
class EventThread;
|
||||
class IGraphicBufferAlloc;
|
||||
class Layer;
|
||||
class LayerBase;
|
||||
class LayerBaseClient;
|
||||
class LayerDim;
|
||||
class LayerScreenshot;
|
||||
class Surface;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@ -125,15 +122,12 @@ public:
|
||||
|
||||
// for debugging only
|
||||
// TODO: this should be made accessible only to HWComposer
|
||||
const Vector< sp<LayerBase> >& getLayerSortedByZForHwcDisplay(int disp);
|
||||
const Vector< sp<Layer> >& getLayerSortedByZForHwcDisplay(int disp);
|
||||
|
||||
private:
|
||||
friend class Client;
|
||||
friend class DisplayEventConnection;
|
||||
friend class LayerBase;
|
||||
friend class LayerBaseClient;
|
||||
friend class Layer;
|
||||
friend class LayerScreenshot;
|
||||
|
||||
// We're reference counted, never destroy SurfaceFlinger directly
|
||||
virtual ~SurfaceFlinger();
|
||||
@ -142,7 +136,7 @@ private:
|
||||
* Internal data structures
|
||||
*/
|
||||
|
||||
class LayerVector : public SortedVector<sp<LayerBase> > {
|
||||
class LayerVector : public SortedVector< sp<Layer> > {
|
||||
public:
|
||||
LayerVector();
|
||||
LayerVector(const LayerVector& rhs);
|
||||
@ -272,9 +266,6 @@ private:
|
||||
sp<LayerDim> createDimLayer(const sp<Client>& client,
|
||||
uint32_t w, uint32_t h, uint32_t flags);
|
||||
|
||||
sp<LayerScreenshot> createScreenshotLayer(const sp<Client>& client,
|
||||
uint32_t w, uint32_t h, uint32_t flags);
|
||||
|
||||
// called in response to the window-manager calling
|
||||
// ISurfaceComposerClient::destroySurface()
|
||||
// The specified layer is first placed in a purgatory list
|
||||
@ -284,17 +275,17 @@ private:
|
||||
// called when all clients have released all their references to
|
||||
// this layer meaning it is entirely safe to destroy all
|
||||
// resources associated to this layer.
|
||||
status_t onLayerDestroyed(const wp<LayerBaseClient>& layer);
|
||||
status_t onLayerDestroyed(const wp<Layer>& layer);
|
||||
|
||||
// remove a layer from SurfaceFlinger immediately
|
||||
status_t removeLayer(const sp<LayerBase>& layer);
|
||||
status_t removeLayer(const sp<Layer>& layer);
|
||||
|
||||
// add a layer to SurfaceFlinger
|
||||
void addClientLayer(const sp<Client>& client, const sp<IBinder>& handle,
|
||||
const sp<LayerBaseClient>& lbc);
|
||||
const sp<Layer>& lbc);
|
||||
|
||||
status_t removeLayer_l(const sp<LayerBase>& layer);
|
||||
status_t purgatorizeLayer_l(const sp<LayerBase>& layer);
|
||||
status_t removeLayer_l(const sp<Layer>& layer);
|
||||
status_t purgatorizeLayer_l(const sp<Layer>& layer);
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
* Boot animation, on/off animations and screen capture
|
||||
@ -408,10 +399,10 @@ private:
|
||||
State mCurrentState;
|
||||
volatile int32_t mTransactionFlags;
|
||||
Condition mTransactionCV;
|
||||
SortedVector<sp<LayerBase> > mLayerPurgatory;
|
||||
SortedVector< sp<Layer> > mLayerPurgatory;
|
||||
bool mTransactionPending;
|
||||
bool mAnimTransactionPending;
|
||||
Vector<sp<LayerBase> > mLayersPendingRemoval;
|
||||
Vector< sp<Layer> > mLayersPendingRemoval;
|
||||
|
||||
// protected by mStateLock (but we could use another lock)
|
||||
bool mLayersRemoved;
|
||||
@ -460,7 +451,7 @@ private:
|
||||
|
||||
// protected by mDestroyedLayerLock;
|
||||
mutable Mutex mDestroyedLayerLock;
|
||||
Vector<LayerBase const *> mDestroyedLayers;
|
||||
Vector<Layer const *> mDestroyedLayers;
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
* Feature prototyping
|
||||
|
Loading…
Reference in New Issue
Block a user