diff options
author | Mathias Agopian <mathias@google.com> | 2009-08-11 22:34:02 -0700 |
---|---|---|
committer | Mathias Agopian <mathias@google.com> | 2009-08-11 23:32:29 -0700 |
commit | 5221271375f361b84a6eeec3d7086f223997fbb3 (patch) | |
tree | f65cab160cf38b9ed577f1cb5bc2f9882fc8631c | |
parent | 40ef81c7fce7cd1b028aec7b8b27b77ce6bf7b90 (diff) | |
download | frameworks_native-5221271375f361b84a6eeec3d7086f223997fbb3.zip frameworks_native-5221271375f361b84a6eeec3d7086f223997fbb3.tar.gz frameworks_native-5221271375f361b84a6eeec3d7086f223997fbb3.tar.bz2 |
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."
-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 cb9bf94..68144b5 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 adba45a..7909c2f 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 d5dad31..4ff0e4a 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 7da69b1..4c58e47 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 d1142cc..8c0b40d 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 4c13d6e..add5d50 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 fbce73d..419574c 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 6fb1d1c..65bf55b 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 5221fed..5e74451 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 22525ce..48ee553 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 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 @@ 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 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 @@ 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 f6c666d..90b5163 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 9fbae1e..b78e8b5 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 4abb7f6..2b6905f 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 cf66be3..0762ebf 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); |