diff options
Diffstat (limited to 'libs')
23 files changed, 645 insertions, 684 deletions
diff --git a/libs/surfaceflinger/Android.mk b/libs/surfaceflinger/Android.mk index 49da111..eb51c22 100644 --- a/libs/surfaceflinger/Android.mk +++ b/libs/surfaceflinger/Android.mk @@ -6,8 +6,6 @@ LOCAL_SRC_FILES:= \ DisplayHardware/DisplayHardware.cpp \ DisplayHardware/DisplayHardwareBase.cpp \ BlurFilter.cpp.arm \ - Buffer.cpp \ - BufferAllocator.cpp \ Layer.cpp \ LayerBase.cpp \ LayerBuffer.cpp \ diff --git a/libs/surfaceflinger/Buffer.cpp b/libs/surfaceflinger/Buffer.cpp deleted file mode 100644 index 6190cd8..0000000 --- a/libs/surfaceflinger/Buffer.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <stdlib.h> -#include <stdint.h> -#include <sys/types.h> - -#include <utils/Errors.h> -#include <utils/Log.h> - -#include <ui/PixelFormat.h> -#include <pixelflinger/pixelflinger.h> - -#include "Buffer.h" -#include "BufferAllocator.h" - -namespace android { - -// =========================================================================== -// Buffer and implementation of android_native_buffer_t -// =========================================================================== - -Buffer::Buffer() - : SurfaceBuffer(), mInitCheck(NO_ERROR), mVStride(0) -{ -} - -Buffer::Buffer(uint32_t w, uint32_t h, PixelFormat format, - uint32_t reqUsage, uint32_t flags) - : SurfaceBuffer(), mInitCheck(NO_INIT), mVStride(0) -{ - mInitCheck = initSize(w, h, format, reqUsage, flags); -} - -Buffer::~Buffer() -{ - if (handle) { - BufferAllocator& allocator(BufferAllocator::get()); - allocator.free(handle); - } -} - -status_t Buffer::initCheck() const { - return mInitCheck; -} - -android_native_buffer_t* Buffer::getNativeBuffer() const -{ - return static_cast<android_native_buffer_t*>(const_cast<Buffer*>(this)); -} - -status_t Buffer::reallocate(uint32_t w, uint32_t h, PixelFormat f, - uint32_t reqUsage, uint32_t flags) -{ - if (handle) { - BufferAllocator& allocator(BufferAllocator::get()); - allocator.free(handle); - handle = 0; - } - return initSize(w, h, f, reqUsage, flags); -} - -status_t Buffer::initSize(uint32_t w, uint32_t h, PixelFormat format, - uint32_t reqUsage, uint32_t flags) -{ - 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 - * - */ - - if (flags & Buffer::SECURE) { - // secure buffer, don't store it into the GPU - usage = BufferAllocator::USAGE_SW_READ_OFTEN | - BufferAllocator::USAGE_SW_WRITE_OFTEN; - } else { - // it's allowed to modify the usage flags here, but generally - // the requested flags should be honored. - usage = reqUsage | BufferAllocator::USAGE_HW_TEXTURE; - } - - if (format == PIXEL_FORMAT_RGBX_8888) - format = PIXEL_FORMAT_RGBA_8888; - - err = allocator.alloc(w, h, format, usage, &handle, &stride); - if (err == NO_ERROR) { - this->width = w; - this->height = h; - this->format = format; - mVStride = 0; - } - - return err; -} - -status_t Buffer::lock(GGLSurface* sur, uint32_t usage) -{ - void* vaddr; - status_t res = SurfaceBuffer::lock(usage, &vaddr); - if (res == NO_ERROR && sur) { - sur->version = sizeof(GGLSurface); - sur->width = width; - sur->height = height; - sur->stride = stride; - sur->format = format; - sur->vstride = mVStride; - sur->data = static_cast<GGLubyte*>(vaddr); - } - return res; -} - -// --------------------------------------------------------------------------- - -}; // namespace android diff --git a/libs/surfaceflinger/Buffer.h b/libs/surfaceflinger/Buffer.h deleted file mode 100644 index 203da3b..0000000 --- a/libs/surfaceflinger/Buffer.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_LAYER_BITMAP_H -#define ANDROID_LAYER_BITMAP_H - -#include <stdint.h> -#include <sys/types.h> - -#include <ui/PixelFormat.h> -#include <ui/Rect.h> -#include <pixelflinger/pixelflinger.h> -#include <private/ui/SurfaceBuffer.h> - -struct android_native_buffer_t; - -namespace android { - -// =========================================================================== -// Buffer -// =========================================================================== - -class Buffer : public SurfaceBuffer -{ -public: - enum { - DONT_CLEAR = 0x00000001, - SECURE = 0x00000004 - }; - - Buffer(); - - // creates w * h buffer - Buffer(uint32_t w, uint32_t h, PixelFormat format, - uint32_t reqUsage, uint32_t flags = 0); - - // return status - status_t initCheck() const; - - uint32_t getWidth() const { return width; } - uint32_t getHeight() const { return height; } - uint32_t getStride() const { return stride; } - uint32_t getUsage() const { return usage; } - PixelFormat getPixelFormat() const { return format; } - Rect getBounds() const { return Rect(width, height); } - - status_t lock(GGLSurface* surface, uint32_t usage); - - android_native_buffer_t* getNativeBuffer() const; - - status_t reallocate(uint32_t w, uint32_t h, PixelFormat f, - uint32_t reqUsage, uint32_t flags); - -private: - friend class LightRefBase<Buffer>; - Buffer(const Buffer& rhs); - virtual ~Buffer(); - Buffer& operator = (const Buffer& rhs); - const Buffer& operator = (const Buffer& rhs) const; - - status_t initSize(uint32_t w, uint32_t h, PixelFormat format, - uint32_t reqUsage, uint32_t flags); - - ssize_t mInitCheck; - uint32_t mVStride; -}; - -}; // namespace android - -#endif // ANDROID_LAYER_BITMAP_H diff --git a/libs/surfaceflinger/BufferAllocator.h b/libs/surfaceflinger/BufferAllocator.h deleted file mode 100644 index a279ded..0000000 --- a/libs/surfaceflinger/BufferAllocator.h +++ /dev/null @@ -1,96 +0,0 @@ -/* -** -** Copyright 2009, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#ifndef ANDROID_BUFFER_ALLOCATOR_H -#define ANDROID_BUFFER_ALLOCATOR_H - -#include <stdint.h> - -#include <cutils/native_handle.h> - -#include <utils/Errors.h> -#include <utils/KeyedVector.h> -#include <utils/threads.h> -#include <utils/Singleton.h> - -#include <ui/PixelFormat.h> - -#include <hardware/gralloc.h> - - -namespace android { -// --------------------------------------------------------------------------- - -class String8; - -class BufferAllocator : public Singleton<BufferAllocator> -{ -public: - enum { - USAGE_SW_READ_NEVER = GRALLOC_USAGE_SW_READ_NEVER, - USAGE_SW_READ_RARELY = GRALLOC_USAGE_SW_READ_RARELY, - USAGE_SW_READ_OFTEN = GRALLOC_USAGE_SW_READ_OFTEN, - USAGE_SW_READ_MASK = GRALLOC_USAGE_SW_READ_MASK, - - USAGE_SW_WRITE_NEVER = GRALLOC_USAGE_SW_WRITE_NEVER, - USAGE_SW_WRITE_RARELY = GRALLOC_USAGE_SW_WRITE_RARELY, - USAGE_SW_WRITE_OFTEN = GRALLOC_USAGE_SW_WRITE_OFTEN, - USAGE_SW_WRITE_MASK = GRALLOC_USAGE_SW_WRITE_MASK, - - USAGE_SOFTWARE_MASK = USAGE_SW_READ_MASK|USAGE_SW_WRITE_MASK, - - USAGE_HW_TEXTURE = GRALLOC_USAGE_HW_TEXTURE, - USAGE_HW_RENDER = GRALLOC_USAGE_HW_RENDER, - USAGE_HW_2D = GRALLOC_USAGE_HW_2D, - USAGE_HW_MASK = GRALLOC_USAGE_HW_MASK - }; - - static inline BufferAllocator& get() { return getInstance(); } - - - status_t alloc(uint32_t w, uint32_t h, PixelFormat format, int usage, - buffer_handle_t* handle, int32_t* stride); - - status_t free(buffer_handle_t handle); - - void dump(String8& res) const; - -private: - struct alloc_rec_t { - uint32_t w; - uint32_t h; - PixelFormat format; - uint32_t usage; - void* vaddr; - size_t size; - }; - - static Mutex sLock; - static KeyedVector<buffer_handle_t, alloc_rec_t> sAllocList; - - friend class Singleton<BufferAllocator>; - BufferAllocator(); - ~BufferAllocator(); - - mutable Mutex mLock; - alloc_device_t *mAllocDev; -}; - -// --------------------------------------------------------------------------- -}; // namespace android - -#endif // ANDROID_BUFFER_ALLOCATOR_H diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp index 8a7abec..f84933e 100644 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp +++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp @@ -123,7 +123,7 @@ void DisplayHardware::init(uint32_t dpy) EGLint numConfigs=0; EGLSurface surface; EGLContext context; - mFlags = 0; + mFlags = CACHED_BUFFERS; // TODO: all the extensions below should be queried through // eglGetProcAddress(). @@ -239,12 +239,17 @@ void DisplayHardware::init(uint32_t dpy) eglMakeCurrent(display, surface, surface, context); const char* const gl_extensions = (const char*)glGetString(GL_EXTENSIONS); + const char* const gl_renderer = (const char*)glGetString(GL_RENDERER); LOGI("OpenGL informations:"); LOGI("vendor : %s", glGetString(GL_VENDOR)); - LOGI("renderer : %s", glGetString(GL_RENDERER)); + LOGI("renderer : %s", gl_renderer); LOGI("version : %s", glGetString(GL_VERSION)); LOGI("extensions: %s", gl_extensions); + if (strstr(gl_renderer, "PowerVR SGX 530")) { + LOGD("Assuming uncached graphics buffers."); + mFlags &= ~CACHED_BUFFERS; + } if (strstr(gl_extensions, "GL_ARB_texture_non_power_of_two")) { mFlags |= NPOT_EXTENSION; } diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h index cb688b7..6914d0c 100644 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h +++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h @@ -51,6 +51,7 @@ public: PARTIAL_UPDATES = 0x00020000, // video driver feature SLOW_CONFIG = 0x00040000, // software SWAP_RECTANGLE = 0x00080000, + CACHED_BUFFERS = 0x00100000 }; DisplayHardware( diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp index 13201db..eb0614f 100644 --- a/libs/surfaceflinger/Layer.cpp +++ b/libs/surfaceflinger/Layer.cpp @@ -25,10 +25,10 @@ #include <utils/Log.h> #include <utils/StopWatch.h> +#include <ui/GraphicBuffer.h> #include <ui/PixelFormat.h> #include <ui/Surface.h> -#include "Buffer.h" #include "clz.h" #include "Layer.h" #include "SurfaceFlinger.h" @@ -51,6 +51,7 @@ Layer::Layer(SurfaceFlinger* flinger, DisplayID display, const sp<Client>& c, int32_t i) : LayerBaseClient(flinger, display, c, i), mSecure(false), + mNoEGLImageForSwBuffers(false), mNeedsBlending(true), mNeedsDithering(false) { @@ -108,25 +109,22 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h, const DisplayHardware& hw(graphicPlane(0).displayHardware()); PixelFormatInfo displayInfo; getPixelFormatInfo(hw.getFormat(), &displayInfo); - - uint32_t bufferFlags = 0; - if (flags & ISurfaceComposer::eSecure) - bufferFlags |= Buffer::SECURE; - + const uint32_t hwFlags = hw.getFlags(); + mFormat = format; mWidth = w; mHeight = h; - mSecure = (bufferFlags & Buffer::SECURE) ? true : false; + mSecure = (flags & ISurfaceComposer::eSecure) ? true : false; mNeedsBlending = (info.h_alpha - info.l_alpha) > 0; - + mNoEGLImageForSwBuffers = !(hwFlags & DisplayHardware::CACHED_BUFFERS); + // we use the red index int displayRedSize = displayInfo.getSize(PixelFormatInfo::INDEX_RED); int layerRedsize = info.getSize(PixelFormatInfo::INDEX_RED); mNeedsDithering = layerRedsize > displayRedSize; - mBufferFlags = bufferFlags; for (size_t i=0 ; i<NUM_BUFFERS ; i++) { - mBuffers[i] = new Buffer(); + mBuffers[i] = new GraphicBuffer(); } mSurface = new SurfaceLayer(mFlinger, clientIndex(), this); return NO_ERROR; @@ -135,8 +133,9 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h, void Layer::reloadTexture(const Region& dirty) { Mutex::Autolock _l(mLock); - sp<Buffer> buffer(getFrontBuffer()); - if (LIKELY(mFlags & DisplayHardware::DIRECT_TEXTURE)) { + sp<GraphicBuffer> buffer(getFrontBuffer()); + if (LIKELY((mFlags & DisplayHardware::DIRECT_TEXTURE) && + (buffer->usage & GRALLOC_USAGE_HW_TEXTURE))) { int index = mFrontBufferIndex; if (LIKELY(!mTextures[index].dirty)) { glBindTexture(GL_TEXTURE_2D, mTextures[index].name); @@ -187,6 +186,7 @@ void Layer::reloadTexture(const Region& dirty) mFlags &= ~DisplayHardware::DIRECT_TEXTURE; } else { // Everything went okay! + mTextures[index].NPOTAdjust = false; mTextures[index].dirty = false; mTextures[index].width = clientBuf->width; mTextures[index].height = clientBuf->height; @@ -194,15 +194,21 @@ void Layer::reloadTexture(const Region& dirty) } } } else { + for (int i=0 ; i<NUM_BUFFERS ; i++) + mTextures[i].image = EGL_NO_IMAGE_KHR; + GGLSurface t; - status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_RARELY); + status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_OFTEN); LOGE_IF(res, "error %d (%s) locking buffer %p", res, strerror(res), buffer.get()); + if (res == NO_ERROR) { if (UNLIKELY(mTextures[0].name == -1U)) { mTextures[0].name = createTexture(); + mTextures[0].width = 0; + mTextures[0].height = 0; } - loadTexture(&mTextures[0], mTextures[0].name, dirty, t); + loadTexture(&mTextures[0], dirty, t); buffer->unlock(); } } @@ -211,8 +217,9 @@ void Layer::reloadTexture(const Region& dirty) void Layer::onDraw(const Region& clip) const { - const int index = (mFlags & DisplayHardware::DIRECT_TEXTURE) ? - mFrontBufferIndex : 0; + int index = mFrontBufferIndex; + if (mTextures[index].image == EGL_NO_IMAGE_KHR) + index = 0; GLuint textureName = mTextures[index].name; if (UNLIKELY(textureName == -1LU)) { // the texture has not been created yet, this Layer has @@ -224,9 +231,9 @@ void Layer::onDraw(const Region& clip) const drawWithOpenGL(clip, mTextures[index]); } -sp<SurfaceBuffer> Layer::requestBuffer(int index, int usage) +sp<GraphicBuffer> Layer::requestBuffer(int index, int usage) { - sp<Buffer> buffer; + sp<GraphicBuffer> buffer; // this ensures our client doesn't go away while we're accessing // the shared area. @@ -269,14 +276,15 @@ sp<SurfaceBuffer> Layer::requestBuffer(int index, int usage) mBuffers[index].clear(); } + const uint32_t effectiveUsage = getEffectiveUsage(usage); if (buffer!=0 && buffer->getStrongCount() == 1) { - err = buffer->reallocate(w, h, mFormat, usage, mBufferFlags); + err = buffer->reallocate(w, h, mFormat, effectiveUsage); } else { // here we have to reallocate a new buffer because we could have a // client in our process with a reference to it (eg: status bar), // and we can't release the handle under its feet. buffer.clear(); - buffer = new Buffer(w, h, mFormat, usage, mBufferFlags); + buffer = new GraphicBuffer(w, h, mFormat, effectiveUsage); err = buffer->initCheck(); } @@ -305,6 +313,40 @@ sp<SurfaceBuffer> Layer::requestBuffer(int index, int usage) return buffer; } +uint32_t Layer::getEffectiveUsage(uint32_t usage) const +{ + /* + * 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 + * + */ + + if (mSecure) { + // secure buffer, don't store it into the GPU + usage = GraphicBuffer::USAGE_SW_READ_OFTEN | + GraphicBuffer::USAGE_SW_WRITE_OFTEN; + } else { + // it's allowed to modify the usage flags here, but generally + // the requested flags should be honored. + if (mNoEGLImageForSwBuffers) { + if (usage & GraphicBuffer::USAGE_HW_MASK) { + // request EGLImage for h/w buffers only + usage |= GraphicBuffer::USAGE_HW_TEXTURE; + } + } else { + // request EGLImage for all buffers + usage |= GraphicBuffer::USAGE_HW_TEXTURE; + } + } + return usage; +} + uint32_t Layer::doTransaction(uint32_t flags) { const Layer::State& front(drawingState()); @@ -383,7 +425,7 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions) mFrontBufferIndex = buf; // get the dirty region - sp<Buffer> newFrontBuffer(getBuffer(buf)); + sp<GraphicBuffer> newFrontBuffer(getBuffer(buf)); const Region dirty(lcblk->getDirtyRegion(buf)); mPostedDirtyRegion = dirty.intersect( newFrontBuffer->getBounds() ); @@ -421,7 +463,9 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions) // FIXME: signal an event if we have more buffers waiting // mFlinger->signalEvent(); - reloadTexture( mPostedDirtyRegion ); + if (!mPostedDirtyRegion.isEmpty()) { + reloadTexture( mPostedDirtyRegion ); + } } void Layer::unlockPageFlip( @@ -465,9 +509,9 @@ Layer::SurfaceLayer::~SurfaceLayer() { } -sp<SurfaceBuffer> Layer::SurfaceLayer::requestBuffer(int index, int usage) +sp<GraphicBuffer> Layer::SurfaceLayer::requestBuffer(int index, int usage) { - sp<SurfaceBuffer> buffer; + sp<GraphicBuffer> buffer; sp<Layer> owner(getOwner()); if (owner != 0) { LOGE_IF(uint32_t(index)>=NUM_BUFFERS, diff --git a/libs/surfaceflinger/Layer.h b/libs/surfaceflinger/Layer.h index f111840..6f59241 100644 --- a/libs/surfaceflinger/Layer.h +++ b/libs/surfaceflinger/Layer.h @@ -20,6 +20,7 @@ #include <stdint.h> #include <sys/types.h> +#include <ui/GraphicBuffer.h> #include <ui/PixelFormat.h> #include <pixelflinger/pixelflinger.h> @@ -28,7 +29,6 @@ #include <GLES/gl.h> #include <GLES/glext.h> -#include "Buffer.h" #include "LayerBase.h" #include "Transform.h" @@ -38,7 +38,6 @@ namespace android { class Client; class FreezeLock; -class Buffer; // --------------------------------------------------------------------------- @@ -74,20 +73,22 @@ public: virtual status_t ditch(); // only for debugging - inline sp<Buffer> getBuffer(int i) { return mBuffers[i]; } + inline sp<GraphicBuffer> getBuffer(int i) { return mBuffers[i]; } // only for debugging inline const sp<FreezeLock>& getFreezeLock() const { return mFreezeLock; } // only for debugging inline PixelFormat pixelFormat() const { return mFormat; } private: - inline sp<Buffer> getFrontBuffer() { + inline sp<GraphicBuffer> getFrontBuffer() { return mBuffers[mFrontBufferIndex]; } void reloadTexture(const Region& dirty); - sp<SurfaceBuffer> requestBuffer(int index, int usage); + uint32_t getEffectiveUsage(uint32_t usage) const; + + sp<GraphicBuffer> requestBuffer(int index, int usage); void destroy(); class SurfaceLayer : public LayerBaseClient::Surface { @@ -96,7 +97,7 @@ private: SurfaceID id, const sp<Layer>& owner); ~SurfaceLayer(); private: - virtual sp<SurfaceBuffer> requestBuffer(int index, int usage); + virtual sp<GraphicBuffer> requestBuffer(int index, int usage); sp<Layer> getOwner() const { return static_cast<Layer*>(Surface::getOwner().get()); } @@ -106,16 +107,16 @@ private: sp<Surface> mSurface; bool mSecure; + bool mNoEGLImageForSwBuffers; int32_t mFrontBufferIndex; bool mNeedsBlending; bool mNeedsDithering; Region mPostedDirtyRegion; sp<FreezeLock> mFreezeLock; PixelFormat mFormat; - uint32_t mBufferFlags; // protected by mLock - sp<Buffer> mBuffers[NUM_BUFFERS]; + sp<GraphicBuffer> mBuffers[NUM_BUFFERS]; Texture mTextures[NUM_BUFFERS]; uint32_t mWidth; uint32_t mHeight; diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp index 83814cc..b376e72 100644 --- a/libs/surfaceflinger/LayerBase.cpp +++ b/libs/surfaceflinger/LayerBase.cpp @@ -449,17 +449,9 @@ void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const glTranslatef(0, 1, 0); glRotatef(-90, 0, 0, 1); } - - if (!(mFlags & (DisplayHardware::NPOT_EXTENSION | - DisplayHardware::DIRECT_TEXTURE))) { - // find the smallest power-of-two that will accommodate our surface - GLuint tw = 1 << (31 - clz(width)); - GLuint th = 1 << (31 - clz(height)); - if (tw < width) tw <<= 1; - if (th < height) th <<= 1; - GLfloat ws = GLfloat(width) /tw; - GLfloat hs = GLfloat(height)/th; - glScalef(ws, hs, 1.0f); + + if (texture.NPOTAdjust) { + glScalef(texture.wScale, texture.hScale, 1.0f); } glEnableClientState(GL_TEXTURE_COORD_ARRAY); @@ -508,21 +500,15 @@ void LayerBase::validateTexture(GLint textureName) const } } -void LayerBase::loadTexture(Texture* texture, GLint textureName, +void LayerBase::loadTexture(Texture* texture, const Region& dirty, const GGLSurface& t) const { - // TODO: defer the actual texture reload until LayerBase::validateTexture - // is called. - - texture->name = textureName; - GLuint& textureWidth(texture->width); - GLuint& textureHeight(texture->height); + if (texture->name == -1U) { + // uh? + return; + } - uint32_t flags = mFlags; - glBindTexture(GL_TEXTURE_2D, textureName); - - GLuint tw = t.width; - GLuint th = t.height; + glBindTexture(GL_TEXTURE_2D, texture->name); /* * In OpenGL ES we can't specify a stride with glTexImage2D (however, @@ -547,64 +533,63 @@ void LayerBase::loadTexture(Texture* texture, GLint textureName, /* * round to POT if needed */ + if (!(mFlags & DisplayHardware::NPOT_EXTENSION)) { + texture->NPOTAdjust = true; + } - GLuint texture_w = tw; - GLuint texture_h = th; - if (!(flags & DisplayHardware::NPOT_EXTENSION)) { + if (texture->NPOTAdjust) { // find the smallest power-of-two that will accommodate our surface - texture_w = 1 << (31 - clz(t.width)); - texture_h = 1 << (31 - clz(t.height)); - if (texture_w < t.width) texture_w <<= 1; - if (texture_h < t.height) texture_h <<= 1; + texture->potWidth = 1 << (31 - clz(t.width)); + texture->potHeight = 1 << (31 - clz(t.height)); + if (texture->potWidth < t.width) texture->potWidth <<= 1; + if (texture->potHeight < t.height) texture->potHeight <<= 1; + texture->wScale = float(t.width) / texture->potWidth; + texture->hScale = float(t.height) / texture->potHeight; + } else { + texture->potWidth = t.width; + texture->potHeight = t.height; } - -regular: + Rect bounds(dirty.bounds()); GLvoid* data = 0; - if (texture_w!=textureWidth || texture_h!=textureHeight) { - // texture size changed, we need to create a new one + if (texture->width != t.width || texture->height != t.height) { + texture->width = t.width; + texture->height = t.height; - if (!textureWidth || !textureHeight) { - // this is the first time, load the whole texture - if (texture_w==tw && texture_h==th) { - // we can do it one pass - data = t.data; - } else { - // we have to create the texture first because it - // doesn't match the size of the buffer - bounds.set(Rect(tw, th)); - } + // texture size changed, we need to create a new one + bounds.set(Rect(t.width, t.height)); + if (t.width == texture->potWidth && + t.height == texture->potHeight) { + // we can do it one pass + data = t.data; } - + if (t.format == GGL_PIXEL_FORMAT_RGB_565) { glTexImage2D(GL_TEXTURE_2D, 0, - GL_RGB, texture_w, texture_h, 0, + GL_RGB, texture->potWidth, texture->potHeight, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data); } else if (t.format == GGL_PIXEL_FORMAT_RGBA_4444) { glTexImage2D(GL_TEXTURE_2D, 0, - GL_RGBA, texture_w, texture_h, 0, + GL_RGBA, texture->potWidth, texture->potHeight, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, data); } else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888 || t.format == GGL_PIXEL_FORMAT_RGBX_8888) { glTexImage2D(GL_TEXTURE_2D, 0, - GL_RGBA, texture_w, texture_h, 0, + GL_RGBA, texture->potWidth, texture->potHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); } else if ( t.format == GGL_PIXEL_FORMAT_YCbCr_422_SP || t.format == GGL_PIXEL_FORMAT_YCbCr_420_SP) { // just show the Y plane of YUV buffers glTexImage2D(GL_TEXTURE_2D, 0, - GL_LUMINANCE, texture_w, texture_h, 0, + GL_LUMINANCE, texture->potWidth, texture->potHeight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data); } else { // oops, we don't handle this format! LOGE("layer %p, texture=%d, using format %d, which is not " - "supported by the GL", this, textureName, t.format); - textureName = -1; + "supported by the GL", this, texture->name, t.format); } - textureWidth = texture_w; - textureHeight = texture_h; } - if (!data && textureName>=0) { + if (!data) { if (t.format == GGL_PIXEL_FORMAT_RGB_565) { glTexSubImage2D(GL_TEXTURE_2D, 0, 0, bounds.top, t.width, bounds.height(), @@ -747,7 +732,7 @@ status_t LayerBaseClient::Surface::onTransact( return BnSurface::onTransact(code, data, reply, flags); } -sp<SurfaceBuffer> LayerBaseClient::Surface::requestBuffer(int index, int usage) +sp<GraphicBuffer> LayerBaseClient::Surface::requestBuffer(int index, int usage) { return NULL; } diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h index 0dfa4fe..efa4f8c 100644 --- a/libs/surfaceflinger/LayerBase.h +++ b/libs/surfaceflinger/LayerBase.h @@ -39,12 +39,11 @@ namespace android { // --------------------------------------------------------------------------- -class SurfaceFlinger; class DisplayHardware; -class GraphicPlane; class Client; -class SurfaceBuffer; -class Buffer; +class GraphicBuffer; +class GraphicPlane; +class SurfaceFlinger; // --------------------------------------------------------------------------- @@ -241,12 +240,18 @@ protected: struct Texture { Texture() : name(-1U), width(0), height(0), - image(EGL_NO_IMAGE_KHR), transform(0), dirty(true) { } + image(EGL_NO_IMAGE_KHR), transform(0), + NPOTAdjust(false), dirty(true) { } GLuint name; GLuint width; GLuint height; + GLuint potWidth; + GLuint potHeight; + GLfloat wScale; + GLfloat hScale; EGLImageKHR image; uint32_t transform; + bool NPOTAdjust; bool dirty; }; @@ -254,7 +259,7 @@ protected: GLclampx b, GLclampx alpha) const; void clearWithOpenGL(const Region& clip) const; void drawWithOpenGL(const Region& clip, const Texture& texture) const; - void loadTexture(Texture* texture, GLint textureName, + void loadTexture(Texture* texture, const Region& dirty, const GGLSurface& t) const; @@ -339,7 +344,7 @@ public: sp<LayerBaseClient> getOwner() const; private: - virtual sp<SurfaceBuffer> requestBuffer(int index, int usage); + virtual sp<GraphicBuffer> requestBuffer(int index, int usage); virtual status_t registerBuffers(const ISurface::BufferHeap& buffers); virtual void postBuffer(ssize_t offset); virtual void unregisterBuffers(); diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp index 667571b..7e27a02 100644 --- a/libs/surfaceflinger/LayerBuffer.cpp +++ b/libs/surfaceflinger/LayerBuffer.cpp @@ -23,13 +23,12 @@ #include <utils/Log.h> #include <utils/StopWatch.h> +#include <ui/GraphicBuffer.h> #include <ui/PixelFormat.h> #include <ui/FramebufferNativeWindow.h> #include <hardware/copybit.h> -#include "Buffer.h" -#include "BufferAllocator.h" #include "LayerBuffer.h" #include "SurfaceFlinger.h" #include "DisplayHardware/DisplayHardware.h" @@ -474,9 +473,9 @@ void LayerBuffer::BufferSource::onDraw(const Region& clip) const mTempBitmap->getWidth() < size_t(tmp_w) || mTempBitmap->getHeight() < size_t(tmp_h)) { mTempBitmap.clear(); - mTempBitmap = new android::Buffer( - tmp_w, tmp_h, src.img.format, - BufferAllocator::USAGE_HW_2D); + mTempBitmap = new GraphicBuffer( + tmp_w, tmp_h, src.img.format, + GraphicBuffer::USAGE_HW_2D); err = mTempBitmap->initCheck(); } @@ -549,7 +548,7 @@ void LayerBuffer::BufferSource::onDraw(const Region& clip) const t.format = src.img.format; t.data = (GGLubyte*)src.img.base; const Region dirty(Rect(t.width, t.height)); - mLayer.loadTexture(&mTexture, mTexture.name, dirty, t); + mLayer.loadTexture(&mTexture, dirty, t); mTexture.transform = mBufferHeap.transform; mLayer.drawWithOpenGL(clip, mTexture); } diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h index 0452818..5eb472c 100644 --- a/libs/surfaceflinger/LayerBuffer.h +++ b/libs/surfaceflinger/LayerBuffer.h @@ -20,9 +20,6 @@ #include <stdint.h> #include <sys/types.h> -#include <binder/IMemory.h> -#include <private/ui/LayerState.h> - #include "LayerBase.h" struct copybit_device_t; @@ -133,7 +130,7 @@ private: status_t mStatus; ISurface::BufferHeap mBufferHeap; size_t mBufferSize; - mutable sp<android::Buffer> mTempBitmap; + mutable sp<GraphicBuffer> mTempBitmap; mutable LayerBase::Texture mTexture; copybit_device_t* mBlitEngine; }; diff --git a/libs/surfaceflinger/LayerDim.cpp b/libs/surfaceflinger/LayerDim.cpp index 8ba0a9d..538dc77 100644 --- a/libs/surfaceflinger/LayerDim.cpp +++ b/libs/surfaceflinger/LayerDim.cpp @@ -21,8 +21,8 @@ #include <utils/Errors.h> #include <utils/Log.h> -#include "Buffer.h" -#include "BufferAllocator.h" +#include <ui/GraphicBuffer.h> + #include "LayerDim.h" #include "SurfaceFlinger.h" #include "DisplayHardware/DisplayHardware.h" @@ -70,9 +70,9 @@ 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, - BufferAllocator::USAGE_SW_WRITE_OFTEN | - BufferAllocator::USAGE_HW_TEXTURE); + sp<GraphicBuffer> buffer = new GraphicBuffer(w, h, PIXEL_FORMAT_RGB_565, + GraphicBuffer::USAGE_SW_WRITE_OFTEN | + GraphicBuffer::USAGE_HW_TEXTURE); android_native_buffer_t* clientBuf = buffer->getNativeBuffer(); diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp index f2b918f..9694cf1 100644 --- a/libs/surfaceflinger/SurfaceFlinger.cpp +++ b/libs/surfaceflinger/SurfaceFlinger.cpp @@ -37,6 +37,7 @@ #include <utils/String16.h> #include <utils/StopWatch.h> +#include <ui/GraphicBufferAllocator.h> #include <ui/PixelFormat.h> #include <ui/DisplayInfo.h> @@ -44,8 +45,6 @@ #include <GLES/gl.h> #include "clz.h" -#include "Buffer.h" -#include "BufferAllocator.h" #include "Layer.h" #include "LayerBlur.h" #include "LayerBuffer.h" @@ -190,6 +189,7 @@ SurfaceFlinger::SurfaceFlinger() mLastSwapBufferTime(0), mDebugInTransaction(0), mLastTransactionTime(0), + mBootFinished(false), mConsoleSignals(0), mSecureFrameBuffer(0) { @@ -294,6 +294,7 @@ void SurfaceFlinger::bootFinished() const nsecs_t now = systemTime(); const nsecs_t duration = now - mBootTime; LOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) ); + mBootFinished = true; property_set("ctl.stop", "bootanim"); } @@ -1521,8 +1522,8 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) if (l != 0) { SharedBufferStack::Statistics stats = l->lcblk->getStats(); result.append( l->lcblk->dump(" ") ); - sp<const Buffer> buf0(l->getBuffer(0)); - sp<const Buffer> buf1(l->getBuffer(1)); + sp<const GraphicBuffer> buf0(l->getBuffer(0)); + sp<const GraphicBuffer> buf1(l->getBuffer(1)); uint32_t w0=0, h0=0, s0=0; uint32_t w1=0, h1=0, s1=0; if (buf0 != 0) { @@ -1573,7 +1574,7 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) } snprintf(buffer, SIZE, " client count: %d\n", mClientsMap.size()); result.append(buffer); - const BufferAllocator& alloc(BufferAllocator::get()); + const GraphicBufferAllocator& alloc(GraphicBufferAllocator::get()); alloc.dump(result); if (locked) { diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h index e446070..6698e00 100644 --- a/libs/surfaceflinger/SurfaceFlinger.h +++ b/libs/surfaceflinger/SurfaceFlinger.h @@ -293,7 +293,7 @@ private: inline void decFreezeCount() { if (mFreezeCount > 0) mFreezeCount--; } inline bool hasFreezeRequest() const { return mFreezeDisplay; } inline bool isFrozen() const { - return mFreezeDisplay || mFreezeCount>0; + return (mFreezeDisplay || mFreezeCount>0) && mBootFinished; } @@ -351,6 +351,7 @@ private: nsecs_t mLastSwapBufferTime; volatile nsecs_t mDebugInTransaction; nsecs_t mLastTransactionTime; + bool mBootFinished; // these are thread safe mutable Barrier mReadyToRunBarrier; diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk index 9577044..73d86ea 100644 --- a/libs/ui/Android.mk +++ b/libs/ui/Android.mk @@ -2,13 +2,15 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ - BufferMapper.cpp \ Camera.cpp \ CameraParameters.cpp \ EGLUtils.cpp \ EventHub.cpp \ EventRecurrence.cpp \ FramebufferNativeWindow.cpp \ + GraphicBuffer.cpp \ + GraphicBufferAllocator.cpp \ + GraphicBufferMapper.cpp \ KeyLayoutMap.cpp \ KeyCharacterMap.cpp \ ICamera.cpp \ @@ -25,7 +27,6 @@ LOCAL_SRC_FILES:= \ Region.cpp \ SharedBufferStack.cpp \ Surface.cpp \ - SurfaceBuffer.cpp \ SurfaceComposerClient.cpp \ SurfaceFlingerSynchro.cpp diff --git a/libs/ui/BufferMapper.cpp b/libs/ui/BufferMapper.cpp deleted file mode 100644 index 4add8f9..0000000 --- a/libs/ui/BufferMapper.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "BufferMapper" - -#include <stdint.h> -#include <errno.h> - -#include <utils/Errors.h> -#include <utils/Log.h> - -#include <ui/BufferMapper.h> -#include <ui/Rect.h> - -#include <hardware/gralloc.h> - - -namespace android { -// --------------------------------------------------------------------------- - -ANDROID_SINGLETON_STATIC_INSTANCE( BufferMapper ) - -BufferMapper::BufferMapper() - : mAllocMod(0) -{ - hw_module_t const* module; - int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module); - LOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID); - if (err == 0) { - mAllocMod = (gralloc_module_t const *)module; - } -} - -status_t BufferMapper::registerBuffer(buffer_handle_t handle) -{ - status_t err = mAllocMod->registerBuffer(mAllocMod, handle); - LOGW_IF(err, "registerBuffer(%p) failed %d (%s)", - handle, err, strerror(-err)); - return err; -} - -status_t BufferMapper::unregisterBuffer(buffer_handle_t handle) -{ - status_t err = mAllocMod->unregisterBuffer(mAllocMod, handle); - LOGW_IF(err, "unregisterBuffer(%p) failed %d (%s)", - handle, err, strerror(-err)); - return err; -} - -status_t BufferMapper::lock(buffer_handle_t handle, - int usage, const Rect& bounds, void** vaddr) -{ - status_t err = mAllocMod->lock(mAllocMod, handle, usage, - bounds.left, bounds.top, bounds.width(), bounds.height(), vaddr); - LOGW_IF(err, "lock(...) failed %d (%s)", err, strerror(-err)); - return err; -} - -status_t BufferMapper::unlock(buffer_handle_t handle) -{ - status_t err = mAllocMod->unlock(mAllocMod, handle); - LOGW_IF(err, "unlock(...) failed %d (%s)", err, strerror(-err)); - return err; -} - -// --------------------------------------------------------------------------- -}; // namespace android diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp new file mode 100644 index 0000000..1cf20d7 --- /dev/null +++ b/libs/ui/GraphicBuffer.cpp @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdlib.h> +#include <stdint.h> +#include <sys/types.h> + +#include <binder/Parcel.h> + +#include <utils/Errors.h> +#include <utils/Log.h> + +#include <ui/GraphicBuffer.h> +#include <ui/GraphicBufferAllocator.h> +#include <ui/GraphicBufferMapper.h> +#include <ui/PixelFormat.h> + +#include <pixelflinger/pixelflinger.h> + +namespace android { + +// =========================================================================== +// Buffer and implementation of android_native_buffer_t +// =========================================================================== + +GraphicBuffer::GraphicBuffer() + : BASE(), mOwner(false), mBufferMapper(GraphicBufferMapper::get()), + mInitCheck(NO_ERROR), mVStride(0), mIndex(-1) +{ + width = + height = + stride = + format = + usage = 0; + handle = NULL; +} + +GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h, + PixelFormat reqFormat, uint32_t reqUsage) + : BASE(), mOwner(false), mBufferMapper(GraphicBufferMapper::get()), + mInitCheck(NO_ERROR), mVStride(0), mIndex(-1) +{ + width = + height = + stride = + format = + usage = 0; + handle = NULL; + mInitCheck = initSize(w, h, reqFormat, reqUsage); +} + +GraphicBuffer::GraphicBuffer(const Parcel& data) + : BASE(), mOwner(true), mBufferMapper(GraphicBufferMapper::get()), + mInitCheck(NO_ERROR), mVStride(0), mIndex(-1) +{ + // we own the handle in this case + width = data.readInt32(); + if (width < 0) { + width = height = stride = format = usage = 0; + handle = 0; + } else { + height = data.readInt32(); + stride = data.readInt32(); + format = data.readInt32(); + usage = data.readInt32(); + handle = data.readNativeHandle(); + } +} + +GraphicBuffer::~GraphicBuffer() +{ + if (handle) { + if (mOwner) { + native_handle_close(handle); + native_handle_delete(const_cast<native_handle*>(handle)); + } else { + GraphicBufferAllocator& allocator(GraphicBufferAllocator::get()); + allocator.free(handle); + } + } +} + +status_t GraphicBuffer::initCheck() const { + return mInitCheck; +} + +android_native_buffer_t* GraphicBuffer::getNativeBuffer() const +{ + return static_cast<android_native_buffer_t*>( + const_cast<GraphicBuffer*>(this)); +} + +status_t GraphicBuffer::reallocate(uint32_t w, uint32_t h, PixelFormat f, + uint32_t reqUsage) +{ + if (handle) { + GraphicBufferAllocator& allocator(GraphicBufferAllocator::get()); + allocator.free(handle); + handle = 0; + } + return initSize(w, h, f, reqUsage); +} + +status_t GraphicBuffer::initSize(uint32_t w, uint32_t h, PixelFormat format, + uint32_t reqUsage) +{ + if (format == PIXEL_FORMAT_RGBX_8888) + format = PIXEL_FORMAT_RGBA_8888; + + GraphicBufferAllocator& allocator = GraphicBufferAllocator::get(); + status_t err = allocator.alloc(w, h, format, reqUsage, &handle, &stride); + if (err == NO_ERROR) { + this->width = w; + this->height = h; + this->format = format; + this->usage = reqUsage; + mVStride = 0; + } + return err; +} + +status_t GraphicBuffer::lock(uint32_t usage, void** vaddr) +{ + const Rect lockBounds(width, height); + status_t res = lock(usage, lockBounds, vaddr); + return res; +} + +status_t GraphicBuffer::lock(uint32_t usage, const Rect& rect, void** vaddr) +{ + if (rect.left < 0 || rect.right > this->width || + rect.top < 0 || rect.bottom > this->height) { + LOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)", + rect.left, rect.top, rect.right, rect.bottom, + this->width, this->height); + return BAD_VALUE; + } + status_t res = getBufferMapper().lock(handle, usage, rect, vaddr); + return res; +} + +status_t GraphicBuffer::unlock() +{ + status_t res = getBufferMapper().unlock(handle); + return res; +} + +status_t GraphicBuffer::lock(GGLSurface* sur, uint32_t usage) +{ + void* vaddr; + status_t res = GraphicBuffer::lock(usage, &vaddr); + if (res == NO_ERROR && sur) { + sur->version = sizeof(GGLSurface); + sur->width = width; + sur->height = height; + sur->stride = stride; + sur->format = format; + sur->vstride = mVStride; + sur->data = static_cast<GGLubyte*>(vaddr); + } + return res; +} + + +status_t GraphicBuffer::writeToParcel(Parcel* reply, + android_native_buffer_t const* buffer) +{ + if (buffer == NULL) + return BAD_VALUE; + + if (buffer->width < 0 || buffer->height < 0) + return BAD_VALUE; + + status_t err = NO_ERROR; + if (buffer->handle == NULL) { + // this buffer doesn't have a handle + reply->writeInt32(NO_MEMORY); + } else { + reply->writeInt32(buffer->width); + reply->writeInt32(buffer->height); + reply->writeInt32(buffer->stride); + reply->writeInt32(buffer->format); + reply->writeInt32(buffer->usage); + err = reply->writeNativeHandle(buffer->handle); + } + return err; +} + + +void GraphicBuffer::setIndex(int index) { + mIndex = index; +} + +int GraphicBuffer::getIndex() const { + return mIndex; +} + +// --------------------------------------------------------------------------- + +}; // namespace android diff --git a/libs/surfaceflinger/BufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp index 3e37bc3..57d5fc3 100644 --- a/libs/surfaceflinger/BufferAllocator.cpp +++ b/libs/ui/GraphicBufferAllocator.cpp @@ -20,18 +20,20 @@ #include <utils/Singleton.h> #include <utils/String8.h> -#include "BufferAllocator.h" +#include <ui/GraphicBufferAllocator.h> +#include <private/ui/sw_gralloc_handle.h> namespace android { // --------------------------------------------------------------------------- -ANDROID_SINGLETON_STATIC_INSTANCE( BufferAllocator ) +ANDROID_SINGLETON_STATIC_INSTANCE( GraphicBufferAllocator ) -Mutex BufferAllocator::sLock; -KeyedVector<buffer_handle_t, BufferAllocator::alloc_rec_t> BufferAllocator::sAllocList; +Mutex GraphicBufferAllocator::sLock; +KeyedVector<buffer_handle_t, + GraphicBufferAllocator::alloc_rec_t> GraphicBufferAllocator::sAllocList; -BufferAllocator::BufferAllocator() +GraphicBufferAllocator::GraphicBufferAllocator() : mAllocDev(0) { hw_module_t const* module; @@ -42,12 +44,12 @@ BufferAllocator::BufferAllocator() } } -BufferAllocator::~BufferAllocator() +GraphicBufferAllocator::~GraphicBufferAllocator() { gralloc_close(mAllocDev); } -void BufferAllocator::dump(String8& result) const +void GraphicBufferAllocator::dump(String8& result) const { Mutex::Autolock _l(sLock); KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList); @@ -73,7 +75,7 @@ static inline uint32_t clamp(uint32_t c) { return c>0 ? c : 1; } -status_t BufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat format, +status_t GraphicBufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat format, int usage, buffer_handle_t* handle, int32_t* stride) { Mutex::Autolock _l(mLock); @@ -83,8 +85,13 @@ status_t BufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat format, h = clamp(h); // we have a h/w allocator and h/w buffer is requested - status_t err = mAllocDev->alloc(mAllocDev, - w, h, format, usage, handle, stride); + status_t err; + + if (usage & GRALLOC_USAGE_HW_MASK) { + err = mAllocDev->alloc(mAllocDev, w, h, format, usage, handle, stride); + } else { + err = sw_gralloc_handle_t::alloc(w, h, format, usage, handle, stride); + } LOGW_IF(err, "alloc(%u, %u, %d, %08x, ...) failed %d (%s)", w, h, format, usage, err, strerror(-err)); @@ -109,13 +116,18 @@ status_t BufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat format, return err; } -status_t BufferAllocator::free(buffer_handle_t handle) +status_t GraphicBufferAllocator::free(buffer_handle_t handle) { Mutex::Autolock _l(mLock); - status_t err = mAllocDev->free(mAllocDev, handle); + status_t err; + if (sw_gralloc_handle_t::validate(handle) < 0) { + err = mAllocDev->free(mAllocDev, handle); + } else { + err = sw_gralloc_handle_t::free((sw_gralloc_handle_t*)handle); + } + LOGW_IF(err, "free(...) failed %d (%s)", err, strerror(-err)); - if (err == NO_ERROR) { Mutex::Autolock _l(sLock); KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList); diff --git a/libs/ui/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp new file mode 100644 index 0000000..ce2acd0 --- /dev/null +++ b/libs/ui/GraphicBufferMapper.cpp @@ -0,0 +1,228 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "GraphicBufferMapper" + +#include <stdint.h> +#ifdef HAVE_ANDROID_OS // just want PAGE_SIZE define +# include <asm/page.h> +#else +# include <sys/user.h> +#endif +#include <errno.h> +#include <sys/mman.h> + +#include <cutils/ashmem.h> + +#include <utils/Errors.h> +#include <utils/Log.h> + +#include <ui/GraphicBufferMapper.h> +#include <ui/Rect.h> + +#include <hardware/gralloc.h> + +#include <private/ui/sw_gralloc_handle.h> + + +namespace android { +// --------------------------------------------------------------------------- + +ANDROID_SINGLETON_STATIC_INSTANCE( GraphicBufferMapper ) + +GraphicBufferMapper::GraphicBufferMapper() + : mAllocMod(0) +{ + hw_module_t const* module; + int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module); + LOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID); + if (err == 0) { + mAllocMod = (gralloc_module_t const *)module; + } +} + +status_t GraphicBufferMapper::registerBuffer(buffer_handle_t handle) +{ + status_t err; + if (sw_gralloc_handle_t::validate(handle) < 0) { + err = mAllocMod->registerBuffer(mAllocMod, handle); + } else { + err = sw_gralloc_handle_t::registerBuffer((sw_gralloc_handle_t*)handle); + } + LOGW_IF(err, "registerBuffer(%p) failed %d (%s)", + handle, err, strerror(-err)); + return err; +} + +status_t GraphicBufferMapper::unregisterBuffer(buffer_handle_t handle) +{ + status_t err; + if (sw_gralloc_handle_t::validate(handle) < 0) { + err = mAllocMod->unregisterBuffer(mAllocMod, handle); + } else { + err = sw_gralloc_handle_t::unregisterBuffer((sw_gralloc_handle_t*)handle); + } + LOGW_IF(err, "unregisterBuffer(%p) failed %d (%s)", + handle, err, strerror(-err)); + return err; +} + +status_t GraphicBufferMapper::lock(buffer_handle_t handle, + int usage, const Rect& bounds, void** vaddr) +{ + status_t err; + if (sw_gralloc_handle_t::validate(handle) < 0) { + err = mAllocMod->lock(mAllocMod, handle, usage, + bounds.left, bounds.top, bounds.width(), bounds.height(), + vaddr); + } else { + err = sw_gralloc_handle_t::lock((sw_gralloc_handle_t*)handle, usage, + bounds.left, bounds.top, bounds.width(), bounds.height(), + vaddr); + } + LOGW_IF(err, "lock(...) failed %d (%s)", err, strerror(-err)); + return err; +} + +status_t GraphicBufferMapper::unlock(buffer_handle_t handle) +{ + status_t err; + if (sw_gralloc_handle_t::validate(handle) < 0) { + err = mAllocMod->unlock(mAllocMod, handle); + } else { + err = sw_gralloc_handle_t::unlock((sw_gralloc_handle_t*)handle); + } + LOGW_IF(err, "unlock(...) failed %d (%s)", err, strerror(-err)); + return err; +} + +// --------------------------------------------------------------------------- + +status_t sw_gralloc_handle_t::alloc(uint32_t w, uint32_t h, int format, + int usage, buffer_handle_t* pHandle, int32_t* pStride) +{ + int align = 4; + int bpp = 0; + switch (format) { + case HAL_PIXEL_FORMAT_RGBA_8888: + case HAL_PIXEL_FORMAT_RGBX_8888: + case HAL_PIXEL_FORMAT_BGRA_8888: + bpp = 4; + break; + case HAL_PIXEL_FORMAT_RGB_888: + bpp = 3; + break; + case HAL_PIXEL_FORMAT_RGB_565: + case HAL_PIXEL_FORMAT_RGBA_5551: + case HAL_PIXEL_FORMAT_RGBA_4444: + bpp = 2; + break; + default: + return -EINVAL; + } + size_t bpr = (w*bpp + (align-1)) & ~(align-1); + size_t size = bpr * h; + size_t stride = bpr / bpp; + size = (size + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1); + + int fd = ashmem_create_region("sw-gralloc-buffer", size); + if (fd < 0) { + LOGE("ashmem_create_region(size=%d) failed (%s)", + size, strerror(-errno)); + return -errno; + } + + int prot = PROT_READ; + if (usage & GRALLOC_USAGE_SW_WRITE_MASK) + prot |= PROT_WRITE; + + if (ashmem_set_prot_region(fd, prot) < 0) { + LOGE("ashmem_set_prot_region(fd=%d, prot=%x) failed (%s)", + fd, prot, strerror(-errno)); + close(fd); + return -errno; + } + + void* base = mmap(0, size, prot, MAP_SHARED, fd, 0); + if (base == MAP_FAILED) { + LOGE("alloc mmap(fd=%d, size=%d, prot=%x) failed (%s)", + fd, size, prot, strerror(-errno)); + close(fd); + return -errno; + } + + sw_gralloc_handle_t* hnd = new sw_gralloc_handle_t(); + hnd->fd = fd; + hnd->size = size; + hnd->base = intptr_t(base); + hnd->prot = prot; + *pStride = stride; + *pHandle = hnd; + + return NO_ERROR; +} + +status_t sw_gralloc_handle_t::free(sw_gralloc_handle_t* hnd) +{ + if (hnd->base) { + munmap((void*)hnd->base, hnd->size); + } + if (hnd->fd >= 0) { + close(hnd->fd); + } + delete hnd; + return NO_ERROR; +} + +status_t sw_gralloc_handle_t::registerBuffer(sw_gralloc_handle_t* hnd) +{ + if (hnd->pid != getpid()) { + void* base = mmap(0, hnd->size, hnd->prot, MAP_SHARED, hnd->fd, 0); + if (base == MAP_FAILED) { + LOGE("registerBuffer mmap(fd=%d, size=%d, prot=%x) failed (%s)", + hnd->fd, hnd->size, hnd->prot, strerror(-errno)); + return -errno; + } + hnd->base = intptr_t(base); + } + return NO_ERROR; +} + +status_t sw_gralloc_handle_t::unregisterBuffer(sw_gralloc_handle_t* hnd) +{ + if (hnd->pid != getpid()) { + if (hnd->base) { + munmap((void*)hnd->base, hnd->size); + } + hnd->base = 0; + } + return NO_ERROR; +} + +status_t sw_gralloc_handle_t::lock(sw_gralloc_handle_t* hnd, int usage, + int l, int t, int w, int h, void** vaddr) +{ + *vaddr = (void*)hnd->base; + return NO_ERROR; +} + +status_t sw_gralloc_handle_t::unlock(sw_gralloc_handle_t* hnd) +{ + return NO_ERROR; +} + +// --------------------------------------------------------------------------- +}; // namespace android diff --git a/libs/ui/ISurface.cpp b/libs/ui/ISurface.cpp index a2dbe7f..4fb38ed 100644 --- a/libs/ui/ISurface.cpp +++ b/libs/ui/ISurface.cpp @@ -27,7 +27,7 @@ #include <ui/Overlay.h> #include <ui/Surface.h> -#include <private/ui/SurfaceBuffer.h> +#include <ui/GraphicBuffer.h> namespace android { @@ -71,14 +71,14 @@ public: { } - virtual sp<SurfaceBuffer> requestBuffer(int bufferIdx, int usage) + virtual sp<GraphicBuffer> requestBuffer(int bufferIdx, int usage) { Parcel data, reply; data.writeInterfaceToken(ISurface::getInterfaceDescriptor()); data.writeInt32(bufferIdx); data.writeInt32(usage); remote()->transact(REQUEST_BUFFER, data, &reply); - sp<SurfaceBuffer> buffer = new SurfaceBuffer(reply); + sp<GraphicBuffer> buffer = new GraphicBuffer(reply); return buffer; } @@ -139,8 +139,8 @@ status_t BnSurface::onTransact( CHECK_INTERFACE(ISurface, data, reply); int bufferIdx = data.readInt32(); int usage = data.readInt32(); - sp<SurfaceBuffer> buffer(requestBuffer(bufferIdx, usage)); - return SurfaceBuffer::writeToParcel(reply, buffer.get()); + sp<GraphicBuffer> buffer(requestBuffer(bufferIdx, usage)); + return GraphicBuffer::writeToParcel(reply, buffer.get()); } case REGISTER_BUFFERS: { CHECK_INTERFACE(ISurface, data, reply); diff --git a/libs/ui/Surface.cpp b/libs/ui/Surface.cpp index 285edb4..7822533 100644 --- a/libs/ui/Surface.cpp +++ b/libs/ui/Surface.cpp @@ -31,7 +31,8 @@ #include <utils/Log.h> #include <ui/DisplayInfo.h> -#include <ui/BufferMapper.h> +#include <ui/GraphicBuffer.h> +#include <ui/GraphicBufferMapper.h> #include <ui/ISurface.h> #include <ui/Surface.h> #include <ui/SurfaceComposerClient.h> @@ -41,15 +42,14 @@ #include <private/ui/SharedBufferStack.h> #include <private/ui/LayerState.h> -#include <private/ui/SurfaceBuffer.h> namespace android { // ---------------------------------------------------------------------- static status_t copyBlt( - const sp<SurfaceBuffer>& dst, - const sp<SurfaceBuffer>& src, + const sp<GraphicBuffer>& dst, + const sp<GraphicBuffer>& src, const Region& reg) { status_t err; @@ -310,7 +310,7 @@ Surface::Surface(const sp<SurfaceControl>& surface) : mClient(surface->mClient), mSurface(surface->mSurface), mToken(surface->mToken), mIdentity(surface->mIdentity), mFormat(surface->mFormat), mFlags(surface->mFlags), - mBufferMapper(BufferMapper::get()), mSharedBufferClient(NULL), + mBufferMapper(GraphicBufferMapper::get()), mSharedBufferClient(NULL), mWidth(surface->mWidth), mHeight(surface->mHeight) { mSharedBufferClient = new SharedBufferClient( @@ -320,7 +320,7 @@ Surface::Surface(const sp<SurfaceControl>& surface) } Surface::Surface(const Parcel& parcel) - : mBufferMapper(BufferMapper::get()), mSharedBufferClient(NULL) + : mBufferMapper(GraphicBufferMapper::get()), mSharedBufferClient(NULL) { sp<IBinder> clientBinder = parcel.readStrongBinder(); mSurface = interface_cast<ISurface>(parcel.readStrongBinder()); @@ -473,11 +473,11 @@ int Surface::perform(android_native_window_t* window, // ---------------------------------------------------------------------------- -status_t Surface::dequeueBuffer(sp<SurfaceBuffer>* buffer) { +status_t Surface::dequeueBuffer(sp<GraphicBuffer>* buffer) { android_native_buffer_t* out; status_t err = dequeueBuffer(&out); if (err == NO_ERROR) { - *buffer = SurfaceBuffer::getSelf(out); + *buffer = GraphicBuffer::getSelf(out); } return err; } @@ -500,7 +500,7 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer) // below we make sure we AT LEAST have the usage flags we want const uint32_t usage(getUsage()); - const sp<SurfaceBuffer>& backBuffer(mBuffers[bufIdx]); + const sp<GraphicBuffer>& backBuffer(mBuffers[bufIdx]); if (backBuffer == 0 || ((uint32_t(backBuffer->usage) & usage) != usage) || mSharedBufferClient->needNewBuffer(bufIdx)) @@ -537,7 +537,7 @@ int Surface::lockBuffer(android_native_buffer_t* buffer) if (err != NO_ERROR) return err; - int32_t bufIdx = SurfaceBuffer::getSelf(buffer)->getIndex(); + int32_t bufIdx = GraphicBuffer::getSelf(buffer)->getIndex(); err = mSharedBufferClient->lock(bufIdx); LOGE_IF(err, "error locking buffer %d (%s)", bufIdx, strerror(-err)); return err; @@ -554,7 +554,7 @@ int Surface::queueBuffer(android_native_buffer_t* buffer) mDirtyRegion.set(mSwapRectangle); } - int32_t bufIdx = SurfaceBuffer::getSelf(buffer)->getIndex(); + int32_t bufIdx = GraphicBuffer::getSelf(buffer)->getIndex(); mSharedBufferClient->setDirtyRegion(bufIdx, mDirtyRegion); err = mSharedBufferClient->queue(bufIdx); LOGE_IF(err, "error queuing buffer %d (%s)", bufIdx, strerror(-err)); @@ -627,7 +627,7 @@ status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking) // we're intending to do software rendering from this point setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); - sp<SurfaceBuffer> backBuffer; + sp<GraphicBuffer> backBuffer; status_t err = dequeueBuffer(&backBuffer); LOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err)); if (err == NO_ERROR) { @@ -652,7 +652,7 @@ status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking) newDirtyRegion.andSelf(bounds); } - const sp<SurfaceBuffer>& frontBuffer(mPostedBuffer); + const sp<GraphicBuffer>& frontBuffer(mPostedBuffer); if (frontBuffer !=0 && backBuffer->width == frontBuffer->width && backBuffer->height == frontBuffer->height && @@ -721,13 +721,13 @@ status_t Surface::getBufferLocked(int index, int usage) status_t err = NO_MEMORY; // free the current buffer - sp<SurfaceBuffer>& currentBuffer(mBuffers[index]); + sp<GraphicBuffer>& currentBuffer(mBuffers[index]); if (currentBuffer != 0) { getBufferMapper().unregisterBuffer(currentBuffer->handle); currentBuffer.clear(); } - sp<SurfaceBuffer> buffer = s->requestBuffer(index, usage); + sp<GraphicBuffer> buffer = s->requestBuffer(index, usage); LOGE_IF(buffer==0, "ISurface::getBuffer(%d, %08x) returned NULL", index, usage); diff --git a/libs/ui/SurfaceBuffer.cpp b/libs/ui/SurfaceBuffer.cpp deleted file mode 100644 index 0510bc1..0000000 --- a/libs/ui/SurfaceBuffer.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "SurfaceBuffer" - -#include <stdint.h> -#include <errno.h> -#include <sys/types.h> - -#include <utils/Errors.h> -#include <utils/Log.h> -#include <binder/Parcel.h> - -#include <ui/BufferMapper.h> -#include <ui/Rect.h> -#include <private/ui/SurfaceBuffer.h> - -namespace android { - -// ============================================================================ -// SurfaceBuffer -// ============================================================================ - -SurfaceBuffer::SurfaceBuffer() - : BASE(), mOwner(false), mBufferMapper(BufferMapper::get()), mIndex(-1) -{ - width = - height = - stride = - format = - usage = 0; - handle = NULL; -} - -SurfaceBuffer::SurfaceBuffer(const Parcel& data) - : BASE(), mOwner(true), mBufferMapper(BufferMapper::get()) -{ - // we own the handle in this case - width = data.readInt32(); - if (width < 0) { - width = height = stride = format = usage = 0; - handle = 0; - } else { - height = data.readInt32(); - stride = data.readInt32(); - format = data.readInt32(); - usage = data.readInt32(); - handle = data.readNativeHandle(); - } -} - -SurfaceBuffer::~SurfaceBuffer() -{ - if (handle && mOwner) { - native_handle_close(handle); - native_handle_delete(const_cast<native_handle*>(handle)); - } -} - -status_t SurfaceBuffer::lock(uint32_t usage, void** vaddr) -{ - const Rect lockBounds(width, height); - status_t res = lock(usage, lockBounds, vaddr); - return res; -} - -status_t SurfaceBuffer::lock(uint32_t usage, const Rect& rect, void** vaddr) -{ - if (rect.left < 0 || rect.right > this->width || - rect.top < 0 || rect.bottom > this->height) { - LOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)", - rect.left, rect.top, rect.right, rect.bottom, - this->width, this->height); - return BAD_VALUE; - } - status_t res = getBufferMapper().lock(handle, usage, rect, vaddr); - return res; -} - -status_t SurfaceBuffer::unlock() -{ - status_t res = getBufferMapper().unlock(handle); - return res; -} - -status_t SurfaceBuffer::writeToParcel(Parcel* reply, - android_native_buffer_t const* buffer) -{ - if (buffer == NULL) - return BAD_VALUE; - - if (buffer->width < 0 || buffer->height < 0) - return BAD_VALUE; - - status_t err = NO_ERROR; - if (buffer->handle == NULL) { - // this buffer doesn't have a handle - reply->writeInt32(NO_MEMORY); - } else { - reply->writeInt32(buffer->width); - reply->writeInt32(buffer->height); - reply->writeInt32(buffer->stride); - reply->writeInt32(buffer->format); - reply->writeInt32(buffer->usage); - err = reply->writeNativeHandle(buffer->handle); - } - return err; -} - - -void SurfaceBuffer::setIndex(int index) { - mIndex = index; -} - -int SurfaceBuffer::getIndex() const { - return mIndex; -} - - -}; // namespace android - |