Switch SurfaceFlinger to HWC 2.0
Enables SurfaceFlinger to speak to version 2.0 of the Hardware Composer
HAL instead of version 1.x (also removing support for the framebuffer
HAL). By default, however, this functionality is disabled. In order to
enable it, USE_HWC2 must be set to true in Android.mk.
Change-Id: I4589e02ac2165236b10ff2f7cb772f87e0d3daab
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index e9cbbca..8d8e40d 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+// #define LOG_NDEBUG 0
+#undef LOG_TAG
+#define LOG_TAG "DisplayDevice"
+
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -33,6 +37,9 @@
#include "DisplayHardware/DisplaySurface.h"
#include "DisplayHardware/HWComposer.h"
+#ifdef USE_HWC2
+#include "DisplayHardware/HWC2.h"
+#endif
#include "RenderEngine/RenderEngine.h"
#include "clz.h"
@@ -65,7 +72,9 @@
const sp<SurfaceFlinger>& flinger,
DisplayType type,
int32_t hwcId,
+#ifndef USE_HWC2
int format,
+#endif
bool isSecure,
const wp<IBinder>& displayToken,
const sp<DisplaySurface>& displaySurface,
@@ -73,12 +82,17 @@
EGLConfig config)
: lastCompositionHadVisibleLayers(false),
mFlinger(flinger),
- mType(type), mHwcDisplayId(hwcId),
+ mType(type),
+ mHwcDisplayId(hwcId),
mDisplayToken(displayToken),
mDisplaySurface(displaySurface),
mDisplay(EGL_NO_DISPLAY),
mSurface(EGL_NO_SURFACE),
- mDisplayWidth(), mDisplayHeight(), mFormat(),
+ mDisplayWidth(),
+ mDisplayHeight(),
+#ifndef USE_HWC2
+ mFormat(),
+#endif
mFlags(),
mPageFlipCount(),
mIsSecure(isSecure),
@@ -98,7 +112,11 @@
EGLSurface eglSurface;
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (config == EGL_NO_CONFIG) {
+#ifdef USE_HWC2
+ config = RenderEngine::chooseEglConfig(display, PIXEL_FORMAT_RGBA_8888);
+#else
config = RenderEngine::chooseEglConfig(display, format);
+#endif
}
eglSurface = eglCreateWindowSurface(display, config, window, NULL);
eglQuerySurface(display, eglSurface, EGL_WIDTH, &mDisplayWidth);
@@ -117,7 +135,9 @@
mConfig = config;
mDisplay = display;
mSurface = eglSurface;
- mFormat = format;
+#ifndef USE_HWC2
+ mFormat = format;
+#endif
mPageFlipCount = 0;
mViewport.makeInvalid();
mFrame.makeInvalid();
@@ -158,8 +178,10 @@
void DisplayDevice::disconnect(HWComposer& hwc) {
if (mHwcDisplayId >= 0) {
hwc.disconnectDisplay(mHwcDisplayId);
+#ifndef USE_HWC2
if (mHwcDisplayId >= DISPLAY_VIRTUAL)
hwc.freeDisplayId(mHwcDisplayId);
+#endif
mHwcDisplayId = -1;
}
}
@@ -176,9 +198,11 @@
return mDisplayHeight;
}
+#ifndef USE_HWC2
PixelFormat DisplayDevice::getFormat() const {
return mFormat;
}
+#endif
EGLSurface DisplayDevice::getEGLSurface() const {
return mSurface;
@@ -195,9 +219,11 @@
return mPageFlipCount;
}
+#ifndef USE_HWC2
status_t DisplayDevice::compositionComplete() const {
return mDisplaySurface->compositionComplete();
}
+#endif
void DisplayDevice::flip(const Region& dirty) const
{
@@ -219,6 +245,31 @@
return mDisplaySurface->beginFrame(mustRecompose);
}
+#ifdef USE_HWC2
+status_t DisplayDevice::prepareFrame(HWComposer& hwc) {
+ status_t error = hwc.prepare(*this);
+ if (error != NO_ERROR) {
+ return error;
+ }
+
+ DisplaySurface::CompositionType compositionType;
+ bool hasClient = hwc.hasClientComposition(mHwcDisplayId);
+ bool hasDevice = hwc.hasDeviceComposition(mHwcDisplayId);
+ if (hasClient && hasDevice) {
+ compositionType = DisplaySurface::COMPOSITION_MIXED;
+ } else if (hasClient) {
+ compositionType = DisplaySurface::COMPOSITION_GLES;
+ } else if (hasDevice) {
+ compositionType = DisplaySurface::COMPOSITION_HWC;
+ } else {
+ // Nothing to do -- when turning the screen off we get a frame like
+ // this. Call it a HWC frame since we won't be doing any GLES work but
+ // will do a prepare/set cycle.
+ compositionType = DisplaySurface::COMPOSITION_HWC;
+ }
+ return mDisplaySurface->prepareFrame(compositionType);
+}
+#else
status_t DisplayDevice::prepareFrame(const HWComposer& hwc) const {
DisplaySurface::CompositionType compositionType;
bool haveGles = hwc.hasGlesComposition(mHwcDisplayId);
@@ -237,8 +288,12 @@
}
return mDisplaySurface->prepareFrame(compositionType);
}
+#endif
void DisplayDevice::swapBuffers(HWComposer& hwc) const {
+#ifdef USE_HWC2
+ if (hwc.hasClientComposition(mHwcDisplayId)) {
+#else
// We need to call eglSwapBuffers() if:
// (1) we don't have a hardware composer, or
// (2) we did GLES composition this frame, and either
@@ -248,6 +303,7 @@
if (hwc.initCheck() != NO_ERROR ||
(hwc.hasGlesComposition(mHwcDisplayId) &&
(hwc.supportsFramebufferTarget() || mType >= DISPLAY_VIRTUAL))) {
+#endif
EGLBoolean success = eglSwapBuffers(mDisplay, mSurface);
if (!success) {
EGLint error = eglGetError();
@@ -269,11 +325,17 @@
}
}
+#ifdef USE_HWC2
+void DisplayDevice::onSwapBuffersCompleted() const {
+ mDisplaySurface->onFrameCommitted();
+}
+#else
void DisplayDevice::onSwapBuffersCompleted(HWComposer& hwc) const {
if (hwc.initCheck() == NO_ERROR) {
mDisplaySurface->onFrameCommitted();
}
}
+#endif
uint32_t DisplayDevice::getFlags() const
{
@@ -302,6 +364,12 @@
false, Transform::ROT_0);
}
+#ifdef USE_HWC2
+const sp<Fence>& DisplayDevice::getClientTargetAcquireFence() const {
+ return mDisplaySurface->getClientTargetAcquireFence();
+}
+#endif
+
// ----------------------------------------------------------------------------
void DisplayDevice::setVisibleLayersSortedByZ(const Vector< sp<Layer> >& layers) {