summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/utils/KeyedVector.h16
-rw-r--r--services/surfaceflinger/DisplayDevice.cpp57
-rw-r--r--services/surfaceflinger/DisplayDevice.h20
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp113
-rw-r--r--services/surfaceflinger/SurfaceFlinger.h29
5 files changed, 172 insertions, 63 deletions
diff --git a/include/utils/KeyedVector.h b/include/utils/KeyedVector.h
index 20575ee..47c2c56 100644
--- a/include/utils/KeyedVector.h
+++ b/include/utils/KeyedVector.h
@@ -56,7 +56,10 @@ public:
inline size_t capacity() const { return mVector.capacity(); }
//! setst the capacity. capacity can never be reduced less than size()
inline ssize_t setCapacity(size_t size) { return mVector.setCapacity(size); }
-
+
+ // returns true if the arguments is known to be identical to this vector
+ inline bool isIdenticalTo(const KeyedVector& rhs) const;
+
/*!
* accessors
*/
@@ -64,6 +67,7 @@ public:
const VALUE& valueAt(size_t index) const;
const KEY& keyAt(size_t index) const;
ssize_t indexOfKey(const KEY& key) const;
+ const VALUE& operator[] (size_t index) const;
/*!
* modifying the array
@@ -123,6 +127,11 @@ KeyedVector<KEY,VALUE>::KeyedVector()
}
template<typename KEY, typename VALUE> inline
+bool KeyedVector<KEY,VALUE>::isIdenticalTo(const KeyedVector<KEY,VALUE>& rhs) const {
+ return mVector.array() == rhs.mVector.array();
+}
+
+template<typename KEY, typename VALUE> inline
ssize_t KeyedVector<KEY,VALUE>::indexOfKey(const KEY& key) const {
return mVector.indexOf( key_value_pair_t<KEY,VALUE>(key) );
}
@@ -140,6 +149,11 @@ const VALUE& KeyedVector<KEY,VALUE>::valueAt(size_t index) const {
}
template<typename KEY, typename VALUE> inline
+const VALUE& KeyedVector<KEY,VALUE>::operator[] (size_t index) const {
+ return valueAt(index);
+}
+
+template<typename KEY, typename VALUE> inline
const KEY& KeyedVector<KEY,VALUE>::keyAt(size_t index) const {
return mVector.itemAt(index).key;
}
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index b09b77c..a33b94b 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -97,33 +97,55 @@ void checkEGLErrors(const char* token)
*
*/
+DisplayDevice::DisplayDevice()
+ : mId(0),
+ mDisplay(EGL_NO_DISPLAY),
+ mSurface(EGL_NO_SURFACE),
+ mContext(EGL_NO_CONTEXT)
+{
+}
+
DisplayDevice::DisplayDevice(
const sp<SurfaceFlinger>& flinger,
int display,
const sp<SurfaceTextureClient>& surface,
EGLConfig config)
- : mFlinger(flinger),
- mDisplayId(display),
- mNativeWindow(surface),
- mDisplay(EGL_NO_DISPLAY),
- mSurface(EGL_NO_SURFACE),
- mContext(EGL_NO_CONTEXT),
- mDpiX(), mDpiY(),
- mRefreshRate(),
- mDensity(),
- mDisplayWidth(), mDisplayHeight(), mFormat(),
- mFlags(),
- mPageFlipCount(),
- mRefreshPeriod(),
- mSecureLayerVisible(false),
- mScreenAcquired(false),
- mOrientation(),
- mLayerStack(0)
+ : mFlinger(flinger),
+ mId(display),
+ mNativeWindow(surface),
+ mDisplay(EGL_NO_DISPLAY),
+ mSurface(EGL_NO_SURFACE),
+ mContext(EGL_NO_CONTEXT),
+ mDpiX(), mDpiY(),
+ mRefreshRate(),
+ mDensity(),
+ mDisplayWidth(), mDisplayHeight(), mFormat(),
+ mFlags(),
+ mPageFlipCount(),
+ mRefreshPeriod(),
+ mSecureLayerVisible(false),
+ mScreenAcquired(false),
+ mOrientation(),
+ mLayerStack(0)
{
init(config);
}
DisplayDevice::~DisplayDevice() {
+ // DO NOT call terminate() from here, because we create
+ // temporaries of this class (on the stack typically), and we don't
+ // want to destroy the EGLSurface in that case
+}
+
+void DisplayDevice::terminate() {
+ if (mSurface != EGL_NO_SURFACE) {
+ eglDestroySurface(mDisplay, mSurface);
+ mSurface = EGL_NO_SURFACE;
+ }
+}
+
+bool DisplayDevice::isValid() const {
+ return mFlinger != NULL;
}
float DisplayDevice::getDpiX() const {
@@ -389,5 +411,6 @@ status_t DisplayDevice::setOrientation(int orientation) {
h = tmp;
}
mOrientation = orientation;
+ dirtyRegion.set(bounds());
return NO_ERROR;
}
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index e1c2d11..96590a0 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -49,10 +49,17 @@ public:
Region undefinedRegion;
enum {
+ DISPLAY_ID_MAIN = 0,
+ DISPLAY_ID_HDMI = 1
+ };
+
+ enum {
PARTIAL_UPDATES = 0x00020000, // video driver feature
SWAP_RECTANGLE = 0x00080000,
};
+ DisplayDevice();
+
DisplayDevice(
const sp<SurfaceFlinger>& flinger,
int dpy,
@@ -61,6 +68,14 @@ public:
~DisplayDevice();
+ // must be called when this object is no longer needed. this will
+ // render the associated EGLSurface invalid.
+ void terminate();
+
+ // whether this is a valid object. An invalid DisplayDevice is returned
+ // when an non existing id is requested
+ bool isValid() const;
+
// Flip the front and back buffers if the back buffer is "dirty". Might
// be instantaneous, might involve copying the frame buffer around.
void flip(const Region& dirty) const;
@@ -110,6 +125,9 @@ public:
uint32_t getPageFlipCount() const;
void dump(String8& res) const;
+ inline bool operator < (const DisplayDevice& rhs) const {
+ return mId < rhs.mId;
+ }
private:
void init(EGLConfig config);
@@ -118,7 +136,7 @@ private:
* Constants, set during initialization
*/
sp<SurfaceFlinger> mFlinger;
- int mDisplayId;
+ int32_t mId;
// ANativeWindow this display is rendering into
sp<SurfaceTextureClient> mNativeWindow;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 7fb825a..f25eb5f 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -370,11 +370,12 @@ status_t SurfaceFlinger::readyToRun()
mEGLContext = createGLContext(mEGLDisplay, mEGLConfig);
// initialize our main display hardware
- DisplayDevice* const hw = new DisplayDevice(this, 0, anw, mEGLConfig);
- mDisplayDevices[0] = hw;
+ mCurrentState.displays.add(DisplayDevice::DISPLAY_ID_MAIN, DisplayDeviceState());
+ DisplayDevice hw(this, DisplayDevice::DISPLAY_ID_MAIN, anw, mEGLConfig);
+ mDisplays.add(DisplayDevice::DISPLAY_ID_MAIN, hw);
// initialize OpenGL ES
- EGLSurface surface = hw->getEGLSurface();
+ EGLSurface surface = hw.getEGLSurface();
initializeGL(mEGLDisplay, surface);
// start the EventThread
@@ -384,7 +385,10 @@ status_t SurfaceFlinger::readyToRun()
// initialize the H/W composer
mHwc = new HWComposer(this,
*static_cast<HWComposer::EventHandler *>(this),
- hw->getRefreshPeriod());
+ hw.getRefreshPeriod());
+
+ // initialize our drawing state
+ mDrawingState = mCurrentState;
// We're now ready to accept clients...
mReadyToRunBarrier.open();
@@ -585,9 +589,8 @@ void SurfaceFlinger::handleMessageRefresh() {
*/
const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
- for (int dpy=0 ; dpy<1 ; dpy++) { // TODO: iterate through all displays
- DisplayDevice& hw(const_cast<DisplayDevice&>(getDisplayDevice(dpy)));
-
+ for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
+ DisplayDevice& hw(mDisplays.editValueAt(dpy));
Region opaqueRegion;
Region dirtyRegion;
computeVisibleRegions(currentLayers,
@@ -615,8 +618,8 @@ void SurfaceFlinger::handleMessageRefresh() {
// build the h/w work list
const bool workListsDirty = mHwWorkListDirty;
mHwWorkListDirty = false;
- for (int dpy=0 ; dpy<1 ; dpy++) { // TODO: iterate through all displays
- DisplayDevice& hw(const_cast<DisplayDevice&>(getDisplayDevice(dpy)));
+ for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
+ const DisplayDevice& hw(mDisplays[dpy]);
const Vector< sp<LayerBase> >& currentLayers(hw.getVisibleLayersSortedByZ());
const size_t count = currentLayers.size();
@@ -646,8 +649,8 @@ void SurfaceFlinger::handleMessageRefresh() {
}
const bool repaintEverything = android_atomic_and(0, &mRepaintEverything);
- for (int dpy=0 ; dpy<1 ; dpy++) { // TODO: iterate through all displays
- DisplayDevice& hw(const_cast<DisplayDevice&>(getDisplayDevice(dpy)));
+ for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
+ DisplayDevice& hw(mDisplays.editValueAt(dpy));
// transform the dirty region into this screen's coordinate space
const Transform& planeTransform(hw.getTransform());
@@ -693,7 +696,7 @@ void SurfaceFlinger::handleMessageRefresh() {
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
- DisplayDevice& hw(const_cast<DisplayDevice&>(getDisplayDevice(0)));
+ DisplayDevice& hw(const_cast<DisplayDevice&>(getDefaultDisplayDevice()));
const Vector< sp<LayerBase> >& layers( hw.getVisibleLayersSortedByZ() );
const size_t count = layers.size();
for (size_t i=0 ; i<count ; ++i) {
@@ -725,8 +728,8 @@ void SurfaceFlinger::postFramebuffer()
HWComposer& hwc(getHwComposer());
- for (int dpy=0 ; dpy<1 ; dpy++) { // TODO: iterate through all displays
- DisplayDevice& hw(const_cast<DisplayDevice&>(getDisplayDevice(dpy)));
+ for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
+ DisplayDevice& hw(mDisplays.editValueAt(dpy));
if (hwc.initCheck() == NO_ERROR) {
const Vector< sp<LayerBase> >& currentLayers(hw.getVisibleLayersSortedByZ());
const size_t count = currentLayers.size();
@@ -746,8 +749,8 @@ void SurfaceFlinger::postFramebuffer()
hwc.commit(mEGLDisplay, getDefaultDisplayDevice().getEGLSurface());
}
- for (int dpy=0 ; dpy<1 ; dpy++) { // TODO: iterate through all displays
- DisplayDevice& hw(const_cast<DisplayDevice&>(getDisplayDevice(dpy)));
+ for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
+ const DisplayDevice& hw(mDisplays[dpy]);
const Vector< sp<LayerBase> >& currentLayers(hw.getVisibleLayersSortedByZ());
const size_t count = currentLayers.size();
if (hwc.initCheck() == NO_ERROR) {
@@ -822,16 +825,52 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
*/
if (transactionFlags & eTransactionNeeded) {
- if (mCurrentState.orientation != mDrawingState.orientation) {
- // the orientation has changed, recompute all visible regions
- // and invalidate everything.
-
- const int dpy = 0; // FIXME: should be a parameter
- DisplayDevice& hw(const_cast<DisplayDevice&>(getDisplayDevice(dpy)));
- hw.setOrientation(mCurrentState.orientation);
- hw.dirtyRegion.set(hw.bounds());
-
+ // here we take advantage of Vector's copy-on-write semantics to
+ // improve performance by skipping the transaction entirely when
+ // know that the lists are identical
+ const KeyedVector<int32_t, DisplayDeviceState>& curr(mCurrentState.displays);
+ const KeyedVector<int32_t, DisplayDeviceState>& draw(mDrawingState.displays);
+ if (!curr.isIdenticalTo(draw)) {
mVisibleRegionsDirty = true;
+ const size_t cc = curr.size();
+ const size_t dc = draw.size();
+
+ // find the displays that were removed
+ // (ie: in drawing state but not in current state)
+ // also handle displays that changed
+ // (ie: displays that are in both lists)
+ for (size_t i=0 ; i<dc ; i++) {
+ if (curr.indexOfKey(draw[i].id) < 0) {
+ // in drawing state but not in current state
+ if (draw[i].id != DisplayDevice::DISPLAY_ID_MAIN) {
+ mDisplays.editValueFor(draw[i].id).terminate();
+ mDisplays.removeItem(draw[i].id);
+ } else {
+ ALOGW("trying to remove the main display");
+ }
+ } else {
+ // this display is in both lists. see if something changed.
+ const DisplayDeviceState& state(curr[i]);
+ if (state.layerStack != draw[i].layerStack) {
+ DisplayDevice& disp(mDisplays.editValueFor(state.id));
+ //disp.setLayerStack(state.layerStack);
+ }
+ if (curr[i].orientation != draw[i].orientation) {
+ DisplayDevice& disp(mDisplays.editValueFor(state.id));
+ disp.setOrientation(state.orientation);
+ }
+ }
+ }
+
+ // find displays that were added
+ // (ie: in current state but not in drawing state)
+ for (size_t i=0 ; i<cc ; i++) {
+ if (mDrawingState.displays.indexOfKey(curr[i].id) < 0) {
+ // FIXME: we need to pass the surface here
+ DisplayDevice disp(this, curr[i].id, 0, mEGLConfig);
+ mDisplays.add(curr[i].id, disp);
+ }
+ }
}
if (currentLayers.size() > mDrawingState.layersSortedByZ.size()) {
@@ -1011,10 +1050,12 @@ void SurfaceFlinger::computeVisibleRegions(
void SurfaceFlinger::invalidateLayerStack(uint32_t layerStack,
const Region& dirty) {
- // FIXME: update the dirty region of all displays
- // presenting this layer's layer stack.
- DisplayDevice& hw(const_cast<DisplayDevice&>(getDisplayDevice(0)));
- hw.dirtyRegion.orSelf(dirty);
+ for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
+ DisplayDevice& hw(mDisplays.editValueAt(dpy));
+ if (hw.getLayerStack() == layerStack) {
+ hw.dirtyRegion.orSelf(dirty);
+ }
+ }
}
void SurfaceFlinger::handlePageFlip()
@@ -1324,9 +1365,10 @@ void SurfaceFlinger::setTransactionState(
}
uint32_t transactionFlags = 0;
- if (mCurrentState.orientation != orientation) {
+ // FIXME: don't hardcode display id here
+ if (mCurrentState.displays.valueFor(0).orientation != orientation) {
if (uint32_t(orientation)<=eOrientation270 || orientation==42) {
- mCurrentState.orientation = orientation;
+ mCurrentState.displays.editValueFor(0).orientation = orientation;
transactionFlags |= eTransactionNeeded;
} else if (orientation != eOrientationUnchanged) {
ALOGW("setTransactionState: ignoring unrecognized orientation: %d",
@@ -1416,7 +1458,7 @@ sp<Layer> SurfaceFlinger::createNormalLayer(
PixelFormat& format)
{
// initialize the surfaces
- switch (format) { // TODO: take h/w into account
+ switch (format) {
case PIXEL_FORMAT_TRANSPARENT:
case PIXEL_FORMAT_TRANSLUCENT:
format = PIXEL_FORMAT_RGBA_8888;
@@ -1804,7 +1846,7 @@ void SurfaceFlinger::dumpAllLocked(
hw.undefinedRegion.dump(result, "undefinedRegion");
snprintf(buffer, SIZE,
" orientation=%d, canDraw=%d\n",
- mCurrentState.orientation, hw.canDraw());
+ hw.getOrientation(), hw.canDraw());
result.append(buffer);
snprintf(buffer, SIZE,
" last eglSwapBuffers() time: %f us\n"
@@ -2727,9 +2769,8 @@ int SurfaceFlinger::LayerVector::do_compare(const void* lhs,
// ---------------------------------------------------------------------------
-SurfaceFlinger::State::State()
- : orientation(ISurfaceComposer::eOrientationDefault),
- orientationFlags(0) {
+SurfaceFlinger::DisplayDeviceState::DisplayDeviceState()
+ : id(DisplayDevice::DISPLAY_ID_MAIN), layerStack(0), orientation(0) {
}
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 6091e33..15d5a37 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -47,6 +47,7 @@
#include "Barrier.h"
#include "MessageQueue.h"
+#include "DisplayDevice.h"
#include "DisplayHardware/HWComposer.h"
@@ -56,7 +57,6 @@ namespace android {
class Client;
class DisplayEventConnection;
-class DisplayDevice;
class EventThread;
class Layer;
class LayerBase;
@@ -119,7 +119,7 @@ public:
// returns the default Display
const DisplayDevice& getDefaultDisplayDevice() const {
- return getDisplayDevice(0);
+ return getDisplayDevice(DisplayDevice::DISPLAY_ID_MAIN);
}
// utility function to delete a texture on the main thread
@@ -156,11 +156,21 @@ private:
virtual int do_compare(const void* lhs, const void* rhs) const;
};
+ struct DisplayDeviceState {
+ DisplayDeviceState();
+ int32_t id;
+ uint32_t layerStack;
+ Rect viewport;
+ Rect frame;
+ uint8_t orientation;
+ inline bool operator < (const DisplayDeviceState& rhs) const {
+ return id < rhs.id;
+ }
+ };
+
struct State {
- State();
LayerVector layersSortedByZ;
- uint8_t orientation;
- uint8_t orientationFlags;
+ KeyedVector<int32_t, DisplayDeviceState> displays;
};
/* ------------------------------------------------------------------------
@@ -175,9 +185,9 @@ private:
*/
virtual sp<ISurfaceComposerClient> createConnection();
virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc();
- virtual void bootFinished();
virtual void setTransactionState(const Vector<ComposerState>& state,
const Vector<DisplayState>& displays, uint32_t flags);
+ virtual void bootFinished();
virtual bool authenticateSurfaceTexture(
const sp<ISurfaceTexture>& surface) const;
virtual sp<IDisplayEventConnection> createDisplayEventConnection();
@@ -317,7 +327,10 @@ private:
* Display and layer stack management
*/
const DisplayDevice& getDisplayDevice(DisplayID dpy) const {
- return *mDisplayDevices[dpy];
+ return mDisplays.valueFor(dpy);
+ }
+ DisplayDevice& getDisplayDevice(DisplayID dpy) {
+ return mDisplays.editValueFor(dpy);
}
// mark a region of a layer stack dirty. this updates the dirty
@@ -370,7 +383,6 @@ private:
Vector<sp<LayerBase> > mLayersPendingRemoval;
// protected by mStateLock (but we could use another lock)
- DisplayDevice* mDisplayDevices[1];
bool mLayersRemoved;
// access must be protected by mInvalidateLock
@@ -393,6 +405,7 @@ private:
bool mVisibleRegionsDirty;
bool mHwWorkListDirty;
int32_t mElectronBeamAnimationMode;
+ DefaultKeyedVector<int32_t, DisplayDevice> mDisplays;
// don't use a lock for these, we don't care
int mDebugRegion;