summaryrefslogtreecommitdiffstats
path: root/services/surfaceflinger/SurfaceFlinger.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'services/surfaceflinger/SurfaceFlinger.cpp')
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp305
1 files changed, 262 insertions, 43 deletions
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index fdc3650..40e5da1 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
#include <stdint.h>
@@ -27,6 +28,7 @@
#include <EGL/egl.h>
#include <cutils/log.h>
+#include <cutils/iosched_policy.h>
#include <cutils/properties.h>
#include <binder/IPCThreadState.h>
@@ -67,6 +69,7 @@
#include "EventThread.h"
#include "Layer.h"
#include "LayerDim.h"
+#include "LayerBlur.h"
#include "SurfaceFlinger.h"
#include "DisplayHardware/FramebufferSurface.h"
@@ -77,6 +80,7 @@
#include "RenderEngine/RenderEngine.h"
#include <cutils/compiler.h>
+#include "DisplayUtils.h"
#define DISPLAY_COUNT 1
@@ -122,6 +126,8 @@ const String16 sAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER"
const String16 sReadFramebuffer("android.permission.READ_FRAME_BUFFER");
const String16 sDump("android.permission.DUMP");
+static sp<Layer> lastSurfaceViewLayer;
+
// ---------------------------------------------------------------------------
SurfaceFlinger::SurfaceFlinger()
@@ -150,10 +156,12 @@ SurfaceFlinger::SurfaceFlinger()
mHWVsyncAvailable(false),
mDaltonize(false),
mHasColorMatrix(false),
+ mHasSecondaryColorMatrix(false),
mHasPoweredOff(false),
mFrameBuckets(),
mTotalTime(0),
- mLastSwapTime(0)
+ mLastSwapTime(0),
+ mActiveFrameSequence(0)
{
ALOGI("SurfaceFlinger is starting");
@@ -446,17 +454,24 @@ void SurfaceFlinger::init() {
eglInitialize(mEGLDisplay, NULL, NULL);
// start the EventThread
- sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
- vsyncPhaseOffsetNs, true, "app");
- mEventThread = new EventThread(vsyncSrc);
- sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
- sfVsyncPhaseOffsetNs, true, "sf");
- mSFEventThread = new EventThread(sfVsyncSrc);
- mEventQueue.setEventThread(mSFEventThread);
+ if (vsyncPhaseOffsetNs != sfVsyncPhaseOffsetNs) {
+ sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
+ vsyncPhaseOffsetNs, true, "app");
+ mEventThread = new EventThread(vsyncSrc);
+ sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
+ sfVsyncPhaseOffsetNs, true, "sf");
+ mSFEventThread = new EventThread(sfVsyncSrc);
+ mEventQueue.setEventThread(mSFEventThread);
+ } else {
+ sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
+ vsyncPhaseOffsetNs, true, "sf-app");
+ mEventThread = new EventThread(vsyncSrc);
+ mEventQueue.setEventThread(mEventThread);
+ }
// Initialize the H/W composer object. There may or may not be an
// actual hardware composer underneath.
- mHwc = new HWComposer(this,
+ mHwc = DisplayUtils::getInstance()->getHWCInstance(this,
*static_cast<HWComposer::EventHandler *>(this));
// get a RenderEngine for the given display / config (can't fail)
@@ -497,6 +512,13 @@ void SurfaceFlinger::init() {
ALOGD("marking display %zu as acquired/unblanked", i);
hw->setPowerMode(HWC_POWER_MODE_NORMAL);
}
+ // When a non-virtual display device is added at boot time,
+ // update the active config by querying HWC otherwise the
+ // default config (config 0) will be used.
+ int activeConfig = mHwc->getActiveConfig(hwcId);
+ if (activeConfig >= 0) {
+ hw->setActiveConfig(activeConfig);
+ }
mDisplays.add(token, hw);
}
}
@@ -507,6 +529,7 @@ void SurfaceFlinger::init() {
mEventControlThread = new EventControlThread(this);
mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);
+ android_set_rt_ioprio(mEventControlThread->getTid(), 1);
// set a fake vsync period if there is no HWComposer
if (mHwc->initCheck() != NO_ERROR) {
@@ -626,10 +649,21 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& display,
info.orientation = 0;
}
- info.w = hwConfig.width;
- info.h = hwConfig.height;
- info.xdpi = xdpi;
- info.ydpi = ydpi;
+ char value[PROPERTY_VALUE_MAX];
+ property_get("ro.sf.hwrotation", value, "0");
+ int additionalRot = atoi(value) / 90;
+ if ((type == DisplayDevice::DISPLAY_PRIMARY) && (additionalRot & DisplayState::eOrientationSwapMask)) {
+ info.h = hwConfig.width;
+ info.w = hwConfig.height;
+ info.xdpi = ydpi;
+ info.ydpi = xdpi;
+ }
+ else {
+ info.w = hwConfig.width;
+ info.h = hwConfig.height;
+ info.xdpi = xdpi;
+ info.ydpi = ydpi;
+ }
info.fps = float(1e9 / hwConfig.refresh);
info.appVsyncOffset = VSYNC_EVENT_PHASE_OFFSET_NS;
info.colorTransform = hwConfig.colorTransform;
@@ -695,8 +729,10 @@ void SurfaceFlinger::setActiveConfigInternal(const sp<DisplayDevice>& hw, int mo
return;
}
- hw->setActiveConfig(mode);
- getHwComposer().setActiveConfig(type, mode);
+ status_t status = getHwComposer().setActiveConfig(type, mode);
+ if (status == NO_ERROR) {
+ hw->setActiveConfig(mode);
+ }
}
status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& display, int mode) {
@@ -869,6 +905,7 @@ void SurfaceFlinger::onHotplugReceived(int type, bool connected) {
} else {
mCurrentState.displays.removeItem(mBuiltinDisplays[type]);
mBuiltinDisplays[type].clear();
+ updateVisibleRegionsDirty();
}
setTransactionFlags(eDisplayTransactionNeeded);
@@ -1045,6 +1082,8 @@ void SurfaceFlinger::postComposition()
mAnimFrameTracker.advanceFrame();
}
+ dumpDrawCycle(false);
+
if (hw->getPowerMode() == HWC_POWER_MODE_OFF) {
return;
}
@@ -1067,6 +1106,7 @@ void SurfaceFlinger::postComposition()
}
void SurfaceFlinger::rebuildLayerStacks() {
+ updateExtendedMode();
// rebuild the visible layer list per screen
if (CC_UNLIKELY(mVisibleRegionsDirty)) {
ATRACE_CALL();
@@ -1082,14 +1122,13 @@ void SurfaceFlinger::rebuildLayerStacks() {
const Transform& tr(hw->getTransform());
const Rect bounds(hw->getBounds());
if (hw->isDisplayOn()) {
- SurfaceFlinger::computeVisibleRegions(layers,
+ computeVisibleRegions(hw->getHwcDisplayId(), layers,
hw->getLayerStack(), dirtyRegion, opaqueRegion);
const size_t count = layers.size();
for (size_t i=0 ; i<count ; i++) {
const sp<Layer>& layer(layers[i]);
- const Layer::State& s(layer->getDrawingState());
- if (s.layerStack == hw->getLayerStack()) {
+ {
Region drawRegion(tr.transform(
layer->visibleNonTransparentRegion));
drawRegion.andSelf(bounds);
@@ -1155,7 +1194,7 @@ void SurfaceFlinger::setUpHWComposer() {
for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
const sp<Layer>& layer(currentLayers[i]);
layer->setGeometry(hw, *cur);
- if (mDebugDisableHWC || mDebugRegion || mDaltonize || mHasColorMatrix) {
+ if (mDebugDisableHWC || mDebugRegion || mDaltonize || mHasColorMatrix || mHasSecondaryColorMatrix) {
cur->setSkip(true);
}
}
@@ -1169,6 +1208,8 @@ void SurfaceFlinger::setUpHWComposer() {
sp<const DisplayDevice> hw(mDisplays[dpy]);
const int32_t id = hw->getHwcDisplayId();
if (id >= 0) {
+ bool freezeSurfacePresent = false;
+ isfreezeSurfacePresent(freezeSurfacePresent, hw, id);
const Vector< sp<Layer> >& currentLayers(
hw->getVisibleLayersSortedByZ());
const size_t count = currentLayers.size();
@@ -1181,6 +1222,11 @@ void SurfaceFlinger::setUpHWComposer() {
*/
const sp<Layer>& layer(currentLayers[i]);
layer->setPerFrameData(hw, *cur);
+ setOrientationEventControl(freezeSurfacePresent,id);
+ if(!strncmp(layer->getName(), "SurfaceView",
+ 11)) {
+ lastSurfaceViewLayer = layer;
+ }
}
}
}
@@ -1205,6 +1251,8 @@ void SurfaceFlinger::setUpHWComposer() {
}
}
+ dumpDrawCycle(true);
+
status_t err = hwc.prepare();
ALOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));
@@ -1227,6 +1275,8 @@ void SurfaceFlinger::doComposition() {
// repaint the framebuffer (if needed)
doDisplayComposition(hw, dirtyRegion);
+ ++mActiveFrameSequence;
+
hw->dirtyRegion.clear();
hw->flip(hw->swapRegion);
hw->swapRegion.clear();
@@ -1287,6 +1337,7 @@ void SurfaceFlinger::postFramebuffer()
if (flipCount % LOG_FRAME_STATS_PERIOD == 0) {
logFrameStats();
}
+ ALOGV_IF(mFrameRateHelper.update(), "FPS: %d", mFrameRateHelper.get());
}
void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
@@ -1439,6 +1490,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
if (state.surface != NULL) {
int width = 0;
+ DisplayUtils* displayUtils = DisplayUtils::getInstance();
int status = state.surface->query(
NATIVE_WINDOW_WIDTH, &width);
ALOGE_IF(status != NO_ERROR,
@@ -1451,15 +1503,21 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
if (MAX_VIRTUAL_DISPLAY_DIMENSION == 0 ||
(width <= MAX_VIRTUAL_DISPLAY_DIMENSION &&
height <= MAX_VIRTUAL_DISPLAY_DIMENSION)) {
- hwcDisplayId = allocateHwcDisplayId(state.type);
+ int usage = 0;
+ status = state.surface->query(
+ NATIVE_WINDOW_CONSUMER_USAGE_BITS, &usage);
+ ALOGW_IF(status != NO_ERROR,
+ "Unable to query usage (%d)", status);
+ if ( (status == NO_ERROR) &&
+ displayUtils->canAllocateHwcDisplayIdForVDS(usage)) {
+ hwcDisplayId = allocateHwcDisplayId(state.type);
+ }
}
- sp<VirtualDisplaySurface> vds = new VirtualDisplaySurface(
- *mHwc, hwcDisplayId, state.surface,
- bqProducer, bqConsumer, state.displayName);
+ displayUtils->initVDSInstance(mHwc, hwcDisplayId, state.surface,
+ dispSurface, producer, bqProducer, bqConsumer,
+ state.displayName, state.isSecure, state.type);
- dispSurface = vds;
- producer = vds;
}
} else {
ALOGE_IF(state.surface!=NULL,
@@ -1475,7 +1533,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
}
const wp<IBinder>& display(curr.keyAt(i));
- if (dispSurface != NULL) {
+ if (dispSurface != NULL && producer != NULL) {
sp<DisplayDevice> hw = new DisplayDevice(this,
state.type, hwcDisplayId,
mHwc->getFormat(hwcDisplayId), state.isSecure,
@@ -1485,6 +1543,16 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
hw->setProjection(state.orientation,
state.viewport, state.frame);
hw->setDisplayName(state.displayName);
+ // When a new display device is added update the active
+ // config by querying HWC otherwise the default config
+ // (config 0) will be used.
+ if (hwcDisplayId >= DisplayDevice::DISPLAY_PRIMARY &&
+ hwcDisplayId < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
+ int activeConfig = mHwc->getActiveConfig(hwcDisplayId);
+ if (activeConfig >= 0) {
+ hw->setActiveConfig(activeConfig);
+ }
+ }
mDisplays.add(display, hw);
if (state.isVirtualDisplay()) {
if (hwcDisplayId >= 0) {
@@ -1643,7 +1711,7 @@ void SurfaceFlinger::commitTransaction()
mTransactionCV.broadcast();
}
-void SurfaceFlinger::computeVisibleRegions(
+void SurfaceFlinger::computeVisibleRegions(size_t dpy,
const LayerVector& currentLayers, uint32_t layerStack,
Region& outDirtyRegion, Region& outOpaqueRegion)
{
@@ -1654,6 +1722,9 @@ void SurfaceFlinger::computeVisibleRegions(
Region dirty;
outDirtyRegion.clear();
+ bool bIgnoreLayers = false;
+ int indexLOI = -1;
+ getIndexLOI(dpy, currentLayers, bIgnoreLayers, indexLOI);
size_t i = currentLayers.size();
while (i--) {
@@ -1662,8 +1733,9 @@ void SurfaceFlinger::computeVisibleRegions(
// start with the whole surface at its current location
const Layer::State& s(layer->getDrawingState());
- // only consider the layers on the given layer stack
- if (s.layerStack != layerStack)
+ if(updateLayerVisibleNonTransparentRegion(dpy, layer,
+ bIgnoreLayers, indexLOI,
+ layerStack, i))
continue;
/*
@@ -1887,11 +1959,14 @@ void SurfaceFlinger::doDisplayComposition(const sp<const DisplayDevice>& hw,
}
}
- if (CC_LIKELY(!mDaltonize && !mHasColorMatrix)) {
+ if (CC_LIKELY(!mDaltonize && !mHasColorMatrix && !mHasSecondaryColorMatrix)) {
if (!doComposeSurfaces(hw, dirtyRegion)) return;
} else {
RenderEngine& engine(getRenderEngine());
mat4 colorMatrix = mColorMatrix;
+ if (mHasSecondaryColorMatrix) {
+ colorMatrix = mHasColorMatrix ? (colorMatrix * mSecondaryColorMatrix) : mSecondaryColorMatrix;
+ }
if (mDaltonize) {
colorMatrix = colorMatrix * mDaltonizer();
}
@@ -1954,7 +2029,7 @@ bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const
// screen is already cleared here
if (!region.isEmpty()) {
// can happen with SurfaceView
- drawWormhole(hw, region);
+ drawWormHoleIfRequired(cur, end, hw, region);
}
}
@@ -2096,6 +2171,8 @@ void SurfaceFlinger::setTransactionState(
uint32_t flags)
{
ATRACE_CALL();
+
+ delayDPTransactionIfNeeded(displays);
Mutex::Autolock _l(mStateLock);
uint32_t transactionFlags = 0;
@@ -2241,6 +2318,41 @@ uint32_t SurfaceFlinger::setClientStateLocked(
flags |= eTransactionNeeded|eTraversalNeeded;
}
}
+ if (what & layer_state_t::eBlurChanged) {
+ ALOGV("eBlurChanged");
+ if (layer->setBlur(uint8_t(255.0f*s.blur+0.5f))) {
+ flags |= eTraversalNeeded;
+ }
+ }
+ if (what & layer_state_t::eBlurMaskSurfaceChanged) {
+ ALOGV("eBlurMaskSurfaceChanged");
+ sp<Layer> maskLayer = 0;
+ if (s.blurMaskSurface != 0) {
+ maskLayer = client->getLayerUser(s.blurMaskSurface);
+ }
+ if (maskLayer == 0) {
+ ALOGV("eBlurMaskSurfaceChanged. maskLayer == 0");
+ } else {
+ ALOGV("eBlurMaskSurfaceChagned. maskLayer.z == %d", maskLayer->getCurrentState().z);
+ if (maskLayer->isBlurLayer()) {
+ ALOGE("Blur layer can not be used as blur mask surface");
+ maskLayer = 0;
+ }
+ }
+ if (layer->setBlurMaskLayer(maskLayer)) {
+ flags |= eTraversalNeeded;
+ }
+ }
+ if (what & layer_state_t::eBlurMaskSamplingChanged) {
+ if (layer->setBlurMaskSampling(s.blurMaskSampling)) {
+ flags |= eTraversalNeeded;
+ }
+ }
+ if (what & layer_state_t::eBlurMaskAlphaThresholdChanged) {
+ if (layer->setBlurMaskAlphaThreshold(s.blurMaskAlphaThreshold)) {
+ flags |= eTraversalNeeded;
+ }
+ }
if (what & layer_state_t::eSizeChanged) {
if (layer->setSize(s.w, s.h)) {
flags |= eTraversalNeeded;
@@ -2309,6 +2421,11 @@ status_t SurfaceFlinger::createLayer(
name, w, h, flags,
handle, gbp, &layer);
break;
+ case ISurfaceComposerClient::eFXSurfaceBlur:
+ result = createBlurLayer(client,
+ name, w, h, flags,
+ handle, gbp, &layer);
+ break;
default:
result = BAD_VALUE;
break;
@@ -2342,7 +2459,7 @@ status_t SurfaceFlinger::createNormalLayer(const sp<Client>& client,
break;
}
- *outLayer = new Layer(this, client, name, w, h, flags);
+ *outLayer = DisplayUtils::getInstance()->getLayerInstance(this, client, name, w, h, flags);
status_t err = (*outLayer)->setBuffers(w, h, format, flags);
if (err == NO_ERROR) {
*handle = (*outLayer)->getHandle();
@@ -2363,6 +2480,16 @@ status_t SurfaceFlinger::createDimLayer(const sp<Client>& client,
return NO_ERROR;
}
+status_t SurfaceFlinger::createBlurLayer(const sp<Client>& client,
+ const String8& name, uint32_t w, uint32_t h, uint32_t flags,
+ sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer)
+{
+ *outLayer = new LayerBlur(this, client, name, w, h, flags);
+ *handle = (*outLayer)->getHandle();
+ *gbp = (*outLayer)->getProducer();
+ return NO_ERROR;
+}
+
status_t SurfaceFlinger::onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle)
{
// called by the window manager when it wants to remove a Layer
@@ -2605,14 +2732,19 @@ void SurfaceFlinger::dumpStatsLocked(const Vector<String16>& args, size_t& index
if (name.isEmpty()) {
mAnimFrameTracker.dumpStats(result);
} else {
+ bool found = false;
const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
const size_t count = currentLayers.size();
for (size_t i=0 ; i<count ; i++) {
const sp<Layer>& layer(currentLayers[i]);
if (name == layer->getName()) {
+ found = true;
layer->dumpFrameStats(result);
}
}
+ if (!found && !strncmp(name.string(), "SurfaceView", 11)) {
+ lastSurfaceViewLayer->dumpFrameStats(result);
+ }
}
}
@@ -2820,7 +2952,8 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index,
result.appendFormat(" h/w composer %s and %s\n",
hwc.initCheck()==NO_ERROR ? "present" : "not present",
(mDebugDisableHWC || mDebugRegion || mDaltonize
- || mHasColorMatrix) ? "disabled" : "enabled");
+ || mHasColorMatrix
+ || mHasSecondaryColorMatrix) ? "disabled" : "enabled");
hwc.dump(result);
/*
@@ -2841,7 +2974,7 @@ SurfaceFlinger::getLayerSortedByZForHwcDisplay(int id) {
}
}
if (dpy == NULL) {
- ALOGE("getLayerSortedByZForHwcDisplay: invalid hwc display id %d", id);
+ ALOGW("getLayerSortedByZForHwcDisplay: invalid hwc display id %d", id);
// Just use the primary display so we have something to return
dpy = getBuiltInDisplay(DisplayDevice::DISPLAY_PRIMARY);
}
@@ -3020,14 +3153,38 @@ status_t SurfaceFlinger::onTransact(
}
case 1018: { // Modify Choreographer's phase offset
n = data.readInt32();
- mEventThread->setPhaseOffset(static_cast<nsecs_t>(n));
+ if (mEventThread != NULL)
+ mEventThread->setPhaseOffset(static_cast<nsecs_t>(n));
return NO_ERROR;
}
case 1019: { // Modify SurfaceFlinger's phase offset
n = data.readInt32();
- mSFEventThread->setPhaseOffset(static_cast<nsecs_t>(n));
+ if (mSFEventThread != NULL)
+ mSFEventThread->setPhaseOffset(static_cast<nsecs_t>(n));
return NO_ERROR;
}
+ case 1030: {
+ // apply a secondary color matrix
+ // this will be combined with any other transformations
+ n = data.readInt32();
+ mHasSecondaryColorMatrix = n ? 1 : 0;
+ if (n) {
+ // color matrix is sent as mat3 matrix followed by vec3
+ // offset, then packed into a mat4 where the last row is
+ // the offset and extra values are 0
+ for (size_t i = 0 ; i < 4; i++) {
+ for (size_t j = 0; j < 4; j++) {
+ mSecondaryColorMatrix[i][j] = data.readFloat();
+ }
+ }
+ } else {
+ mSecondaryColorMatrix = mat4();
+ }
+ invalidateHwcGeometry();
+ repaintEverything();
+ return NO_ERROR;
+ }
+
}
}
return err;
@@ -3155,7 +3312,8 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
const sp<IGraphicBufferProducer>& producer,
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
uint32_t minLayerZ, uint32_t maxLayerZ,
- bool useIdentityTransform, ISurfaceComposer::Rotation rotation) {
+ bool useIdentityTransform, ISurfaceComposer::Rotation rotation,
+ bool useReadPixels) {
if (CC_UNLIKELY(display == 0))
return BAD_VALUE;
@@ -3205,6 +3363,7 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
uint32_t minLayerZ,maxLayerZ;
bool useIdentityTransform;
Transform::orientation_flags rotation;
+ bool useReadPixels;
status_t result;
public:
MessageCaptureScreen(SurfaceFlinger* flinger,
@@ -3212,12 +3371,14 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
const sp<IGraphicBufferProducer>& producer,
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
uint32_t minLayerZ, uint32_t maxLayerZ,
- bool useIdentityTransform, Transform::orientation_flags rotation)
+ bool useIdentityTransform, Transform::orientation_flags rotation,
+ bool useReadPixels)
: flinger(flinger), display(display), producer(producer),
sourceCrop(sourceCrop), reqWidth(reqWidth), reqHeight(reqHeight),
minLayerZ(minLayerZ), maxLayerZ(maxLayerZ),
useIdentityTransform(useIdentityTransform),
rotation(rotation),
+ useReadPixels(useReadPixels),
result(PERMISSION_DENIED)
{
}
@@ -3227,9 +3388,10 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
virtual bool handler() {
Mutex::Autolock _l(flinger->mStateLock);
sp<const DisplayDevice> hw(flinger->getDisplayDevice(display));
+ bool useReadPixels = this->useReadPixels && !flinger->mGpuToCpuSupported;
result = flinger->captureScreenImplLocked(hw, producer,
sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
- useIdentityTransform, rotation);
+ useIdentityTransform, rotation, useReadPixels);
static_cast<GraphicProducerWrapper*>(IInterface::asBinder(producer).get())->exit(result);
return true;
}
@@ -3252,7 +3414,7 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
sp<MessageBase> msg = new MessageCaptureScreen(this,
display, IGraphicBufferProducer::asInterface( wrapper ),
sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
- useIdentityTransform, rotationFlags);
+ useIdentityTransform, rotationFlags, useReadPixels);
status_t res = postMessageAsync(msg);
if (res == NO_ERROR) {
@@ -3301,6 +3463,12 @@ void SurfaceFlinger::renderScreenImplLocked(
// make sure to clear all GL error flags
engine.checkErrors();
+ if (DisplayDevice::DISPLAY_PRIMARY == hw->getDisplayType() &&
+ hw->isPanelInverseMounted()) {
+ rotation = (Transform::orientation_flags)
+ (rotation ^ Transform::ROT_180);
+ }
+
// set-up our viewport
engine.setViewportAndProjection(
reqWidth, reqHeight, sourceCrop, hw_h, yswap, rotation);
@@ -3316,7 +3484,7 @@ void SurfaceFlinger::renderScreenImplLocked(
const Layer::State& state(layer->getDrawingState());
if (state.layerStack == hw->getLayerStack()) {
if (state.z >= minLayerZ && state.z <= maxLayerZ) {
- if (layer->isVisible()) {
+ if (canDrawLayerinScreenShot(hw,layer)) {
if (filtering) layer->setFiltering(true);
layer->draw(hw, useIdentityTransform);
if (filtering) layer->setFiltering(false);
@@ -3336,7 +3504,8 @@ status_t SurfaceFlinger::captureScreenImplLocked(
const sp<IGraphicBufferProducer>& producer,
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
uint32_t minLayerZ, uint32_t maxLayerZ,
- bool useIdentityTransform, Transform::orientation_flags rotation)
+ bool useIdentityTransform, Transform::orientation_flags rotation,
+ bool useReadPixels)
{
ATRACE_CALL();
@@ -3354,6 +3523,8 @@ status_t SurfaceFlinger::captureScreenImplLocked(
return BAD_VALUE;
}
+ ++mActiveFrameSequence;
+
reqWidth = (!reqWidth) ? hw_w : reqWidth;
reqHeight = (!reqHeight) ? hw_h : reqHeight;
@@ -3388,7 +3559,8 @@ status_t SurfaceFlinger::captureScreenImplLocked(
if (image != EGL_NO_IMAGE_KHR) {
// this binds the given EGLImage as a framebuffer for the
// duration of this scope.
- RenderEngine::BindImageAsFramebuffer imageBond(getRenderEngine(), image);
+ RenderEngine::BindImageAsFramebuffer imageBond(getRenderEngine(), image,
+ useReadPixels, reqWidth, reqHeight);
if (imageBond.getStatus() == NO_ERROR) {
// this will in fact render into our dequeued buffer
// via an FBO, which means we didn't have to create
@@ -3435,6 +3607,15 @@ status_t SurfaceFlinger::captureScreenImplLocked(
ALOGW("captureScreen: error creating EGL fence: %#x", eglGetError());
}
}
+ if (useReadPixels) {
+ sp<GraphicBuffer> buf = static_cast<GraphicBuffer*>(buffer);
+ void* vaddr;
+ if (buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, &vaddr) == NO_ERROR) {
+ getRenderEngine().readPixels(0, 0, buffer->stride, reqHeight,
+ (uint32_t *)vaddr);
+ buf->unlock();
+ }
+ }
if (DEBUG_SCREENSHOTS) {
uint32_t* pixels = new uint32_t[reqWidth*reqHeight];
getRenderEngine().readPixels(0, 0, reqWidth, reqHeight, pixels);
@@ -3492,6 +3673,44 @@ void SurfaceFlinger::checkScreenshot(size_t w, size_t s, size_t h, void const* v
}
}
+/* ------------------------------------------------------------------------
+ * Extensions
+ */
+
+bool SurfaceFlinger::updateLayerVisibleNonTransparentRegion(const int& /*dpy*/,
+ const sp<Layer>& layer, bool& /*bIgnoreLayers*/, int& /*indexLOI*/,
+ uint32_t layerStack, const int& /*i*/) {
+
+ const Layer::State& s(layer->getDrawingState());
+
+ // only consider the layers on the given layer stack
+ if (s.layerStack != layerStack) {
+ /* set the visible region as empty since we have removed the
+ * layerstack check in rebuildLayerStack() function
+ */
+ Region visibleNonTransRegion;
+ visibleNonTransRegion.set(Rect(0,0));
+ layer->setVisibleNonTransparentRegion(visibleNonTransRegion);
+
+ return true;
+ }
+
+ return false;
+}
+
+bool SurfaceFlinger::canDrawLayerinScreenShot(
+ const sp<const DisplayDevice>& /*hw*/,
+ const sp<Layer>& layer) {
+ return layer->isVisible();
+}
+
+void SurfaceFlinger::drawWormHoleIfRequired(HWComposer::LayerListIterator& /*cur*/,
+ const HWComposer::LayerListIterator& /*end*/,
+ const sp<const DisplayDevice>& hw,
+ const Region& region) {
+ drawWormhole(hw, region);
+}
+
// ---------------------------------------------------------------------------
SurfaceFlinger::LayerVector::LayerVector() {