diff options
author | Mathias Agopian <mathias@google.com> | 2009-04-10 14:24:30 -0700 |
---|---|---|
committer | Mathias Agopian <mathias@google.com> | 2009-04-10 14:24:30 -0700 |
commit | 1473f46cbc82aa6f0ba744cc896a36923823d55b (patch) | |
tree | 1a03737c7eb71b32735693e5cfdd91d0b57a2ad5 /libs/surfaceflinger/LayerBitmap.cpp | |
parent | 71d83c04897a10394009b02808bb6b86886b27e1 (diff) | |
download | frameworks_base-1473f46cbc82aa6f0ba744cc896a36923823d55b.zip frameworks_base-1473f46cbc82aa6f0ba744cc896a36923823d55b.tar.gz frameworks_base-1473f46cbc82aa6f0ba744cc896a36923823d55b.tar.bz2 |
Integrate from //sandbox/mathias/donut/...@145728
SurfaceFlinger rework for new EGL driver model support.
Diffstat (limited to 'libs/surfaceflinger/LayerBitmap.cpp')
-rw-r--r-- | libs/surfaceflinger/LayerBitmap.cpp | 264 |
1 files changed, 149 insertions, 115 deletions
diff --git a/libs/surfaceflinger/LayerBitmap.cpp b/libs/surfaceflinger/LayerBitmap.cpp index e844350..d633a2d 100644 --- a/libs/surfaceflinger/LayerBitmap.cpp +++ b/libs/surfaceflinger/LayerBitmap.cpp @@ -14,170 +14,204 @@ * limitations under the License. */ -#define LOG_TAG "SurfaceFlinger" - #include <stdlib.h> #include <stdint.h> #include <sys/types.h> -#include <cutils/memory.h> #include <utils/Errors.h> #include <utils/Log.h> #include <utils/MemoryDealer.h> +#include <utils/MemoryBase.h> #include <utils/IMemory.h> + #include <ui/PixelFormat.h> +#include <ui/Surface.h> #include <pixelflinger/pixelflinger.h> +#include "BufferAllocator.h" #include "LayerBitmap.h" #include "SurfaceFlinger.h" -#include "VRamHeap.h" namespace android { -// --------------------------------------------------------------------------- +// =========================================================================== +// Buffer and implementation of android_native_buffer_t +// =========================================================================== -LayerBitmap::LayerBitmap() - : mAllocFlags(0), mOffset(0), mSize(-1U), mAlignment(2) +Buffer::Buffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) + : SurfaceBuffer(), mInitCheck(NO_INIT), mFlags(flags), + mVStride(0) { - memset(&mSurface, 0, sizeof(mSurface)); + this->format = format; + if (w>0 && h>0) { + mInitCheck = initSize(w, h); + } } -LayerBitmap::~LayerBitmap() +Buffer::~Buffer() { - mSurface.data = 0; + if (handle) { + BufferAllocator& allocator = BufferAllocator::get(); + if (usage & BufferAllocator::USAGE_SW_READ_MASK) { + allocator.unmap(handle); + } + allocator.free(handle); + } } -status_t LayerBitmap::init(const sp<MemoryDealer>& allocator) -{ - if (mAllocator != NULL) - return BAD_VALUE; - mAllocator = allocator; - return NO_ERROR; +status_t Buffer::initCheck() const { + return mInitCheck; } -status_t LayerBitmap::setBits(uint32_t w, uint32_t h, uint32_t alignment, - PixelFormat format, uint32_t flags) +android_native_buffer_t* Buffer::getNativeBuffer() const { - const sp<MemoryDealer>& allocator(mAllocator); - if (allocator == NULL) - return NO_INIT; - - if (UNLIKELY(w == mSurface.width && h == mSurface.height && - format == mSurface.format)) - { // same format and size, do nothing. - return NO_ERROR; - } - - PixelFormatInfo info; - getPixelFormatInfo(format, &info); - - uint32_t allocFlags = MemoryDealer::PAGE_ALIGNED; - const uint32_t align = 4; // must match GL_UNPACK_ALIGNMENT - const uint32_t Bpp = info.bytesPerPixel; - uint32_t stride = (w + (alignment-1)) & ~(alignment-1); - stride = ((stride * Bpp + (align-1)) & ~(align-1)) / Bpp; - size_t size = info.getScanlineSize(stride) * h; - if (allocFlags & MemoryDealer::PAGE_ALIGNED) { - size_t pagesize = getpagesize(); - size = (size + (pagesize-1)) & ~(pagesize-1); - } + return static_cast<android_native_buffer_t*>(const_cast<Buffer*>(this)); +} - /* FIXME: we should be able to have a h/v stride because the user of the - * surface might have stride limitation (for instance h/w codecs often do) +status_t Buffer::initSize(uint32_t w, uint32_t h) +{ + status_t err = NO_ERROR; + + BufferAllocator& allocator = BufferAllocator::get(); + + /* + * buffers used for software rendering, but h/w composition + * are allocated with SW_READ_OFTEN | SW_WRITE_OFTEN | HW_TEXTURE + * + * buffers used for h/w rendering and h/w composition + * are allocated with HW_RENDER | HW_TEXTURE + * + * buffers used with h/w rendering and either NPOT or no egl_image_ext + * are allocated with SW_READ_RARELY | HW_RENDER + * */ - int32_t vstride = 0; - - mAlignment = alignment; - mAllocFlags = allocFlags; - mOffset = 0; - if (mSize != size) { - // would be nice to have a reallocate() api - mBitsMemory.clear(); // free-memory - mBitsMemory = allocator->allocate(size, allocFlags); - mSize = size; + + if (mFlags & Buffer::SECURE) { + // secure buffer, don't store it into the GPU + usage = BufferAllocator::USAGE_SW_READ_OFTEN | + BufferAllocator::USAGE_SW_WRITE_OFTEN; } else { - // don't erase memory if we didn't have to reallocate - flags &= ~SECURE_BITS; - } - if (mBitsMemory != 0) { - mOffset = mBitsMemory->offset(); - mSurface.data = static_cast<GGLubyte*>(mBitsMemory->pointer()); - mSurface.version = sizeof(GGLSurface); - mSurface.width = w; - mSurface.height = h; - mSurface.stride = stride; - mSurface.vstride = vstride; - mSurface.format = format; - if (flags & SECURE_BITS) - clear(); + 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; + } } - if (mBitsMemory==0 || mSurface.data==0) { - LOGE("not enough memory for layer bitmap size=%u", size); - allocator->dump("LayerBitmap"); - mSurface.data = 0; - mSize = -1U; - return NO_MEMORY; + err = allocator.alloc(w, h, format, usage, &handle, &stride); + + if (err == NO_ERROR) { + if (usage & BufferAllocator::USAGE_SW_READ_MASK) { + err = allocator.map(handle, &bits); + } + if (err == NO_ERROR) { + width = w; + height = h; + mVStride = 0; + } } - return NO_ERROR; + + return err; } -void LayerBitmap::clear() +status_t Buffer::getBitmapSurface(copybit_image_t* img) const { - // NOTE: this memset should not be necessary, at least for - // opaque surface. However, for security reasons it's better to keep it - // (in the case of pmem, it's possible that the memory contains old - // data) - if (mSurface.data) { - memset(mSurface.data, 0, mSize); - //if (bytesPerPixel(mSurface.format) == 4) { - // android_memset32((uint32_t*)mSurface.data, 0xFF0000FF, mSize); - //} else { - // android_memset16((uint16_t*)mSurface.data, 0xF800, mSize); - //} - } + img->w = stride ?: width; + img->h = mVStride ?: height; + img->format = format; + + // FIXME: this should use a native_handle + img->offset = 0; + img->base = bits; + img->fd = getHandle()->data[0]; + + return NO_ERROR; } -status_t LayerBitmap::getInfo(surface_info_t* info) const +status_t Buffer::getBitmapSurface(GGLSurface* sur) const { - if (mSurface.data == 0) { - memset(info, 0, sizeof(surface_info_t)); - info->bits_offset = NO_MEMORY; - return NO_MEMORY; - } - info->w = uint16_t(width()); - info->h = uint16_t(height()); - info->stride= uint16_t(stride()); - info->bpr = uint16_t(stride() * bytesPerPixel(pixelFormat())); - info->format= uint8_t(pixelFormat()); - info->flags = surface_info_t::eBufferDirty; - info->bits_offset = ssize_t(mOffset); + sur->version = sizeof(GGLSurface); + sur->width = width; + sur->height = height; + sur->stride = stride; + sur->format = format; + sur->vstride = mVStride; + sur->data = static_cast<GGLubyte*>(bits); return NO_ERROR; } -status_t LayerBitmap::resize(uint32_t w, uint32_t h) +// =========================================================================== +// LayerBitmap +// =========================================================================== + + +LayerBitmap::LayerBitmap() + : mInfo(0), mWidth(0), mHeight(0) { - int err = setBits(w, h, mAlignment, pixelFormat(), SECURE_BITS); - return err; } -size_t LayerBitmap::size() const +LayerBitmap::~LayerBitmap() { - return mSize; } -void LayerBitmap::getBitmapSurface(copybit_image_t* img) const +status_t LayerBitmap::init(surface_info_t* info, + uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) { - const sp<IMemoryHeap>& mh(getAllocator()->getMemoryHeap()); - void* sbase = mh->base(); - const GGLSurface& t(surface()); - img->w = t.stride ?: t.width; - img->h = t.vstride ?: t.height; - img->format = t.format; - img->offset = intptr_t(t.data) - intptr_t(sbase); - img->base = sbase; - img->fd = mh->heapID(); + if (info == NULL) + return BAD_VALUE; + + mFormat = format; + mFlags = flags; + mWidth = w; + mHeight = h; + + mInfo = info; + memset(info, 0, sizeof(surface_info_t)); + info->flags = surface_info_t::eNeedNewBuffer; + + // init the buffer, but don't trigger an allocation + mBuffer = new Buffer(0, 0, format, flags); + return NO_ERROR; +} + +status_t LayerBitmap::setSize(uint32_t w, uint32_t h) +{ + Mutex::Autolock _l(mLock); + if ((w != mWidth) || (h != mHeight)) { + mWidth = w; + mHeight = h; + // this will signal the client that it needs to asks us for a new buffer + mInfo->flags = surface_info_t::eNeedNewBuffer; + } + return NO_ERROR; +} + +sp<Buffer> LayerBitmap::allocate() +{ + Mutex::Autolock _l(mLock); + sp<Buffer> buffer(mBuffer); + const uint32_t w = mWidth; + const uint32_t h = mHeight; + if (w != buffer->getWidth() || h != buffer->getHeight()) { + surface_info_t* info = mInfo; + buffer = new Buffer(w, h, mFormat, mFlags); + status_t err = buffer->initCheck(); + if (LIKELY(err == NO_ERROR)) { + info->flags = surface_info_t::eBufferDirty; + info->status = NO_ERROR; + } else { + memset(info, 0, sizeof(surface_info_t)); + info->status = NO_MEMORY; + } + mBuffer = buffer; + } + return buffer; } // --------------------------------------------------------------------------- |