summaryrefslogtreecommitdiffstats
path: root/libs/surfaceflinger
diff options
context:
space:
mode:
Diffstat (limited to 'libs/surfaceflinger')
-rw-r--r--libs/surfaceflinger/Android.mk1
-rw-r--r--libs/surfaceflinger/Barrier.h4
-rw-r--r--libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp15
-rw-r--r--libs/surfaceflinger/DisplayHardware/DisplayHardware.h2
-rw-r--r--libs/surfaceflinger/Layer.cpp573
-rw-r--r--libs/surfaceflinger/Layer.h122
-rw-r--r--libs/surfaceflinger/LayerBase.cpp296
-rw-r--r--libs/surfaceflinger/LayerBase.h102
-rw-r--r--libs/surfaceflinger/LayerBlur.cpp57
-rw-r--r--libs/surfaceflinger/LayerBlur.h6
-rw-r--r--libs/surfaceflinger/LayerBuffer.cpp61
-rw-r--r--libs/surfaceflinger/LayerBuffer.h14
-rw-r--r--libs/surfaceflinger/LayerDim.cpp3
-rw-r--r--libs/surfaceflinger/LayerDim.h6
-rw-r--r--libs/surfaceflinger/MessageQueue.cpp13
-rw-r--r--libs/surfaceflinger/MessageQueue.h35
-rw-r--r--libs/surfaceflinger/SurfaceFlinger.cpp153
-rw-r--r--libs/surfaceflinger/SurfaceFlinger.h23
-rw-r--r--libs/surfaceflinger/TextureManager.cpp241
-rw-r--r--libs/surfaceflinger/TextureManager.h82
-rw-r--r--libs/surfaceflinger/Transform.cpp7
-rw-r--r--libs/surfaceflinger/Transform.h4
22 files changed, 972 insertions, 848 deletions
diff --git a/libs/surfaceflinger/Android.mk b/libs/surfaceflinger/Android.mk
index 86eb78d..b8a0630 100644
--- a/libs/surfaceflinger/Android.mk
+++ b/libs/surfaceflinger/Android.mk
@@ -13,6 +13,7 @@ LOCAL_SRC_FILES:= \
LayerDim.cpp \
MessageQueue.cpp \
SurfaceFlinger.cpp \
+ TextureManager.cpp \
Tokenizer.cpp \
Transform.cpp
diff --git a/libs/surfaceflinger/Barrier.h b/libs/surfaceflinger/Barrier.h
index e2bcf6a..6f8507e 100644
--- a/libs/surfaceflinger/Barrier.h
+++ b/libs/surfaceflinger/Barrier.h
@@ -29,10 +29,6 @@ public:
inline Barrier() : state(CLOSED) { }
inline ~Barrier() { }
void open() {
- // gcc memory barrier, this makes sure all memory writes
- // have been issued by gcc. On an SMP system we'd need a real
- // h/w barrier.
- asm volatile ("":::"memory");
Mutex::Autolock _l(lock);
state = OPENED;
cv.broadcast();
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index ea68352..51de1da 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -73,7 +73,7 @@ void checkEGLErrors(const char* token)
DisplayHardware::DisplayHardware(
const sp<SurfaceFlinger>& flinger,
uint32_t dpy)
- : DisplayHardwareBase(flinger, dpy)
+ : DisplayHardwareBase(flinger, dpy), mFlags(0)
{
init(dpy);
}
@@ -125,7 +125,6 @@ void DisplayHardware::init(uint32_t dpy)
EGLint numConfigs=0;
EGLSurface surface;
EGLContext context;
- mFlags = CACHED_BUFFERS;
// TODO: all the extensions below should be queried through
// eglGetProcAddress().
@@ -253,22 +252,10 @@ void DisplayHardware::init(uint32_t dpy)
LOGI("GL_MAX_TEXTURE_SIZE = %d", mMaxTextureSize);
LOGI("GL_MAX_VIEWPORT_DIMS = %d", mMaxViewportDims);
-#if 0
- // for drivers that don't have proper support for flushing cached buffers
- // on gralloc unlock, uncomment this block and test for the specific
- // renderer substring
- if (strstr(gl_renderer, "<some vendor string>")) {
- LOGD("Assuming uncached graphics buffers.");
- mFlags &= ~CACHED_BUFFERS;
- }
-#endif
if (strstr(gl_extensions, "GL_ARB_texture_non_power_of_two")) {
mFlags |= NPOT_EXTENSION;
}
- if (strstr(gl_extensions, "GL_OES_draw_texture")) {
- mFlags |= DRAW_TEXTURE_EXTENSION;
- }
#ifdef EGL_ANDROID_image_native_buffer
if (strstr( gl_extensions, "GL_OES_EGL_image") &&
(strstr(egl_extensions, "EGL_KHR_image_base") ||
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h
index df046af..ebd7c42 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h
@@ -46,12 +46,10 @@ public:
DIRECT_TEXTURE = 0x00000002,
COPY_BITS_EXTENSION = 0x00000008,
NPOT_EXTENSION = 0x00000100,
- DRAW_TEXTURE_EXTENSION = 0x00000200,
BUFFER_PRESERVED = 0x00010000,
PARTIAL_UPDATES = 0x00020000, // video driver feature
SLOW_CONFIG = 0x00040000, // software
SWAP_RECTANGLE = 0x00080000,
- CACHED_BUFFERS = 0x00100000
};
DisplayHardware(
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index ce7e9aa..3fbb4d3 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -47,47 +47,42 @@ template <typename T> inline T min(T a, T b) {
// ---------------------------------------------------------------------------
-const uint32_t Layer::typeInfo = LayerBaseClient::typeInfo | 4;
-const char* const Layer::typeID = "Layer";
-
-// ---------------------------------------------------------------------------
-
Layer::Layer(SurfaceFlinger* flinger, DisplayID display,
- const sp<Client>& c, int32_t i)
- : LayerBaseClient(flinger, display, c, i),
+ const sp<Client>& client, int32_t i)
+ : LayerBaseClient(flinger, display, client, i),
+ lcblk(NULL),
mSecure(false),
- mNoEGLImageForSwBuffers(false),
mNeedsBlending(true),
- mNeedsDithering(false)
+ mNeedsDithering(false),
+ mTextureManager(mFlags),
+ mBufferManager(mTextureManager),
+ mWidth(0), mHeight(0), mFixedSize(false)
{
// no OpenGL operation is possible here, since we might not be
// in the OpenGL thread.
- mFrontBufferIndex = lcblk->getFrontBuffer();
+ lcblk = new SharedBufferServer(
+ client->ctrlblk, i, mBufferManager.getDefaultBufferCount(),
+ getIdentity());
+
+ mBufferManager.setActiveBufferIndex( lcblk->getFrontBuffer() );
}
Layer::~Layer()
{
- destroy();
+ // FIXME: must be called from the main UI thread
+ EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
+ mBufferManager.destroy(dpy);
+
// the actual buffers will be destroyed here
+ delete lcblk;
}
-void Layer::destroy()
+// called with SurfaceFlinger::mStateLock as soon as the layer is entered
+// in the purgatory list
+void Layer::onRemoved()
{
- for (size_t i=0 ; i<NUM_BUFFERS ; i++) {
- if (mTextures[i].name != -1U) {
- glDeleteTextures(1, &mTextures[i].name);
- mTextures[i].name = -1U;
- }
- if (mTextures[i].image != EGL_NO_IMAGE_KHR) {
- EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
- eglDestroyImageKHR(dpy, mTextures[i].image);
- mTextures[i].image = EGL_NO_IMAGE_KHR;
- }
- Mutex::Autolock _l(mLock);
- mBuffers[i].clear();
- mWidth = mHeight = 0;
- }
- mSurface.clear();
+ // wake up the condition
+ lcblk->setStatus(NO_INIT);
}
sp<LayerBaseClient::Surface> Layer::createSurface() const
@@ -97,9 +92,17 @@ sp<LayerBaseClient::Surface> Layer::createSurface() const
status_t Layer::ditch()
{
+ // NOTE: Called from the main UI thread
+
// the layer is not on screen anymore. free as much resources as possible
mFreezeLock.clear();
- destroy();
+
+ EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
+ mBufferManager.destroy(dpy);
+ mSurface.clear();
+
+ Mutex::Autolock _l(mLock);
+ mWidth = mHeight = 0;
return NO_ERROR;
}
@@ -131,24 +134,19 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h,
mHeight = h;
mSecure = (flags & ISurfaceComposer::eSecure) ? true : false;
mNeedsBlending = (info.h_alpha - info.l_alpha) > 0;
- mNoEGLImageForSwBuffers = !(hwFlags & DisplayHardware::CACHED_BUFFERS);
// we use the red index
int displayRedSize = displayInfo.getSize(PixelFormatInfo::INDEX_RED);
int layerRedsize = info.getSize(PixelFormatInfo::INDEX_RED);
mNeedsDithering = layerRedsize > displayRedSize;
- for (size_t i=0 ; i<NUM_BUFFERS ; i++) {
- mBuffers[i] = new GraphicBuffer();
- }
mSurface = new SurfaceLayer(mFlinger, clientIndex(), this);
return NO_ERROR;
}
void Layer::reloadTexture(const Region& dirty)
{
- Mutex::Autolock _l(mLock);
- sp<GraphicBuffer> buffer(getFrontBufferLocked());
+ 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
@@ -156,118 +154,24 @@ void Layer::reloadTexture(const Region& dirty)
return;
}
- const int index = mFrontBufferIndex;
-
- // create the new texture name if needed
- if (UNLIKELY(mTextures[index].name == -1U)) {
- mTextures[index].name = createTexture();
- mTextures[index].width = 0;
- mTextures[index].height = 0;
- }
-
#ifdef EGL_ANDROID_image_native_buffer
if (mFlags & DisplayHardware::DIRECT_TEXTURE) {
- if (buffer->usage & GraphicBuffer::USAGE_HW_TEXTURE) {
- if (mTextures[index].dirty) {
- if (initializeEglImage(buffer, &mTextures[index]) != NO_ERROR) {
- // not sure what we can do here...
- mFlags &= ~DisplayHardware::DIRECT_TEXTURE;
- goto slowpath;
- }
- }
- } else {
- if (mHybridBuffer==0 || (mHybridBuffer->width != buffer->width ||
- mHybridBuffer->height != buffer->height)) {
- mHybridBuffer.clear();
- mHybridBuffer = new GraphicBuffer(
- buffer->width, buffer->height, buffer->format,
- GraphicBuffer::USAGE_SW_WRITE_OFTEN |
- GraphicBuffer::USAGE_HW_TEXTURE);
- if (initializeEglImage(
- mHybridBuffer, &mTextures[0]) != NO_ERROR) {
- // not sure what we can do here...
- mFlags &= ~DisplayHardware::DIRECT_TEXTURE;
- mHybridBuffer.clear();
- goto slowpath;
- }
- }
-
- GGLSurface t;
- 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) {
- Texture* const texture(&mTextures[0]);
-
- glBindTexture(GL_TEXTURE_2D, texture->name);
-
- sp<GraphicBuffer> buf(mHybridBuffer);
- void* vaddr;
- res = buf->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN, &vaddr);
- if (res == NO_ERROR) {
- int bpp = 0;
- switch (t.format) {
- case HAL_PIXEL_FORMAT_RGB_565:
- case HAL_PIXEL_FORMAT_RGBA_4444:
- bpp = 2;
- break;
- case HAL_PIXEL_FORMAT_RGBA_8888:
- case HAL_PIXEL_FORMAT_RGBX_8888:
- bpp = 4;
- break;
- default:
- if (isSupportedYuvFormat(t.format)) {
- // just show the Y plane of YUV buffers
- bpp = 1;
- break;
- }
- // oops, we don't handle this format!
- LOGE("layer %p, texture=%d, using format %d, which is not "
- "supported by the GL", this, texture->name, t.format);
- }
- if (bpp) {
- const Rect bounds(dirty.getBounds());
- size_t src_stride = t.stride;
- size_t dst_stride = buf->stride;
- if (src_stride == dst_stride &&
- bounds.width() == t.width &&
- bounds.height() == t.height)
- {
- memcpy(vaddr, t.data, t.height * t.stride * bpp);
- } else {
- GLubyte const * src = t.data +
- (bounds.left + bounds.top * src_stride) * bpp;
- GLubyte * dst = (GLubyte *)vaddr +
- (bounds.left + bounds.top * dst_stride) * bpp;
- const size_t length = bounds.width() * bpp;
- size_t h = bounds.height();
- src_stride *= bpp;
- dst_stride *= bpp;
- while (h--) {
- memcpy(dst, src, length);
- dst += dst_stride;
- src += src_stride;
- }
- }
- }
- buf->unlock();
- }
- buffer->unlock();
- }
+ EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
+ if (mBufferManager.initEglImage(dpy, buffer) != NO_ERROR) {
+ // not sure what we can do here...
+ mFlags &= ~DisplayHardware::DIRECT_TEXTURE;
+ goto slowpath;
}
} else
#endif
{
slowpath:
- for (size_t i=0 ; i<NUM_BUFFERS ; i++) {
- mTextures[i].image = EGL_NO_IMAGE_KHR;
- }
GGLSurface t;
status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_OFTEN);
LOGE_IF(res, "error %d (%s) locking buffer %p",
res, strerror(res), buffer.get());
if (res == NO_ERROR) {
- loadTexture(&mTextures[0], dirty, t);
+ mBufferManager.loadTexture(dirty, t);
buffer->unlock();
}
}
@@ -275,11 +179,8 @@ slowpath:
void Layer::onDraw(const Region& clip) const
{
- int index = mFrontBufferIndex;
- if (mTextures[index].image == EGL_NO_IMAGE_KHR)
- index = 0;
- GLuint textureName = mTextures[index].name;
- if (UNLIKELY(textureName == -1LU)) {
+ Texture tex(mBufferManager.getActiveTexture());
+ if (tex.name == -1LU) {
// 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
@@ -305,13 +206,53 @@ void Layer::onDraw(const Region& clip) const
}
return;
}
- drawWithOpenGL(clip, mTextures[index]);
+ drawWithOpenGL(clip, tex);
+}
+
+bool Layer::needsFiltering() const
+{
+ if (!(mFlags & DisplayHardware::SLOW_CONFIG)) {
+ // NOTE: there is a race here, because mFixedSize is updated in a
+ // binder transaction. however, it doesn't really matter since it is
+ // evaluated each time we draw. To be perfectly correct, this flag
+ // would have to be associated with a buffer.
+ if (mFixedSize)
+ return true;
+ }
+ return LayerBase::needsFiltering();
+}
+
+
+status_t Layer::setBufferCount(int bufferCount)
+{
+ // Ensures our client doesn't go away while we're accessing
+ // the shared area.
+ sp<Client> ourClient(client.promote());
+ if (ourClient == 0) {
+ // 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)
+ mBufferManager.resize(bufferCount);
+
+ return err;
}
-sp<GraphicBuffer> Layer::requestBuffer(int index, int usage)
+sp<GraphicBuffer> Layer::requestBuffer(int index,
+ uint32_t reqWidth, uint32_t reqHeight, uint32_t reqFormat,
+ uint32_t usage)
{
sp<GraphicBuffer> buffer;
+ if ((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.
sp<Client> ourClient(client.promote());
@@ -324,7 +265,7 @@ sp<GraphicBuffer> Layer::requestBuffer(int index, int usage)
* 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.
- *
+ *
* Make sure the buffer we're resizing is not the front buffer and has been
* dequeued. Once this condition is asserted, we are guaranteed that this
* buffer cannot become the front buffer under our feet, since we're called
@@ -337,31 +278,33 @@ sp<GraphicBuffer> Layer::requestBuffer(int index, int usage)
return buffer;
}
- uint32_t w, h;
+ uint32_t w, h, f;
{ // scope for the lock
Mutex::Autolock _l(mLock);
- w = mWidth;
- h = mHeight;
- buffer = mBuffers[index];
-
- // destroy() could have been called before we get here, we log it
- // because it's uncommon, and the code below should handle it
- LOGW_IF(buffer==0,
- "mBuffers[%d] is null (mWidth=%d, mHeight=%d)",
- index, w, h);
-
- mBuffers[index].clear();
+ const bool fixedSizeChanged = mFixedSize != (reqWidth && reqHeight);
+ const bool formatChanged = mReqFormat != reqFormat;
+ mReqWidth = reqWidth;
+ mReqHeight = reqHeight;
+ mReqFormat = reqFormat;
+ mFixedSize = reqWidth && reqHeight;
+ w = reqWidth ? reqWidth : mWidth;
+ h = reqHeight ? reqHeight : mHeight;
+ f = reqFormat ? reqFormat : mFormat;
+ buffer = mBufferManager.detachBuffer(index);
+ if (fixedSizeChanged || formatChanged) {
+ lcblk->reallocateAllExcept(index);
+ }
}
const uint32_t effectiveUsage = getEffectiveUsage(usage);
if (buffer!=0 && buffer->getStrongCount() == 1) {
- err = buffer->reallocate(w, h, mFormat, effectiveUsage);
+ err = buffer->reallocate(w, h, f, effectiveUsage);
} else {
// here we have to reallocate a new buffer because we could have a
// client in our process with a reference to it (eg: status bar),
// and we can't release the handle under its feet.
buffer.clear();
- buffer = new GraphicBuffer(w, h, mFormat, effectiveUsage);
+ buffer = new GraphicBuffer(w, h, f, effectiveUsage);
err = buffer->initCheck();
}
@@ -377,15 +320,7 @@ sp<GraphicBuffer> Layer::requestBuffer(int index, int usage)
if (err == NO_ERROR && buffer->handle != 0) {
Mutex::Autolock _l(mLock);
- if (mWidth && mHeight) {
- // and we have new buffer
- mBuffers[index] = buffer;
- // texture is now dirty...
- mTextures[index].dirty = true;
- } else {
- // oops we got killed while we were allocating the buffer
- buffer.clear();
- }
+ mBufferManager.attachBuffer(index, buffer);
}
return buffer;
}
@@ -411,15 +346,8 @@ uint32_t Layer::getEffectiveUsage(uint32_t usage) const
} else {
// it's allowed to modify the usage flags here, but generally
// the requested flags should be honored.
- if (mNoEGLImageForSwBuffers) {
- if (usage & GraphicBuffer::USAGE_HW_MASK) {
- // request EGLImage for h/w buffers only
- usage |= GraphicBuffer::USAGE_HW_TEXTURE;
- }
- } else {
- // request EGLImage for all buffers
- usage |= GraphicBuffer::USAGE_HW_TEXTURE;
- }
+ // request EGLImage for all buffers
+ usage |= GraphicBuffer::USAGE_HW_TEXTURE;
}
return usage;
}
@@ -429,42 +357,46 @@ uint32_t Layer::doTransaction(uint32_t flags)
const Layer::State& front(drawingState());
const Layer::State& temp(currentState());
- if ((front.requested_w != temp.requested_w) ||
- (front.requested_h != temp.requested_h)) {
+ const bool sizeChanged = (front.requested_w != temp.requested_w) ||
+ (front.requested_h != temp.requested_h);
+
+ 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), (%dx%d), (%dx%d)",
- this,
- int(temp.requested_w), int(temp.requested_h),
- int(front.requested_w), int(front.requested_h),
- int(mBuffers[0]->getWidth()), int(mBuffers[0]->getHeight()),
- int(mBuffers[1]->getWidth()), int(mBuffers[1]->getHeight()));
-
- // we're being resized and there is a freeze display request,
- // acquire a freeze lock, so that the screen stays put
- // until we've redrawn at the new size; this is to avoid
- // glitches upon orientation changes.
- if (mFlinger->hasFreezeRequest()) {
- // if the surface is hidden, don't try to acquire the
- // freeze lock, since hidden surfaces may never redraw
- if (!(front.flags & ISurfaceComposer::eLayerHidden)) {
- mFreezeLock = mFlinger->getFreezeLock();
+ "resize (layer=%p), requested (%dx%d), drawing (%d,%d)",
+ this,
+ int(temp.requested_w), int(temp.requested_h),
+ int(front.requested_w), int(front.requested_h));
+
+ if (!isFixedSize()) {
+ // we're being resized and there is a freeze display request,
+ // acquire a freeze lock, so that the screen stays put
+ // until we've redrawn at the new size; this is to avoid
+ // glitches upon orientation changes.
+ if (mFlinger->hasFreezeRequest()) {
+ // if the surface is hidden, don't try to acquire the
+ // freeze lock, since hidden surfaces may never redraw
+ if (!(front.flags & ISurfaceComposer::eLayerHidden)) {
+ mFreezeLock = mFlinger->getFreezeLock();
+ }
}
- }
- // this will make sure LayerBase::doTransaction doesn't update
- // the drawing state's size
- Layer::State& editDraw(mDrawingState);
- editDraw.requested_w = temp.requested_w;
- editDraw.requested_h = temp.requested_h;
+ // this will make sure LayerBase::doTransaction doesn't update
+ // the drawing state's size
+ Layer::State& editDraw(mDrawingState);
+ editDraw.requested_w = temp.requested_w;
+ editDraw.requested_h = temp.requested_h;
- // record the new size, form this point on, when the client request a
- // buffer, it'll get the new size.
- setDrawingSize(temp.requested_w, temp.requested_h);
+ // 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);
- // all buffers need reallocation
- lcblk->reallocate();
+ // all buffers need reallocation
+ lcblk->reallocateAll();
+ } else {
+ // record the new size
+ setBufferSize(temp.requested_w, temp.requested_h);
+ }
}
if (temp.sequence != front.sequence) {
@@ -478,12 +410,17 @@ uint32_t Layer::doTransaction(uint32_t flags)
return LayerBase::doTransaction(flags);
}
-void Layer::setDrawingSize(uint32_t w, uint32_t h) {
+void Layer::setBufferSize(uint32_t w, uint32_t h) {
Mutex::Autolock _l(mLock);
mWidth = w;
mHeight = h;
}
+bool Layer::isFixedSize() const {
+ Mutex::Autolock _l(mLock);
+ return mFixedSize;
+}
+
// ----------------------------------------------------------------------------
// pageflip handling...
// ----------------------------------------------------------------------------
@@ -491,22 +428,25 @@ void Layer::setDrawingSize(uint32_t w, uint32_t h) {
void Layer::lockPageFlip(bool& recomputeVisibleRegions)
{
ssize_t buf = lcblk->retireAndLock();
- if (buf < NO_ERROR) {
- //LOGW("nothing to retire (%s)", strerror(-buf));
- // NOTE: here the buffer is locked because we will used
+ 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;
}
- // ouch, this really should never happen
- if (uint32_t(buf)>=NUM_BUFFERS) {
+ if (buf < NO_ERROR) {
LOGE("retireAndLock() buffer index (%d) out of range", buf);
mPostedDirtyRegion.clear();
return;
}
// we retired a buffer, which becomes the new front buffer
- mFrontBufferIndex = buf;
+ if (mBufferManager.setActiveBufferIndex(buf) < NO_ERROR) {
+ LOGE("retireAndLock() buffer index (%d) out of range", buf);
+ mPostedDirtyRegion.clear();
+ return;
+ }
// get the dirty region
sp<GraphicBuffer> newFrontBuffer(getBuffer(buf));
@@ -559,9 +499,15 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions)
mFlinger->signalEvent();
}
- if (!mPostedDirtyRegion.isEmpty()) {
- reloadTexture( mPostedDirtyRegion );
- }
+ /* 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(
@@ -585,17 +531,177 @@ void Layer::unlockPageFlip(
}
if (visibleRegionScreen.isEmpty()) {
// an invisible layer should not hold a freeze-lock
- // (because it may never be updated and thereore never release it)
+ // (because it may never be updated and therefore never release it)
mFreezeLock.clear();
}
}
void Layer::finishPageFlip()
{
- status_t err = lcblk->unlock( mFrontBufferIndex );
- LOGE_IF(err!=NO_ERROR,
- "layer %p, buffer=%d wasn't locked!",
- this, mFrontBufferIndex);
+ int buf = mBufferManager.getActiveBufferIndex();
+ status_t err = lcblk->unlock( buf );
+ LOGE_IF(err!=NO_ERROR, "layer %p, buffer=%d wasn't locked!", this, buf);
+}
+
+
+void Layer::dump(String8& result, char* buffer, size_t SIZE) const
+{
+ LayerBaseClient::dump(result, buffer, SIZE);
+
+ SharedBufferStack::Statistics stats = lcblk->getStats();
+ 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;
+ if (buf0 != 0) {
+ w0 = buf0->getWidth();
+ h0 = buf0->getHeight();
+ s0 = buf0->getStride();
+ }
+ if (buf1 != 0) {
+ w1 = buf1->getWidth();
+ h1 = buf1->getHeight();
+ s1 = buf1->getStride();
+ }
+ snprintf(buffer, SIZE,
+ " "
+ "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u],"
+ " freezeLock=%p, dq-q-time=%u us\n",
+ pixelFormat(),
+ w0, h0, s0, w1, h1, s1,
+ getFreezeLock().get(), stats.totalTime);
+
+ result.append(buffer);
+}
+
+// ---------------------------------------------------------------------------
+
+Layer::BufferManager::BufferManager(TextureManager& tm)
+ : mNumBuffers(NUM_BUFFERS), mTextureManager(tm),
+ mActiveBuffer(0), mFailover(false)
+{
+}
+
+Layer::BufferManager::~BufferManager()
+{
+}
+
+status_t Layer::BufferManager::resize(size_t size)
+{
+ Mutex::Autolock _l(mLock);
+ 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) {
+ // TODO: need to validate 'index'
+ mActiveBuffer = index;
+ return NO_ERROR;
+}
+
+size_t Layer::BufferManager::getActiveBufferIndex() const {
+ return mActiveBuffer;
+}
+
+Texture Layer::BufferManager::getActiveTexture() const {
+ Texture res;
+ if (mFailover) {
+ res = mFailoverTexture;
+ } else {
+ static_cast<Image&>(res) = mBufferData[mActiveBuffer].texture;
+ }
+ return res;
+}
+
+sp<GraphicBuffer> Layer::BufferManager::getActiveBuffer() const {
+ const size_t activeBuffer = mActiveBuffer;
+ BufferData const * const buffers = mBufferData;
+ Mutex::Autolock _l(mLock);
+ return buffers[activeBuffer].buffer;
+}
+
+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;
+ }
+ }
+ 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)
+{
+ size_t index = mActiveBuffer;
+ Image& texture(mBufferData[index].texture);
+ status_t 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);
+ }
+ }
+ 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;
}
// ---------------------------------------------------------------------------
@@ -610,20 +716,37 @@ Layer::SurfaceLayer::~SurfaceLayer()
{
}
-sp<GraphicBuffer> Layer::SurfaceLayer::requestBuffer(int index, int usage)
+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) {
- LOGE_IF(uint32_t(index)>=NUM_BUFFERS,
- "getBuffer() index (%d) out of range", index);
- if (uint32_t(index) < NUM_BUFFERS) {
- buffer = owner->requestBuffer(index, usage);
- }
+ /*
+ * 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)
+{
+ 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);
+ }
+ return err;
+}
+
// ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/Layer.h b/libs/surfaceflinger/Layer.h
index 743afb4..59603a5 100644
--- a/libs/surfaceflinger/Layer.h
+++ b/libs/surfaceflinger/Layer.h
@@ -31,6 +31,7 @@
#include "LayerBase.h"
#include "Transform.h"
+#include "TextureManager.h"
namespace android {
@@ -41,16 +42,13 @@ class FreezeLock;
// ---------------------------------------------------------------------------
-const size_t NUM_BUFFERS = 2;
-
class Layer : public LayerBaseClient
{
-public:
- static const uint32_t typeInfo;
- static const char* const typeID;
- virtual char const* getTypeID() const { return typeID; }
- virtual uint32_t getTypeInfo() const { return typeInfo; }
-
+public:
+ // lcblk is (almost) only accessed from the main SF thread, in the places
+ // where it's not, a reference to Client must be held
+ SharedBufferServer* lcblk;
+
Layer(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client, int32_t i);
@@ -59,7 +57,8 @@ public:
status_t setBuffers(uint32_t w, uint32_t h,
PixelFormat format, uint32_t flags=0);
- void setDrawingSize(uint32_t w, uint32_t h);
+ void setBufferSize(uint32_t w, uint32_t h);
+ bool isFixedSize() const;
virtual void onDraw(const Region& clip) const;
virtual uint32_t doTransaction(uint32_t transactionFlags);
@@ -68,30 +67,32 @@ public:
virtual void finishPageFlip();
virtual bool needsBlending() const { return mNeedsBlending; }
virtual bool needsDithering() const { return mNeedsDithering; }
+ virtual bool needsFiltering() const;
virtual bool isSecure() const { return mSecure; }
virtual sp<Surface> createSurface() const;
virtual status_t ditch();
+ virtual void onRemoved();
// only for debugging
- inline sp<GraphicBuffer> getBuffer(int i) { return mBuffers[i]; }
+ inline sp<GraphicBuffer> getBuffer(int i) const { return mBufferManager.getBuffer(i); }
// only for debugging
inline const sp<FreezeLock>& getFreezeLock() const { return mFreezeLock; }
// only for debugging
inline PixelFormat pixelFormat() const { return mFormat; }
- // only for debugging
- inline int getFrontBufferIndex() const { return mFrontBufferIndex; }
+
+ virtual const char* getTypeId() const { return "Layer"; }
+
+protected:
+ virtual void dump(String8& result, char* scratch, size_t size) const;
private:
- inline sp<GraphicBuffer> getFrontBufferLocked() {
- return mBuffers[mFrontBufferIndex];
- }
-
void reloadTexture(const Region& dirty);
uint32_t getEffectiveUsage(uint32_t usage) const;
- sp<GraphicBuffer> requestBuffer(int index, int usage);
- void destroy();
+ 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:
@@ -99,7 +100,9 @@ private:
SurfaceID id, const sp<Layer>& owner);
~SurfaceLayer();
private:
- virtual sp<GraphicBuffer> requestBuffer(int index, int usage);
+ 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());
}
@@ -109,22 +112,83 @@ private:
sp<Surface> mSurface;
bool mSecure;
- bool mNoEGLImageForSwBuffers;
int32_t mFrontBufferIndex;
bool mNeedsBlending;
bool mNeedsDithering;
Region mPostedDirtyRegion;
sp<FreezeLock> mFreezeLock;
PixelFormat mFormat;
-
- // protected by mLock
- sp<GraphicBuffer> mBuffers[NUM_BUFFERS];
- Texture mTextures[NUM_BUFFERS];
- sp<GraphicBuffer> mHybridBuffer;
- uint32_t mWidth;
- uint32_t mHeight;
-
- mutable Mutex mLock;
+
+ 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 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);
+
+ // ----------------------------------------------
+ // 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 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;
+ };
+
+ TextureManager mTextureManager;
+ BufferManager mBufferManager;
+
+ // this lock protects mWidth and mHeight which are accessed from
+ // the main thread and requestBuffer's binder transaction thread.
+ mutable Mutex mLock;
+ uint32_t mWidth;
+ uint32_t mHeight;
+ uint32_t mReqWidth;
+ uint32_t mReqHeight;
+ uint32_t mReqFormat;
+ bool mFixedSize;
};
// ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp
index a8b735e..76733a9 100644
--- a/libs/surfaceflinger/LayerBase.cpp
+++ b/libs/surfaceflinger/LayerBase.cpp
@@ -32,29 +32,21 @@
#include "LayerBase.h"
#include "SurfaceFlinger.h"
#include "DisplayHardware/DisplayHardware.h"
+#include "TextureManager.h"
namespace android {
// ---------------------------------------------------------------------------
-const uint32_t LayerBase::typeInfo = 1;
-const char* const LayerBase::typeID = "LayerBase";
-
-const uint32_t LayerBaseClient::typeInfo = LayerBase::typeInfo | 2;
-const char* const LayerBaseClient::typeID = "LayerBaseClient";
-
-// ---------------------------------------------------------------------------
-
LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display)
: dpy(display), contentDirty(false),
mFlinger(flinger),
- mTransformed(false),
- mUseLinearFiltering(false),
+ mNeedsFiltering(false),
mOrientation(0),
mLeft(0), mTop(0),
mTransactionFlags(0),
- mPremultipliedAlpha(true), mDebug(false),
+ mPremultipliedAlpha(true), mName("unnamed"), mDebug(false),
mInvalidate(0)
{
const DisplayHardware& hw(flinger->graphicPlane(0).displayHardware());
@@ -221,13 +213,12 @@ uint32_t LayerBase::doTransaction(uint32_t flags)
flags |= eVisibleRegion;
this->contentDirty = true;
- const bool linearFiltering = mUseLinearFiltering;
- mUseLinearFiltering = false;
+ mNeedsFiltering = false;
if (!(mFlags & DisplayHardware::SLOW_CONFIG)) {
// we may use linear filtering, if the matrix scales us
const uint8_t type = temp.transform.getType();
if (!temp.transform.preserveRects() || (type >= Transform::SCALE)) {
- mUseLinearFiltering = true;
+ mNeedsFiltering = true;
}
}
}
@@ -267,7 +258,6 @@ void LayerBase::validateVisibility(const Transform& planeTransform)
// cache a few things...
mOrientation = tr.getOrientation();
mTransformedBounds = tr.makeBounds(w, h);
- mTransformed = transformed;
mLeft = tr.tx();
mTop = tr.ty();
}
@@ -348,25 +338,13 @@ void LayerBase::draw(const Region& inClip) const
*/
}
-GLuint LayerBase::createTexture() const
-{
- GLuint textureName = -1;
- glGenTextures(1, &textureName);
- glBindTexture(GL_TEXTURE_2D, textureName);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- return textureName;
-}
-
-void LayerBase::clearWithOpenGL(const Region& clip, GLclampx red,
- GLclampx green, GLclampx blue,
- GLclampx alpha) const
+void LayerBase::clearWithOpenGL(const Region& clip, GLclampf red,
+ GLclampf green, GLclampf blue,
+ GLclampf alpha) const
{
const DisplayHardware& hw(graphicPlane(0).displayHardware());
const uint32_t fbHeight = hw.getHeight();
- glColor4x(red,green,blue,alpha);
+ glColor4f(red,green,blue,alpha);
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
glDisable(GL_DITHER);
@@ -374,7 +352,7 @@ void LayerBase::clearWithOpenGL(const Region& clip, GLclampx red,
Region::const_iterator it = clip.begin();
Region::const_iterator const end = clip.end();
glEnable(GL_SCISSOR_TEST);
- glVertexPointer(2, GL_FIXED, 0, mVertices);
+ glVertexPointer(2, GL_FLOAT, 0, mVertices);
while (it != end) {
const Rect& r = *it++;
const GLint sy = fbHeight - (r.top + r.height());
@@ -418,14 +396,14 @@ void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const
env = GL_REPLACE;
src = GL_SRC_ALPHA;
}
- const GGLfixed alpha = (s.alpha << 16)/255;
- glColor4x(alpha, alpha, alpha, alpha);
+ const GLfloat alpha = s.alpha * (1.0f/255.0f);
+ glColor4f(alpha, alpha, alpha, alpha);
glEnable(GL_BLEND);
glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env);
} else {
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
- glColor4x(0x10000, 0x10000, 0x10000, 0x10000);
+ glColor4f(1, 1, 1, 1);
if (needsBlending()) {
GLenum src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;
glEnable(GL_BLEND);
@@ -437,13 +415,11 @@ void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const
Region::const_iterator it = clip.begin();
Region::const_iterator const end = clip.end();
-
- //StopWatch watch("GL transformed");
- const GLfixed texCoords[4][2] = {
- { 0, 0 },
- { 0, 0x10000 },
- { 0x10000, 0x10000 },
- { 0x10000, 0 }
+ const GLfloat texCoords[4][2] = {
+ { 0, 0 },
+ { 0, 1 },
+ { 1, 1 },
+ { 1, 0 }
};
glMatrixMode(GL_TEXTURE);
@@ -470,8 +446,8 @@ void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const
}
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glVertexPointer(2, GL_FIXED, 0, mVertices);
- glTexCoordPointer(2, GL_FIXED, 0, texCoords);
+ glVertexPointer(2, GL_FLOAT, 0, mVertices);
+ glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
while (it != end) {
const Rect& r = *it++;
@@ -487,7 +463,7 @@ void LayerBase::validateTexture(GLint textureName) const
glBindTexture(GL_TEXTURE_2D, textureName);
// TODO: reload the texture if needed
// this is currently done in loadTexture() below
- if (mUseLinearFiltering) {
+ if (needsFiltering()) {
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
} else {
@@ -502,200 +478,32 @@ void LayerBase::validateTexture(GLint textureName) const
}
}
-bool LayerBase::isSupportedYuvFormat(int format) const
+void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const
{
- switch (format) {
- case HAL_PIXEL_FORMAT_YCbCr_422_SP:
- case HAL_PIXEL_FORMAT_YCbCr_420_SP:
- case HAL_PIXEL_FORMAT_YCbCr_422_P:
- case HAL_PIXEL_FORMAT_YCbCr_420_P:
- case HAL_PIXEL_FORMAT_YCbCr_422_I:
- case HAL_PIXEL_FORMAT_YCbCr_420_I:
- case HAL_PIXEL_FORMAT_YCrCb_420_SP:
- return true;
- }
- return false;
-}
-
-void LayerBase::loadTexture(Texture* texture,
- const Region& dirty, const GGLSurface& t) const
-{
- if (texture->name == -1U) {
- // uh?
- return;
- }
-
- glBindTexture(GL_TEXTURE_2D, texture->name);
-
- /*
- * In OpenGL ES we can't specify a stride with glTexImage2D (however,
- * GL_UNPACK_ALIGNMENT is a limited form of stride).
- * So if the stride here isn't representable with GL_UNPACK_ALIGNMENT, we
- * need to do something reasonable (here creating a bigger texture).
- *
- * extra pixels = (((stride - width) * pixelsize) / GL_UNPACK_ALIGNMENT);
- *
- * This situation doesn't happen often, but some h/w have a limitation
- * for their framebuffer (eg: must be multiple of 8 pixels), and
- * we need to take that into account when using these buffers as
- * textures.
- *
- * This should never be a problem with POT textures
- */
-
- int unpack = __builtin_ctz(t.stride * bytesPerPixel(t.format));
- unpack = 1 << ((unpack > 3) ? 3 : unpack);
- glPixelStorei(GL_UNPACK_ALIGNMENT, unpack);
-
- /*
- * round to POT if needed
- */
- if (!(mFlags & DisplayHardware::NPOT_EXTENSION)) {
- texture->NPOTAdjust = true;
- }
-
- if (texture->NPOTAdjust) {
- // find the smallest power-of-two that will accommodate our surface
- texture->potWidth = 1 << (31 - clz(t.width));
- texture->potHeight = 1 << (31 - clz(t.height));
- if (texture->potWidth < t.width) texture->potWidth <<= 1;
- if (texture->potHeight < t.height) texture->potHeight <<= 1;
- texture->wScale = float(t.width) / texture->potWidth;
- texture->hScale = float(t.height) / texture->potHeight;
- } else {
- texture->potWidth = t.width;
- texture->potHeight = t.height;
- }
-
- Rect bounds(dirty.bounds());
- GLvoid* data = 0;
- if (texture->width != t.width || texture->height != t.height) {
- texture->width = t.width;
- texture->height = t.height;
-
- // texture size changed, we need to create a new one
- bounds.set(Rect(t.width, t.height));
- if (t.width == texture->potWidth &&
- t.height == texture->potHeight) {
- // we can do it one pass
- data = t.data;
- }
-
- if (t.format == HAL_PIXEL_FORMAT_RGB_565) {
- glTexImage2D(GL_TEXTURE_2D, 0,
- GL_RGB, texture->potWidth, texture->potHeight, 0,
- GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data);
- } else if (t.format == HAL_PIXEL_FORMAT_RGBA_4444) {
- glTexImage2D(GL_TEXTURE_2D, 0,
- GL_RGBA, texture->potWidth, texture->potHeight, 0,
- GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, data);
- } else if (t.format == HAL_PIXEL_FORMAT_RGBA_8888 ||
- t.format == HAL_PIXEL_FORMAT_RGBX_8888) {
- glTexImage2D(GL_TEXTURE_2D, 0,
- GL_RGBA, texture->potWidth, texture->potHeight, 0,
- GL_RGBA, GL_UNSIGNED_BYTE, data);
- } else if (isSupportedYuvFormat(t.format)) {
- // just show the Y plane of YUV buffers
- glTexImage2D(GL_TEXTURE_2D, 0,
- GL_LUMINANCE, texture->potWidth, texture->potHeight, 0,
- GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
- } else {
- // oops, we don't handle this format!
- LOGE("layer %p, texture=%d, using format %d, which is not "
- "supported by the GL", this, texture->name, t.format);
- }
- }
- if (!data) {
- if (t.format == HAL_PIXEL_FORMAT_RGB_565) {
- glTexSubImage2D(GL_TEXTURE_2D, 0,
- 0, bounds.top, t.width, bounds.height(),
- GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
- t.data + bounds.top*t.stride*2);
- } else if (t.format == HAL_PIXEL_FORMAT_RGBA_4444) {
- glTexSubImage2D(GL_TEXTURE_2D, 0,
- 0, bounds.top, t.width, bounds.height(),
- GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4,
- t.data + bounds.top*t.stride*2);
- } else if (t.format == HAL_PIXEL_FORMAT_RGBA_8888 ||
- t.format == HAL_PIXEL_FORMAT_RGBX_8888) {
- glTexSubImage2D(GL_TEXTURE_2D, 0,
- 0, bounds.top, t.width, bounds.height(),
- GL_RGBA, GL_UNSIGNED_BYTE,
- t.data + bounds.top*t.stride*4);
- } else if (isSupportedYuvFormat(t.format)) {
- // just show the Y plane of YUV buffers
- glTexSubImage2D(GL_TEXTURE_2D, 0,
- 0, bounds.top, t.width, bounds.height(),
- GL_LUMINANCE, GL_UNSIGNED_BYTE,
- t.data + bounds.top*t.stride);
- }
- }
-}
-
-status_t LayerBase::initializeEglImage(
- const sp<GraphicBuffer>& buffer, Texture* texture)
-{
- status_t err = NO_ERROR;
-
- // we need to recreate the texture
- EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
-
- // free the previous image
- if (texture->image != EGL_NO_IMAGE_KHR) {
- eglDestroyImageKHR(dpy, texture->image);
- texture->image = EGL_NO_IMAGE_KHR;
- }
-
- // construct an EGL_NATIVE_BUFFER_ANDROID
- android_native_buffer_t* clientBuf = buffer->getNativeBuffer();
-
- // create the new EGLImageKHR
- const EGLint attrs[] = {
- EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
- EGL_NONE, EGL_NONE
- };
- texture->image = eglCreateImageKHR(
- dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
- (EGLClientBuffer)clientBuf, attrs);
-
- if (texture->image != EGL_NO_IMAGE_KHR) {
- glBindTexture(GL_TEXTURE_2D, texture->name);
- glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,
- (GLeglImageOES)texture->image);
- GLint error = glGetError();
- if (UNLIKELY(error != GL_NO_ERROR)) {
- LOGE("layer=%p, glEGLImageTargetTexture2DOES(%p) "
- "failed err=0x%04x",
- this, texture->image, error);
- err = INVALID_OPERATION;
- } else {
- // Everything went okay!
- texture->NPOTAdjust = false;
- texture->dirty = false;
- texture->width = clientBuf->width;
- texture->height = clientBuf->height;
- }
- } else {
- LOGE("layer=%p, eglCreateImageKHR() failed. err=0x%4x",
- this, eglGetError());
- err = INVALID_OPERATION;
- }
- return err;
+ const Layer::State& s(drawingState());
+ snprintf(buffer, SIZE,
+ "+ %s %p\n"
+ " "
+ "z=%9d, pos=(%4d,%4d), size=(%4d,%4d), "
+ "needsBlending=%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,
+ s.alpha, s.flags,
+ s.transform[0][0], s.transform[0][1],
+ s.transform[1][0], s.transform[1][1]);
+ result.append(buffer);
}
-
// ---------------------------------------------------------------------------
-int32_t LayerBaseClient::sIdentity = 0;
+int32_t LayerBaseClient::sIdentity = 1;
LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client, int32_t i)
- : LayerBase(flinger, display), lcblk(NULL), client(client), mIndex(i),
+ : LayerBase(flinger, display), client(client), mIndex(i),
mIdentity(uint32_t(android_atomic_inc(&sIdentity)))
{
- lcblk = new SharedBufferServer(
- client->ctrlblk, i, NUM_BUFFERS,
- mIdentity);
}
void LayerBaseClient::onFirstRef()
@@ -712,16 +520,15 @@ LayerBaseClient::~LayerBaseClient()
if (client != 0) {
client->free(mIndex);
}
- delete lcblk;
}
-int32_t LayerBaseClient::serverIndex() const
+ssize_t LayerBaseClient::serverIndex() const
{
sp<Client> client(this->client.promote());
if (client != 0) {
return (client->cid<<16)|mIndex;
}
- return 0xFFFF0000 | mIndex;
+ return ssize_t(0xFFFF0000 | mIndex);
}
sp<LayerBaseClient::Surface> LayerBaseClient::getSurface()
@@ -742,12 +549,19 @@ sp<LayerBaseClient::Surface> LayerBaseClient::createSurface() const
const_cast<LayerBaseClient *>(this));
}
-// called with SurfaceFlinger::mStateLock as soon as the layer is entered
-// in the purgatory list
-void LayerBaseClient::onRemoved()
+void LayerBaseClient::dump(String8& result, char* buffer, size_t SIZE) const
{
- // wake up the condition
- lcblk->setStatus(NO_INIT);
+ LayerBase::dump(result, buffer, SIZE);
+
+ sp<Client> client(this->client.promote());
+ snprintf(buffer, SIZE,
+ " name=%s\n"
+ " id=0x%08x, client=0x%08x, identity=%u\n",
+ getName().string(),
+ clientIndex(), client.get() ? client->cid : 0,
+ getIdentity());
+
+ result.append(buffer);
}
// ---------------------------------------------------------------------------
@@ -799,11 +613,17 @@ status_t LayerBaseClient::Surface::onTransact(
return BnSurface::onTransact(code, data, reply, flags);
}
-sp<GraphicBuffer> LayerBaseClient::Surface::requestBuffer(int index, int usage)
+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;
+}
+
status_t LayerBaseClient::Surface::registerBuffers(
const ISurface::BufferHeap& buffers)
{
diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h
index 62ec839..2e2f2df 100644
--- a/libs/surfaceflinger/LayerBase.h
+++ b/libs/surfaceflinger/LayerBase.h
@@ -29,7 +29,7 @@
#include <ui/Region.h>
#include <ui/Overlay.h>
-#include <surfaceflinger/ISurfaceFlingerClient.h>
+#include <surfaceflinger/ISurfaceComposerClient.h>
#include <private/surfaceflinger/SharedBufferStack.h>
#include <private/surfaceflinger/LayerState.h>
@@ -46,40 +46,15 @@ class Client;
class GraphicBuffer;
class GraphicPlane;
class SurfaceFlinger;
+class Texture;
// ---------------------------------------------------------------------------
class LayerBase : public RefBase
{
- // poor man's dynamic_cast below
- template<typename T>
- struct getTypeInfoOfAnyType {
- static uint32_t get() { return T::typeInfo; }
- };
-
- template<typename T>
- struct getTypeInfoOfAnyType<T*> {
- static uint32_t get() { return getTypeInfoOfAnyType<T>::get(); }
- };
-
public:
- static const uint32_t typeInfo;
- static const char* const typeID;
- virtual char const* getTypeID() const { return typeID; }
- virtual uint32_t getTypeInfo() const { return typeInfo; }
-
- template<typename T>
- static T dynamicCast(LayerBase* base) {
- uint32_t mostDerivedInfo = base->getTypeInfo();
- uint32_t castToInfo = getTypeInfoOfAnyType<T>::get();
- if ((mostDerivedInfo & castToInfo) == castToInfo)
- return static_cast<T>(base);
- return 0;
- }
+ LayerBase(SurfaceFlinger* flinger, DisplayID display);
-
- LayerBase(SurfaceFlinger* flinger, DisplayID display);
-
DisplayID dpy;
mutable bool contentDirty;
Region visibleRegionScreen;
@@ -125,6 +100,9 @@ public:
void invalidate();
+ virtual const char* getTypeId() const { return "LayerBase"; }
+ virtual ssize_t serverIndex() const { return -1; }
+
/**
* draw - performs some global clipping optimizations
* and calls onDraw().
@@ -199,9 +177,9 @@ public:
virtual bool needsDithering() const { return false; }
/**
- * transformed -- true is this surface needs a to be transformed
+ * needsLinearFiltering - true if this surface needs filtering
*/
- virtual bool transformed() const { return mTransformed; }
+ virtual bool needsFiltering() const { return mNeedsFiltering; }
/**
* isSecure - true if this surface is secure, that is if it prevents
@@ -217,7 +195,10 @@ public:
* current list */
virtual void onRemoved() { };
-
+ /** always call base class first */
+ virtual void dump(String8& result, char* scratch, size_t size) const;
+
+
enum { // flags for doTransaction()
eVisibleRegion = 0x00000002,
};
@@ -241,44 +222,18 @@ protected:
const GraphicPlane& graphicPlane(int dpy) const;
GraphicPlane& graphicPlane(int dpy);
- GLuint createTexture() const;
-
- struct Texture {
- Texture() : name(-1U), width(0), height(0),
- image(EGL_NO_IMAGE_KHR), transform(0),
- NPOTAdjust(false), dirty(true) { }
- GLuint name;
- GLuint width;
- GLuint height;
- GLuint potWidth;
- GLuint potHeight;
- GLfloat wScale;
- GLfloat hScale;
- EGLImageKHR image;
- uint32_t transform;
- bool NPOTAdjust;
- bool dirty;
- };
-
- void clearWithOpenGL(const Region& clip, GLclampx r, GLclampx g,
- GLclampx b, GLclampx alpha) const;
+ 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;
- void loadTexture(Texture* texture,
- const Region& dirty, const GGLSurface& t) const;
- status_t initializeEglImage(
- const sp<GraphicBuffer>& buffer, Texture* texture);
-
- bool isSupportedYuvFormat(int format) const;
sp<SurfaceFlinger> mFlinger;
uint32_t mFlags;
// cached during validateVisibility()
- bool mTransformed;
- bool mUseLinearFiltering;
+ bool mNeedsFiltering;
int32_t mOrientation;
- GLfixed mVertices[4][2];
+ GLfloat mVertices[4][2];
Rect mTransformedBounds;
int mLeft;
int mTop;
@@ -313,14 +268,6 @@ class LayerBaseClient : public LayerBase
{
public:
class Surface;
- static const uint32_t typeInfo;
- static const char* const typeID;
- virtual char const* getTypeID() const { return typeID; }
- virtual uint32_t getTypeInfo() const { return typeInfo; }
-
- // lcblk is (almost) only accessed from the main SF thread, in the places
- // where it's not, a reference to Client must be held
- SharedBufferServer* lcblk;
LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client, int32_t i);
@@ -331,14 +278,11 @@ public:
inline uint32_t getIdentity() const { return mIdentity; }
inline int32_t clientIndex() const { return mIndex; }
- int32_t serverIndex() const;
-
sp<Surface> getSurface();
virtual sp<Surface> createSurface() const;
-
- virtual void onRemoved();
-
+ virtual ssize_t serverIndex() const;
+ virtual const char* getTypeId() const { return "LayerBaseClient"; }
class Surface : public BnSurface
{
@@ -356,7 +300,10 @@ public:
sp<LayerBaseClient> getOwner() const;
private:
- virtual sp<GraphicBuffer> requestBuffer(int index, int usage);
+ virtual sp<GraphicBuffer> requestBuffer(int bufferIdx,
+ uint32_t w, uint32_t h, uint32_t format, uint32_t usage);
+ virtual status_t setBufferCount(int bufferCount);
+
virtual status_t registerBuffers(const ISurface::BufferHeap& buffers);
virtual void postBuffer(ssize_t offset);
virtual void unregisterBuffers();
@@ -373,8 +320,11 @@ public:
friend class Surface;
+protected:
+ virtual void dump(String8& result, char* scratch, size_t size) const;
+
private:
- int32_t mIndex;
+ int32_t mIndex;
mutable Mutex mLock;
mutable wp<Surface> mClientSurface;
// only read
diff --git a/libs/surfaceflinger/LayerBlur.cpp b/libs/surfaceflinger/LayerBlur.cpp
index 5fd7904..09c90e8 100644
--- a/libs/surfaceflinger/LayerBlur.cpp
+++ b/libs/surfaceflinger/LayerBlur.cpp
@@ -33,11 +33,6 @@
namespace android {
// ---------------------------------------------------------------------------
-const uint32_t LayerBlur::typeInfo = LayerBaseClient::typeInfo | 8;
-const char* const LayerBlur::typeID = "LayerBlur";
-
-// ---------------------------------------------------------------------------
-
LayerBlur::LayerBlur(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client, int32_t i)
: LayerBaseClient(flinger, display, client, i), mCacheDirty(true),
@@ -100,7 +95,9 @@ void LayerBlur::unlockPageFlip(const Transform& planeTransform, Region& outDirty
mCacheDirty = false;
} else {
if (!mAutoRefreshPending) {
- mFlinger->signalDelayedEvent(ms2ns(500));
+ mFlinger->postMessageAsync(
+ new MessageBase(MessageQueue::INVALIDATE),
+ ms2ns(500));
mAutoRefreshPending = true;
}
}
@@ -206,8 +203,8 @@ void LayerBlur::onDraw(const Region& clip) const
const State& s = drawingState();
if (UNLIKELY(s.alpha < 0xFF)) {
- const GGLfixed alpha = (s.alpha << 16)/255;
- glColor4x(0, 0, 0, alpha);
+ const GLfloat alpha = s.alpha * (1.0f/255.0f);
+ glColor4f(0, 0, 0, alpha);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
@@ -225,38 +222,20 @@ void LayerBlur::onDraw(const Region& clip) const
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- if (UNLIKELY(transformed()
- || !(mFlags & DisplayHardware::DRAW_TEXTURE_EXTENSION) )) {
- // This is a very rare scenario.
- glMatrixMode(GL_TEXTURE);
- glLoadIdentity();
- glScalef(mWidthScale, mHeightScale, 1);
- glTranslatef(-x, mYOffset - y, 0);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glVertexPointer(2, GL_FIXED, 0, mVertices);
- glTexCoordPointer(2, GL_FIXED, 0, mVertices);
- while (it != end) {
- const Rect& r = *it++;
- const GLint sy = fbHeight - (r.top + r.height());
- glScissor(r.left, sy, r.width(), r.height());
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
- }
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
- } else {
- // NOTE: this is marginally faster with the software gl, because
- // glReadPixels() reads the fb bottom-to-top, however we'll
- // skip all the jaccobian computations.
- Rect r;
- GLint crop[4] = { 0, 0, w, h };
- glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
- y = fbHeight - (y + h);
- while (it != end) {
- const Rect& r = *it++;
- const GLint sy = fbHeight - (r.top + r.height());
- glScissor(r.left, sy, r.width(), r.height());
- glDrawTexiOES(x, y, 0, w, h);
- }
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+ glScalef(mWidthScale, mHeightScale, 1);
+ glTranslatef(-x, mYOffset - y, 0);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glVertexPointer(2, GL_FLOAT, 0, mVertices);
+ glTexCoordPointer(2, GL_FLOAT, 0, mVertices);
+ while (it != end) {
+ const Rect& r = *it++;
+ const GLint sy = fbHeight - (r.top + r.height());
+ glScissor(r.left, sy, r.width(), r.height());
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
}
diff --git a/libs/surfaceflinger/LayerBlur.h b/libs/surfaceflinger/LayerBlur.h
index 5b63dec..380f587 100644
--- a/libs/surfaceflinger/LayerBlur.h
+++ b/libs/surfaceflinger/LayerBlur.h
@@ -31,11 +31,6 @@ namespace android {
class LayerBlur : public LayerBaseClient
{
public:
- static const uint32_t typeInfo;
- static const char* const typeID;
- virtual char const* getTypeID() const { return typeID; }
- virtual uint32_t getTypeInfo() const { return typeInfo; }
-
LayerBlur(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client, int32_t i);
virtual ~LayerBlur();
@@ -43,6 +38,7 @@ public:
virtual void onDraw(const Region& clip) const;
virtual bool needsBlending() const { return true; }
virtual bool isSecure() const { return false; }
+ virtual const char* getTypeId() const { return "LayerBlur"; }
virtual uint32_t doTransaction(uint32_t flags);
virtual void setVisibleRegion(const Region& visibleRegion);
diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp
index 5c21593..8a582da 100644
--- a/libs/surfaceflinger/LayerBuffer.cpp
+++ b/libs/surfaceflinger/LayerBuffer.cpp
@@ -39,8 +39,6 @@ namespace android {
// ---------------------------------------------------------------------------
-const uint32_t LayerBuffer::typeInfo = LayerBaseClient::typeInfo | 0x20;
-const char* const LayerBuffer::typeID = "LayerBuffer";
gralloc_module_t const* LayerBuffer::sGrallocModule = 0;
// ---------------------------------------------------------------------------
@@ -120,7 +118,7 @@ uint32_t LayerBuffer::doTransaction(uint32_t flags)
source->onTransaction(flags);
uint32_t res = LayerBase::doTransaction(flags);
// we always want filtering for these surfaces
- mUseLinearFiltering = !(mFlags & DisplayHardware::SLOW_CONFIG);
+ mNeedsFiltering = !(mFlags & DisplayHardware::SLOW_CONFIG);
return res;
}
@@ -145,14 +143,6 @@ void LayerBuffer::onDraw(const Region& clip) const
}
}
-bool LayerBuffer::transformed() const
-{
- sp<Source> source(getSource());
- if (LIKELY(source != 0))
- return source->transformed();
- return false;
-}
-
void LayerBuffer::serverDestroy()
{
sp<Source> source(clearSource());
@@ -321,16 +311,13 @@ void LayerBuffer::Source::postBuffer(ssize_t offset) {
}
void LayerBuffer::Source::unregisterBuffers() {
}
-bool LayerBuffer::Source::transformed() const {
- return mLayer.mTransformed;
-}
// ---------------------------------------------------------------------------
LayerBuffer::BufferSource::BufferSource(LayerBuffer& layer,
const ISurface::BufferHeap& buffers)
: Source(layer), mStatus(NO_ERROR), mBufferSize(0),
- mUseEGLImageDirectly(true)
+ mTextureManager(layer.mFlags)
{
if (buffers.heap == NULL) {
// this is allowed, but in this case, it is illegal to receive
@@ -444,11 +431,6 @@ void LayerBuffer::BufferSource::setBuffer(const sp<LayerBuffer::Buffer>& buffer)
mBuffer = buffer;
}
-bool LayerBuffer::BufferSource::transformed() const
-{
- return mBufferHeap.transform ? true : Source::transformed();
-}
-
void LayerBuffer::BufferSource::onDraw(const Region& clip) const
{
sp<Buffer> ourBuffer(getBuffer());
@@ -462,35 +444,10 @@ void LayerBuffer::BufferSource::onDraw(const Region& clip) const
NativeBuffer src(ourBuffer->getBuffer());
const Rect transformedBounds(mLayer.getTransformedBounds());
- if (UNLIKELY(mTexture.name == -1LU)) {
- mTexture.name = mLayer.createTexture();
- }
-
#if defined(EGL_ANDROID_image_native_buffer)
if (mLayer.mFlags & DisplayHardware::DIRECT_TEXTURE) {
err = INVALID_OPERATION;
if (ourBuffer->supportsCopybit()) {
-
- // there are constraints on buffers used by the GPU and these may not
- // be honored here. We need to change the API so the buffers
- // are allocated with gralloc. For now disable this code-path
-#if 0
- // First, try to use the buffer as an EGLImage directly
- if (mUseEGLImageDirectly) {
- // NOTE: Assume the buffer is allocated with the proper USAGE flags
-
- sp<GraphicBuffer> buffer = new GraphicBuffer(
- src.img.w, src.img.h, src.img.format,
- GraphicBuffer::USAGE_HW_TEXTURE,
- src.img.w, src.img.handle, false);
-
- err = mLayer.initializeEglImage(buffer, &mTexture);
- if (err != NO_ERROR) {
- mUseEGLImageDirectly = false;
- }
- }
-#endif
-
copybit_device_t* copybit = mLayer.mBlitEngine;
if (copybit && err != NO_ERROR) {
// create our EGLImageKHR the first time
@@ -527,7 +484,7 @@ void LayerBuffer::BufferSource::onDraw(const Region& clip) const
t.format = src.img.format;
t.data = (GGLubyte*)src.img.base;
const Region dirty(Rect(t.width, t.height));
- mLayer.loadTexture(&mTexture, dirty, t);
+ mTextureManager.loadTexture(&mTexture, dirty, t);
}
mTexture.transform = mBufferHeap.transform;
@@ -569,7 +526,7 @@ status_t LayerBuffer::BufferSource::initTempBuffer() const
// figure out if we need linear filtering
if (buffers.w * h == buffers.h * w) {
// same pixel area, don't use filtering
- mLayer.mUseLinearFiltering = false;
+ mLayer.mNeedsFiltering = false;
}
// Allocate a temporary buffer and create the corresponding EGLImageKHR
@@ -593,7 +550,8 @@ status_t LayerBuffer::BufferSource::initTempBuffer() const
dst.crop.r = w;
dst.crop.b = h;
- err = mLayer.initializeEglImage(buffer, &mTexture);
+ EGLDisplay dpy(mLayer.mFlinger->graphicPlane(0).getEGLDisplay());
+ err = mTextureManager.initEglImage(&mTexture, dpy, buffer);
}
return err;
@@ -609,7 +567,6 @@ void LayerBuffer::BufferSource::clearTempBufferImage() const
glDeleteTextures(1, &mTexture.name);
Texture defaultTexture;
mTexture = defaultTexture;
- mTexture.name = mLayer.createTexture();
}
// ---------------------------------------------------------------------------
@@ -665,9 +622,9 @@ LayerBuffer::OverlaySource::~OverlaySource()
void LayerBuffer::OverlaySource::onDraw(const Region& clip) const
{
// this would be where the color-key would be set, should we need it.
- GLclampx red = 0;
- GLclampx green = 0;
- GLclampx blue = 0;
+ GLclampf red = 0;
+ GLclampf green = 0;
+ GLclampf blue = 0;
mLayer.clearWithOpenGL(clip, red, green, blue, 0);
}
diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h
index b176623..d38dde2 100644
--- a/libs/surfaceflinger/LayerBuffer.h
+++ b/libs/surfaceflinger/LayerBuffer.h
@@ -21,6 +21,7 @@
#include <sys/types.h>
#include "LayerBase.h"
+#include "TextureManager.h"
struct copybit_device_t;
@@ -45,31 +46,25 @@ class LayerBuffer : public LayerBaseClient
virtual void onVisibilityResolved(const Transform& planeTransform);
virtual void postBuffer(ssize_t offset);
virtual void unregisterBuffers();
- virtual bool transformed() const;
virtual void destroy() { }
protected:
LayerBuffer& mLayer;
};
public:
- static const uint32_t typeInfo;
- static const char* const typeID;
- virtual char const* getTypeID() const { return typeID; }
- virtual uint32_t getTypeInfo() const { return typeInfo; }
-
LayerBuffer(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client, int32_t i);
virtual ~LayerBuffer();
virtual void onFirstRef();
virtual bool needsBlending() const;
+ virtual const char* getTypeId() const { return "LayerBuffer"; }
virtual sp<LayerBaseClient::Surface> createSurface() const;
virtual status_t ditch();
virtual void onDraw(const Region& clip) const;
virtual uint32_t doTransaction(uint32_t flags);
virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion);
- virtual bool transformed() const;
status_t registerBuffers(const ISurface::BufferHeap& buffers);
void postBuffer(ssize_t offset);
@@ -133,7 +128,6 @@ private:
virtual void onDraw(const Region& clip) const;
virtual void postBuffer(ssize_t offset);
virtual void unregisterBuffers();
- virtual bool transformed() const;
virtual void destroy() { }
private:
status_t initTempBuffer() const;
@@ -143,9 +137,9 @@ private:
status_t mStatus;
ISurface::BufferHeap mBufferHeap;
size_t mBufferSize;
- mutable LayerBase::Texture mTexture;
+ mutable Texture mTexture;
mutable NativeBuffer mTempBuffer;
- mutable bool mUseEGLImageDirectly;
+ mutable TextureManager mTextureManager;
};
class OverlaySource : public Source {
diff --git a/libs/surfaceflinger/LayerDim.cpp b/libs/surfaceflinger/LayerDim.cpp
index fd61e30..568fedb 100644
--- a/libs/surfaceflinger/LayerDim.cpp
+++ b/libs/surfaceflinger/LayerDim.cpp
@@ -30,9 +30,6 @@
namespace android {
// ---------------------------------------------------------------------------
-const uint32_t LayerDim::typeInfo = LayerBaseClient::typeInfo | 0x10;
-const char* const LayerDim::typeID = "LayerDim";
-
bool LayerDim::sUseTexture;
GLuint LayerDim::sTexId;
EGLImageKHR LayerDim::sImage;
diff --git a/libs/surfaceflinger/LayerDim.h b/libs/surfaceflinger/LayerDim.h
index d4672a1..19a9990 100644
--- a/libs/surfaceflinger/LayerDim.h
+++ b/libs/surfaceflinger/LayerDim.h
@@ -37,11 +37,6 @@ class LayerDim : public LayerBaseClient
static int32_t sWidth;
static int32_t sHeight;
public:
- static const uint32_t typeInfo;
- static const char* const typeID;
- virtual char const* getTypeID() const { return typeID; }
- virtual uint32_t getTypeInfo() const { return typeInfo; }
-
LayerDim(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client, int32_t i);
virtual ~LayerDim();
@@ -49,6 +44,7 @@ public:
virtual void onDraw(const Region& clip) const;
virtual bool needsBlending() const { return true; }
virtual bool isSecure() const { return false; }
+ virtual const char* getTypeId() const { return "LayerDim"; }
static void initDimmer(SurfaceFlinger* flinger, uint32_t w, uint32_t h);
};
diff --git a/libs/surfaceflinger/MessageQueue.cpp b/libs/surfaceflinger/MessageQueue.cpp
index b43d801..d668e88 100644
--- a/libs/surfaceflinger/MessageQueue.cpp
+++ b/libs/surfaceflinger/MessageQueue.cpp
@@ -60,9 +60,9 @@ MessageQueue::~MessageQueue()
{
}
-MessageList::value_type MessageQueue::waitMessage(nsecs_t timeout)
+sp<MessageBase> MessageQueue::waitMessage(nsecs_t timeout)
{
- MessageList::value_type result;
+ sp<MessageBase> result;
bool again;
do {
@@ -132,6 +132,7 @@ MessageList::value_type MessageQueue::waitMessage(nsecs_t timeout)
if (again) {
// the message has been processed. release our reference to it
// without holding the lock.
+ result->notify();
result = 0;
}
@@ -141,7 +142,7 @@ MessageList::value_type MessageQueue::waitMessage(nsecs_t timeout)
}
status_t MessageQueue::postMessage(
- const MessageList::value_type& message, nsecs_t relTime, uint32_t flags)
+ const sp<MessageBase>& message, nsecs_t relTime, uint32_t flags)
{
return queueMessage(message, relTime, flags);
}
@@ -154,7 +155,7 @@ status_t MessageQueue::invalidate() {
}
status_t MessageQueue::queueMessage(
- const MessageList::value_type& message, nsecs_t relTime, uint32_t flags)
+ const sp<MessageBase>& message, nsecs_t relTime, uint32_t flags)
{
Mutex::Autolock _l(mLock);
message->when = systemTime() + relTime;
@@ -167,13 +168,13 @@ status_t MessageQueue::queueMessage(
return NO_ERROR;
}
-void MessageQueue::dump(const MessageList::value_type& message)
+void MessageQueue::dump(const sp<MessageBase>& message)
{
Mutex::Autolock _l(mLock);
dumpLocked(message);
}
-void MessageQueue::dumpLocked(const MessageList::value_type& message)
+void MessageQueue::dumpLocked(const sp<MessageBase>& message)
{
LIST::const_iterator cur(mMessages.begin());
LIST::const_iterator end(mMessages.end());
diff --git a/libs/surfaceflinger/MessageQueue.h b/libs/surfaceflinger/MessageQueue.h
index dc8138d..890f809 100644
--- a/libs/surfaceflinger/MessageQueue.h
+++ b/libs/surfaceflinger/MessageQueue.h
@@ -25,6 +25,7 @@
#include <utils/Timers.h>
#include <utils/List.h>
+#include "Barrier.h"
namespace android {
@@ -37,7 +38,6 @@ class MessageList
List< sp<MessageBase> > mList;
typedef List< sp<MessageBase> > LIST;
public:
- typedef sp<MessageBase> value_type;
inline LIST::iterator begin() { return mList.begin(); }
inline LIST::const_iterator begin() const { return mList.begin(); }
inline LIST::iterator end() { return mList.end(); }
@@ -63,11 +63,19 @@ public:
// return true if message has a handler
virtual bool handler() { return false; }
+
+ // waits for the handler to be processed
+ void wait() const { barrier.wait(); }
+ // releases all waiters. this is done automatically if
+ // handler returns true
+ void notify() const { barrier.open(); }
+
protected:
virtual ~MessageBase() { }
private:
+ mutable Barrier barrier;
friend class LightRefBase<MessageBase>;
};
@@ -82,42 +90,33 @@ class MessageQueue
typedef List< sp<MessageBase> > LIST;
public:
- // this is a work-around the multichar constant warning. A macro would
- // work too, but would pollute the namespace.
- template <int a, int b, int c, int d>
- struct WHAT {
- static const uint32_t Value =
- (uint32_t(a&0xff)<<24)|(uint32_t(b&0xff)<<16)|
- (uint32_t(c&0xff)<<8)|uint32_t(d&0xff);
- };
-
MessageQueue();
~MessageQueue();
// pre-defined messages
enum {
- INVALIDATE = WHAT<'_','p','d','t'>::Value
+ INVALIDATE = '_upd'
};
- MessageList::value_type waitMessage(nsecs_t timeout = -1);
+ sp<MessageBase> waitMessage(nsecs_t timeout = -1);
- status_t postMessage(const MessageList::value_type& message,
+ status_t postMessage(const sp<MessageBase>& message,
nsecs_t reltime=0, uint32_t flags = 0);
-
+
status_t invalidate();
- void dump(const MessageList::value_type& message);
+ void dump(const sp<MessageBase>& message);
private:
- status_t queueMessage(const MessageList::value_type& message,
+ status_t queueMessage(const sp<MessageBase>& message,
nsecs_t reltime, uint32_t flags);
- void dumpLocked(const MessageList::value_type& message);
+ void dumpLocked(const sp<MessageBase>& message);
Mutex mLock;
Condition mCondition;
MessageList mMessages;
bool mInvalidate;
- MessageList::value_type mInvalidateMessage;
+ sp<MessageBase> mInvalidateMessage;
};
// ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index 0722fda..fff0853 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -206,8 +206,8 @@ void SurfaceFlinger::init()
property_get("debug.sf.showbackground", value, "0");
mDebugBackground = atoi(value);
- LOGI_IF(mDebugRegion, "showupdates enabled");
- LOGI_IF(mDebugBackground, "showbackground enabled");
+ LOGI_IF(mDebugRegion, "showupdates enabled");
+ LOGI_IF(mDebugBackground, "showbackground enabled");
}
SurfaceFlinger::~SurfaceFlinger()
@@ -225,7 +225,7 @@ sp<IMemoryHeap> SurfaceFlinger::getCblk() const
return mServerHeap;
}
-sp<ISurfaceFlingerClient> SurfaceFlinger::createConnection()
+sp<ISurfaceComposerClient> SurfaceFlinger::createConnection()
{
Mutex::Autolock _l(mStateLock);
uint32_t token = mTokens.acquire();
@@ -357,7 +357,6 @@ status_t SurfaceFlinger::readyToRun()
dcblk->ydpi = hw.getDpiY();
dcblk->fps = hw.getRefreshRate();
dcblk->density = hw.getDensity();
- asm volatile ("":::"memory");
// Initialize OpenGL|ES
glActiveTexture(GL_TEXTURE0);
@@ -427,7 +426,7 @@ void SurfaceFlinger::waitForEvent()
timeout = waitTime>0 ? waitTime : 0;
}
- MessageList::value_type msg = mEventQueue.waitMessage(timeout);
+ sp<MessageBase> msg = mEventQueue.waitMessage(timeout);
// see if we timed out
if (isFrozen()) {
@@ -462,9 +461,20 @@ void SurfaceFlinger::signal() const {
const_cast<SurfaceFlinger*>(this)->signalEvent();
}
-void SurfaceFlinger::signalDelayedEvent(nsecs_t delay)
+status_t SurfaceFlinger::postMessageAsync(const sp<MessageBase>& msg,
+ nsecs_t reltime, uint32_t flags)
{
- mEventQueue.postMessage( new MessageBase(MessageQueue::INVALIDATE), delay);
+ return mEventQueue.postMessage(msg, reltime, flags);
+}
+
+status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg,
+ nsecs_t reltime, uint32_t flags)
+{
+ status_t res = mEventQueue.postMessage(msg, reltime, flags);
+ if (res == NO_ERROR) {
+ msg->wait();
+ }
+ return res;
}
// ----------------------------------------------------------------------------
@@ -1079,15 +1089,15 @@ status_t SurfaceFlinger::invalidateLayerVisibility(const sp<LayerBase>& layer)
status_t SurfaceFlinger::addLayer_l(const sp<LayerBase>& layer)
{
- if (layer == 0)
- return BAD_VALUE;
ssize_t i = mCurrentState.layersSortedByZ.add(
layer, &LayerBase::compareCurrentStateZ);
- sp<LayerBaseClient> lbc = LayerBase::dynamicCast< LayerBaseClient* >(layer.get());
- if (lbc != 0) {
- mLayerMap.add(lbc->serverIndex(), lbc);
- }
- return NO_ERROR;
+ return (i < 0) ? status_t(i) : status_t(NO_ERROR);
+}
+
+status_t SurfaceFlinger::addClientLayer_l(const sp<LayerBaseClient>& lbc)
+{
+ ssize_t serverIndex = lbc->serverIndex();
+ return mLayerMap.add(serverIndex, lbc);
}
status_t SurfaceFlinger::removeLayer_l(const sp<LayerBase>& layerBase)
@@ -1095,10 +1105,9 @@ status_t SurfaceFlinger::removeLayer_l(const sp<LayerBase>& layerBase)
ssize_t index = mCurrentState.layersSortedByZ.remove(layerBase);
if (index >= 0) {
mLayersRemoved = true;
- sp<LayerBaseClient> layer =
- LayerBase::dynamicCast< LayerBaseClient* >(layerBase.get());
- if (layer != 0) {
- mLayerMap.removeItem(layer->serverIndex());
+ ssize_t serverIndex = layerBase->serverIndex();
+ if (serverIndex >= 0) {
+ mLayerMap.removeItem(serverIndex);
}
return NO_ERROR;
}
@@ -1137,15 +1146,11 @@ uint32_t SurfaceFlinger::getTransactionFlags(uint32_t flags)
return android_atomic_and(~flags, &mTransactionFlags) & flags;
}
-uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags, nsecs_t delay)
+uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags)
{
uint32_t old = android_atomic_or(flags, &mTransactionFlags);
if ((old & flags)==0) { // wake the server up
- if (delay > 0) {
- signalDelayedEvent(delay);
- } else {
- signalEvent();
- }
+ signalEvent();
}
return old;
}
@@ -1225,7 +1230,7 @@ int SurfaceFlinger::setOrientation(DisplayID dpy,
}
sp<ISurface> SurfaceFlinger::createSurface(ClientID clientId, int pid,
- const String8& name, ISurfaceFlingerClient::surface_data_t* params,
+ const String8& name, ISurfaceComposerClient::surface_data_t* params,
DisplayID d, uint32_t w, uint32_t h, PixelFormat format,
uint32_t flags)
{
@@ -1247,7 +1252,7 @@ sp<ISurface> SurfaceFlinger::createSurface(ClientID clientId, int pid,
//LOGD("createSurface for pid %d (%d x %d)", pid, w, h);
int32_t id = client->generateId(pid);
- if (uint32_t(id) >= NUM_LAYERS_MAX) {
+ if (uint32_t(id) >= SharedBufferStack::NUM_LAYERS_MAX) {
LOGE("createSurface() failed, generateId = %d", id);
return surfaceHandle;
}
@@ -1298,7 +1303,7 @@ sp<LayerBaseClient> SurfaceFlinger::createNormalSurfaceLocked(
format = PIXEL_FORMAT_RGBA_8888;
break;
case PIXEL_FORMAT_OPAQUE:
- format = PIXEL_FORMAT_RGB_565;
+ format = PIXEL_FORMAT_RGBX_8888;
break;
}
@@ -1307,6 +1312,7 @@ sp<LayerBaseClient> SurfaceFlinger::createNormalSurfaceLocked(
if (LIKELY(err == NO_ERROR)) {
layer->initStates(w, h, flags);
addLayer_l(layer);
+ addClientLayer_l(layer);
} else {
LOGE("createNormalSurfaceLocked() failed (%s)", strerror(-err));
layer.clear();
@@ -1321,6 +1327,7 @@ sp<LayerBaseClient> SurfaceFlinger::createBlurSurfaceLocked(
sp<LayerBlur> layer = new LayerBlur(this, display, client, id);
layer->initStates(w, h, flags);
addLayer_l(layer);
+ addClientLayer_l(layer);
return layer;
}
@@ -1331,6 +1338,7 @@ sp<LayerBaseClient> SurfaceFlinger::createDimSurfaceLocked(
sp<LayerDim> layer = new LayerDim(this, display, client, id);
layer->initStates(w, h, flags);
addLayer_l(layer);
+ addClientLayer_l(layer);
return layer;
}
@@ -1341,6 +1349,7 @@ sp<LayerBaseClient> SurfaceFlinger::createPushBuffersSurfaceLocked(
sp<LayerBuffer> layer = new LayerBuffer(this, display, client, id);
layer->initStates(w, h, flags);
addLayer_l(layer);
+ addClientLayer_l(layer);
return layer;
}
@@ -1397,7 +1406,7 @@ status_t SurfaceFlinger::destroySurface(const sp<LayerBaseClient>& layer)
}
};
- mEventQueue.postMessage( new MessageDestroySurface(this, layer) );
+ postMessageAsync( new MessageDestroySurface(this, layer) );
return NO_ERROR;
}
@@ -1512,83 +1521,17 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
result.append(buffer);
}
- size_t s = mClientsMap.size();
- char name[64];
- for (size_t i=0 ; i<s ; i++) {
- sp<Client> client = mClientsMap.valueAt(i);
- sprintf(name, " Client (id=0x%08x)", client->cid);
- client->dump(name);
- }
const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
const size_t count = currentLayers.size();
for (size_t i=0 ; i<count ; i++) {
- /*** LayerBase ***/
- const sp<LayerBase>& layer = currentLayers[i];
- const Layer::State& s = layer->drawingState();
- snprintf(buffer, SIZE,
- "+ %s %p\n"
- " "
- "z=%9d, pos=(%4d,%4d), size=(%4d,%4d), "
- "needsBlending=%1d, needsDithering=%1d, invalidate=%1d, "
- "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n",
- layer->getTypeID(), layer.get(),
- s.z, layer->tx(), layer->ty(), s.w, s.h,
- layer->needsBlending(), layer->needsDithering(),
- layer->contentDirty,
- s.alpha, s.flags,
- s.transform[0][0], s.transform[0][1],
- s.transform[1][0], s.transform[1][1]);
- result.append(buffer);
- buffer[0] = 0;
- /*** LayerBaseClient ***/
- sp<LayerBaseClient> lbc =
- LayerBase::dynamicCast< LayerBaseClient* >(layer.get());
- if (lbc != 0) {
- sp<Client> client(lbc->client.promote());
- snprintf(buffer, SIZE,
- " name=%s\n", lbc->getName().string());
- result.append(buffer);
- snprintf(buffer, SIZE,
- " id=0x%08x, client=0x%08x, identity=%u\n",
- lbc->clientIndex(), client.get() ? client->cid : 0,
- lbc->getIdentity());
-
- result.append(buffer);
- buffer[0] = 0;
- }
- /*** Layer ***/
- sp<Layer> l = LayerBase::dynamicCast< Layer* >(layer.get());
- if (l != 0) {
- SharedBufferStack::Statistics stats = l->lcblk->getStats();
- result.append( l->lcblk->dump(" ") );
- sp<const GraphicBuffer> buf0(l->getBuffer(0));
- sp<const GraphicBuffer> buf1(l->getBuffer(1));
- uint32_t w0=0, h0=0, s0=0;
- uint32_t w1=0, h1=0, s1=0;
- if (buf0 != 0) {
- w0 = buf0->getWidth();
- h0 = buf0->getHeight();
- s0 = buf0->getStride();
- }
- if (buf1 != 0) {
- w1 = buf1->getWidth();
- h1 = buf1->getHeight();
- s1 = buf1->getStride();
- }
- snprintf(buffer, SIZE,
- " "
- "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u],"
- " freezeLock=%p, dq-q-time=%u us\n",
- l->pixelFormat(),
- w0, h0, s0, w1, h1, s1,
- l->getFreezeLock().get(), stats.totalTime);
- result.append(buffer);
- buffer[0] = 0;
- }
+ const sp<LayerBase>& layer(currentLayers[i]);
+ layer->dump(result, buffer, SIZE);
+ const Layer::State& s(layer->drawingState());
s.transparentRegion.dump(result, "transparentRegion");
layer->transparentRegionScreen.dump(result, "transparentRegionScreen");
layer->visibleRegionScreen.dump(result, "visibleRegionScreen");
}
+
mWormholeRegion.dump(result, "WormholeRegion");
const DisplayHardware& hw(graphicPlane(0).displayHardware());
snprintf(buffer, SIZE,
@@ -1601,16 +1544,19 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
" last transaction time : %f us\n",
mLastSwapBufferTime/1000.0, mLastTransactionTime/1000.0);
result.append(buffer);
+
if (inSwapBuffersDuration || !locked) {
snprintf(buffer, SIZE, " eglSwapBuffers time: %f us\n",
inSwapBuffersDuration/1000.0);
result.append(buffer);
}
+
if (inTransactionDuration || !locked) {
snprintf(buffer, SIZE, " transaction time: %f us\n",
inTransactionDuration/1000.0);
result.append(buffer);
}
+
snprintf(buffer, SIZE, " client count: %d\n", mClientsMap.size());
result.append(buffer);
const GraphicBufferAllocator& alloc(GraphicBufferAllocator::get());
@@ -1733,7 +1679,7 @@ Client::~Client() {
int32_t Client::generateId(int pid)
{
const uint32_t i = clz( ~mBitmap );
- if (i >= NUM_LAYERS_MAX) {
+ if (i >= SharedBufferStack::NUM_LAYERS_MAX) {
return NO_MEMORY;
}
mPid = pid;
@@ -1760,7 +1706,8 @@ void Client::free(int32_t id)
}
bool Client::isValid(int32_t i) const {
- return (uint32_t(i)<NUM_LAYERS_MAX) && (mBitmap & (1<<(31-i)));
+ return (uint32_t(i)<SharedBufferStack::NUM_LAYERS_MAX) &&
+ (mBitmap & (1<<(31-i)));
}
sp<LayerBaseClient> Client::getLayerUser(int32_t i) const {
@@ -1773,10 +1720,6 @@ sp<LayerBaseClient> Client::getLayerUser(int32_t i) const {
return lbc;
}
-void Client::dump(const char* what)
-{
-}
-
// ---------------------------------------------------------------------------
#if 0
#pragma mark -
@@ -1797,7 +1740,7 @@ sp<IMemoryHeap> BClient::getControlBlock() const {
}
sp<ISurface> BClient::createSurface(
- ISurfaceFlingerClient::surface_data_t* params, int pid,
+ ISurfaceComposerClient::surface_data_t* params, int pid,
const String8& name,
DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
uint32_t flags)
diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h
index d75dc15..d8fe98c 100644
--- a/libs/surfaceflinger/SurfaceFlinger.h
+++ b/libs/surfaceflinger/SurfaceFlinger.h
@@ -32,7 +32,7 @@
#include <ui/PixelFormat.h>
#include <surfaceflinger/ISurfaceComposer.h>
-#include <surfaceflinger/ISurfaceFlingerClient.h>
+#include <surfaceflinger/ISurfaceComposerClient.h>
#include "Barrier.h"
#include "Layer.h"
@@ -73,7 +73,6 @@ public:
inline bool isValid(int32_t i) const;
sp<LayerBaseClient> getLayerUser(int32_t i) const;
- void dump(const char* what);
const Vector< wp<LayerBaseClient> >& getLayers() const {
return mLayers;
@@ -159,7 +158,7 @@ public:
virtual status_t dump(int fd, const Vector<String16>& args);
// ISurfaceComposer interface
- virtual sp<ISurfaceFlingerClient> createConnection();
+ virtual sp<ISurfaceComposerClient> createConnection();
virtual sp<IMemoryHeap> getCblk() const;
virtual void bootFinished();
virtual void openGlobalTransaction();
@@ -190,7 +189,7 @@ private:
friend class LayerDim;
sp<ISurface> createSurface(ClientID client, int pid, const String8& name,
- ISurfaceFlingerClient::surface_data_t* params,
+ ISurfaceComposerClient::surface_data_t* params,
DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
uint32_t flags);
@@ -256,8 +255,6 @@ private:
public: // hack to work around gcc 4.0.3 bug
void signalEvent();
private:
- void signalDelayedEvent(nsecs_t delay);
-
void handleConsoleEvents();
void handleTransaction(uint32_t transactionFlags);
void handleTransactionLocked(
@@ -281,12 +278,13 @@ private:
void destroyConnection(ClientID cid);
sp<LayerBaseClient> getLayerUser_l(SurfaceID index) const;
status_t addLayer_l(const sp<LayerBase>& layer);
+ status_t addClientLayer_l(const sp<LayerBaseClient>& lbc);
status_t removeLayer_l(const sp<LayerBase>& layer);
status_t purgatorizeLayer_l(const sp<LayerBase>& layer);
void free_resources_l();
uint32_t getTransactionFlags(uint32_t flags);
- uint32_t setTransactionFlags(uint32_t flags, nsecs_t delay = 0);
+ uint32_t setTransactionFlags(uint32_t flags);
void commitTransaction();
@@ -310,7 +308,12 @@ private:
mutable MessageQueue mEventQueue;
-
+
+ status_t postMessageAsync(const sp<MessageBase>& msg,
+ nsecs_t reltime=0, uint32_t flags = 0);
+
+ status_t postMessageSync(const sp<MessageBase>& msg,
+ nsecs_t reltime=0, uint32_t flags = 0);
// access must be protected by mStateLock
@@ -390,14 +393,14 @@ public:
// ---------------------------------------------------------------------------
-class BClient : public BnSurfaceFlingerClient
+class BClient : public BnSurfaceComposerClient
{
public:
BClient(SurfaceFlinger *flinger, ClientID cid,
const sp<IMemoryHeap>& cblk);
~BClient();
- // ISurfaceFlingerClient interface
+ // ISurfaceComposerClient interface
virtual sp<IMemoryHeap> getControlBlock() const;
virtual sp<ISurface> createSurface(
diff --git a/libs/surfaceflinger/TextureManager.cpp b/libs/surfaceflinger/TextureManager.cpp
new file mode 100644
index 0000000..ee2159b
--- /dev/null
+++ b/libs/surfaceflinger/TextureManager.cpp
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+#include <utils/Log.h>
+
+#include <ui/GraphicBuffer.h>
+
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
+#include <hardware/hardware.h>
+
+#include "clz.h"
+#include "DisplayHardware/DisplayHardware.h"
+#include "TextureManager.h"
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+TextureManager::TextureManager(uint32_t flags)
+ : mFlags(flags)
+{
+}
+
+GLuint TextureManager::createTexture()
+{
+ GLuint textureName = -1;
+ glGenTextures(1, &textureName);
+ glBindTexture(GL_TEXTURE_2D, textureName);
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ return textureName;
+}
+
+bool TextureManager::isSupportedYuvFormat(int format)
+{
+ switch (format) {
+ case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+ case HAL_PIXEL_FORMAT_YCbCr_422_P:
+ case HAL_PIXEL_FORMAT_YCbCr_420_P:
+ case HAL_PIXEL_FORMAT_YCbCr_422_I:
+ case HAL_PIXEL_FORMAT_YCbCr_420_I:
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ return true;
+ }
+ return false;
+}
+
+status_t TextureManager::initEglImage(Image* texture,
+ EGLDisplay dpy, const sp<GraphicBuffer>& buffer)
+{
+ status_t err = NO_ERROR;
+ if (!texture->dirty) return err;
+
+ // free the previous image
+ if (texture->image != EGL_NO_IMAGE_KHR) {
+ eglDestroyImageKHR(dpy, texture->image);
+ texture->image = EGL_NO_IMAGE_KHR;
+ }
+
+ // construct an EGL_NATIVE_BUFFER_ANDROID
+ android_native_buffer_t* clientBuf = buffer->getNativeBuffer();
+
+ // create the new EGLImageKHR
+ const EGLint attrs[] = {
+ EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
+ EGL_NONE, EGL_NONE
+ };
+ texture->image = eglCreateImageKHR(
+ dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
+ (EGLClientBuffer)clientBuf, attrs);
+
+ if (texture->image != EGL_NO_IMAGE_KHR) {
+ if (texture->name == -1UL) {
+ texture->name = createTexture();
+ texture->width = 0;
+ texture->height = 0;
+ }
+ glBindTexture(GL_TEXTURE_2D, texture->name);
+ glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,
+ (GLeglImageOES)texture->image);
+ GLint error = glGetError();
+ if (error != GL_NO_ERROR) {
+ LOGE("glEGLImageTargetTexture2DOES(%p) failed err=0x%04x",
+ texture->image, error);
+ err = INVALID_OPERATION;
+ } else {
+ // Everything went okay!
+ texture->dirty = false;
+ texture->width = clientBuf->width;
+ texture->height = clientBuf->height;
+ }
+ } else {
+ LOGE("eglCreateImageKHR() failed. err=0x%4x", eglGetError());
+ err = INVALID_OPERATION;
+ }
+ return err;
+}
+
+status_t TextureManager::loadTexture(Texture* texture,
+ const Region& dirty, const GGLSurface& t)
+{
+ if (texture->name == -1UL) {
+ texture->name = createTexture();
+ texture->width = 0;
+ texture->height = 0;
+ }
+
+ glBindTexture(GL_TEXTURE_2D, texture->name);
+
+ /*
+ * In OpenGL ES we can't specify a stride with glTexImage2D (however,
+ * GL_UNPACK_ALIGNMENT is a limited form of stride).
+ * So if the stride here isn't representable with GL_UNPACK_ALIGNMENT, we
+ * need to do something reasonable (here creating a bigger texture).
+ *
+ * extra pixels = (((stride - width) * pixelsize) / GL_UNPACK_ALIGNMENT);
+ *
+ * This situation doesn't happen often, but some h/w have a limitation
+ * for their framebuffer (eg: must be multiple of 8 pixels), and
+ * we need to take that into account when using these buffers as
+ * textures.
+ *
+ * This should never be a problem with POT textures
+ */
+
+ int unpack = __builtin_ctz(t.stride * bytesPerPixel(t.format));
+ unpack = 1 << ((unpack > 3) ? 3 : unpack);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, unpack);
+
+ /*
+ * round to POT if needed
+ */
+ if (!(mFlags & DisplayHardware::NPOT_EXTENSION)) {
+ texture->NPOTAdjust = true;
+ }
+
+ if (texture->NPOTAdjust) {
+ // find the smallest power-of-two that will accommodate our surface
+ texture->potWidth = 1 << (31 - clz(t.width));
+ texture->potHeight = 1 << (31 - clz(t.height));
+ if (texture->potWidth < t.width) texture->potWidth <<= 1;
+ if (texture->potHeight < t.height) texture->potHeight <<= 1;
+ texture->wScale = float(t.width) / texture->potWidth;
+ texture->hScale = float(t.height) / texture->potHeight;
+ } else {
+ texture->potWidth = t.width;
+ texture->potHeight = t.height;
+ }
+
+ Rect bounds(dirty.bounds());
+ GLvoid* data = 0;
+ if (texture->width != t.width || texture->height != t.height) {
+ texture->width = t.width;
+ texture->height = t.height;
+
+ // texture size changed, we need to create a new one
+ bounds.set(Rect(t.width, t.height));
+ if (t.width == texture->potWidth &&
+ t.height == texture->potHeight) {
+ // we can do it one pass
+ data = t.data;
+ }
+
+ if (t.format == HAL_PIXEL_FORMAT_RGB_565) {
+ glTexImage2D(GL_TEXTURE_2D, 0,
+ GL_RGB, texture->potWidth, texture->potHeight, 0,
+ GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data);
+ } else if (t.format == HAL_PIXEL_FORMAT_RGBA_4444) {
+ glTexImage2D(GL_TEXTURE_2D, 0,
+ GL_RGBA, texture->potWidth, texture->potHeight, 0,
+ GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, data);
+ } else if (t.format == HAL_PIXEL_FORMAT_RGBA_8888 ||
+ t.format == HAL_PIXEL_FORMAT_RGBX_8888) {
+ glTexImage2D(GL_TEXTURE_2D, 0,
+ GL_RGBA, texture->potWidth, texture->potHeight, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, data);
+ } else if (isSupportedYuvFormat(t.format)) {
+ // just show the Y plane of YUV buffers
+ glTexImage2D(GL_TEXTURE_2D, 0,
+ GL_LUMINANCE, texture->potWidth, texture->potHeight, 0,
+ GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
+ } else {
+ // oops, we don't handle this format!
+ LOGE("texture=%d, using format %d, which is not "
+ "supported by the GL", texture->name, t.format);
+ }
+ }
+ if (!data) {
+ if (t.format == HAL_PIXEL_FORMAT_RGB_565) {
+ glTexSubImage2D(GL_TEXTURE_2D, 0,
+ 0, bounds.top, t.width, bounds.height(),
+ GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
+ t.data + bounds.top*t.stride*2);
+ } else if (t.format == HAL_PIXEL_FORMAT_RGBA_4444) {
+ glTexSubImage2D(GL_TEXTURE_2D, 0,
+ 0, bounds.top, t.width, bounds.height(),
+ GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4,
+ t.data + bounds.top*t.stride*2);
+ } else if (t.format == HAL_PIXEL_FORMAT_RGBA_8888 ||
+ t.format == HAL_PIXEL_FORMAT_RGBX_8888) {
+ glTexSubImage2D(GL_TEXTURE_2D, 0,
+ 0, bounds.top, t.width, bounds.height(),
+ GL_RGBA, GL_UNSIGNED_BYTE,
+ t.data + bounds.top*t.stride*4);
+ } else if (isSupportedYuvFormat(t.format)) {
+ // just show the Y plane of YUV buffers
+ glTexSubImage2D(GL_TEXTURE_2D, 0,
+ 0, bounds.top, t.width, bounds.height(),
+ GL_LUMINANCE, GL_UNSIGNED_BYTE,
+ t.data + bounds.top*t.stride);
+ }
+ }
+ return NO_ERROR;
+}
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/libs/surfaceflinger/TextureManager.h b/libs/surfaceflinger/TextureManager.h
new file mode 100644
index 0000000..d0acfe9
--- /dev/null
+++ b/libs/surfaceflinger/TextureManager.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2010 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_TEXTURE_MANAGER_H
+#define ANDROID_TEXTURE_MANAGER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES/gl.h>
+
+#include <ui/Region.h>
+
+#include <pixelflinger/pixelflinger.h>
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+class GraphicBuffer;
+
+// ---------------------------------------------------------------------------
+
+struct Image {
+ Image() : name(-1U), image(EGL_NO_IMAGE_KHR), width(0), height(0),
+ transform(0), dirty(true) { }
+ GLuint name;
+ EGLImageKHR image;
+ GLuint width;
+ GLuint height;
+ uint32_t transform;
+ bool dirty;
+};
+
+struct Texture : public Image {
+ Texture() : Image(), NPOTAdjust(false) { }
+ GLuint potWidth;
+ GLuint potHeight;
+ GLfloat wScale;
+ GLfloat hScale;
+ bool NPOTAdjust;
+};
+
+// ---------------------------------------------------------------------------
+
+class TextureManager {
+ uint32_t mFlags;
+ GLuint createTexture();
+ static bool isSupportedYuvFormat(int format);
+public:
+
+ TextureManager(uint32_t flags);
+
+ // load bitmap data into the active buffer
+ status_t loadTexture(Texture* texture,
+ const Region& dirty, const GGLSurface& t);
+
+ // make active buffer an EGLImage if needed
+ status_t initEglImage(Image* texture,
+ EGLDisplay dpy, const sp<GraphicBuffer>& buffer);
+};
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_TEXTURE_MANAGER_H
diff --git a/libs/surfaceflinger/Transform.cpp b/libs/surfaceflinger/Transform.cpp
index 175f989..5e27cc9 100644
--- a/libs/surfaceflinger/Transform.cpp
+++ b/libs/surfaceflinger/Transform.cpp
@@ -229,14 +229,13 @@ Transform::vec3 Transform::transform(const vec3& v) const {
return r;
}
-void Transform::transform(fixed1616* point, int x, int y) const
+void Transform::transform(float* point, int x, int y) const
{
- const float toFixed = 65536.0f;
const mat33& M(mMatrix);
vec2 v(x, y);
v = transform(v);
- point[0] = v[0] * toFixed;
- point[1] = v[1] * toFixed;
+ point[0] = v[0];
+ point[1] = v[1];
}
Rect Transform::makeBounds(int w, int h) const
diff --git a/libs/surfaceflinger/Transform.h b/libs/surfaceflinger/Transform.h
index 2e5b893..20fa11a 100644
--- a/libs/surfaceflinger/Transform.h
+++ b/libs/surfaceflinger/Transform.h
@@ -37,8 +37,6 @@ public:
explicit Transform(uint32_t orientation);
~Transform();
- typedef int32_t fixed1616;
-
// FIXME: must match OVERLAY_TRANSFORM_*, pull from hardware.h
enum orientation_flags {
ROT_0 = 0x00000000,
@@ -76,7 +74,7 @@ public:
// transform data
Rect makeBounds(int w, int h) const;
- void transform(fixed1616* point, int x, int y) const;
+ void transform(float* point, int x, int y) const;
Region transform(const Region& reg) const;
Transform operator * (const Transform& rhs) const;