diff options
author | Mathias Agopian <mathias@google.com> | 2011-04-20 14:20:59 -0700 |
---|---|---|
committer | Mathias Agopian <mathias@google.com> | 2011-06-13 15:51:35 -0700 |
commit | a67932fe6864ac346e7f78b86df11cf6c5344137 (patch) | |
tree | c7a9d1e48498b0683666c32d005fad728dd3475e /services/surfaceflinger | |
parent | ac642349ba89c8839c421502fb779bee5cebfee3 (diff) | |
download | frameworks_native-a67932fe6864ac346e7f78b86df11cf6c5344137.zip frameworks_native-a67932fe6864ac346e7f78b86df11cf6c5344137.tar.gz frameworks_native-a67932fe6864ac346e7f78b86df11cf6c5344137.tar.bz2 |
unify SurfaceTexture and Surface
Add the concept of synchronous dequeueBuffer in SurfaceTexture
Implement {Surface|SurfaceTextureClient}::setSwapInterval()
Add SurfaceTexture logging
fix onFrameAvailable
Diffstat (limited to 'services/surfaceflinger')
-rw-r--r-- | services/surfaceflinger/Android.mk | 22 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.cpp | 866 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.h | 164 | ||||
-rw-r--r-- | services/surfaceflinger/LayerBase.cpp | 208 | ||||
-rw-r--r-- | services/surfaceflinger/LayerBase.h | 84 | ||||
-rw-r--r-- | services/surfaceflinger/LayerDim.cpp | 2 | ||||
-rw-r--r-- | services/surfaceflinger/LayerDim.h | 2 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 214 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 42 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceTextureLayer.cpp | 76 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceTextureLayer.h | 55 | ||||
-rw-r--r-- | services/surfaceflinger/clz.h | 10 |
12 files changed, 499 insertions, 1246 deletions
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index 9daaad8..c618263 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -2,18 +2,18 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ - clz.cpp.arm \ - DisplayHardware/DisplayHardware.cpp \ + Layer.cpp \ + LayerBase.cpp \ + LayerDim.cpp \ + DisplayHardware/DisplayHardware.cpp \ DisplayHardware/DisplayHardwareBase.cpp \ - DisplayHardware/HWComposer.cpp \ - GLExtensions.cpp \ - Layer.cpp \ - LayerBase.cpp \ - LayerDim.cpp \ - MessageQueue.cpp \ - SurfaceFlinger.cpp \ - TextureManager.cpp \ - Transform.cpp + DisplayHardware/HWComposer.cpp \ + GLExtensions.cpp \ + MessageQueue.cpp \ + SurfaceFlinger.cpp \ + SurfaceTextureLayer.cpp \ + Transform.cpp \ + LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\" LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 8df2b92..0137120 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -18,8 +18,9 @@ #include <stdint.h> #include <sys/types.h> -#include <cutils/properties.h> +#include <cutils/compiler.h> #include <cutils/native_handle.h> +#include <cutils/properties.h> #include <utils/Errors.h> #include <utils/Log.h> @@ -31,12 +32,12 @@ #include <surfaceflinger/Surface.h> #include "clz.h" +#include "DisplayHardware/DisplayHardware.h" +#include "DisplayHardware/HWComposer.h" #include "GLExtensions.h" #include "Layer.h" #include "SurfaceFlinger.h" -#include "DisplayHardware/DisplayHardware.h" -#include "DisplayHardware/HWComposer.h" - +#include "SurfaceTextureLayer.h" #define DEBUG_RESIZE 0 @@ -52,102 +53,81 @@ template <typename T> inline T min(T a, T b) { Layer::Layer(SurfaceFlinger* flinger, DisplayID display, const sp<Client>& client) : LayerBaseClient(flinger, display, client), + mTextureName(-1U), + mQueuedFrames(0), + mCurrentTransform(0), + mCurrentOpacity(true), mFormat(PIXEL_FORMAT_NONE), mGLExtensions(GLExtensions::getInstance()), - mNeedsBlending(true), + mOpaqueLayer(true), mNeedsDithering(false), mSecure(false), mProtectedByApp(false), - mTextureManager(), - mBufferManager(mTextureManager), - mWidth(0), mHeight(0), - mNeedsScaling(false), mFixedSize(false) -{ -} - -Layer::~Layer() + mFixedSize(false) { - // FIXME: must be called from the main UI thread - EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay()); - mBufferManager.destroy(dpy); - - // we can use getUserClientUnsafe here because we know we're - // single-threaded at that point. - sp<UserClient> ourClient(mUserClientRef.getUserClientUnsafe()); - if (ourClient != 0) { - ourClient->detachLayer(this); - } + mCurrentCrop.makeInvalid(); + glGenTextures(1, &mTextureName); } void Layer::destroy() const { mFlinger->destroyLayer(this); } -status_t Layer::setToken(const sp<UserClient>& userClient, - SharedClient* sharedClient, int32_t token) +void Layer::onFirstRef() { - sp<SharedBufferServer> lcblk = new SharedBufferServer( - sharedClient, token, mBufferManager.getDefaultBufferCount(), - getIdentity()); - - - sp<UserClient> ourClient(mUserClientRef.getClient()); - - /* - * Here it is guaranteed that userClient != ourClient - * (see UserClient::getTokenForSurface()). - * - * We release the token used by this surface in ourClient below. - * This should be safe to do so now, since this layer won't be attached - * to this client, it should be okay to reuse that id. - * - * If this causes problems, an other solution would be to keep a list - * of all the {UserClient, token} ever used and release them when the - * Layer is destroyed. - * - */ - - if (ourClient != 0) { - ourClient->detachLayer(this); - } - - status_t err = mUserClientRef.setToken(userClient, lcblk, token); - LOGE_IF(err != NO_ERROR, - "ClientRef::setToken(%p, %p, %u) failed", - userClient.get(), lcblk.get(), token); - - if (err == NO_ERROR) { - // we need to free the buffers associated with this surface - } - - return err; + LayerBaseClient::onFirstRef(); + struct FrameQueuedListener : public SurfaceTexture::FrameAvailableListener { + FrameQueuedListener(Layer* layer) : mLayer(layer) { } + private: + wp<Layer> mLayer; + virtual void onFrameAvailable() { + sp<Layer> that(mLayer.promote()); + if (that != 0) { + that->onFrameQueued(); + } + } + }; + mSurfaceTexture = new SurfaceTextureLayer(mTextureName, this); + mSurfaceTexture->setFrameAvailableListener(new FrameQueuedListener(this)); + mSurfaceTexture->setSynchronousMode(true); + mSurfaceTexture->setBufferCountServer(2); } -int32_t Layer::getToken() const +Layer::~Layer() { - return mUserClientRef.getToken(); + glDeleteTextures(1, &mTextureName); } -sp<UserClient> Layer::getClient() const -{ - return mUserClientRef.getClient(); +void Layer::onFrameQueued() { + if (android_atomic_or(1, &mQueuedFrames) == 0) { + mFlinger->signalEvent(); + } } // called with SurfaceFlinger::mStateLock as soon as the layer is entered // in the purgatory list void Layer::onRemoved() { - ClientRef::Access sharedClient(mUserClientRef); - SharedBufferServer* lcblk(sharedClient.get()); - if (lcblk) { - // wake up the condition - lcblk->setStatus(NO_INIT); - } } -sp<LayerBaseClient::Surface> Layer::createSurface() const +sp<ISurface> Layer::createSurface() { - sp<Surface> sur(new SurfaceLayer(mFlinger, const_cast<Layer *>(this))); + class BSurface : public BnSurface, public LayerCleaner { + wp<const Layer> mOwner; + virtual sp<ISurfaceTexture> getSurfaceTexture() const { + sp<ISurfaceTexture> res; + sp<const Layer> that( mOwner.promote() ); + if (that != NULL) { + res = that->mSurfaceTexture; + } + return res; + } + public: + BSurface(const sp<SurfaceFlinger>& flinger, + const sp<Layer>& layer) + : LayerCleaner(flinger, layer), mOwner(layer) { } + }; + sp<ISurface> sur(new BSurface(mFlinger, this)); return sur; } @@ -175,17 +155,14 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h, const uint32_t hwFlags = hw.getFlags(); mFormat = format; - mWidth = w; - mHeight = h; - - mReqFormat = format; - mReqWidth = w; - mReqHeight = h; mSecure = (flags & ISurfaceComposer::eSecure) ? true : false; mProtectedByApp = (flags & ISurfaceComposer::eProtectedByApp) ? true : false; - mNeedsBlending = (info.h_alpha - info.l_alpha) > 0 && - (flags & ISurfaceComposer::eOpaque) == 0; + mOpaqueLayer = (flags & ISurfaceComposer::eOpaque); + mCurrentOpacity = getOpacityForFormat(format); + + mSurfaceTexture->setDefaultBufferSize(w, h); + mSurfaceTexture->setDefaultBufferFormat(format); // we use the red index int displayRedSize = displayInfo.getSize(PixelFormatInfo::INDEX_RED); @@ -216,10 +193,12 @@ void Layer::setGeometry(hwc_layer_t* hwcl) return; } - Transform tr(Transform(mOrientation) * Transform(mBufferTransform)); + // FIXME: shouldn't we take the state's transform into account here? + + Transform tr(Transform(mOrientation) * Transform(mCurrentTransform)); hwcl->transform = tr.getOrientation(); - if (needsBlending()) { + if (!isOpaque()) { hwcl->blending = mPremultipliedAlpha ? HWC_BLENDING_PREMULT : HWC_BLENDING_COVERAGE; } @@ -236,7 +215,7 @@ void Layer::setGeometry(hwc_layer_t* hwcl) } void Layer::setPerFrameData(hwc_layer_t* hwcl) { - sp<GraphicBuffer> buffer(mBufferManager.getActiveBuffer()); + const sp<GraphicBuffer>& buffer(mActiveBuffer); if (buffer == NULL) { // this can happen if the client never drew into this layer yet, // or if we ran out of memory. In that case, don't let @@ -247,11 +226,11 @@ void Layer::setPerFrameData(hwc_layer_t* hwcl) { } hwcl->handle = buffer->handle; - if (!mBufferCrop.isEmpty()) { - hwcl->sourceCrop.left = mBufferCrop.left; - hwcl->sourceCrop.top = mBufferCrop.top; - hwcl->sourceCrop.right = mBufferCrop.right; - hwcl->sourceCrop.bottom = mBufferCrop.bottom; + if (isCropped()) { + hwcl->sourceCrop.left = mCurrentCrop.left; + hwcl->sourceCrop.top = mCurrentCrop.top; + hwcl->sourceCrop.right = mCurrentCrop.right; + hwcl->sourceCrop.bottom = mCurrentCrop.bottom; } else { hwcl->sourceCrop.left = 0; hwcl->sourceCrop.top = 0; @@ -260,51 +239,12 @@ void Layer::setPerFrameData(hwc_layer_t* hwcl) { } } -void Layer::reloadTexture(const Region& dirty) -{ - sp<GraphicBuffer> buffer(mBufferManager.getActiveBuffer()); - if (buffer == NULL) { - // this situation can happen if we ran out of memory for instance. - // not much we can do. continue to use whatever texture was bound - // to this context. - return; - } - - if (mGLExtensions.haveDirectTexture()) { - EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay()); - if (mBufferManager.initEglImage(dpy, buffer) != NO_ERROR) { - // not sure what we can do here... - goto slowpath; - } - } else { -slowpath: - GGLSurface t; - if (buffer->usage & GRALLOC_USAGE_SW_READ_MASK) { - 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) { - mBufferManager.loadTexture(dirty, t); - buffer->unlock(); - } - } else { - // we can't do anything - } - } -} - -void Layer::drawForSreenShot() const -{ - const bool currentFiltering = mNeedsFiltering; - const_cast<Layer*>(this)->mNeedsFiltering = true; - LayerBase::drawForSreenShot(); - const_cast<Layer*>(this)->mNeedsFiltering = currentFiltering; +static inline uint16_t pack565(int r, int g, int b) { + return (r<<11)|(g<<5)|b; } - void Layer::onDraw(const Region& clip) const { - Texture tex(mBufferManager.getActiveTexture()); - if (tex.name == -1LU) { + if (CC_UNLIKELY(mActiveBuffer == 0)) { // the texture has not been created yet, this Layer has // in fact never been drawn into. This happens frequently with // SurfaceView because the WindowManager can't know when the client @@ -330,7 +270,25 @@ void Layer::onDraw(const Region& clip) const } return; } - drawWithOpenGL(clip, tex); + + GLenum target = mSurfaceTexture->getCurrentTextureTarget(); + glBindTexture(target, mTextureName); + if (getFiltering() || needsFiltering() || isFixedSize() || isCropped()) { + // TODO: we could be more subtle with isFixedSize() + glTexParameterx(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterx(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } else { + glTexParameterx(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterx(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } + glEnable(target); + glMatrixMode(GL_TEXTURE); + glLoadMatrixf(mTextureMatrix); + glMatrixMode(GL_MODELVIEW); + + drawWithOpenGL(clip); + + glDisable(target); } // As documented in libhardware header, formats in the range @@ -340,186 +298,37 @@ void Layer::onDraw(const Region& clip) const // hardware.h, instead of using hard-coded values here. #define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF) -bool Layer::needsBlending(const sp<GraphicBuffer>& buffer) const +bool Layer::getOpacityForFormat(uint32_t format) { - // If buffers where set with eOpaque flag, all buffers are known to - // be opaque without having to check their actual format - if (mNeedsBlending && buffer != NULL) { - PixelFormat format = buffer->getPixelFormat(); - - if (HARDWARE_IS_DEVICE_FORMAT(format)) { - return false; - } - - PixelFormatInfo info; - status_t err = getPixelFormatInfo(format, &info); - if (!err && info.h_alpha <= info.l_alpha) { - return false; - } + if (HARDWARE_IS_DEVICE_FORMAT(format)) { + return true; } - - // Return opacity as determined from flags and format options - // passed to setBuffers() - return mNeedsBlending; + PixelFormatInfo info; + status_t err = getPixelFormatInfo(PixelFormat(format), &info); + // in case of error (unknown format), we assume no blending + return (err || info.h_alpha <= info.l_alpha); } -bool Layer::needsBlending() const -{ - if (mBufferManager.hasActiveBuffer()) { - return needsBlending(mBufferManager.getActiveBuffer()); - } - return mNeedsBlending; -} - -bool Layer::needsFiltering() const +bool Layer::isOpaque() const { - if (!(mFlags & DisplayHardware::SLOW_CONFIG)) { - // if our buffer is not the same size than ourselves, - // we need filtering. - Mutex::Autolock _l(mLock); - if (mNeedsScaling) - return true; - } - return LayerBase::needsFiltering(); + // if we don't have a buffer yet, we're translucent regardless of the + // layer's opaque flag. + if (mActiveBuffer == 0) + return false; + + // if the layer has the opaque flag, then we're always opaque, + // otherwise we use the current buffer's format. + return mOpaqueLayer || mCurrentOpacity; } bool Layer::isProtected() const { - sp<GraphicBuffer> activeBuffer(mBufferManager.getActiveBuffer()); + const sp<GraphicBuffer>& activeBuffer(mActiveBuffer); return (activeBuffer != 0) && (activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED); } -status_t Layer::setBufferCount(int bufferCount) -{ - ClientRef::Access sharedClient(mUserClientRef); - SharedBufferServer* lcblk(sharedClient.get()); - if (!lcblk) { - // oops, the client is already gone - return DEAD_OBJECT; - } - - // NOTE: lcblk->resize() is protected by an internal lock - status_t err = lcblk->resize(bufferCount); - if (err == NO_ERROR) { - EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay()); - mBufferManager.resize(bufferCount, mFlinger, dpy); - } - - return err; -} - -sp<GraphicBuffer> Layer::requestBuffer(int index, - uint32_t reqWidth, uint32_t reqHeight, uint32_t reqFormat, - uint32_t usage) -{ - sp<GraphicBuffer> buffer; - - if (int32_t(reqWidth | reqHeight | reqFormat) < 0) - return buffer; - - if ((!reqWidth && reqHeight) || (reqWidth && !reqHeight)) - return buffer; - - // this ensures our client doesn't go away while we're accessing - // the shared area. - ClientRef::Access sharedClient(mUserClientRef); - SharedBufferServer* lcblk(sharedClient.get()); - if (!lcblk) { - // oops, the client is already gone - return buffer; - } - - /* - * This is called from the client's Surface::dequeue(). This can happen - * at any time, especially while we're in the middle of using the - * buffer 'index' as our front buffer. - */ - - status_t err = NO_ERROR; - uint32_t w, h, f; - { // scope for the lock - Mutex::Autolock _l(mLock); - - // zero means default - const bool fixedSize = reqWidth && reqHeight; - if (!reqFormat) reqFormat = mFormat; - if (!reqWidth) reqWidth = mWidth; - if (!reqHeight) reqHeight = mHeight; - - w = reqWidth; - h = reqHeight; - f = reqFormat; - - if ((reqWidth != mReqWidth) || (reqHeight != mReqHeight) || - (reqFormat != mReqFormat)) { - mReqWidth = reqWidth; - mReqHeight = reqHeight; - mReqFormat = reqFormat; - mFixedSize = fixedSize; - mNeedsScaling = mWidth != mReqWidth || mHeight != mReqHeight; - - lcblk->reallocateAllExcept(index); - } - } - - // here we have to reallocate a new buffer because the buffer could be - // used as the front buffer, or by a client in our process - // (eg: status bar), and we can't release the handle under its feet. - const uint32_t effectiveUsage = getEffectiveUsage(usage); - buffer = new GraphicBuffer(w, h, f, effectiveUsage); - err = buffer->initCheck(); - - if (err || buffer->handle == 0) { - GraphicBuffer::dumpAllocationsToSystemLog(); - LOGE_IF(err || buffer->handle == 0, - "Layer::requestBuffer(this=%p), index=%d, w=%d, h=%d failed (%s)", - this, index, w, h, strerror(-err)); - } else { - LOGD_IF(DEBUG_RESIZE, - "Layer::requestBuffer(this=%p), index=%d, w=%d, h=%d, handle=%p", - this, index, w, h, buffer->handle); - } - - if (err == NO_ERROR && buffer->handle != 0) { - Mutex::Autolock _l(mLock); - mBufferManager.attachBuffer(index, buffer); - } - 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. - // request EGLImage for all buffers - usage |= GraphicBuffer::USAGE_HW_TEXTURE; - } - if (mProtectedByApp) { - // need a hardware-protected path to external video sink - usage |= GraphicBuffer::USAGE_PROTECTED; - } - return usage; -} - uint32_t Layer::doTransaction(uint32_t flags) { const Layer::State& front(drawingState()); @@ -531,10 +340,12 @@ uint32_t Layer::doTransaction(uint32_t flags) if (sizeChanged) { // the size changed, we need to ask our client to request a new buffer LOGD_IF(DEBUG_RESIZE, - "resize (layer=%p), requested (%dx%d), drawing (%d,%d)", + "resize (layer=%p), requested (%dx%d), drawing (%d,%d), " + "fixedSize=%d", this, int(temp.requested_w), int(temp.requested_h), - int(front.requested_w), int(front.requested_h)); + int(front.requested_w), int(front.requested_h), + isFixedSize()); if (!isFixedSize()) { // we're being resized and there is a freeze display request, @@ -557,17 +368,7 @@ uint32_t Layer::doTransaction(uint32_t flags) // record the new size, form this point on, when the client request // a buffer, it'll get the new size. - setBufferSize(temp.requested_w, temp.requested_h); - - ClientRef::Access sharedClient(mUserClientRef); - SharedBufferServer* lcblk(sharedClient.get()); - if (lcblk) { - // all buffers need reallocation - lcblk->reallocateAll(); - } - } else { - // record the new size - setBufferSize(temp.requested_w, temp.requested_h); + mSurfaceTexture->setDefaultBufferSize(temp.requested_w, temp.requested_h); } } @@ -582,16 +383,19 @@ uint32_t Layer::doTransaction(uint32_t flags) return LayerBase::doTransaction(flags); } -void Layer::setBufferSize(uint32_t w, uint32_t h) { +bool Layer::isFixedSize() const { Mutex::Autolock _l(mLock); - mWidth = w; - mHeight = h; - mNeedsScaling = mWidth != mReqWidth || mHeight != mReqHeight; + return mFixedSize; } -bool Layer::isFixedSize() const { +void Layer::setFixedSize(bool fixedSize) +{ Mutex::Autolock _l(mLock); - return mFixedSize; + mFixedSize = fixedSize; +} + +bool Layer::isCropped() const { + return !mCurrentCrop.isEmpty(); } // ---------------------------------------------------------------------------- @@ -600,61 +404,48 @@ bool Layer::isFixedSize() const { void Layer::lockPageFlip(bool& recomputeVisibleRegions) { - ClientRef::Access sharedClient(mUserClientRef); - SharedBufferServer* lcblk(sharedClient.get()); - if (!lcblk) { - // client died - recomputeVisibleRegions = true; - return; - } - - ssize_t buf = lcblk->retireAndLock(); - if (buf == NOT_ENOUGH_DATA) { - // NOTE: This is not an error, it simply means there is nothing to - // retire. The buffer is locked because we will use it - // for composition later in the loop - return; - } - - if (buf < NO_ERROR) { - LOGE("retireAndLock() buffer index (%d) out of range", int(buf)); - mPostedDirtyRegion.clear(); - return; - } + if (android_atomic_and(0, &mQueuedFrames)) { + if (mSurfaceTexture->updateTexImage() < NO_ERROR) { + // something happened! + recomputeVisibleRegions = true; + return; + } - // we retired a buffer, which becomes the new front buffer + // signal another event if we have more frames waiting + if (mSurfaceTexture->getQueuedCount()) { + if (android_atomic_or(1, &mQueuedFrames) == 0) { + mFlinger->signalEvent(); + } + } - const bool noActiveBuffer = !mBufferManager.hasActiveBuffer(); - const bool activeBlending = - noActiveBuffer ? true : needsBlending(mBufferManager.getActiveBuffer()); + mActiveBuffer = mSurfaceTexture->getCurrentBuffer(); + mSurfaceTexture->getTransformMatrix(mTextureMatrix); - if (mBufferManager.setActiveBufferIndex(buf) < NO_ERROR) { - LOGE("retireAndLock() buffer index (%d) out of range", int(buf)); - mPostedDirtyRegion.clear(); - return; - } - - if (noActiveBuffer) { - // we didn't have an active buffer, we need to recompute - // our visible region - recomputeVisibleRegions = true; - } + const Rect crop(mSurfaceTexture->getCurrentCrop()); + const uint32_t transform(mSurfaceTexture->getCurrentTransform()); + if ((crop != mCurrentCrop) || (transform != mCurrentTransform)) { + mCurrentCrop = crop; + mCurrentTransform = transform; + mFlinger->invalidateHwcGeometry(); + } - sp<GraphicBuffer> newFrontBuffer(getBuffer(buf)); - if (newFrontBuffer != NULL) { - if (!noActiveBuffer && activeBlending != needsBlending(newFrontBuffer)) { - // new buffer has different opacity than previous active buffer, need - // to recompute visible regions accordingly + const bool opacity(getOpacityForFormat(mActiveBuffer->format)); + if (opacity != mCurrentOpacity) { + mCurrentOpacity = opacity; recomputeVisibleRegions = true; } - // get the dirty region - // compute the posted region - const Region dirty(lcblk->getDirtyRegion(buf)); - mPostedDirtyRegion = dirty.intersect( newFrontBuffer->getBounds() ); + const GLenum target(mSurfaceTexture->getCurrentTextureTarget()); + glTexParameterx(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterx(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // update the layer size and release freeze-lock const Layer::State& front(drawingState()); + + // FIXME: mPostedDirtyRegion = dirty & bounds + mPostedDirtyRegion.set(front.w, front.h); + + sp<GraphicBuffer> newFrontBuffer(mActiveBuffer); if ((newFrontBuffer->getWidth() == front.requested_w && newFrontBuffer->getHeight() == front.requested_h) || isFixedSize()) @@ -685,35 +476,7 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions) // we now have the correct size, unfreeze the screen mFreezeLock.clear(); } - - // get the crop region - setBufferCrop( lcblk->getCrop(buf) ); - - // get the transformation - setBufferTransform( lcblk->getTransform(buf) ); - - } else { - // this should not happen unless we ran out of memory while - // allocating the buffer. we're hoping that things will get back - // to normal the next time the app tries to draw into this buffer. - // meanwhile, pretend the screen didn't update. - mPostedDirtyRegion.clear(); - } - - if (lcblk->getQueuedCount()) { - // signal an event if we have more buffers waiting - mFlinger->signalEvent(); } - - /* a buffer was posted, so we need to call reloadTexture(), which - * will update our internal data structures (eg: EGLImageKHR or - * texture names). we need to do this even if mPostedDirtyRegion is - * empty -- it's orthogonal to the fact that a new buffer was posted, - * for instance, a degenerate case could be that the user did an empty - * update but repainted the buffer with appropriate content (after a - * resize for instance). - */ - reloadTexture( mPostedDirtyRegion ); } void Layer::unlockPageFlip( @@ -746,329 +509,36 @@ void Layer::dump(String8& result, char* buffer, size_t SIZE) const { LayerBaseClient::dump(result, buffer, SIZE); - ClientRef::Access sharedClient(mUserClientRef); - SharedBufferServer* lcblk(sharedClient.get()); - uint32_t totalTime = 0; - if (lcblk) { - SharedBufferStack::Statistics stats = lcblk->getStats(); - totalTime= stats.totalTime; - result.append( lcblk->dump(" ") ); - } - - sp<const GraphicBuffer> buf0(getBuffer(0)); - sp<const GraphicBuffer> buf1(getBuffer(1)); - uint32_t w0=0, h0=0, s0=0; - uint32_t w1=0, h1=0, s1=0; + sp<const GraphicBuffer> buf0(mActiveBuffer); + uint32_t w0=0, h0=0, s0=0, f0=0; if (buf0 != 0) { w0 = buf0->getWidth(); h0 = buf0->getHeight(); s0 = buf0->getStride(); - } - if (buf1 != 0) { - w1 = buf1->getWidth(); - h1 = buf1->getHeight(); - s1 = buf1->getStride(); + f0 = buf0->format; } snprintf(buffer, SIZE, " " - "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u]," - " freezeLock=%p, dq-q-time=%u us\n", - mFormat, w0, h0, s0, w1, h1, s1, - getFreezeLock().get(), totalTime); + "format=%2d, activeBuffer=[%3ux%3u:%3u,%3u]," + " freezeLock=%p, queued-frames=%d\n", + mFormat, w0, h0, s0,f0, + getFreezeLock().get(), mQueuedFrames); result.append(buffer); -} - -// --------------------------------------------------------------------------- - -Layer::ClientRef::ClientRef() - : mControlBlock(0), mToken(-1) { -} - -Layer::ClientRef::~ClientRef() { -} - -int32_t Layer::ClientRef::getToken() const { - Mutex::Autolock _l(mLock); - return mToken; -} - -sp<UserClient> Layer::ClientRef::getClient() const { - Mutex::Autolock _l(mLock); - return mUserClient.promote(); -} - -status_t Layer::ClientRef::setToken(const sp<UserClient>& uc, - const sp<SharedBufferServer>& sharedClient, int32_t token) { - Mutex::Autolock _l(mLock); - - { // scope for strong mUserClient reference - sp<UserClient> userClient(mUserClient.promote()); - if (userClient != 0 && mControlBlock != 0) { - mControlBlock->setStatus(NO_INIT); - } - } - - mUserClient = uc; - mToken = token; - mControlBlock = sharedClient; - return NO_ERROR; -} - -sp<UserClient> Layer::ClientRef::getUserClientUnsafe() const { - return mUserClient.promote(); -} - -// this class gives us access to SharedBufferServer safely -// it makes sure the UserClient (and its associated shared memory) -// won't go away while we're accessing it. -Layer::ClientRef::Access::Access(const ClientRef& ref) - : mControlBlock(0) -{ - Mutex::Autolock _l(ref.mLock); - mUserClientStrongRef = ref.mUserClient.promote(); - if (mUserClientStrongRef != 0) - mControlBlock = ref.mControlBlock; -} - -Layer::ClientRef::Access::~Access() -{ -} - -// --------------------------------------------------------------------------- - -Layer::BufferManager::BufferManager(TextureManager& tm) - : mNumBuffers(NUM_BUFFERS), mTextureManager(tm), - mActiveBufferIndex(-1), mFailover(false) -{ -} - -Layer::BufferManager::~BufferManager() -{ -} - -status_t Layer::BufferManager::resize(size_t size, - const sp<SurfaceFlinger>& flinger, EGLDisplay dpy) -{ - Mutex::Autolock _l(mLock); - - if (size < mNumBuffers) { - // If there is an active texture, move it into slot 0 if needed - if (mActiveBufferIndex > 0) { - BufferData activeBufferData = mBufferData[mActiveBufferIndex]; - mBufferData[mActiveBufferIndex] = mBufferData[0]; - mBufferData[0] = activeBufferData; - mActiveBufferIndex = 0; - } - - // Free the buffers that are no longer needed. - for (size_t i = size; i < mNumBuffers; i++) { - mBufferData[i].buffer = 0; - - // Create a message to destroy the textures on SurfaceFlinger's GL - // thread. - class MessageDestroyTexture : public MessageBase { - Image mTexture; - EGLDisplay mDpy; - public: - MessageDestroyTexture(const Image& texture, EGLDisplay dpy) - : mTexture(texture), mDpy(dpy) { } - virtual bool handler() { - status_t err = Layer::BufferManager::destroyTexture( - &mTexture, mDpy); - LOGE_IF(err<0, "error destroying texture: %d (%s)", - mTexture.name, strerror(-err)); - return true; // XXX: err == 0; ???? - } - }; - - MessageDestroyTexture *msg = new MessageDestroyTexture( - mBufferData[i].texture, dpy); - - // Don't allow this texture to be cleaned up by - // BufferManager::destroy. - mBufferData[i].texture.name = -1U; - mBufferData[i].texture.image = EGL_NO_IMAGE_KHR; - - // Post the message to the SurfaceFlinger object. - flinger->postMessageAsync(msg); - } - } - - mNumBuffers = size; - return NO_ERROR; -} - -// only for debugging -sp<GraphicBuffer> Layer::BufferManager::getBuffer(size_t index) const { - return mBufferData[index].buffer; -} - -status_t Layer::BufferManager::setActiveBufferIndex(size_t index) { - BufferData const * const buffers = mBufferData; - Mutex::Autolock _l(mLock); - mActiveBuffer = buffers[index].buffer; - mActiveBufferIndex = index; - return NO_ERROR; -} - -size_t Layer::BufferManager::getActiveBufferIndex() const { - return mActiveBufferIndex; -} - -Texture Layer::BufferManager::getActiveTexture() const { - Texture res; - if (mFailover || mActiveBufferIndex<0) { - res = mFailoverTexture; - } else { - static_cast<Image&>(res) = mBufferData[mActiveBufferIndex].texture; - } - return res; -} - -sp<GraphicBuffer> Layer::BufferManager::getActiveBuffer() const { - return mActiveBuffer; -} - -bool Layer::BufferManager::hasActiveBuffer() const { - return mActiveBufferIndex >= 0; -} - -sp<GraphicBuffer> Layer::BufferManager::detachBuffer(size_t index) -{ - BufferData* const buffers = mBufferData; - sp<GraphicBuffer> buffer; - Mutex::Autolock _l(mLock); - buffer = buffers[index].buffer; - buffers[index].buffer = 0; - return buffer; -} - -status_t Layer::BufferManager::attachBuffer(size_t index, - const sp<GraphicBuffer>& buffer) -{ - BufferData* const buffers = mBufferData; - Mutex::Autolock _l(mLock); - buffers[index].buffer = buffer; - buffers[index].texture.dirty = true; - return NO_ERROR; -} -status_t Layer::BufferManager::destroy(EGLDisplay dpy) -{ - BufferData* const buffers = mBufferData; - size_t num; - { // scope for the lock - Mutex::Autolock _l(mLock); - num = mNumBuffers; - for (size_t i=0 ; i<num ; i++) { - buffers[i].buffer = 0; - } + if (mSurfaceTexture != 0) { + mSurfaceTexture->dump(result, " ", buffer, SIZE); } - for (size_t i=0 ; i<num ; i++) { - destroyTexture(&buffers[i].texture, dpy); - } - destroyTexture(&mFailoverTexture, dpy); - return NO_ERROR; } -status_t Layer::BufferManager::initEglImage(EGLDisplay dpy, - const sp<GraphicBuffer>& buffer) -{ - status_t err = NO_INIT; - ssize_t index = mActiveBufferIndex; - if (index >= 0) { - if (!mFailover) { - { - // Without that lock, there is a chance of race condition - // where while composing a specific index, requestBuf - // with the same index can be executed and touch the same data - // that is being used in initEglImage. - // (e.g. dirty flag in texture) - Mutex::Autolock _l(mLock); - Image& texture(mBufferData[index].texture); - err = mTextureManager.initEglImage(&texture, dpy, buffer); - } - // if EGLImage fails, we switch to regular texture mode, and we - // free all resources associated with using EGLImages. - if (err == NO_ERROR) { - mFailover = false; - destroyTexture(&mFailoverTexture, dpy); - } else { - mFailover = true; - const size_t num = mNumBuffers; - for (size_t i=0 ; i<num ; i++) { - destroyTexture(&mBufferData[i].texture, dpy); - } - } - } else { - // we failed once, don't try again - err = BAD_VALUE; - } - } - return err; -} - -status_t Layer::BufferManager::loadTexture( - const Region& dirty, const GGLSurface& t) -{ - return mTextureManager.loadTexture(&mFailoverTexture, dirty, t); -} - -status_t Layer::BufferManager::destroyTexture(Image* tex, EGLDisplay dpy) -{ - if (tex->name != -1U) { - glDeleteTextures(1, &tex->name); - tex->name = -1U; - } - if (tex->image != EGL_NO_IMAGE_KHR) { - eglDestroyImageKHR(dpy, tex->image); - tex->image = EGL_NO_IMAGE_KHR; - } - return NO_ERROR; -} - -// --------------------------------------------------------------------------- - -Layer::SurfaceLayer::SurfaceLayer(const sp<SurfaceFlinger>& flinger, - const sp<Layer>& owner) - : Surface(flinger, owner->getIdentity(), owner) -{ -} - -Layer::SurfaceLayer::~SurfaceLayer() -{ -} - -sp<GraphicBuffer> Layer::SurfaceLayer::requestBuffer(int index, - uint32_t w, uint32_t h, uint32_t format, uint32_t usage) -{ - sp<GraphicBuffer> buffer; - sp<Layer> owner(getOwner()); - if (owner != 0) { - /* - * requestBuffer() cannot be called from the main thread - * as it could cause a dead-lock, since it may have to wait - * on conditions updated my the main thread. - */ - buffer = owner->requestBuffer(index, w, h, format, usage); - } - return buffer; -} - -status_t Layer::SurfaceLayer::setBufferCount(int bufferCount) +uint32_t Layer::getEffectiveUsage(uint32_t usage) const { - status_t err = DEAD_OBJECT; - sp<Layer> owner(getOwner()); - if (owner != 0) { - /* - * setBufferCount() cannot be called from the main thread - * as it could cause a dead-lock, since it may have to wait - * on conditions updated my the main thread. - */ - err = owner->setBufferCount(bufferCount); + // TODO: should we do something special if mSecure is set? + if (mProtectedByApp) { + // need a hardware-protected path to external video sink + usage |= GraphicBuffer::USAGE_PROTECTED; } - return err; + return usage; } // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 278d64e..72e290c 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -20,9 +20,11 @@ #include <stdint.h> #include <sys/types.h> +#include <gui/SurfaceTexture.h> + +#include <pixelflinger/pixelflinger.h> #include <ui/GraphicBuffer.h> #include <ui/PixelFormat.h> -#include <pixelflinger/pixelflinger.h> #include <EGL/egl.h> #include <EGL/eglext.h> @@ -30,8 +32,8 @@ #include <GLES/glext.h> #include "LayerBase.h" +#include "SurfaceTextureLayer.h" #include "Transform.h" -#include "TextureManager.h" namespace android { @@ -40,7 +42,6 @@ namespace android { class FreezeLock; class Client; class GLExtensions; -class UserClient; // --------------------------------------------------------------------------- @@ -58,164 +59,59 @@ public: status_t setBuffers(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags=0); - // associate a UserClient to this Layer - status_t setToken(const sp<UserClient>& uc, SharedClient* sc, int32_t idx); - int32_t getToken() const; - sp<UserClient> getClient() const; - // Set this Layer's buffers size - void setBufferSize(uint32_t w, uint32_t h); bool isFixedSize() const; // LayerBase interface virtual void setGeometry(hwc_layer_t* hwcl); virtual void setPerFrameData(hwc_layer_t* hwcl); - virtual void drawForSreenShot() const; virtual void onDraw(const Region& clip) const; virtual uint32_t doTransaction(uint32_t transactionFlags); virtual void lockPageFlip(bool& recomputeVisibleRegions); virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion); - virtual bool needsBlending(const sp<GraphicBuffer>& buffer) const; - virtual bool needsBlending() const; + virtual bool isOpaque() const; virtual bool needsDithering() const { return mNeedsDithering; } - virtual bool needsFiltering() const; virtual bool isSecure() const { return mSecure; } virtual bool isProtected() const; - virtual sp<Surface> createSurface() const; virtual void onRemoved(); // only for debugging - inline sp<GraphicBuffer> getBuffer(int i) const { - return mBufferManager.getBuffer(i); } - // only for debugging - inline const sp<FreezeLock>& getFreezeLock() const { - return mFreezeLock; } + inline const sp<FreezeLock>& getFreezeLock() const { return mFreezeLock; } protected: virtual void destroy() const; + virtual void onFirstRef(); virtual void dump(String8& result, char* scratch, size_t size) const; private: - void reloadTexture(const Region& dirty); + friend class SurfaceTextureLayer; + void onFrameQueued(); + virtual sp<ISurface> createSurface(); uint32_t getEffectiveUsage(uint32_t usage) const; - sp<GraphicBuffer> requestBuffer(int bufferIdx, - uint32_t w, uint32_t h, uint32_t format, uint32_t usage); - status_t setBufferCount(int bufferCount); - - // ----------------------------------------------------------------------- - - class SurfaceLayer : public LayerBaseClient::Surface { - public: - SurfaceLayer(const sp<SurfaceFlinger>& flinger, const sp<Layer>& owner); - ~SurfaceLayer(); - private: - virtual sp<GraphicBuffer> requestBuffer(int bufferIdx, - uint32_t w, uint32_t h, uint32_t format, uint32_t usage); - virtual status_t setBufferCount(int bufferCount); - sp<Layer> getOwner() const { - return static_cast<Layer*>(Surface::getOwner().get()); - } - }; - friend class SurfaceLayer; + void setFixedSize(bool fixedSize); + bool isCropped() const; + static bool getOpacityForFormat(uint32_t format); // ----------------------------------------------------------------------- - class ClientRef { - ClientRef(const ClientRef& rhs); - ClientRef& operator = (const ClientRef& rhs); - mutable Mutex mLock; - // binder thread, page-flip thread - sp<SharedBufferServer> mControlBlock; - wp<UserClient> mUserClient; - int32_t mToken; - public: - ClientRef(); - ~ClientRef(); - int32_t getToken() const; - sp<UserClient> getClient() const; - status_t setToken(const sp<UserClient>& uc, - const sp<SharedBufferServer>& sharedClient, int32_t token); - sp<UserClient> getUserClientUnsafe() const; - class Access { - Access(const Access& rhs); - Access& operator = (const Access& rhs); - sp<UserClient> mUserClientStrongRef; - sp<SharedBufferServer> mControlBlock; - public: - Access(const ClientRef& ref); - ~Access(); - inline SharedBufferServer* get() const { return mControlBlock.get(); } - }; - friend class Access; - }; - - // ----------------------------------------------------------------------- - - class BufferManager { - static const size_t NUM_BUFFERS = 2; - struct BufferData { - sp<GraphicBuffer> buffer; - Image texture; - }; - // this lock protect mBufferData[].buffer but since there - // is very little contention, we have only one like for - // the whole array, we also use it to protect mNumBuffers. - mutable Mutex mLock; - BufferData mBufferData[SharedBufferStack::NUM_BUFFER_MAX]; - size_t mNumBuffers; - Texture mFailoverTexture; - TextureManager& mTextureManager; - ssize_t mActiveBufferIndex; - sp<GraphicBuffer> mActiveBuffer; - bool mFailover; - static status_t destroyTexture(Image* tex, EGLDisplay dpy); - - public: - static size_t getDefaultBufferCount() { return NUM_BUFFERS; } - BufferManager(TextureManager& tm); - ~BufferManager(); - - // detach/attach buffer from/to given index - sp<GraphicBuffer> detachBuffer(size_t index); - status_t attachBuffer(size_t index, const sp<GraphicBuffer>& buffer); - // resize the number of active buffers - status_t resize(size_t size, const sp<SurfaceFlinger>& flinger, - EGLDisplay dpy); - - // ---------------------------------------------- - // must be called from GL thread - - // set/get active buffer index - status_t setActiveBufferIndex(size_t index); - size_t getActiveBufferIndex() const; - // return the active buffer - sp<GraphicBuffer> getActiveBuffer() const; - // return wether we have an active buffer - bool hasActiveBuffer() const; - // return the active texture (or fail-over) - Texture getActiveTexture() const; - // frees resources associated with all buffers - status_t destroy(EGLDisplay dpy); - // load bitmap data into the active buffer - status_t loadTexture(const Region& dirty, const GGLSurface& t); - // make active buffer an EGLImage if needed - status_t initEglImage(EGLDisplay dpy, - const sp<GraphicBuffer>& buffer); - - // ---------------------------------------------- - // only for debugging - sp<GraphicBuffer> getBuffer(size_t index) const; - }; - - // ----------------------------------------------------------------------- + // constants + sp<SurfaceTextureLayer> mSurfaceTexture; + GLuint mTextureName; // thread-safe - ClientRef mUserClientRef; + volatile int32_t mQueuedFrames; + + // main thread + sp<GraphicBuffer> mActiveBuffer; + GLfloat mTextureMatrix[16]; + Rect mCurrentCrop; + uint32_t mCurrentTransform; + bool mCurrentOpacity; // constants PixelFormat mFormat; const GLExtensions& mGLExtensions; - bool mNeedsBlending; + bool mOpaqueLayer; bool mNeedsDithering; // page-flip thread (currently main thread) @@ -226,18 +122,8 @@ private: // page-flip thread and transaction thread (currently main thread) sp<FreezeLock> mFreezeLock; - // see threading usage in declaration - TextureManager mTextureManager; - BufferManager mBufferManager; - // binder thread, transaction thread mutable Mutex mLock; - uint32_t mWidth; - uint32_t mHeight; - uint32_t mReqWidth; - uint32_t mReqHeight; - uint32_t mReqFormat; - bool mNeedsScaling; bool mFixedSize; }; diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp index 022f251..bcd8c83 100644 --- a/services/surfaceflinger/LayerBase.cpp +++ b/services/surfaceflinger/LayerBase.cpp @@ -32,8 +32,6 @@ #include "LayerBase.h" #include "SurfaceFlinger.h" #include "DisplayHardware/DisplayHardware.h" -#include "TextureManager.h" - namespace android { @@ -44,7 +42,7 @@ int32_t LayerBase::sSequence = 1; LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display) : dpy(display), contentDirty(false), sequence(uint32_t(android_atomic_inc(&sSequence))), - mFlinger(flinger), + mFlinger(flinger), mFiltering(false), mNeedsFiltering(false), mOrientation(0), mLeft(0), mTop(0), @@ -54,8 +52,6 @@ LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display) { const DisplayHardware& hw(flinger->graphicPlane(0).displayHardware()); mFlags = hw.getFlags(); - mBufferCrop.makeInvalid(); - mBufferTransform = 0; } LayerBase::~LayerBase() @@ -310,6 +306,16 @@ void LayerBase::setPerFrameData(hwc_layer_t* hwcl) { hwcl->handle = NULL; } +void LayerBase::setFiltering(bool filtering) +{ + mFiltering = filtering; +} + +bool LayerBase::getFiltering() const +{ + return mFiltering; +} + void LayerBase::draw(const Region& clip) const { // reset GL state @@ -318,10 +324,12 @@ void LayerBase::draw(const Region& clip) const onDraw(clip); } -void LayerBase::drawForSreenShot() const +void LayerBase::drawForSreenShot() { const DisplayHardware& hw(graphicPlane(0).displayHardware()); + setFiltering(true); onDraw( Region(hw.bounds()) ); + setFiltering(false); } void LayerBase::clearWithOpenGL(const Region& clip, GLclampf red, @@ -332,8 +340,12 @@ void LayerBase::clearWithOpenGL(const Region& clip, GLclampf red, const uint32_t fbHeight = hw.getHeight(); glColor4f(red,green,blue,alpha); - TextureManager::deactivateTextures(); - +#if defined(GL_OES_EGL_image_external) + if (GLExtensions::getInstance().haveTextureExternal()) { + glDisable(GL_TEXTURE_EXTERNAL_OES); + } +#endif + glDisable(GL_TEXTURE_2D); glDisable(GL_BLEND); glDisable(GL_DITHER); @@ -354,24 +366,11 @@ void LayerBase::clearWithOpenGL(const Region& clip) const clearWithOpenGL(clip,0,0,0,0); } -template <typename T> -static inline -void swap(T& a, T& b) { - T t(a); - a = b; - b = t; -} - -void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const +void LayerBase::drawWithOpenGL(const Region& clip) const { const DisplayHardware& hw(graphicPlane(0).displayHardware()); const uint32_t fbHeight = hw.getHeight(); const State& s(drawingState()); - - // bind our texture - TextureManager::activateTexture(texture, needsFiltering()); - uint32_t width = texture.width; - uint32_t height = texture.height; GLenum src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA; if (UNLIKELY(s.alpha < 0xFF)) { @@ -387,7 +386,7 @@ void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const } else { glColor4f(1, 1, 1, 1); glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - if (needsBlending()) { + if (!isOpaque()) { glEnable(GL_BLEND); glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA); } else { @@ -395,86 +394,20 @@ void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const } } - /* - * compute texture coordinates - * here, we handle NPOT, cropping and buffer transformations - */ - - GLfloat cl, ct, cr, cb; - if (!mBufferCrop.isEmpty()) { - // source is cropped - const GLfloat us = (texture.NPOTAdjust ? texture.wScale : 1.0f) / width; - const GLfloat vs = (texture.NPOTAdjust ? texture.hScale : 1.0f) / height; - cl = mBufferCrop.left * us; - ct = mBufferCrop.top * vs; - cr = mBufferCrop.right * us; - cb = mBufferCrop.bottom * vs; - } else { - cl = 0; - ct = 0; - cr = (texture.NPOTAdjust ? texture.wScale : 1.0f); - cb = (texture.NPOTAdjust ? texture.hScale : 1.0f); - } - - /* - * For the buffer transformation, we apply the rotation last. - * Since we're transforming the texture-coordinates, we need - * to apply the inverse of the buffer transformation: - * inverse( FLIP_V -> FLIP_H -> ROT_90 ) - * <=> inverse( ROT_90 * FLIP_H * FLIP_V ) - * = inverse(FLIP_V) * inverse(FLIP_H) * inverse(ROT_90) - * = FLIP_V * FLIP_H * ROT_270 - * <=> ROT_270 -> FLIP_H -> FLIP_V - * - * The rotation is performed first, in the texture coordinate space. - * - */ - struct TexCoords { GLfloat u; GLfloat v; }; - enum { - // name of the corners in the texture map - LB = 0, // left-bottom - LT = 1, // left-top - RT = 2, // right-top - RB = 3 // right-bottom - }; - - // vertices in screen space - int vLT = LB; - int vLB = LT; - int vRB = RT; - int vRT = RB; - - // the texture's source is rotated - uint32_t transform = mBufferTransform; - if (transform & HAL_TRANSFORM_ROT_90) { - vLT = RB; - vLB = LB; - vRB = LT; - vRT = RT; - } - if (transform & HAL_TRANSFORM_FLIP_V) { - swap(vLT, vLB); - swap(vRT, vRB); - } - if (transform & HAL_TRANSFORM_FLIP_H) { - swap(vLT, vRT); - swap(vLB, vRB); - } - TexCoords texCoords[4]; - texCoords[vLT].u = cl; - texCoords[vLT].v = ct; - texCoords[vLB].u = cl; - texCoords[vLB].v = cb; - texCoords[vRB].u = cr; - texCoords[vRB].v = cb; - texCoords[vRT].u = cr; - texCoords[vRT].v = ct; + texCoords[0].u = 0; + texCoords[0].v = 1; + texCoords[1].u = 0; + texCoords[1].v = 0; + texCoords[2].u = 1; + texCoords[2].v = 0; + texCoords[3].u = 1; + texCoords[3].v = 1; if (needsDithering()) { glEnable(GL_DITHER); @@ -497,20 +430,6 @@ void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const glDisableClientState(GL_TEXTURE_COORD_ARRAY); } -void LayerBase::setBufferCrop(const Rect& crop) { - if (mBufferCrop != crop) { - mBufferCrop = crop; - mFlinger->invalidateHwcGeometry(); - } -} - -void LayerBase::setBufferTransform(uint32_t transform) { - if (mBufferTransform != transform) { - mBufferTransform = transform; - mFlinger->invalidateHwcGeometry(); - } -} - void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const { const Layer::State& s(drawingState()); @@ -518,10 +437,10 @@ void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const "+ %s %p\n" " " "z=%9d, pos=(%4d,%4d), size=(%4d,%4d), " - "needsBlending=%1d, needsDithering=%1d, invalidate=%1d, " + "isOpaque=%1d, needsDithering=%1d, invalidate=%1d, " "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n", getTypeId(), this, s.z, tx(), ty(), s.w, s.h, - needsBlending(), needsDithering(), contentDirty, + isOpaque(), needsDithering(), contentDirty, s.alpha, s.flags, s.transform[0][0], s.transform[0][1], s.transform[1][0], s.transform[1][1]); @@ -555,9 +474,22 @@ LayerBaseClient::~LayerBaseClient() } } -sp<LayerBaseClient::Surface> LayerBaseClient::getSurface() +sp<ISurface> LayerBaseClient::createSurface() +{ + class BSurface : public BnSurface, public LayerCleaner { + virtual sp<ISurfaceTexture> getSurfaceTexture() const { return 0; } + public: + BSurface(const sp<SurfaceFlinger>& flinger, + const sp<LayerBaseClient>& layer) + : LayerCleaner(flinger, layer) { } + }; + sp<ISurface> sur(new BSurface(mFlinger, this)); + return sur; +} + +sp<ISurface> LayerBaseClient::getSurface() { - sp<Surface> s; + sp<ISurface> s; Mutex::Autolock _l(mLock); LOG_ALWAYS_FATAL_IF(mHasSurface, @@ -573,12 +505,6 @@ wp<IBinder> LayerBaseClient::getSurfaceBinder() const { return mClientSurfaceBinder; } -sp<LayerBaseClient::Surface> LayerBaseClient::createSurface() const -{ - return new Surface(mFlinger, mIdentity, - const_cast<LayerBaseClient *>(this)); -} - void LayerBaseClient::dump(String8& result, char* buffer, size_t SIZE) const { LayerBase::dump(result, buffer, SIZE); @@ -601,44 +527,14 @@ void LayerBaseClient::shortDump(String8& result, char* scratch, size_t size) con // --------------------------------------------------------------------------- -LayerBaseClient::Surface::Surface( - const sp<SurfaceFlinger>& flinger, - int identity, - const sp<LayerBaseClient>& owner) - : mFlinger(flinger), mIdentity(identity), mOwner(owner) -{ +LayerBaseClient::LayerCleaner::LayerCleaner(const sp<SurfaceFlinger>& flinger, + const sp<LayerBaseClient>& layer) + : mFlinger(flinger), mLayer(layer) { } -LayerBaseClient::Surface::~Surface() -{ - /* - * This is a good place to clean-up all client resources - */ - +LayerBaseClient::LayerCleaner::~LayerCleaner() { // destroy client resources - mFlinger->destroySurface(mOwner); -} - -sp<LayerBaseClient> LayerBaseClient::Surface::getOwner() const { - sp<LayerBaseClient> owner(mOwner.promote()); - return owner; -} - -status_t LayerBaseClient::Surface::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - return BnSurface::onTransact(code, data, reply, flags); -} - -sp<GraphicBuffer> LayerBaseClient::Surface::requestBuffer(int bufferIdx, - uint32_t w, uint32_t h, uint32_t format, uint32_t usage) -{ - return NULL; -} - -status_t LayerBaseClient::Surface::setBufferCount(int bufferCount) -{ - return INVALID_OPERATION; + mFlinger->destroySurface(mLayer); } // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h index 6c49a19..faf71dd 100644 --- a/services/surfaceflinger/LayerBase.h +++ b/services/surfaceflinger/LayerBase.h @@ -29,7 +29,6 @@ #include <ui/Region.h> #include <surfaceflinger/ISurfaceComposerClient.h> -#include <private/surfaceflinger/SharedBufferStack.h> #include <private/surfaceflinger/LayerState.h> #include <pixelflinger/pixelflinger.h> @@ -43,13 +42,12 @@ namespace android { // --------------------------------------------------------------------------- -class DisplayHardware; class Client; +class DisplayHardware; class GraphicBuffer; class GraphicPlane; class LayerBaseClient; class SurfaceFlinger; -class Texture; // --------------------------------------------------------------------------- @@ -121,7 +119,7 @@ public: * to perform the actual drawing. */ virtual void draw(const Region& clip) const; - virtual void drawForSreenShot() const; + virtual void drawForSreenShot(); /** * onDraw - draws the surface. @@ -174,9 +172,9 @@ public: virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion); /** - * needsBlending - true if this surface needs blending + * isOpaque - true if this surface is opaque */ - virtual bool needsBlending() const { return false; } + virtual bool isOpaque() const { return true; } /** * needsDithering - true if this surface needs dithering @@ -184,11 +182,9 @@ public: virtual bool needsDithering() const { return false; } /** - * needsLinearFiltering - true if this surface needs filtering + * needsLinearFiltering - true if this surface's state requires filtering */ - virtual bool needsFiltering() const { - return (!(mFlags & DisplayHardware::SLOW_CONFIG)) && mNeedsFiltering; - } + virtual bool needsFiltering() const { return mNeedsFiltering; } /** * isSecure - true if this surface is secure, that is if it prevents @@ -231,21 +227,25 @@ protected: void clearWithOpenGL(const Region& clip, GLclampf r, GLclampf g, GLclampf b, GLclampf alpha) const; void clearWithOpenGL(const Region& clip) const; - void drawWithOpenGL(const Region& clip, const Texture& texture) const; - - // these must be called from the post/drawing thread - void setBufferCrop(const Rect& crop); - void setBufferTransform(uint32_t transform); + void drawWithOpenGL(const Region& clip) const; + + void setFiltering(bool filtering); + bool getFiltering() const; sp<SurfaceFlinger> mFlinger; uint32_t mFlags; - // post/drawing thread - Rect mBufferCrop; - uint32_t mBufferTransform; +private: + // accessed only in the main thread + // Whether filtering is forced on or not + bool mFiltering; // cached during validateVisibility() + // Whether filtering is needed b/c of the drawingstate bool mNeedsFiltering; + +protected: + // cached during validateVisibility() int32_t mOrientation; GLfloat mVertices[4][2]; Rect mTransformedBounds; @@ -281,52 +281,38 @@ private: class LayerBaseClient : public LayerBase { public: - class Surface; - LayerBaseClient(SurfaceFlinger* flinger, DisplayID display, const sp<Client>& client); - virtual ~LayerBaseClient(); - sp<Surface> getSurface(); + virtual ~LayerBaseClient(); + + sp<ISurface> getSurface(); wp<IBinder> getSurfaceBinder() const; - virtual sp<Surface> createSurface() const; + virtual sp<LayerBaseClient> getLayerBaseClient() const { return const_cast<LayerBaseClient*>(this); } + virtual const char* getTypeId() const { return "LayerBaseClient"; } uint32_t getIdentity() const { return mIdentity; } - class Surface : public BnSurface { - public: - int32_t getIdentity() const { return mIdentity; } - - protected: - Surface(const sp<SurfaceFlinger>& flinger, int identity, - const sp<LayerBaseClient>& owner); - virtual ~Surface(); - virtual status_t onTransact(uint32_t code, const Parcel& data, - Parcel* reply, uint32_t flags); - sp<LayerBaseClient> getOwner() const; - - private: - virtual sp<GraphicBuffer> requestBuffer(int bufferIdx, - uint32_t w, uint32_t h, uint32_t format, uint32_t usage); - virtual status_t setBufferCount(int bufferCount); - - protected: - friend class LayerBaseClient; - sp<SurfaceFlinger> mFlinger; - int32_t mIdentity; - wp<LayerBaseClient> mOwner; - }; - - friend class Surface; - protected: virtual void dump(String8& result, char* scratch, size_t size) const; virtual void shortDump(String8& result, char* scratch, size_t size) const; + class LayerCleaner { + sp<SurfaceFlinger> mFlinger; + wp<LayerBaseClient> mLayer; + protected: + ~LayerCleaner(); + public: + LayerCleaner(const sp<SurfaceFlinger>& flinger, + const sp<LayerBaseClient>& layer); + }; + private: + virtual sp<ISurface> createSurface(); + mutable Mutex mLock; mutable bool mHasSurface; wp<IBinder> mClientSurfaceBinder; diff --git a/services/surfaceflinger/LayerDim.cpp b/services/surfaceflinger/LayerDim.cpp index f79166d..654817d 100644 --- a/services/surfaceflinger/LayerDim.cpp +++ b/services/surfaceflinger/LayerDim.cpp @@ -65,8 +65,6 @@ void LayerDim::onDraw(const Region& clip) const glDisable(GL_TEXTURE_EXTERNAL_OES); } #endif - glDisable(GL_TEXTURE_2D); - glVertexPointer(2, GL_FLOAT, 0, mVertices); while (it != end) { diff --git a/services/surfaceflinger/LayerDim.h b/services/surfaceflinger/LayerDim.h index 75f9a89..8770e6d 100644 --- a/services/surfaceflinger/LayerDim.h +++ b/services/surfaceflinger/LayerDim.h @@ -37,7 +37,7 @@ public: virtual ~LayerDim(); virtual void onDraw(const Region& clip) const; - virtual bool needsBlending() const { return true; } + virtual bool isOpaque() const { return false; } virtual bool isSecure() const { return false; } virtual bool isProtectedByApp() const { return false; } virtual bool isProtectedByDRM() const { return false; } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index b7a51a4..97edfee 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -53,6 +53,8 @@ #include "DisplayHardware/DisplayHardware.h" #include "DisplayHardware/HWComposer.h" +#include <private/surfaceflinger/SharedBufferStack.h> + /* ideally AID_GRAPHICS would be in a semi-public header * or there would be a way to map a user/group name to its id */ @@ -133,17 +135,6 @@ sp<ISurfaceComposerClient> SurfaceFlinger::createConnection() return bclient; } -sp<ISurfaceComposerClient> SurfaceFlinger::createClientConnection() -{ - sp<ISurfaceComposerClient> bclient; - sp<UserClient> client(new UserClient(this)); - status_t err = client->initCheck(); - if (err == NO_ERROR) { - bclient = client; - } - return bclient; -} - sp<IGraphicBufferAlloc> SurfaceFlinger::createGraphicBufferAlloc() { sp<GraphicBufferAlloc> gba(new GraphicBufferAlloc()); @@ -322,11 +313,6 @@ void SurfaceFlinger::signalEvent() { mEventQueue.invalidate(); } -void SurfaceFlinger::signal() const { - // this is the IPC call - const_cast<SurfaceFlinger*>(this)->signalEvent(); -} - bool SurfaceFlinger::authenticateSurface(const sp<ISurface>& surface) const { Mutex::Autolock _l(mStateLock); sp<IBinder> surfBinder(surface->asBinder()); @@ -658,7 +644,7 @@ void SurfaceFlinger::computeVisibleRegions( // handle hidden surfaces by setting the visible region to empty if (LIKELY(!(s.flags & ISurfaceComposer::eLayerHidden) && s.alpha)) { - const bool translucent = layer->needsBlending(); + const bool translucent = !layer->isOpaque(); const Rect bounds(layer->visibleBounds()); visibleRegion.set(bounds); visibleRegion.andSelf(screenRegion); @@ -921,7 +907,7 @@ void SurfaceFlinger::composeSurfaces(const Region& dirty) for (size_t i=0 ; i<count ; i++) { if (cur[i].hints & HWC_HINT_CLEAR_FB) { const sp<LayerBase>& layer(layers[i]); - if (!(layer->needsBlending())) { + if (layer->isOpaque()) { transparent.orSelf(layer->visibleRegionScreen); } } @@ -979,8 +965,6 @@ void SurfaceFlinger::debugFlashRegions() composeSurfaces(repaint); } - TextureManager::deactivateTextures(); - glDisable(GL_BLEND); glDisable(GL_DITHER); glDisable(GL_SCISSOR_TEST); @@ -1070,6 +1054,7 @@ void SurfaceFlinger::drawWormhole() const glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisable(GL_TEXTURE_2D); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); } @@ -1269,7 +1254,7 @@ sp<ISurface> SurfaceFlinger::createSurface( uint32_t flags) { sp<LayerBaseClient> layer; - sp<LayerBaseClient::Surface> surfaceHandle; + sp<ISurface> surfaceHandle; if (int32_t(w|h) < 0) { LOGE("createSurface() failed, w or h is negative (w=%d, h=%d)", @@ -1300,13 +1285,13 @@ sp<ISurface> SurfaceFlinger::createSurface( surfaceHandle = layer->getSurface(); if (surfaceHandle != 0) { params->token = token; - params->identity = surfaceHandle->getIdentity(); + params->identity = layer->getIdentity(); params->width = w; params->height = h; params->format = format; if (normalLayer != 0) { Mutex::Autolock _l(mStateLock); - mLayerMap.add(surfaceHandle->asBinder(), normalLayer); + mLayerMap.add(layer->getSurfaceBinder(), normalLayer); } } @@ -1782,7 +1767,6 @@ status_t SurfaceFlinger::electronBeamOffAnimationImplLocked() GLfloat vtx[8]; const GLfloat texCoords[4][2] = { {0,v}, {0,0}, {u,0}, {u,v} }; - glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, tname); glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -1900,6 +1884,7 @@ status_t SurfaceFlinger::electronBeamOffAnimationImplLocked() glEnable(GL_SCISSOR_TEST); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDeleteTextures(1, &tname); + glDisable(GL_TEXTURE_2D); return NO_ERROR; } @@ -1930,7 +1915,6 @@ status_t SurfaceFlinger::electronBeamOnAnimationImplLocked() GLfloat vtx[8]; const GLfloat texCoords[4][2] = { {0,v}, {0,0}, {u,0}, {u,v} }; - glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, tname); glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -2044,6 +2028,7 @@ status_t SurfaceFlinger::electronBeamOnAnimationImplLocked() glEnable(GL_SCISSOR_TEST); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDeleteTextures(1, &tname); + glDisable(GL_TEXTURE_2D); return NO_ERROR; } @@ -2408,133 +2393,78 @@ sp<LayerBaseClient> Client::getLayerUser(int32_t i) const return lbc; } -sp<IMemoryHeap> Client::getControlBlock() const { - return 0; -} -ssize_t Client::getTokenForSurface(const sp<ISurface>& sur) const { - return -1; + +status_t Client::onTransact( + uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) +{ + // these must be checked + IPCThreadState* ipc = IPCThreadState::self(); + const int pid = ipc->getCallingPid(); + const int uid = ipc->getCallingUid(); + const int self_pid = getpid(); + if (UNLIKELY(pid != self_pid && uid != AID_GRAPHICS && uid != 0)) { + // we're called from a different process, do the real check + if (!checkCallingPermission( + String16("android.permission.ACCESS_SURFACE_FLINGER"))) + { + LOGE("Permission Denial: " + "can't openGlobalTransaction pid=%d, uid=%d", pid, uid); + return PERMISSION_DENIED; + } + } + return BnSurfaceComposerClient::onTransact(code, data, reply, flags); } + + sp<ISurface> Client::createSurface( ISurfaceComposerClient::surface_data_t* params, const String8& name, DisplayID display, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) { - return mFlinger->createSurface(params, name, this, - display, w, h, format, flags); -} -status_t Client::destroySurface(SurfaceID sid) { - return mFlinger->removeSurface(this, sid); -} -status_t Client::setState(int32_t count, const layer_state_t* states) { - return mFlinger->setClientState(this, count, states); -} - -// --------------------------------------------------------------------------- - -UserClient::UserClient(const sp<SurfaceFlinger>& flinger) - : ctrlblk(0), mBitmap(0), mFlinger(flinger) -{ - const int pgsize = getpagesize(); - const int cblksize = ((sizeof(SharedClient)+(pgsize-1))&~(pgsize-1)); - - mCblkHeap = new MemoryHeapBase(cblksize, 0, - "SurfaceFlinger Client control-block"); - - ctrlblk = static_cast<SharedClient *>(mCblkHeap->getBase()); - if (ctrlblk) { // construct the shared structure in-place. - new(ctrlblk) SharedClient; - } -} - -UserClient::~UserClient() -{ - if (ctrlblk) { - ctrlblk->~SharedClient(); // destroy our shared-structure. - } - /* - * When a UserClient dies, it's unclear what to do exactly. - * We could go ahead and destroy all surfaces linked to that client - * however, it wouldn't be fair to the main Client - * (usually the the window-manager), which might want to re-target - * the layer to another UserClient. - * I think the best is to do nothing, or not much; in most cases the - * WM itself will go ahead and clean things up when it detects a client of - * his has died. - * The remaining question is what to display? currently we keep - * just keep the current buffer. + * createSurface must be called from the GL thread so that it can + * have access to the GL context. */ -} -status_t UserClient::initCheck() const { - return ctrlblk == 0 ? NO_INIT : NO_ERROR; -} - -void UserClient::detachLayer(const Layer* layer) -{ - int32_t name = layer->getToken(); - if (name >= 0) { - int32_t mask = 1LU<<name; - if ((android_atomic_and(~mask, &mBitmap) & mask) == 0) { - LOGW("token %d wasn't marked as used %08x", name, int(mBitmap)); + class MessageCreateSurface : public MessageBase { + sp<ISurface> result; + SurfaceFlinger* flinger; + ISurfaceComposerClient::surface_data_t* params; + Client* client; + const String8& name; + DisplayID display; + uint32_t w, h; + PixelFormat format; + uint32_t flags; + public: + MessageCreateSurface(SurfaceFlinger* flinger, + ISurfaceComposerClient::surface_data_t* params, + const String8& name, Client* client, + DisplayID display, uint32_t w, uint32_t h, PixelFormat format, + uint32_t flags) + : flinger(flinger), params(params), client(client), name(name), + display(display), w(w), h(h), format(format), flags(flags) + { } - } -} - -sp<IMemoryHeap> UserClient::getControlBlock() const { - return mCblkHeap; -} - -ssize_t UserClient::getTokenForSurface(const sp<ISurface>& sur) const -{ - int32_t name = NAME_NOT_FOUND; - sp<Layer> layer(mFlinger->getLayer(sur)); - if (layer == 0) { - return name; - } - - // if this layer already has a token, just return it - name = layer->getToken(); - if ((name >= 0) && (layer->getClient() == this)) { - return name; - } - - name = 0; - do { - int32_t mask = 1LU<<name; - if ((android_atomic_or(mask, &mBitmap) & mask) == 0) { - // we found and locked that name - status_t err = layer->setToken( - const_cast<UserClient*>(this), ctrlblk, name); - if (err != NO_ERROR) { - // free the name - android_atomic_and(~mask, &mBitmap); - name = err; - } - break; + sp<ISurface> getResult() const { return result; } + virtual bool handler() { + result = flinger->createSurface(params, name, client, + display, w, h, format, flags); + return true; } - if (++name >= int32_t(SharedBufferStack::NUM_LAYERS_MAX)) - name = NO_MEMORY; - } while(name >= 0); - - //LOGD("getTokenForSurface(%p) => %d (client=%p, bitmap=%08lx)", - // sur->asBinder().get(), name, this, mBitmap); - return name; -} + }; -sp<ISurface> UserClient::createSurface( - ISurfaceComposerClient::surface_data_t* params, - const String8& name, - DisplayID display, uint32_t w, uint32_t h, PixelFormat format, - uint32_t flags) { - return 0; + sp<MessageBase> msg = new MessageCreateSurface(mFlinger.get(), + params, name, this, display, w, h, format, flags); + mFlinger->postMessageSync(msg); + return static_cast<MessageCreateSurface*>( msg.get() )->getResult(); } -status_t UserClient::destroySurface(SurfaceID sid) { - return INVALID_OPERATION; +status_t Client::destroySurface(SurfaceID sid) { + return mFlinger->removeSurface(this, sid); } -status_t UserClient::setState(int32_t count, const layer_state_t* states) { - return INVALID_OPERATION; +status_t Client::setState(int32_t count, const layer_state_t* states) { + return mFlinger->setClientState(this, count, states); } // --------------------------------------------------------------------------- @@ -2547,11 +2477,11 @@ sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h PixelFormat format, uint32_t usage) { sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage)); status_t err = graphicBuffer->initCheck(); - if (err != 0) { - LOGE("createGraphicBuffer: init check failed: %d", err); - return 0; - } else if (graphicBuffer->handle == 0) { - LOGE("createGraphicBuffer: unable to create GraphicBuffer"); + if (err != 0 || graphicBuffer->handle == 0) { + GraphicBuffer::dumpAllocationsToSystemLog(); + LOGE("GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d) " + "failed (%s), handle=%p", + w, h, strerror(-err), graphicBuffer->handle); return 0; } return graphicBuffer; diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 992861a..af1ef04 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -50,6 +50,7 @@ class DisplayHardware; class FreezeLock; class Layer; class LayerDim; +struct surface_flinger_cblk_t; #define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) #define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) @@ -72,14 +73,14 @@ public: private: // ISurfaceComposerClient interface - virtual sp<IMemoryHeap> getControlBlock() const; - virtual ssize_t getTokenForSurface(const sp<ISurface>& sur) const; virtual sp<ISurface> createSurface( surface_data_t* params, const String8& name, DisplayID display, uint32_t w, uint32_t h,PixelFormat format, uint32_t flags); virtual status_t destroySurface(SurfaceID surfaceId); virtual status_t setState(int32_t count, const layer_state_t* states); + virtual status_t onTransact( + uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); // constant sp<SurfaceFlinger> mFlinger; @@ -92,40 +93,6 @@ private: mutable Mutex mLock; }; -class UserClient : public BnSurfaceComposerClient -{ -public: - // pointer to this client's control block - SharedClient* ctrlblk; - -public: - UserClient(const sp<SurfaceFlinger>& flinger); - ~UserClient(); - - status_t initCheck() const; - - // protected by SurfaceFlinger::mStateLock - void detachLayer(const Layer* layer); - -private: - - // ISurfaceComposerClient interface - virtual sp<IMemoryHeap> getControlBlock() const; - virtual ssize_t getTokenForSurface(const sp<ISurface>& sur) const; - virtual sp<ISurface> createSurface( - surface_data_t* params, const String8& name, - DisplayID display, uint32_t w, uint32_t h,PixelFormat format, - uint32_t flags); - virtual status_t destroySurface(SurfaceID surfaceId); - virtual status_t setState(int32_t count, const layer_state_t* states); - - // atomic-ops - mutable volatile int32_t mBitmap; - - sp<IMemoryHeap> mCblkHeap; - sp<SurfaceFlinger> mFlinger; -}; - class GraphicBufferAlloc : public BnGraphicBufferAlloc { public: @@ -199,7 +166,6 @@ public: // ISurfaceComposer interface virtual sp<ISurfaceComposerClient> createConnection(); - virtual sp<ISurfaceComposerClient> createClientConnection(); virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc(); virtual sp<IMemoryHeap> getCblk() const; virtual void bootFinished(); @@ -208,7 +174,6 @@ public: virtual status_t freezeDisplay(DisplayID dpy, uint32_t flags); virtual status_t unfreezeDisplay(DisplayID dpy, uint32_t flags); virtual int setOrientation(DisplayID dpy, int orientation, uint32_t flags); - virtual void signal() const; virtual bool authenticateSurface(const sp<ISurface>& surface) const; virtual status_t captureScreen(DisplayID dpy, @@ -235,7 +200,6 @@ private: friend class Client; friend class LayerBase; friend class LayerBaseClient; - friend class LayerBaseClient::Surface; friend class Layer; friend class LayerDim; diff --git a/services/surfaceflinger/SurfaceTextureLayer.cpp b/services/surfaceflinger/SurfaceTextureLayer.cpp new file mode 100644 index 0000000..60fa965 --- /dev/null +++ b/services/surfaceflinger/SurfaceTextureLayer.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2011 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 "Layer.h" +#include "SurfaceTextureLayer.h" + +namespace android { +// --------------------------------------------------------------------------- + + +SurfaceTextureLayer::SurfaceTextureLayer(GLuint tex, const sp<Layer>& layer) + : SurfaceTexture(tex), mLayer(layer) { +} + +SurfaceTextureLayer::~SurfaceTextureLayer() { +} + + +status_t SurfaceTextureLayer::setDefaultBufferSize(uint32_t w, uint32_t h) +{ + //LOGD("%s, w=%u, h=%u", __PRETTY_FUNCTION__, w, h); + return SurfaceTexture::setDefaultBufferSize(w, h); +} + +status_t SurfaceTextureLayer::setDefaultBufferFormat(uint32_t format) +{ + mDefaultFormat = format; + return NO_ERROR; +} + +status_t SurfaceTextureLayer::setBufferCount(int bufferCount) { + status_t res = SurfaceTexture::setBufferCount(bufferCount); + return res; +} + +status_t SurfaceTextureLayer::dequeueBuffer(int *buf, + uint32_t w, uint32_t h, uint32_t format, uint32_t usage) { + + status_t res(NO_INIT); + sp<Layer> layer(mLayer.promote()); + if (layer != NULL) { + if (format == 0) + format = mDefaultFormat; + uint32_t effectiveUsage = layer->getEffectiveUsage(usage); + //LOGD("%s, w=%u, h=%u, format=%u, usage=%08x, effectiveUsage=%08x", + // __PRETTY_FUNCTION__, w, h, format, usage, effectiveUsage); + res = SurfaceTexture::dequeueBuffer(buf, w, h, format, effectiveUsage); + if (res == NO_ERROR) { + layer->setFixedSize(w && h); + } + } + return res; +} + + +// --------------------------------------------------------------------------- +}; // namespace android diff --git a/services/surfaceflinger/SurfaceTextureLayer.h b/services/surfaceflinger/SurfaceTextureLayer.h new file mode 100644 index 0000000..7faff54 --- /dev/null +++ b/services/surfaceflinger/SurfaceTextureLayer.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2011 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_SURFACE_TEXTURE_LAYER_H +#define ANDROID_SURFACE_TEXTURE_LAYER_H + +#include <stdlib.h> +#include <stdint.h> +#include <sys/types.h> + +#include <utils/Errors.h> +#include <gui/SurfaceTexture.h> + +namespace android { +// --------------------------------------------------------------------------- + +class Layer; + +class SurfaceTextureLayer : public SurfaceTexture +{ + wp<Layer> mLayer; + uint32_t mDefaultFormat; + +public: + SurfaceTextureLayer(GLuint tex, const sp<Layer>& layer); + ~SurfaceTextureLayer(); + + status_t setDefaultBufferSize(uint32_t w, uint32_t h); + status_t setDefaultBufferFormat(uint32_t format); + +public: + virtual status_t setBufferCount(int bufferCount); + +protected: + virtual status_t dequeueBuffer(int *buf, uint32_t w, uint32_t h, + uint32_t format, uint32_t usage); +}; + +// --------------------------------------------------------------------------- +}; // namespace android + +#endif // ANDROID_SURFACE_TEXTURE_LAYER_H diff --git a/services/surfaceflinger/clz.h b/services/surfaceflinger/clz.h index 0ddf986..ca44555 100644 --- a/services/surfaceflinger/clz.h +++ b/services/surfaceflinger/clz.h @@ -20,18 +20,10 @@ namespace android { -int clz_impl(int32_t x); - -int inline clz(int32_t x) -{ -#if defined(__arm__) && !defined(__thumb__) +int inline clz(int32_t x) { return __builtin_clz(x); -#else - return clz_impl(x); -#endif } - }; // namespace android #endif /* ANDROID_SURFACE_FLINGER_CLZ_H */ |