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

SurfaceFlinger rework for new EGL driver model support.
diff --git a/libs/ui/Surface.cpp b/libs/ui/Surface.cpp
index 4ea9ae2..357e4d0 100644
--- a/libs/ui/Surface.cpp
+++ b/libs/ui/Surface.cpp
@@ -23,24 +23,126 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 
-#include <utils/Atomic.h>
 #include <utils/Errors.h>
 #include <utils/threads.h>
 #include <utils/IPCThreadState.h>
 #include <utils/IMemory.h>
 #include <utils/Log.h>
 
+#include <ui/DisplayInfo.h>
+#include <ui/BufferMapper.h>
+#include <ui/EGLNativeWindowSurface.h>
 #include <ui/ISurface.h>
 #include <ui/Surface.h>
 #include <ui/SurfaceComposerClient.h>
 #include <ui/Rect.h>
 
+#include <EGL/android_natives.h>
+
 #include <private/ui/SharedState.h>
 #include <private/ui/LayerState.h>
 
+#include <pixelflinger/pixelflinger.h>
+
 namespace android {
 
-// ---------------------------------------------------------------------------
+// ============================================================================
+//  SurfaceBuffer
+// ============================================================================
+
+SurfaceBuffer::SurfaceBuffer() 
+    : BASE(), handle(0), mOwner(false)
+{
+    width  = 
+    height = 
+    stride = 
+    format = 
+    usage  = 0;
+    android_native_buffer_t::getHandle = getHandle;
+}
+
+SurfaceBuffer::SurfaceBuffer(const Parcel& data) 
+    : BASE(), handle(0), mOwner(true)
+{
+    // we own the handle in this case
+    width  = data.readInt32();
+    height = data.readInt32();
+    stride = data.readInt32();
+    format = data.readInt32();
+    usage  = data.readInt32();
+    handle = data.readNativeHandle();
+    android_native_buffer_t::getHandle = getHandle;
+}
+
+SurfaceBuffer::~SurfaceBuffer()
+{
+    if (handle && mOwner) {
+        native_handle_close(handle);
+        native_handle_delete(const_cast<native_handle*>(handle));
+    }
+}
+
+int SurfaceBuffer::getHandle(android_native_buffer_t const * base, 
+        buffer_handle_t* handle)
+{
+    *handle = getSelf(base)->handle;
+    return 0;
+}
+
+status_t SurfaceBuffer::writeToParcel(Parcel* reply, 
+        android_native_buffer_t const* buffer)
+{
+    buffer_handle_t handle;
+    status_t err = buffer->getHandle(buffer, &handle);
+    if (err < 0) {
+        return err;
+    }
+    reply->writeInt32(buffer->width);
+    reply->writeInt32(buffer->height);
+    reply->writeInt32(buffer->stride);
+    reply->writeInt32(buffer->format);
+    reply->writeInt32(buffer->usage);
+    reply->writeNativeHandle(handle);
+    return NO_ERROR;
+}
+
+// ----------------------------------------------------------------------
+
+static void copyBlt(const android_native_buffer_t* dst,
+        const android_native_buffer_t* src, const Region& reg)
+{
+    Region::iterator iterator(reg);
+    if (iterator) {
+        // NOTE: dst and src must be the same format
+        Rect r;
+        const size_t bpp = bytesPerPixel(src->format);
+        const size_t dbpr = dst->stride * bpp;
+        const size_t sbpr = src->stride * bpp;
+        while (iterator.iterate(&r)) {
+            ssize_t h = r.bottom - r.top;
+            if (h) {
+                size_t size = (r.right - r.left) * bpp;
+                uint8_t* s = (GGLubyte*)src->bits + 
+                        (r.left + src->stride * r.top) * bpp;
+                uint8_t* d = (GGLubyte*)dst->bits +
+                        (r.left + dst->stride * r.top) * bpp;
+                if (dbpr==sbpr && size==sbpr) {
+                    size *= h;
+                    h = 1;
+                }
+                do {
+                    memcpy(d, s, size);
+                    d += dbpr;
+                    s += sbpr;
+                } while (--h > 0);
+            }
+        }
+    }
+}
+
+// ============================================================================
+//  Surface
+// ============================================================================
 
 Surface::Surface(const sp<SurfaceComposerClient>& client, 
         const sp<ISurface>& surface,
@@ -51,26 +153,44 @@
       mToken(data.token), mIdentity(data.identity),
       mFormat(format), mFlags(flags), mOwner(owner)
 {
+    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;
+
     mSwapRectangle.makeInvalid();
-    mSurfaceHeapBase[0] = 0;
-    mSurfaceHeapBase[1] = 0;
-    mHeap[0] = data.heap[0]; 
-    mHeap[1] = data.heap[1];
+
+    DisplayInfo dinfo;
+    SurfaceComposerClient::getDisplayInfo(0, &dinfo);
+    const_cast<float&>(android_native_window_t::xdpi) = dinfo.xdpi;
+    const_cast<float&>(android_native_window_t::ydpi) = dinfo.ydpi;
+    // FIXME: set real values here
+    const_cast<int&>(android_native_window_t::minSwapInterval) = 1;
+    const_cast<int&>(android_native_window_t::maxSwapInterval) = 1;
+    const_cast<uint32_t&>(android_native_window_t::flags) = 0;
 }
 
 Surface::Surface(Surface const* rhs)
     : mOwner(false)
 {
-    mToken   = rhs->mToken;
-    mIdentity= rhs->mIdentity;
-    mClient  = rhs->mClient;
-    mSurface = rhs->mSurface;
-    mHeap[0] = rhs->mHeap[0];
-    mHeap[1] = rhs->mHeap[1];
-    mFormat  = rhs->mFormat;
-    mFlags   = rhs->mFlags;
-    mSurfaceHeapBase[0] = rhs->mSurfaceHeapBase[0];
-    mSurfaceHeapBase[1] = rhs->mSurfaceHeapBase[1];
+    // FIXME: we really should get rid of this ctor. the memcpy below
+    //should be safe for now, but android_native_window_t is not supposed
+    // to be clonable.
+    memcpy( static_cast<android_native_window_t*>(this),
+            static_cast<android_native_window_t const *>(rhs),
+            sizeof(android_native_window_t));
+
+    mToken      = rhs->mToken;
+    mIdentity   = rhs->mIdentity;
+    mClient     = rhs->mClient;
+    mSurface    = rhs->mSurface;
+    mBuffers[0] = rhs->mBuffers[0];
+    mBuffers[1] = rhs->mBuffers[1];
+    mFormat     = rhs->mFormat;
+    mFlags      = rhs->mFlags;
     mSwapRectangle.makeInvalid();
 }
 
@@ -78,21 +198,26 @@
 {
     if (mOwner && mToken>=0 && mClient!=0) {
         mClient->destroySurface(mToken);
+        if (mBuffers[0] != 0) {
+            BufferMapper::get().unmap(mBuffers[0]->getHandle());
+        }
+        if (mBuffers[1] != 0) {
+            BufferMapper::get().unmap(mBuffers[1]->getHandle());
+        }
     }
     mClient.clear();
     mSurface.clear();
-    mHeap[0].clear();
-    mHeap[1].clear();
     IPCThreadState::self()->flushCommands();
 }
 
 sp<Surface> Surface::dup() const
 {
+    // FIXME: we should get rid of Surface::dup()
     Surface const * r = this;
     if (this && mOwner) {
         // the only reason we need to do this is because of Java's garbage
         // collector: because we're creating a copy of the Surface
-        // instead of a reference, we can garantee that when our last
+        // instead of a reference, we can guarantee that when our last
         // reference goes away, the real surface will be deleted.
         // Without this hack (the code is correct too), we'd have to
         // wait for a GC for the surface to go away.
@@ -101,31 +226,244 @@
     return const_cast<Surface*>(r);
 }
 
-status_t Surface::nextBuffer(SurfaceInfo* info) {
-    return mClient->nextBuffer(this, info);
+status_t Surface::validate(per_client_cblk_t const* cblk) const
+{
+    if (cblk == 0) {
+        LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity);
+        return NO_INIT;
+    }
+    status_t err = cblk->validate(mToken);
+    if (err != NO_ERROR) {
+        LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)",
+                mToken, mIdentity, err, strerror(-err));
+        return err;
+    }
+    if (mIdentity != uint32_t(cblk->layers[mToken].identity)) {
+        LOGE("using an invalid surface id=%d, identity=%u should be %d",
+                mToken, mIdentity, cblk->layers[mToken].identity);
+        return NO_INIT;
+    }
+    return NO_ERROR;
 }
 
+// ----------------------------------------------------------------------------
+
+int Surface::setSwapRectangle(android_native_window_t* window,
+        int l, int t, int w, int h)
+{
+    Surface* self = getSelf(window);
+    self->setSwapRectangle(Rect(l, t, l+w, t+h));
+    return 0;
+}
+
+void Surface::connect(android_native_window_t* window)
+{
+}
+
+void Surface::disconnect(android_native_window_t* window)
+{
+}
+
+int Surface::setSwapInterval(android_native_window_t* window, int interval)
+{
+    return 0;
+}
+
+int Surface::dequeueBuffer(android_native_window_t* window, 
+        android_native_buffer_t** buffer)
+{
+    Surface* self = getSelf(window);
+    return self->dequeueBuffer(buffer);
+}
+
+int Surface::lockBuffer(android_native_window_t* window, 
+        android_native_buffer_t* buffer)
+{
+    Surface* self = getSelf(window);
+    return self->lockBuffer(buffer);
+}
+
+int Surface::queueBuffer(android_native_window_t* window, 
+        android_native_buffer_t* buffer)
+{
+    Surface* self = getSelf(window);
+    return self->queueBuffer(buffer);
+}
+
+// ----------------------------------------------------------------------------
+
+int Surface::dequeueBuffer(android_native_buffer_t** buffer)
+{
+    // FIXME: dequeueBuffer() needs proper implementation
+
+    Mutex::Autolock _l(mSurfaceLock);
+
+    per_client_cblk_t* const cblk = mClient->mControl;
+    status_t err = validate(cblk);
+    if (err != NO_ERROR)
+        return err;
+
+    SurfaceID index(mToken); 
+    
+    int32_t backIdx = cblk->lock_layer(size_t(index),
+            per_client_cblk_t::BLOCKING);
+
+    if (backIdx < 0)
+        return status_t(backIdx); 
+
+    mBackbufferIndex = backIdx;
+    layer_cblk_t* const lcblk = &(cblk->layers[index]);
+
+    volatile const surface_info_t* const back = lcblk->surface + backIdx;
+    if (back->flags & surface_info_t::eNeedNewBuffer) {
+        getBufferLocked(backIdx);
+    }
+
+    const sp<SurfaceBuffer>& backBuffer(mBuffers[backIdx]);
+    *buffer = backBuffer.get();
+
+    return NO_ERROR;
+}
+
+int Surface::lockBuffer(android_native_buffer_t* buffer)
+{
+    // FIXME: lockBuffer() needs proper implementation
+    return 0;
+}
+
+int Surface::queueBuffer(android_native_buffer_t* buffer)
+{   
+    Mutex::Autolock _l(mSurfaceLock);
+
+    per_client_cblk_t* const cblk = mClient->mControl;
+    status_t err = validate(cblk);
+    if (err != NO_ERROR)
+        return err;
+
+    // transmit the dirty region
+    const Region dirty(swapRectangle());
+    SurfaceID index(mToken); 
+    layer_cblk_t* const lcblk = &(cblk->layers[index]);
+    _send_dirty_region(lcblk, dirty);
+
+    uint32_t newstate = cblk->unlock_layer_and_post(size_t(index));
+    if (!(newstate & eNextFlipPending))
+        mClient->signalServer();
+
+    return NO_ERROR;
+}
+
+// ----------------------------------------------------------------------------
+
 status_t Surface::lock(SurfaceInfo* info, bool blocking) {
     return Surface::lock(info, NULL, blocking);
 }
 
-status_t Surface::lock(SurfaceInfo* info, Region* dirty, bool blocking) {
-    if (heapBase(0) == 0) return INVALID_OPERATION;
-    if (heapBase(1) == 0) return INVALID_OPERATION;
-    return mClient->lockSurface(this, info, dirty, blocking);
+status_t Surface::lock(SurfaceInfo* other, Region* dirty, bool blocking) 
+{
+    // FIXME: needs some locking here
+    android_native_buffer_t* backBuffer;
+    status_t err = dequeueBuffer(&backBuffer);
+    if (err == NO_ERROR) {
+        err = lockBuffer(backBuffer);
+        if (err == NO_ERROR) {
+            backBuffer->common.incRef(&backBuffer->common);
+            mLockedBuffer = backBuffer;
+            other->w      = backBuffer->width;
+            other->h      = backBuffer->height;
+            other->s      = backBuffer->stride;
+            other->usage  = backBuffer->usage;
+            other->format = backBuffer->format;
+            other->bits   = backBuffer->bits;
+
+            // we handle copy-back here...
+            
+            const Rect bounds(backBuffer->width, backBuffer->height);
+            Region newDirtyRegion;
+
+            per_client_cblk_t* const cblk = mClient->mControl;
+            layer_cblk_t* const lcblk = &(cblk->layers[SurfaceID(mToken)]);
+            volatile const surface_info_t* const back = lcblk->surface + mBackbufferIndex;
+            if (back->flags & surface_info_t::eBufferDirty) {
+                // content is meaningless in this case and the whole surface
+                // needs to be redrawn.
+                newDirtyRegion.set(bounds);
+                if (dirty) {
+                    *dirty = newDirtyRegion;
+                }
+            } else 
+            {
+                if (dirty) {
+                    dirty->andSelf(Region(bounds));
+                    newDirtyRegion = *dirty;
+                } else {
+                    newDirtyRegion.set(bounds);
+                }
+                Region copyback;
+                if (!(lcblk->flags & eNoCopyBack)) {
+                    const Region previousDirtyRegion(dirtyRegion());
+                    copyback = previousDirtyRegion.subtract(newDirtyRegion);
+                }
+                const sp<SurfaceBuffer>& frontBuffer(mBuffers[1-mBackbufferIndex]);
+                if (!copyback.isEmpty() && frontBuffer!=0) {
+                    // copy front to back
+                    copyBlt(backBuffer, frontBuffer.get(), copyback);
+                }
+            }
+            setDirtyRegion(newDirtyRegion);
+
+
+            Rect lockBounds(backBuffer->width, backBuffer->height);
+            if (dirty) {
+                lockBounds = dirty->bounds();
+            }
+            buffer_handle_t handle;
+            backBuffer->getHandle(backBuffer, &handle);
+            status_t res = BufferMapper::get().lock(handle,
+                    GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, 
+                    lockBounds);
+            LOGW_IF(res, "failed locking buffer %d (%p)", 
+                    mBackbufferIndex, handle);
+            setSwapRectangle(lockBounds);
+        }
+    }
+    return err;
+}
+    
+status_t Surface::unlockAndPost() 
+{
+    // FIXME: needs some locking here
+
+    if (mLockedBuffer == 0)
+        return BAD_VALUE;
+
+    buffer_handle_t handle;
+    mLockedBuffer->getHandle(mLockedBuffer, &handle);
+    status_t res = BufferMapper::get().unlock(handle);
+    LOGW_IF(res, "failed unlocking buffer %d (%p)",
+            mBackbufferIndex, handle);
+
+    const Rect dirty(dirtyRegion().bounds());
+    setSwapRectangle(dirty);
+    status_t err = queueBuffer(mLockedBuffer);
+    mLockedBuffer->common.decRef(&mLockedBuffer->common);
+    mLockedBuffer = 0;
+    return err;
 }
 
-status_t Surface::unlockAndPost() {
-    if (heapBase(0) == 0) return INVALID_OPERATION;
-    if (heapBase(1) == 0) return INVALID_OPERATION;
-    return mClient->unlockAndPostSurface(this);
+void Surface::_send_dirty_region(
+        layer_cblk_t* lcblk, const Region& dirty)
+{
+    const int32_t index = (lcblk->flags & eBufferIndex) >> eBufferIndexShift;
+    flat_region_t* flat_region = lcblk->region + index;
+    status_t err = dirty.write(flat_region, sizeof(flat_region_t));
+    if (err < NO_ERROR) {
+        // region doesn't fit, use the bounds
+        const Region reg(dirty.bounds());
+        reg.write(flat_region, sizeof(flat_region_t));
+    }
 }
 
-status_t Surface::unlock() {
-    if (heapBase(0) == 0) return INVALID_OPERATION;
-    if (heapBase(1) == 0) return INVALID_OPERATION;
-    return mClient->unlockSurface(this);
-}
 
 status_t Surface::setLayer(int32_t layer) {
     return mClient->setLayer(this, layer);
@@ -183,8 +521,6 @@
     ISurfaceFlingerClient::surface_data_t data;
     sp<IBinder> clientBinder= parcel->readStrongBinder();
     sp<ISurface> surface    = interface_cast<ISurface>(parcel->readStrongBinder());
-    data.heap[0]            = interface_cast<IMemoryHeap>(parcel->readStrongBinder());
-    data.heap[1]            = interface_cast<IMemoryHeap>(parcel->readStrongBinder());
     data.token              = parcel->readInt32();
     data.identity           = parcel->readInt32();
     PixelFormat format      = parcel->readInt32();
@@ -204,21 +540,16 @@
     uint32_t identity = 0;
     sp<SurfaceComposerClient> client;
     sp<ISurface> sur;
-    sp<IMemoryHeap> heap[2];
     if (surface->isValid()) {
         token = surface->mToken;
         identity = surface->mIdentity;
         client = surface->mClient;
         sur = surface->mSurface;
-        heap[0] = surface->mHeap[0];
-        heap[1] = surface->mHeap[1];
         format = surface->mFormat;
         flags = surface->mFlags;
     }
     parcel->writeStrongBinder(client!=0  ? client->connection() : NULL);
     parcel->writeStrongBinder(sur!=0     ? sur->asBinder()      : NULL);
-    parcel->writeStrongBinder(heap[0]!=0 ? heap[0]->asBinder()  : NULL);
-    parcel->writeStrongBinder(heap[1]!=0 ? heap[1]->asBinder()  : NULL);
     parcel->writeInt32(token);
     parcel->writeInt32(identity);
     parcel->writeInt32(format);
@@ -233,23 +564,24 @@
     return lhs->mSurface->asBinder() == rhs->mSurface->asBinder();
 }
 
-void* Surface::heapBase(int i) const 
+status_t Surface::getBufferLocked(int index)
 {
-    void* heapBase = mSurfaceHeapBase[i];
-    // map lazily so it doesn't get mapped in clients that don't need it
-    if (heapBase == 0) {
-        const sp<IMemoryHeap>& heap(mHeap[i]);
-        if (heap != 0) {
-            heapBase = static_cast<uint8_t*>(heap->base());
-            if (heapBase == MAP_FAILED) {
-                heapBase = NULL;
-                LOGE("Couldn't map Surface's heap (binder=%p, heap=%p)",
-                        heap->asBinder().get(), heap.get());
-            }
-            mSurfaceHeapBase[i] = heapBase;
+    status_t err = NO_MEMORY;
+    sp<SurfaceBuffer> buffer = mSurface->getBuffer();
+    LOGE_IF(buffer==0, "ISurface::getBuffer() returned NULL");
+    if (buffer != 0) {
+        sp<SurfaceBuffer>& currentBuffer(mBuffers[index]);
+        if (currentBuffer != 0) {
+            BufferMapper::get().unmap(currentBuffer->getHandle());
+            currentBuffer.clear();
+        }
+        err = BufferMapper::get().map(buffer->getHandle(), &buffer->bits);
+        LOGW_IF(err, "map(...) failed %d (%s)", err, strerror(-err));
+        if (err == NO_ERROR) {
+            currentBuffer = buffer;
         }
     }
-    return heapBase;
+    return err; 
 }
 
 }; // namespace android