summaryrefslogtreecommitdiffstats
path: root/services/surfaceflinger/Layer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'services/surfaceflinger/Layer.cpp')
-rw-r--r--services/surfaceflinger/Layer.cpp113
1 files changed, 109 insertions, 4 deletions
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index a060d31..7be58c6 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -35,6 +35,7 @@
#include "Layer.h"
#include "SurfaceFlinger.h"
#include "DisplayHardware/DisplayHardware.h"
+#include "DisplayHardware/HWComposer.h"
#define DEBUG_RESIZE 0
@@ -170,7 +171,8 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h,
mReqHeight = h;
mSecure = (flags & ISurfaceComposer::eSecure) ? true : false;
- mNeedsBlending = (info.h_alpha - info.l_alpha) > 0;
+ mNeedsBlending = (info.h_alpha - info.l_alpha) > 0 &&
+ (flags & ISurfaceComposer::eOpaque) == 0;
// we use the red index
int displayRedSize = displayInfo.getSize(PixelFormatInfo::INDEX_RED);
@@ -181,6 +183,62 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h,
return NO_ERROR;
}
+void Layer::setGeometry(hwc_layer_t* hwcl)
+{
+ hwcl->compositionType = HWC_FRAMEBUFFER;
+ hwcl->hints = 0;
+ hwcl->flags = 0;
+ hwcl->transform = 0;
+ hwcl->blending = HWC_BLENDING_NONE;
+
+ // we can't do alpha-fade with the hwc HAL
+ const State& s(drawingState());
+ if (s.alpha < 0xFF) {
+ hwcl->flags = HWC_SKIP_LAYER;
+ return;
+ }
+
+ // we can only handle simple transformation
+ if (mOrientation & Transform::ROT_INVALID) {
+ hwcl->flags = HWC_SKIP_LAYER;
+ return;
+ }
+
+ hwcl->transform = mOrientation;
+
+ if (needsBlending()) {
+ hwcl->blending = mPremultipliedAlpha ?
+ HWC_BLENDING_PREMULT : HWC_BLENDING_COVERAGE;
+ }
+
+ hwcl->displayFrame.left = mTransformedBounds.left;
+ hwcl->displayFrame.top = mTransformedBounds.top;
+ hwcl->displayFrame.right = mTransformedBounds.right;
+ hwcl->displayFrame.bottom = mTransformedBounds.bottom;
+
+ hwcl->visibleRegionScreen.rects =
+ reinterpret_cast<hwc_rect_t const *>(
+ visibleRegionScreen.getArray(
+ &hwcl->visibleRegionScreen.numRects));
+}
+
+void Layer::setPerFrameData(hwc_layer_t* hwcl) {
+ sp<GraphicBuffer> buffer(mBufferManager.getActiveBuffer());
+ if (buffer == NULL) {
+ // this situation can happen if we ran out of memory for instance.
+ // not much we can do. continue to use whatever texture was bound
+ // to this context.
+ hwcl->handle = NULL;
+ return;
+ }
+ hwcl->handle = const_cast<native_handle_t*>(buffer->handle);
+ // TODO: set the crop value properly
+ hwcl->sourceCrop.left = 0;
+ hwcl->sourceCrop.top = 0;
+ hwcl->sourceCrop.right = buffer->width;
+ hwcl->sourceCrop.bottom = buffer->height;
+}
+
void Layer::reloadTexture(const Region& dirty)
{
sp<GraphicBuffer> buffer(mBufferManager.getActiveBuffer());
@@ -282,8 +340,10 @@ status_t Layer::setBufferCount(int bufferCount)
// NOTE: lcblk->resize() is protected by an internal lock
status_t err = lcblk->resize(bufferCount);
- if (err == NO_ERROR)
- mBufferManager.resize(bufferCount);
+ if (err == NO_ERROR) {
+ EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
+ mBufferManager.resize(bufferCount, mFlinger, dpy);
+ }
return err;
}
@@ -321,6 +381,7 @@ sp<GraphicBuffer> Layer::requestBuffer(int index,
Mutex::Autolock _l(mLock);
// zero means default
+ const bool fixedSize = reqWidth && reqHeight;
if (!reqFormat) reqFormat = mFormat;
if (!reqWidth) reqWidth = mWidth;
if (!reqHeight) reqHeight = mHeight;
@@ -334,6 +395,7 @@ sp<GraphicBuffer> Layer::requestBuffer(int index,
mReqWidth = reqWidth;
mReqHeight = reqHeight;
mReqFormat = reqFormat;
+ mFixedSize = fixedSize;
lcblk->reallocateAllExcept(index);
}
@@ -714,9 +776,52 @@ Layer::BufferManager::~BufferManager()
{
}
-status_t Layer::BufferManager::resize(size_t size)
+status_t Layer::BufferManager::resize(size_t size,
+ const sp<SurfaceFlinger>& flinger, EGLDisplay dpy)
{
Mutex::Autolock _l(mLock);
+
+ if (size < mNumBuffers) {
+ // Move the active texture into slot 0
+ BufferData activeBufferData = mBufferData[mActiveBuffer];
+ mBufferData[mActiveBuffer] = mBufferData[0];
+ mBufferData[0] = activeBufferData;
+ mActiveBuffer = 0;
+
+ // Free the buffers that are no longer needed.
+ for (size_t i = size; i < mNumBuffers; i++) {
+ mBufferData[i].buffer = 0;
+
+ // Create a message to destroy the textures on SurfaceFlinger's GL
+ // thread.
+ class MessageDestroyTexture : public MessageBase {
+ Image mTexture;
+ EGLDisplay mDpy;
+ public:
+ MessageDestroyTexture(const Image& texture, EGLDisplay dpy)
+ : mTexture(texture), mDpy(dpy) { }
+ virtual bool handler() {
+ status_t err = Layer::BufferManager::destroyTexture(
+ &mTexture, mDpy);
+ LOGE_IF(err<0, "error destroying texture: %d (%s)",
+ mTexture.name, strerror(-err));
+ return true; // XXX: err == 0; ????
+ }
+ };
+
+ MessageDestroyTexture *msg = new MessageDestroyTexture(
+ mBufferData[i].texture, dpy);
+
+ // Don't allow this texture to be cleaned up by
+ // BufferManager::destroy.
+ mBufferData[i].texture.name = -1U;
+ mBufferData[i].texture.image = EGL_NO_IMAGE_KHR;
+
+ // Post the message to the SurfaceFlinger object.
+ flinger->postMessageAsync(msg);
+ }
+ }
+
mNumBuffers = size;
return NO_ERROR;
}