second take, hopefully this time it doesn't break one of the builds: "SurfaceFlinger will now allocate buffers based on the usage specified by the clients. This allows to allocate the right kind of buffer automatically, without having the user to specify anything."
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index d1142cc..8c0b40d 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -217,7 +217,7 @@
     drawWithOpenGL(clip, mTextures[index]);
 }
 
-sp<SurfaceBuffer> Layer::peekBuffer()
+sp<SurfaceBuffer> Layer::peekBuffer(int usage)
 {
     /*
      * This is called from the client's Surface::lock(), after it locked
@@ -250,7 +250,7 @@
     }
     
     LayerBitmap& layerBitmap(mBuffers[backBufferIndex]);
-    sp<SurfaceBuffer> buffer = layerBitmap.allocate();
+    sp<SurfaceBuffer> buffer = layerBitmap.allocate(usage);
     
     LOGD_IF(DEBUG_RESIZE,
             "Layer::getBuffer(this=%p), index=%d, (%d,%d), (%d,%d)",
@@ -649,12 +649,12 @@
 {
 }
 
-sp<SurfaceBuffer> Layer::SurfaceLayer::getBuffer()
+sp<SurfaceBuffer> Layer::SurfaceLayer::getBuffer(int usage)
 {
     sp<SurfaceBuffer> buffer = 0;
     sp<Layer> owner(getOwner());
     if (owner != 0) {
-        buffer = owner->peekBuffer();
+        buffer = owner->peekBuffer(usage);
     }
     return buffer;
 }
diff --git a/libs/surfaceflinger/Layer.h b/libs/surfaceflinger/Layer.h
index 4c13d6e..add5d50 100644
--- a/libs/surfaceflinger/Layer.h
+++ b/libs/surfaceflinger/Layer.h
@@ -101,7 +101,7 @@
 
     status_t resize(int32_t index, uint32_t w, uint32_t h, const char* what);
     Region post(uint32_t* oldState, bool& recomputeVisibleRegions);
-    sp<SurfaceBuffer> peekBuffer();
+    sp<SurfaceBuffer> peekBuffer(int usage);
     void destroy();
     void scheduleBroadcast();
 
@@ -114,7 +114,7 @@
                 ~SurfaceLayer();
 
     private:
-        virtual sp<SurfaceBuffer> getBuffer();
+        virtual sp<SurfaceBuffer> getBuffer(int usage);
 
         sp<Layer> getOwner() const {
             return static_cast<Layer*>(Surface::getOwner().get());
diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp
index fbce73dd..419574c 100644
--- a/libs/surfaceflinger/LayerBase.cpp
+++ b/libs/surfaceflinger/LayerBase.cpp
@@ -759,7 +759,7 @@
     return BnSurface::onTransact(code, data, reply, flags);
 }
 
-sp<SurfaceBuffer> LayerBaseClient::Surface::getBuffer() 
+sp<SurfaceBuffer> LayerBaseClient::Surface::getBuffer(int) 
 {
     return NULL; 
 }
diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h
index 6fb1d1c..65bf55b 100644
--- a/libs/surfaceflinger/LayerBase.h
+++ b/libs/surfaceflinger/LayerBase.h
@@ -335,7 +335,7 @@
         sp<LayerBaseClient> getOwner() const;
 
     private:
-        virtual sp<SurfaceBuffer> getBuffer();
+        virtual sp<SurfaceBuffer> getBuffer(int usage);
         virtual status_t registerBuffers(const ISurface::BufferHeap& buffers); 
         virtual void postBuffer(ssize_t offset);
         virtual void unregisterBuffers();
diff --git a/libs/surfaceflinger/LayerBitmap.cpp b/libs/surfaceflinger/LayerBitmap.cpp
index 5221fed..5e74451 100644
--- a/libs/surfaceflinger/LayerBitmap.cpp
+++ b/libs/surfaceflinger/LayerBitmap.cpp
@@ -38,13 +38,14 @@
 // Buffer and implementation of android_native_buffer_t
 // ===========================================================================
 
-Buffer::Buffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
+Buffer::Buffer(uint32_t w, uint32_t h, PixelFormat format,
+        uint32_t reqUsage, uint32_t flags)
     : SurfaceBuffer(), mInitCheck(NO_INIT), mFlags(flags), 
     mVStride(0)
 {
     this->format = format;
     if (w>0 && h>0) {
-        mInitCheck = initSize(w, h);
+        mInitCheck = initSize(w, h, reqUsage);
     }
 }
 
@@ -65,7 +66,7 @@
     return static_cast<android_native_buffer_t*>(const_cast<Buffer*>(this));
 }
 
-status_t Buffer::initSize(uint32_t w, uint32_t h)
+status_t Buffer::initSize(uint32_t w, uint32_t h, uint32_t reqUsage)
 {
     status_t err = NO_ERROR;
 
@@ -88,16 +89,9 @@
         usage = BufferAllocator::USAGE_SW_READ_OFTEN | 
                 BufferAllocator::USAGE_SW_WRITE_OFTEN;
     } else {
-        if (mFlags & Buffer::GPU) {
-            // the client wants to do GL rendering
-            usage = BufferAllocator::USAGE_HW_RENDER |
-                    BufferAllocator::USAGE_HW_TEXTURE;
-        } else {
-            // software rendering-client, h/w composition
-            usage = BufferAllocator::USAGE_SW_READ_OFTEN | 
-                    BufferAllocator::USAGE_SW_WRITE_OFTEN |
-                    BufferAllocator::USAGE_HW_TEXTURE;
-        }
+        // it's allowed to modify the usage flags here, but generally
+        // the requested flags should be honored.
+        usage = reqUsage | BufferAllocator::USAGE_HW_TEXTURE;
     }
 
     err = allocator.alloc(w, h, format, usage, &handle, &stride);
@@ -174,12 +168,12 @@
     return NO_ERROR;
 }
 
-sp<Buffer> LayerBitmap::allocate()
+sp<Buffer> LayerBitmap::allocate(uint32_t reqUsage)
 {
     Mutex::Autolock _l(mLock);
     surface_info_t* info = mInfo;
     mBuffer.clear(); // free buffer before allocating a new one
-    sp<Buffer> buffer = new Buffer(mWidth, mHeight, mFormat, mFlags);
+    sp<Buffer> buffer = new Buffer(mWidth, mHeight, mFormat, reqUsage, mFlags);
     status_t err = buffer->initCheck();
     if (LIKELY(err == NO_ERROR)) {
         info->flags  = surface_info_t::eBufferDirty;
diff --git a/libs/surfaceflinger/LayerBitmap.h b/libs/surfaceflinger/LayerBitmap.h
index 22525ce..48ee553 100644
--- a/libs/surfaceflinger/LayerBitmap.h
+++ b/libs/surfaceflinger/LayerBitmap.h
@@ -58,7 +58,8 @@
     };
 
     // creates w * h buffer
-    Buffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags = 0);
+    Buffer(uint32_t w, uint32_t h, PixelFormat format,
+            uint32_t reqUsage, uint32_t flags = 0);
 
     // return status
     status_t initCheck() const;
@@ -81,7 +82,7 @@
     Buffer& operator = (const Buffer& rhs);
     const Buffer& operator = (const Buffer& rhs) const;
 
-    status_t initSize(uint32_t w, uint32_t h);
+    status_t initSize(uint32_t w, uint32_t h, uint32_t reqUsage);
 
     ssize_t                 mInitCheck;
     uint32_t                mFlags;
@@ -108,7 +109,7 @@
 
     status_t setSize(uint32_t w, uint32_t h);
 
-    sp<Buffer> allocate();
+    sp<Buffer> allocate(uint32_t reqUsage);
     status_t free();
     
     sp<const Buffer>  getBuffer() const { return mBuffer; }
diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp
index 90e7f50..e1f4bea 100644
--- a/libs/surfaceflinger/LayerBuffer.cpp
+++ b/libs/surfaceflinger/LayerBuffer.cpp
@@ -28,6 +28,7 @@
 
 #include <hardware/copybit.h>
 
+#include "BufferAllocator.h"
 #include "LayerBuffer.h"
 #include "SurfaceFlinger.h"
 #include "DisplayHardware/DisplayHardware.h"
@@ -464,7 +465,10 @@
                         mTempBitmap->getWidth() < tmp_w || 
                         mTempBitmap->getHeight() < tmp_h) {
                     mTempBitmap.clear();
-                    mTempBitmap = new android::Buffer(tmp_w, tmp_h, src.img.format);
+                    mTempBitmap = new android::Buffer(
+                            tmp_w, tmp_h, src.img.format,
+                            BufferAllocator::USAGE_HW_TEXTURE |
+                            BufferAllocator::USAGE_HW_2D);
                     err = mTempBitmap->initCheck();
                 }
 
diff --git a/libs/surfaceflinger/LayerDim.cpp b/libs/surfaceflinger/LayerDim.cpp
index 8e9df9c..6ebb49f 100644
--- a/libs/surfaceflinger/LayerDim.cpp
+++ b/libs/surfaceflinger/LayerDim.cpp
@@ -21,6 +21,7 @@
 #include <utils/Errors.h>
 #include <utils/Log.h>
 
+#include "BufferAllocator.h"
 #include "LayerDim.h"
 #include "SurfaceFlinger.h"
 #include "DisplayHardware/DisplayHardware.h"
@@ -68,7 +69,11 @@
 
     if (LIKELY(flags & DisplayHardware::DIRECT_TEXTURE)) {
         // TODO: api to pass the usage flags
-        sp<Buffer> buffer = new Buffer(w, h, PIXEL_FORMAT_RGB_565);
+        sp<Buffer> buffer = new Buffer(w, h, PIXEL_FORMAT_RGB_565,
+                 BufferAllocator::USAGE_SW_WRITE_OFTEN |
+                 BufferAllocator::USAGE_HW_TEXTURE |
+                 BufferAllocator::USAGE_HW_2D);
+        
         android_native_buffer_t* clientBuf = buffer->getNativeBuffer();
 
         glGenTextures(1, &sTexId);
diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp
index f6c666d..90b5163 100644
--- a/libs/ui/FramebufferNativeWindow.cpp
+++ b/libs/ui/FramebufferNativeWindow.cpp
@@ -132,6 +132,7 @@
     android_native_window_t::lockBuffer = lockBuffer;
     android_native_window_t::queueBuffer = queueBuffer;
     android_native_window_t::query = query;
+    android_native_window_t::perform = perform;
 }
 
 FramebufferNativeWindow::~FramebufferNativeWindow() 
@@ -235,6 +236,18 @@
     return BAD_VALUE;
 }
 
+int FramebufferNativeWindow::perform(android_native_window_t* window,
+        int operation, ...)
+{
+    switch (operation) {
+        case NATIVE_WINDOW_SET_USAGE:
+            break;
+        default:
+            return NAME_NOT_FOUND;
+    }
+    return NO_ERROR;
+}
+
 // ----------------------------------------------------------------------------
 }; // namespace android
 // ----------------------------------------------------------------------------
diff --git a/libs/ui/ISurface.cpp b/libs/ui/ISurface.cpp
index 9fbae1e..b78e8b5 100644
--- a/libs/ui/ISurface.cpp
+++ b/libs/ui/ISurface.cpp
@@ -71,10 +71,11 @@
     {
     }
 
-    virtual sp<SurfaceBuffer> getBuffer()
+    virtual sp<SurfaceBuffer> getBuffer(int usage)
     {
         Parcel data, reply;
         data.writeInterfaceToken(ISurface::getInterfaceDescriptor());
+        data.writeInt32(usage);
         remote()->transact(GET_BUFFER, data, &reply);
         sp<SurfaceBuffer> buffer = new SurfaceBuffer(reply);
         return buffer;
@@ -135,7 +136,8 @@
     switch(code) {
         case GET_BUFFER: {
             CHECK_INTERFACE(ISurface, data, reply);
-            sp<SurfaceBuffer> buffer(getBuffer());
+            int usage = data.readInt32();
+            sp<SurfaceBuffer> buffer(getBuffer(usage));
             return SurfaceBuffer::writeToParcel(reply, buffer.get());
         }
         case REGISTER_BUFFERS: {
diff --git a/libs/ui/Surface.cpp b/libs/ui/Surface.cpp
index 4abb7f6..2b6905f 100644
--- a/libs/ui/Surface.cpp
+++ b/libs/ui/Surface.cpp
@@ -414,6 +414,7 @@
     android_native_window_t::lockBuffer       = lockBuffer;
     android_native_window_t::queueBuffer      = queueBuffer;
     android_native_window_t::query            = query;
+    android_native_window_t::perform          = perform;
     mSwapRectangle.makeInvalid();
     DisplayInfo dinfo;
     SurfaceComposerClient::getDisplayInfo(0, &dinfo);
@@ -423,6 +424,8 @@
     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;
+    // be default we request a hardware surface
+    mUsage = GRALLOC_USAGE_HW_RENDER;
 }
 
 
@@ -512,6 +515,17 @@
     return self->query(what, value);
 }
 
+int Surface::perform(android_native_window_t* window, 
+        int operation, ...)
+{
+    va_list args;
+    va_start(args, operation);
+    Surface* self = getSelf(window);
+    int res = self->perform(operation, args);
+    va_end(args);
+    return res;
+}
+
 // ----------------------------------------------------------------------------
 
 status_t Surface::dequeueBuffer(sp<SurfaceBuffer>* buffer)
@@ -561,7 +575,7 @@
 
     volatile const surface_info_t* const back = lcblk->surface + backIdx;
     if (back->flags & surface_info_t::eNeedNewBuffer) {
-        err = getBufferLocked(backIdx);
+        err = getBufferLocked(backIdx, mUsage);
     }
 
     if (err == NO_ERROR) {
@@ -627,6 +641,20 @@
     return BAD_VALUE;
 }
 
+int Surface::perform(int operation, va_list args)
+{
+    int res = NO_ERROR;
+    switch (operation) {
+        case NATIVE_WINDOW_SET_USAGE:
+            mUsage = va_arg(args, int);
+            break;
+        default:
+            res = NAME_NOT_FOUND;
+            break;
+    }
+    return res;
+}
+
 // ----------------------------------------------------------------------------
 
 status_t Surface::lock(SurfaceInfo* info, bool blocking) {
@@ -636,6 +664,9 @@
 status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking) 
 {
     // FIXME: needs some locking here
+
+    // we're intending to do software rendering from this point
+    mUsage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN;
     
     sp<SurfaceBuffer> backBuffer;
     status_t err = dequeueBuffer(&backBuffer);
@@ -725,10 +756,10 @@
     mSwapRectangle = r;
 }
 
-status_t Surface::getBufferLocked(int index)
+status_t Surface::getBufferLocked(int index, int usage)
 {
     status_t err = NO_MEMORY;
-    sp<SurfaceBuffer> buffer = mSurface->getBuffer();
+    sp<SurfaceBuffer> buffer = mSurface->getBuffer(usage);
     LOGE_IF(buffer==0, "ISurface::getBuffer() returned NULL");
     if (buffer != 0) {
         sp<SurfaceBuffer>& currentBuffer(mBuffers[index]);