one more step towards multiple display support
- remove dependency on cached state in validateVisibility - get rid of mVertices and mTransformedBounds - get rid of validateVisibility - get rid of unlockPageFlip - handleTransaction now returns a dirty region - computevisibileregion now uses window-manager space
This commit is contained in:
parent
e7db724bed
commit
4fec873a98
|
@ -72,11 +72,11 @@ public:
|
|||
|
||||
//! returns number of items in the vector
|
||||
inline size_t size() const { return VectorImpl::size(); }
|
||||
//! returns wether or not the vector is empty
|
||||
//! returns whether or not the vector is empty
|
||||
inline bool isEmpty() const { return VectorImpl::isEmpty(); }
|
||||
//! returns how many items can be stored without reallocating the backing store
|
||||
inline size_t capacity() const { return VectorImpl::capacity(); }
|
||||
//! setst the capacity. capacity can never be reduced less than size()
|
||||
//! sets the capacity. capacity can never be reduced less than size()
|
||||
inline ssize_t setCapacity(size_t size) { return VectorImpl::setCapacity(size); }
|
||||
|
||||
/*!
|
||||
|
@ -102,12 +102,12 @@ public:
|
|||
const TYPE& mirrorItemAt(ssize_t index) const;
|
||||
|
||||
/*!
|
||||
* modifing the array
|
||||
* modifying the array
|
||||
*/
|
||||
|
||||
//! copy-on write support, grants write access to an item
|
||||
TYPE& editItemAt(size_t index);
|
||||
//! grants right acces to the top of the stack (last element)
|
||||
//! grants right access to the top of the stack (last element)
|
||||
TYPE& editTop();
|
||||
|
||||
/*!
|
||||
|
|
|
@ -145,14 +145,6 @@ void Layer::setName(const String8& name) {
|
|||
mSurfaceTexture->setName(name);
|
||||
}
|
||||
|
||||
void Layer::validateVisibility(const Transform& globalTransform, const DisplayHardware& hw) {
|
||||
LayerBase::validateVisibility(globalTransform, hw);
|
||||
|
||||
// This optimization allows the SurfaceTexture to bake in
|
||||
// the rotation so hardware overlays can be used
|
||||
mSurfaceTexture->setTransformHint(getTransformHint());
|
||||
}
|
||||
|
||||
sp<ISurface> Layer::createSurface()
|
||||
{
|
||||
class BSurface : public BnSurface, public LayerCleaner {
|
||||
|
@ -225,7 +217,8 @@ Rect Layer::computeBufferCrop() const {
|
|||
} else if (mActiveBuffer != NULL){
|
||||
crop = Rect(mActiveBuffer->getWidth(), mActiveBuffer->getHeight());
|
||||
} else {
|
||||
crop = Rect(mTransformedBounds.width(), mTransformedBounds.height());
|
||||
crop.makeInvalid();
|
||||
return crop;
|
||||
}
|
||||
|
||||
// ... then reduce that in the same proportions as the window crop reduces
|
||||
|
@ -258,9 +251,11 @@ Rect Layer::computeBufferCrop() const {
|
|||
return crop;
|
||||
}
|
||||
|
||||
void Layer::setGeometry(HWComposer::HWCLayerInterface& layer)
|
||||
void Layer::setGeometry(
|
||||
const DisplayHardware& hw,
|
||||
HWComposer::HWCLayerInterface& layer)
|
||||
{
|
||||
LayerBaseClient::setGeometry(layer);
|
||||
LayerBaseClient::setGeometry(hw, layer);
|
||||
|
||||
// enable this layer
|
||||
layer.setSkip(false);
|
||||
|
@ -276,12 +271,11 @@ void Layer::setGeometry(HWComposer::HWCLayerInterface& layer)
|
|||
* 1) buffer orientation/flip/mirror
|
||||
* 2) state transformation (window manager)
|
||||
* 3) layer orientation (screen orientation)
|
||||
* mTransform is already the composition of (2) and (3)
|
||||
* (NOTE: the matrices are multiplied in reverse order)
|
||||
*/
|
||||
|
||||
const Transform bufferOrientation(mCurrentTransform);
|
||||
const Transform tr(mTransform * bufferOrientation);
|
||||
const Transform tr(hw.getTransform() * s.transform * bufferOrientation);
|
||||
|
||||
// this gives us only the "orientation" component of the transform
|
||||
const uint32_t finalTransform = tr.getOrientation();
|
||||
|
@ -339,7 +333,7 @@ void Layer::onDraw(const DisplayHardware& hw, const Region& clip) const
|
|||
const sp<LayerBase>& layer(drawingLayers[i]);
|
||||
if (layer.get() == static_cast<LayerBase const*>(this))
|
||||
break;
|
||||
under.orSelf(layer->visibleRegionScreen);
|
||||
under.orSelf( hw.getTransform().transform(layer->visibleRegion) );
|
||||
}
|
||||
// if not everything below us is covered, we plug the holes!
|
||||
Region holes(clip.subtract(under));
|
||||
|
@ -527,10 +521,11 @@ bool Layer::onPreComposition() {
|
|||
return mQueuedFrames > 0;
|
||||
}
|
||||
|
||||
void Layer::lockPageFlip(bool& recomputeVisibleRegions)
|
||||
Region Layer::latchBuffer(bool& recomputeVisibleRegions)
|
||||
{
|
||||
ATRACE_CALL();
|
||||
|
||||
Region outDirtyRegion;
|
||||
if (mQueuedFrames > 0) {
|
||||
|
||||
// if we've already called updateTexImage() without going through
|
||||
|
@ -539,8 +534,7 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions)
|
|||
// compositionComplete() call.
|
||||
// we'll trigger an update in onPreComposition().
|
||||
if (mRefreshPending) {
|
||||
mPostedDirtyRegion.clear();
|
||||
return;
|
||||
return outDirtyRegion;
|
||||
}
|
||||
|
||||
// Capture the old state of the layer for comparisons later
|
||||
|
@ -637,17 +631,21 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions)
|
|||
|
||||
Reject r(mDrawingState, currentState(), recomputeVisibleRegions);
|
||||
|
||||
// XXX: not sure if setTransformHint belongs here
|
||||
// it should only be needed when the main screen orientation changes
|
||||
mSurfaceTexture->setTransformHint(getTransformHint());
|
||||
|
||||
if (mSurfaceTexture->updateTexImage(&r) < NO_ERROR) {
|
||||
// something happened!
|
||||
recomputeVisibleRegions = true;
|
||||
return;
|
||||
return outDirtyRegion;
|
||||
}
|
||||
|
||||
// update the active buffer
|
||||
mActiveBuffer = mSurfaceTexture->getCurrentBuffer();
|
||||
if (mActiveBuffer == NULL) {
|
||||
// this can only happen if the very first buffer was rejected.
|
||||
return;
|
||||
return outDirtyRegion;
|
||||
}
|
||||
|
||||
mRefreshPending = true;
|
||||
|
@ -686,38 +684,17 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions)
|
|||
recomputeVisibleRegions = true;
|
||||
}
|
||||
|
||||
// FIXME: mPostedDirtyRegion = dirty & bounds
|
||||
const Layer::State& front(drawingState());
|
||||
mPostedDirtyRegion.set(front.active.w, front.active.h);
|
||||
|
||||
glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
// FIXME: postedRegion should be dirty & bounds
|
||||
const Layer::State& front(drawingState());
|
||||
Region dirtyRegion(Rect(front.active.w, front.active.h));
|
||||
|
||||
// transform the dirty region to window-manager space
|
||||
outDirtyRegion = (front.transform.transform(dirtyRegion));
|
||||
}
|
||||
}
|
||||
|
||||
void Layer::unlockPageFlip(
|
||||
const Transform& planeTransform, Region& outDirtyRegion)
|
||||
{
|
||||
ATRACE_CALL();
|
||||
|
||||
Region postedRegion(mPostedDirtyRegion);
|
||||
if (!postedRegion.isEmpty()) {
|
||||
mPostedDirtyRegion.clear();
|
||||
if (!visibleRegionScreen.isEmpty()) {
|
||||
// The dirty region is given in the layer's coordinate space
|
||||
// transform the dirty region by the surface's transformation
|
||||
// and the global transformation.
|
||||
const Layer::State& s(drawingState());
|
||||
const Transform tr(planeTransform * s.transform);
|
||||
postedRegion = tr.transform(postedRegion);
|
||||
|
||||
// At this point, the dirty region is in screen space.
|
||||
// Make sure it's constrained by the visible region (which
|
||||
// is in screen space as well).
|
||||
postedRegion.andSelf(visibleRegionScreen);
|
||||
outDirtyRegion.orSelf(postedRegion);
|
||||
}
|
||||
}
|
||||
return outDirtyRegion;
|
||||
}
|
||||
|
||||
void Layer::dump(String8& result, char* buffer, size_t SIZE) const
|
||||
|
@ -786,7 +763,14 @@ uint32_t Layer::getEffectiveUsage(uint32_t usage) const
|
|||
uint32_t Layer::getTransformHint() const {
|
||||
uint32_t orientation = 0;
|
||||
if (!mFlinger->mDebugDisableTransformHint) {
|
||||
orientation = getPlaneOrientation();
|
||||
// The transform hint is used to improve performance on the main
|
||||
// display -- we can only have a single transform hint, it cannot
|
||||
// apply to all displays.
|
||||
// This is why we use the default display here. This is not an
|
||||
// oversight.
|
||||
const DisplayHardware& hw(mFlinger->getDefaultDisplayHardware());
|
||||
const Transform& planeTransform(hw.getTransform());
|
||||
orientation = planeTransform.getOrientation();
|
||||
if (orientation & Transform::ROT_INVALID) {
|
||||
orientation = 0;
|
||||
}
|
||||
|
|
|
@ -64,20 +64,20 @@ public:
|
|||
bool isFixedSize() const;
|
||||
|
||||
// LayerBase interface
|
||||
virtual void setGeometry(HWComposer::HWCLayerInterface& layer);
|
||||
virtual void setGeometry(const DisplayHardware& hw,
|
||||
HWComposer::HWCLayerInterface& layer);
|
||||
virtual void setPerFrameData(HWComposer::HWCLayerInterface& layer);
|
||||
virtual void setAcquireFence(HWComposer::HWCLayerInterface& layer);
|
||||
|
||||
virtual void onDraw(const DisplayHardware& hw, const Region& clip) const;
|
||||
virtual uint32_t doTransaction(uint32_t transactionFlags);
|
||||
virtual void lockPageFlip(bool& recomputeVisibleRegions);
|
||||
virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion);
|
||||
virtual Region latchBuffer(bool& recomputeVisibleRegions);
|
||||
virtual bool isOpaque() const;
|
||||
virtual bool isSecure() const { return mSecure; }
|
||||
virtual bool isProtected() const;
|
||||
virtual void onRemoved();
|
||||
virtual sp<Layer> getLayer() const { return const_cast<Layer*>(this); }
|
||||
virtual void setName(const String8& name);
|
||||
virtual void validateVisibility(const Transform& globalTransform, const DisplayHardware& hw);
|
||||
|
||||
// LayerBaseClient interface
|
||||
virtual wp<IBinder> getSurfaceTextureBinder() const;
|
||||
|
@ -142,7 +142,6 @@ private:
|
|||
// page-flip thread (currently main thread)
|
||||
bool mSecure; // no screenshots
|
||||
bool mProtectedByApp; // application requires protected path to external sink
|
||||
Region mPostedDirtyRegion;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
|
@ -45,8 +45,6 @@ LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display)
|
|||
sequence(uint32_t(android_atomic_inc(&sSequence))),
|
||||
mFlinger(flinger), mFiltering(false),
|
||||
mNeedsFiltering(false),
|
||||
mOrientation(0),
|
||||
mPlaneOrientation(0),
|
||||
mTransactionFlags(0),
|
||||
mPremultipliedAlpha(true), mName("unnamed"), mDebug(false)
|
||||
{
|
||||
|
@ -170,19 +168,14 @@ bool LayerBase::setCrop(const Rect& crop) {
|
|||
return true;
|
||||
}
|
||||
|
||||
Rect LayerBase::visibleBounds() const
|
||||
{
|
||||
return mTransformedBounds;
|
||||
}
|
||||
|
||||
void LayerBase::setVisibleRegion(const Region& visibleRegion) {
|
||||
// always called from main thread
|
||||
visibleRegionScreen = visibleRegion;
|
||||
this->visibleRegion = visibleRegion;
|
||||
}
|
||||
|
||||
void LayerBase::setCoveredRegion(const Region& coveredRegion) {
|
||||
// always called from main thread
|
||||
coveredRegionScreen = coveredRegion;
|
||||
this->coveredRegion = coveredRegion;
|
||||
}
|
||||
|
||||
uint32_t LayerBase::doTransaction(uint32_t flags)
|
||||
|
@ -219,57 +212,45 @@ uint32_t LayerBase::doTransaction(uint32_t flags)
|
|||
return flags;
|
||||
}
|
||||
|
||||
void LayerBase::validateVisibility(const Transform& planeTransform, const DisplayHardware& hw)
|
||||
void LayerBase::computeGeometry(const DisplayHardware& hw, LayerMesh* mesh) const
|
||||
{
|
||||
const Layer::State& s(drawingState());
|
||||
const Transform tr(planeTransform * s.transform);
|
||||
const bool transformed = tr.transformed();
|
||||
const Transform tr(hw.getTransform() * s.transform);
|
||||
const uint32_t hw_h = hw.getHeight();
|
||||
const Rect& crop(s.active.crop);
|
||||
|
||||
Rect win(s.active.w, s.active.h);
|
||||
if (!crop.isEmpty()) {
|
||||
win.intersect(crop, &win);
|
||||
}
|
||||
|
||||
mNumVertices = 4;
|
||||
tr.transform(mVertices[0], win.left, win.top);
|
||||
tr.transform(mVertices[1], win.left, win.bottom);
|
||||
tr.transform(mVertices[2], win.right, win.bottom);
|
||||
tr.transform(mVertices[3], win.right, win.top);
|
||||
for (size_t i=0 ; i<4 ; i++)
|
||||
mVertices[i][1] = hw_h - mVertices[i][1];
|
||||
|
||||
if (CC_UNLIKELY(transformed)) {
|
||||
// NOTE: here we could also punt if we have too many rectangles
|
||||
// in the transparent region
|
||||
if (tr.preserveRects()) {
|
||||
// transform the transparent region
|
||||
transparentRegionScreen = tr.transform(s.transparentRegion);
|
||||
} else {
|
||||
// transformation too complex, can't do the transparent region
|
||||
// optimization.
|
||||
transparentRegionScreen.clear();
|
||||
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];
|
||||
}
|
||||
} else {
|
||||
transparentRegionScreen = s.transparentRegion;
|
||||
}
|
||||
|
||||
// cache a few things...
|
||||
mOrientation = tr.getOrientation();
|
||||
mPlaneOrientation = planeTransform.getOrientation();
|
||||
mTransform = tr;
|
||||
mTransformedBounds = tr.transform(win);
|
||||
}
|
||||
|
||||
void LayerBase::lockPageFlip(bool& recomputeVisibleRegions) {
|
||||
Rect LayerBase::computeBounds() const {
|
||||
const Layer::State& s(drawingState());
|
||||
const Rect& crop(s.active.crop);
|
||||
Rect win(s.active.w, s.active.h);
|
||||
if (!crop.isEmpty()) {
|
||||
win.intersect(crop, &win);
|
||||
}
|
||||
return s.transform.transform(win);
|
||||
}
|
||||
|
||||
void LayerBase::unlockPageFlip(
|
||||
const Transform& planeTransform, Region& outDirtyRegion) {
|
||||
Region LayerBase::latchBuffer(bool& recomputeVisibleRegions) {
|
||||
Region result;
|
||||
return result;
|
||||
}
|
||||
|
||||
void LayerBase::setGeometry(HWComposer::HWCLayerInterface& layer)
|
||||
void LayerBase::setGeometry(
|
||||
const DisplayHardware& hw,
|
||||
HWComposer::HWCLayerInterface& layer)
|
||||
{
|
||||
layer.setDefaultState();
|
||||
|
||||
|
@ -289,10 +270,14 @@ void LayerBase::setGeometry(HWComposer::HWCLayerInterface& layer)
|
|||
HWC_BLENDING_COVERAGE);
|
||||
}
|
||||
|
||||
// scaling is already applied in mTransformedBounds
|
||||
layer.setFrame(mTransformedBounds);
|
||||
layer.setVisibleRegionScreen(visibleRegionScreen);
|
||||
layer.setCrop(mTransformedBounds.getBounds());
|
||||
const Transform& tr = hw.getTransform();
|
||||
Rect transformedBounds(computeBounds());
|
||||
transformedBounds = tr.transform(transformedBounds);
|
||||
|
||||
// scaling is already applied in transformedBounds
|
||||
layer.setFrame(transformedBounds);
|
||||
layer.setCrop(transformedBounds.getBounds());
|
||||
layer.setVisibleRegionScreen(tr.transform(visibleRegion));
|
||||
}
|
||||
|
||||
void LayerBase::setPerFrameData(HWComposer::HWCLayerInterface& layer) {
|
||||
|
@ -335,8 +320,11 @@ void LayerBase::clearWithOpenGL(const DisplayHardware& hw, const Region& clip,
|
|||
glDisable(GL_TEXTURE_2D);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
glVertexPointer(2, GL_FLOAT, 0, mVertices);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, mNumVertices);
|
||||
LayerMesh mesh;
|
||||
computeGeometry(hw, &mesh);
|
||||
|
||||
glVertexPointer(2, GL_FLOAT, 0, mesh.getVertices());
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, mesh.getVertexCount());
|
||||
}
|
||||
|
||||
void LayerBase::clearWithOpenGL(const DisplayHardware& hw, const Region& clip) const
|
||||
|
@ -371,6 +359,12 @@ void LayerBase::drawWithOpenGL(const DisplayHardware& hw, const Region& clip) co
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -380,9 +374,9 @@ void LayerBase::drawWithOpenGL(const DisplayHardware& hw, const Region& clip) co
|
|||
if (!s.active.crop.isEmpty()) {
|
||||
crop = s.active.crop;
|
||||
}
|
||||
GLfloat left = GLfloat(crop.left) / GLfloat(s.active.w);
|
||||
GLfloat top = GLfloat(crop.top) / GLfloat(s.active.h);
|
||||
GLfloat right = GLfloat(crop.right) / GLfloat(s.active.w);
|
||||
GLfloat left = GLfloat(crop.left) / GLfloat(s.active.w);
|
||||
GLfloat top = GLfloat(crop.top) / GLfloat(s.active.h);
|
||||
GLfloat right = GLfloat(crop.right) / GLfloat(s.active.w);
|
||||
GLfloat bottom = GLfloat(crop.bottom) / GLfloat(s.active.h);
|
||||
|
||||
TexCoords texCoords[4];
|
||||
|
@ -399,9 +393,9 @@ void LayerBase::drawWithOpenGL(const DisplayHardware& hw, const Region& clip) co
|
|||
}
|
||||
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glVertexPointer(2, GL_FLOAT, 0, mVertices);
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, mNumVertices);
|
||||
glVertexPointer(2, GL_FLOAT, 0, mesh.getVertices());
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, mesh.getVertexCount());
|
||||
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisable(GL_BLEND);
|
||||
|
@ -417,8 +411,7 @@ void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const
|
|||
result.append(buffer);
|
||||
|
||||
s.transparentRegion.dump(result, "transparentRegion");
|
||||
transparentRegionScreen.dump(result, "transparentRegionScreen");
|
||||
visibleRegionScreen.dump(result, "visibleRegionScreen");
|
||||
visibleRegion.dump(result, "visibleRegion");
|
||||
|
||||
snprintf(buffer, SIZE,
|
||||
" "
|
||||
|
|
|
@ -57,9 +57,9 @@ public:
|
|||
|
||||
DisplayID dpy;
|
||||
mutable bool contentDirty;
|
||||
Region visibleRegionScreen;
|
||||
Region transparentRegionScreen;
|
||||
Region coveredRegionScreen;
|
||||
// regions below are in window-manager space
|
||||
Region visibleRegion;
|
||||
Region coveredRegion;
|
||||
int32_t sequence;
|
||||
|
||||
struct Geometry {
|
||||
|
@ -86,6 +86,20 @@ public:
|
|||
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;
|
||||
|
||||
|
@ -105,15 +119,18 @@ public:
|
|||
|
||||
uint32_t getTransactionFlags(uint32_t flags);
|
||||
uint32_t setTransactionFlags(uint32_t flags);
|
||||
|
||||
Rect visibleBounds() const;
|
||||
|
||||
void computeGeometry(const DisplayHardware& hw, LayerMesh* mesh) const;
|
||||
Rect computeBounds() const;
|
||||
|
||||
|
||||
virtual sp<LayerBaseClient> getLayerBaseClient() const { return 0; }
|
||||
virtual sp<Layer> getLayer() const { return 0; }
|
||||
|
||||
virtual const char* getTypeId() const { return "LayerBase"; }
|
||||
|
||||
virtual void setGeometry(HWComposer::HWCLayerInterface& layer);
|
||||
virtual void setGeometry(const DisplayHardware& hw,
|
||||
HWComposer::HWCLayerInterface& layer);
|
||||
virtual void setPerFrameData(HWComposer::HWCLayerInterface& layer);
|
||||
virtual void setAcquireFence(HWComposer::HWCLayerInterface& layer);
|
||||
|
||||
|
@ -156,26 +173,13 @@ public:
|
|||
virtual void setCoveredRegion(const Region& coveredRegion);
|
||||
|
||||
/**
|
||||
* validateVisibility - cache a bunch of things
|
||||
*/
|
||||
virtual void validateVisibility(const Transform& globalTransform, const DisplayHardware& hw);
|
||||
|
||||
/**
|
||||
* lockPageFlip - called each time the screen is redrawn and returns whether
|
||||
* 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 void lockPageFlip(bool& recomputeVisibleRegions);
|
||||
|
||||
/**
|
||||
* unlockPageFlip - called each time the screen is redrawn. updates the
|
||||
* final dirty region wrt the planeTransform.
|
||||
* At this point, all visible regions, surface position and size, etc... are
|
||||
* correct.
|
||||
*/
|
||||
virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion);
|
||||
|
||||
virtual Region latchBuffer(bool& recomputeVisibleRegions);
|
||||
|
||||
/**
|
||||
* isOpaque - true if this surface is opaque
|
||||
*/
|
||||
|
@ -233,9 +237,6 @@ public:
|
|||
inline const State& currentState() const { return mCurrentState; }
|
||||
inline State& currentState() { return mCurrentState; }
|
||||
|
||||
int32_t getOrientation() const { return mOrientation; }
|
||||
int32_t getPlaneOrientation() const { return mPlaneOrientation; }
|
||||
|
||||
void clearWithOpenGL(const DisplayHardware& hw, const Region& clip) const;
|
||||
|
||||
protected:
|
||||
|
@ -253,19 +254,10 @@ private:
|
|||
// Whether filtering is forced on or not
|
||||
bool mFiltering;
|
||||
|
||||
// cached during validateVisibility()
|
||||
// Whether filtering is needed b/c of the drawingstate
|
||||
bool mNeedsFiltering;
|
||||
|
||||
protected:
|
||||
// cached during validateVisibility()
|
||||
int32_t mOrientation;
|
||||
int32_t mPlaneOrientation;
|
||||
Transform mTransform;
|
||||
GLfloat mVertices[4][2];
|
||||
size_t mNumVertices;
|
||||
Rect mTransformedBounds;
|
||||
|
||||
// these are protected by an external lock
|
||||
State mCurrentState;
|
||||
State mDrawingState;
|
||||
|
|
|
@ -58,8 +58,11 @@ void LayerDim::onDraw(const DisplayHardware& hw, const Region& clip) const
|
|||
|
||||
glColor4f(0, 0, 0, alpha);
|
||||
|
||||
glVertexPointer(2, GL_FLOAT, 0, mVertices);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
LayerMesh mesh;
|
||||
computeGeometry(hw, &mesh);
|
||||
|
||||
glVertexPointer(2, GL_FLOAT, 0, mesh.getVertices());
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, mesh.getVertexCount());
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
|
|
@ -120,6 +120,9 @@ void LayerScreenshot::onDraw(const DisplayHardware& hw, const Region& clip) cons
|
|||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
LayerMesh mesh;
|
||||
computeGeometry(hw, &mesh);
|
||||
|
||||
glColor4f(0, 0, 0, alpha);
|
||||
|
||||
glDisable(GL_TEXTURE_EXTERNAL_OES);
|
||||
|
@ -133,8 +136,8 @@ void LayerScreenshot::onDraw(const DisplayHardware& hw, const Region& clip) cons
|
|||
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, mTexCoords);
|
||||
glVertexPointer(2, GL_FLOAT, 0, mVertices);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, mNumVertices);
|
||||
glVertexPointer(2, GL_FLOAT, 0, mesh.getVertices());
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, mesh.getVertexCount());
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
|
|
@ -49,13 +49,13 @@ void MessageBase::handleMessage(const Message&) {
|
|||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
void MessageQueue::Handler::signalRefresh() {
|
||||
void MessageQueue::Handler::dispatchRefresh() {
|
||||
if ((android_atomic_or(eventMaskRefresh, &mEventMask) & eventMaskRefresh) == 0) {
|
||||
mQueue.mLooper->sendMessage(this, Message(MessageQueue::REFRESH));
|
||||
}
|
||||
}
|
||||
|
||||
void MessageQueue::Handler::signalInvalidate() {
|
||||
void MessageQueue::Handler::dispatchInvalidate() {
|
||||
if ((android_atomic_or(eventMaskInvalidate, &mEventMask) & eventMaskInvalidate) == 0) {
|
||||
mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE));
|
||||
}
|
||||
|
@ -132,13 +132,31 @@ status_t MessageQueue::postMessage(
|
|||
return NO_ERROR;
|
||||
}
|
||||
|
||||
/* when INVALIDATE_ON_VSYNC is set SF only processes
|
||||
* buffer updates on VSYNC and performs a refresh immediately
|
||||
* after.
|
||||
*
|
||||
* when INVALIDATE_ON_VSYNC is set to false, SF will instead
|
||||
* perform the buffer updates immediately, but the refresh only
|
||||
* at the next VSYNC.
|
||||
* THIS MODE IS BUGGY ON GALAXY NEXUS AND WILL CAUSE HANGS
|
||||
*/
|
||||
#define INVALIDATE_ON_VSYNC 1
|
||||
|
||||
void MessageQueue::invalidate() {
|
||||
// mHandler->signalInvalidate();
|
||||
#if INVALIDATE_ON_VSYNC
|
||||
mEvents->requestNextVsync();
|
||||
#else
|
||||
mHandler->dispatchInvalidate();
|
||||
#endif
|
||||
}
|
||||
|
||||
void MessageQueue::refresh() {
|
||||
#if INVALIDATE_ON_VSYNC
|
||||
mHandler->dispatchRefresh();
|
||||
#else
|
||||
mEvents->requestNextVsync();
|
||||
#endif
|
||||
}
|
||||
|
||||
int MessageQueue::cb_eventReceiver(int fd, int events, void* data) {
|
||||
|
@ -152,7 +170,11 @@ int MessageQueue::eventReceiver(int fd, int events) {
|
|||
while ((n = DisplayEventReceiver::getEvents(mEventTube, buffer, 8)) > 0) {
|
||||
for (int i=0 ; i<n ; i++) {
|
||||
if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
|
||||
mHandler->signalRefresh();
|
||||
#if INVALIDATE_ON_VSYNC
|
||||
mHandler->dispatchInvalidate();
|
||||
#else
|
||||
mHandler->dispatchRefresh();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,8 +70,8 @@ class MessageQueue {
|
|||
public:
|
||||
Handler(MessageQueue& queue) : mQueue(queue), mEventMask(0) { }
|
||||
virtual void handleMessage(const Message& message);
|
||||
void signalRefresh();
|
||||
void signalInvalidate();
|
||||
void dispatchRefresh();
|
||||
void dispatchInvalidate();
|
||||
};
|
||||
|
||||
friend class Handler;
|
||||
|
|
|
@ -425,100 +425,117 @@ status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg,
|
|||
return res;
|
||||
}
|
||||
|
||||
bool SurfaceFlinger::threadLoop()
|
||||
{
|
||||
bool SurfaceFlinger::threadLoop() {
|
||||
waitForEvent();
|
||||
return true;
|
||||
}
|
||||
|
||||
void SurfaceFlinger::onMessageReceived(int32_t what)
|
||||
{
|
||||
void SurfaceFlinger::onMessageReceived(int32_t what) {
|
||||
ATRACE_CALL();
|
||||
switch (what) {
|
||||
case MessageQueue::REFRESH: {
|
||||
// case MessageQueue::INVALIDATE: {
|
||||
// if we're in a global transaction, don't do anything.
|
||||
const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
|
||||
uint32_t transactionFlags = peekTransactionFlags(mask);
|
||||
if (CC_UNLIKELY(transactionFlags)) {
|
||||
handleTransaction(transactionFlags);
|
||||
}
|
||||
|
||||
// post surfaces (if needed)
|
||||
handlePageFlip();
|
||||
|
||||
// signalRefresh();
|
||||
//
|
||||
// } break;
|
||||
//
|
||||
// case MessageQueue::REFRESH: {
|
||||
|
||||
handleRefresh();
|
||||
|
||||
// TODO: iterate through all displays
|
||||
const DisplayHardware& hw(getDisplayHardware(0));
|
||||
|
||||
// if (mDirtyRegion.isEmpty()) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
if (CC_UNLIKELY(mHwWorkListDirty)) {
|
||||
// build the h/w work list
|
||||
handleWorkList(hw);
|
||||
}
|
||||
|
||||
if (CC_LIKELY(hw.canDraw())) {
|
||||
// repaint the framebuffer (if needed)
|
||||
handleRepaint(hw);
|
||||
// inform the h/w that we're done compositing
|
||||
hw.compositionComplete();
|
||||
postFramebuffer();
|
||||
} else {
|
||||
// pretend we did the post
|
||||
hw.compositionComplete();
|
||||
}
|
||||
|
||||
// render to the external display if we have one
|
||||
EGLSurface externalDisplaySurface = getExternalDisplaySurface();
|
||||
if (externalDisplaySurface != EGL_NO_SURFACE) {
|
||||
EGLSurface cur = eglGetCurrentSurface(EGL_DRAW);
|
||||
EGLBoolean success = eglMakeCurrent(eglGetCurrentDisplay(),
|
||||
externalDisplaySurface, externalDisplaySurface,
|
||||
eglGetCurrentContext());
|
||||
|
||||
ALOGE_IF(!success, "eglMakeCurrent -> external failed");
|
||||
|
||||
if (success) {
|
||||
// redraw the screen entirely...
|
||||
glDisable(GL_TEXTURE_EXTERNAL_OES);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glClearColor(0,0,0,1);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
|
||||
const size_t count = layers.size();
|
||||
for (size_t i=0 ; i<count ; ++i) {
|
||||
const sp<LayerBase>& layer(layers[i]);
|
||||
layer->drawForSreenShot(hw);
|
||||
}
|
||||
|
||||
success = eglSwapBuffers(eglGetCurrentDisplay(), externalDisplaySurface);
|
||||
ALOGE_IF(!success, "external display eglSwapBuffers failed");
|
||||
|
||||
hw.compositionComplete();
|
||||
}
|
||||
|
||||
success = eglMakeCurrent(eglGetCurrentDisplay(),
|
||||
cur, cur, eglGetCurrentContext());
|
||||
|
||||
ALOGE_IF(!success, "eglMakeCurrent -> internal failed");
|
||||
}
|
||||
|
||||
} break;
|
||||
case MessageQueue::INVALIDATE:
|
||||
handleMessageTransaction();
|
||||
handleMessageInvalidate();
|
||||
signalRefresh();
|
||||
break;
|
||||
case MessageQueue::REFRESH:
|
||||
handleMessageRefresh();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SurfaceFlinger::handleMessageTransaction() {
|
||||
const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
|
||||
uint32_t transactionFlags = peekTransactionFlags(mask);
|
||||
if (transactionFlags) {
|
||||
Region dirtyRegion;
|
||||
dirtyRegion = handleTransaction(transactionFlags);
|
||||
// XXX: dirtyRegion should be per screen
|
||||
mDirtyRegion |= dirtyRegion;
|
||||
}
|
||||
}
|
||||
|
||||
void SurfaceFlinger::handleMessageInvalidate() {
|
||||
Region dirtyRegion;
|
||||
dirtyRegion = handlePageFlip();
|
||||
// XXX: dirtyRegion should be per screen
|
||||
mDirtyRegion |= dirtyRegion;
|
||||
}
|
||||
|
||||
void SurfaceFlinger::handleMessageRefresh() {
|
||||
handleRefresh();
|
||||
|
||||
// XXX: dirtyRegion should be per screen, we should check all of them
|
||||
if (mDirtyRegion.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: iterate through all displays
|
||||
const DisplayHardware& hw(getDisplayHardware(0));
|
||||
|
||||
// XXX: dirtyRegion should be per screen
|
||||
// transform the dirty region into this screen's coordinate space
|
||||
const Transform& planeTransform(hw.getTransform());
|
||||
mDirtyRegion = planeTransform.transform(mDirtyRegion);
|
||||
mDirtyRegion.orSelf(getAndClearInvalidateRegion());
|
||||
mDirtyRegion.andSelf(hw.bounds());
|
||||
|
||||
|
||||
if (CC_UNLIKELY(mHwWorkListDirty)) {
|
||||
// build the h/w work list
|
||||
handleWorkList(hw);
|
||||
}
|
||||
|
||||
if (CC_LIKELY(hw.canDraw())) {
|
||||
// repaint the framebuffer (if needed)
|
||||
handleRepaint(hw);
|
||||
// inform the h/w that we're done compositing
|
||||
hw.compositionComplete();
|
||||
postFramebuffer();
|
||||
} else {
|
||||
// pretend we did the post
|
||||
hw.compositionComplete();
|
||||
}
|
||||
|
||||
// render to the external display if we have one
|
||||
EGLSurface externalDisplaySurface = getExternalDisplaySurface();
|
||||
if (externalDisplaySurface != EGL_NO_SURFACE) {
|
||||
EGLSurface cur = eglGetCurrentSurface(EGL_DRAW);
|
||||
EGLBoolean success = eglMakeCurrent(eglGetCurrentDisplay(),
|
||||
externalDisplaySurface, externalDisplaySurface,
|
||||
eglGetCurrentContext());
|
||||
|
||||
ALOGE_IF(!success, "eglMakeCurrent -> external failed");
|
||||
|
||||
if (success) {
|
||||
// redraw the screen entirely...
|
||||
glDisable(GL_TEXTURE_EXTERNAL_OES);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glClearColor(0,0,0,1);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
|
||||
const size_t count = layers.size();
|
||||
for (size_t i=0 ; i<count ; ++i) {
|
||||
const sp<LayerBase>& layer(layers[i]);
|
||||
layer->drawForSreenShot(hw);
|
||||
}
|
||||
|
||||
success = eglSwapBuffers(eglGetCurrentDisplay(), externalDisplaySurface);
|
||||
ALOGE_IF(!success, "external display eglSwapBuffers failed");
|
||||
|
||||
hw.compositionComplete();
|
||||
}
|
||||
|
||||
success = eglMakeCurrent(eglGetCurrentDisplay(),
|
||||
cur, cur, eglGetCurrentContext());
|
||||
|
||||
ALOGE_IF(!success, "eglMakeCurrent -> internal failed");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void SurfaceFlinger::postFramebuffer()
|
||||
{
|
||||
ATRACE_CALL();
|
||||
|
@ -564,10 +581,12 @@ void SurfaceFlinger::postFramebuffer()
|
|||
mSwapRegion.clear();
|
||||
}
|
||||
|
||||
void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
|
||||
Region SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
|
||||
{
|
||||
ATRACE_CALL();
|
||||
|
||||
Region dirtyRegion;
|
||||
|
||||
Mutex::Autolock _l(mStateLock);
|
||||
const nsecs_t now = systemTime();
|
||||
mDebugInTransaction = now;
|
||||
|
@ -580,16 +599,19 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
|
|||
|
||||
const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
|
||||
transactionFlags = getTransactionFlags(mask);
|
||||
handleTransactionLocked(transactionFlags);
|
||||
dirtyRegion = handleTransactionLocked(transactionFlags);
|
||||
|
||||
mLastTransactionTime = systemTime() - now;
|
||||
mDebugInTransaction = 0;
|
||||
invalidateHwcGeometry();
|
||||
// here the transaction has been committed
|
||||
|
||||
return dirtyRegion;
|
||||
}
|
||||
|
||||
void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
|
||||
Region SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
|
||||
{
|
||||
Region dirtyRegion;
|
||||
const LayerVector& currentLayers(mCurrentState.layersSortedByZ);
|
||||
const size_t count = currentLayers.size();
|
||||
|
||||
|
@ -652,13 +674,34 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
|
|||
const sp<LayerBase>& layer(previousLayers[i]);
|
||||
if (currentLayers.indexOf( layer ) < 0) {
|
||||
// this layer is not visible anymore
|
||||
mDirtyRegionRemovedLayer.orSelf(layer->visibleRegionScreen);
|
||||
// TODO: we could traverse the tree from front to back and compute the actual visible region
|
||||
// TODO: we could cache the transformed region
|
||||
Layer::State front(layer->drawingState());
|
||||
Region visibleReg = front.transform.transform(
|
||||
Region(Rect(front.active.w, front.active.h)));
|
||||
dirtyRegion.orSelf(visibleReg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
commitTransaction();
|
||||
return dirtyRegion;
|
||||
}
|
||||
|
||||
void SurfaceFlinger::commitTransaction()
|
||||
{
|
||||
if (!mLayersPendingRemoval.isEmpty()) {
|
||||
// Notify removed layers now that they can't be drawn from
|
||||
for (size_t i = 0; i < mLayersPendingRemoval.size(); i++) {
|
||||
mLayersPendingRemoval[i]->onRemoved();
|
||||
}
|
||||
mLayersPendingRemoval.clear();
|
||||
}
|
||||
|
||||
mDrawingState = mCurrentState;
|
||||
mTransationPending = false;
|
||||
mTransactionCV.broadcast();
|
||||
}
|
||||
|
||||
void SurfaceFlinger::computeVisibleRegions(
|
||||
|
@ -666,10 +709,6 @@ void SurfaceFlinger::computeVisibleRegions(
|
|||
{
|
||||
ATRACE_CALL();
|
||||
|
||||
const DisplayHardware& hw(getDefaultDisplayHardware()); // FIXME: we shouldn't rely on DisplayHardware here
|
||||
const Transform& planeTransform(hw.getTransform());
|
||||
const Region screenRegion(hw.bounds());
|
||||
|
||||
Region aboveOpaqueLayers;
|
||||
Region aboveCoveredLayers;
|
||||
Region dirty;
|
||||
|
@ -679,7 +718,6 @@ void SurfaceFlinger::computeVisibleRegions(
|
|||
size_t i = currentLayers.size();
|
||||
while (i--) {
|
||||
const sp<LayerBase>& layer = currentLayers[i];
|
||||
layer->validateVisibility(planeTransform, hw);
|
||||
|
||||
// start with the whole surface at its current location
|
||||
const Layer::State& s(layer->drawingState());
|
||||
|
@ -707,17 +745,30 @@ void SurfaceFlinger::computeVisibleRegions(
|
|||
// handle hidden surfaces by setting the visible region to empty
|
||||
if (CC_LIKELY(!(s.flags & ISurfaceComposer::eLayerHidden) && s.alpha)) {
|
||||
const bool translucent = !layer->isOpaque();
|
||||
const Rect bounds(layer->visibleBounds());
|
||||
Rect bounds(layer->computeBounds());
|
||||
visibleRegion.set(bounds);
|
||||
visibleRegion.andSelf(screenRegion);
|
||||
if (!visibleRegion.isEmpty()) {
|
||||
// Remove the transparent area from the visible region
|
||||
if (translucent) {
|
||||
visibleRegion.subtractSelf(layer->transparentRegionScreen);
|
||||
Region transparentRegionScreen;
|
||||
const Transform tr(s.transform);
|
||||
if (tr.transformed()) {
|
||||
if (tr.preserveRects()) {
|
||||
// transform the transparent region
|
||||
transparentRegionScreen = tr.transform(s.transparentRegion);
|
||||
} else {
|
||||
// transformation too complex, can't do the
|
||||
// transparent region optimization.
|
||||
transparentRegionScreen.clear();
|
||||
}
|
||||
} else {
|
||||
transparentRegionScreen = s.transparentRegion;
|
||||
}
|
||||
visibleRegion.subtractSelf(transparentRegionScreen);
|
||||
}
|
||||
|
||||
// compute the opaque region
|
||||
const int32_t layerOrientation = layer->getOrientation();
|
||||
const int32_t layerOrientation = s.transform.getOrientation();
|
||||
if (s.alpha==255 && !translucent &&
|
||||
((layerOrientation & Transform::ROT_INVALID) == false)) {
|
||||
// the opaque region is the layer's footprint
|
||||
|
@ -740,7 +791,7 @@ void SurfaceFlinger::computeVisibleRegions(
|
|||
// we need to invalidate the whole region
|
||||
dirty = visibleRegion;
|
||||
// as well, as the old visible region
|
||||
dirty.orSelf(layer->visibleRegionScreen);
|
||||
dirty.orSelf(layer->visibleRegion);
|
||||
layer->contentDirty = false;
|
||||
} else {
|
||||
/* compute the exposed region:
|
||||
|
@ -756,8 +807,8 @@ void SurfaceFlinger::computeVisibleRegions(
|
|||
* exposed because of a resize.
|
||||
*/
|
||||
const Region newExposed = visibleRegion - coveredRegion;
|
||||
const Region oldVisibleRegion = layer->visibleRegionScreen;
|
||||
const Region oldCoveredRegion = layer->coveredRegionScreen;
|
||||
const Region oldVisibleRegion = layer->visibleRegion;
|
||||
const Region oldCoveredRegion = layer->coveredRegion;
|
||||
const Region oldExposed = oldVisibleRegion - oldCoveredRegion;
|
||||
dirty = (visibleRegion&oldCoveredRegion) | (newExposed-oldExposed);
|
||||
}
|
||||
|
@ -779,63 +830,51 @@ void SurfaceFlinger::computeVisibleRegions(
|
|||
}
|
||||
}
|
||||
|
||||
// invalidate the areas where a layer was removed
|
||||
dirtyRegion.orSelf(mDirtyRegionRemovedLayer);
|
||||
mDirtyRegionRemovedLayer.clear();
|
||||
|
||||
mSecureFrameBuffer = secureFrameBuffer;
|
||||
opaqueRegion = aboveOpaqueLayers;
|
||||
}
|
||||
|
||||
|
||||
void SurfaceFlinger::commitTransaction()
|
||||
{
|
||||
if (!mLayersPendingRemoval.isEmpty()) {
|
||||
// Notify removed layers now that they can't be drawn from
|
||||
for (size_t i = 0; i < mLayersPendingRemoval.size(); i++) {
|
||||
mLayersPendingRemoval[i]->onRemoved();
|
||||
}
|
||||
mLayersPendingRemoval.clear();
|
||||
}
|
||||
|
||||
mDrawingState = mCurrentState;
|
||||
mTransationPending = false;
|
||||
mTransactionCV.broadcast();
|
||||
}
|
||||
|
||||
void SurfaceFlinger::handlePageFlip()
|
||||
Region SurfaceFlinger::handlePageFlip()
|
||||
{
|
||||
ATRACE_CALL();
|
||||
const DisplayHardware& hw(getDefaultDisplayHardware()); // FIXME: it's a problem we need DisplayHardware here
|
||||
const Region screenRegion(hw.bounds());
|
||||
Region dirtyRegion;
|
||||
|
||||
const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
|
||||
const bool visibleRegions = lockPageFlip(currentLayers);
|
||||
|
||||
if (visibleRegions || mVisibleRegionsDirty) {
|
||||
Region opaqueRegion;
|
||||
computeVisibleRegions(currentLayers, mDirtyRegion, opaqueRegion);
|
||||
bool visibleRegions = false;
|
||||
const size_t count = currentLayers.size();
|
||||
sp<LayerBase> const* layers = currentLayers.array();
|
||||
for (size_t i=0 ; i<count ; i++) {
|
||||
const sp<LayerBase>& layer(layers[i]);
|
||||
dirtyRegion.orSelf( layer->latchBuffer(visibleRegions) );
|
||||
}
|
||||
|
||||
/*
|
||||
* rebuild the visible layer list
|
||||
*/
|
||||
const size_t count = currentLayers.size();
|
||||
mVisibleLayersSortedByZ.clear();
|
||||
mVisibleLayersSortedByZ.setCapacity(count);
|
||||
for (size_t i=0 ; i<count ; i++) {
|
||||
if (!currentLayers[i]->visibleRegionScreen.isEmpty())
|
||||
mVisibleLayersSortedByZ.add(currentLayers[i]);
|
||||
}
|
||||
if (visibleRegions || mVisibleRegionsDirty) {
|
||||
Region opaqueRegion;
|
||||
computeVisibleRegions(currentLayers, dirtyRegion, opaqueRegion);
|
||||
|
||||
mWormholeRegion = screenRegion.subtract(opaqueRegion);
|
||||
mVisibleRegionsDirty = false;
|
||||
invalidateHwcGeometry();
|
||||
/*
|
||||
* rebuild the visible layer list
|
||||
*/
|
||||
|
||||
// XXX: mVisibleLayersSortedByZ should be per-screen
|
||||
const size_t count = currentLayers.size();
|
||||
mVisibleLayersSortedByZ.clear();
|
||||
mVisibleLayersSortedByZ.setCapacity(count);
|
||||
for (size_t i=0 ; i<count ; i++) {
|
||||
if (!currentLayers[i]->visibleRegion.isEmpty())
|
||||
mVisibleLayersSortedByZ.add(currentLayers[i]);
|
||||
}
|
||||
|
||||
unlockPageFlip(currentLayers);
|
||||
// FIXME: mWormholeRegion needs to be calculated per screen
|
||||
const DisplayHardware& hw(getDefaultDisplayHardware()); // XXX: we can't keep that here
|
||||
mWormholeRegion = Region(hw.getBounds()).subtract(
|
||||
hw.getTransform().transform(opaqueRegion) );
|
||||
mVisibleRegionsDirty = false;
|
||||
invalidateHwcGeometry();
|
||||
}
|
||||
|
||||
mDirtyRegion.orSelf(getAndClearInvalidateRegion());
|
||||
mDirtyRegion.andSelf(screenRegion);
|
||||
return dirtyRegion;
|
||||
}
|
||||
|
||||
void SurfaceFlinger::invalidateHwcGeometry()
|
||||
|
@ -843,30 +882,6 @@ void SurfaceFlinger::invalidateHwcGeometry()
|
|||
mHwWorkListDirty = true;
|
||||
}
|
||||
|
||||
bool SurfaceFlinger::lockPageFlip(const LayerVector& currentLayers)
|
||||
{
|
||||
bool recomputeVisibleRegions = false;
|
||||
size_t count = currentLayers.size();
|
||||
sp<LayerBase> const* layers = currentLayers.array();
|
||||
for (size_t i=0 ; i<count ; i++) {
|
||||
const sp<LayerBase>& layer(layers[i]);
|
||||
layer->lockPageFlip(recomputeVisibleRegions);
|
||||
}
|
||||
return recomputeVisibleRegions;
|
||||
}
|
||||
|
||||
void SurfaceFlinger::unlockPageFlip(const LayerVector& currentLayers)
|
||||
{
|
||||
const DisplayHardware& hw(getDefaultDisplayHardware()); // FIXME: it's a problem we need DisplayHardware here
|
||||
const Transform& planeTransform(hw.getTransform());
|
||||
const size_t count = currentLayers.size();
|
||||
sp<LayerBase> const* layers = currentLayers.array();
|
||||
for (size_t i=0 ; i<count ; i++) {
|
||||
const sp<LayerBase>& layer(layers[i]);
|
||||
layer->unlockPageFlip(planeTransform, mDirtyRegion);
|
||||
}
|
||||
}
|
||||
|
||||
void SurfaceFlinger::handleRefresh()
|
||||
{
|
||||
bool needInvalidate = false;
|
||||
|
@ -896,7 +911,7 @@ void SurfaceFlinger::handleWorkList(const DisplayHardware& hw)
|
|||
HWComposer::LayerListIterator cur = hwc.begin();
|
||||
const HWComposer::LayerListIterator end = hwc.end();
|
||||
for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
|
||||
currentLayers[i]->setGeometry(*cur);
|
||||
currentLayers[i]->setGeometry(hw, *cur);
|
||||
if (mDebugDisableHWC || mDebugRegion) {
|
||||
cur->setSkip(true);
|
||||
}
|
||||
|
@ -1012,9 +1027,10 @@ void SurfaceFlinger::composeSurfaces(const DisplayHardware& hw, const Region& di
|
|||
|
||||
const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
|
||||
const size_t count = layers.size();
|
||||
const Transform& tr = hw.getTransform();
|
||||
for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
|
||||
const sp<LayerBase>& layer(layers[i]);
|
||||
const Region clip(dirty.intersect(layer->visibleRegionScreen));
|
||||
const Region clip(dirty.intersect(tr.transform(layer->visibleRegion)));
|
||||
if (!clip.isEmpty()) {
|
||||
if (cur->getCompositionType() == HWC_OVERLAY) {
|
||||
if (i && (cur->getHints() & HWC_HINT_CLEAR_FB)
|
||||
|
|
|
@ -129,6 +129,9 @@ public:
|
|||
GLuint* textureName, GLfloat* uOut, GLfloat* vOut);
|
||||
|
||||
void onMessageReceived(int32_t what);
|
||||
void handleMessageTransaction();
|
||||
void handleMessageInvalidate();
|
||||
void handleMessageRefresh();
|
||||
|
||||
status_t postMessageAsync(const sp<MessageBase>& msg,
|
||||
nsecs_t reltime=0, uint32_t flags = 0);
|
||||
|
@ -237,17 +240,23 @@ public: // hack to work around gcc 4.0.3 bug
|
|||
|
||||
private:
|
||||
void waitForEvent();
|
||||
void handleTransaction(uint32_t transactionFlags);
|
||||
void handleTransactionLocked(uint32_t transactionFlags);
|
||||
Region handleTransaction(uint32_t transactionFlags);
|
||||
Region handleTransactionLocked(uint32_t transactionFlags);
|
||||
|
||||
void computeVisibleRegions(
|
||||
const LayerVector& currentLayers,
|
||||
Region& dirtyRegion,
|
||||
Region& wormholeRegion);
|
||||
|
||||
void handlePageFlip();
|
||||
bool lockPageFlip(const LayerVector& currentLayers);
|
||||
void unlockPageFlip(const LayerVector& currentLayers);
|
||||
/* handlePageFilp: this is were we latch a new buffer
|
||||
* if available and compute the dirty region.
|
||||
* The return value is the dirty region expressed in the
|
||||
* window manager's coordinate space (or the layer's state
|
||||
* space, which is the same thing), in particular the dirty
|
||||
* region is independent from a specific display's orientation.
|
||||
*/
|
||||
Region handlePageFlip();
|
||||
|
||||
void handleRefresh();
|
||||
void handleWorkList(const DisplayHardware& hw);
|
||||
void handleRepaint(const DisplayHardware& hw);
|
||||
|
|
Loading…
Reference in New Issue