summaryrefslogtreecommitdiffstats
path: root/services/surfaceflinger/Layer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'services/surfaceflinger/Layer.cpp')
-rw-r--r--services/surfaceflinger/Layer.cpp196
1 files changed, 97 insertions, 99 deletions
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 4062340..0825ec6 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -36,13 +36,14 @@
#include <gui/Surface.h>
#include "clz.h"
-#include "DisplayHardware/DisplayHardware.h"
-#include "DisplayHardware/HWComposer.h"
+#include "DisplayDevice.h"
#include "GLExtensions.h"
#include "Layer.h"
#include "SurfaceFlinger.h"
#include "SurfaceTextureLayer.h"
+#include "DisplayHardware/HWComposer.h"
+
#define DEBUG_RESIZE 0
namespace android {
@@ -63,7 +64,6 @@ Layer::Layer(SurfaceFlinger* flinger,
mFormat(PIXEL_FORMAT_NONE),
mGLExtensions(GLExtensions::getInstance()),
mOpaqueLayer(true),
- mNeedsDithering(false),
mSecure(false),
mProtectedByApp(false)
{
@@ -71,14 +71,10 @@ Layer::Layer(SurfaceFlinger* flinger,
glGenTextures(1, &mTextureName);
}
-void Layer::onLayerDisplayed() {
- if (mFrameLatencyNeeded) {
- const DisplayHardware& hw(graphicPlane(0).displayHardware());
- mFrameStats[mFrameLatencyOffset].timestamp = mSurfaceTexture->getTimestamp();
- mFrameStats[mFrameLatencyOffset].set = systemTime();
- mFrameStats[mFrameLatencyOffset].vsync = hw.getRefreshTimestamp();
- mFrameLatencyOffset = (mFrameLatencyOffset + 1) % 128;
- mFrameLatencyNeeded = false;
+void Layer::onLayerDisplayed(const sp<const DisplayDevice>& hw,
+ HWComposer::HWCLayerInterface* layer) {
+ if (layer) {
+ mSurfaceTexture->setReleaseFence(layer->getAndResetReleaseFenceFd());
}
}
@@ -117,8 +113,7 @@ void Layer::onFirstRef()
Layer::~Layer()
{
- mFlinger->postMessageAsync(
- new SurfaceFlinger::MessageDestroyGLTexture(mTextureName) );
+ mFlinger->deleteTextureAsync(mTextureName);
}
void Layer::onFrameQueued() {
@@ -138,14 +133,6 @@ void Layer::setName(const String8& name) {
mSurfaceTexture->setName(name);
}
-void Layer::validateVisibility(const Transform& globalTransform) {
- LayerBase::validateVisibility(globalTransform);
-
- // 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 {
@@ -183,10 +170,8 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h,
return err;
}
- // the display's pixel format
- const DisplayHardware& hw(graphicPlane(0).displayHardware());
uint32_t const maxSurfaceDims = min(
- hw.getMaxTextureSize(), hw.getMaxViewportDims());
+ mFlinger->getMaxTextureSize(), mFlinger->getMaxViewportDims());
// never allow a surface larger than what our underlying GL implementation
// can handle.
@@ -195,26 +180,17 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h,
return BAD_VALUE;
}
- PixelFormatInfo displayInfo;
- getPixelFormatInfo(hw.getFormat(), &displayInfo);
- const uint32_t hwFlags = hw.getFlags();
-
mFormat = format;
- mSecure = (flags & ISurfaceComposer::eSecure) ? true : false;
- mProtectedByApp = (flags & ISurfaceComposer::eProtectedByApp) ? true : false;
- mOpaqueLayer = (flags & ISurfaceComposer::eOpaque);
+ mSecure = (flags & ISurfaceComposerClient::eSecure) ? true : false;
+ mProtectedByApp = (flags & ISurfaceComposerClient::eProtectedByApp) ? true : false;
+ mOpaqueLayer = (flags & ISurfaceComposerClient::eOpaque);
mCurrentOpacity = getOpacityForFormat(format);
mSurfaceTexture->setDefaultBufferSize(w, h);
mSurfaceTexture->setDefaultBufferFormat(format);
mSurfaceTexture->setConsumerUsageBits(getEffectiveUsage(0));
- // we use the red index
- int displayRedSize = displayInfo.getSize(PixelFormatInfo::INDEX_RED);
- int layerRedsize = info.getSize(PixelFormatInfo::INDEX_RED);
- mNeedsDithering = layerRedsize > displayRedSize;
-
return NO_ERROR;
}
@@ -226,7 +202,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
@@ -259,16 +236,19 @@ Rect Layer::computeBufferCrop() const {
return crop;
}
-void Layer::setGeometry(hwc_layer_t* hwcl)
+void Layer::setGeometry(
+ const sp<const DisplayDevice>& hw,
+ HWComposer::HWCLayerInterface& layer)
{
- LayerBaseClient::setGeometry(hwcl);
+ LayerBaseClient::setGeometry(hw, layer);
- hwcl->flags &= ~HWC_SKIP_LAYER;
+ // enable this layer
+ layer.setSkip(false);
// we can't do alpha-fade with the hwc HAL
const State& s(drawingState());
if (s.alpha < 0xFF) {
- hwcl->flags = HWC_SKIP_LAYER;
+ layer.setSkip(true);
}
/*
@@ -276,44 +256,52 @@ void Layer::setGeometry(hwc_layer_t* hwcl)
* 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();
// we can only handle simple transformation
if (finalTransform & Transform::ROT_INVALID) {
- hwcl->flags = HWC_SKIP_LAYER;
+ layer.setSkip(true);
} else {
- hwcl->transform = finalTransform;
+ layer.setTransform(finalTransform);
}
-
- Rect crop = computeBufferCrop();
- hwcl->sourceCrop.left = crop.left;
- hwcl->sourceCrop.top = crop.top;
- hwcl->sourceCrop.right = crop.right;
- hwcl->sourceCrop.bottom = crop.bottom;
+ layer.setCrop(computeBufferCrop());
}
-void Layer::setPerFrameData(hwc_layer_t* hwcl) {
+void Layer::setPerFrameData(const sp<const DisplayDevice>& hw,
+ HWComposer::HWCLayerInterface& layer) {
const sp<GraphicBuffer>& buffer(mActiveBuffer);
- if (buffer == NULL) {
- // this can happen if the client never drew into this layer yet,
- // or if we ran out of memory. In that case, don't let
- // HWC handle it.
- hwcl->flags |= HWC_SKIP_LAYER;
- hwcl->handle = NULL;
- } else {
- hwcl->handle = buffer->handle;
+ // NOTE: buffer can be NULL if the client never drew into this
+ // layer yet, or if we ran out of memory
+ layer.setBuffer(buffer);
+}
+
+void Layer::setAcquireFence(const sp<const DisplayDevice>& hw,
+ HWComposer::HWCLayerInterface& layer) {
+ int fenceFd = -1;
+
+ // TODO: there is a possible optimization here: we only need to set the
+ // acquire fence the first time a new buffer is acquired on EACH display.
+
+ if (layer.getCompositionType() == HWC_OVERLAY) {
+ sp<Fence> fence = mSurfaceTexture->getCurrentFence();
+ if (fence.get()) {
+ fenceFd = fence->dup();
+ if (fenceFd == -1) {
+ ALOGW("failed to dup layer fence, skipping sync: %d", errno);
+ }
+ }
}
+ layer.setAcquireFenceFd(fenceFd);
}
-void Layer::onDraw(const Region& clip) const
+void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const
{
ATRACE_CALL();
@@ -335,16 +323,25 @@ void Layer::onDraw(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));
if (!holes.isEmpty()) {
- clearWithOpenGL(holes, 0, 0, 0, 1);
+ clearWithOpenGL(hw, holes, 0, 0, 0, 1);
}
return;
}
+ // TODO: replace this with a server-side wait
+ sp<Fence> fence = mSurfaceTexture->getCurrentFence();
+ if (fence.get()) {
+ status_t err = fence->wait(Fence::TIMEOUT_NEVER);
+ ALOGW_IF(err != OK, "Layer::onDraw: failed waiting for fence: %d", err);
+ // Go ahead and draw the buffer anyway; no matter what we do the screen
+ // is probably going to have something visibly wrong.
+ }
+
if (!isProtected()) {
// TODO: we could be more subtle with isFixedSize()
const bool useFiltering = getFiltering() || needsFiltering() || isFixedSize();
@@ -376,7 +373,7 @@ void Layer::onDraw(const Region& clip) const
glEnable(GL_TEXTURE_2D);
}
- drawWithOpenGL(clip);
+ drawWithOpenGL(hw, clip);
glDisable(GL_TEXTURE_EXTERNAL_OES);
glDisable(GL_TEXTURE_2D);
@@ -514,10 +511,23 @@ bool Layer::onPreComposition() {
return mQueuedFrames > 0;
}
-void Layer::lockPageFlip(bool& recomputeVisibleRegions)
+void Layer::onPostComposition() {
+ if (mFrameLatencyNeeded) {
+ const HWComposer& hwc = mFlinger->getHwComposer();
+ const size_t offset = mFrameLatencyOffset;
+ mFrameStats[offset].timestamp = mSurfaceTexture->getTimestamp();
+ mFrameStats[offset].set = systemTime();
+ mFrameStats[offset].vsync = hwc.getRefreshTimestamp();
+ mFrameLatencyOffset = (mFrameLatencyOffset + 1) % 128;
+ mFrameLatencyNeeded = false;
+ }
+}
+
+Region Layer::latchBuffer(bool& recomputeVisibleRegions)
{
ATRACE_CALL();
+ Region outDirtyRegion;
if (mQueuedFrames > 0) {
// if we've already called updateTexImage() without going through
@@ -526,8 +536,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
@@ -624,17 +633,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;
@@ -672,38 +685,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);
- }
-}
-void Layer::unlockPageFlip(
- const Transform& planeTransform, Region& outDirtyRegion)
-{
- ATRACE_CALL();
+ // FIXME: postedRegion should be dirty & bounds
+ const Layer::State& front(drawingState());
+ Region dirtyRegion(Rect(front.active.w, front.active.h));
- 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);
- }
+ // transform the dirty region to window-manager space
+ outDirtyRegion = (front.transform.transform(dirtyRegion));
}
+ return outDirtyRegion;
}
void Layer::dump(String8& result, char* buffer, size_t SIZE) const
@@ -736,8 +728,7 @@ void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const
{
LayerBaseClient::dumpStats(result, buffer, SIZE);
const size_t o = mFrameLatencyOffset;
- const DisplayHardware& hw(graphicPlane(0).displayHardware());
- const nsecs_t period = hw.getRefreshPeriod();
+ const nsecs_t period = mFlinger->getHwComposer().getRefreshPeriod();
result.appendFormat("%lld\n", period);
for (size_t i=0 ; i<128 ; i++) {
const size_t index = (o+i) % 128;
@@ -772,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.
+ sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
+ const Transform& planeTransform(hw->getTransform());
+ orientation = planeTransform.getOrientation();
if (orientation & Transform::ROT_INVALID) {
orientation = 0;
}