summaryrefslogtreecommitdiffstats
path: root/services/surfaceflinger
diff options
context:
space:
mode:
Diffstat (limited to 'services/surfaceflinger')
-rw-r--r--services/surfaceflinger/Android.mk35
-rw-r--r--services/surfaceflinger/Client.cpp59
-rw-r--r--services/surfaceflinger/Client.h22
-rw-r--r--services/surfaceflinger/DisplayDevice.cpp293
-rw-r--r--services/surfaceflinger/DisplayDevice.h40
-rw-r--r--services/surfaceflinger/DisplayHardware/DisplaySurface.h68
-rw-r--r--services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp67
-rw-r--r--services/surfaceflinger/DisplayHardware/FramebufferSurface.h26
-rw-r--r--services/surfaceflinger/DisplayHardware/GraphicBufferAlloc.cpp53
-rw-r--r--services/surfaceflinger/DisplayHardware/GraphicBufferAlloc.h44
-rw-r--r--services/surfaceflinger/DisplayHardware/HWComposer.cpp252
-rw-r--r--services/surfaceflinger/DisplayHardware/HWComposer.h45
-rw-r--r--services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp56
-rw-r--r--services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h55
-rw-r--r--services/surfaceflinger/EventThread.cpp16
-rw-r--r--services/surfaceflinger/FrameTracker.cpp143
-rw-r--r--services/surfaceflinger/FrameTracker.h124
-rw-r--r--services/surfaceflinger/GLExtensions.cpp5
-rw-r--r--services/surfaceflinger/Layer.cpp839
-rw-r--r--services/surfaceflinger/Layer.h336
-rw-r--r--services/surfaceflinger/LayerBase.cpp573
-rw-r--r--services/surfaceflinger/LayerBase.h359
-rw-r--r--services/surfaceflinger/LayerDim.cpp15
-rw-r--r--services/surfaceflinger/LayerDim.h10
-rw-r--r--services/surfaceflinger/LayerScreenshot.cpp171
-rw-r--r--services/surfaceflinger/LayerScreenshot.h62
-rw-r--r--services/surfaceflinger/MessageQueue.cpp15
-rw-r--r--services/surfaceflinger/MessageQueue.h16
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp1044
-rw-r--r--services/surfaceflinger/SurfaceFlinger.h113
-rw-r--r--services/surfaceflinger/SurfaceFlingerConsumer.cpp104
-rw-r--r--services/surfaceflinger/SurfaceFlingerConsumer.h59
-rw-r--r--services/surfaceflinger/SurfaceTextureLayer.cpp23
-rw-r--r--services/surfaceflinger/SurfaceTextureLayer.h16
-rw-r--r--services/surfaceflinger/Transform.cpp38
-rw-r--r--services/surfaceflinger/Transform.h2
-rw-r--r--services/surfaceflinger/clz.cpp37
-rw-r--r--services/surfaceflinger/tests/Transaction_test.cpp12
-rw-r--r--services/surfaceflinger/tests/resize/resize.cpp19
-rw-r--r--services/surfaceflinger/tests/surface/Android.mk18
-rw-r--r--services/surfaceflinger/tests/surface/surface.cpp66
41 files changed, 2820 insertions, 2530 deletions
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 5a57697..ec296d3 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -2,23 +2,22 @@ LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
- Client.cpp \
- DisplayDevice.cpp \
- EventThread.cpp \
- Layer.cpp \
- LayerBase.cpp \
- LayerDim.cpp \
- LayerScreenshot.cpp \
- DisplayHardware/FramebufferSurface.cpp \
- DisplayHardware/GraphicBufferAlloc.cpp \
- DisplayHardware/HWComposer.cpp \
- DisplayHardware/PowerHAL.cpp \
- GLExtensions.cpp \
- MessageQueue.cpp \
- SurfaceFlinger.cpp \
- SurfaceTextureLayer.cpp \
- Transform.cpp \
-
+ Client.cpp \
+ DisplayDevice.cpp \
+ EventThread.cpp \
+ FrameTracker.cpp \
+ GLExtensions.cpp \
+ Layer.cpp \
+ LayerDim.cpp \
+ MessageQueue.cpp \
+ SurfaceFlinger.cpp \
+ SurfaceFlingerConsumer.cpp \
+ SurfaceTextureLayer.cpp \
+ Transform.cpp \
+ DisplayHardware/FramebufferSurface.cpp \
+ DisplayHardware/HWComposer.cpp \
+ DisplayHardware/PowerHAL.cpp \
+ DisplayHardware/VirtualDisplaySurface.cpp \
LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\"
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
@@ -44,6 +43,7 @@ endif
LOCAL_SHARED_LIBRARIES := \
libcutils \
+ liblog \
libdl \
libhardware \
libutils \
@@ -68,6 +68,7 @@ LOCAL_SRC_FILES:= \
LOCAL_SHARED_LIBRARIES := \
libcutils \
+ liblog \
libdl
LOCAL_MODULE:= libsurfaceflinger_ddmconnection
diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp
index c28254f..dd65348 100644
--- a/services/surfaceflinger/Client.cpp
+++ b/services/surfaceflinger/Client.cpp
@@ -23,7 +23,6 @@
#include "Client.h"
#include "Layer.h"
-#include "LayerBase.h"
#include "SurfaceFlinger.h"
namespace android {
@@ -35,7 +34,7 @@ const String16 sAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER"
// ---------------------------------------------------------------------------
Client::Client(const sp<SurfaceFlinger>& flinger)
- : mFlinger(flinger), mNameGenerator(1)
+ : mFlinger(flinger)
{
}
@@ -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,15 +53,13 @@ status_t Client::initCheck() const {
return NO_ERROR;
}
-size_t Client::attachLayer(const sp<LayerBaseClient>& layer)
+void Client::attachLayer(const sp<IBinder>& handle, const sp<Layer>& layer)
{
Mutex::Autolock _l(mLock);
- size_t name = mNameGenerator++;
- mLayers.add(name, layer);
- return name;
+ 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
@@ -74,14 +71,14 @@ void Client::detachLayer(const LayerBaseClient* layer)
}
}
}
-sp<LayerBaseClient> Client::getLayerUser(int32_t i) const
+sp<Layer> Client::getLayerUser(const sp<IBinder>& handle) const
{
Mutex::Autolock _l(mLock);
- sp<LayerBaseClient> lbc;
- wp<LayerBaseClient> layer(mLayers.valueFor(i));
+ sp<Layer> lbc;
+ wp<Layer> layer(mLayers.valueFor(handle));
if (layer != 0) {
lbc = layer.promote();
- ALOGE_IF(lbc==0, "getLayerUser(name=%d) is dead", int(i));
+ ALOGE_IF(lbc==0, "getLayerUser(name=%p) is dead", handle.get());
}
return lbc;
}
@@ -108,11 +105,11 @@ status_t Client::onTransact(
}
-sp<ISurface> Client::createSurface(
- ISurfaceComposerClient::surface_data_t* params,
+status_t Client::createSurface(
const String8& name,
- uint32_t w, uint32_t h, PixelFormat format,
- uint32_t flags)
+ uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
+ sp<IBinder>* handle,
+ sp<IGraphicBufferProducer>* gbp)
{
/*
* createSurface must be called from the GL thread so that it can
@@ -120,39 +117,41 @@ sp<ISurface> Client::createSurface(
*/
class MessageCreateLayer : public MessageBase {
- sp<ISurface> result;
SurfaceFlinger* flinger;
- ISurfaceComposerClient::surface_data_t* params;
Client* client;
+ sp<IBinder>* handle;
+ sp<IGraphicBufferProducer>* gbp;
+ status_t result;
const String8& name;
uint32_t w, h;
PixelFormat format;
uint32_t flags;
public:
MessageCreateLayer(SurfaceFlinger* flinger,
- ISurfaceComposerClient::surface_data_t* params,
const String8& name, Client* client,
- uint32_t w, uint32_t h, PixelFormat format,
- uint32_t flags)
- : flinger(flinger), params(params), client(client), name(name),
- w(w), h(h), format(format), flags(flags)
- {
+ uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
+ sp<IBinder>* handle,
+ sp<IGraphicBufferProducer>* gbp)
+ : flinger(flinger), client(client),
+ handle(handle), gbp(gbp),
+ name(name), w(w), h(h), format(format), flags(flags) {
}
- sp<ISurface> getResult() const { return result; }
+ status_t getResult() const { return result; }
virtual bool handler() {
- result = flinger->createLayer(params, name, client,
- w, h, format, flags);
+ result = flinger->createLayer(name, client, w, h, format, flags,
+ handle, gbp);
return true;
}
};
sp<MessageBase> msg = new MessageCreateLayer(mFlinger.get(),
- params, name, this, w, h, format, flags);
+ name, this, w, h, format, flags, handle, gbp);
mFlinger->postMessageSync(msg);
return static_cast<MessageCreateLayer*>( msg.get() )->getResult();
}
-status_t Client::destroySurface(SurfaceID sid) {
- return mFlinger->onLayerRemoved(this, sid);
+
+status_t Client::destroySurface(const sp<IBinder>& handle) {
+ return mFlinger->onLayerRemoved(this, handle);
}
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/Client.h b/services/surfaceflinger/Client.h
index d6c6931..84e649f 100644
--- a/services/surfaceflinger/Client.h
+++ b/services/surfaceflinger/Client.h
@@ -30,7 +30,7 @@ namespace android {
// ---------------------------------------------------------------------------
-class LayerBaseClient;
+class Layer;
class SurfaceFlinger;
// ---------------------------------------------------------------------------
@@ -44,20 +44,21 @@ public:
status_t initCheck() const;
// protected by SurfaceFlinger::mStateLock
- size_t attachLayer(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(int32_t i) const;
+ sp<Layer> getLayerUser(const sp<IBinder>& handle) const;
private:
// ISurfaceComposerClient interface
- virtual sp<ISurface> createSurface(
- surface_data_t* params, const String8& name,
- uint32_t w, uint32_t h,PixelFormat format,
- uint32_t flags);
+ virtual status_t createSurface(
+ const String8& name,
+ uint32_t w, uint32_t h,PixelFormat format, uint32_t flags,
+ sp<IBinder>* handle,
+ sp<IGraphicBufferProducer>* gbp);
- virtual status_t destroySurface(SurfaceID surfaceId);
+ virtual status_t destroySurface(const sp<IBinder>& handle);
virtual status_t onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
@@ -66,8 +67,7 @@ private:
sp<SurfaceFlinger> mFlinger;
// protected by mLock
- DefaultKeyedVector< size_t, wp<LayerBaseClient> > mLayers;
- size_t mNameGenerator;
+ DefaultKeyedVector< wp<IBinder>, wp<Layer> > mLayers;
// thread-safe
mutable Mutex mLock;
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 69b9c34..68b0b7f 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -27,7 +27,7 @@
#include <ui/DisplayInfo.h>
#include <ui/PixelFormat.h>
-#include <gui/SurfaceTextureClient.h>
+#include <gui/Surface.h>
#include <GLES/gl.h>
#include <EGL/egl.h>
@@ -35,14 +35,14 @@
#include <hardware/gralloc.h>
-#include "DisplayHardware/FramebufferSurface.h"
+#include "DisplayHardware/DisplaySurface.h"
#include "DisplayHardware/HWComposer.h"
#include "clz.h"
#include "DisplayDevice.h"
#include "GLExtensions.h"
#include "SurfaceFlinger.h"
-#include "LayerBase.h"
+#include "Layer.h"
// ----------------------------------------------------------------------------
using namespace android;
@@ -70,16 +70,15 @@ void checkGLErrors()
DisplayDevice::DisplayDevice(
const sp<SurfaceFlinger>& flinger,
DisplayType type,
+ int32_t hwcId,
bool isSecure,
const wp<IBinder>& displayToken,
- const sp<ANativeWindow>& nativeWindow,
- const sp<FramebufferSurface>& framebufferSurface,
+ const sp<DisplaySurface>& displaySurface,
EGLConfig config)
: mFlinger(flinger),
- mType(type), mHwcDisplayId(-1),
+ mType(type), mHwcDisplayId(hwcId),
mDisplayToken(displayToken),
- mNativeWindow(nativeWindow),
- mFramebufferSurface(framebufferSurface),
+ mDisplaySurface(displaySurface),
mDisplay(EGL_NO_DISPLAY),
mSurface(EGL_NO_SURFACE),
mContext(EGL_NO_CONTEXT),
@@ -89,41 +88,10 @@ DisplayDevice::DisplayDevice(
mIsSecure(isSecure),
mSecureLayerVisible(false),
mScreenAcquired(false),
- mLayerStack(0),
+ mLayerStack(NO_LAYER_STACK),
mOrientation()
{
- init(config);
-}
-
-DisplayDevice::~DisplayDevice() {
- if (mSurface != EGL_NO_SURFACE) {
- eglDestroySurface(mDisplay, mSurface);
- mSurface = EGL_NO_SURFACE;
- }
-}
-
-bool DisplayDevice::isValid() const {
- return mFlinger != NULL;
-}
-
-int DisplayDevice::getWidth() const {
- return mDisplayWidth;
-}
-
-int DisplayDevice::getHeight() const {
- return mDisplayHeight;
-}
-
-PixelFormat DisplayDevice::getFormat() const {
- return mFormat;
-}
-
-EGLSurface DisplayDevice::getEGLSurface() const {
- return mSurface;
-}
-
-void DisplayDevice::init(EGLConfig config)
-{
+ mNativeWindow = new Surface(mDisplaySurface->getIGraphicBufferProducer());
ANativeWindow* const window = mNativeWindow.get();
int format;
@@ -147,11 +115,8 @@ void DisplayDevice::init(EGLConfig config)
mViewport.makeInvalid();
mFrame.makeInvalid();
- // external displays are always considered enabled
- mScreenAcquired = (mType >= DisplayDevice::NUM_DISPLAY_TYPES);
-
- // get an h/w composer ID
- mHwcDisplayId = mFlinger->allocateHwcDisplayId(mType);
+ // virtual displays are always considered enabled
+ mScreenAcquired = (mType >= DisplayDevice::DISPLAY_VIRTUAL);
// Name the display. The name will be replaced shortly if the display
// was created with createDisplay().
@@ -171,6 +136,42 @@ void DisplayDevice::init(EGLConfig config)
setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
}
+DisplayDevice::~DisplayDevice() {
+ if (mSurface != EGL_NO_SURFACE) {
+ eglDestroySurface(mDisplay, mSurface);
+ mSurface = EGL_NO_SURFACE;
+ }
+}
+
+void DisplayDevice::disconnect(HWComposer& hwc) {
+ if (mHwcDisplayId >= 0) {
+ hwc.disconnectDisplay(mHwcDisplayId);
+ if (mHwcDisplayId >= DISPLAY_VIRTUAL)
+ hwc.freeDisplayId(mHwcDisplayId);
+ mHwcDisplayId = -1;
+ }
+}
+
+bool DisplayDevice::isValid() const {
+ return mFlinger != NULL;
+}
+
+int DisplayDevice::getWidth() const {
+ return mDisplayWidth;
+}
+
+int DisplayDevice::getHeight() const {
+ return mDisplayHeight;
+}
+
+PixelFormat DisplayDevice::getFormat() const {
+ return mFormat;
+}
+
+EGLSurface DisplayDevice::getEGLSurface() const {
+ return mSurface;
+}
+
void DisplayDevice::setDisplayName(const String8& displayName) {
if (!displayName.isEmpty()) {
// never override the name with an empty name
@@ -183,10 +184,7 @@ uint32_t DisplayDevice::getPageFlipCount() const {
}
status_t DisplayDevice::compositionComplete() const {
- if (mFramebufferSurface == NULL) {
- return NO_ERROR;
- }
- return mFramebufferSurface->compositionComplete();
+ return mDisplaySurface->compositionComplete();
}
void DisplayDevice::flip(const Region& dirty) const
@@ -196,58 +194,50 @@ void DisplayDevice::flip(const Region& dirty) const
EGLDisplay dpy = mDisplay;
EGLSurface surface = mSurface;
-#ifdef EGL_ANDROID_swap_rectangle
+#ifdef EGL_ANDROID_swap_rectangle
if (mFlags & SWAP_RECTANGLE) {
const Region newDirty(dirty.intersect(bounds()));
const Rect b(newDirty.getBounds());
eglSetSwapRectangleANDROID(dpy, surface,
b.left, b.top, b.width(), b.height());
- }
+ }
#endif
mPageFlipCount++;
}
void DisplayDevice::swapBuffers(HWComposer& hwc) const {
- EGLBoolean success = EGL_TRUE;
- if (hwc.initCheck() != NO_ERROR) {
- // no HWC, we call eglSwapBuffers()
- success = eglSwapBuffers(mDisplay, mSurface);
- } else {
- // We have a valid HWC, but not all displays can use it, in particular
- // the virtual displays are on their own.
- // TODO: HWC 1.2 will allow virtual displays
- if (mType >= DisplayDevice::DISPLAY_VIRTUAL) {
- // always call eglSwapBuffers() for virtual displays
- success = eglSwapBuffers(mDisplay, mSurface);
- } else if (hwc.supportsFramebufferTarget()) {
- // as of hwc 1.1 we always call eglSwapBuffers if we have some
- // GLES layers
- if (hwc.hasGlesComposition(mType)) {
- success = eglSwapBuffers(mDisplay, mSurface);
+ // We need to call eglSwapBuffers() unless:
+ // (a) there was no GLES composition this frame, or
+ // (b) we're using a legacy HWC with no framebuffer target support (in
+ // which case HWComposer::commit() handles things).
+ if (hwc.initCheck() != NO_ERROR ||
+ (hwc.hasGlesComposition(mHwcDisplayId) &&
+ hwc.supportsFramebufferTarget())) {
+ EGLBoolean success = eglSwapBuffers(mDisplay, mSurface);
+ if (!success) {
+ EGLint error = eglGetError();
+ if (error == EGL_CONTEXT_LOST ||
+ mType == DisplayDevice::DISPLAY_PRIMARY) {
+ LOG_ALWAYS_FATAL("eglSwapBuffers(%p, %p) failed with 0x%08x",
+ mDisplay, mSurface, error);
+ } else {
+ ALOGE("eglSwapBuffers(%p, %p) failed with 0x%08x",
+ mDisplay, mSurface, error);
}
- } else {
- // HWC doesn't have the framebuffer target, we don't call
- // eglSwapBuffers(), since this is handled by HWComposer::commit().
}
}
- if (!success) {
- EGLint error = eglGetError();
- if (error == EGL_CONTEXT_LOST ||
- mType == DisplayDevice::DISPLAY_PRIMARY) {
- LOG_ALWAYS_FATAL("eglSwapBuffers(%p, %p) failed with 0x%08x",
- mDisplay, mSurface, error);
- }
+ status_t result = mDisplaySurface->advanceFrame();
+ if (result != NO_ERROR) {
+ ALOGE("[%s] failed pushing new frame to HWC: %d",
+ mDisplayName.string(), result);
}
}
void DisplayDevice::onSwapBuffersCompleted(HWComposer& hwc) const {
if (hwc.initCheck() == NO_ERROR) {
- if (hwc.supportsFramebufferTarget()) {
- int fd = hwc.getAndResetReleaseFenceFd(mType);
- mFramebufferSurface->setReleaseFenceFd(fd);
- }
+ mDisplaySurface->onFrameCommitted();
}
}
@@ -282,18 +272,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++) {
- if (layers[i]->isSecure()) {
+ 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;
}
@@ -365,94 +356,96 @@ status_t DisplayDevice::orientationToTransfrom(
}
void DisplayDevice::setProjection(int orientation,
- const Rect& viewport, const Rect& frame) {
- mOrientation = orientation;
- mViewport = viewport;
- mFrame = frame;
- updateGeometryTransform();
-}
+ const Rect& newViewport, const Rect& newFrame) {
+ Rect viewport(newViewport);
+ Rect frame(newFrame);
-void DisplayDevice::updateGeometryTransform() {
- int w = mDisplayWidth;
- int h = mDisplayHeight;
- Transform TL, TP, R, S;
- if (DisplayDevice::orientationToTransfrom(
- mOrientation, w, h, &R) == NO_ERROR) {
- dirtyRegion.set(bounds());
-
- Rect viewport(mViewport);
- Rect frame(mFrame);
-
- if (!frame.isValid()) {
- // the destination frame can be invalid if it has never been set,
- // in that case we assume the whole display frame.
- frame = Rect(w, h);
- }
+ const int w = mDisplayWidth;
+ const int h = mDisplayHeight;
- if (viewport.isEmpty()) {
- // viewport can be invalid if it has never been set, in that case
- // we assume the whole display size.
- // it's also invalid to have an empty viewport, so we handle that
- // case in the same way.
- viewport = Rect(w, h);
- if (R.getOrientation() & Transform::ROT_90) {
- // viewport is always specified in the logical orientation
- // of the display (ie: post-rotation).
- swap(viewport.right, viewport.bottom);
- }
- }
+ Transform R;
+ DisplayDevice::orientationToTransfrom(orientation, w, h, &R);
- float src_width = viewport.width();
- float src_height = viewport.height();
- float dst_width = frame.width();
- float dst_height = frame.height();
- if (src_width != dst_width || src_height != dst_height) {
- float sx = dst_width / src_width;
- float sy = dst_height / src_height;
- S.set(sx, 0, 0, sy);
+ if (!frame.isValid()) {
+ // the destination frame can be invalid if it has never been set,
+ // in that case we assume the whole display frame.
+ frame = Rect(w, h);
+ }
+
+ if (viewport.isEmpty()) {
+ // viewport can be invalid if it has never been set, in that case
+ // we assume the whole display size.
+ // it's also invalid to have an empty viewport, so we handle that
+ // case in the same way.
+ viewport = Rect(w, h);
+ if (R.getOrientation() & Transform::ROT_90) {
+ // viewport is always specified in the logical orientation
+ // of the display (ie: post-rotation).
+ swap(viewport.right, viewport.bottom);
}
+ }
+
+ dirtyRegion.set(getBounds());
+
+ Transform TL, TP, S;
+ float src_width = viewport.width();
+ float src_height = viewport.height();
+ float dst_width = frame.width();
+ float dst_height = frame.height();
+ if (src_width != dst_width || src_height != dst_height) {
+ float sx = dst_width / src_width;
+ float sy = dst_height / src_height;
+ S.set(sx, 0, 0, sy);
+ }
- float src_x = viewport.left;
- float src_y = viewport.top;
- float dst_x = frame.left;
- float dst_y = frame.top;
- TL.set(-src_x, -src_y);
- TP.set(dst_x, dst_y);
-
- // The viewport and frame are both in the logical orientation.
- // Apply the logical translation, scale to physical size, apply the
- // physical translation and finally rotate to the physical orientation.
- mGlobalTransform = R * TP * S * TL;
-
- const uint8_t type = mGlobalTransform.getType();
- mNeedsFiltering = (!mGlobalTransform.preserveRects() ||
- (type >= Transform::SCALE));
+ float src_x = viewport.left;
+ float src_y = viewport.top;
+ float dst_x = frame.left;
+ float dst_y = frame.top;
+ TL.set(-src_x, -src_y);
+ TP.set(dst_x, dst_y);
+
+ // The viewport and frame are both in the logical orientation.
+ // Apply the logical translation, scale to physical size, apply the
+ // physical translation and finally rotate to the physical orientation.
+ mGlobalTransform = R * TP * S * TL;
+
+ const uint8_t type = mGlobalTransform.getType();
+ mNeedsFiltering = (!mGlobalTransform.preserveRects() ||
+ (type >= Transform::SCALE));
+
+ mScissor = mGlobalTransform.transform(viewport);
+ if (mScissor.isEmpty()) {
+ mScissor.set(getBounds());
}
+
+ mOrientation = orientation;
+ mViewport = viewport;
+ mFrame = frame;
}
void DisplayDevice::dump(String8& result, char* buffer, size_t SIZE) const {
const Transform& tr(mGlobalTransform);
snprintf(buffer, SIZE,
"+ DisplayDevice: %s\n"
- " type=%x, layerStack=%u, (%4dx%4d), ANativeWindow=%p, orient=%2d (type=%08x), "
+ " type=%x, hwcId=%d, layerStack=%u, (%4dx%4d), ANativeWindow=%p, orient=%2d (type=%08x), "
"flips=%u, isSecure=%d, secureVis=%d, acquired=%d, numLayers=%u\n"
- " v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], "
+ " v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], s:[%d,%d,%d,%d],"
"transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n",
- mDisplayName.string(), mType,
+ mDisplayName.string(), mType, mHwcDisplayId,
mLayerStack, mDisplayWidth, mDisplayHeight, mNativeWindow.get(),
mOrientation, tr.getType(), getPageFlipCount(),
mIsSecure, mSecureLayerVisible, mScreenAcquired, mVisibleLayersSortedByZ.size(),
mViewport.left, mViewport.top, mViewport.right, mViewport.bottom,
mFrame.left, mFrame.top, mFrame.right, mFrame.bottom,
+ mScissor.left, mScissor.top, mScissor.right, mScissor.bottom,
tr[0][0], tr[1][0], tr[2][0],
tr[0][1], tr[1][1], tr[2][1],
tr[0][2], tr[1][2], tr[2][2]);
result.append(buffer);
- String8 fbtargetDump;
- if (mFramebufferSurface != NULL) {
- mFramebufferSurface->dump(fbtargetDump);
- result.append(fbtargetDump);
- }
+ String8 surfaceDump;
+ mDisplaySurface->dump(surfaceDump);
+ result.append(surfaceDump);
}
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index d6da422..377d924 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -37,8 +37,8 @@ struct ANativeWindow;
namespace android {
class DisplayInfo;
-class FramebufferSurface;
-class LayerBase;
+class DisplaySurface;
+class Layer;
class SurfaceFlinger;
class HWComposer;
@@ -65,13 +65,17 @@ public:
SWAP_RECTANGLE = 0x00080000,
};
+ enum {
+ NO_LAYER_STACK = 0xFFFFFFFF,
+ };
+
DisplayDevice(
const sp<SurfaceFlinger>& flinger,
DisplayType type,
+ int32_t hwcId, // negative for non-HWC-composited displays
bool isSecure,
const wp<IBinder>& displayToken,
- const sp<ANativeWindow>& nativeWindow,
- const sp<FramebufferSurface>& framebufferSurface,
+ const sp<DisplaySurface>& displaySurface,
EGLConfig config);
~DisplayDevice();
@@ -95,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;
@@ -105,8 +109,9 @@ public:
int getOrientation() const { return mOrientation; }
const Transform& getTransform() const { return mGlobalTransform; }
- const Rect& getViewport() const { return mViewport; }
- const Rect& getFrame() const { return mFrame; }
+ const Rect getViewport() const { return mViewport; }
+ const Rect getFrame() const { return mFrame; }
+ const Rect& getScissor() const { return mScissor; }
bool needsFiltering() const { return mNeedsFiltering; }
uint32_t getLayerStack() const { return mLayerStack; }
@@ -116,7 +121,7 @@ public:
void swapBuffers(HWComposer& hwc) const;
status_t compositionComplete() const;
-
+
// called after h/w composer has completed its set() call
void onSwapBuffersCompleted(HWComposer& hwc) const;
@@ -141,6 +146,9 @@ public:
bool isScreenAcquired() const;
bool canDraw() const;
+ // release HWC resources (if any) for removable displays
+ void disconnect(HWComposer& hwc);
+
/* ------------------------------------------------------------------------
* Debugging
*/
@@ -148,8 +156,6 @@ public:
void dump(String8& result, char* buffer, size_t SIZE) const;
private:
- void init(EGLConfig config);
-
/*
* Constants, set during initialization
*/
@@ -160,9 +166,7 @@ private:
// ANativeWindow this display is rendering into
sp<ANativeWindow> mNativeWindow;
-
- // set if mNativeWindow is a FramebufferSurface
- sp<FramebufferSurface> mFramebufferSurface;
+ sp<DisplaySurface> mDisplaySurface;
EGLDisplay mDisplay;
EGLSurface mSurface;
@@ -181,7 +185,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;
@@ -196,12 +200,14 @@ private:
static status_t orientationToTransfrom(int orientation,
int w, int h, Transform* tr);
- void updateGeometryTransform();
-
uint32_t mLayerStack;
int mOrientation;
+ // user-provided visible area of the layer stack
Rect mViewport;
+ // user-provided rectangle where mViewport gets mapped to
Rect mFrame;
+ // pre-computed scissor to apply to the display
+ Rect mScissor;
Transform mGlobalTransform;
bool mNeedsFiltering;
};
diff --git a/services/surfaceflinger/DisplayHardware/DisplaySurface.h b/services/surfaceflinger/DisplayHardware/DisplaySurface.h
new file mode 100644
index 0000000..2eca3cb
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/DisplaySurface.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2013 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_SF_DISPLAY_SURFACE_H
+#define ANDROID_SF_DISPLAY_SURFACE_H
+
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <utils/StrongPointer.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+class IGraphicBufferProducer;
+class String8;
+
+class DisplaySurface : public virtual RefBase {
+public:
+ virtual sp<IGraphicBufferProducer> getIGraphicBufferProducer() const = 0;
+
+ // Should be called when composition rendering is complete for a frame (but
+ // eglSwapBuffers hasn't necessarily been called). Required by certain
+ // older drivers for synchronization.
+ // TODO: Remove this when we drop support for HWC 1.0.
+ virtual status_t compositionComplete() = 0;
+
+ // Inform the surface that GLES composition is complete for this frame, and
+ // the surface should make sure that HWComposer has the correct buffer for
+ // this frame. Some implementations may only push a new buffer to
+ // HWComposer if GLES composition took place, others need to push a new
+ // buffer on every frame.
+ //
+ // advanceFrame must be followed by a call to onFrameCommitted before
+ // advanceFrame may be called again.
+ virtual status_t advanceFrame() = 0;
+
+ // onFrameCommitted is called after the frame has been committed to the
+ // hardware composer. The surface collects the release fence for this
+ // frame's buffer.
+ virtual void onFrameCommitted() = 0;
+
+ virtual void dump(String8& result) const = 0;
+
+protected:
+ DisplaySurface() {}
+ virtual ~DisplaySurface() {}
+};
+
+// ---------------------------------------------------------------------------
+} // namespace android
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_SF_DISPLAY_SURFACE_H
+
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 6c86a53..54a3ce8 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -29,12 +29,12 @@
#include <EGL/egl.h>
#include <hardware/hardware.h>
-#include <gui/SurfaceTextureClient.h>
+#include <gui/Surface.h>
+#include <gui/GraphicBufferAlloc.h>
#include <ui/GraphicBuffer.h>
-#include "DisplayHardware/FramebufferSurface.h"
-#include "DisplayHardware/GraphicBufferAlloc.h"
-#include "DisplayHardware/HWComposer.h"
+#include "FramebufferSurface.h"
+#include "HWComposer.h"
#ifndef NUM_FRAMEBUFFER_SURFACE_BUFFERS
#define NUM_FRAMEBUFFER_SURFACE_BUFFERS (2)
@@ -68,6 +68,17 @@ FramebufferSurface::FramebufferSurface(HWComposer& hwc, int disp) :
mBufferQueue->setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS);
}
+sp<IGraphicBufferProducer> FramebufferSurface::getIGraphicBufferProducer() const {
+ return getBufferQueue();
+}
+
+status_t FramebufferSurface::advanceFrame() {
+ // Once we remove FB HAL support, we can call nextBuffer() from here
+ // instead of using onFrameAvailable(). No real benefit, except it'll be
+ // more like VirtualDisplaySurface.
+ return NO_ERROR;
+}
+
status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence) {
Mutex::Autolock lock(mMutex);
@@ -129,22 +140,14 @@ void FramebufferSurface::freeBufferLocked(int slotIndex) {
}
}
-status_t FramebufferSurface::setReleaseFenceFd(int fenceFd) {
- status_t err = NO_ERROR;
- if (fenceFd >= 0) {
- sp<Fence> fence(new Fence(fenceFd));
- if (mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT) {
- status_t err = addReleaseFence(mCurrentBufferSlot, fence);
- ALOGE_IF(err, "setReleaseFenceFd: failed to add the fence: %s (%d)",
- strerror(-err), err);
- }
+void FramebufferSurface::onFrameCommitted() {
+ sp<Fence> fence = mHwc.getAndResetReleaseFence(mDisplayType);
+ if (fence->isValid() &&
+ mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT) {
+ status_t err = addReleaseFence(mCurrentBufferSlot, fence);
+ ALOGE_IF(err, "setReleaseFenceFd: failed to add the fence: %s (%d)",
+ strerror(-err), err);
}
- return err;
-}
-
-status_t FramebufferSurface::setUpdateRectangle(const Rect& r)
-{
- return INVALID_OPERATION;
}
status_t FramebufferSurface::compositionComplete()
@@ -152,11 +155,33 @@ status_t FramebufferSurface::compositionComplete()
return mHwc.fbCompositionComplete();
}
-void FramebufferSurface::dump(String8& result) {
- mHwc.fbDump(result);
+// Since DisplaySurface and ConsumerBase both have a method with this
+// signature, results will vary based on the static pointer type the caller is
+// using:
+// void dump(FrameBufferSurface* fbs, String8& s) {
+// // calls FramebufferSurface::dump()
+// fbs->dump(s);
+//
+// // calls ConsumerBase::dump() since it is non-virtual
+// static_cast<ConsumerBase*>(fbs)->dump(s);
+//
+// // calls FramebufferSurface::dump() since it is virtual
+// static_cast<DisplaySurface*>(fbs)->dump(s);
+// }
+// To make sure that all of these end up doing the same thing, we just redirect
+// to ConsumerBase::dump() here. It will take the internal lock, and then call
+// virtual dumpLocked(), which is where the real work happens.
+void FramebufferSurface::dump(String8& result) const {
ConsumerBase::dump(result);
}
+void FramebufferSurface::dumpLocked(String8& result, const char* prefix,
+ char* buffer, size_t SIZE) const
+{
+ mHwc.fbDump(result);
+ ConsumerBase::dumpLocked(result, prefix, buffer, SIZE);
+}
+
// ----------------------------------------------------------------------------
}; // namespace android
// ----------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index 6336345..2fde789 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -22,6 +22,8 @@
#include <gui/ConsumerBase.h>
+#include "DisplaySurface.h"
+
// ---------------------------------------------------------------------------
namespace android {
// ---------------------------------------------------------------------------
@@ -32,23 +34,20 @@ class HWComposer;
// ---------------------------------------------------------------------------
-class FramebufferSurface : public ConsumerBase {
+class FramebufferSurface : public ConsumerBase,
+ public DisplaySurface {
public:
FramebufferSurface(HWComposer& hwc, int disp);
- bool isUpdateOnDemand() const { return false; }
- status_t setUpdateRectangle(const Rect& updateRect);
- status_t compositionComplete();
+ virtual sp<IGraphicBufferProducer> getIGraphicBufferProducer() const;
- virtual void dump(String8& result);
+ virtual status_t compositionComplete();
+ virtual status_t advanceFrame();
+ virtual void onFrameCommitted();
- // setReleaseFenceFd stores a fence file descriptor that will signal when the
- // current buffer is no longer being read. This fence will be returned to
- // the producer when the current buffer is released by updateTexImage().
- // Multiple fences can be set for a given buffer; they will be merged into
- // a single union fence. The SurfaceTexture will close the file descriptor
- // when finished with it.
- status_t setReleaseFenceFd(int fenceFd);
+ // Implementation of DisplaySurface::dump(). Note that ConsumerBase also
+ // has a non-virtual dump() with the same signature.
+ virtual void dump(String8& result) const;
private:
virtual ~FramebufferSurface() { }; // this class cannot be overloaded
@@ -56,6 +55,9 @@ private:
virtual void onFrameAvailable();
virtual void freeBufferLocked(int slotIndex);
+ virtual void dumpLocked(String8& result, const char* prefix,
+ char* buffer, size_t SIZE) const;
+
// nextBuffer waits for and then latches the next buffer from the
// BufferQueue and releases the previously latched buffer to the
// BufferQueue. The new buffer is returned in the 'buffer' argument.
diff --git a/services/surfaceflinger/DisplayHardware/GraphicBufferAlloc.cpp b/services/surfaceflinger/DisplayHardware/GraphicBufferAlloc.cpp
deleted file mode 100644
index 965ff01..0000000
--- a/services/surfaceflinger/DisplayHardware/GraphicBufferAlloc.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- **
- ** Copyright 2012 The Android Open Source Project
- **
- ** Licensed under the Apache License Version 2.0(the "License");
- ** you may not use this file except in compliance with the License.
- ** You may obtain a copy of the License at
- **
- ** http://www.apache.org/licenses/LICENSE-2.0
- **
- ** Unless required by applicable law or agreed to in writing software
- ** distributed under the License is distributed on an "AS IS" BASIS
- ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied.
- ** See the License for the specific language governing permissions and
- ** limitations under the License.
- */
-
-#include <cutils/log.h>
-
-#include <ui/GraphicBuffer.h>
-
-#include "DisplayHardware/GraphicBufferAlloc.h"
-
-// ----------------------------------------------------------------------------
-namespace android {
-// ----------------------------------------------------------------------------
-
-GraphicBufferAlloc::GraphicBufferAlloc() {
-}
-
-GraphicBufferAlloc::~GraphicBufferAlloc() {
-}
-
-sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h,
- PixelFormat format, uint32_t usage, status_t* error) {
- sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage));
- status_t err = graphicBuffer->initCheck();
- *error = err;
- if (err != 0 || graphicBuffer->handle == 0) {
- if (err == NO_MEMORY) {
- GraphicBuffer::dumpAllocationsToSystemLog();
- }
- ALOGE("GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d) "
- "failed (%s), handle=%p",
- w, h, strerror(-err), graphicBuffer->handle);
- return 0;
- }
- return graphicBuffer;
-}
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-// ----------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayHardware/GraphicBufferAlloc.h b/services/surfaceflinger/DisplayHardware/GraphicBufferAlloc.h
deleted file mode 100644
index b08750c..0000000
--- a/services/surfaceflinger/DisplayHardware/GraphicBufferAlloc.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_SF_GRAPHIC_BUFFER_ALLOC_H
-#define ANDROID_SF_GRAPHIC_BUFFER_ALLOC_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <gui/IGraphicBufferAlloc.h>
-#include <ui/PixelFormat.h>
-#include <utils/Errors.h>
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-class GraphicBuffer;
-
-class GraphicBufferAlloc : public BnGraphicBufferAlloc {
-public:
- GraphicBufferAlloc();
- virtual ~GraphicBufferAlloc();
- virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
- PixelFormat format, uint32_t usage, status_t* error);
-};
-
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_SF_GRAPHIC_BUFFER_ALLOC_H
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 068fdcd..a9afbe5 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -25,6 +25,7 @@
#include <string.h>
#include <sys/types.h>
+#include <utils/CallStack.h>
#include <utils/Errors.h>
#include <utils/misc.h>
#include <utils/String8.h>
@@ -37,19 +38,27 @@
#include <hardware/hardware.h>
#include <hardware/hwcomposer.h>
+#include <android/configuration.h>
+
#include <cutils/log.h>
#include <cutils/properties.h>
-#include "Layer.h" // needed only for debugging
-#include "LayerBase.h"
#include "HWComposer.h"
-#include "SurfaceFlinger.h"
-#include <utils/CallStack.h>
+
+#include "../Layer.h" // needed only for debugging
+#include "../SurfaceFlinger.h"
namespace android {
+// This is not a real HWC version. It's used for in-development features that
+// haven't been committed to a specific real HWC version.
+#define HWC_DEVICE_API_VERSION_1_EXP HARDWARE_DEVICE_API_VERSION_2(1, 0xFF, HWC_HEADER_VERSION)
+
#define MIN_HWC_HEADER_VERSION HWC_HEADER_VERSION
+#define NUM_PHYSICAL_DISPLAYS HWC_NUM_DISPLAY_TYPES
+#define VIRTUAL_DISPLAY_ID_BASE HWC_NUM_DISPLAY_TYPES
+
static uint32_t hwcApiVersion(const hwc_composer_device_1_t* hwc) {
uint32_t hwcVersion = hwc->common.version;
return hwcVersion & HARDWARE_API_VERSION_2_MAJ_MIN_MASK;
@@ -100,7 +109,7 @@ HWComposer::HWComposer(
bool needVSyncThread = true;
// Note: some devices may insist that the FB HAL be opened before HWC.
- loadFbHalModule();
+ int fberr = loadFbHalModule();
loadHwcModule();
if (mFbDev && mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
@@ -114,12 +123,13 @@ HWComposer::HWComposer(
// If we have no HWC, or a pre-1.1 HWC, an FB dev is mandatory.
if ((!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
&& !mFbDev) {
- ALOGE("ERROR: failed to open framebuffer, aborting");
+ ALOGE("ERROR: failed to open framebuffer (%s), aborting",
+ strerror(-fberr));
abort();
}
// these display IDs are always reserved
- for (size_t i=0 ; i<HWC_NUM_DISPLAY_TYPES ; i++) {
+ for (size_t i=0 ; i<NUM_PHYSICAL_DISPLAYS ; i++) {
mAllocatedDisplayIDs.markBit(i);
}
@@ -146,12 +156,12 @@ HWComposer::HWComposer(
// the number of displays we actually have depends on the
// hw composer version
- if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_2)) {
- // 1.2 adds support for virtual displays
+ if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_EXP)) {
+ // 1.?? adds support for virtual displays
mNumDisplays = MAX_DISPLAYS;
} else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
// 1.1 adds support for multiple displays
- mNumDisplays = HWC_NUM_DISPLAY_TYPES;
+ mNumDisplays = NUM_PHYSICAL_DISPLAYS;
} else {
mNumDisplays = 1;
}
@@ -179,7 +189,7 @@ HWComposer::HWComposer(
}
} else if (mHwc) {
// here we're guaranteed to have at least HWC 1.1
- for (size_t i =0 ; i<HWC_NUM_DISPLAY_TYPES ; i++) {
+ for (size_t i =0 ; i<NUM_PHYSICAL_DISPLAYS ; i++) {
queryDisplayProperties(i);
}
}
@@ -235,20 +245,17 @@ void HWComposer::loadHwcModule()
}
// Load and prepare the FB HAL, which uses the gralloc module. Sets mFbDev.
-void HWComposer::loadFbHalModule()
+int HWComposer::loadFbHalModule()
{
hw_module_t const* module;
- if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) != 0) {
+ int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
+ if (err != 0) {
ALOGE("%s module not found", GRALLOC_HARDWARE_MODULE_ID);
- return;
+ return err;
}
- int err = framebuffer_open(module, &mFbDev);
- if (err) {
- ALOGE("framebuffer_open failed (%s)", strerror(-err));
- return;
- }
+ return framebuffer_open(module, &mFbDev);
}
status_t HWComposer::initCheck() const {
@@ -287,7 +294,7 @@ void HWComposer::vsync(int disp, int64_t timestamp) {
}
void HWComposer::hotplug(int disp, int connected) {
- if (disp == HWC_DISPLAY_PRIMARY || disp >= HWC_NUM_DISPLAY_TYPES) {
+ if (disp == HWC_DISPLAY_PRIMARY || disp >= VIRTUAL_DISPLAY_ID_BASE) {
ALOGE("hotplug event received for invalid display: disp=%d connected=%d",
disp, connected);
return;
@@ -296,6 +303,11 @@ void HWComposer::hotplug(int disp, int connected) {
mEventHandler.onHotplugReceived(disp, bool(connected));
}
+static float getDefaultDensity(uint32_t height) {
+ if (height >= 1080) return ACONFIGURATION_DENSITY_XHIGH;
+ else return ACONFIGURATION_DENSITY_TV;
+}
+
static const uint32_t DISPLAY_ATTRIBUTES[] = {
HWC_DISPLAY_VSYNC_PERIOD,
HWC_DISPLAY_WIDTH,
@@ -306,10 +318,6 @@ static const uint32_t DISPLAY_ATTRIBUTES[] = {
};
#define NUM_DISPLAY_ATTRIBUTES (sizeof(DISPLAY_ATTRIBUTES) / sizeof(DISPLAY_ATTRIBUTES)[0])
-// http://developer.android.com/reference/android/util/DisplayMetrics.html
-#define ANDROID_DENSITY_TV 213
-#define ANDROID_DENSITY_XHIGH 320
-
status_t HWComposer::queryDisplayProperties(int disp) {
LOG_ALWAYS_FATAL_IF(!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1));
@@ -363,15 +371,23 @@ status_t HWComposer::queryDisplayProperties(int disp) {
mDisplayData[disp].format = HAL_PIXEL_FORMAT_RGBA_8888;
mDisplayData[disp].connected = true;
if (mDisplayData[disp].xdpi == 0.0f || mDisplayData[disp].ydpi == 0.0f) {
- // is there anything smarter we can do?
- if (h >= 1080) {
- mDisplayData[disp].xdpi = ANDROID_DENSITY_XHIGH;
- mDisplayData[disp].ydpi = ANDROID_DENSITY_XHIGH;
- } else {
- mDisplayData[disp].xdpi = ANDROID_DENSITY_TV;
- mDisplayData[disp].ydpi = ANDROID_DENSITY_TV;
- }
+ float dpi = getDefaultDensity(h);
+ mDisplayData[disp].xdpi = dpi;
+ mDisplayData[disp].ydpi = dpi;
+ }
+ return NO_ERROR;
+}
+
+status_t HWComposer::setVirtualDisplayProperties(int32_t id,
+ uint32_t w, uint32_t h, uint32_t format) {
+ if (id < VIRTUAL_DISPLAY_ID_BASE || id >= int32_t(mNumDisplays) ||
+ !mAllocatedDisplayIDs.hasBit(id)) {
+ return BAD_INDEX;
}
+ mDisplayData[id].width = w;
+ mDisplayData[id].height = h;
+ mDisplayData[id].format = format;
+ mDisplayData[id].xdpi = mDisplayData[id].ydpi = getDefaultDensity(h);
return NO_ERROR;
}
@@ -381,11 +397,12 @@ int32_t HWComposer::allocateDisplayId() {
}
int32_t id = mAllocatedDisplayIDs.firstUnmarkedBit();
mAllocatedDisplayIDs.markBit(id);
+ mDisplayData[id].connected = true;
return id;
}
status_t HWComposer::freeDisplayId(int32_t id) {
- if (id < HWC_NUM_DISPLAY_TYPES) {
+ if (id < NUM_PHYSICAL_DISPLAYS) {
// cannot free the reserved IDs
return BAD_VALUE;
}
@@ -393,6 +410,7 @@ status_t HWComposer::freeDisplayId(int32_t id) {
return BAD_INDEX;
}
mAllocatedDisplayIDs.clearBit(id);
+ mDisplayData[id].connected = false;
return NO_ERROR;
}
@@ -409,6 +427,10 @@ nsecs_t HWComposer::getRefreshTimestamp(int disp) const {
return now - ((now - mLastHwVSync) % mDisplayData[disp].refresh);
}
+sp<Fence> HWComposer::getDisplayFence(int disp) const {
+ return mDisplayData[disp].lastDisplayFence;
+}
+
uint32_t HWComposer::getWidth(int disp) const {
return mDisplayData[disp].width;
}
@@ -494,7 +516,7 @@ status_t HWComposer::createWorkList(int32_t id, size_t numLayers) {
if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
disp.framebufferTarget = &disp.list->hwLayers[numLayers - 1];
memset(disp.framebufferTarget, 0, sizeof(hwc_layer_1_t));
- const hwc_rect_t r = { 0, 0, disp.width, disp.height };
+ const hwc_rect_t r = { 0, 0, (int) disp.width, (int) disp.height };
disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET;
disp.framebufferTarget->hints = 0;
disp.framebufferTarget->flags = 0;
@@ -508,6 +530,7 @@ status_t HWComposer::createWorkList(int32_t id, size_t numLayers) {
&disp.framebufferTarget->displayFrame;
disp.framebufferTarget->acquireFenceFd = -1;
disp.framebufferTarget->releaseFenceFd = -1;
+ disp.framebufferTarget->planeAlpha = 0xFF;
}
disp.list->retireFenceFd = -1;
disp.list->flags = HWC_GEOMETRY_CHANGED;
@@ -524,7 +547,7 @@ status_t HWComposer::setFramebufferTarget(int32_t id,
DisplayData& disp(mDisplayData[id]);
if (!disp.framebufferTarget) {
// this should never happen, but apparently eglCreateWindowSurface()
- // triggers a SurfaceTextureClient::queueBuffer() on some
+ // triggers a Surface::queueBuffer() on some
// devices (!?) -- log and ignore.
ALOGE("HWComposer: framebufferTarget is null");
// CallStack stack;
@@ -534,7 +557,7 @@ status_t HWComposer::setFramebufferTarget(int32_t id,
}
int acquireFenceFd = -1;
- if (acquireFence != NULL) {
+ if (acquireFence->isValid()) {
acquireFenceFd = acquireFence->dup();
}
@@ -562,7 +585,7 @@ status_t HWComposer::prepare() {
}
mLists[i] = disp.list;
if (mLists[i]) {
- if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_2)) {
+ if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_EXP)) {
mLists[i]->outbuf = NULL;
mLists[i]->outbufAcquireFenceFd = -1;
} else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
@@ -611,20 +634,20 @@ status_t HWComposer::prepare() {
}
bool HWComposer::hasHwcComposition(int32_t id) const {
- if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
+ if (!mHwc || uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
return false;
return mDisplayData[id].hasOvComp;
}
bool HWComposer::hasGlesComposition(int32_t id) const {
- if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
- return false;
+ if (!mHwc || uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
+ return true;
return mDisplayData[id].hasFbComp;
}
-int HWComposer::getAndResetReleaseFenceFd(int32_t id) {
+sp<Fence> HWComposer::getAndResetReleaseFence(int32_t id) {
if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
- return BAD_INDEX;
+ return Fence::NO_FENCE;
int fd = INVALID_OPERATION;
if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
@@ -635,7 +658,7 @@ int HWComposer::getAndResetReleaseFenceFd(int32_t id) {
disp.framebufferTarget->releaseFenceFd = -1;
}
}
- return fd;
+ return fd >= 0 ? new Fence(fd) : Fence::NO_FENCE;
}
status_t HWComposer::commit() {
@@ -649,13 +672,24 @@ status_t HWComposer::commit() {
mLists[0]->sur = eglGetCurrentSurface(EGL_DRAW);
}
+ for (size_t i=VIRTUAL_DISPLAY_ID_BASE; i<mNumDisplays; i++) {
+ DisplayData& disp(mDisplayData[i]);
+ if (disp.outbufHandle) {
+ mLists[i]->outbuf = disp.outbufHandle;
+ mLists[i]->outbufAcquireFenceFd =
+ disp.outbufAcquireFence->dup();
+ }
+ }
+
err = mHwc->set(mHwc, mNumDisplays, mLists);
for (size_t i=0 ; i<mNumDisplays ; i++) {
DisplayData& disp(mDisplayData[i]);
+ disp.lastDisplayFence = disp.lastRetireFence;
+ disp.lastRetireFence = Fence::NO_FENCE;
if (disp.list) {
if (disp.list->retireFenceFd != -1) {
- close(disp.list->retireFenceFd);
+ disp.lastRetireFence = new Fence(disp.list->retireFenceFd);
disp.list->retireFenceFd = -1;
}
disp.list->flags &= ~HWC_GEOMETRY_CHANGED;
@@ -666,7 +700,7 @@ status_t HWComposer::commit() {
}
status_t HWComposer::release(int disp) {
- LOG_FATAL_IF(disp >= HWC_NUM_DISPLAY_TYPES);
+ LOG_FATAL_IF(disp >= VIRTUAL_DISPLAY_ID_BASE);
if (mHwc) {
eventControl(disp, HWC_EVENT_VSYNC, 0);
return (status_t)mHwc->blank(mHwc, disp, 1);
@@ -675,7 +709,7 @@ status_t HWComposer::release(int disp) {
}
status_t HWComposer::acquire(int disp) {
- LOG_FATAL_IF(disp >= HWC_NUM_DISPLAY_TYPES);
+ LOG_FATAL_IF(disp >= VIRTUAL_DISPLAY_ID_BASE);
if (mHwc) {
return (status_t)mHwc->blank(mHwc, disp, 0);
}
@@ -684,17 +718,15 @@ status_t HWComposer::acquire(int disp) {
void HWComposer::disconnectDisplay(int disp) {
LOG_ALWAYS_FATAL_IF(disp < 0 || disp == HWC_DISPLAY_PRIMARY);
- if (disp >= HWC_NUM_DISPLAY_TYPES) {
- // nothing to do for these yet
- return;
- }
DisplayData& dd(mDisplayData[disp]);
- if (dd.list != NULL) {
- free(dd.list);
- dd.list = NULL;
- dd.framebufferTarget = NULL; // points into dd.list
- dd.fbTargetHandle = NULL;
- }
+ free(dd.list);
+ dd.list = NULL;
+ dd.framebufferTarget = NULL; // points into dd.list
+ dd.fbTargetHandle = NULL;
+ dd.outbufHandle = NULL;
+ dd.lastRetireFence = Fence::NO_FENCE;
+ dd.lastDisplayFence = Fence::NO_FENCE;
+ dd.outbufAcquireFence = Fence::NO_FENCE;
}
int HWComposer::getVisualID() const {
@@ -718,9 +750,7 @@ int HWComposer::fbPost(int32_t id,
if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
return setFramebufferTarget(id, acquireFence, buffer);
} else {
- if (acquireFence != NULL) {
- acquireFence->waitForever(1000, "HWComposer::fbPost");
- }
+ acquireFence->waitForever("HWComposer::fbPost");
return mFbDev->post(mFbDev, buffer->handle);
}
}
@@ -745,6 +775,25 @@ void HWComposer::fbDump(String8& result) {
}
}
+status_t HWComposer::setOutputBuffer(int32_t id, const sp<Fence>& acquireFence,
+ const sp<GraphicBuffer>& buf) {
+ if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
+ return BAD_INDEX;
+ if (id < VIRTUAL_DISPLAY_ID_BASE)
+ return INVALID_OPERATION;
+
+ DisplayData& disp(mDisplayData[id]);
+ disp.outbufHandle = buf->handle;
+ disp.outbufAcquireFence = acquireFence;
+ return NO_ERROR;
+}
+
+sp<Fence> HWComposer::getLastRetireFence(int32_t id) {
+ if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
+ return Fence::NO_FENCE;
+ return mDisplayData[id].lastRetireFence;
+}
+
/*
* Helper template to implement a concrete HWCLayer
* This holds the pointer to the concrete hwc layer type
@@ -775,9 +824,10 @@ private:
* This implements the HWCLayer side of HWCIterableLayer.
*/
class HWCLayerVersion1 : public Iterable<HWCLayerVersion1, hwc_layer_1_t> {
+ struct hwc_composer_device_1* mHwc;
public:
- HWCLayerVersion1(hwc_layer_1_t* layer)
- : Iterable<HWCLayerVersion1, hwc_layer_1_t>(layer) { }
+ HWCLayerVersion1(struct hwc_composer_device_1* hwc, hwc_layer_1_t* layer)
+ : Iterable<HWCLayerVersion1, hwc_layer_1_t>(layer), mHwc(hwc) { }
virtual int32_t getCompositionType() const {
return getLayer()->compositionType;
@@ -785,10 +835,10 @@ public:
virtual uint32_t getHints() const {
return getLayer()->hints;
}
- virtual int getAndResetReleaseFenceFd() {
+ virtual sp<Fence> getAndResetReleaseFence() {
int fd = getLayer()->releaseFenceFd;
getLayer()->releaseFenceFd = -1;
- return fd;
+ return fd >= 0 ? new Fence(fd) : Fence::NO_FENCE;
}
virtual void setAcquireFenceFd(int fenceFd) {
getLayer()->acquireFenceFd = fenceFd;
@@ -796,17 +846,28 @@ public:
virtual void setPerFrameDefaultState() {
//getLayer()->compositionType = HWC_FRAMEBUFFER;
}
+ virtual void setPlaneAlpha(uint8_t alpha) {
+ if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_2)) {
+ getLayer()->planeAlpha = alpha;
+ } else {
+ if (alpha < 0xFF) {
+ getLayer()->flags |= HWC_SKIP_LAYER;
+ }
+ }
+ }
virtual void setDefaultState() {
- getLayer()->compositionType = HWC_FRAMEBUFFER;
- getLayer()->hints = 0;
- getLayer()->flags = HWC_SKIP_LAYER;
- getLayer()->handle = 0;
- getLayer()->transform = 0;
- getLayer()->blending = HWC_BLENDING_NONE;
- getLayer()->visibleRegionScreen.numRects = 0;
- getLayer()->visibleRegionScreen.rects = NULL;
- getLayer()->acquireFenceFd = -1;
- getLayer()->releaseFenceFd = -1;
+ hwc_layer_1_t* const l = getLayer();
+ l->compositionType = HWC_FRAMEBUFFER;
+ l->hints = 0;
+ l->flags = HWC_SKIP_LAYER;
+ l->handle = 0;
+ l->transform = 0;
+ l->blending = HWC_BLENDING_NONE;
+ l->visibleRegionScreen.numRects = 0;
+ l->visibleRegionScreen.rects = NULL;
+ l->acquireFenceFd = -1;
+ l->releaseFenceFd = -1;
+ l->planeAlpha = 0xFF;
}
virtual void setSkip(bool skip) {
if (skip) {
@@ -869,7 +930,7 @@ HWComposer::LayerListIterator HWComposer::getLayerIterator(int32_t id, size_t in
if (!mHwc || !disp.list || index > disp.list->numHwLayers) {
return LayerListIterator();
}
- return LayerListIterator(new HWCLayerVersion1(disp.list->hwLayers), index);
+ return LayerListIterator(new HWCLayerVersion1(mHwc, disp.list->hwLayers), index);
}
/*
@@ -907,17 +968,17 @@ void HWComposer::dump(String8& result, char* buffer, size_t SIZE) const {
result.appendFormat(" mDebugForceFakeVSync=%d\n", mDebugForceFakeVSync);
for (size_t i=0 ; i<mNumDisplays ; i++) {
const DisplayData& disp(mDisplayData[i]);
+ if (!disp.connected)
+ continue;
- const Vector< sp<LayerBase> >& visibleLayersSortedByZ =
+ const Vector< sp<Layer> >& visibleLayersSortedByZ =
mFlinger->getLayerSortedByZForHwcDisplay(i);
- if (disp.connected) {
- result.appendFormat(
- " Display[%d] : %ux%u, xdpi=%f, ydpi=%f, refresh=%lld\n",
- i, disp.width, disp.height, disp.xdpi, disp.ydpi, disp.refresh);
- }
+ result.appendFormat(
+ " Display[%d] : %ux%u, xdpi=%f, ydpi=%f, refresh=%lld\n",
+ i, disp.width, disp.height, disp.xdpi, disp.ydpi, disp.refresh);
- if (disp.list && disp.connected) {
+ if (disp.list) {
result.appendFormat(
" numHwLayers=%u, flags=%08x\n",
disp.list->numHwLayers, disp.list->flags);
@@ -932,13 +993,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();
}
@@ -1032,5 +1091,22 @@ bool HWComposer::VSyncThread::threadLoop() {
return true;
}
+HWComposer::DisplayData::DisplayData()
+: width(0), height(0), format(0),
+ xdpi(0.0f), ydpi(0.0f),
+ refresh(0),
+ connected(false),
+ hasFbComp(false), hasOvComp(false),
+ capacity(0), list(NULL),
+ framebufferTarget(NULL), fbTargetHandle(0),
+ lastRetireFence(Fence::NO_FENCE), lastDisplayFence(Fence::NO_FENCE),
+ outbufHandle(NULL), outbufAcquireFence(Fence::NO_FENCE),
+ events(0)
+{}
+
+HWComposer::DisplayData::~DisplayData() {
+ free(list);
+}
+
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 7c67407..604de38 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -22,13 +22,15 @@
#include <hardware/hwcomposer_defs.h>
+#include <ui/Fence.h>
+
+#include <utils/BitSet.h>
#include <utils/Condition.h>
#include <utils/Mutex.h>
#include <utils/StrongPointer.h>
#include <utils/Thread.h>
#include <utils/Timers.h>
#include <utils/Vector.h>
-#include <utils/BitSet.h>
extern "C" int clock_nanosleep(clockid_t clock_id, int flags,
const struct timespec *request,
@@ -45,7 +47,6 @@ namespace android {
class GraphicBuffer;
class Fence;
-class LayerBase;
class Region;
class String8;
class SurfaceFlinger;
@@ -111,9 +112,9 @@ public:
// does this display have layers handled by GLES
bool hasGlesComposition(int32_t id) const;
- // get the releaseFence file descriptor for the given display
+ // get the releaseFence file descriptor for a display's framebuffer layer.
// the release fence is only valid after commit()
- int getAndResetReleaseFenceFd(int32_t id);
+ sp<Fence> getAndResetReleaseFence(int32_t id);
// needed forward declarations
class LayerListIterator;
@@ -127,6 +128,17 @@ public:
int fbCompositionComplete();
void fbDump(String8& result);
+ // Set the output buffer and acquire fence for a virtual display.
+ // Returns INVALID_OPERATION if id is not a virtual display.
+ status_t setOutputBuffer(int32_t id, const sp<Fence>& acquireFence,
+ const sp<GraphicBuffer>& buf);
+
+ // Get the retire fence for the last committed frame. This fence will
+ // signal when the h/w composer is completely finished with the frame.
+ // For physical displays, it is no longer being displayed. For virtual
+ // displays, writes to the output buffer are complete.
+ sp<Fence> getLastRetireFence(int32_t id);
+
/*
* Interface to hardware composer's layers functionality.
* This abstracts the HAL interface to layers which can evolve in
@@ -140,8 +152,7 @@ public:
public:
virtual int32_t getCompositionType() const = 0;
virtual uint32_t getHints() const = 0;
- virtual int getAndResetReleaseFenceFd() = 0;
- virtual void setPerFrameDefaultState() = 0;
+ virtual sp<Fence> getAndResetReleaseFence() = 0;
virtual void setDefaultState() = 0;
virtual void setSkip(bool skip) = 0;
virtual void setBlending(uint32_t blending) = 0;
@@ -151,6 +162,7 @@ public:
virtual void setVisibleRegionScreen(const Region& reg) = 0;
virtual void setBuffer(const sp<GraphicBuffer>& buffer) = 0;
virtual void setAcquireFenceFd(int fenceFd) = 0;
+ virtual void setPlaneAlpha(uint8_t alpha) = 0;
virtual void onDisplayed() = 0;
};
@@ -233,6 +245,7 @@ public:
// HWC_DISPLAY_PRIMARY).
nsecs_t getRefreshPeriod(int disp) const;
nsecs_t getRefreshTimestamp(int disp) const;
+ sp<Fence> getDisplayFence(int disp) const;
uint32_t getWidth(int disp) const;
uint32_t getHeight(int disp) const;
uint32_t getFormat(int disp) const;
@@ -240,6 +253,9 @@ public:
float getDpiY(int disp) const;
bool isConnected(int disp) const;
+ status_t setVirtualDisplayProperties(int32_t id, uint32_t w, uint32_t h,
+ uint32_t format);
+
// this class is only used to fake the VSync event on systems that don't
// have it.
class VSyncThread : public Thread {
@@ -263,7 +279,7 @@ public:
private:
void loadHwcModule();
- void loadFbHalModule();
+ int loadFbHalModule();
LayerListIterator getLayerIterator(int32_t id, size_t index);
@@ -286,13 +302,8 @@ private:
struct DisplayData {
- DisplayData() : xdpi(0), ydpi(0), refresh(0),
- connected(false), hasFbComp(false), hasOvComp(false),
- capacity(0), list(NULL),
- framebufferTarget(NULL), fbTargetHandle(NULL), events(0) { }
- ~DisplayData() {
- free(list);
- }
+ DisplayData();
+ ~DisplayData();
uint32_t width;
uint32_t height;
uint32_t format; // pixel format from FB hal, for pre-hwc-1.1
@@ -306,6 +317,12 @@ private:
hwc_display_contents_1* list;
hwc_layer_1* framebufferTarget;
buffer_handle_t fbTargetHandle;
+ sp<Fence> lastRetireFence; // signals when the last set op retires
+ sp<Fence> lastDisplayFence; // signals when the last set op takes
+ // effect on screen
+ buffer_handle_t outbufHandle;
+ sp<Fence> outbufAcquireFence;
+
// protected by mEventControlLock
int32_t events;
};
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
new file mode 100644
index 0000000..2838b23
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2013 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 "VirtualDisplaySurface.h"
+
+#include <cutils/log.h>
+#include <gui/IGraphicBufferProducer.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int32_t dispId,
+ const sp<IGraphicBufferProducer>& sink, const String8& name)
+: mSink(sink)
+{
+ LOG_ALWAYS_FATAL_IF(dispId >= 0);
+}
+
+VirtualDisplaySurface::~VirtualDisplaySurface() {
+}
+
+sp<IGraphicBufferProducer> VirtualDisplaySurface::getIGraphicBufferProducer() const {
+ return mSink;
+}
+
+status_t VirtualDisplaySurface::compositionComplete() {
+ return NO_ERROR;
+}
+
+status_t VirtualDisplaySurface::advanceFrame() {
+ return NO_ERROR;
+}
+
+void VirtualDisplaySurface::onFrameCommitted() {
+}
+
+void VirtualDisplaySurface::dump(String8& result) const {
+}
+
+// ---------------------------------------------------------------------------
+} // namespace android
+// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
new file mode 100644
index 0000000..f321795
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2013 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_SF_VIRTUAL_DISPLAY_SURFACE_H
+#define ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H
+
+#include "DisplaySurface.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+class HWComposer;
+
+/* This DisplaySurface implementation is a stub used for developing HWC
+ * virtual display support. It is currently just a passthrough.
+ */
+class VirtualDisplaySurface : public DisplaySurface {
+public:
+ VirtualDisplaySurface(HWComposer& hwc, int32_t dispId,
+ const sp<IGraphicBufferProducer>& sink,
+ const String8& name);
+
+ virtual sp<IGraphicBufferProducer> getIGraphicBufferProducer() const;
+
+ virtual status_t compositionComplete();
+ virtual status_t advanceFrame();
+ virtual void onFrameCommitted();
+ virtual void dump(String8& result) const;
+
+private:
+ virtual ~VirtualDisplaySurface();
+
+ sp<IGraphicBufferProducer> mSink;
+};
+
+// ---------------------------------------------------------------------------
+} // namespace android
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H
+
diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp
index edb9fa5..4d0fc79 100644
--- a/services/surfaceflinger/EventThread.cpp
+++ b/services/surfaceflinger/EventThread.cpp
@@ -41,7 +41,7 @@ EventThread::EventThread(const sp<SurfaceFlinger>& flinger)
mUseSoftwareVSync(false),
mDebugVsyncEnabled(false) {
- for (int32_t i=0 ; i<HWC_DISPLAY_TYPES_SUPPORTED ; i++) {
+ for (int32_t i=0 ; i<HWC_NUM_DISPLAY_TYPES ; i++) {
mVSyncEvent[i].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
mVSyncEvent[i].header.id = 0;
mVSyncEvent[i].header.timestamp = 0;
@@ -112,11 +112,11 @@ void EventThread::onScreenAcquired() {
void EventThread::onVSyncReceived(int type, nsecs_t timestamp) {
- ALOGE_IF(type >= HWC_DISPLAY_TYPES_SUPPORTED,
- "received event for an invalid display (id=%d)", type);
+ ALOGE_IF(type >= HWC_NUM_DISPLAY_TYPES,
+ "received vsync event for an invalid display (id=%d)", type);
Mutex::Autolock _l(mLock);
- if (type < HWC_DISPLAY_TYPES_SUPPORTED) {
+ if (type < HWC_NUM_DISPLAY_TYPES) {
mVSyncEvent[type].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
mVSyncEvent[type].header.id = type;
mVSyncEvent[type].header.timestamp = timestamp;
@@ -126,11 +126,11 @@ void EventThread::onVSyncReceived(int type, nsecs_t timestamp) {
}
void EventThread::onHotplugReceived(int type, bool connected) {
- ALOGE_IF(type >= HWC_DISPLAY_TYPES_SUPPORTED,
- "received event for an invalid display (id=%d)", type);
+ ALOGE_IF(type >= HWC_NUM_DISPLAY_TYPES,
+ "received hotplug event for an invalid display (id=%d)", type);
Mutex::Autolock _l(mLock);
- if (type < HWC_DISPLAY_TYPES_SUPPORTED) {
+ if (type < HWC_NUM_DISPLAY_TYPES) {
DisplayEventReceiver::Event event;
event.header.type = DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG;
event.header.id = type;
@@ -184,7 +184,7 @@ Vector< sp<EventThread::Connection> > EventThread::waitForEvent(
size_t vsyncCount = 0;
nsecs_t timestamp = 0;
- for (int32_t i=0 ; i<HWC_DISPLAY_TYPES_SUPPORTED ; i++) {
+ for (int32_t i=0 ; i<HWC_NUM_DISPLAY_TYPES ; i++) {
timestamp = mVSyncEvent[i].header.timestamp;
if (timestamp) {
// we have a vsync event to dispatch
diff --git a/services/surfaceflinger/FrameTracker.cpp b/services/surfaceflinger/FrameTracker.cpp
new file mode 100644
index 0000000..9b55d44
--- /dev/null
+++ b/services/surfaceflinger/FrameTracker.cpp
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// This is needed for stdint.h to define INT64_MAX in C++
+#define __STDC_LIMIT_MACROS
+
+#include <ui/Fence.h>
+
+#include <utils/String8.h>
+
+#include "FrameTracker.h"
+
+namespace android {
+
+FrameTracker::FrameTracker() :
+ mOffset(0),
+ mNumFences(0) {
+}
+
+void FrameTracker::setDesiredPresentTime(nsecs_t presentTime) {
+ Mutex::Autolock lock(mMutex);
+ mFrameRecords[mOffset].desiredPresentTime = presentTime;
+}
+
+void FrameTracker::setFrameReadyTime(nsecs_t readyTime) {
+ Mutex::Autolock lock(mMutex);
+ mFrameRecords[mOffset].frameReadyTime = readyTime;
+}
+
+void FrameTracker::setFrameReadyFence(const sp<Fence>& readyFence) {
+ Mutex::Autolock lock(mMutex);
+ mFrameRecords[mOffset].frameReadyFence = readyFence;
+ mNumFences++;
+}
+
+void FrameTracker::setActualPresentTime(nsecs_t presentTime) {
+ Mutex::Autolock lock(mMutex);
+ mFrameRecords[mOffset].actualPresentTime = presentTime;
+}
+
+void FrameTracker::setActualPresentFence(const sp<Fence>& readyFence) {
+ Mutex::Autolock lock(mMutex);
+ mFrameRecords[mOffset].actualPresentFence = readyFence;
+ mNumFences++;
+}
+
+void FrameTracker::advanceFrame() {
+ Mutex::Autolock lock(mMutex);
+ mOffset = (mOffset+1) % NUM_FRAME_RECORDS;
+ mFrameRecords[mOffset].desiredPresentTime = INT64_MAX;
+ mFrameRecords[mOffset].frameReadyTime = INT64_MAX;
+ mFrameRecords[mOffset].actualPresentTime = INT64_MAX;
+
+ if (mFrameRecords[mOffset].frameReadyFence != NULL) {
+ // We're clobbering an unsignaled fence, so we need to decrement the
+ // fence count.
+ mFrameRecords[mOffset].frameReadyFence = NULL;
+ mNumFences--;
+ }
+
+ if (mFrameRecords[mOffset].actualPresentFence != NULL) {
+ // We're clobbering an unsignaled fence, so we need to decrement the
+ // fence count.
+ mFrameRecords[mOffset].actualPresentFence = NULL;
+ mNumFences--;
+ }
+
+ // Clean up the signaled fences to keep the number of open fence FDs in
+ // this process reasonable.
+ processFencesLocked();
+}
+
+void FrameTracker::clear() {
+ Mutex::Autolock lock(mMutex);
+ for (size_t i = 0; i < NUM_FRAME_RECORDS; i++) {
+ mFrameRecords[i].desiredPresentTime = 0;
+ mFrameRecords[i].frameReadyTime = 0;
+ mFrameRecords[i].actualPresentTime = 0;
+ mFrameRecords[i].frameReadyFence.clear();
+ mFrameRecords[i].actualPresentFence.clear();
+ }
+ mNumFences = 0;
+ mFrameRecords[mOffset].desiredPresentTime = INT64_MAX;
+ mFrameRecords[mOffset].frameReadyTime = INT64_MAX;
+ mFrameRecords[mOffset].actualPresentTime = INT64_MAX;
+}
+
+void FrameTracker::processFencesLocked() const {
+ FrameRecord* records = const_cast<FrameRecord*>(mFrameRecords);
+ int& numFences = const_cast<int&>(mNumFences);
+
+ for (int i = 1; i < NUM_FRAME_RECORDS && numFences > 0; i++) {
+ size_t idx = (mOffset+NUM_FRAME_RECORDS-i) % NUM_FRAME_RECORDS;
+
+ const sp<Fence>& rfence = records[idx].frameReadyFence;
+ if (rfence != NULL) {
+ records[idx].frameReadyTime = rfence->getSignalTime();
+ if (records[idx].frameReadyTime < INT64_MAX) {
+ records[idx].frameReadyFence = NULL;
+ numFences--;
+ }
+ }
+
+ const sp<Fence>& pfence = records[idx].actualPresentFence;
+ if (pfence != NULL) {
+ records[idx].actualPresentTime = pfence->getSignalTime();
+ if (records[idx].actualPresentTime < INT64_MAX) {
+ records[idx].actualPresentFence = NULL;
+ numFences--;
+ }
+ }
+ }
+}
+
+void FrameTracker::dump(String8& result) const {
+ Mutex::Autolock lock(mMutex);
+ processFencesLocked();
+
+ const size_t o = mOffset;
+ for (size_t i = 1; i < NUM_FRAME_RECORDS; i++) {
+ const size_t index = (o+i) % NUM_FRAME_RECORDS;
+ result.appendFormat("%lld\t%lld\t%lld\n",
+ mFrameRecords[index].desiredPresentTime,
+ mFrameRecords[index].actualPresentTime,
+ mFrameRecords[index].frameReadyTime);
+ }
+ result.append("\n");
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/FrameTracker.h b/services/surfaceflinger/FrameTracker.h
new file mode 100644
index 0000000..3d122c4
--- /dev/null
+++ b/services/surfaceflinger/FrameTracker.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_FRAMETRACKER_H
+#define ANDROID_FRAMETRACKER_H
+
+#include <stddef.h>
+
+#include <utils/Mutex.h>
+#include <utils/Timers.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+class String8;
+class Fence;
+
+// FrameTracker tracks information about the most recently rendered frames. It
+// uses a circular buffer of frame records, and is *NOT* thread-safe -
+// mutexing must be done at a higher level if multi-threaded access is
+// possible.
+//
+// Some of the time values tracked may be set either as a specific timestamp
+// or a fence. When a non-NULL fence is set for a given time value, the
+// signal time of that fence is used instead of the timestamp.
+class FrameTracker {
+
+public:
+ // NUM_FRAME_RECORDS is the size of the circular buffer used to track the
+ // frame time history.
+ enum { NUM_FRAME_RECORDS = 128 };
+
+ FrameTracker();
+
+ // setDesiredPresentTime sets the time at which the current frame
+ // should be presented to the user under ideal (i.e. zero latency)
+ // conditions.
+ void setDesiredPresentTime(nsecs_t desiredPresentTime);
+
+ // setFrameReadyTime sets the time at which the current frame became ready
+ // to be presented to the user. For example, if the frame contents is
+ // being written to memory by some asynchronous hardware, this would be
+ // the time at which those writes completed.
+ void setFrameReadyTime(nsecs_t readyTime);
+
+ // setFrameReadyFence sets the fence that is used to get the time at which
+ // the current frame became ready to be presented to the user.
+ void setFrameReadyFence(const sp<Fence>& readyFence);
+
+ // setActualPresentTime sets the timestamp at which the current frame became
+ // visible to the user.
+ void setActualPresentTime(nsecs_t displayTime);
+
+ // setActualPresentFence sets the fence that is used to get the time
+ // at which the current frame became visible to the user.
+ void setActualPresentFence(const sp<Fence>& fence);
+
+ // advanceFrame advances the frame tracker to the next frame.
+ void advanceFrame();
+
+ // clear resets all the tracked frame data to zero.
+ void clear();
+
+ // dump appends the current frame display time history to the result string.
+ void dump(String8& result) const;
+
+private:
+ struct FrameRecord {
+ FrameRecord() :
+ desiredPresentTime(0),
+ frameReadyTime(0),
+ actualPresentTime(0) {}
+ nsecs_t desiredPresentTime;
+ nsecs_t frameReadyTime;
+ nsecs_t actualPresentTime;
+ sp<Fence> frameReadyFence;
+ sp<Fence> actualPresentFence;
+ };
+
+ // processFences iterates over all the frame records that have a fence set
+ // and replaces that fence with a timestamp if the fence has signaled. If
+ // the fence is not signaled the record's displayTime is set to INT64_MAX.
+ //
+ // This method is const because although it modifies the frame records it
+ // does so in such a way that the information represented should not
+ // change. This allows it to be called from the dump method.
+ void processFencesLocked() const;
+
+ // mFrameRecords is the circular buffer storing the tracked data for each
+ // frame.
+ FrameRecord mFrameRecords[NUM_FRAME_RECORDS];
+
+ // mOffset is the offset into mFrameRecords of the current frame.
+ size_t mOffset;
+
+ // mNumFences is the total number of fences set in the frame records. It
+ // is incremented each time a fence is added and decremented each time a
+ // signaled fence is removed in processFences or if advanceFrame clobbers
+ // a fence.
+ //
+ // The number of fences is tracked so that the run time of processFences
+ // doesn't grow with NUM_FRAME_RECORDS.
+ int mNumFences;
+
+ // mMutex is used to protect access to all member variables.
+ mutable Mutex mMutex;
+};
+
+}
+
+#endif // ANDROID_FRAMETRACKER_H
diff --git a/services/surfaceflinger/GLExtensions.cpp b/services/surfaceflinger/GLExtensions.cpp
index 493122d..e5fb083 100644
--- a/services/surfaceflinger/GLExtensions.cpp
+++ b/services/surfaceflinger/GLExtensions.cpp
@@ -28,7 +28,8 @@ ANDROID_SINGLETON_STATIC_INSTANCE( GLExtensions )
GLExtensions::GLExtensions()
: mHaveTextureExternal(false),
mHaveNpot(false),
- mHaveDirectTexture(false)
+ mHaveDirectTexture(false),
+ mHaveFramebufferObject(false)
{
}
@@ -79,7 +80,7 @@ void GLExtensions::initWithGLStrings(
mHaveDirectTexture = true;
}
#else
-#warning "EGL_ANDROID_image_native_buffer not supported"
+#error "EGL_ANDROID_image_native_buffer not supported"
#endif
if (hasExtension("GL_ARB_texture_non_power_of_two")) {
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 7edbdc5..4779804 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -50,116 +50,122 @@ namespace android {
// ---------------------------------------------------------------------------
-Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client)
- : LayerBaseClient(flinger, client),
+int32_t Layer::sSequence = 1;
+
+Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client,
+ const String8& name, uint32_t w, uint32_t h, uint32_t flags)
+ : 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),
- mFrameLatencyOffset(0),
- 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) {
- mSurfaceTexture->setReleaseFence(layer->getAndResetReleaseFenceFd());
- }
+ uint32_t layerFlags = 0;
+ if (flags & ISurfaceComposerClient::eHidden)
+ layerFlags = layer_state_t::eLayerHidden;
+
+ if (flags & ISurfaceComposerClient::eNonPremultiplied)
+ mPremultipliedAlpha = false;
+
+ mName = name;
+
+ 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;
}
void Layer::onFirstRef()
{
- LayerBaseClient::onFirstRef();
-
- struct FrameQueuedListener : public SurfaceTexture::FrameAvailableListener {
- FrameQueuedListener(Layer* layer) : mLayer(layer) { }
- private:
- wp<Layer> mLayer;
- virtual void onFrameAvailable() {
- sp<Layer> that(mLayer.promote());
- if (that != 0) {
- that->onFrameQueued();
- }
- }
- };
-
- // Creates a custom BufferQueue for SurfaceTexture to use
- sp<BufferQueue> bq = new SurfaceTextureLayer();
- mSurfaceTexture = new SurfaceTexture(mTextureName, true,
+ // Creates a custom BufferQueue for SurfaceFlingerConsumer to use
+ sp<BufferQueue> bq = new SurfaceTextureLayer(mFlinger);
+ mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(mTextureName, true,
GL_TEXTURE_EXTERNAL_OES, false, bq);
- mSurfaceTexture->setConsumerUsageBits(getEffectiveUsage(0));
- mSurfaceTexture->setFrameAvailableListener(new FrameQueuedListener(this));
- mSurfaceTexture->setSynchronousMode(true);
+ mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
+ mSurfaceFlingerConsumer->setFrameAvailableListener(this);
+ mSurfaceFlingerConsumer->setSynchronousMode(true);
+ mSurfaceFlingerConsumer->setName(mName);
#ifdef TARGET_DISABLE_TRIPLE_BUFFERING
#warning "disabling triple buffering"
- mSurfaceTexture->setDefaultMaxBufferCount(2);
+ mSurfaceFlingerConsumer->setDefaultMaxBufferCount(2);
#else
- mSurfaceTexture->setDefaultMaxBufferCount(3);
+ mSurfaceFlingerConsumer->setDefaultMaxBufferCount(3);
#endif
const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
updateTransformHint(hw);
}
-Layer::~Layer()
-{
+Layer::~Layer() {
+ sp<Client> c(mClientRef.promote());
+ if (c != 0) {
+ c->detachLayer(this);
+ }
mFlinger->deleteTextureAsync(mTextureName);
}
-void Layer::onFrameQueued() {
- android_atomic_inc(&mQueuedFrames);
- mFlinger->signalLayerUpdate();
-}
+// ---------------------------------------------------------------------------
+// callbacks
+// ---------------------------------------------------------------------------
-// called with SurfaceFlinger::mStateLock as soon as the layer is entered
-// in the purgatory list
-void Layer::onRemoved()
-{
- mSurfaceTexture->abandon();
+void Layer::onLayerDisplayed(const sp<const DisplayDevice>& hw,
+ HWComposer::HWCLayerInterface* layer) {
+ if (layer) {
+ layer->onDisplayed();
+ mSurfaceFlingerConsumer->setReleaseFence(layer->getAndResetReleaseFence());
+ }
}
-void Layer::setName(const String8& name) {
- LayerBase::setName(name);
- mSurfaceTexture->setName(name);
+void Layer::onFrameAvailable() {
+ android_atomic_inc(&mQueuedFrames);
+ mFlinger->signalLayerUpdate();
}
-sp<ISurface> Layer::createSurface()
-{
- class BSurface : public BnSurface, public LayerCleaner {
- wp<const Layer> mOwner;
- virtual sp<ISurfaceTexture> getSurfaceTexture() const {
- sp<ISurfaceTexture> res;
- sp<const Layer> that( mOwner.promote() );
- if (that != NULL) {
- res = that->mSurfaceTexture->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;
+// called with SurfaceFlinger::mStateLock from the drawing thread after
+// the layer has been remove from the current state list (and just before
+// it's removed from the drawing state list)
+void Layer::onRemoved() {
+ mSurfaceFlingerConsumer->abandon();
}
-wp<IBinder> Layer::getSurfaceTextureBinder() const
-{
- return mSurfaceTexture->getBufferQueue()->asBinder();
+// ---------------------------------------------------------------------------
+// set-up
+// ---------------------------------------------------------------------------
+
+String8 Layer::getName() const {
+ return mName;
}
status_t Layer::setBuffers( uint32_t w, uint32_t h,
@@ -190,33 +196,124 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h,
mOpaqueLayer = (flags & ISurfaceComposerClient::eOpaque);
mCurrentOpacity = getOpacityForFormat(format);
- mSurfaceTexture->setDefaultBufferSize(w, h);
- mSurfaceTexture->setDefaultBufferFormat(format);
- mSurfaceTexture->setConsumerUsageBits(getEffectiveUsage(0));
+ mSurfaceFlingerConsumer->setDefaultBufferSize(w, h);
+ mSurfaceFlingerConsumer->setDefaultBufferFormat(format);
+ mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
return NO_ERROR;
}
-Rect Layer::computeBufferCrop() const {
- // Start with the SurfaceTexture's buffer crop...
+sp<IBinder> Layer::getHandle() {
+ Mutex::Autolock _l(mLock);
+
+ LOG_ALWAYS_FATAL_IF(mHasSurface,
+ "Layer::getHandle() has already been called");
+
+ mHasSurface = true;
+
+ /*
+ * The layer handle is just a BBinder object passed to the client
+ * (remote process) -- we don't keep any reference on our side such that
+ * the dtor is called when the remote side let go of its reference.
+ *
+ * LayerCleaner ensures that mFlinger->onLayerDestroyed() is called for
+ * this layer when the handle is destroyed.
+ */
+
+ class Handle : public BBinder, public LayerCleaner {
+ wp<const Layer> mOwner;
+ public:
+ Handle(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer)
+ : LayerCleaner(flinger, layer), mOwner(layer) {
+ }
+ };
+
+ return new Handle(mFlinger, this);
+}
+
+sp<BufferQueue> Layer::getBufferQueue() const {
+ return mSurfaceFlingerConsumer->getBufferQueue();
+}
+
+//virtual sp<IGraphicBufferProducer> getSurfaceTexture() const {
+// sp<IGraphicBufferProducer> res;
+// sp<const Layer> that( mOwner.promote() );
+// if (that != NULL) {
+// res = that->mSurfaceFlingerConsumer->getBufferQueue();
+// }
+// return res;
+//}
+
+// ---------------------------------------------------------------------------
+// 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)
Rect crop;
if (!mCurrentCrop.isEmpty()) {
+ // if the buffer crop is defined, we use that
crop = mCurrentCrop;
- } else if (mActiveBuffer != NULL){
- crop = Rect(mActiveBuffer->getWidth(), mActiveBuffer->getHeight());
+ } else if (mActiveBuffer != NULL) {
+ // otherwise we use the whole buffer
+ crop = mActiveBuffer->getBounds();
} else {
+ // if we don't have a buffer yet, we use an empty/invalid crop
crop.makeInvalid();
- return crop;
}
+ return crop;
+}
- // ... then reduce that in the same proportions as the window crop reduces
- // the window size.
- const State& s(drawingState());
+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
- // SurfaceTexture.
- uint32_t invTransform = mCurrentTransform;
+ // SurfaceFlingerConsumer.
+ uint32_t invTransform = getContentTransform();
int winWidth = s.active.w;
int winHeight = s.active.h;
if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
@@ -225,17 +322,24 @@ Rect Layer::computeBufferCrop() const {
winWidth = s.active.h;
winHeight = s.active.w;
}
- Rect winCrop = s.active.crop.transform(invTransform,
- s.active.w, s.active.h);
+ 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);
- crop.left += int(ceilf(float(winCrop.left) * xScale));
- crop.top += int(ceilf(float(winCrop.top) * yScale));
- crop.right -= int(ceilf(float(winWidth - winCrop.right) * xScale));
- crop.bottom -= int(ceilf(float(winHeight - winCrop.bottom) * yScale));
- }
+ 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;
}
@@ -243,21 +347,32 @@ void Layer::setGeometry(
const sp<const DisplayDevice>& hw,
HWComposer::HWCLayerInterface& layer)
{
- LayerBaseClient::setGeometry(hw, layer);
+ layer.setDefaultState();
// enable this layer
layer.setSkip(false);
- // we can't do alpha-fade with the hwc HAL
- const State& s(drawingState());
- if (s.alpha < 0xFF) {
+ if (isSecure() && !hw->isSecure()) {
layer.setSkip(true);
}
- if (isSecure() && !hw->isSecure()) {
- 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);
+
/*
* Transformations are applied in this order:
* 1) buffer orientation/flip/mirror
@@ -267,23 +382,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);
}
- layer.setCrop(computeBufferCrop());
}
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);
@@ -297,8 +418,8 @@ void Layer::setAcquireFence(const sp<const DisplayDevice>& hw,
// 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()) {
+ sp<Fence> fence = mSurfaceFlingerConsumer->getCurrentFence();
+ if (fence->isValid()) {
fenceFd = fence->dup();
if (fenceFd == -1) {
ALOGW("failed to dup layer fence, skipping sync: %d", errno);
@@ -308,6 +429,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();
@@ -327,8 +460,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) );
}
@@ -340,9 +473,11 @@ void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const
return;
}
- status_t err = mSurfaceTexture->doGLFenceWait();
- if (err != OK) {
- ALOGE("onDraw: failed waiting for fence: %d", err);
+ // Bind the current buffer to the GL texture, and wait for it to be
+ // ready for us to draw into.
+ status_t err = mSurfaceFlingerConsumer->bindTextureImage();
+ if (err != NO_ERROR) {
+ ALOGW("onDraw: bindTextureImage failed (err=%d)", err);
// Go ahead and draw the buffer anyway; no matter what we do the screen
// is probably going to have something visibly wrong.
}
@@ -355,8 +490,8 @@ void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const
// Query the texture matrix given our current filtering mode.
float textureMatrix[16];
- mSurfaceTexture->setFilteringEnabled(useFiltering);
- mSurfaceTexture->getTransformMatrix(textureMatrix);
+ mSurfaceFlingerConsumer->setFilteringEnabled(useFiltering);
+ mSurfaceFlingerConsumer->getTransformMatrix(textureMatrix);
// Set things up for texturing.
glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureName);
@@ -386,6 +521,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
@@ -404,6 +652,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
{
@@ -425,8 +696,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());
@@ -475,7 +777,7 @@ uint32_t Layer::doTransaction(uint32_t flags)
// record the new size, form this point on, when the client request
// a buffer, it'll get the new size.
- mSurfaceTexture->setDefaultBufferSize(
+ mSurfaceFlingerConsumer->setDefaultBufferSize(
temp.requested.w, temp.requested.h);
}
@@ -485,7 +787,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.
@@ -498,15 +800,116 @@ 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.requestedTransparentRegion = 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;
}
// ----------------------------------------------------------------------------
@@ -520,18 +923,38 @@ bool Layer::onPreComposition() {
void Layer::onPostComposition() {
if (mFrameLatencyNeeded) {
+ nsecs_t desiredPresentTime = mSurfaceFlingerConsumer->getTimestamp();
+ mFrameTracker.setDesiredPresentTime(desiredPresentTime);
+
+ sp<Fence> frameReadyFence = mSurfaceFlingerConsumer->getCurrentFence();
+ if (frameReadyFence->isValid()) {
+ mFrameTracker.setFrameReadyFence(frameReadyFence);
+ } else {
+ // There was no fence for this frame, so assume that it was ready
+ // to be presented at the desired present time.
+ mFrameTracker.setFrameReadyTime(desiredPresentTime);
+ }
+
const HWComposer& hwc = mFlinger->getHwComposer();
- const size_t offset = mFrameLatencyOffset;
- mFrameStats[offset].timestamp = mSurfaceTexture->getTimestamp();
- mFrameStats[offset].set = systemTime();
- mFrameStats[offset].vsync = hwc.getRefreshTimestamp(HWC_DISPLAY_PRIMARY);
- mFrameLatencyOffset = (mFrameLatencyOffset + 1) % 128;
+ sp<Fence> presentFence = hwc.getDisplayFence(HWC_DISPLAY_PRIMARY);
+ if (presentFence->isValid()) {
+ mFrameTracker.setActualPresentFence(presentFence);
+ } else {
+ // The HWC doesn't support present fences, so use the refresh
+ // timestamp instead.
+ nsecs_t presentTime = hwc.getRefreshTimestamp(HWC_DISPLAY_PRIMARY);
+ mFrameTracker.setActualPresentTime(presentTime);
+ }
+
+ mFrameTracker.advanceFrame();
mFrameLatencyNeeded = false;
}
}
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)
@@ -559,7 +982,7 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions)
mFlinger->signalLayerUpdate();
}
- struct Reject : public SurfaceTexture::BufferRejecter {
+ struct Reject : public SurfaceFlingerConsumer::BufferRejecter {
Layer::State& front;
Layer::State& current;
bool& recomputeVisibleRegions;
@@ -584,7 +1007,6 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions)
swap(bufWidth, bufHeight);
}
-
bool isFixedSize = item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
if (front.active != front.requested) {
@@ -637,6 +1059,27 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions)
return true;
}
}
+
+ // if the transparent region has changed (this test is
+ // conservative, but that's fine, worst case we're doing
+ // a bit of extra work), we latch the new one and we
+ // trigger a visible-region recompute.
+ if (!front.activeTransparentRegion.isTriviallyEqual(
+ front.requestedTransparentRegion)) {
+ front.activeTransparentRegion = front.requestedTransparentRegion;
+
+ // We also need to update the current state so that
+ // we don't end-up overwriting the drawing state with
+ // this stale current state during the next transaction
+ //
+ // NOTE: We don't need to hold the transaction lock here
+ // because State::active is only accessed from this thread.
+ current.activeTransparentRegion = front.activeTransparentRegion;
+
+ // recompute visible region
+ recomputeVisibleRegions = true;
+ }
+
return false;
}
};
@@ -644,14 +1087,14 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions)
Reject r(mDrawingState, currentState(), recomputeVisibleRegions);
- if (mSurfaceTexture->updateTexImage(&r, true) < NO_ERROR) {
+ if (mSurfaceFlingerConsumer->updateTexImage(&r) != NO_ERROR) {
// something happened!
recomputeVisibleRegions = true;
return outDirtyRegion;
}
// update the active buffer
- mActiveBuffer = mSurfaceTexture->getCurrentBuffer();
+ mActiveBuffer = mSurfaceFlingerConsumer->getCurrentBuffer();
if (mActiveBuffer == NULL) {
// this can only happen if the very first buffer was rejected.
return outDirtyRegion;
@@ -665,9 +1108,9 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions)
recomputeVisibleRegions = true;
}
- Rect crop(mSurfaceTexture->getCurrentCrop());
- const uint32_t transform(mSurfaceTexture->getCurrentTransform());
- const uint32_t scalingMode(mSurfaceTexture->getCurrentScalingMode());
+ Rect crop(mSurfaceFlingerConsumer->getCurrentCrop());
+ const uint32_t transform(mSurfaceFlingerConsumer->getCurrentTransform());
+ const uint32_t scalingMode(mSurfaceFlingerConsumer->getCurrentScalingMode());
if ((crop != mCurrentCrop) ||
(transform != mCurrentTransform) ||
(scalingMode != mCurrentScalingMode))
@@ -705,9 +1148,64 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions)
return outDirtyRegion;
}
+uint32_t Layer::getEffectiveUsage(uint32_t usage) const
+{
+ // TODO: should we do something special if mSecure is set?
+ if (mProtectedByApp) {
+ // need a hardware-protected path to external video sink
+ usage |= GraphicBuffer::USAGE_PROTECTED;
+ }
+ usage |= GraphicBuffer::USAGE_HW_COMPOSER;
+ return usage;
+}
+
+void Layer::updateTransformHint(const sp<const DisplayDevice>& hw) const {
+ uint32_t orientation = 0;
+ if (!mFlinger->mDebugDisableTransformHint) {
+ // The transform hint is used to improve performance, but we can
+ // only have a single transform hint, it cannot
+ // apply to all displays.
+ const Transform& planeTransform(hw->getTransform());
+ orientation = planeTransform.getOrientation();
+ if (orientation & Transform::ROT_INVALID) {
+ orientation = 0;
+ }
+ }
+ mSurfaceFlingerConsumer->setTransformHint(orientation);
+}
+
+// ----------------------------------------------------------------------------
+// debugging
+// ----------------------------------------------------------------------------
+
void Layer::dump(String8& result, char* buffer, size_t SIZE) const
{
- LayerBaseClient::dump(result, buffer, SIZE);
+ const Layer::State& s(drawingState());
+
+ snprintf(buffer, SIZE,
+ "+ %s %p (%s)\n",
+ getTypeId(), this, getName().string());
+ result.append(buffer);
+
+ s.activeTransparentRegion.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;
@@ -726,61 +1224,34 @@ void Layer::dump(String8& result, char* buffer, size_t SIZE) const
result.append(buffer);
- if (mSurfaceTexture != 0) {
- mSurfaceTexture->dump(result, " ", buffer, SIZE);
+ if (mSurfaceFlingerConsumer != 0) {
+ mSurfaceFlingerConsumer->dump(result, " ", buffer, SIZE);
}
}
-void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const
-{
- LayerBaseClient::dumpStats(result, buffer, SIZE);
- const size_t o = mFrameLatencyOffset;
- const nsecs_t period =
- mFlinger->getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
- result.appendFormat("%lld\n", period);
- for (size_t i=0 ; i<128 ; i++) {
- const size_t index = (o+i) % 128;
- const nsecs_t time_app = mFrameStats[index].timestamp;
- const nsecs_t time_set = mFrameStats[index].set;
- const nsecs_t time_vsync = mFrameStats[index].vsync;
- result.appendFormat("%lld\t%lld\t%lld\n",
- time_app,
- time_vsync,
- time_set);
- }
- result.append("\n");
+
+void Layer::shortDump(String8& result, char* scratch, size_t size) const {
+ Layer::dump(result, scratch, size);
}
-void Layer::clearStats()
-{
- LayerBaseClient::clearStats();
- memset(mFrameStats, 0, sizeof(mFrameStats));
+void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const {
+ mFrameTracker.dump(result);
}
-uint32_t Layer::getEffectiveUsage(uint32_t usage) const
-{
- // TODO: should we do something special if mSecure is set?
- if (mProtectedByApp) {
- // need a hardware-protected path to external video sink
- usage |= GraphicBuffer::USAGE_PROTECTED;
- }
- usage |= GraphicBuffer::USAGE_HW_COMPOSER;
- return usage;
+void Layer::clearStats() {
+ mFrameTracker.clear();
}
-void Layer::updateTransformHint(const sp<const DisplayDevice>& hw) const {
- uint32_t orientation = 0;
- if (!mFlinger->mDebugDisableTransformHint) {
- // The transform hint is used to improve performance, but we can
- // only have a single transform hint, it cannot
- // apply to all displays.
- const Transform& planeTransform(hw->getTransform());
- orientation = planeTransform.getOrientation();
- if (orientation & Transform::ROT_INVALID) {
- orientation = 0;
- }
- }
- mSurfaceTexture->setTransformHint(orientation);
+// ---------------------------------------------------------------------------
+
+Layer::LayerCleaner::LayerCleaner(const sp<SurfaceFlinger>& flinger,
+ const sp<Layer>& layer)
+ : mFlinger(flinger), mLayer(layer) {
+}
+
+Layer::LayerCleaner::~LayerCleaner() {
+ // destroy client resources
+ mFlinger->onLayerDestroyed(mLayer);
}
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index c5eb26b..2765db1 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -20,103 +20,351 @@
#include <stdint.h>
#include <sys/types.h>
-#include <gui/SurfaceTexture.h>
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES/gl.h>
+#include <GLES/glext.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 <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GLES/gl.h>
-#include <GLES/glext.h>
+#include <private/gui/LayerState.h>
-#include "LayerBase.h"
+#include "FrameTracker.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;
// ---------------------------------------------------------------------------
-class Layer : public LayerBaseClient
-{
+/*
+ * 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 SurfaceFlingerConsumer::FrameAvailableListener {
+ static int32_t sSequence;
+
public:
- Layer(SurfaceFlinger* flinger, const sp<Client>& client);
- virtual ~Layer();
+ 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,
+ };
- virtual const char* getTypeId() const { return "Layer"; }
+ 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;
+ // the transparentRegion hint is a bit special, it's latched only
+ // when we receive a buffer -- this is because it's "content"
+ // dependent.
+ Region activeTransparentRegion;
+ Region requestedTransparentRegion;
+ };
+
+ 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,
+ const String8& name, uint32_t w, uint32_t h, uint32_t flags);
+ virtual ~Layer();
// the this layer's size and format
- status_t setBuffers(uint32_t w, uint32_t h,
- PixelFormat format, uint32_t flags=0);
+ status_t setBuffers(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags);
+
+ // 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);
- bool isFixedSize() const;
+ void computeGeometry(const sp<const DisplayDevice>& hw, LayerMesh* mesh) const;
+ Rect computeBounds() const;
+
+ sp<IBinder> getHandle();
+ sp<BufferQueue> getBufferQueue() const;
+ String8 getName() const;
+
+ // -----------------------------------------------------------------------
+
+ virtual const char* getTypeId() const { return "Layer"; }
- // 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;
+
+ /*
+ * called with the state lock when the surface is removed from the
+ * current list
+ */
+ virtual void onRemoved();
- // only for debugging
- inline const sp<GraphicBuffer>& getActiveBuffer() const { return mActiveBuffer; }
- // Updates the transform hint in our SurfaceTexture to match
+ // 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;
-protected:
- virtual void onFirstRef();
+ /*
+ * 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;
+
+ // -----------------------------------------------------------------------
+
+ 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();
+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:
- friend class SurfaceTextureLayer;
- void onFrameQueued();
- 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;
- Rect computeBufferCrop() const;
static bool getOpacityForFormat(uint32_t format);
+ // 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<SurfaceTexture> mSurfaceTexture;
+ 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;
+ FrameTracker mFrameTracker;
// main thread
sp<GraphicBuffer> mActiveBuffer;
@@ -126,26 +374,20 @@ private:
bool mCurrentOpacity;
bool mRefreshPending;
bool mFrameLatencyNeeded;
- int mFrameLatencyOffset;
-
- struct Statistics {
- Statistics() : timestamp(0), set(0), vsync(0) { }
- nsecs_t timestamp; // buffer timestamp
- nsecs_t set; // buffer displayed timestamp
- nsecs_t vsync; // vsync immediately before set
- };
-
- // protected by mLock
- Statistics mFrameStats[128];
-
- // 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 once we've returned this surface's handle
+ mutable bool mHasSurface;
+ const wp<Client> mClientRef;
};
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
deleted file mode 100644
index 9b03c74..0000000
--- a/services/surfaceflinger/LayerBase.cpp
+++ /dev/null
@@ -1,573 +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 <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 s.transform.transform(win);
-}
-
-Region LayerBase::latchBuffer(bool& recomputeVisibleRegions) {
- Region result;
- return result;
-}
-
-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()) {
- layer.setBlending(mPremultipliedAlpha ?
- HWC_BLENDING_PREMULT :
- HWC_BLENDING_COVERAGE);
- }
-
- 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());
-}
-
-void LayerBase::setPerFrameData(const sp<const DisplayDevice>& hw,
- HWComposer::HWCLayerInterface& layer) {
- layer.setPerFrameDefaultState();
- // 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.
- const Transform& tr = hw->getTransform();
- layer.setVisibleRegionScreen(tr.transform(visibleRegion));
-}
-
-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;
- };
-
- Rect win(s.active.w, s.active.h);
- if (!s.active.crop.isEmpty()) {
- win.intersect(s.active.crop, &win);
- }
-
- 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;
-}
-
-// ---------------------------------------------------------------------------
-
-int32_t LayerBaseClient::sIdentity = 1;
-
-LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger,
- const sp<Client>& client)
- : LayerBase(flinger),
- mHasSurface(false),
- mClientRef(client),
- mIdentity(uint32_t(android_atomic_inc(&sIdentity)))
-{
-}
-
-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<ISurfaceTexture> 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, identity=%u\n",
- client.get(), getIdentity());
-
- 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
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
deleted file mode 100644
index 4d5a5b0..0000000
--- a/services/surfaceflinger/LayerBase.h
+++ /dev/null
@@ -1,359 +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;
-
-// ---------------------------------------------------------------------------
-
-class LayerBase : 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 SurfaceTexture's transform hint, for layers that have
- * a SurfaceTexture.
- */
- virtual void updateTransformHint(const sp<const DisplayDevice>& hw) 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;
-
-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);
-};
-
-
-// ---------------------------------------------------------------------------
-
-class LayerBaseClient : public LayerBase
-{
-public:
- LayerBaseClient(SurfaceFlinger* flinger, const sp<Client>& client);
-
- virtual ~LayerBaseClient();
-
- sp<ISurface> getSurface();
- 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"; }
-
- uint32_t getIdentity() const { return mIdentity; }
-
-protected:
- virtual void dump(String8& result, char* scratch, size_t size) const;
- virtual void shortDump(String8& result, char* scratch, size_t size) const;
-
- 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;
- mutable bool mHasSurface;
- wp<IBinder> mClientSurfaceBinder;
- const wp<Client> mClientRef;
- // only read
- const uint32_t mIdentity;
- static int32_t sIdentity;
-};
-
-// ---------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_LAYER_BASE_H
diff --git a/services/surfaceflinger/LayerDim.cpp b/services/surfaceflinger/LayerDim.cpp
index 25caa0a..36bafdb 100644
--- a/services/surfaceflinger/LayerDim.cpp
+++ b/services/surfaceflinger/LayerDim.cpp
@@ -33,13 +33,12 @@
namespace android {
// ---------------------------------------------------------------------------
-LayerDim::LayerDim(SurfaceFlinger* flinger, const sp<Client>& client)
- : LayerBaseClient(flinger, client)
-{
+LayerDim::LayerDim(SurfaceFlinger* flinger, const sp<Client>& client,
+ const String8& name, uint32_t w, uint32_t h, uint32_t flags)
+ : Layer(flinger, client, name, w, h, flags) {
}
-LayerDim::~LayerDim()
-{
+LayerDim::~LayerDim() {
}
void LayerDim::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const
@@ -71,6 +70,12 @@ void LayerDim::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) con
}
}
+bool LayerDim::isVisible() const {
+ const Layer::State& s(drawingState());
+ return !(s.flags & layer_state_t::eLayerHidden) && s.alpha;
+}
+
+
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/surfaceflinger/LayerDim.h b/services/surfaceflinger/LayerDim.h
index 06f312d..e19bf52 100644
--- a/services/surfaceflinger/LayerDim.h
+++ b/services/surfaceflinger/LayerDim.h
@@ -23,16 +23,17 @@
#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);
+ LayerDim(SurfaceFlinger* flinger, const sp<Client>& client,
+ const String8& name, uint32_t w, uint32_t h, uint32_t flags);
virtual ~LayerDim();
virtual void onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const;
@@ -41,6 +42,9 @@ 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;
};
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/LayerScreenshot.cpp b/services/surfaceflinger/LayerScreenshot.cpp
deleted file mode 100644
index f8009b3..0000000
--- a/services/surfaceflinger/LayerScreenshot.cpp
+++ /dev/null
@@ -1,171 +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 <GLES/gl.h>
-#include <GLES/glext.h>
-
-#include <utils/Errors.h>
-#include <utils/Log.h>
-
-#include <ui/GraphicBuffer.h>
-
-#include "LayerScreenshot.h"
-#include "SurfaceFlinger.h"
-#include "DisplayDevice.h"
-
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-LayerScreenshot::LayerScreenshot(SurfaceFlinger* flinger,
- const sp<Client>& client)
- : LayerBaseClient(flinger, client),
- mTextureName(0), mFlinger(flinger), mIsSecure(false)
-{
-}
-
-LayerScreenshot::~LayerScreenshot()
-{
- if (mTextureName) {
- mFlinger->deleteTextureAsync(mTextureName);
- }
-}
-
-status_t LayerScreenshot::captureLocked(int32_t layerStack) {
- GLfloat u, v;
- status_t result = mFlinger->renderScreenToTextureLocked(layerStack,
- &mTextureName, &u, &v);
- if (result != NO_ERROR) {
- return result;
- }
- initTexture(u, v);
-
- // Currently screenshot always comes from the default display
- mIsSecure = mFlinger->getDefaultDisplayDevice()->getSecureLayerVisible();
-
- return NO_ERROR;
-}
-
-status_t LayerScreenshot::capture() {
- GLfloat u, v;
- status_t result = mFlinger->renderScreenToTexture(0, &mTextureName, &u, &v);
- if (result != NO_ERROR) {
- return result;
- }
- initTexture(u, v);
-
- // Currently screenshot always comes from the default display
- mIsSecure = mFlinger->getDefaultDisplayDevice()->getSecureLayerVisible();
-
- return NO_ERROR;
-}
-
-void LayerScreenshot::initTexture(GLfloat u, GLfloat v) {
- glBindTexture(GL_TEXTURE_2D, mTextureName);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- mTexCoords[0] = 0; mTexCoords[1] = v;
- mTexCoords[2] = 0; mTexCoords[3] = 0;
- mTexCoords[4] = u; mTexCoords[5] = 0;
- mTexCoords[6] = u; mTexCoords[7] = v;
-}
-
-void LayerScreenshot::initStates(uint32_t w, uint32_t h, uint32_t flags) {
- LayerBaseClient::initStates(w, h, flags);
- if (!(flags & ISurfaceComposerClient::eHidden)) {
- capture();
- }
- if (flags & ISurfaceComposerClient::eSecure) {
- ALOGW("ignoring surface flag eSecure - LayerScreenshot is considered "
- "secure iff it captures the contents of a secure surface.");
- }
-}
-
-uint32_t LayerScreenshot::doTransaction(uint32_t flags)
-{
- const LayerBase::State& draw(drawingState());
- const LayerBase::State& curr(currentState());
-
- if (draw.flags & layer_state_t::eLayerHidden) {
- if (!(curr.flags & layer_state_t::eLayerHidden)) {
- // we're going from hidden to visible
- status_t err = captureLocked(curr.layerStack);
- if (err != NO_ERROR) {
- ALOGW("createScreenshotSurface failed (%s)", strerror(-err));
- }
- }
- } else if (curr.flags & layer_state_t::eLayerHidden) {
- // we're going from visible to hidden
- if (mTextureName) {
- glDeleteTextures(1, &mTextureName);
- mTextureName = 0;
- }
- }
- return LayerBaseClient::doTransaction(flags);
-}
-
-void LayerScreenshot::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const
-{
- const State& s(drawingState());
- if (s.alpha>0) {
- const GLfloat alpha = s.alpha/255.0f;
- const uint32_t fbHeight = hw->getHeight();
-
- if (s.alpha == 0xFF) {
- glDisable(GL_BLEND);
- glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
- } else {
- glEnable(GL_BLEND);
- glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- }
-
- GLuint texName = mTextureName;
- if (isSecure() && !hw->isSecure()) {
- texName = mFlinger->getProtectedTexName();
- }
-
- LayerMesh mesh;
- computeGeometry(hw, &mesh);
-
- glColor4f(alpha, alpha, alpha, alpha);
-
- glDisable(GL_TEXTURE_EXTERNAL_OES);
- glEnable(GL_TEXTURE_2D);
-
- glBindTexture(GL_TEXTURE_2D, texName);
- glMatrixMode(GL_TEXTURE);
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
-
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glTexCoordPointer(2, GL_FLOAT, 0, mTexCoords);
- glVertexPointer(2, GL_FLOAT, 0, mesh.getVertices());
- glDrawArrays(GL_TRIANGLE_FAN, 0, mesh.getVertexCount());
-
- glDisable(GL_BLEND);
- glDisable(GL_TEXTURE_2D);
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
- }
-}
-
-// ---------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/services/surfaceflinger/LayerScreenshot.h b/services/surfaceflinger/LayerScreenshot.h
deleted file mode 100644
index 38cbd88..0000000
--- a/services/surfaceflinger/LayerScreenshot.h
+++ /dev/null
@@ -1,62 +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 <EGL/egl.h>
-#include <EGL/eglext.h>
-
-#include "LayerBase.h"
-
-// ---------------------------------------------------------------------------
-
-namespace android {
-
-class LayerScreenshot : public LayerBaseClient
-{
- GLuint mTextureName;
- GLfloat mTexCoords[8];
- sp<SurfaceFlinger> mFlinger;
- bool mIsSecure;
-public:
- LayerScreenshot(SurfaceFlinger* flinger, const sp<Client>& client);
- virtual ~LayerScreenshot();
-
- status_t capture();
-
- virtual void initStates(uint32_t w, uint32_t h, uint32_t flags);
- virtual uint32_t doTransaction(uint32_t flags);
- virtual void onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const;
- virtual bool isOpaque() const { return false; }
- virtual bool isSecure() const { return mIsSecure; }
- virtual bool isProtectedByApp() const { return false; }
- virtual bool isProtectedByDRM() const { return false; }
- virtual const char* getTypeId() const { return "LayerScreenshot"; }
-
-private:
- status_t captureLocked(int32_t layerStack);
- void initTexture(GLfloat u, GLfloat v);
-};
-
-// ---------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_LAYER_SCREENSHOT_H
diff --git a/services/surfaceflinger/MessageQueue.cpp b/services/surfaceflinger/MessageQueue.cpp
index 3f77f74..c9c7b96 100644
--- a/services/surfaceflinger/MessageQueue.cpp
+++ b/services/surfaceflinger/MessageQueue.cpp
@@ -61,6 +61,12 @@ void MessageQueue::Handler::dispatchInvalidate() {
}
}
+void MessageQueue::Handler::dispatchTransaction() {
+ if ((android_atomic_or(eventMaskTransaction, &mEventMask) & eventMaskTransaction) == 0) {
+ mQueue.mLooper->sendMessage(this, Message(MessageQueue::TRANSACTION));
+ }
+}
+
void MessageQueue::Handler::handleMessage(const Message& message) {
switch (message.what) {
case INVALIDATE:
@@ -71,6 +77,10 @@ void MessageQueue::Handler::handleMessage(const Message& message) {
android_atomic_and(~eventMaskRefresh, &mEventMask);
mQueue.mFlinger->onMessageReceived(message.what);
break;
+ case TRANSACTION:
+ android_atomic_and(~eventMaskTransaction, &mEventMask);
+ mQueue.mFlinger->onMessageReceived(message.what);
+ break;
}
}
@@ -132,6 +142,7 @@ 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.
@@ -143,6 +154,10 @@ status_t MessageQueue::postMessage(
*/
#define INVALIDATE_ON_VSYNC 1
+void MessageQueue::invalidateTransactionNow() {
+ mHandler->dispatchTransaction();
+}
+
void MessageQueue::invalidate() {
#if INVALIDATE_ON_VSYNC
mEvents->requestNextVsync();
diff --git a/services/surfaceflinger/MessageQueue.h b/services/surfaceflinger/MessageQueue.h
index 710b2c2..b77e08e 100644
--- a/services/surfaceflinger/MessageQueue.h
+++ b/services/surfaceflinger/MessageQueue.h
@@ -62,8 +62,9 @@ private:
class MessageQueue {
class Handler : public MessageHandler {
enum {
- eventMaskInvalidate = 0x1,
- eventMaskRefresh = 0x2
+ eventMaskInvalidate = 0x1,
+ eventMaskRefresh = 0x2,
+ eventMaskTransaction = 0x4
};
MessageQueue& mQueue;
int32_t mEventMask;
@@ -72,6 +73,7 @@ class MessageQueue {
virtual void handleMessage(const Message& message);
void dispatchRefresh();
void dispatchInvalidate();
+ void dispatchTransaction();
};
friend class Handler;
@@ -89,8 +91,9 @@ class MessageQueue {
public:
enum {
- INVALIDATE = 0,
- REFRESH = 1,
+ INVALIDATE = 0,
+ REFRESH = 1,
+ TRANSACTION = 2
};
MessageQueue();
@@ -100,8 +103,13 @@ public:
void waitMessage();
status_t postMessage(const sp<MessageBase>& message, nsecs_t reltime=0);
+
+ // sends INVALIDATE message at next VSYNC
void invalidate();
+ // sends REFRESH message at next VSYNC
void refresh();
+ // sends TRANSACTION message immediately
+ void invalidateTransactionNow();
};
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 055bfe4..ef0d521 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -39,7 +39,8 @@
#include <gui/BufferQueue.h>
#include <gui/GuiConfig.h>
#include <gui/IDisplayEventConnection.h>
-#include <gui/SurfaceTextureClient.h>
+#include <gui/Surface.h>
+#include <gui/GraphicBufferAlloc.h>
#include <ui/GraphicBufferAllocator.h>
#include <ui/PixelFormat.h>
@@ -52,6 +53,7 @@
#include <utils/Trace.h>
#include <private/android_filesystem_config.h>
+#include <private/gui/SyncFeatures.h>
#include "clz.h"
#include "DdmConnection.h"
@@ -61,18 +63,16 @@
#include "GLExtensions.h"
#include "Layer.h"
#include "LayerDim.h"
-#include "LayerScreenshot.h"
#include "SurfaceFlinger.h"
#include "DisplayHardware/FramebufferSurface.h"
-#include "DisplayHardware/GraphicBufferAlloc.h"
#include "DisplayHardware/HWComposer.h"
-
-
-#define EGL_VERSION_HW_ANDROID 0x3143
+#include "DisplayHardware/VirtualDisplaySurface.h"
#define DISPLAY_COUNT 1
+EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
+
namespace android {
// ---------------------------------------------------------------------------
@@ -93,6 +93,7 @@ SurfaceFlinger::SurfaceFlinger()
mBootTime(systemTime()),
mVisibleRegionsDirty(false),
mHwWorkListDirty(false),
+ mAnimCompositionPending(false),
mDebugRegion(0),
mDebugDDMS(0),
mDebugDisableHWC(0),
@@ -108,6 +109,9 @@ SurfaceFlinger::SurfaceFlinger()
// debugging stuff...
char value[PROPERTY_VALUE_MAX];
+ property_get("ro.bq.gpu_to_cpu_unsupported", value, "0");
+ mGpuToCpuSupported = !atoi(value);
+
property_get("debug.sf.showupdates", value, "0");
mDebugRegion = atoi(value);
@@ -488,6 +492,10 @@ status_t SurfaceFlinger::readyToRun()
mEGLConfig = selectEGLConfig(mEGLDisplay, format);
mEGLContext = createGLContext(mEGLDisplay, mEGLConfig);
+ // figure out which format we got
+ eglGetConfigAttrib(mEGLDisplay, mEGLConfig,
+ EGL_NATIVE_VISUAL_ID, &mEGLNativeVisualId);
+
LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,
"couldn't create EGLContext");
@@ -501,11 +509,10 @@ status_t SurfaceFlinger::readyToRun()
createBuiltinDisplayLocked(type);
wp<IBinder> token = mBuiltinDisplays[i];
- sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i);
- sp<SurfaceTextureClient> stc = new SurfaceTextureClient(
- static_cast< sp<ISurfaceTexture> >(fbs->getBufferQueue()));
sp<DisplayDevice> hw = new DisplayDevice(this,
- type, isSecure, token, stc, fbs, mEGLConfig);
+ type, allocateHwcDisplayId(type), isSecure, token,
+ new FramebufferSurface(*mHwc, i),
+ mEGLConfig);
if (i > DisplayDevice::DISPLAY_PRIMARY) {
// FIXME: currently we don't get blank/unblank requests
// for displays other than the main display, so we always
@@ -571,44 +578,10 @@ uint32_t SurfaceFlinger::getMaxViewportDims() const {
// ----------------------------------------------------------------------------
bool SurfaceFlinger::authenticateSurfaceTexture(
- const sp<ISurfaceTexture>& surfaceTexture) const {
+ const sp<IGraphicBufferProducer>& bufferProducer) const {
Mutex::Autolock _l(mStateLock);
- sp<IBinder> surfaceTextureBinder(surfaceTexture->asBinder());
-
- // Check the visible layer list for the ISurface
- 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) {
- wp<IBinder> lbcBinder = lbc->getSurfaceTextureBinder();
- if (lbcBinder == surfaceTextureBinder) {
- return true;
- }
- }
- }
-
- // Check the layers in the purgatory. This check is here so that if a
- // SurfaceTexture gets destroyed before all the clients are done using it,
- // the error will not be reported as "surface XYZ is not authenticated", but
- // will instead fail later on when the client tries to use the surface,
- // which should be reported as "surface XYZ returned an -ENODEV". The
- // purgatorized layers are no less authentic than the visible ones, so this
- // 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;
- }
- }
- }
-
- return false;
+ sp<IBinder> surfaceTextureBinder(bufferProducer->asBinder());
+ return mGraphicBufferProducerList.indexOf(surfaceTextureBinder) >= 0;
}
status_t SurfaceFlinger::getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info) {
@@ -771,6 +744,9 @@ void SurfaceFlinger::eventControl(int disp, int event, int enabled) {
void SurfaceFlinger::onMessageReceived(int32_t what) {
ATRACE_CALL();
switch (what) {
+ case MessageQueue::TRANSACTION:
+ handleMessageTransaction();
+ break;
case MessageQueue::INVALIDATE:
handleMessageTransaction();
handleMessageInvalidate();
@@ -831,10 +807,10 @@ void SurfaceFlinger::doDebugFlashRegions()
while (it != end) {
const Rect& r = *it++;
GLfloat vertices[][2] = {
- { r.left, height - r.top },
- { r.left, height - r.bottom },
- { r.right, height - r.bottom },
- { r.right, height - r.top }
+ { (GLfloat) r.left, (GLfloat) (height - r.top) },
+ { (GLfloat) r.left, (GLfloat) (height - r.bottom) },
+ { (GLfloat) r.right, (GLfloat) (height - r.bottom) },
+ { (GLfloat) r.right, (GLfloat) (height - r.top) }
};
glVertexPointer(2, GL_FLOAT, 0, vertices);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
@@ -880,6 +856,22 @@ void SurfaceFlinger::postComposition()
for (size_t i=0 ; i<count ; i++) {
currentLayers[i]->onPostComposition();
}
+
+ if (mAnimCompositionPending) {
+ mAnimCompositionPending = false;
+
+ const HWComposer& hwc = getHwComposer();
+ sp<Fence> presentFence = hwc.getDisplayFence(HWC_DISPLAY_PRIMARY);
+ if (presentFence->isValid()) {
+ mAnimFrameTracker.setActualPresentFence(presentFence);
+ } else {
+ // The HWC doesn't support present fences, so use the refresh
+ // timestamp instead.
+ nsecs_t presentTime = hwc.getRefreshTimestamp(HWC_DISPLAY_PRIMARY);
+ mAnimFrameTracker.setActualPresentTime(presentTime);
+ }
+ mAnimFrameTracker.advanceFrame();
+ }
}
void SurfaceFlinger::rebuildLayerStacks() {
@@ -893,7 +885,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());
@@ -903,7 +895,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(
@@ -933,14 +925,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);
@@ -956,7 +948,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);
@@ -966,7 +958,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);
}
}
@@ -1020,7 +1012,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();
@@ -1076,7 +1068,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;
@@ -1113,11 +1105,14 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
// Call makeCurrent() on the primary display so we can
// be sure that nothing associated with this display
// is current.
- const sp<const DisplayDevice> hw(getDefaultDisplayDevice());
- DisplayDevice::makeCurrent(mEGLDisplay, hw, mEGLContext);
+ const sp<const DisplayDevice> defaultDisplay(getDefaultDisplayDevice());
+ DisplayDevice::makeCurrent(mEGLDisplay, defaultDisplay, mEGLContext);
+ sp<DisplayDevice> hw(getDisplayDevice(draw.keyAt(i)));
+ if (hw != NULL)
+ hw->disconnect(getHwComposer());
+ if (draw[i].type < DisplayDevice::NUM_DISPLAY_TYPES)
+ mEventThread->onHotplugReceived(draw[i].type, false);
mDisplays.removeItem(draw.keyAt(i));
- getHwComposer().disconnectDisplay(draw[i].type);
- mEventThread->onHotplugReceived(draw[i].type, false);
} else {
ALOGW("trying to remove the main display");
}
@@ -1130,6 +1125,9 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
// recreating the DisplayDevice, so we just remove it
// from the drawing state, so that it get re-added
// below.
+ sp<DisplayDevice> hw(getDisplayDevice(display));
+ if (hw != NULL)
+ hw->disconnect(getHwComposer());
mDisplays.removeItem(display);
mDrawingState.displays.removeItemsAt(i);
dc--; i--;
@@ -1159,38 +1157,48 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
if (draw.indexOfKey(curr.keyAt(i)) < 0) {
const DisplayDeviceState& state(curr[i]);
- sp<FramebufferSurface> fbs;
- sp<SurfaceTextureClient> stc;
- if (!state.isVirtualDisplay()) {
-
+ sp<DisplaySurface> dispSurface;
+ int32_t hwcDisplayId = -1;
+ if (state.isVirtualDisplay()) {
+ // Virtual displays without a surface are dormant:
+ // they have external state (layer stack, projection,
+ // etc.) but no internal state (i.e. a DisplayDevice).
+ if (state.surface != NULL) {
+ hwcDisplayId = allocateHwcDisplayId(state.type);
+ dispSurface = new VirtualDisplaySurface(
+ *mHwc, hwcDisplayId, state.surface,
+ state.displayName);
+ }
+ } else {
ALOGE_IF(state.surface!=NULL,
"adding a supported display, but rendering "
"surface is provided (%p), ignoring it",
state.surface.get());
-
+ hwcDisplayId = allocateHwcDisplayId(state.type);
// for supported (by hwc) displays we provide our
// own rendering surface
- fbs = new FramebufferSurface(*mHwc, state.type);
- stc = new SurfaceTextureClient(
- static_cast< sp<ISurfaceTexture> >(
- fbs->getBufferQueue()));
- } else {
- if (state.surface != NULL) {
- stc = new SurfaceTextureClient(state.surface);
- }
+ dispSurface = new FramebufferSurface(*mHwc, state.type);
}
const wp<IBinder>& display(curr.keyAt(i));
- if (stc != NULL) {
+ if (dispSurface != NULL) {
sp<DisplayDevice> hw = new DisplayDevice(this,
- state.type, state.isSecure, display, stc, fbs,
- mEGLConfig);
+ state.type, hwcDisplayId, state.isSecure,
+ display, dispSurface, mEGLConfig);
hw->setLayerStack(state.layerStack);
hw->setProjection(state.orientation,
state.viewport, state.frame);
hw->setDisplayName(state.displayName);
mDisplays.add(display, hw);
- mEventThread->onHotplugReceived(state.type, true);
+ if (state.isVirtualDisplay()) {
+ if (hwcDisplayId >= 0) {
+ mHwc->setVirtualDisplayProperties(hwcDisplayId,
+ hw->getWidth(), hw->getHeight(),
+ hw->getFormat());
+ }
+ } else {
+ mEventThread->onHotplugReceived(state.type, true);
+ }
}
}
}
@@ -1223,8 +1231,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
@@ -1237,17 +1245,22 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
if (disp == NULL) {
disp = hw;
} else {
- disp = getDefaultDisplayDevice();
+ disp = NULL;
break;
}
}
}
}
- if (disp != NULL) {
- // presumably this means this layer is using a layerStack
- // that is not visible on any display
- layerBase->updateTransformHint(disp);
+ if (disp == NULL) {
+ // NOTE: TEMPORARY FIX ONLY. Real fix should cause layers to
+ // redraw after transform hint changes. See bug 8508397.
+
+ // could be null when this layer is using a layerStack
+ // that is not visible on any display. Also can occur at
+ // screen off/on times.
+ disp = getDefaultDisplayDevice();
}
+ layer->updateTransformHint(disp);
}
}
@@ -1269,7 +1282,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
@@ -1296,6 +1309,10 @@ void SurfaceFlinger::commitTransaction()
mLayersPendingRemoval.clear();
}
+ // If this transaction is part of a window animation then the next frame
+ // we composite should be considered an animation as well.
+ mAnimCompositionPending = mAnimTransactionPending;
+
mDrawingState = mCurrentState;
mTransactionPending = false;
mAnimTransactionPending = false;
@@ -1316,12 +1333,12 @@ 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());
- // only consider the layers on the given later stack
+ // only consider the layers on the given layer stack
if (s.layerStack != layerStack)
continue;
@@ -1358,7 +1375,7 @@ void SurfaceFlinger::computeVisibleRegions(
// handle hidden surfaces by setting the visible region to empty
if (CC_LIKELY(layer->isVisible())) {
const bool translucent = !layer->isOpaque();
- Rect bounds(layer->computeBounds());
+ Rect bounds(s.transform.transform(layer->computeBounds()));
visibleRegion.set(bounds);
if (!visibleRegion.isEmpty()) {
// Remove the transparent area from the visible region
@@ -1367,14 +1384,14 @@ void SurfaceFlinger::computeVisibleRegions(
if (tr.transformed()) {
if (tr.preserveRects()) {
// transform the transparent region
- transparentRegion = tr.transform(s.transparentRegion);
+ transparentRegion = tr.transform(s.activeTransparentRegion);
} else {
// transformation too complex, can't do the
// transparent region optimization.
transparentRegion.clear();
}
} else {
- transparentRegion = s.transparentRegion;
+ transparentRegion = s.activeTransparentRegion;
}
}
@@ -1459,7 +1476,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);
@@ -1541,7 +1558,20 @@ void SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
} else {
- const Region region(hw->undefinedRegion.intersect(dirty));
+ // we start with the whole screen area
+ const Region bounds(hw->getBounds());
+
+ // we remove the scissor part
+ // we're left with the letterbox region
+ // (common case is that letterbox ends-up being empty)
+ const Region letterbox(bounds.subtract(hw->getScissor()));
+
+ // compute the area to clear
+ Region region(hw->undefinedRegion.merge(letterbox));
+
+ // but limit it to the dirty region
+ region.andSelf(dirty);
+
// screen is already cleared here
if (!region.isEmpty()) {
// can happen with SurfaceView
@@ -1549,13 +1579,12 @@ void SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const
}
}
- if (hw->getDisplayType() >= DisplayDevice::DISPLAY_EXTERNAL) {
- // TODO: just to be on the safe side, we don't set the
+ if (hw->getDisplayType() != DisplayDevice::DISPLAY_PRIMARY) {
+ // just to be on the safe side, we don't set the
// scissor on the main display. It should never be needed
// anyways (though in theory it could since the API allows it).
const Rect& bounds(hw->getBounds());
- const Transform& tr(hw->getTransform());
- const Rect scissor(tr.transform(hw->getViewport()));
+ const Rect& scissor(hw->getScissor());
if (scissor != bounds) {
// scissor doesn't match the screen's dimensions, so we
// need to clear everything outside of it and enable
@@ -1563,9 +1592,6 @@ void SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const
const GLint height = hw->getHeight();
glScissor(scissor.left, height - scissor.bottom,
scissor.getWidth(), scissor.getHeight());
- // clear everything unscissored
- glClearColor(0, 0, 0, 0);
- glClear(GL_COLOR_BUFFER_BIT);
// enable scissor for this frame
glEnable(GL_SCISSOR_TEST);
}
@@ -1576,13 +1602,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()) {
@@ -1614,7 +1640,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()) {
@@ -1641,66 +1667,43 @@ void SurfaceFlinger::drawWormhole(const sp<const DisplayDevice>& hw,
while (it != end) {
const Rect& r = *it++;
GLfloat vertices[][2] = {
- { r.left, height - r.top },
- { r.left, height - r.bottom },
- { r.right, height - r.bottom },
- { r.right, height - r.top }
+ { (GLfloat) r.left, (GLfloat) (height - r.top) },
+ { (GLfloat) r.left, (GLfloat) (height - r.bottom) },
+ { (GLfloat) r.right, (GLfloat) (height - r.bottom) },
+ { (GLfloat) r.right, (GLfloat) (height - r.top) }
};
glVertexPointer(2, GL_FLOAT, 0, vertices);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
}
-ssize_t SurfaceFlinger::addClientLayer(const sp<Client>& client,
- const sp<LayerBaseClient>& lbc)
+void SurfaceFlinger::addClientLayer(const sp<Client>& client,
+ const sp<IBinder>& handle,
+ const sp<IGraphicBufferProducer>& gbc,
+ const sp<Layer>& lbc)
{
// attach this layer to the client
- size_t name = client->attachLayer(lbc);
+ client->attachLayer(handle, lbc);
// add this layer to the current state list
Mutex::Autolock _l(mStateLock);
mCurrentState.layersSortedByZ.add(lbc);
-
- return ssize_t(name);
+ mGraphicBufferProducerList.add(gbc->asBinder());
}
-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);
- if (err == NO_ERROR)
- setTransactionFlags(eTransactionNeeded);
- return err;
-}
-
-status_t SurfaceFlinger::removeLayer_l(const sp<LayerBase>& layerBase)
-{
- ssize_t index = mCurrentState.layersSortedByZ.remove(layerBase);
+ ssize_t index = mCurrentState.layersSortedByZ.remove(layer);
if (index >= 0) {
+ mLayersPendingRemoval.push(layer);
mLayersRemoved = true;
+ setTransactionFlags(eTransactionNeeded);
return NO_ERROR;
}
return status_t(index);
}
-status_t SurfaceFlinger::purgatorizeLayer_l(const sp<LayerBase>& layerBase)
-{
- // 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);
- if (err >= 0) {
- mLayerPurgatory.add(layerBase);
- }
-
- mLayersPendingRemoval.push(layerBase);
-
- // it's possible that we don't find a layer, because it might
- // have been destroyed already -- this is not technically an error
- // from the user because there is a race between Client::destroySurface(),
- // ~Client() and ~ISurface().
- return (err == NAME_NOT_FOUND) ? status_t(NO_ERROR) : err;
-}
-
uint32_t SurfaceFlinger::peekTransactionFlags(uint32_t flags)
{
return android_atomic_release_load(&mTransactionFlags);
@@ -1843,7 +1846,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) {
@@ -1901,55 +1904,49 @@ uint32_t SurfaceFlinger::setClientStateLocked(
return flags;
}
-sp<ISurface> SurfaceFlinger::createLayer(
- ISurfaceComposerClient::surface_data_t* params,
+status_t SurfaceFlinger::createLayer(
const String8& name,
const sp<Client>& client,
- uint32_t w, uint32_t h, PixelFormat format,
- uint32_t flags)
+ uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
+ sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp)
{
- sp<LayerBaseClient> layer;
- sp<ISurface> surfaceHandle;
-
+ //ALOGD("createLayer for (%d x %d), name=%s", w, h, name.string());
if (int32_t(w|h) < 0) {
ALOGE("createLayer() failed, w or h is negative (w=%d, h=%d)",
int(w), int(h));
- return surfaceHandle;
+ return BAD_VALUE;
}
- //ALOGD("createLayer for (%d x %d), name=%s", w, h, name.string());
+ status_t result = NO_ERROR;
+
+ sp<Layer> layer;
+
switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
case ISurfaceComposerClient::eFXSurfaceNormal:
- layer = createNormalLayer(client, w, h, flags, format);
+ result = createNormalLayer(client,
+ name, w, h, flags, format,
+ handle, gbp, &layer);
break;
- case ISurfaceComposerClient::eFXSurfaceBlur:
case ISurfaceComposerClient::eFXSurfaceDim:
- layer = createDimLayer(client, w, h, flags);
+ result = createDimLayer(client,
+ name, w, h, flags,
+ handle, gbp, &layer);
break;
- case ISurfaceComposerClient::eFXSurfaceScreenshot:
- layer = createScreenshotLayer(client, w, h, flags);
+ default:
+ result = BAD_VALUE;
break;
}
- if (layer != 0) {
- layer->initStates(w, h, flags);
- layer->setName(name);
- ssize_t token = addClientLayer(client, layer);
- surfaceHandle = layer->getSurface();
- if (surfaceHandle != 0) {
- params->token = token;
- params->identity = layer->getIdentity();
- }
+ if (result == NO_ERROR) {
+ addClientLayer(client, *handle, *gbp, layer);
setTransactionFlags(eTransactionNeeded);
}
-
- return surfaceHandle;
+ return result;
}
-sp<Layer> SurfaceFlinger::createNormalLayer(
- const sp<Client>& client,
- uint32_t w, uint32_t h, uint32_t flags,
- PixelFormat& format)
+status_t SurfaceFlinger::createNormalLayer(const sp<Client>& client,
+ const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format,
+ sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer)
{
// initialize the surfaces
switch (format) {
@@ -1971,71 +1968,48 @@ sp<Layer> SurfaceFlinger::createNormalLayer(
format = PIXEL_FORMAT_RGBA_8888;
#endif
- sp<Layer> layer = new Layer(this, client);
- status_t err = layer->setBuffers(w, h, format, flags);
- if (CC_LIKELY(err != NO_ERROR)) {
- ALOGE("createNormalLayer() failed (%s)", strerror(-err));
- layer.clear();
+ *outLayer = new Layer(this, client, name, w, h, flags);
+ status_t err = (*outLayer)->setBuffers(w, h, format, flags);
+ if (err == NO_ERROR) {
+ *handle = (*outLayer)->getHandle();
+ *gbp = (*outLayer)->getBufferQueue();
}
- return layer;
-}
-sp<LayerDim> SurfaceFlinger::createDimLayer(
- const sp<Client>& client,
- uint32_t w, uint32_t h, uint32_t flags)
-{
- sp<LayerDim> layer = new LayerDim(this, client);
- return layer;
+ ALOGE_IF(err, "createNormalLayer() failed (%s)", strerror(-err));
+ return err;
}
-sp<LayerScreenshot> SurfaceFlinger::createScreenshotLayer(
- const sp<Client>& client,
- uint32_t w, uint32_t h, uint32_t flags)
+status_t SurfaceFlinger::createDimLayer(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)
{
- sp<LayerScreenshot> layer = new LayerScreenshot(this, client);
- return layer;
+ *outLayer = new LayerDim(this, client, name, w, h, flags);
+ *handle = (*outLayer)->getHandle();
+ *gbp = (*outLayer)->getBufferQueue();
+ return NO_ERROR;
}
-status_t SurfaceFlinger::onLayerRemoved(const sp<Client>& client, SurfaceID sid)
+status_t SurfaceFlinger::onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle)
{
- /*
- * called by the window manager, when a surface should be marked for
- * destruction.
- *
- * The surface is removed from the current and drawing lists, but placed
- * in the purgatory queue, so it's not destroyed right-away (we need
- * to wait for all client's references to go away first).
- */
-
- status_t err = NAME_NOT_FOUND;
- Mutex::Autolock _l(mStateLock);
- sp<LayerBaseClient> layer = client->getLayerUser(sid);
-
- if (layer != 0) {
- err = purgatorizeLayer_l(layer);
- if (err == NO_ERROR) {
- setTransactionFlags(eTransactionNeeded);
- }
+ // called by the window manager when it wants to remove a Layer
+ status_t err = NO_ERROR;
+ sp<Layer> l(client->getLayerUser(handle));
+ if (l != NULL) {
+ err = removeLayer(l);
+ ALOGE_IF(err<0 && err != NAME_NOT_FOUND,
+ "error removing layer=%p (%s)", l.get(), strerror(-err));
}
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
+ // called by ~LayerCleaner() when all references to the IBinder (handle)
+ // 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);
- if (err == NAME_NOT_FOUND) {
- // The surface wasn't in the current list, which means it was
- // removed already, which means it is in the purgatory,
- // and need to be removed from there.
- ssize_t idx = mLayerPurgatory.remove(l);
- ALOGE_IF(idx < 0,
- "layer=%p is not in the purgatory list", l.get());
- }
+ err = removeLayer(l);
ALOGE_IF(err<0 && err != NAME_NOT_FOUND,
"error removing layer=%p (%s)", l.get(), strerror(-err));
}
@@ -2045,12 +2019,14 @@ status_t SurfaceFlinger::onLayerDestroyed(const wp<LayerBaseClient>& layer)
// ---------------------------------------------------------------------------
void SurfaceFlinger::onInitializeDisplays() {
- // reset screen orientation
+ // reset screen orientation and use primary layer stack
Vector<ComposerState> state;
Vector<DisplayState> displays;
DisplayState d;
- d.what = DisplayState::eDisplayProjectionChanged;
+ d.what = DisplayState::eDisplayProjectionChanged |
+ DisplayState::eLayerStackChanged;
d.token = mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY];
+ d.layerStack = 0;
d.orientation = DisplayState::eOrientationDefault;
d.frame.makeInvalid();
d.viewport.makeInvalid();
@@ -2173,11 +2149,14 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
char buffer[SIZE];
String8 result;
- if (!PermissionCache::checkCallingPermission(sDump)) {
+
+ IPCThreadState* ipc = IPCThreadState::self();
+ const int pid = ipc->getCallingPid();
+ const int uid = ipc->getCallingUid();
+ if ((uid != AID_SHELL) &&
+ !PermissionCache::checkPermission(sDump, pid, uid)) {
snprintf(buffer, SIZE, "Permission Denial: "
- "can't dump SurfaceFlinger from pid=%d, uid=%d\n",
- IPCThreadState::self()->getCallingPid(),
- IPCThreadState::self()->getCallingUid());
+ "can't dump SurfaceFlinger from pid=%d, uid=%d\n", pid, uid);
result.append(buffer);
} else {
// Try to get the main lock, but don't insist if we can't
@@ -2239,7 +2218,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);
}
@@ -2254,22 +2233,26 @@ void SurfaceFlinger::dumpStatsLocked(const Vector<String16>& args, size_t& index
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]);
- if (name.isEmpty()) {
- snprintf(buffer, SIZE, "%s\n", layer->getName().string());
- result.append(buffer);
- }
- if (name.isEmpty() || (name == layer->getName())) {
- layer->dumpStats(result, buffer, SIZE);
+ const nsecs_t period =
+ getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
+ result.appendFormat("%lld\n", period);
+
+ if (name.isEmpty()) {
+ mAnimFrameTracker.dump(result);
+ } else {
+ 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()) {
+ layer->dumpStats(result, buffer, SIZE);
+ }
}
}
}
void SurfaceFlinger::clearStatsLocked(const Vector<String16>& args, size_t& index,
- String8& result, char* buffer, size_t SIZE) const
+ String8& result, char* buffer, size_t SIZE)
{
String8 name;
if (index < args.size()) {
@@ -2280,11 +2263,13 @@ 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();
}
}
+
+ mAnimFrameTracker.clear();
}
/*static*/ void SurfaceFlinger::appendSfConfigString(String8& result)
@@ -2326,6 +2311,10 @@ void SurfaceFlinger::dumpAllLocked(
appendGuiConfigString(result);
result.append("\n");
+ result.append("Sync configuration: ");
+ result.append(SyncFeatures::getInstance().toString());
+ result.append("\n");
+
/*
* Dump the visible layer list
*/
@@ -2334,23 +2323,11 @@ 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);
}
/*
- * Dump the layers in the purgatory
- */
-
- const size_t purgatorySize = mLayerPurgatory.size();
- 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));
- layer->shortDump(result, buffer, SIZE);
- }
-
- /*
* Dump Display state
*/
@@ -2371,17 +2348,20 @@ void SurfaceFlinger::dumpAllLocked(
HWComposer& hwc(getHwComposer());
sp<const DisplayDevice> hw(getDefaultDisplayDevice());
const GLExtensions& extensions(GLExtensions::getInstance());
+
+ snprintf(buffer, SIZE, "EGL implementation : %s\n",
+ eglQueryStringImplementationANDROID(mEGLDisplay, EGL_VERSION));
+ result.append(buffer);
+ snprintf(buffer, SIZE, "%s\n",
+ eglQueryStringImplementationANDROID(mEGLDisplay, EGL_EXTENSIONS));
+ result.append(buffer);
+
snprintf(buffer, SIZE, "GLES: %s, %s, %s\n",
extensions.getVendor(),
extensions.getRenderer(),
extensions.getVersion());
result.append(buffer);
-
- snprintf(buffer, SIZE, "EGL : %s\n",
- eglQueryString(mEGLDisplay, EGL_VERSION_HW_ANDROID));
- result.append(buffer);
-
- snprintf(buffer, SIZE, "EXTS: %s\n", extensions.getExtension());
+ snprintf(buffer, SIZE, "%s\n", extensions.getExtension());
result.append(buffer);
hw->undefinedRegion.dump(result, "undefinedRegion");
@@ -2395,13 +2375,18 @@ void SurfaceFlinger::dumpAllLocked(
" transaction-flags : %08x\n"
" refresh-rate : %f fps\n"
" x-dpi : %f\n"
- " y-dpi : %f\n",
+ " y-dpi : %f\n"
+ " EGL_NATIVE_VISUAL_ID : %d\n"
+ " gpu_to_cpu_unsupported : %d\n"
+ ,
mLastSwapBufferTime/1000.0,
mLastTransactionTime/1000.0,
mTransactionFlags,
1e9 / hwc.getRefreshPeriod(HWC_DISPLAY_PRIMARY),
hwc.getDpiX(HWC_DISPLAY_PRIMARY),
- hwc.getDpiY(HWC_DISPLAY_PRIMARY));
+ hwc.getDpiY(HWC_DISPLAY_PRIMARY),
+ mEGLNativeVisualId,
+ !mGpuToCpuSupported);
result.append(buffer);
snprintf(buffer, SIZE, " eglSwapBuffers time: %f us\n",
@@ -2435,10 +2420,22 @@ void SurfaceFlinger::dumpAllLocked(
alloc.dump(result);
}
-const Vector< sp<LayerBase> >&
-SurfaceFlinger::getLayerSortedByZForHwcDisplay(int disp) {
+const Vector< sp<Layer> >&
+SurfaceFlinger::getLayerSortedByZForHwcDisplay(int id) {
// Note: mStateLock is held here
- return getDisplayDevice( getBuiltInDisplay(disp) )->getVisibleLayersSortedByZ();
+ wp<IBinder> dpy;
+ for (size_t i=0 ; i<mDisplays.size() ; i++) {
+ if (mDisplays.valueAt(i)->getHwcDisplayId() == id) {
+ dpy = mDisplays.keyAt(i);
+ break;
+ }
+ }
+ if (dpy == NULL) {
+ ALOGE("getLayerSortedByZForHwcDisplay: invalid hwc display id %d", id);
+ // Just use the primary display so we have something to return
+ dpy = getBuiltInDisplay(DisplayDevice::DISPLAY_PRIMARY);
+ }
+ return getDisplayDevice(dpy)->getVisibleLayersSortedByZ();
}
bool SurfaceFlinger::startDdmConnection()
@@ -2464,6 +2461,7 @@ status_t SurfaceFlinger::onTransact(
{
switch (code) {
case CREATE_CONNECTION:
+ case CREATE_DISPLAY:
case SET_TRANSACTION_STATE:
case BOOT_FINISHED:
case BLANK:
@@ -2570,101 +2568,320 @@ void SurfaceFlinger::repaintEverything() {
}
// ---------------------------------------------------------------------------
+// Capture screen into an IGraphiBufferProducer
+// ---------------------------------------------------------------------------
-status_t SurfaceFlinger::renderScreenToTexture(uint32_t layerStack,
- GLuint* textureName, GLfloat* uOut, GLfloat* vOut)
-{
- Mutex::Autolock _l(mStateLock);
- return renderScreenToTextureLocked(layerStack, textureName, uOut, vOut);
+/* The code below is here to handle b/8734824
+ *
+ * We create a IGraphicBufferProducer wrapper that forwards all calls
+ * to the calling binder thread, where they are executed. This allows
+ * the calling thread to be reused (on the other side) and not
+ * depend on having "enough" binder threads to handle the requests.
+ *
+ */
+
+class GraphicProducerWrapper : public BBinder, public MessageHandler {
+ sp<IGraphicBufferProducer> impl;
+ sp<Looper> looper;
+ status_t result;
+ bool exitPending;
+ bool exitRequested;
+ mutable Barrier barrier;
+ volatile int32_t memoryBarrier;
+ uint32_t code;
+ Parcel const* data;
+ Parcel* reply;
+
+ enum {
+ MSG_API_CALL,
+ MSG_EXIT
+ };
+
+ /*
+ * this is called by our "fake" BpGraphicBufferProducer. We package the
+ * data and reply Parcel and forward them to the calling thread.
+ */
+ virtual status_t transact(uint32_t code,
+ const Parcel& data, Parcel* reply, uint32_t flags) {
+ this->code = code;
+ this->data = &data;
+ this->reply = reply;
+ android_atomic_acquire_store(0, &memoryBarrier);
+ if (exitPending) {
+ // if we've exited, we run the message synchronously right here
+ handleMessage(Message(MSG_API_CALL));
+ } else {
+ barrier.close();
+ looper->sendMessage(this, Message(MSG_API_CALL));
+ barrier.wait();
+ }
+ return NO_ERROR;
+ }
+
+ /*
+ * here we run on the binder calling thread. All we've got to do is
+ * call the real BpGraphicBufferProducer.
+ */
+ virtual void handleMessage(const Message& message) {
+ android_atomic_release_load(&memoryBarrier);
+ if (message.what == MSG_API_CALL) {
+ impl->asBinder()->transact(code, data[0], reply);
+ barrier.open();
+ } else if (message.what == MSG_EXIT) {
+ exitRequested = true;
+ }
+ }
+
+public:
+ GraphicProducerWrapper(const sp<IGraphicBufferProducer>& impl) :
+ impl(impl), looper(new Looper(true)), result(NO_ERROR),
+ exitPending(false), exitRequested(false) {
+ }
+
+ status_t waitForResponse() {
+ do {
+ looper->pollOnce(-1);
+ } while (!exitRequested);
+ return result;
+ }
+
+ void exit(status_t result) {
+ exitPending = true;
+ looper->sendMessage(this, Message(MSG_EXIT));
+ }
+};
+
+status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
+ const sp<IGraphicBufferProducer>& producer,
+ uint32_t reqWidth, uint32_t reqHeight,
+ uint32_t minLayerZ, uint32_t maxLayerZ,
+ bool isCpuConsumer) {
+
+ if (CC_UNLIKELY(display == 0))
+ return BAD_VALUE;
+
+ if (CC_UNLIKELY(producer == 0))
+ return BAD_VALUE;
+
+
+ class MessageCaptureScreen : public MessageBase {
+ SurfaceFlinger* flinger;
+ sp<IBinder> display;
+ sp<IGraphicBufferProducer> producer;
+ uint32_t reqWidth, reqHeight;
+ uint32_t minLayerZ,maxLayerZ;
+ bool useReadPixels;
+ status_t result;
+ public:
+ MessageCaptureScreen(SurfaceFlinger* flinger,
+ const sp<IBinder>& display,
+ const sp<IGraphicBufferProducer>& producer,
+ uint32_t reqWidth, uint32_t reqHeight,
+ uint32_t minLayerZ, uint32_t maxLayerZ, bool useReadPixels)
+ : flinger(flinger), display(display), producer(producer),
+ reqWidth(reqWidth), reqHeight(reqHeight),
+ minLayerZ(minLayerZ), maxLayerZ(maxLayerZ),
+ useReadPixels(useReadPixels),
+ result(PERMISSION_DENIED)
+ {
+ }
+ status_t getResult() const {
+ return result;
+ }
+ virtual bool handler() {
+ Mutex::Autolock _l(flinger->mStateLock);
+ sp<const DisplayDevice> hw(flinger->getDisplayDevice(display));
+ if (!useReadPixels) {
+ result = flinger->captureScreenImplLocked(hw,
+ producer, reqWidth, reqHeight, minLayerZ, maxLayerZ);
+ } else {
+ result = flinger->captureScreenImplCpuConsumerLocked(hw,
+ producer, reqWidth, reqHeight, minLayerZ, maxLayerZ);
+ }
+ static_cast<GraphicProducerWrapper*>(producer->asBinder().get())->exit(result);
+ return true;
+ }
+ };
+
+ // make sure to process transactions before screenshots -- a transaction
+ // might already be pending but scheduled for VSYNC; this guarantees we
+ // will handle it before the screenshot. When VSYNC finally arrives
+ // the scheduled transaction will be a no-op. If no transactions are
+ // scheduled at this time, this will end-up being a no-op as well.
+ mEventQueue.invalidateTransactionNow();
+
+ bool useReadPixels = false;
+ if (isCpuConsumer) {
+ bool formatSupportedBytBitmap =
+ (mEGLNativeVisualId == HAL_PIXEL_FORMAT_RGBA_8888) ||
+ (mEGLNativeVisualId == HAL_PIXEL_FORMAT_RGBX_8888);
+ if (formatSupportedBytBitmap == false) {
+ // the pixel format we have is not compatible with
+ // Bitmap.java, which is the likely client of this API,
+ // so we just revert to glReadPixels() in that case.
+ useReadPixels = true;
+ }
+ if (mGpuToCpuSupported == false) {
+ // When we know the GL->CPU path works, we can call
+ // captureScreenImplLocked() directly, instead of using the
+ // glReadPixels() workaround.
+ useReadPixels = true;
+ }
+ }
+
+ // this creates a "fake" BBinder which will serve as a "fake" remote
+ // binder to receive the marshaled calls and forward them to the
+ // real remote (a BpGraphicBufferProducer)
+ sp<GraphicProducerWrapper> wrapper = new GraphicProducerWrapper(producer);
+
+ // the asInterface() call below creates our "fake" BpGraphicBufferProducer
+ // which does the marshaling work forwards to our "fake remote" above.
+ sp<MessageBase> msg = new MessageCaptureScreen(this,
+ display, IGraphicBufferProducer::asInterface( wrapper ),
+ reqWidth, reqHeight, minLayerZ, maxLayerZ,
+ useReadPixels);
+
+ status_t res = postMessageAsync(msg);
+ if (res == NO_ERROR) {
+ res = wrapper->waitForResponse();
+ }
+ return res;
}
-status_t SurfaceFlinger::renderScreenToTextureLocked(uint32_t layerStack,
- GLuint* textureName, GLfloat* uOut, GLfloat* vOut)
+
+void SurfaceFlinger::renderScreenImplLocked(
+ const sp<const DisplayDevice>& hw,
+ uint32_t reqWidth, uint32_t reqHeight,
+ uint32_t minLayerZ, uint32_t maxLayerZ,
+ bool yswap)
{
ATRACE_CALL();
- if (!GLExtensions::getInstance().haveFramebufferObject())
- return INVALID_OPERATION;
-
// get screen geometry
- // FIXME: figure out what it means to have a screenshot texture w/ multi-display
- sp<const DisplayDevice> hw(getDefaultDisplayDevice());
const uint32_t hw_w = hw->getWidth();
const uint32_t hw_h = hw->getHeight();
- GLfloat u = 1;
- GLfloat v = 1;
+
+ const bool filtering = reqWidth != hw_w || reqWidth != hw_h;
// make sure to clear all GL error flags
while ( glGetError() != GL_NO_ERROR ) ;
- // create a FBO
- GLuint name, tname;
- glGenTextures(1, &tname);
- glBindTexture(GL_TEXTURE_2D, tname);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
- hw_w, hw_h, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
- if (glGetError() != GL_NO_ERROR) {
- while ( glGetError() != GL_NO_ERROR ) ;
- GLint tw = (2 << (31 - clz(hw_w)));
- GLint th = (2 << (31 - clz(hw_h)));
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
- tw, th, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
- u = GLfloat(hw_w) / tw;
- v = GLfloat(hw_h) / th;
- }
- glGenFramebuffersOES(1, &name);
- glBindFramebufferOES(GL_FRAMEBUFFER_OES, name);
- glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES,
- GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tname, 0);
-
- DisplayDevice::setViewportAndProjection(hw);
+ // set-up our viewport
+ glViewport(0, 0, reqWidth, reqHeight);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ if (yswap) glOrthof(0, hw_w, hw_h, 0, 0, 1);
+ else glOrthof(0, hw_w, 0, hw_h, 0, 1);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
// redraw the screen entirely...
- glDisable(GL_TEXTURE_EXTERNAL_OES);
- glDisable(GL_TEXTURE_2D);
+ glDisable(GL_SCISSOR_TEST);
glClearColor(0,0,0,1);
glClear(GL_COLOR_BUFFER_BIT);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- const Vector< sp<LayerBase> >& layers(hw->getVisibleLayersSortedByZ());
+ glDisable(GL_TEXTURE_EXTERNAL_OES);
+ glDisable(GL_TEXTURE_2D);
+
+ const LayerVector& layers( mDrawingState.layersSortedByZ );
const size_t count = layers.size();
for (size_t i=0 ; i<count ; ++i) {
- const sp<LayerBase>& layer(layers[i]);
- layer->draw(hw);
+ const sp<Layer>& layer(layers[i]);
+ const Layer::State& state(layer->drawingState());
+ if (state.layerStack == hw->getLayerStack()) {
+ if (state.z >= minLayerZ && state.z <= maxLayerZ) {
+ if (layer->isVisible()) {
+ if (filtering) layer->setFiltering(true);
+ layer->draw(hw);
+ if (filtering) layer->setFiltering(false);
+ }
+ }
+ }
}
+ // compositionComplete is needed for older driver
hw->compositionComplete();
+}
- // back to main framebuffer
- glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
- glDeleteFramebuffersOES(1, &name);
- *textureName = tname;
- *uOut = u;
- *vOut = v;
+status_t SurfaceFlinger::captureScreenImplLocked(
+ const sp<const DisplayDevice>& hw,
+ const sp<IGraphicBufferProducer>& producer,
+ uint32_t reqWidth, uint32_t reqHeight,
+ uint32_t minLayerZ, uint32_t maxLayerZ)
+{
+ ATRACE_CALL();
+
+ // get screen geometry
+ const uint32_t hw_w = hw->getWidth();
+ const uint32_t hw_h = hw->getHeight();
+
+ // if we have secure windows on this display, never allow the screen capture
+ if (hw->getSecureLayerVisible()) {
+ ALOGW("FB is protected: PERMISSION_DENIED");
+ return PERMISSION_DENIED;
+ }
+
+ if ((reqWidth > hw_w) || (reqHeight > hw_h)) {
+ ALOGE("size mismatch (%d, %d) > (%d, %d)",
+ reqWidth, reqHeight, hw_w, hw_h);
+ return BAD_VALUE;
+ }
+
+ reqWidth = (!reqWidth) ? hw_w : reqWidth;
+ reqHeight = (!reqHeight) ? hw_h : reqHeight;
+
+ // Create a surface to render into
+ sp<Surface> surface = new Surface(producer);
+ ANativeWindow* const window = surface.get();
+
+ // set the buffer size to what the user requested
+ native_window_set_buffers_user_dimensions(window, reqWidth, reqHeight);
+
+ // and create the corresponding EGLSurface
+ EGLSurface eglSurface = eglCreateWindowSurface(
+ mEGLDisplay, mEGLConfig, window, NULL);
+ if (eglSurface == EGL_NO_SURFACE) {
+ ALOGE("captureScreenImplLocked: eglCreateWindowSurface() failed 0x%4x",
+ eglGetError());
+ return BAD_VALUE;
+ }
+
+ if (!eglMakeCurrent(mEGLDisplay, eglSurface, eglSurface, mEGLContext)) {
+ ALOGE("captureScreenImplLocked: eglMakeCurrent() failed 0x%4x",
+ eglGetError());
+ eglDestroySurface(mEGLDisplay, eglSurface);
+ return BAD_VALUE;
+ }
+
+ renderScreenImplLocked(hw, reqWidth, reqHeight, minLayerZ, maxLayerZ, false);
+
+ // and finishing things up...
+ if (eglSwapBuffers(mEGLDisplay, eglSurface) != EGL_TRUE) {
+ ALOGE("captureScreenImplLocked: eglSwapBuffers() failed 0x%4x",
+ eglGetError());
+ eglDestroySurface(mEGLDisplay, eglSurface);
+ return BAD_VALUE;
+ }
+
+ eglDestroySurface(mEGLDisplay, eglSurface);
+
return NO_ERROR;
}
-// ---------------------------------------------------------------------------
-status_t SurfaceFlinger::captureScreenImplLocked(const sp<IBinder>& display,
- sp<IMemoryHeap>* heap,
- uint32_t* w, uint32_t* h, PixelFormat* f,
- uint32_t sw, uint32_t sh,
+status_t SurfaceFlinger::captureScreenImplCpuConsumerLocked(
+ const sp<const DisplayDevice>& hw,
+ const sp<IGraphicBufferProducer>& producer,
+ uint32_t reqWidth, uint32_t reqHeight,
uint32_t minLayerZ, uint32_t maxLayerZ)
{
ATRACE_CALL();
- status_t result = PERMISSION_DENIED;
-
if (!GLExtensions::getInstance().haveFramebufferObject()) {
return INVALID_OPERATION;
}
// get screen geometry
- sp<const DisplayDevice> hw(getDisplayDevice(display));
const uint32_t hw_w = hw->getWidth();
const uint32_t hw_h = hw->getHeight();
@@ -2674,28 +2891,22 @@ status_t SurfaceFlinger::captureScreenImplLocked(const sp<IBinder>& display,
return PERMISSION_DENIED;
}
- if ((sw > hw_w) || (sh > hw_h)) {
- ALOGE("size mismatch (%d, %d) > (%d, %d)", sw, sh, hw_w, hw_h);
+ if ((reqWidth > hw_w) || (reqHeight > hw_h)) {
+ ALOGE("size mismatch (%d, %d) > (%d, %d)",
+ reqWidth, reqHeight, hw_w, hw_h);
return BAD_VALUE;
}
- sw = (!sw) ? hw_w : sw;
- sh = (!sh) ? hw_h : sh;
- const size_t size = sw * sh * 4;
- const bool filtering = sw != hw_w || sh != hw_h;
-
-// ALOGD("screenshot: sw=%d, sh=%d, minZ=%d, maxZ=%d",
-// sw, sh, minLayerZ, maxLayerZ);
+ reqWidth = (!reqWidth) ? hw_w : reqWidth;
+ reqHeight = (!reqHeight) ? hw_h : reqHeight;
- // make sure to clear all GL error flags
- while ( glGetError() != GL_NO_ERROR ) ;
-
- // create a FBO
- GLuint name, tname;
+ GLuint tname;
glGenRenderbuffersOES(1, &tname);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, tname);
- glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_RGBA8_OES, sw, sh);
+ glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_RGBA8_OES, reqWidth, reqHeight);
+ // create a FBO
+ GLuint name;
glGenFramebuffersOES(1, &name);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, name);
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
@@ -2703,150 +2914,73 @@ status_t SurfaceFlinger::captureScreenImplLocked(const sp<IBinder>& display,
GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
+ status_t result = NO_ERROR;
if (status == GL_FRAMEBUFFER_COMPLETE_OES) {
- // invert everything, b/c glReadPixel() below will invert the FB
- GLint viewport[4];
- glGetIntegerv(GL_VIEWPORT, viewport);
- glViewport(0, 0, sw, sh);
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
- glOrthof(0, hw_w, hw_h, 0, 0, 1);
- glMatrixMode(GL_MODELVIEW);
-
- // redraw the screen entirely...
- glClearColor(0,0,0,1);
- glClear(GL_COLOR_BUFFER_BIT);
-
- const Vector< sp<LayerBase> >& layers(hw->getVisibleLayersSortedByZ());
- const size_t count = layers.size();
- for (size_t i=0 ; i<count ; ++i) {
- const sp<LayerBase>& layer(layers[i]);
- const uint32_t z = layer->drawingState().z;
- if (z >= minLayerZ && z <= maxLayerZ) {
- if (filtering) layer->setFiltering(true);
- layer->draw(hw);
- if (filtering) layer->setFiltering(false);
- }
- }
-
- // check for errors and return screen capture
- if (glGetError() != GL_NO_ERROR) {
- // error while rendering
- result = INVALID_OPERATION;
- } else {
- // allocate shared memory large enough to hold the
- // screen capture
- sp<MemoryHeapBase> base(
- new MemoryHeapBase(size, 0, "screen-capture") );
- void* const ptr = base->getBase();
- if (ptr != MAP_FAILED) {
- // capture the screen with glReadPixels()
- ScopedTrace _t(ATRACE_TAG, "glReadPixels");
- glReadPixels(0, 0, sw, sh, GL_RGBA, GL_UNSIGNED_BYTE, ptr);
- if (glGetError() == GL_NO_ERROR) {
- *heap = base;
- *w = sw;
- *h = sh;
- *f = PIXEL_FORMAT_RGBA_8888;
- result = NO_ERROR;
+ renderScreenImplLocked(hw, reqWidth, reqHeight, minLayerZ, maxLayerZ, true);
+
+ // Below we render the screenshot into the
+ // CpuConsumer using glReadPixels from our FBO.
+ // Some older drivers don't support the GL->CPU path so we
+ // have to wrap it with a CPU->CPU path, which is what
+ // glReadPixels essentially is.
+
+ sp<Surface> sur = new Surface(producer);
+ ANativeWindow* window = sur.get();
+
+ if (native_window_api_connect(window, NATIVE_WINDOW_API_CPU) == NO_ERROR) {
+ int err = 0;
+ err = native_window_set_buffers_dimensions(window, reqWidth, reqHeight);
+ err |= native_window_set_buffers_format(window, HAL_PIXEL_FORMAT_RGBA_8888);
+ err |= native_window_set_usage(window,
+ GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
+
+ if (err == NO_ERROR) {
+ ANativeWindowBuffer* buffer;
+ if (native_window_dequeue_buffer_and_wait(window, &buffer) == NO_ERROR) {
+ sp<GraphicBuffer> buf = static_cast<GraphicBuffer*>(buffer);
+ void* vaddr;
+ if (buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, &vaddr) == NO_ERROR) {
+ glReadPixels(0, 0, buffer->stride, reqHeight,
+ GL_RGBA, GL_UNSIGNED_BYTE, vaddr);
+ buf->unlock();
+ }
+ window->queueBuffer(window, buffer, -1);
}
- } else {
- result = NO_MEMORY;
}
+ native_window_api_disconnect(window, NATIVE_WINDOW_API_CPU);
}
- glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
+
} else {
- result = BAD_VALUE;
+ ALOGE("got GL_FRAMEBUFFER_COMPLETE_OES while taking screenshot");
+ result = INVALID_OPERATION;
}
- // release FBO resources
+ // back to main framebuffer
glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
glDeleteRenderbuffersOES(1, &tname);
glDeleteFramebuffersOES(1, &name);
- hw->compositionComplete();
-
-// ALOGD("screenshot: result = %s", result<0 ? strerror(result) : "OK");
+ DisplayDevice::setViewportAndProjection(hw);
return result;
}
-
-status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
- sp<IMemoryHeap>* heap,
- uint32_t* width, uint32_t* height, PixelFormat* format,
- uint32_t sw, uint32_t sh,
- uint32_t minLayerZ, uint32_t maxLayerZ)
-{
- if (CC_UNLIKELY(display == 0))
- return BAD_VALUE;
-
- if (!GLExtensions::getInstance().haveFramebufferObject())
- return INVALID_OPERATION;
-
- class MessageCaptureScreen : public MessageBase {
- SurfaceFlinger* flinger;
- sp<IBinder> display;
- sp<IMemoryHeap>* heap;
- uint32_t* w;
- uint32_t* h;
- PixelFormat* f;
- uint32_t sw;
- uint32_t sh;
- uint32_t minLayerZ;
- uint32_t maxLayerZ;
- status_t result;
- public:
- MessageCaptureScreen(SurfaceFlinger* flinger, const sp<IBinder>& display,
- sp<IMemoryHeap>* heap, uint32_t* w, uint32_t* h, PixelFormat* f,
- uint32_t sw, uint32_t sh,
- uint32_t minLayerZ, uint32_t maxLayerZ)
- : flinger(flinger), display(display),
- heap(heap), w(w), h(h), f(f), sw(sw), sh(sh),
- minLayerZ(minLayerZ), maxLayerZ(maxLayerZ),
- result(PERMISSION_DENIED)
- {
- }
- status_t getResult() const {
- return result;
- }
- virtual bool handler() {
- Mutex::Autolock _l(flinger->mStateLock);
- result = flinger->captureScreenImplLocked(display,
- heap, w, h, f, sw, sh, minLayerZ, maxLayerZ);
- return true;
- }
- };
-
- sp<MessageBase> msg = new MessageCaptureScreen(this,
- display, heap, width, height, format, sw, sh, minLayerZ, maxLayerZ);
- status_t res = postMessageSync(msg);
- if (res == NO_ERROR) {
- res = static_cast<MessageCaptureScreen*>( msg.get() )->getResult();
- }
- return res;
-}
-
// ---------------------------------------------------------------------------
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;
@@ -2868,7 +3002,7 @@ SurfaceFlinger::DisplayDeviceState::DisplayDeviceState()
}
SurfaceFlinger::DisplayDeviceState::DisplayDeviceState(DisplayDevice::DisplayType type)
- : type(type), layerStack(0), orientation(0) {
+ : type(type), layerStack(DisplayDevice::NO_LAYER_STACK), orientation(0) {
viewport.makeInvalid();
frame.makeInvalid();
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 1b549e4..739099c 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -45,8 +45,9 @@
#include <private/gui/LayerState.h>
#include "Barrier.h"
-#include "MessageQueue.h"
#include "DisplayDevice.h"
+#include "FrameTracker.h"
+#include "MessageQueue.h"
#include "DisplayHardware/HWComposer.h"
@@ -59,11 +60,8 @@ class DisplayEventConnection;
class EventThread;
class IGraphicBufferAlloc;
class Layer;
-class LayerBase;
-class LayerBaseClient;
class LayerDim;
-class LayerScreenshot;
-class SurfaceTextureClient;
+class Surface;
// ---------------------------------------------------------------------------
@@ -102,14 +100,6 @@ public:
// force full composition on all displays
void repaintEverything();
- // renders content on given display to a texture. thread-safe version.
- status_t renderScreenToTexture(uint32_t layerStack, GLuint* textureName,
- GLfloat* uOut, GLfloat* vOut);
-
- // renders content on given display to a texture, w/o acquiring main lock
- status_t renderScreenToTextureLocked(uint32_t layerStack, GLuint* textureName,
- GLfloat* uOut, GLfloat* vOut);
-
// returns the default Display
sp<const DisplayDevice> getDefaultDisplayDevice() const {
return getDisplayDevice(mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY]);
@@ -118,9 +108,6 @@ public:
// utility function to delete a texture on the main thread
void deleteTextureAsync(GLuint texture);
- // allocate a h/w composer display id
- int32_t allocateHwcDisplayId(DisplayDevice::DisplayType type);
-
// enable/disable h/w composer event
// TODO: this should be made accessible only to EventThread
void eventControl(int disp, int event, int enabled);
@@ -132,15 +119,13 @@ 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 id);
private:
friend class Client;
friend class DisplayEventConnection;
- friend class LayerBase;
- friend class LayerBaseClient;
friend class Layer;
- friend class LayerScreenshot;
+ friend class SurfaceTextureLayer;
// We're reference counted, never destroy SurfaceFlinger directly
virtual ~SurfaceFlinger();
@@ -149,7 +134,7 @@ private:
* Internal data structures
*/
- class LayerVector : public SortedVector<sp<LayerBase> > {
+ class LayerVector : public SortedVector< sp<Layer> > {
public:
LayerVector();
LayerVector(const LayerVector& rhs);
@@ -163,7 +148,7 @@ private:
bool isMainDisplay() const { return type == DisplayDevice::DISPLAY_PRIMARY; }
bool isVirtualDisplay() const { return type >= DisplayDevice::DISPLAY_VIRTUAL; }
DisplayDevice::DisplayType type;
- sp<ISurfaceTexture> surface;
+ sp<IGraphicBufferProducer> surface;
uint32_t layerStack;
Rect viewport;
Rect frame;
@@ -195,12 +180,12 @@ private:
const Vector<DisplayState>& displays, uint32_t flags);
virtual void bootFinished();
virtual bool authenticateSurfaceTexture(
- const sp<ISurfaceTexture>& surface) const;
+ const sp<IGraphicBufferProducer>& bufferProducer) const;
virtual sp<IDisplayEventConnection> createDisplayEventConnection();
- virtual status_t captureScreen(const sp<IBinder>& display, sp<IMemoryHeap>* heap,
- uint32_t* width, uint32_t* height, PixelFormat* format,
- uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ,
- uint32_t maxLayerZ);
+ virtual status_t captureScreen(const sp<IBinder>& display,
+ const sp<IGraphicBufferProducer>& producer,
+ uint32_t reqWidth, uint32_t reqHeight,
+ uint32_t minLayerZ, uint32_t maxLayerZ, bool isCpuConsumer);
// called when screen needs to turn off
virtual void blank(const sp<IBinder>& display);
// called when screen is turning back on
@@ -266,39 +251,36 @@ private:
/* ------------------------------------------------------------------------
* Layer management
*/
- sp<ISurface> createLayer(ISurfaceComposerClient::surface_data_t* params,
- const String8& name, const sp<Client>& client,
- uint32_t w, uint32_t h, PixelFormat format, uint32_t flags);
-
- sp<Layer> createNormalLayer(const sp<Client>& client,
- uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format);
+ status_t createLayer(const String8& name, const sp<Client>& client,
+ uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
+ sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp);
- sp<LayerDim> createDimLayer(const sp<Client>& client,
- uint32_t w, uint32_t h, uint32_t flags);
+ status_t createNormalLayer(const sp<Client>& client, const String8& name,
+ uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format,
+ sp<IBinder>* outHandle, sp<IGraphicBufferProducer>* outGbp,
+ sp<Layer>* outLayer);
- sp<LayerScreenshot> createScreenshotLayer(const sp<Client>& client,
- uint32_t w, uint32_t h, uint32_t flags);
+ status_t createDimLayer(const sp<Client>& client, const String8& name,
+ uint32_t w, uint32_t h, uint32_t flags, sp<IBinder>* outHandle,
+ sp<IGraphicBufferProducer>* outGbp, sp<Layer>* outLayer);
// called in response to the window-manager calling
// ISurfaceComposerClient::destroySurface()
- // The specified layer is first placed in a purgatory list
- // until all references from the client are released.
- status_t onLayerRemoved(const sp<Client>& client, SurfaceID sid);
+ status_t onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle);
// 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
- ssize_t addClientLayer(const sp<Client>& client,
- const sp<LayerBaseClient>& lbc);
-
- status_t removeLayer_l(const sp<LayerBase>& layer);
- status_t purgatorizeLayer_l(const sp<LayerBase>& layer);
+ void addClientLayer(const sp<Client>& client,
+ const sp<IBinder>& handle,
+ const sp<IGraphicBufferProducer>& gbc,
+ const sp<Layer>& lbc);
/* ------------------------------------------------------------------------
* Boot animation, on/off animations and screen capture
@@ -306,10 +288,24 @@ private:
void startBootAnim();
- status_t captureScreenImplLocked(const sp<IBinder>& display, sp<IMemoryHeap>* heap,
- uint32_t* width, uint32_t* height, PixelFormat* format,
- uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ,
- uint32_t maxLayerZ);
+ void renderScreenImplLocked(
+ const sp<const DisplayDevice>& hw,
+ uint32_t reqWidth, uint32_t reqHeight,
+ uint32_t minLayerZ, uint32_t maxLayerZ,
+ bool yswap);
+
+ status_t captureScreenImplLocked(
+ const sp<const DisplayDevice>& hw,
+ const sp<IGraphicBufferProducer>& producer,
+ uint32_t reqWidth, uint32_t reqHeight,
+ uint32_t minLayerZ, uint32_t maxLayerZ);
+
+ status_t captureScreenImplCpuConsumerLocked(
+ const sp<const DisplayDevice>& hw,
+ const sp<IGraphicBufferProducer>& producer,
+ uint32_t reqWidth, uint32_t reqHeight,
+ uint32_t minLayerZ, uint32_t maxLayerZ);
+
/* ------------------------------------------------------------------------
* EGL
@@ -345,6 +341,9 @@ private:
// region of all screens presenting this layer stack.
void invalidateLayerStack(uint32_t layerStack, const Region& dirty);
+ // allocate a h/w composer display id
+ int32_t allocateHwcDisplayId(DisplayDevice::DisplayType type);
+
/* ------------------------------------------------------------------------
* H/W composer
*/
@@ -390,7 +389,7 @@ private:
void dumpStatsLocked(const Vector<String16>& args, size_t& index,
String8& result, char* buffer, size_t SIZE) const;
void clearStatsLocked(const Vector<String16>& args, size_t& index,
- String8& result, char* buffer, size_t SIZE) const;
+ String8& result, char* buffer, size_t SIZE);
void dumpAllLocked(String8& result, char* buffer, size_t SIZE) const;
bool startDdmConnection();
static void appendSfConfigString(String8& result);
@@ -404,10 +403,10 @@ private:
State mCurrentState;
volatile int32_t mTransactionFlags;
Condition mTransactionCV;
- SortedVector<sp<LayerBase> > mLayerPurgatory;
bool mTransactionPending;
bool mAnimTransactionPending;
- Vector<sp<LayerBase> > mLayersPendingRemoval;
+ Vector< sp<Layer> > mLayersPendingRemoval;
+ SortedVector< wp<IBinder> > mGraphicBufferProducerList;
// protected by mStateLock (but we could use another lock)
bool mLayersRemoved;
@@ -419,12 +418,14 @@ private:
HWComposer* mHwc;
GLuint mProtectedTexName;
nsecs_t mBootTime;
+ bool mGpuToCpuSupported;
sp<EventThread> mEventThread;
GLint mMaxViewportDims[2];
GLint mMaxTextureSize;
EGLContext mEGLContext;
EGLConfig mEGLConfig;
EGLDisplay mEGLDisplay;
+ EGLint mEGLNativeVisualId;
sp<IBinder> mBuiltinDisplays[DisplayDevice::NUM_DISPLAY_TYPES];
// Can only accessed from the main thread, these members
@@ -432,6 +433,7 @@ private:
State mDrawingState;
bool mVisibleRegionsDirty;
bool mHwWorkListDirty;
+ bool mAnimCompositionPending;
// this may only be written from the main thread with mStateLock held
// it may be read from other threads with mStateLock held
@@ -451,10 +453,11 @@ private:
// these are thread safe
mutable MessageQueue mEventQueue;
mutable Barrier mReadyToRunBarrier;
+ FrameTracker mAnimFrameTracker;
// protected by mDestroyedLayerLock;
mutable Mutex mDestroyedLayerLock;
- Vector<LayerBase const *> mDestroyedLayers;
+ Vector<Layer const *> mDestroyedLayers;
/* ------------------------------------------------------------------------
* Feature prototyping
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.cpp b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
new file mode 100644
index 0000000..2869250
--- /dev/null
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+//#define LOG_NDEBUG 0
+
+#include "SurfaceFlingerConsumer.h"
+
+#include <private/gui/SyncFeatures.h>
+
+#include <utils/Trace.h>
+#include <utils/Errors.h>
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+status_t SurfaceFlingerConsumer::updateTexImage(BufferRejecter* rejecter)
+{
+ ATRACE_CALL();
+ ALOGV("updateTexImage");
+ Mutex::Autolock lock(mMutex);
+
+ if (mAbandoned) {
+ ALOGE("updateTexImage: GLConsumer is abandoned!");
+ return NO_INIT;
+ }
+
+ // Make sure the EGL state is the same as in previous calls.
+ status_t err = checkAndUpdateEglStateLocked();
+ if (err != NO_ERROR) {
+ return err;
+ }
+
+ BufferQueue::BufferItem item;
+
+ // Acquire the next buffer.
+ // In asynchronous mode the list is guaranteed to be one buffer
+ // deep, while in synchronous mode we use the oldest buffer.
+ err = acquireBufferLocked(&item);
+ if (err != NO_ERROR) {
+ if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
+ // This variant of updateTexImage does not guarantee that the
+ // texture is bound, so no need to call glBindTexture.
+ err = NO_ERROR;
+ } else {
+ ALOGE("updateTexImage: acquire failed: %s (%d)",
+ strerror(-err), err);
+ }
+ return err;
+ }
+
+
+ // We call the rejecter here, in case the caller has a reason to
+ // not accept this buffer. This is used by SurfaceFlinger to
+ // reject buffers which have the wrong size
+ int buf = item.mBuf;
+ if (rejecter && rejecter->reject(mSlots[buf].mGraphicBuffer, item)) {
+ releaseBufferLocked(buf, EGL_NO_SYNC_KHR);
+ return NO_ERROR;
+ }
+
+ // Release the previous buffer.
+ err = releaseAndUpdateLocked(item);
+ if (err != NO_ERROR) {
+ return err;
+ }
+
+ if (!SyncFeatures::getInstance().useNativeFenceSync()) {
+ // Bind the new buffer to the GL texture.
+ //
+ // Older devices require the "implicit" synchronization provided
+ // by glEGLImageTargetTexture2DOES, which this method calls. Newer
+ // devices will either call this in Layer::onDraw, or (if it's not
+ // a GL-composited layer) not at all.
+ err = bindTextureImageLocked();
+ }
+
+ return err;
+}
+
+status_t SurfaceFlingerConsumer::bindTextureImage()
+{
+ Mutex::Autolock lock(mMutex);
+
+ return bindTextureImageLocked();
+}
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.h b/services/surfaceflinger/SurfaceFlingerConsumer.h
new file mode 100644
index 0000000..22eec81
--- /dev/null
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SURFACEFLINGERCONSUMER_H
+#define ANDROID_SURFACEFLINGERCONSUMER_H
+
+#include <gui/GLConsumer.h>
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+/*
+ * This is a thin wrapper around GLConsumer.
+ */
+class SurfaceFlingerConsumer : public GLConsumer {
+public:
+ SurfaceFlingerConsumer(GLuint tex, bool allowSynchronousMode = true,
+ GLenum texTarget = GL_TEXTURE_EXTERNAL_OES, bool useFenceSync = true,
+ const sp<BufferQueue> &bufferQueue = 0)
+ : GLConsumer(tex, allowSynchronousMode, texTarget, useFenceSync,
+ bufferQueue)
+ {}
+
+ class BufferRejecter {
+ friend class SurfaceFlingerConsumer;
+ virtual bool reject(const sp<GraphicBuffer>& buf,
+ const BufferQueue::BufferItem& item) = 0;
+
+ protected:
+ virtual ~BufferRejecter() { }
+ };
+
+ // This version of updateTexImage() takes a functor that may be used to
+ // reject the newly acquired buffer. Unlike the GLConsumer version,
+ // this does not guarantee that the buffer has been bound to the GL
+ // texture.
+ status_t updateTexImage(BufferRejecter* rejecter);
+
+ // See GLConsumer::bindTextureImageLocked().
+ status_t bindTextureImage();
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_SURFACEFLINGERCONSUMER_H
diff --git a/services/surfaceflinger/SurfaceTextureLayer.cpp b/services/surfaceflinger/SurfaceTextureLayer.cpp
index 0b638b4..d0f0dae 100644
--- a/services/surfaceflinger/SurfaceTextureLayer.cpp
+++ b/services/surfaceflinger/SurfaceTextureLayer.cpp
@@ -20,18 +20,35 @@
#include <utils/Errors.h>
-#include "Layer.h"
+#include "SurfaceFlinger.h"
#include "SurfaceTextureLayer.h"
namespace android {
// ---------------------------------------------------------------------------
-SurfaceTextureLayer::SurfaceTextureLayer()
- : BufferQueue(true) {
+SurfaceTextureLayer::SurfaceTextureLayer(const sp<SurfaceFlinger>& flinger)
+ : BufferQueue(true), flinger(flinger) {
}
SurfaceTextureLayer::~SurfaceTextureLayer() {
+ // remove ourselves from SurfaceFlinger's list. We do this asynchronously
+ // because we don't know where this dtor is called from, it could be
+ // called with the mStateLock held, leading to a dead-lock (it actually
+ // happens).
+ class MessageCleanUpList : public MessageBase {
+ sp<SurfaceFlinger> flinger;
+ wp<IBinder> gbp;
+ public:
+ MessageCleanUpList(const sp<SurfaceFlinger>& flinger, const wp<IBinder>& gbp)
+ : flinger(flinger), gbp(gbp) { }
+ virtual bool handler() {
+ Mutex::Autolock _l(flinger->mStateLock);
+ flinger->mGraphicBufferProducerList.remove(gbp);
+ return true;
+ }
+ };
+ flinger->postMessageAsync( new MessageCleanUpList(flinger, this) );
}
status_t SurfaceTextureLayer::connect(int api, QueueBufferOutput* output) {
diff --git a/services/surfaceflinger/SurfaceTextureLayer.h b/services/surfaceflinger/SurfaceTextureLayer.h
index e892ea0..13cff2f 100644
--- a/services/surfaceflinger/SurfaceTextureLayer.h
+++ b/services/surfaceflinger/SurfaceTextureLayer.h
@@ -28,15 +28,19 @@ namespace android {
// ---------------------------------------------------------------------------
class Layer;
+class SurfaceFlinger;
-// SurfaceTextureLayer is now a BufferQueue since SurfaceTexture has been
-// refactored
-class SurfaceTextureLayer : public BufferQueue
-{
+/*
+ * This is a thin wrapper around BufferQueue, used by the Layer class.
+ */
+class SurfaceTextureLayer : public BufferQueue {
+ sp<SurfaceFlinger> flinger;
public:
- SurfaceTextureLayer();
- ~SurfaceTextureLayer();
+ SurfaceTextureLayer(const sp<SurfaceFlinger>& flinger);
+ virtual ~SurfaceTextureLayer();
+ // After calling the superclass connect(), set or clear synchronous
+ // mode appropriately for the specified API.
virtual status_t connect(int api, QueueBufferOutput* output);
};
diff --git a/services/surfaceflinger/Transform.cpp b/services/surfaceflinger/Transform.cpp
index aca90e0..315720e 100644
--- a/services/surfaceflinger/Transform.cpp
+++ b/services/surfaceflinger/Transform.cpp
@@ -298,6 +298,44 @@ uint32_t Transform::type() const
return mType;
}
+Transform Transform::inverse() const {
+ // our 3x3 matrix is always of the form of a 2x2 transformation
+ // followed by a translation: T*M, therefore:
+ // (T*M)^-1 = M^-1 * T^-1
+ Transform result;
+ if (mType <= TRANSLATE) {
+ // 1 0 x
+ // 0 1 y
+ // 0 0 1
+ result = *this;
+ result.mMatrix[2][0] = -result.mMatrix[2][0];
+ result.mMatrix[2][1] = -result.mMatrix[2][1];
+ } else {
+ // a c x
+ // b d y
+ // 0 0 1
+ const mat33& M(mMatrix);
+ const float a = M[0][0];
+ const float b = M[1][0];
+ const float c = M[0][1];
+ const float d = M[1][1];
+ const float x = M[2][0];
+ const float y = M[2][1];
+
+ Transform R, T;
+ const float idet = 1.0 / (a*d - b*c);
+ R.mMatrix[0][0] = d*idet; R.mMatrix[0][1] = -c*idet;
+ R.mMatrix[1][0] = -b*idet; R.mMatrix[1][1] = a*idet;
+ R.mType = mType &= ~TRANSLATE;
+
+ T.mMatrix[2][0] = -x;
+ T.mMatrix[2][1] = -y;
+ T.mType = TRANSLATE;
+ result = R * T;
+ }
+ return result;
+}
+
uint32_t Transform::getType() const {
return type() & 0xFF;
}
diff --git a/services/surfaceflinger/Transform.h b/services/surfaceflinger/Transform.h
index 4fe261a..c4efade 100644
--- a/services/surfaceflinger/Transform.h
+++ b/services/surfaceflinger/Transform.h
@@ -80,6 +80,8 @@ public:
Rect transform(const Rect& bounds) const;
Transform operator * (const Transform& rhs) const;
+ Transform inverse() const;
+
// for debugging
void dump(const char* name) const;
diff --git a/services/surfaceflinger/clz.cpp b/services/surfaceflinger/clz.cpp
deleted file mode 100644
index 2456b86..0000000
--- a/services/surfaceflinger/clz.cpp
+++ /dev/null
@@ -1,37 +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 "clz.h"
-
-namespace android {
-
-int clz_impl(int32_t x)
-{
-#if defined(__arm__) && !defined(__thumb__)
- return __builtin_clz(x);
-#else
- if (!x) return 32;
- int e = 31;
- if (x&0xFFFF0000) { e -=16; x >>=16; }
- if (x&0x0000FF00) { e -= 8; x >>= 8; }
- if (x&0x000000F0) { e -= 4; x >>= 4; }
- if (x&0x0000000C) { e -= 2; x >>= 2; }
- if (x&0x00000002) { e -= 1; }
- return e;
-#endif
-}
-
-}; // namespace android
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 0592c5b..4d363c8 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -31,14 +31,14 @@ namespace android {
// Fill an RGBA_8888 formatted surface with a single color.
static void fillSurfaceRGBA8(const sp<SurfaceControl>& sc,
uint8_t r, uint8_t g, uint8_t b) {
- Surface::SurfaceInfo info;
+ ANativeWindow_Buffer outBuffer;
sp<Surface> s = sc->getSurface();
ASSERT_TRUE(s != NULL);
- ASSERT_EQ(NO_ERROR, s->lock(&info));
- uint8_t* img = reinterpret_cast<uint8_t*>(info.bits);
- for (uint32_t y = 0; y < info.h; y++) {
- for (uint32_t x = 0; x < info.w; x++) {
- uint8_t* pixel = img + (4 * (y*info.s + x));
+ ASSERT_EQ(NO_ERROR, s->lock(&outBuffer, NULL));
+ uint8_t* img = reinterpret_cast<uint8_t*>(outBuffer.bits);
+ for (uint32_t y = 0; y < outBuffer.height; y++) {
+ for (uint32_t x = 0; x < outBuffer.width; x++) {
+ uint8_t* pixel = img + (4 * (y*outBuffer.stride + x));
pixel[0] = r;
pixel[1] = g;
pixel[2] = b;
diff --git a/services/surfaceflinger/tests/resize/resize.cpp b/services/surfaceflinger/tests/resize/resize.cpp
index d61ea70..8b051e8 100644
--- a/services/surfaceflinger/tests/resize/resize.cpp
+++ b/services/surfaceflinger/tests/resize/resize.cpp
@@ -38,26 +38,27 @@ int main(int argc, char** argv)
// create a client to surfaceflinger
sp<SurfaceComposerClient> client = new SurfaceComposerClient();
- sp<Surface> surface = client->createSurface(String8("resize"),
+ sp<SurfaceControl> surfaceControl = client->createSurface(String8("resize"),
160, 240, PIXEL_FORMAT_RGB_565, 0);
+ sp<Surface> surface = surfaceControl->getSurface();
SurfaceComposerClient::openGlobalTransaction();
- surface->setLayer(100000);
+ surfaceControl->setLayer(100000);
SurfaceComposerClient::closeGlobalTransaction();
- Surface::SurfaceInfo info;
- surface->lock(&info);
- ssize_t bpr = info.s * bytesPerPixel(info.format);
- android_memset16((uint16_t*)info.bits, 0xF800, bpr*info.h);
+ ANativeWindow_Buffer outBuffer;
+ surface->lock(&outBuffer, NULL);
+ ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
+ android_memset16((uint16_t*)outBuffer.bits, 0xF800, bpr*outBuffer.height);
surface->unlockAndPost();
- surface->lock(&info);
- android_memset16((uint16_t*)info.bits, 0x07E0, bpr*info.h);
+ surface->lock(&outBuffer);
+ android_memset16((uint16_t*)outBuffer.bits, 0x07E0, bpr*outBuffer.height);
surface->unlockAndPost();
SurfaceComposerClient::openGlobalTransaction();
- surface->setSize(320, 240);
+ surfaceControl->setSize(320, 240);
SurfaceComposerClient::closeGlobalTransaction();
diff --git a/services/surfaceflinger/tests/surface/Android.mk b/services/surfaceflinger/tests/surface/Android.mk
deleted file mode 100644
index c59060e..0000000
--- a/services/surfaceflinger/tests/surface/Android.mk
+++ /dev/null
@@ -1,18 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- surface.cpp
-
-LOCAL_SHARED_LIBRARIES := \
- libcutils \
- libutils \
- libbinder \
- libui \
- libgui
-
-LOCAL_MODULE:= test-surface
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_EXECUTABLE)
diff --git a/services/surfaceflinger/tests/surface/surface.cpp b/services/surfaceflinger/tests/surface/surface.cpp
deleted file mode 100644
index 9c41cc3..0000000
--- a/services/surfaceflinger/tests/surface/surface.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2010 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 <cutils/memory.h>
-
-#include <utils/Log.h>
-
-#include <binder/IPCThreadState.h>
-#include <binder/ProcessState.h>
-#include <binder/IServiceManager.h>
-
-#include <gui/Surface.h>
-#include <gui/SurfaceComposerClient.h>
-
-using namespace android;
-
-int main(int argc, char** argv)
-{
- // set up the thread-pool
- sp<ProcessState> proc(ProcessState::self());
- ProcessState::self()->startThreadPool();
-
- // create a client to surfaceflinger
- sp<SurfaceComposerClient> client = new SurfaceComposerClient();
-
- sp<SurfaceControl> surfaceControl = client->createSurface(
- String8("surface"), 160, 240, PIXEL_FORMAT_RGB_565, 0);
- SurfaceComposerClient::openGlobalTransaction();
- surfaceControl->setLayer(100000);
- SurfaceComposerClient::closeGlobalTransaction();
-
- // pretend it went cross-process
- Parcel parcel;
- SurfaceControl::writeSurfaceToParcel(surfaceControl, &parcel);
- parcel.setDataPosition(0);
- sp<Surface> surface = Surface::readFromParcel(parcel);
- ANativeWindow* window = surface.get();
-
- printf("window=%p\n", window);
-
- int err = native_window_set_buffer_count(window, 8);
- ANativeWindowBuffer* buffer;
-
- for (int i=0 ; i<8 ; i++) {
- window->dequeueBuffer(window, &buffer);
- printf("buffer %d: %p\n", i, buffer);
- }
-
- printf("test complete. CTRL+C to finish.\n");
-
- IPCThreadState::self()->joinThreadPool();
- return 0;
-}