From 0a53d5c81b5553d6063b8133492275ce88186978 Mon Sep 17 00:00:00 2001 From: Jamie Gennis Date: Mon, 20 Dec 2010 11:21:07 -0800 Subject: Add the ISurfaceComposer::createGraphicBuffer IPC. This change adds a new binder method to the ISurfaceComposer interface. This IPC is intended to allow SurfaceFlinger clients to allocate gralloc buffers using SurfaceFlinger as a proxy to gralloc. Change-Id: Ide9fc283aec5da6268ba62cfed0c3319a50b640d --- include/surfaceflinger/ISurfaceComposer.h | 8 +++++++ libs/surfaceflinger_client/ISurfaceComposer.cpp | 32 +++++++++++++++++++++++++ services/surfaceflinger/SurfaceFlinger.cpp | 19 +++++++++++++++ services/surfaceflinger/SurfaceFlinger.h | 2 ++ 4 files changed, 61 insertions(+) diff --git a/include/surfaceflinger/ISurfaceComposer.h b/include/surfaceflinger/ISurfaceComposer.h index 693fbfb..1bab7d7 100644 --- a/include/surfaceflinger/ISurfaceComposer.h +++ b/include/surfaceflinger/ISurfaceComposer.h @@ -131,6 +131,13 @@ public: * This is an ASYNCHRONOUS call. */ virtual void signal() const = 0; + + /* Create a new GraphicBuffer for the client to use. SurfaceFlinger will + * not maintain a reference to the GraphicBuffer, so the underlying native + * handle will be freed once the client references are released. + */ + virtual sp createGraphicBuffer(uint32_t w, uint32_t h, + PixelFormat format, uint32_t usage) const = 0; }; // ---------------------------------------------------------------------------- @@ -144,6 +151,7 @@ public: BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION, CREATE_CONNECTION, CREATE_CLIENT_CONNECTION, + CREATE_GRAPHIC_BUFFER, GET_CBLK, OPEN_GLOBAL_TRANSACTION, CLOSE_GLOBAL_TRANSACTION, diff --git a/libs/surfaceflinger_client/ISurfaceComposer.cpp b/libs/surfaceflinger_client/ISurfaceComposer.cpp index b8a7a79..a42b49d 100644 --- a/libs/surfaceflinger_client/ISurfaceComposer.cpp +++ b/libs/surfaceflinger_client/ISurfaceComposer.cpp @@ -26,6 +26,7 @@ #include #include +#include #include @@ -169,6 +170,25 @@ public: data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); remote()->transact(BnSurfaceComposer::SIGNAL, data, &reply, IBinder::FLAG_ONEWAY); } + + virtual sp createGraphicBuffer(uint32_t w, uint32_t h, + PixelFormat format, uint32_t usage) const { + Parcel data, reply; + data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + data.writeInt32(w); + data.writeInt32(h); + data.writeInt32(format); + data.writeInt32(usage); + remote()->transact(BnSurfaceComposer::CREATE_GRAPHIC_BUFFER, data, + &reply); + sp graphicBuffer; + bool nonNull = (bool)reply.readInt32(); + if (nonNull) { + graphicBuffer = new GraphicBuffer(); + reply.read(*graphicBuffer); + } + return graphicBuffer; + } }; IMPLEMENT_META_INTERFACE(SurfaceComposer, "android.ui.ISurfaceComposer"); @@ -247,6 +267,18 @@ status_t BnSurfaceComposer::onTransact( reply->writeInt32(f); reply->writeInt32(res); } break; + case CREATE_GRAPHIC_BUFFER: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + uint32_t w = data.readInt32(); + uint32_t h = data.readInt32(); + PixelFormat format = data.readInt32(); + uint32_t usage = data.readInt32(); + sp result(createGraphicBuffer(w, h, format, usage)); + reply->writeInt32(result != 0); + if (result != 0) { + reply->write(*result); + } + } break; case TURN_ELECTRON_BEAM_OFF: { CHECK_INTERFACE(ISurfaceComposer, data, reply); int32_t mode = data.readInt32(); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 825d90b..c982ea5 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2267,6 +2267,25 @@ sp SurfaceFlinger::getLayer(const sp& sur) const // --------------------------------------------------------------------------- +sp SurfaceFlinger::createGraphicBuffer(uint32_t w, uint32_t h, + PixelFormat format, uint32_t usage) const { + // XXX: HACK HACK HACK!!! This should NOT be static, but it is to fix a + // race between SurfaceFlinger unref'ing the buffer and the client ref'ing + // it. + static sp graphicBuffer(new GraphicBuffer(w, h, format, usage)); + status_t err = graphicBuffer->initCheck(); + if (err != 0) { + LOGE("createGraphicBuffer: init check failed: %d", err); + return 0; + } else if (graphicBuffer->handle == 0) { + LOGE("createGraphicBuffer: unable to create GraphicBuffer"); + return 0; + } + return graphicBuffer; +} + +// --------------------------------------------------------------------------- + Client::Client(const sp& flinger) : mFlinger(flinger), mNameGenerator(1) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index ca7d27d..48642d4 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -322,6 +322,8 @@ private: status_t electronBeamOnAnimationImplLocked(); status_t renderScreenToTextureLocked(DisplayID dpy, GLuint* textureName, GLfloat* uOut, GLfloat* vOut); + sp createGraphicBuffer(uint32_t w, uint32_t h, + PixelFormat format, uint32_t usage) const; friend class FreezeLock; sp getFreezeLock() const; -- cgit v1.1