Merge "BufferQueue: clean up buffer counting" into jb-mr1-dev
diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h
index 73214a4..a143d81 100644
--- a/include/gui/SurfaceComposerClient.h
+++ b/include/gui/SurfaceComposerClient.h
@@ -148,11 +148,6 @@
public:
ScreenshotClient();
- // TODO: Remove me. Do not use.
- // This is a compatibility shim for one product whose drivers are depending on
- // this legacy function (when they shouldn't).
- status_t update();
-
// frees the previous screenshot and capture a new one
status_t update(const sp<IBinder>& display);
status_t update(const sp<IBinder>& display,
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 0ffa932..e4922a4 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -558,14 +558,6 @@
: mWidth(0), mHeight(0), mFormat(PIXEL_FORMAT_NONE) {
}
-// TODO: Remove me. Do not use.
-// This is a compatibility shim for one product whose drivers are depending on
-// this legacy function (when they shouldn't).
-status_t ScreenshotClient::update() {
- sp<ISurfaceComposer> sm(ComposerService::getComposerService());
- return update(sm->getBuiltInDisplay(0));
-}
-
status_t ScreenshotClient::update(const sp<IBinder>& display) {
sp<ISurfaceComposer> s(ComposerService::getComposerService());
if (s == NULL) return NO_INIT;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 1678fe1..75c228d 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -46,8 +46,31 @@
namespace android {
-static bool hwcHasVersion(const hwc_composer_device_1_t* hwc, uint32_t version) {
- return hwc->common.version >= version;
+#define MIN_HWC_HEADER_VERSION 0
+
+static uint32_t hwcApiVersion(const hwc_composer_device_1_t* hwc) {
+ uint32_t hwcVersion = hwc->common.version;
+ if (MIN_HWC_HEADER_VERSION == 0 &&
+ (hwcVersion & HARDWARE_API_VERSION_2_MAJ_MIN_MASK) == 0) {
+ // legacy version encoding
+ hwcVersion <<= 16;
+ }
+ return hwcVersion & HARDWARE_API_VERSION_2_MAJ_MIN_MASK;
+}
+
+static uint32_t hwcHeaderVersion(const hwc_composer_device_1_t* hwc) {
+ uint32_t hwcVersion = hwc->common.version;
+ if (MIN_HWC_HEADER_VERSION == 0 &&
+ (hwcVersion & HARDWARE_API_VERSION_2_MAJ_MIN_MASK) == 0) {
+ // legacy version encoding
+ hwcVersion <<= 16;
+ }
+ return hwcVersion & HARDWARE_API_VERSION_2_HEADER_MASK;
+}
+
+static bool hwcHasApiVersion(const hwc_composer_device_1_t* hwc,
+ uint32_t version) {
+ return hwcApiVersion(hwc) >= (version & HARDWARE_API_VERSION_2_MAJ_MIN_MASK);
}
// ---------------------------------------------------------------------------
@@ -91,8 +114,10 @@
ALOGE_IF(err, "%s device failed to initialize (%s)",
HWC_HARDWARE_COMPOSER, strerror(-err));
if (err == 0) {
- if (mHwc->common.version < HWC_DEVICE_API_VERSION_1_0) {
- ALOGE("%s device version %#x too old, will not be used",
+ if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0) ||
+ hwcHeaderVersion(mHwc) < MIN_HWC_HEADER_VERSION ||
+ hwcHeaderVersion(mHwc) > HWC_HEADER_VERSION) {
+ ALOGE("%s device version %#x unsupported, will not be used",
HWC_HARDWARE_COMPOSER, mHwc->common.version);
hwc_close_1(mHwc);
mHwc = NULL;
@@ -100,6 +125,9 @@
}
if (mHwc) {
+ ALOGI("Using %s version %u.%u", HWC_HARDWARE_COMPOSER,
+ (hwcApiVersion(mHwc) >> 24) & 0xff,
+ (hwcApiVersion(mHwc) >> 16) & 0xff);
if (mHwc->registerProcs) {
mCBContext->hwc = this;
mCBContext->procs.invalidate = &hook_invalidate;
@@ -125,12 +153,14 @@
// the number of displays we actually have depends on the
// hw composer version
- if (mHwc->common.version == HWC_DEVICE_API_VERSION_1_1) {
- // 1.1 adds support for multiple displays
- mNumDisplays = HWC_NUM_DISPLAY_TYPES;
- } else if (mHwc->common.version > HWC_DEVICE_API_VERSION_1_1) {
+ if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_2)) {
// 1.2 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;
+ } else {
+ mNumDisplays = 1;
}
}
}
@@ -326,7 +356,7 @@
status_t HWComposer::commit() {
int err = NO_ERROR;
if (mHwc) {
- if (mHwc->common.version == HWC_DEVICE_API_VERSION_1_0) {
+ if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
// On version 1.0, the OpenGL ES target surface is communicated
// by the (dpy, sur) fields and we are guaranteed to have only
// a single display.
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 1162432..cd1b336 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -944,7 +944,7 @@
if (!curr.isIdenticalTo(draw)) {
mVisibleRegionsDirty = true;
const size_t cc = curr.size();
- const size_t dc = draw.size();
+ size_t dc = draw.size();
// find the displays that were removed
// (ie: in drawing state but not in current state)
@@ -965,27 +965,27 @@
const wp<IBinder>& display(curr.keyAt(j));
if (state.surface->asBinder() != draw[i].surface->asBinder()) {
// changing the surface is like destroying and
- // recreating the DisplayDevice
- sp<SurfaceTextureClient> stc(
- new SurfaceTextureClient(state.surface));
- sp<DisplayDevice> disp = new DisplayDevice(this,
- state.type, display, stc, NULL, mEGLConfig);
+ // recreating the DisplayDevice, so we just remove it
+ // from the drawing state, so that it get re-added
+ // below.
+ mDisplays.removeItem(display);
+ mDrawingState.displays.removeItemsAt(i);
+ dc--; i--;
+ // at this point we must loop to the next item
+ continue;
+ }
- disp->setLayerStack(state.layerStack);
- disp->setOrientation(state.orientation);
- // TODO: take viewport and frame into account
- mDisplays.replaceValueFor(display, disp);
- }
- if (state.layerStack != draw[i].layerStack) {
- const sp<DisplayDevice>& disp(getDisplayDevice(display));
- disp->setLayerStack(state.layerStack);
- }
- if (state.orientation != draw[i].orientation ||
- state.viewport != draw[i].viewport ||
- state.frame != draw[i].frame) {
- const sp<DisplayDevice>& disp(getDisplayDevice(display));
- disp->setOrientation(state.orientation);
- // TODO: take viewport and frame into account
+ const sp<DisplayDevice>& disp(getDisplayDevice(display));
+ if (disp != NULL) {
+ if (state.layerStack != draw[i].layerStack) {
+ disp->setLayerStack(state.layerStack);
+ }
+ if (state.orientation != draw[i].orientation ||
+ state.viewport != draw[i].viewport ||
+ state.frame != draw[i].frame) {
+ disp->setOrientation(state.orientation);
+ // TODO: take viewport and frame into account
+ }
}
}
}
@@ -995,12 +995,17 @@
for (size_t i=0 ; i<cc ; i++) {
if (draw.indexOfKey(curr.keyAt(i)) < 0) {
const DisplayDeviceState& state(curr[i]);
- sp<SurfaceTextureClient> stc(
- new SurfaceTextureClient(state.surface));
- const wp<IBinder>& display(curr.keyAt(i));
- sp<DisplayDevice> disp = new DisplayDevice(this,
- state.type, display, stc, 0, mEGLConfig);
- mDisplays.add(display, disp);
+ if (state.surface != NULL) {
+ sp<SurfaceTextureClient> stc(
+ new SurfaceTextureClient(state.surface));
+ const wp<IBinder>& display(curr.keyAt(i));
+ sp<DisplayDevice> disp = new DisplayDevice(this,
+ state.type, display, stc, 0, mEGLConfig);
+ disp->setLayerStack(state.layerStack);
+ disp->setOrientation(state.orientation);
+ // TODO: take viewport and frame into account
+ mDisplays.add(display, disp);
+ }
}
}
}
@@ -1264,15 +1269,13 @@
void SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const Region& dirty)
{
+ const int32_t id = hw->getHwcDisplayId();
HWComposer& hwc(getHwComposer());
- int32_t id = hw->getHwcDisplayId();
HWComposer::LayerListIterator cur = hwc.begin(id);
const HWComposer::LayerListIterator end = hwc.end(id);
- const bool hasGlesComposition = hwc.hasGlesComposition(id);
- const bool hasHwcComposition = hwc.hasHwcComposition(id);
- if (cur==end || hasGlesComposition) {
-
+ const bool hasGlesComposition = hwc.hasGlesComposition(id) || (cur==end);
+ if (hasGlesComposition) {
DisplayDevice::makeCurrent(hw, mEGLContext);
// set the frame buffer
@@ -1280,6 +1283,7 @@
glLoadIdentity();
// Never touch the framebuffer if we don't have any framebuffer layers
+ const bool hasHwcComposition = hwc.hasHwcComposition(id);
if (hasHwcComposition) {
// when using overlays, we assume a fully transparent framebuffer
// NOTE: we could reduce how much we need to clear, for instance
@@ -1296,38 +1300,49 @@
drawWormhole(hw, region);
}
}
+ }
- /*
- * and then, render the layers targeted at the framebuffer
- */
+ /*
+ * and then, render the layers targeted at the framebuffer
+ */
- const Vector< sp<LayerBase> >& layers(hw->getVisibleLayersSortedByZ());
- const size_t count = layers.size();
- const Transform& tr = hw->getTransform();
- for (size_t i=0 ; i<count ; ++i) {
+ const Vector< sp<LayerBase> >& 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 Region clip(dirty.intersect(tr.transform(layer->visibleRegion)));
- if (cur != end) {
- // we're using h/w composer
- if (!clip.isEmpty()) {
- if (cur->getCompositionType() == HWC_OVERLAY) {
- if (i && (cur->getHints() & HWC_HINT_CLEAR_FB)
- && layer->isOpaque()) {
+ if (!clip.isEmpty()) {
+ switch (cur->getCompositionType()) {
+ case HWC_OVERLAY: {
+ if ((cur->getHints() & HWC_HINT_CLEAR_FB)
+ && i
+ && layer->isOpaque()
+ && hasGlesComposition) {
// never clear the very first layer since we're
// guaranteed the FB is already cleared
layer->clearWithOpenGL(hw, clip);
}
- } else {
- layer->draw(hw, clip);
+ break;
}
- layer->setAcquireFence(hw, *cur);
+ case HWC_FRAMEBUFFER: {
+ layer->draw(hw, clip);
+ break;
+ }
}
- ++cur;
- } else {
- // we're not using h/w composer
- if (!clip.isEmpty()) {
- layer->draw(hw, clip);
- }
+ }
+ layer->setAcquireFence(hw, *cur);
+ }
+ } else {
+ // we're not using h/w composer
+ for (size_t i=0 ; i<count ; ++i) {
+ const sp<LayerBase>& layer(layers[i]);
+ const Region clip(dirty.intersect(
+ tr.transform(layer->visibleRegion)));
+ if (!clip.isEmpty()) {
+ layer->draw(hw, clip);
}
}
}