factor EGL/GL and surface creation out of DisplayHardware

Change-Id: Icd85a6a4caad06f056578008af3e21666fa8b1f4
diff --git a/services/surfaceflinger/DisplayHardware.cpp b/services/surfaceflinger/DisplayHardware.cpp
index fdde15a..af33a89 100644
--- a/services/surfaceflinger/DisplayHardware.cpp
+++ b/services/surfaceflinger/DisplayHardware.cpp
@@ -31,6 +31,7 @@
 #include <EGL/eglext.h>
 
 #include <hardware/gralloc.h>
+#include <private/gui/SharedBufferStack.h>
 
 #include "DisplayHardware/FramebufferSurface.h"
 #include "DisplayHardware/DisplayHardwareBase.h"
@@ -40,8 +41,9 @@
 #include "GLExtensions.h"
 #include "SurfaceFlinger.h"
 
+// ----------------------------------------------------------------------------
 using namespace android;
-
+// ----------------------------------------------------------------------------
 
 static __attribute__((noinline))
 void checkGLErrors()
@@ -88,6 +90,8 @@
     }
 }
 
+// ----------------------------------------------------------------------------
+
 /*
  * Initialize the display to the specified values.
  *
@@ -95,79 +99,78 @@
 
 DisplayHardware::DisplayHardware(
         const sp<SurfaceFlinger>& flinger,
-        uint32_t dpy)
-    : DisplayHardwareBase(flinger, dpy),
-      mFlinger(flinger), mFlags(0), mHwc(0), mSecureLayerVisible(false)
+        int display,
+        const sp<SurfaceTextureClient>& surface,
+        EGLConfig config)
+    : DisplayHardwareBase(flinger, display),
+      mFlinger(flinger),
+      mDisplayId(display),
+      mHwc(0),
+      mNativeWindow(surface),
+      mFlags(0),
+      mSecureLayerVisible(false)
 {
-    init(dpy);
+    init(config);
 }
 
-DisplayHardware::~DisplayHardware()
-{
-    fini();
+DisplayHardware::~DisplayHardware() {
 }
 
-float DisplayHardware::getDpiX() const          { return mDpiX; }
-float DisplayHardware::getDpiY() const          { return mDpiY; }
-float DisplayHardware::getDensity() const       { return mDensity; }
-float DisplayHardware::getRefreshRate() const   { return mRefreshRate; }
-int DisplayHardware::getWidth() const           { return mDisplayWidth; }
-int DisplayHardware::getHeight() const          { return mDisplayHeight; }
-PixelFormat DisplayHardware::getFormat() const  { return mFormat; }
-uint32_t DisplayHardware::getMaxTextureSize() const { return mMaxTextureSize; }
-
-uint32_t DisplayHardware::getMaxViewportDims() const {
-    return mMaxViewportDims[0] < mMaxViewportDims[1] ?
-            mMaxViewportDims[0] : mMaxViewportDims[1];
+float DisplayHardware::getDpiX() const {
+    return mDpiX;
 }
 
-static status_t selectConfigForPixelFormat(
-        EGLDisplay dpy,
-        EGLint const* attrs,
-        PixelFormat format,
-        EGLConfig* outConfig)
-{
-    EGLConfig config = NULL;
-    EGLint numConfigs = -1, n=0;
-    eglGetConfigs(dpy, NULL, 0, &numConfigs);
-    EGLConfig* const configs = new EGLConfig[numConfigs];
-    eglChooseConfig(dpy, attrs, configs, numConfigs, &n);
-    for (int i=0 ; i<n ; i++) {
-        EGLint nativeVisualId = 0;
-        eglGetConfigAttrib(dpy, configs[i], EGL_NATIVE_VISUAL_ID, &nativeVisualId);
-        if (nativeVisualId>0 && format == nativeVisualId) {
-            *outConfig = configs[i];
-            delete [] configs;
-            return NO_ERROR;
-        }
-    }
-    delete [] configs;
-    return NAME_NOT_FOUND;
+float DisplayHardware::getDpiY() const {
+    return mDpiY;
 }
 
+float DisplayHardware::getDensity() const {
+    return mDensity;
+}
 
-void DisplayHardware::init(uint32_t dpy)
+float DisplayHardware::getRefreshRate() const {
+    return mRefreshRate;
+}
+
+int DisplayHardware::getWidth() const {
+    return mDisplayWidth;
+}
+
+int DisplayHardware::getHeight() const {
+    return mDisplayHeight;
+}
+
+PixelFormat DisplayHardware::getFormat() const {
+    return mFormat;
+}
+
+EGLSurface DisplayHardware::getEGLSurface() const {
+    return mSurface;
+}
+
+void DisplayHardware::init(EGLConfig config)
 {
-    mNativeWindow = new FramebufferSurface();
-    framebuffer_device_t const * fbDev = mNativeWindow->getDevice();
-    if (!fbDev) {
-        ALOGE("Display subsystem failed to initialize. check logs. exiting...");
-        exit(0);
+    ANativeWindow* const window = mNativeWindow.get();
+
+    int concreteType;
+    window->query(window, NATIVE_WINDOW_CONCRETE_TYPE, &concreteType);
+    if (concreteType == NATIVE_WINDOW_FRAMEBUFFER) {
+        mFramebufferSurface = static_cast<FramebufferSurface *>(mNativeWindow.get());
     }
 
     int format;
-    ANativeWindow const * const window = mNativeWindow.get();
     window->query(window, NATIVE_WINDOW_FORMAT, &format);
-    mDpiX = mNativeWindow->xdpi;
-    mDpiY = mNativeWindow->ydpi;
-    mRefreshRate = fbDev->fps;
-
-    if (mDpiX == 0 || mDpiY == 0) {
-        ALOGE("invalid screen resolution from fb HAL (xdpi=%f, ydpi=%f), "
-               "defaulting to 160 dpi", mDpiX, mDpiY);
-        mDpiX = mDpiY = 160;
+    mDpiX = window->xdpi;
+    mDpiY = window->ydpi;
+    if (mFramebufferSurface != NULL) {
+        mRefreshRate = mFramebufferSurface->getRefreshRate();
+    } else {
+        mRefreshRate = 60;
     }
+    mRefreshPeriod = nsecs_t(1e9 / mRefreshRate);
 
+
+    // TODO: Not sure if display density should handled by SF any longer
     class Density {
         static int getDensityFromProperty(char const* propName) {
             char property[PROPERTY_VALUE_MAX];
@@ -183,173 +186,52 @@
         static int getBuildDensity()  {
             return getDensityFromProperty("ro.sf.lcd_density"); }
     };
-
-
     // The density of the device is provided by a build property
     mDensity = Density::getBuildDensity() / 160.0f;
-
     if (mDensity == 0) {
         // the build doesn't provide a density -- this is wrong!
         // use xdpi instead
         ALOGE("ro.sf.lcd_density must be defined as a build property");
         mDensity = mDpiX / 160.0f;
     }
-
     if (Density::getEmuDensity()) {
         // if "qemu.sf.lcd_density" is specified, it overrides everything
         mDpiX = mDpiY = mDensity = Density::getEmuDensity();
         mDensity /= 160.0f;
     }
 
-
-
-    /* FIXME: this is a temporary HACK until we are able to report the refresh rate
-     * properly from the HAL. The WindowManagerService now relies on this value.
-     */
-#ifndef REFRESH_RATE
-    mRefreshRate = fbDev->fps;
-#else
-    mRefreshRate = REFRESH_RATE;
-#warning "refresh rate set via makefile to REFRESH_RATE"
-#endif
-
-    mRefreshPeriod = nsecs_t(1e9 / mRefreshRate);
-
-    EGLint w, h, dummy;
-    EGLint numConfigs=0;
-    EGLSurface surface;
-    EGLContext context;
-    EGLBoolean result;
-    status_t err;
-
-    // initialize EGL
-    EGLint attribs[] = {
-            EGL_SURFACE_TYPE,           EGL_WINDOW_BIT,
-            EGL_RECORDABLE_ANDROID,     EGL_TRUE,
-            EGL_NONE
-    };
-
-    // TODO: all the extensions below should be queried through
-    // eglGetProcAddress().
-
-    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-    eglInitialize(display, NULL, NULL);
-    eglGetConfigs(display, NULL, 0, &numConfigs);
-
-    EGLConfig config = NULL;
-    err = selectConfigForPixelFormat(display, attribs, format, &config);
-    if (err) {
-        // maybe we failed because of EGL_RECORDABLE_ANDROID
-        ALOGW("couldn't find an EGLConfig with EGL_RECORDABLE_ANDROID");
-        attribs[2] = EGL_NONE;
-        err = selectConfigForPixelFormat(display, attribs, format, &config);
-    }
-
-    ALOGE_IF(err, "couldn't find an EGLConfig matching the screen format");
-    
-    EGLint r,g,b,a;
-    eglGetConfigAttrib(display, config, EGL_RED_SIZE,   &r);
-    eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g);
-    eglGetConfigAttrib(display, config, EGL_BLUE_SIZE,  &b);
-    eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a);
-
-    if (mNativeWindow->isUpdateOnDemand()) {
-        mFlags |= PARTIAL_UPDATES;
-    }
-    
-    if (eglGetConfigAttrib(display, config, EGL_CONFIG_CAVEAT, &dummy) == EGL_TRUE) {
-        if (dummy == EGL_SLOW_CONFIG)
-            mFlags |= SLOW_CONFIG;
-    }
-
     /*
-     * Create our main surface
+     * Create our display's surface
      */
 
-    surface = eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL);
+    EGLSurface surface;
+    EGLint w, h;
+    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    surface = eglCreateWindowSurface(display, config, window, NULL);
     eglQuerySurface(display, surface, EGL_WIDTH,  &mDisplayWidth);
     eglQuerySurface(display, surface, EGL_HEIGHT, &mDisplayHeight);
 
-    if (mFlags & PARTIAL_UPDATES) {
-        // if we have partial updates, we definitely don't need to
-        // preserve the backbuffer, which may be costly.
-        eglSurfaceAttrib(display, surface,
-                EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED);
+    if (mFramebufferSurface != NULL) {
+        if (mFramebufferSurface->isUpdateOnDemand()) {
+            mFlags |= PARTIAL_UPDATES;
+            // if we have partial updates, we definitely don't need to
+            // preserve the backbuffer, which may be costly.
+            eglSurfaceAttrib(display, surface,
+                    EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED);
+        }
     }
 
-    /*
-     * Create our OpenGL ES context
-     */
-    
-    EGLint contextAttributes[] = {
-#ifdef EGL_IMG_context_priority
-#ifdef HAS_CONTEXT_PRIORITY
-#warning "using EGL_IMG_context_priority"
-        EGL_CONTEXT_PRIORITY_LEVEL_IMG, EGL_CONTEXT_PRIORITY_HIGH_IMG,
-#endif
-#endif
-        EGL_NONE, EGL_NONE
-    };
-    context = eglCreateContext(display, config, NULL, contextAttributes);
-
     mDisplay = display;
-    mConfig  = config;
     mSurface = surface;
-    mContext = context;
-    mFormat  = fbDev->format;
+    mFormat  = format;
     mPageFlipCount = 0;
 
-    /*
-     * Gather OpenGL ES extensions
-     */
-
-    result = eglMakeCurrent(display, surface, surface, context);
-    if (!result) {
-        ALOGE("Couldn't create a working GLES context. check logs. exiting...");
-        exit(0);
-    }
-
-    GLExtensions& extensions(GLExtensions::getInstance());
-    extensions.initWithGLStrings(
-            glGetString(GL_VENDOR),
-            glGetString(GL_RENDERER),
-            glGetString(GL_VERSION),
-            glGetString(GL_EXTENSIONS),
-            eglQueryString(display, EGL_VENDOR),
-            eglQueryString(display, EGL_VERSION),
-            eglQueryString(display, EGL_EXTENSIONS));
-
-    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
-    glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);
-
-    ALOGI("EGL informations:");
-    ALOGI("# of configs : %d", numConfigs);
-    ALOGI("vendor    : %s", extensions.getEglVendor());
-    ALOGI("version   : %s", extensions.getEglVersion());
-    ALOGI("extensions: %s", extensions.getEglExtension());
-    ALOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported");
-    ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config);
-
-    ALOGI("OpenGL informations:");
-    ALOGI("vendor    : %s", extensions.getVendor());
-    ALOGI("renderer  : %s", extensions.getRenderer());
-    ALOGI("version   : %s", extensions.getVersion());
-    ALOGI("extensions: %s", extensions.getExtension());
-    ALOGI("GL_MAX_TEXTURE_SIZE = %d", mMaxTextureSize);
-    ALOGI("GL_MAX_VIEWPORT_DIMS = %d x %d", mMaxViewportDims[0], mMaxViewportDims[1]);
-    ALOGI("flags = %08x", mFlags);
-
-    // Unbind the context from this thread
-    eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-
-
     // initialize the H/W composer
     mHwc = new HWComposer(mFlinger, *this, mRefreshPeriod);
     if (mHwc->initCheck() == NO_ERROR) {
         mHwc->setFrameBuffer(mDisplay, mSurface);
     }
 
-
     // initialize the display orientation transform.
     // it's a constant that should come from the display driver.
     int displayOrientation = ISurfaceComposer::eOrientationDefault;
@@ -378,6 +260,20 @@
         mLogicalDisplayHeight = h;
     }
     DisplayHardware::setOrientation(ISurfaceComposer::eOrientationDefault);
+
+    // initialize the shared control block
+    surface_flinger_cblk_t* const scblk = mFlinger->getControlBlock();
+    scblk->connected |= 1 << mDisplayId;
+    display_cblk_t* dcblk = &scblk->displays[mDisplayId];
+    memset(dcblk, 0, sizeof(display_cblk_t));
+    dcblk->w = w; // XXX: plane.getWidth();
+    dcblk->h = h; // XXX: plane.getHeight();
+    dcblk->format = format;
+    dcblk->orientation = ISurfaceComposer::eOrientationDefault;
+    dcblk->xdpi = mDpiX;
+    dcblk->ydpi = mDpiY;
+    dcblk->fps = mRefreshRate;
+    dcblk->density = mDensity;
 }
 
 void DisplayHardware::setVSyncHandler(const sp<VSyncHandler>& handler) {
@@ -411,19 +307,6 @@
     return *mHwc;
 }
 
-/*
- * Clean up.  Throw out our local state.
- *
- * (It's entirely possible we'll never get here, since this is meant
- * for real hardware, which doesn't restart.)
- */
-
-void DisplayHardware::fini()
-{
-    eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-    eglTerminate(mDisplay);
-}
-
 void DisplayHardware::releaseScreen() const
 {
     DisplayHardwareBase::releaseScreen();
@@ -458,7 +341,10 @@
 }
 
 status_t DisplayHardware::compositionComplete() const {
-    return mNativeWindow->compositionComplete();
+    if (mFramebufferSurface == NULL) {
+        return NO_ERROR;
+    }
+    return mFramebufferSurface->compositionComplete();
 }
 
 void DisplayHardware::flip(const Region& dirty) const
@@ -478,7 +364,9 @@
 #endif
     
     if (mFlags & PARTIAL_UPDATES) {
-        mNativeWindow->setUpdateRectangle(dirty.getBounds());
+        if (mFramebufferSurface != NULL) {
+            mFramebufferSurface->setUpdateRectangle(dirty.getBounds());
+        }
     }
     
     mPageFlipCount++;
@@ -489,10 +377,6 @@
         eglSwapBuffers(dpy, surface);
     }
     checkEGLErrors("eglSwapBuffers");
-
-    // for debugging
-    //glClearColor(1,0,0,0);
-    //glClear(GL_COLOR_BUFFER_BIT);
 }
 
 uint32_t DisplayHardware::getFlags() const
@@ -500,14 +384,11 @@
     return mFlags;
 }
 
-void DisplayHardware::makeCurrent() const
-{
-    eglMakeCurrent(mDisplay, mSurface, mSurface, mContext);
-}
-
 void DisplayHardware::dump(String8& res) const
 {
-    mNativeWindow->dump(res);
+    if (mFramebufferSurface != NULL) {
+        mFramebufferSurface->dump(res);
+    }
 }
 
 // ----------------------------------------------------------------------------