summaryrefslogtreecommitdiffstats
path: root/services/surfaceflinger
diff options
context:
space:
mode:
authorMathias Agopian <mathias@google.com>2011-04-20 14:20:59 -0700
committerMathias Agopian <mathias@google.com>2011-06-13 15:51:35 -0700
commit7bb843ca0777111dae7daf8f1b0705817cf523c4 (patch)
tree10545edc3ce21f38282d5e67e5bc08ff729884b3 /services/surfaceflinger
parentdfc7958a2eafba52db90743a4707eed1d780b63b (diff)
downloadframeworks_base-7bb843ca0777111dae7daf8f1b0705817cf523c4.zip
frameworks_base-7bb843ca0777111dae7daf8f1b0705817cf523c4.tar.gz
frameworks_base-7bb843ca0777111dae7daf8f1b0705817cf523c4.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.mk22
-rw-r--r--services/surfaceflinger/Layer.cpp866
-rw-r--r--services/surfaceflinger/Layer.h164
-rw-r--r--services/surfaceflinger/LayerBase.cpp208
-rw-r--r--services/surfaceflinger/LayerBase.h84
-rw-r--r--services/surfaceflinger/LayerDim.cpp2
-rw-r--r--services/surfaceflinger/LayerDim.h2
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp214
-rw-r--r--services/surfaceflinger/SurfaceFlinger.h42
-rw-r--r--services/surfaceflinger/SurfaceTextureLayer.cpp76
-rw-r--r--services/surfaceflinger/SurfaceTextureLayer.h55
-rw-r--r--services/surfaceflinger/clz.h10
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 */