Integrate from //sandbox/mathias/donut/...@145728

SurfaceFlinger rework for new EGL driver model support.
diff --git a/libs/ui/EGLNativeWindowSurface.cpp b/libs/ui/EGLNativeWindowSurface.cpp
index f1071cf..5d9d6a4 100644
--- a/libs/ui/EGLNativeWindowSurface.cpp
+++ b/libs/ui/EGLNativeWindowSurface.cpp
@@ -20,142 +20,225 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <errno.h>
 
 #include <cutils/log.h>
 #include <cutils/atomic.h>
+#include <utils/threads.h>
 
 #include <ui/SurfaceComposerClient.h>
-#include <ui/DisplayInfo.h>
 #include <ui/Rect.h>
+#include <ui/EGLNativeWindowSurface.h>
 
 #include <EGL/egl.h>
 
 #include <pixelflinger/format.h>
+#include <pixelflinger/pixelflinger.h>
 
-#include <ui/EGLNativeWindowSurface.h>
+#include <hardware/hardware.h>
+#include <hardware/gralloc.h>
 
 // ----------------------------------------------------------------------------
 namespace android {
 // ----------------------------------------------------------------------------
 
-EGLNativeWindowSurface::EGLNativeWindowSurface(const sp<Surface>& surface)
-    : EGLNativeSurface<EGLNativeWindowSurface>(),
-    mSurface(surface), mConnected(false)
-{
-    egl_native_window_t::magic = 0x600913;
-    egl_native_window_t::version = sizeof(egl_native_window_t);
-    egl_native_window_t::ident = 0;
-    egl_native_window_t::incRef = &EGLNativeWindowSurface::hook_incRef;
-    egl_native_window_t::decRef = &EGLNativeWindowSurface::hook_decRef;
-    egl_native_window_t::swapBuffers = &EGLNativeWindowSurface::hook_swapBuffers;
-    egl_native_window_t::connect = &EGLNativeWindowSurface::hook_connect;
-    egl_native_window_t::disconnect = &EGLNativeWindowSurface::hook_disconnect;
-    
-    DisplayInfo dinfo;
-    SurfaceComposerClient::getDisplayInfo(0, &dinfo);
-    egl_native_window_t::xdpi = dinfo.xdpi;
-    egl_native_window_t::ydpi = dinfo.ydpi;
-    egl_native_window_t::fps  = dinfo.fps;
-    egl_native_window_t::flags= EGL_NATIVES_FLAG_DESTROY_BACKBUFFER;
-}
+/*
+ * This implements the (main) framebuffer management. This class is used
+ * mostly by SurfaceFlinger, but also by command line GL application.
+ * 
+ * In fact this is an implementation of android_native_window_t on top of
+ * the framebuffer.
+ * 
+ * Currently it is pretty simple, it manages only two buffers (the front and 
+ * back buffer).
+ * 
+ */
 
-EGLNativeWindowSurface::~EGLNativeWindowSurface()
+FramebufferNativeWindow::FramebufferNativeWindow() 
+    : BASE(), fbDev(0), grDev(0)
 {
-    disconnect();
-    mSurface.clear();
-    magic = 0;
-}
+    hw_module_t const* module;
+    if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
+        int stride;
+        framebuffer_open(module, &fbDev);
+        gralloc_open(module, &grDev);
+        int err;
 
-void EGLNativeWindowSurface::hook_incRef(NativeWindowType window)
-{
-    EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window);
-    that->incStrong(that);
-}
+        
+        // initialize the buffer FIFO
+        mNumBuffers = 2;
+        mNumFreeBuffers = 2;
+        mBufferHead = mNumBuffers-1;
+        buffers[0] = new NativeBuffer(
+                fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB);
+        buffers[1] = new NativeBuffer(
+                fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB);
+        
+        err = grDev->alloc(grDev,
+                fbDev->width, fbDev->height, fbDev->format, 
+                GRALLOC_USAGE_HW_FB, &buffers[0]->handle, &buffers[0]->stride);
 
-void EGLNativeWindowSurface::hook_decRef(NativeWindowType window)
-{
-    EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window);
-    that->decStrong(that);
-}
+        LOGE_IF(err, "fb buffer 0 allocation failed w=%d, h=%d, err=%s",
+                fbDev->width, fbDev->height, strerror(-err));
 
-void EGLNativeWindowSurface::hook_connect(NativeWindowType window)
-{
-    EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window);
-    that->connect();
-}
+        err = grDev->alloc(grDev,
+                fbDev->width, fbDev->height, fbDev->format, 
+                GRALLOC_USAGE_HW_FB, &buffers[1]->handle, &buffers[1]->stride);
 
-void EGLNativeWindowSurface::hook_disconnect(NativeWindowType window)
-{
-    EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window);
-    that->disconnect();
-}
+        LOGE_IF(err, "fb buffer 1 allocation failed w=%d, h=%d, err=%s",
+                fbDev->width, fbDev->height, strerror(-err));
 
-uint32_t EGLNativeWindowSurface::hook_swapBuffers(NativeWindowType window)
-{
-    EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window);
-    return that->swapBuffers();
-}
+        gralloc_module_t* m = 
+            reinterpret_cast<gralloc_module_t*>(grDev->common.module);
 
-void EGLNativeWindowSurface::setSwapRectangle(int l, int t, int w, int h)
-{
-    mSurface->setSwapRectangle(Rect(l, t, l+w, t+h));
-}
-
-uint32_t EGLNativeWindowSurface::swapBuffers()
-{
-    const int w = egl_native_window_t::width;
-    const int h = egl_native_window_t::height;
-    const sp<Surface>& surface(mSurface);
-    Surface::SurfaceInfo info;
-    surface->unlockAndPost();
-    surface->lock(&info);
-    // update the address of the buffer to draw to next
-    egl_native_window_t::base   = intptr_t(info.base);
-    egl_native_window_t::offset = intptr_t(info.bits) - intptr_t(info.base);
-    
-    // update size if it changed
-    if (w != int(info.w) || h != int(info.h)) {
-        egl_native_window_t::width  = info.w;
-        egl_native_window_t::height = info.h;
-        egl_native_window_t::stride = info.bpr / bytesPerPixel(info.format);
-        egl_native_window_t::format = info.format;
-        return EGL_NATIVES_FLAG_SIZE_CHANGED;
+        // FIXME: do we actually need to map the framebuffer?
+        m->map(m, buffers[0]->handle, &buffers[0]->bits);
+        m->map(m, buffers[1]->handle, &buffers[1]->bits);
     }
+
+    uint32_t flags = fbDev->flags & SURFACE_FLAG_MAPPED;
+    
+    /*
+     * FIXME: SURFACE_FLAG_PRESERVE_CONTENT
+     * how to implement this, there is no concept of preserve content in
+     * the framebuffer, which just "posts" buffer.
+     * 
+     * It looks like what we need is a way to know if the posted buffer can
+     * be reused. But if so, why allocating 2 buffers?...
+     * 
+     * should the lock/unlock calls take care of the copy-back?
+     * 
+     * 
+     * In the end, the client wants to know if the backbuffer is preserved
+     * though... it's complicated.
+     * 
+     */
+    
+    //flags |= SURFACE_FLAG_PRESERVE_CONTENT;
+    
+
+    const_cast<uint32_t&>(android_native_window_t::flags) = flags; 
+    const_cast<float&>(android_native_window_t::xdpi) = fbDev->xdpi;
+    const_cast<float&>(android_native_window_t::ydpi) = fbDev->ydpi;
+    const_cast<int&>(android_native_window_t::minSwapInterval) = 
+        fbDev->minSwapInterval;
+    const_cast<int&>(android_native_window_t::maxSwapInterval) = 
+        fbDev->maxSwapInterval;
+
+    android_native_window_t::connect = connect;
+    android_native_window_t::disconnect = disconnect;
+    android_native_window_t::setSwapInterval = setSwapInterval;
+    android_native_window_t::setSwapRectangle = setSwapRectangle;
+    android_native_window_t::dequeueBuffer = dequeueBuffer;
+    android_native_window_t::lockBuffer = lockBuffer;
+    android_native_window_t::queueBuffer = queueBuffer;
+}
+
+FramebufferNativeWindow::~FramebufferNativeWindow() {
+    grDev->free(grDev, buffers[0]->handle);
+    grDev->free(grDev, buffers[1]->handle);
+    gralloc_module_t* m = 
+        reinterpret_cast<gralloc_module_t*>(grDev->common.module);
+    m->unmap(m, buffers[0]->handle);
+    m->unmap(m, buffers[1]->handle);
+    gralloc_close(grDev);
+    framebuffer_close(fbDev);
+}
+
+void FramebufferNativeWindow::connect(android_native_window_t* window) 
+{
+}
+
+void FramebufferNativeWindow::disconnect(android_native_window_t* window) 
+{
+}
+
+int FramebufferNativeWindow::setSwapInterval(
+        android_native_window_t* window, int interval) 
+{
+    framebuffer_device_t* fb = getSelf(window)->fbDev;
+    return fb->setSwapInterval(fb, interval);
+}
+
+int FramebufferNativeWindow::setSwapRectangle(android_native_window_t* window,
+        int l, int t, int w, int h)
+{
+    FramebufferNativeWindow* self = getSelf(window);
+    Mutex::Autolock _l(self->mutex);
+    self->mDirty = Rect(l, t, l+w, t+h); 
     return 0;
 }
 
-void EGLNativeWindowSurface::connect()
-{   
-    if (!mConnected) {
-        Surface::SurfaceInfo info;
-        mSurface->lock(&info);
-        mSurface->setSwapRectangle(Rect(info.w, info.h));
-        mConnected = true;
+int FramebufferNativeWindow::dequeueBuffer(android_native_window_t* window, 
+        android_native_buffer_t** buffer)
+{
+    FramebufferNativeWindow* self = getSelf(window);
+    Mutex::Autolock _l(self->mutex);
+    framebuffer_device_t* fb = self->fbDev;
 
-        egl_native_window_t::width  = info.w;
-        egl_native_window_t::height = info.h;
-        egl_native_window_t::stride = info.bpr / bytesPerPixel(info.format);
-        egl_native_window_t::format = info.format;
-        egl_native_window_t::base   = intptr_t(info.base);
-        egl_native_window_t::offset = intptr_t(info.bits) - intptr_t(info.base);
-        // FIXME: egl_native_window_t::memory_type used to be set from
-        // mSurface, but we wanted to break this dependency. We set it to
-        // GPU because the software rendered doesn't care, but the h/w
-        // accelerator needs it. Eventually, this value should go away
-        // completely, since memory will be managed by OpenGL.
-        egl_native_window_t::memory_type = NATIVE_MEMORY_TYPE_GPU; 
-        egl_native_window_t::fd = 0;
+    // wait for a free buffer
+    while (!self->mNumFreeBuffers) {
+        self->mCondition.wait(self->mutex);
     }
+    // get this buffer
+    self->mNumFreeBuffers--;
+    int index = self->mBufferHead++;
+    if (self->mBufferHead >= self->mNumBuffers)
+        self->mBufferHead = 0;
+
+    *buffer = self->buffers[index].get();
+
+    return 0;
 }
 
-void EGLNativeWindowSurface::disconnect()
+int FramebufferNativeWindow::lockBuffer(android_native_window_t* window, 
+        android_native_buffer_t* buffer)
 {
-    if (mConnected) {
-        mSurface->unlock();
-        mConnected = false;
+    FramebufferNativeWindow* self = getSelf(window);
+    Mutex::Autolock _l(self->mutex);
+
+    // wait that the buffer we're locking is not front anymore
+    while (self->front == buffer) {
+        self->mCondition.wait(self->mutex);
     }
+        
+    gralloc_module_t* m = 
+        reinterpret_cast<gralloc_module_t*>(self->grDev->common.module);
+    const Rect& dirty(self->mDirty);
+
+    buffer_handle_t handle = static_cast<NativeBuffer*>(buffer)->handle;
+    int res = m->lock(m, handle, GRALLOC_USAGE_HW_FB,
+            dirty.left, dirty.right, dirty.width(), dirty.height());
+    
+    return res;
+}
+
+int FramebufferNativeWindow::queueBuffer(android_native_window_t* window, 
+        android_native_buffer_t* buffer)
+{
+    FramebufferNativeWindow* self = getSelf(window);
+    Mutex::Autolock _l(self->mutex);
+    framebuffer_device_t* fb = self->fbDev;
+    gralloc_module_t* m = 
+        reinterpret_cast<gralloc_module_t*>(self->grDev->common.module);
+
+    buffer_handle_t handle = static_cast<NativeBuffer*>(buffer)->handle;
+    m->unlock(m, handle);
+    int res = fb->post(fb, handle);
+
+    self->front = static_cast<NativeBuffer*>(buffer);
+    self->mNumFreeBuffers++;
+    self->mCondition.broadcast();
+    return res;
 }
 
 // ----------------------------------------------------------------------------
 }; // namespace android
 // ----------------------------------------------------------------------------
+
+
+EGLNativeWindowType android_createDisplaySurface(void)
+{
+    return new android::FramebufferNativeWindow();
+}
+