diff options
author | 2009-08-10 21:59:56 -0700 | |
---|---|---|
committer | 2009-08-11 16:12:56 -0700 | |
commit | df37b62c62f8efd3b5a433f9b4d40d30cec13a31 (patch) | |
tree | 43c783e665b9e1c47210d3c5a8f929b33acda72f | |
parent | d779f052b4180f347ed0bd725fdfedda504773e5 (diff) |
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.
This change makes SurfaceHolder.setType(GPU) obsolete (it's now ignored).
Added an API to android_native_window_t to allow extending the functionality without ever breaking binary compatibility. This is used to implement the new set_usage() API. This API needs to be called by software renderers because the default is to use usage flags suitable for h/w.
-rw-r--r-- | include/ui/FramebufferNativeWindow.h | 1 | ||||
-rw-r--r-- | include/ui/ISurface.h | 2 | ||||
-rw-r--r-- | include/ui/Surface.h | 5 | ||||
-rw-r--r-- | include/ui/egl/android_natives.h | 43 | ||||
-rw-r--r-- | libs/surfaceflinger/Layer.cpp | 8 | ||||
-rw-r--r-- | libs/surfaceflinger/Layer.h | 4 | ||||
-rw-r--r-- | libs/surfaceflinger/LayerBase.cpp | 2 | ||||
-rw-r--r-- | libs/surfaceflinger/LayerBase.h | 2 | ||||
-rw-r--r-- | libs/surfaceflinger/LayerBitmap.cpp | 24 | ||||
-rw-r--r-- | libs/surfaceflinger/LayerBitmap.h | 7 | ||||
-rw-r--r-- | libs/surfaceflinger/LayerBuffer.cpp | 6 | ||||
-rw-r--r-- | libs/surfaceflinger/LayerDim.cpp | 7 | ||||
-rw-r--r-- | libs/ui/FramebufferNativeWindow.cpp | 13 | ||||
-rw-r--r-- | libs/ui/ISurface.cpp | 6 | ||||
-rw-r--r-- | libs/ui/Surface.cpp | 37 | ||||
-rw-r--r-- | opengl/libagl/egl.cpp | 4 |
16 files changed, 134 insertions, 37 deletions
diff --git a/include/ui/FramebufferNativeWindow.h b/include/ui/FramebufferNativeWindow.h index cb9bf940e2..68144b5944 100644 --- a/include/ui/FramebufferNativeWindow.h +++ b/include/ui/FramebufferNativeWindow.h @@ -63,6 +63,7 @@ private: static int lockBuffer(android_native_window_t* window, android_native_buffer_t* buffer); static int queueBuffer(android_native_window_t* window, android_native_buffer_t* buffer); static int query(android_native_window_t* window, int what, int* value); + static int perform(android_native_window_t* window, int operation, ...); framebuffer_device_t* fbDev; alloc_device_t* grDev; diff --git a/include/ui/ISurface.h b/include/ui/ISurface.h index adba45a48c..7909c2f41d 100644 --- a/include/ui/ISurface.h +++ b/include/ui/ISurface.h @@ -50,7 +50,7 @@ protected: public: DECLARE_META_INTERFACE(Surface); - virtual sp<SurfaceBuffer> getBuffer() = 0; + virtual sp<SurfaceBuffer> getBuffer(int usage) = 0; class BufferHeap { public: diff --git a/include/ui/Surface.h b/include/ui/Surface.h index d5dad31d00..4ff0e4abd8 100644 --- a/include/ui/Surface.h +++ b/include/ui/Surface.h @@ -184,7 +184,7 @@ private: friend class IOMX; const sp<ISurface>& getISurface() const { return mSurface; } - status_t getBufferLocked(int index); + status_t getBufferLocked(int index, int usage); status_t validate(per_client_cblk_t const* cblk) const; static void _send_dirty_region(layer_cblk_t* lcblk, const Region& dirty); @@ -197,11 +197,13 @@ private: static int lockBuffer(android_native_window_t* window, android_native_buffer_t* buffer); static int queueBuffer(android_native_window_t* window, android_native_buffer_t* buffer); static int query(android_native_window_t* window, int what, int* value); + static int perform(android_native_window_t* window, int operation, ...); int dequeueBuffer(android_native_buffer_t** buffer); int lockBuffer(android_native_buffer_t* buffer); int queueBuffer(android_native_buffer_t* buffer); int query(int what, int* value); + int perform(int operation, va_list args); status_t dequeueBuffer(sp<SurfaceBuffer>* buffer); status_t lockBuffer(const sp<SurfaceBuffer>& buffer); @@ -217,6 +219,7 @@ private: uint32_t mIdentity; uint32_t mWidth; uint32_t mHeight; + uint32_t mUsage; PixelFormat mFormat; uint32_t mFlags; mutable Region mDirtyRegion; diff --git a/include/ui/egl/android_natives.h b/include/ui/egl/android_natives.h index 7da69b144a..4c58e474c6 100644 --- a/include/ui/egl/android_natives.h +++ b/include/ui/egl/android_natives.h @@ -67,6 +67,11 @@ enum { NATIVE_WINDOW_FORMAT = 2, }; +/* valid operations for the (*perform)() hook */ +enum { + NATIVE_WINDOW_SET_USAGE = 0 +}; + struct android_native_window_t { #ifdef __cplusplus @@ -142,11 +147,45 @@ struct android_native_window_t * Returns 0 on success or -errno on error. */ int (*query)(struct android_native_window_t* window, - int what, int* value); + int what, int* value); + + /* + * hook used to perform various operations on the surface. + * (*perform)() is a generic mechanism to add functionality to + * android_native_window_t while keeping backward binary compatibility. + * + * This hook should not be called directly, instead use the helper functions + * defined below. + * + * The valid operations are: + * NATIVE_WINDOW_SET_USAGE + * + */ + + int (*perform)(struct android_native_window_t* window, + int operation, ... ); - void* reserved_proc[4]; + void* reserved_proc[3]; }; + +/* + * native_window_set_usage() sets the intended usage flags for the next + * buffers acquired with (*lockBuffer)() and on. + * By default (if this function is never called), a usage of + * GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE + * is assumed. + * Calling this function will usually cause following buffers to be + * reallocated. + */ + +inline int native_window_set_usage( + struct android_native_window_t* window, int usage) +{ + return window->perform(window, NATIVE_WINDOW_SET_USAGE, usage); +} + + // --------------------------------------------------------------------------- /* FIXME: this is legacy for pixmaps */ diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp index d1142cca86..8c0b40d9e4 100644 --- a/libs/surfaceflinger/Layer.cpp +++ b/libs/surfaceflinger/Layer.cpp @@ -217,7 +217,7 @@ void Layer::onDraw(const Region& clip) const 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 @@ sp<SurfaceBuffer> Layer::peekBuffer() } 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 @@ Layer::SurfaceLayer::~SurfaceLayer() { } -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 4c13d6ea28..add5d50747 100644 --- a/libs/surfaceflinger/Layer.h +++ b/libs/surfaceflinger/Layer.h @@ -101,7 +101,7 @@ private: 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 @@ private: ~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 fbce73ddd3..419574c7de 100644 --- a/libs/surfaceflinger/LayerBase.cpp +++ b/libs/surfaceflinger/LayerBase.cpp @@ -759,7 +759,7 @@ status_t LayerBaseClient::Surface::onTransact( 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 6fb1d1c50c..65bf55b51b 100644 --- a/libs/surfaceflinger/LayerBase.h +++ b/libs/surfaceflinger/LayerBase.h @@ -335,7 +335,7 @@ public: 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 5221fed56f..5e74451d5f 100644 --- a/libs/surfaceflinger/LayerBitmap.cpp +++ b/libs/surfaceflinger/LayerBitmap.cpp @@ -38,13 +38,14 @@ namespace android { // 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 @@ android_native_buffer_t* Buffer::getNativeBuffer() const 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 @@ status_t Buffer::initSize(uint32_t w, uint32_t h) 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 @@ status_t LayerBitmap::setSize(uint32_t w, uint32_t h) 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 22525cebdf..48ee553e52 100644 --- a/libs/surfaceflinger/LayerBitmap.h +++ b/libs/surfaceflinger/LayerBitmap.h @@ -58,7 +58,8 @@ public: }; // 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 @@ private: 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 @@ public: 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 90e7f50480..e1f4bea228 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 @@ void LayerBuffer::BufferSource::onDraw(const Region& clip) const 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 8e9df9cc9b..6ebb49f64c 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 @@ void LayerDim::initDimmer(SurfaceFlinger* flinger, uint32_t w, uint32_t h) 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 f6c666df42..90b51634c6 100644 --- a/libs/ui/FramebufferNativeWindow.cpp +++ b/libs/ui/FramebufferNativeWindow.cpp @@ -132,6 +132,7 @@ FramebufferNativeWindow::FramebufferNativeWindow() 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 @@ int FramebufferNativeWindow::query(android_native_window_t* window, 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 9fbae1ebaf..b78e8b5ab5 100644 --- a/libs/ui/ISurface.cpp +++ b/libs/ui/ISurface.cpp @@ -71,10 +71,11 @@ public: { } - 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 @@ status_t BnSurface::onTransact( 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 4abb7f62ad..2b6905f33f 100644 --- a/libs/ui/Surface.cpp +++ b/libs/ui/Surface.cpp @@ -414,6 +414,7 @@ void Surface::init() 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 @@ void Surface::init() 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 @@ int Surface::query(android_native_window_t* window, 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 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer) 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 @@ int Surface::query(int what, int* value) 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* info, bool blocking) { 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 @@ void Surface::setSwapRectangle(const Rect& r) { 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]); diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp index cf66be3372..0762ebf605 100644 --- a/opengl/libagl/egl.cpp +++ b/opengl/libagl/egl.cpp @@ -384,6 +384,10 @@ egl_window_surface_v2_t::~egl_window_surface_v2_t() { EGLBoolean egl_window_surface_v2_t::connect() { + // we're intending to do software rendering + native_window_set_usage(nativeWindow, + GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); + // dequeue a buffer if (nativeWindow->dequeueBuffer(nativeWindow, &buffer) != NO_ERROR) { return setError(EGL_BAD_ALLOC, EGL_FALSE); |