Merge "glgen stubs to fix bad methods in gles20 bindings"
diff --git a/include/utils/SystemClock.h b/include/utils/SystemClock.h
index 7c319be..d75264c 100644
--- a/include/utils/SystemClock.h
+++ b/include/utils/SystemClock.h
@@ -25,6 +25,7 @@
 int setCurrentTimeMillis(int64_t millis);
 int64_t uptimeMillis();
 int64_t elapsedRealtime();
+int64_t elapsedRealtimeNano();
 
 }; // namespace android
 
diff --git a/include/utils/Timers.h b/include/utils/Timers.h
index 8b4d322..92f66c9 100644
--- a/include/utils/Timers.h
+++ b/include/utils/Timers.h
@@ -78,9 +78,10 @@
     SYSTEM_TIME_REALTIME = 0,  // system-wide realtime clock
     SYSTEM_TIME_MONOTONIC = 1, // monotonic time since unspecified starting point
     SYSTEM_TIME_PROCESS = 2,   // high-resolution per-process clock
-    SYSTEM_TIME_THREAD = 3     // high-resolution per-thread clock
+    SYSTEM_TIME_THREAD = 3,    // high-resolution per-thread clock
+    SYSTEM_TIME_BOOTTIME = 4   // same as SYSTEM_TIME_MONOTONIC, but including CPU suspend time
 };
-    
+
 // return the system-time according to the specified clock
 #ifdef __cplusplus
 nsecs_t systemTime(int clock = SYSTEM_TIME_MONOTONIC);
diff --git a/libs/utils/SystemClock.cpp b/libs/utils/SystemClock.cpp
index 8b8ac10..53e0626 100644
--- a/libs/utils/SystemClock.cpp
+++ b/libs/utils/SystemClock.cpp
@@ -106,7 +106,22 @@
  */
 int64_t elapsedRealtime()
 {
+	return nanoseconds_to_milliseconds(elapsedRealtimeNano());
+}
+
+/*
+ * native public static long elapsedRealtimeNano();
+ */
+int64_t elapsedRealtimeNano()
+{
 #ifdef HAVE_ANDROID_OS
+    struct timespec ts;
+    int result = clock_gettime(CLOCK_BOOTTIME, &ts);
+    if (result == 0) {
+        return seconds_to_nanoseconds(ts.tv_sec) + ts.tv_nsec;
+    }
+
+    // CLOCK_BOOTTIME doesn't exist, fallback to /dev/alarm
     static int s_fd = -1;
 
     if (s_fd == -1) {
@@ -114,25 +129,20 @@
         if (android_atomic_cmpxchg(-1, fd, &s_fd)) {
             close(fd);
         }
+        result = ioctl(s_fd,
+                ANDROID_ALARM_GET_TIME(ANDROID_ALARM_ELAPSED_REALTIME), &ts);
     }
 
-    struct timespec ts;
-    int result = ioctl(s_fd,
-            ANDROID_ALARM_GET_TIME(ANDROID_ALARM_ELAPSED_REALTIME), &ts);
-
     if (result == 0) {
-        int64_t when = seconds_to_nanoseconds(ts.tv_sec) + ts.tv_nsec;
-        return (int64_t) nanoseconds_to_milliseconds(when);
-    } else {
-        // XXX: there was an error, probably because the driver didn't
-        // exist ... this should return
-        // a real error, like an exception!
-        int64_t when = systemTime(SYSTEM_TIME_MONOTONIC);
-        return (int64_t) nanoseconds_to_milliseconds(when);
+        return seconds_to_nanoseconds(ts.tv_sec) + ts.tv_nsec;
     }
+
+    // XXX: there was an error, probably because the driver didn't
+    // exist ... this should return
+    // a real error, like an exception!
+    return systemTime(SYSTEM_TIME_MONOTONIC);
 #else
-    int64_t when = systemTime(SYSTEM_TIME_MONOTONIC);
-    return (int64_t) nanoseconds_to_milliseconds(when);
+    return systemTime(SYSTEM_TIME_MONOTONIC);
 #endif
 }
 
diff --git a/libs/utils/Timers.cpp b/libs/utils/Timers.cpp
index 64b4701..d4f8516 100644
--- a/libs/utils/Timers.cpp
+++ b/libs/utils/Timers.cpp
@@ -39,7 +39,8 @@
             CLOCK_REALTIME,
             CLOCK_MONOTONIC,
             CLOCK_PROCESS_CPUTIME_ID,
-            CLOCK_THREAD_CPUTIME_ID
+            CLOCK_THREAD_CPUTIME_ID,
+            CLOCK_BOOTTIME
     };
     struct timespec t;
     t.tv_sec = t.tv_nsec = 0;
diff --git a/opengl/specs/EGL_ANDROID_fence_sync.txt b/opengl/specs/EGL_ANDROID_fence_sync.txt
index bb618c9..316ee1c 100644
--- a/opengl/specs/EGL_ANDROID_fence_sync.txt
+++ b/opengl/specs/EGL_ANDROID_fence_sync.txt
@@ -20,7 +20,7 @@
 
 Version
 
-    Version 1, May 29, 2012
+    Version 2, July 23, 2012
 
 Number
 
@@ -48,7 +48,9 @@
 
 New Procedures and Functions
 
-    None.
+    EGLint eglDupAndroidFenceFDANDROID(
+                        EGLDisplay dpy,
+                        EGLSyncKHR);
 
 New Tokens
 
@@ -58,9 +60,14 @@
 
     EGL_SYNC_ANDROID_FENCE_ANDROID          0x3144
 
-    Accepted by the <attribute> parameter of eglGetSyncAttribKHR:
+    Accepted by the <attrib_list> parameter of eglCreateSyncKHR:
 
-    EGL_SYNC_FENCE_FD_ANDROID               0x3145
+    EGL_SYNC_ANDROID_FENCE_FD_ANDROID       0x3145
+
+    Accepted by the <attrib_list> parameter of eglCreateSyncKHR, and returned
+    by eglDupAndroidFenceFDANDROID in the event of an error:
+
+    EGL_NO_ANDROID_FENCE_ANDROID            -1
 
     Returned in <value> when eglGetSyncAttribKHR is called with <attribute>
     EGL_SYNC_CONDITION_KHR:
@@ -73,43 +80,45 @@
     Objects), added by KHR_fence_sync
 
     "If <type> is EGL_SYNC_ANDROID_FENCE_ANDROID, an EGL Android fence sync
-    object is created. In this case the EGL_SYNC_FENCE_FD_ANDROID attribute may
-    optionally be specified. If this attribute is specified, it must be set to
-    a file descriptor that refers to a native Android fence object.
+    object is created. In this case the EGL_SYNC_ANDROID_FENCE_FD_ANDROID
+    attribute may optionally be specified. If this attribute is specified, it
+    must be set to either a file descriptor that refers to a native Android
+    fence object or to the value EGL_NO_ANDROID_FENCE_ANDROID.
 
     The default values for the EGL Android fence sync object attributes are as
     follows:
 
-      Attribute Name            Initial Attribute Value(s)
-      ---------------           --------------------------
-      EGL_SYNC_TYPE_KHR         EGL_SYNC_ANDROID_FENCE_ANDROID
-      EGL_SYNC_STATUS_KHR       EGL_UNSIGNALED_KHR
-      EGL_SYNC_CONDITION_KHR    EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR
+      Attribute Name                     Initial Attribute Value(s)
+      ---------------                    --------------------------
+      EGL_SYNC_TYPE_KHR                  EGL_SYNC_ANDROID_FENCE_ANDROID
+      EGL_SYNC_STATUS_KHR                EGL_UNSIGNALED_KHR
+      EGL_SYNC_CONDITION_KHR             EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR
+      EGL_SYNC_ANDROID_FENCE_FD_ANDROID  EGL_NO_ANDROID_FENCE_ANDROID
 
-    Upon creation of an EGL Android fence sync object, the
-    EGL_SYNC_FENCE_FD_ANDROID attribute is set to a newly generated file
-    descriptor that refers to a native Android fence object. If the
-    EGL_SYNC_FENCE_FD_ANDROID attribute is specified in the eglCreateSyncKHR
-    call then the generated file descriptor refers to the same native Android
-    fence object as the file descriptor passed to eglCreateSyncKHR.  Note,
-    however, that the value of the sync object attribute is *not* the same file
-    descriptor as the one passed to eglCreateSyncKHR - it simply refers to the
-    same underlying native Android fence object. Additionally, if the
-    EGL_SYNC_FENCE_FD_ANDROID attribute is specified then the
-    EGL_SYNC_CONDITION_KHR attribute is set to
-    EGL_SYNC_ANDROID_FENCE_SIGNALED_ANDROID and the EGL_SYNC_STATUS_KHR
+    If the EGL_SYNC_ANDROID_FENCE_FD_ANDROID attribute is not
+    EGL_NO_ANDROID_FENCE_ANDROID then the EGL_SYNC_CONDITION_KHR attribute is
+    set to EGL_SYNC_ANDROID_FENCE_SIGNALED_ANDROID and the EGL_SYNC_STATUS_KHR
     attribute is set to reflect the signal status of the native Android fence
-    object."
+    object. Additionally, the EGL implementation assumes ownership of the file
+    descriptor, so the caller must not use it after calling eglCreateSyncKHR."
 
     Modify Section 3.8.1 (Sync Objects), added by KHR_fence_sync, starting at
     the seventh paragraph
 
     "When a fence sync object is created or when an EGL Android fence sync
-    object is created without specifying the EGL_SYNC_FENCE_FD_ANDROID
-    attribute, eglCreateSyncKHR also inserts a fence command into the command
-    stream of the bound client API's current context (i.e., the context
-    returned by eglGetCurrentContext), and associates it with the newly created
-    sync object.
+    object is created with the EGL_SYNC_ANDROID_FENCE_FD_ANDROID attribute set
+    to EGL_NO_ANDROID_FENCE_ANDROID, eglCreateSyncKHR also inserts a fence
+    command into the command stream of the bound client API's current context
+    (i.e., the context returned by eglGetCurrentContext), and associates it
+    with the newly created sync object.
+
+    After associating the fence command with an EGL Android fence sync object,
+    the next Flush() operation performed by the current client API causes a
+    new native Android fence object to be created, and the
+    EGL_SYNC_ANDROID_FENCE_ANDROID attribute of the EGL Android fence object
+    is set to a file descriptor that refers to the new native Android fence
+    object. This new native Android fence object is signaled when the EGL
+    Android fence sync object is signaled.
 
     When the condition of the sync object is satisfied by the fence command,
     the sync is signaled by the associated client API context, causing any
@@ -124,7 +133,8 @@
     state is affected by execution of the fence command.
 
     The EGL_SYNC_ANDROID_FENCE_SIGNALED_ANDROID condition is satisfied by the
-    signaling of the native Android fence object. When this happens any
+    signaling of the native Android fence object referred to by the
+    EGL_SYNC_ANDROID_FENCE_FD_ANDROID attribute. When this happens any
     eglClientWaitSyncKHR commands blocking on <sync> unblock."
 
     Modify the list of eglCreateSyncKHR errors in Section 3.8.1 (Sync Objects),
@@ -140,7 +150,7 @@
         empty (containing only EGL_NONE), EGL_NO_SYNC_KHR is returned and an
         EGL_BAD_ATTRIBUTE error is generated.
       * If <type> is EGL_SYNC_ANDROID_FENCE_ANDROID and <attrib_list> contains
-        an attribute other than EGL_SYNC_FENCE_FD_ANDROID, EGL_NO_SYNC_KHR is
+        an attribute other than EGL_SYNC_ANDROID_FENCE_FD_ANDROID, EGL_NO_SYNC_KHR is
         returned and an EGL_BAD_ATTRIBUTE error is generated.
       * If <type> is not a supported type of sync object,
         EGL_NO_SYNC_KHR is returned and an EGL_BAD_ATTRIBUTE error is
@@ -162,14 +172,12 @@
     Modify table 3.cc in Section 3.8.1 (Sync Objects), added by KHR_fence_sync
 
     "
-    Attribute                 Description                Supported Sync Objects
-    -----------------         -----------------------    ----------------------
-    EGL_SYNC_TYPE_KHR         Type of the sync object    All
-    EGL_SYNC_STATUS_KHR       Status of the sync object  All
-    EGL_SYNC_CONDITION_KHR    Signaling condition        EGL_SYNC_FENCE_KHR and
-                                                         EGL_SYNC_ANDROID_FENCE_ANDROID only
-    EGL_SYNC_FENCE_FD_ANDROID Native Android fence       EGL_SYNC_ANDROID_FENCE_ANDROID only
-                              object file descriptor
+    Attribute                          Description                Supported Sync Objects
+    -----------------                  -----------------------    ----------------------
+    EGL_SYNC_TYPE_KHR                  Type of the sync object    All
+    EGL_SYNC_STATUS_KHR                Status of the sync object  All
+    EGL_SYNC_CONDITION_KHR             Signaling condition        EGL_SYNC_FENCE_KHR and
+                                                                  EGL_SYNC_ANDROID_FENCE_ANDROID only
     "
 
     Modify the second paragraph description of eglDestroySyncKHR in Section
@@ -177,9 +185,34 @@
 
     "If no errors are generated, EGL_TRUE is returned, and <sync> will no
     longer be the handle of a valid sync object.  Additionally, if <sync> is an
-    EGL Android fence sync object then the file descriptor stored in the
-    EGL_SYNC_FENCE_FD_ANDROID attribute is closed and is no longer a valid file
-    descriptor."
+    EGL Android fence sync object and the EGL_SYNC_ANDROID_FENCE_FD_ANDROID
+    attribute is not EGL_NO_ANDROID_FENCE_ANDROID then that file descriptor is
+    closed."
+
+    Add the following after the last paragraph of Section 3.8.1 (Sync
+    Objects), added by KHR_fence_sync
+
+    The command
+
+        EGLint eglDupAndroidFenceFDANDROID(
+                            EGLdisplay dpy,
+                            EGLSyncKHR sync);
+
+    duplicates the file descriptor stored in the
+    EGL_SYNC_ANDROID_FENCE_FD_ANDROID attribute of an EGL Android fence sync
+    object and returns the new file descriptor.
+
+    Errors
+    ------
+
+      * If <sync> is not a valid sync object for <dpy>,
+        EGL_NO_ANDROID_FENCE_ANDROID is returned and an EGL_BAD_PARAMETER
+        error is generated.
+      * If the EGL_SYNC_ANDROID_FENCE_FD_ANDROID attribute of <sync> is
+        EGL_NO_ANDROID_FENCE_ANDROID, EGL_NO_ANDROID_FENCE_ANDROID is returned
+        and an EGL_BAD_PARAMETER error is generated.
+      * If <dpy> does not match the display passed to eglCreateSyncKHR
+        when <sync> was created, the behaviour is undefined."
 
 Issues
 
@@ -198,16 +231,38 @@
 
     2. Who is responsible for dup'ing the Android fence file descriptors?
 
-    RESOLVED: The recipient of a file descriptor is responsible for dup'ing it
-    if it wishes to maintain a reference to the Android fence object.
+    RESOLVED: Whenever a file descriptor is passed into or returned from an
+    EGL call in this extension, ownership of that file descriptor is
+    transfered. The recipient of the file descriptor must close it when it is
+    no longer needed, and the provider of the file descriptor must dup it
+    before providing it if they require continued use of the native Android
+    fence.
 
-    This means that when eglCreateSyncKHR is called with an existing file
-    descriptor, the EGL implementation must dup it. On the other hand, when
-    eglGetSyncAttribKHR is called to query the file descriptor, it is the
-    responsibility of the caller to dup the file descriptor if it wishes to
-    maintain a reference that will outlast the EGLSyncKHR object.
+    3. Can the EGL_SYNC_ANDROID_FENCE_FD_ANDROID attribute be queried?
+
+    RESOLVED: No.
+
+    Returning the file descriptor owned by the EGL implementation would
+    violate the file descriptor ownership rule described in issue #2. Having
+    eglGetSyncAttribKHR return a different (dup'd) file descriptor each time
+    it's called seems wrong, so a new function was added to explicitly dup the
+    file descriptor.
+
+    That said, the attribute is useful both as a way to pass an existing file
+    descriptor to eglCreateSyncKHR and as a way to describe the subsequent
+    behavior of EGL Android fence sync objects, so it is left as an attribute
+    for which the value cannot be queried.
 
 Revision History
 
+#2 (Jamie Gennis, July 23, 2012)
+    - Changed the file descriptor ownership transferring behavior.
+    - Added the eglDupAndroidFenceFDANDROID function.
+    - Removed EGL_SYNC_ANDROID_FENCE_FD_ANDROID from the table of gettable
+    attributes.
+    - Added language specifying that a native Android fence is created at the
+    flush following the creation of an EGL Android fence sync object that is
+    not passed an existing native fence.
+
 #1 (Jamie Gennis, May 29, 2012)
     - Initial draft.
diff --git a/services/surfaceflinger/DisplayHardware.cpp b/services/surfaceflinger/DisplayHardware.cpp
index eb64c9f..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)
+        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,31 @@
     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);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+void DisplayHardware::setVisibleLayersSortedByZ(const Vector< sp<LayerBase> >& layers) {
+    mVisibleLayersSortedByZ = layers;
+    size_t count = layers.size();
+    for (size_t i=0 ; i<count ; i++) {
+        if (layers[i]->isSecure()) {
+            mSecureLayerVisible = true;
+        }
+    }
+}
+
+Vector< sp<LayerBase> > DisplayHardware::getVisibleLayersSortedByZ() const {
+    return mVisibleLayersSortedByZ;
+}
+
+bool DisplayHardware::getSecureLayerVisible() const {
+    return mSecureLayerVisible;
 }
 
 // ----------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayHardware.h b/services/surfaceflinger/DisplayHardware.h
index 3da9f16..029c3da 100644
--- a/services/surfaceflinger/DisplayHardware.h
+++ b/services/surfaceflinger/DisplayHardware.h
@@ -27,7 +27,6 @@
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
 
-#include "GLExtensions.h"
 #include "Transform.h"
 
 #include "DisplayHardware/DisplayHardwareBase.h"
@@ -37,6 +36,7 @@
 namespace android {
 
 class FramebufferSurface;
+class SurfaceTextureClient;
 
 class DisplayHardware :
     public DisplayHardwareBase,
@@ -52,15 +52,15 @@
     };
 
     enum {
-        COPY_BITS_EXTENSION         = 0x00000008,
         PARTIAL_UPDATES             = 0x00020000,   // video driver feature
-        SLOW_CONFIG                 = 0x00040000,   // software
         SWAP_RECTANGLE              = 0x00080000,
     };
 
     DisplayHardware(
             const sp<SurfaceFlinger>& flinger,
-            uint32_t displayIndex);
+            int dpy,
+            const sp<SurfaceTextureClient>& surface,
+            EGLConfig config);
 
     virtual ~DisplayHardware();
 
@@ -79,11 +79,14 @@
     int         getHeight() const;
     PixelFormat getFormat() const;
     uint32_t    getFlags() const;
-    uint32_t    getMaxTextureSize() const;
-    uint32_t    getMaxViewportDims() const;
     nsecs_t     getRefreshPeriod() const;
     nsecs_t     getRefreshTimestamp() const;
-    void        makeCurrent() const;
+
+    EGLSurface  getEGLSurface() const;
+
+    void                    setVisibleLayersSortedByZ(const Vector< sp<LayerBase> >& layers);
+    Vector< sp<LayerBase> > getVisibleLayersSortedByZ() const;
+    bool                    getSecureLayerVisible() const;
 
     status_t                setOrientation(int orientation);
     int                     getOrientation() const { return mOrientation; }
@@ -102,7 +105,6 @@
 
     uint32_t getPageFlipCount() const;
     EGLDisplay getEGLDisplay() const { return mDisplay; }
-    EGLConfig getEGLConfig() const { return mConfig; }
 
     void dump(String8& res) const;
 
@@ -117,15 +119,26 @@
     inline Rect bounds() const { return getBounds(); }
 
 private:
-    virtual void onVSyncReceived(int dpy, nsecs_t timestamp);
-    void init(uint32_t displayIndex);
-    void fini();
+    void init(EGLConfig config);
 
+    virtual void onVSyncReceived(int dpy, nsecs_t timestamp);
+
+    /*
+     *  Constants, set during initialization
+     */
     sp<SurfaceFlinger> mFlinger;
+    int mDisplayId;
+    HWComposer* mHwc;
+    PowerHAL mPowerHAL;
+    // ANativeWindow this display is rendering into
+    sp<SurfaceTextureClient> mNativeWindow;
+    // set if mNativeWindow is a FramebufferSurface
+    sp<FramebufferSurface> mFramebufferSurface;
+
+
     EGLDisplay      mDisplay;
     EGLSurface      mSurface;
     EGLContext      mContext;
-    EGLConfig       mConfig;
     float           mDpiX;
     float           mDpiY;
     float           mRefreshRate;
@@ -135,15 +148,19 @@
     PixelFormat     mFormat;
     uint32_t        mFlags;
     mutable uint32_t mPageFlipCount;
-    GLint           mMaxViewportDims[2];
-    GLint           mMaxTextureSize;
 
     nsecs_t         mRefreshPeriod;
     mutable nsecs_t mLastHwVSync;
 
-    // constant once set
-    HWComposer*     mHwc;
-    PowerHAL        mPowerHAL;
+
+    /*
+     * Can only accessed from the main thread, these members
+     * don't need synchronization.
+     */
+    // list of visible layers on that display
+    Vector< sp<LayerBase> > mVisibleLayersSortedByZ;
+    // Whether we have a visible secure layer on this display
+    bool mSecureLayerVisible;
 
 
     // this used to be in GraphicPlane
@@ -157,13 +174,12 @@
     int                     mUserDisplayWidth;
     int                     mUserDisplayHeight;
 
-
     mutable Mutex   mLock;
 
-    // protected by mLock
+    /*
+     *  protected by mLock
+     */
     wp<VSyncHandler>    mVSyncHandler;
-
-    sp<FramebufferSurface> mNativeWindow;
 };
 
 }; // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 6cfb190..7695e7f 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -38,6 +38,15 @@
 namespace android {
 // ----------------------------------------------------------------------------
 
+sp<FramebufferSurface> FramebufferSurface::create() {
+    sp<FramebufferSurface> result = new FramebufferSurface();
+    if (result->fbDev == NULL) {
+        result = NULL;
+    }
+    return result;
+}
+
+// ----------------------------------------------------------------------------
 
 /*
  * This implements the (main) framebuffer management. This class is used
@@ -64,10 +73,19 @@
         mUpdateOnDemand = (fbDev->setUpdateRect != 0);
 
         const_cast<uint32_t&>(ANativeWindow::flags) = fbDev->flags;
-        const_cast<float&>(ANativeWindow::xdpi) = fbDev->xdpi;
-        const_cast<float&>(ANativeWindow::ydpi) = fbDev->ydpi;
         const_cast<int&>(ANativeWindow::minSwapInterval) =  fbDev->minSwapInterval;
         const_cast<int&>(ANativeWindow::maxSwapInterval) =  fbDev->maxSwapInterval;
+
+        if (fbDev->xdpi == 0 || fbDev->ydpi == 0) {
+            ALOGE("invalid screen resolution from fb HAL (xdpi=%f, ydpi=%f), "
+                   "defaulting to 160 dpi", fbDev->xdpi, fbDev->ydpi);
+            const_cast<float&>(ANativeWindow::xdpi) = 160;
+            const_cast<float&>(ANativeWindow::ydpi) = 160;
+        } else {
+            const_cast<float&>(ANativeWindow::xdpi) = fbDev->xdpi;
+            const_cast<float&>(ANativeWindow::ydpi) = fbDev->ydpi;
+        }
+
     } else {
         ALOGE("Couldn't get gralloc module");
     }
@@ -139,6 +157,19 @@
     }
 }
 
+float FramebufferSurface::getRefreshRate() const {
+    /* FIXME: REFRESH_RATE 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
+    return fbDev->fps;
+#else
+    return REFRESH_RATE;
+#warning "refresh rate set via makefile to REFRESH_RATE"
+#endif
+}
+
 status_t FramebufferSurface::setUpdateRectangle(const Rect& r)
 {
     if (!mUpdateOnDemand) {
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index 5b4fd01..672bfbb 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -37,11 +37,11 @@
 
 class FramebufferSurface : public SurfaceTextureClient {
 public:
-    FramebufferSurface();
 
-    virtual void onFirstRef();
+    static sp<FramebufferSurface> create();
 
-    framebuffer_device_t const * getDevice() const { return fbDev; }
+    // TODO: this should be coming from HWC
+    float getRefreshRate() const;
 
     bool isUpdateOnDemand() const { return mUpdateOnDemand; }
     status_t setUpdateRectangle(const Rect& updateRect);
@@ -49,7 +49,11 @@
 
     void dump(String8& result);
 
+protected:
+    virtual void onFirstRef();
+
 private:
+    FramebufferSurface();
     virtual ~FramebufferSurface(); // this class cannot be overloaded
     virtual int query(int what, int* value) const;
 
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index a09b5c7..b2f2683 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -182,11 +182,8 @@
         return err;
     }
 
-    // the display's pixel format
-    // XXX: we shouldn't rely on the DisplayHardware to do this
-    const DisplayHardware& hw(mFlinger->getDefaultDisplayHardware());
     uint32_t const maxSurfaceDims = min(
-            hw.getMaxTextureSize(), hw.getMaxViewportDims());
+            mFlinger->getMaxTextureSize(), mFlinger->getMaxViewportDims());
 
     // never allow a surface larger than what our underlying GL implementation
     // can handle.
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index d227b2d..c689297 100644
--- a/services/surfaceflinger/LayerBase.h
+++ b/services/surfaceflinger/LayerBase.h
@@ -25,6 +25,7 @@
 #include <GLES/gl.h>
 
 #include <utils/RefBase.h>
+#include <utils/String8.h>
 
 #include <ui/Region.h>
 
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 6c900be..840222c 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -59,6 +59,7 @@
 #include "LayerScreenshot.h"
 #include "SurfaceFlinger.h"
 
+#include "DisplayHardware/FramebufferSurface.h"
 #include "DisplayHardware/HWComposer.h"
 
 #include <private/android_filesystem_config.h>
@@ -98,7 +99,6 @@
         mDebugInTransaction(0),
         mLastTransactionTime(0),
         mBootFinished(false),
-        mSecureFrameBuffer(0),
         mExternalDisplaySurface(EGL_NO_SURFACE)
 {
     init();
@@ -142,6 +142,9 @@
 SurfaceFlinger::~SurfaceFlinger()
 {
     glDeleteTextures(1, &mWormholeTexName);
+    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+    eglTerminate(display);
 }
 
 void SurfaceFlinger::binderDied(const wp<IBinder>& who)
@@ -198,59 +201,95 @@
     property_set("service.bootanim.exit", "1");
 }
 
-static inline uint16_t pack565(int r, int g, int b) {
-    return (r<<11)|(g<<5)|b;
+status_t SurfaceFlinger::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;
 }
 
-status_t SurfaceFlinger::readyToRun()
-{
-    ALOGI(  "SurfaceFlinger's main thread ready to run. "
-            "Initializing graphics H/W...");
+EGLConfig SurfaceFlinger::selectEGLConfig(EGLDisplay display, EGLint nativeVisualId) {
+    // select our EGLConfig. It must support EGL_RECORDABLE_ANDROID if
+    // it is to be used with WIFI displays
+    EGLConfig config;
+    EGLint dummy;
+    status_t err;
+    EGLint attribs[] = {
+            EGL_SURFACE_TYPE,           EGL_WINDOW_BIT,
+            EGL_RECORDABLE_ANDROID,     EGL_TRUE,
+            EGL_NONE
+    };
+    err = selectConfigForPixelFormat(display, attribs, nativeVisualId, &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, nativeVisualId, &config);
+    }
+    ALOGE_IF(err, "couldn't find an EGLConfig matching the screen format");
+    if (eglGetConfigAttrib(display, config, EGL_CONFIG_CAVEAT, &dummy) == EGL_TRUE) {
+        ALOGW_IF(dummy == EGL_SLOW_CONFIG, "EGL_SLOW_CONFIG selected!");
+    }
+    return config;
+}
 
-    // we only support one display currently
-    int dpy = 0;
+EGLContext SurfaceFlinger::createGLContext(EGLDisplay display, EGLConfig config) {
+    // Also create our EGLContext
+    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
+    };
+    EGLContext ctxt = eglCreateContext(display, config, NULL, contextAttributes);
+    ALOGE_IF(ctxt==EGL_NO_CONTEXT, "EGLContext creation failed");
+    return ctxt;
+}
 
-    {
-        // initialize the main display
-        // TODO: initialize all displays
-        DisplayHardware* const hw = new DisplayHardware(this, dpy);
-        mDisplayHardwares[0] = hw;
+void SurfaceFlinger::initializeGL(EGLDisplay display, EGLSurface surface) {
+    EGLBoolean result = eglMakeCurrent(display, surface, surface, mEGLContext);
+    if (!result) {
+        ALOGE("Couldn't create a working GLES context. check logs. exiting...");
+        exit(0);
     }
 
-    // create the shared control-block
-    mServerHeap = new MemoryHeapBase(4096,
-            MemoryHeapBase::READ_ONLY, "SurfaceFlinger read-only heap");
-    ALOGE_IF(mServerHeap==0, "can't create shared memory dealer");
+    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));
 
-    mServerCblk = static_cast<surface_flinger_cblk_t*>(mServerHeap->getBase());
-    ALOGE_IF(mServerCblk==0, "can't get to shared control block's address");
+    EGLint w, h;
+    eglQuerySurface(display, surface, EGL_WIDTH,  &w);
+    eglQuerySurface(display, surface, EGL_HEIGHT, &h);
 
-    new(mServerCblk) surface_flinger_cblk_t;
+    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
+    glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);
 
-    // initialize primary screen
-    // (other display should be initialized in the same manner, but
-    // asynchronously, as they could come and go. None of this is supported
-    // yet).
-    const DisplayHardware& hw(getDefaultDisplayHardware());
-    const uint32_t w = hw.getWidth();
-    const uint32_t h = hw.getHeight();
-    const uint32_t f = hw.getFormat();
-    hw.makeCurrent();
-
-    // initialize the shared control block
-    mServerCblk->connected |= 1<<dpy;
-    display_cblk_t* dcblk = mServerCblk->displays + dpy;
-    memset(dcblk, 0, sizeof(display_cblk_t));
-    dcblk->w            = w; // XXX: plane.getWidth();
-    dcblk->h            = h; // XXX: plane.getHeight();
-    dcblk->format       = f;
-    dcblk->orientation  = ISurfaceComposer::eOrientationDefault;
-    dcblk->xdpi         = hw.getDpiX();
-    dcblk->ydpi         = hw.getDpiY();
-    dcblk->fps          = hw.getRefreshRate();
-    dcblk->density      = hw.getDensity();
-
-    // Initialize OpenGL|ES
     glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
     glPixelStorei(GL_PACK_ALIGNMENT, 4);
     glEnableClientState(GL_VERTEX_ARRAY);
@@ -258,6 +297,12 @@
     glDisable(GL_DITHER);
     glDisable(GL_CULL_FACE);
 
+    struct pack565 {
+        inline uint16_t operator() (int r, int g, int b) const {
+            return (r<<11)|(g<<5)|b;
+        }
+    } pack565;
+
     const uint16_t g0 = pack565(0x0F,0x1F,0x0F);
     const uint16_t g1 = pack565(0x17,0x2f,0x17);
     const uint16_t wormholeTexData[4] = { g0, g1, g1, g0 };
@@ -286,15 +331,77 @@
     // put the origin in the left-bottom corner
     glOrthof(0, w, 0, h, 0, 1); // l=0, r=w ; b=0, t=h
 
+    // print some debugging info
+    EGLint r,g,b,a;
+    eglGetConfigAttrib(display, mEGLConfig, EGL_RED_SIZE,   &r);
+    eglGetConfigAttrib(display, mEGLConfig, EGL_GREEN_SIZE, &g);
+    eglGetConfigAttrib(display, mEGLConfig, EGL_BLUE_SIZE,  &b);
+    eglGetConfigAttrib(display, mEGLConfig, EGL_ALPHA_SIZE, &a);
+    ALOGI("EGL informations:");
+    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, mEGLConfig);
+    ALOGI("OpenGL ES 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]);
+}
+
+surface_flinger_cblk_t* SurfaceFlinger::getControlBlock() const {
+    return mServerCblk;
+}
+
+status_t SurfaceFlinger::readyToRun()
+{
+    ALOGI(  "SurfaceFlinger's main thread ready to run. "
+            "Initializing graphics H/W...");
+
+    // create the shared control-block
+    mServerHeap = new MemoryHeapBase(4096,
+            MemoryHeapBase::READ_ONLY, "SurfaceFlinger read-only heap");
+    ALOGE_IF(mServerHeap==0, "can't create shared memory dealer");
+    mServerCblk = static_cast<surface_flinger_cblk_t*>(mServerHeap->getBase());
+    ALOGE_IF(mServerCblk==0, "can't get to shared control block's address");
+    new(mServerCblk) surface_flinger_cblk_t;
+
+
+    // initialize EGL
+    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    eglInitialize(display, NULL, NULL);
+
+    // Initialize the main display
+    // create native window to main display
+    sp<FramebufferSurface> anw = FramebufferSurface::create();
+    ANativeWindow* const window = anw.get();
+    if (!window) {
+        ALOGE("Display subsystem failed to initialize. check logs. exiting...");
+        exit(0);
+    }
+
+    // initialize the config and context
+    int format;
+    window->query(window, NATIVE_WINDOW_FORMAT, &format);
+    mEGLConfig  = selectEGLConfig(display, format);
+    mEGLContext = createGLContext(display, mEGLConfig);
+
+    // initialize our main display hardware
+    DisplayHardware* const hw = new DisplayHardware(this, 0, anw, mEGLConfig);
+    mDisplayHardwares[0] = hw;
+
+    //  initialize OpenGL ES
+    EGLSurface surface = hw->getEGLSurface();
+    initializeGL(display, surface);
 
     // start the EventThread
     mEventThread = new EventThread(this);
     mEventQueue.setEventThread(mEventThread);
 
-    /*
-     *  We're now ready to accept clients...
-     */
-
+    // We're now ready to accept clients...
     mReadyToRunBarrier.open();
 
     // start boot animation
@@ -309,6 +416,15 @@
     property_set("ctl.start", "bootanim");
 }
 
+uint32_t SurfaceFlinger::getMaxTextureSize() const {
+    return mMaxTextureSize;
+}
+
+uint32_t SurfaceFlinger::getMaxViewportDims() const {
+    return mMaxViewportDims[0] < mMaxViewportDims[1] ?
+            mMaxViewportDims[0] : mMaxViewportDims[1];
+}
+
 // ----------------------------------------------------------------------------
 
 bool SurfaceFlinger::authenticateSurfaceTexture(
@@ -367,7 +483,7 @@
     if (display != NULL) {
         stc = new SurfaceTextureClient(display);
         result = eglCreateWindowSurface(hw.getEGLDisplay(),
-                hw.getEGLConfig(), (EGLNativeWindowType)stc.get(), NULL);
+                mEGLConfig, (EGLNativeWindowType)stc.get(), NULL);
         ALOGE_IF(result == EGL_NO_SURFACE,
                 "eglCreateWindowSurface failed (ISurfaceTexture=%p)",
                 display.get());
@@ -465,6 +581,40 @@
 void SurfaceFlinger::handleMessageRefresh() {
     handleRefresh();
 
+    if (mVisibleRegionsDirty) {
+        Region opaqueRegion;
+        Region dirtyRegion;
+        const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
+        computeVisibleRegions(currentLayers, dirtyRegion, opaqueRegion);
+        mDirtyRegion.orSelf(dirtyRegion);
+
+        /*
+         *  rebuild the visible layer list per screen
+         */
+
+        // TODO: iterate through all displays
+        DisplayHardware& hw(const_cast<DisplayHardware&>(getDisplayHardware(0)));
+
+        Vector< sp<LayerBase> > layersSortedByZ;
+        const size_t count = currentLayers.size();
+        for (size_t i=0 ; i<count ; i++) {
+            if (!currentLayers[i]->visibleRegion.isEmpty()) {
+                // TODO: also check that this layer is associated to this display
+                layersSortedByZ.add(currentLayers[i]);
+            }
+        }
+        hw.setVisibleLayersSortedByZ(layersSortedByZ);
+
+
+        // FIXME: mWormholeRegion needs to be calculated per screen
+        //const DisplayHardware& hw(getDefaultDisplayHardware()); // XXX: we can't keep that here
+        mWormholeRegion = Region(hw.getBounds()).subtract(
+                hw.getTransform().transform(opaqueRegion) );
+        mVisibleRegionsDirty = false;
+        invalidateHwcGeometry();
+    }
+
+
     // XXX: dirtyRegion should be per screen, we should check all of them
     if (mDirtyRegion.isEmpty()) {
         return;
@@ -515,7 +665,8 @@
             glClear(GL_COLOR_BUFFER_BIT);
             glMatrixMode(GL_MODELVIEW);
             glLoadIdentity();
-            const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
+
+            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]);
@@ -546,7 +697,8 @@
 
     const DisplayHardware& hw(getDefaultDisplayHardware());
     HWComposer& hwc(hw.getHwComposer());
-    size_t numLayers = mVisibleLayersSortedByZ.size();
+    const Vector< sp<LayerBase> >& layers(hw.getVisibleLayersSortedByZ());
+    size_t numLayers = layers.size();
     const nsecs_t now = systemTime();
     mDebugInSwapBuffers = now;
 
@@ -555,7 +707,7 @@
         const HWComposer::LayerListIterator end = hwc.end();
         for (size_t i = 0; cur != end && i < numLayers; ++i, ++cur) {
             if (cur->getCompositionType() == HWC_OVERLAY) {
-                mVisibleLayersSortedByZ[i]->setAcquireFence(*cur);
+                layers[i]->setAcquireFence(*cur);
             } else {
                 cur->setAcquireFenceFd(-1);
             }
@@ -568,11 +720,11 @@
         HWComposer::LayerListIterator cur = hwc.begin();
         const HWComposer::LayerListIterator end = hwc.end();
         for (size_t i = 0; cur != end && i < numLayers; ++i, ++cur) {
-            mVisibleLayersSortedByZ[i]->onLayerDisplayed(&*cur);
+            layers[i]->onLayerDisplayed(&*cur);
         }
     } else {
         for (size_t i = 0; i < numLayers; i++) {
-            mVisibleLayersSortedByZ[i]->onLayerDisplayed(NULL);
+            layers[i]->onLayerDisplayed(NULL);
         }
     }
 
@@ -713,7 +865,7 @@
     Region aboveCoveredLayers;
     Region dirty;
 
-    bool secureFrameBuffer = false;
+    dirtyRegion.clear();
 
     size_t i = currentLayers.size();
     while (i--) {
@@ -823,14 +975,8 @@
         // Store the visible region is screen space
         layer->setVisibleRegion(visibleRegion);
         layer->setCoveredRegion(coveredRegion);
-
-        // If a secure layer is partially visible, lock-down the screen!
-        if (layer->isSecure() && !visibleRegion.isEmpty()) {
-            secureFrameBuffer = true;
-        }
     }
 
-    mSecureFrameBuffer = secureFrameBuffer;
     opaqueRegion = aboveOpaqueLayers;
 }
 
@@ -849,30 +995,7 @@
         dirtyRegion.orSelf( layer->latchBuffer(visibleRegions) );
     }
 
-    if (visibleRegions || mVisibleRegionsDirty) {
-        Region opaqueRegion;
-        computeVisibleRegions(currentLayers, dirtyRegion, opaqueRegion);
-
-        /*
-         *  rebuild the visible layer list
-         */
-
-        // XXX: mVisibleLayersSortedByZ should be per-screen
-        const size_t count = currentLayers.size();
-        mVisibleLayersSortedByZ.clear();
-        mVisibleLayersSortedByZ.setCapacity(count);
-        for (size_t i=0 ; i<count ; i++) {
-            if (!currentLayers[i]->visibleRegion.isEmpty())
-                mVisibleLayersSortedByZ.add(currentLayers[i]);
-        }
-
-        // FIXME: mWormholeRegion needs to be calculated per screen
-        const DisplayHardware& hw(getDefaultDisplayHardware()); // XXX: we can't keep that here
-        mWormholeRegion = Region(hw.getBounds()).subtract(
-                hw.getTransform().transform(opaqueRegion) );
-        mVisibleRegionsDirty = false;
-        invalidateHwcGeometry();
-    }
+    mVisibleRegionsDirty |= visibleRegions;
 
     return dirtyRegion;
 }
@@ -904,7 +1027,7 @@
     mHwWorkListDirty = false;
     HWComposer& hwc(hw.getHwComposer());
     if (hwc.initCheck() == NO_ERROR) {
-        const Vector< sp<LayerBase> >& currentLayers(mVisibleLayersSortedByZ);
+        const Vector< sp<LayerBase> >& currentLayers(hw.getVisibleLayersSortedByZ());
         const size_t count = currentLayers.size();
         hwc.createWorkList(count);
 
@@ -971,7 +1094,7 @@
         return;
     }
 
-    const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
+    const Vector< sp<LayerBase> >& layers(hw.getVisibleLayersSortedByZ());
     size_t count = layers.size();
 
     ALOGE_IF(hwc.getNumLayers() != count,
@@ -1025,25 +1148,29 @@
          * and then, render the layers targeted at the framebuffer
          */
 
-        const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
+        const Vector< sp<LayerBase> >& layers(hw.getVisibleLayersSortedByZ());
         const size_t count = layers.size();
         const Transform& tr = hw.getTransform();
-        for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
+        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()) {
-                if (cur->getCompositionType() == HWC_OVERLAY) {
+                if (cur != end && cur->getCompositionType() == HWC_OVERLAY) {
                     if (i && (cur->getHints() & HWC_HINT_CLEAR_FB)
                             && layer->isOpaque()) {
                         // never clear the very first layer since we're
                         // guaranteed the FB is already cleared
                         layer->clearWithOpenGL(hw, clip);
                     }
+                    ++cur;
                     continue;
                 }
                 // render the layer
                 layer->draw(hw, clip);
             }
+            if (cur != end) {
+                ++cur;
+            }
         }
     }
 }
@@ -1741,7 +1868,7 @@
             hwc.initCheck()==NO_ERROR ? "present" : "not present",
                     (mDebugDisableHWC || mDebugRegion) ? "disabled" : "enabled");
     result.append(buffer);
-    hwc.dump(result, buffer, SIZE, mVisibleLayersSortedByZ);
+    hwc.dump(result, buffer, SIZE, hw.getVisibleLayersSortedByZ());
 
     /*
      * Dump gralloc state
@@ -1931,7 +2058,7 @@
     glClear(GL_COLOR_BUFFER_BIT);
     glMatrixMode(GL_MODELVIEW);
     glLoadIdentity();
-    const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
+    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]);
@@ -2428,19 +2555,27 @@
     status_t result = PERMISSION_DENIED;
 
     // only one display supported for now
-    if (CC_UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
+    if (CC_UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT)) {
         return BAD_VALUE;
+    }
 
-    if (!GLExtensions::getInstance().haveFramebufferObject())
+    if (!GLExtensions::getInstance().haveFramebufferObject()) {
         return INVALID_OPERATION;
+    }
 
     // get screen geometry
     const DisplayHardware& hw(getDisplayHardware(dpy));
     const uint32_t hw_w = hw.getWidth();
     const uint32_t hw_h = hw.getHeight();
 
-    if ((sw > hw_w) || (sh > hw_h))
+    // if we have secure windows on this display, never allow the screen capture
+    if (hw.getSecureLayerVisible()) {
+        return PERMISSION_DENIED;
+    }
+
+    if ((sw > hw_w) || (sh > hw_h)) {
         return BAD_VALUE;
+    }
 
     sw = (!sw) ? hw_w : sw;
     sh = (!sh) ? hw_h : sh;
@@ -2579,14 +2714,8 @@
         }
         virtual bool handler() {
             Mutex::Autolock _l(flinger->mStateLock);
-
-            // if we have secure windows, never allow the screen capture
-            if (flinger->mSecureFrameBuffer)
-                return true;
-
             result = flinger->captureScreenImplLocked(dpy,
                     heap, w, h, f, sw, sh, minLayerZ, maxLayerZ);
-
             return true;
         }
     };
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 91cc6a5..4af31fb 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -148,6 +148,8 @@
 
     GLuint getProtectedTexName() const { return mProtectedTexName; }
 
+    surface_flinger_cblk_t* getControlBlock() const;
+
 
     class MessageDestroyGLTexture : public MessageBase {
         GLuint texture;
@@ -294,6 +296,18 @@
             void        debugFlashRegions(const DisplayHardware& hw);
             void        drawWormhole() const;
 
+            uint32_t    getMaxTextureSize() const;
+            uint32_t    getMaxViewportDims() const;
+
+            static status_t selectConfigForPixelFormat(
+                    EGLDisplay dpy,
+                    EGLint const* attrs,
+                    PixelFormat format,
+                    EGLConfig* outConfig);
+            static EGLConfig selectEGLConfig(EGLDisplay disp, EGLint visualId);
+            static EGLContext createGLContext(EGLDisplay disp, EGLConfig config);
+            void initializeGL(EGLDisplay display, EGLSurface surface);
+
             void        startBootAnim();
 
             void listLayersLocked(const Vector<String16>& args, size_t& index,
@@ -331,6 +345,11 @@
                 GLuint                      mProtectedTexName;
                 nsecs_t                     mBootTime;
                 sp<EventThread>             mEventThread;
+                GLint                       mMaxViewportDims[2];
+                GLint                       mMaxTextureSize;
+                EGLContext                  mEGLContext;
+                EGLConfig                   mEGLConfig;
+
 
                 // Can only accessed from the main thread, these members
                 // don't need synchronization
@@ -342,7 +361,6 @@
                 bool                        mVisibleRegionsDirty;
                 bool                        mHwWorkListDirty;
                 int32_t                     mElectronBeamAnimationMode;
-                Vector< sp<LayerBase> >     mVisibleLayersSortedByZ;
 
 
                 // don't use a lock for these, we don't care
@@ -364,9 +382,6 @@
     mutable     Mutex                       mDestroyedLayerLock;
                 Vector<LayerBase const *>   mDestroyedLayers;
 
-   // only written in the main thread, only read in other threads
-   volatile     int32_t                     mSecureFrameBuffer;
-
 
    EGLSurface getExternalDisplaySurface() const;
    sp<SurfaceTextureClient> mExternalDisplayNativeWindow;