summaryrefslogtreecommitdiffstats
path: root/services/surfaceflinger
diff options
context:
space:
mode:
authorMathias Agopian <mathias@google.com>2012-09-13 18:17:13 -0700
committerMathias Agopian <mathias@google.com>2012-09-17 18:57:53 -0700
commitda27af9832a0170f1fc40ef3f21371c4d30d21b3 (patch)
treee4d80c394a30865c2196581ee5b23820bbcd3c41 /services/surfaceflinger
parentcde87a3b9d3f8dc15232d927b56ee9e5e520f58d (diff)
downloadframeworks_native-da27af9832a0170f1fc40ef3f21371c4d30d21b3.zip
frameworks_native-da27af9832a0170f1fc40ef3f21371c4d30d21b3.tar.gz
frameworks_native-da27af9832a0170f1fc40ef3f21371c4d30d21b3.tar.bz2
add support hwc 1.1
Bug: 7124069 Change-Id: I53d705105c4ad8954d3f50ee4f4c8b7ec936b871
Diffstat (limited to 'services/surfaceflinger')
-rw-r--r--services/surfaceflinger/DisplayDevice.cpp26
-rw-r--r--services/surfaceflinger/DisplayDevice.h5
-rw-r--r--services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp39
-rw-r--r--services/surfaceflinger/DisplayHardware/FramebufferSurface.h16
-rw-r--r--services/surfaceflinger/DisplayHardware/HWComposer.cpp209
-rw-r--r--services/surfaceflinger/DisplayHardware/HWComposer.h20
-rw-r--r--services/surfaceflinger/Layer.cpp4
-rw-r--r--services/surfaceflinger/Layer.h1
-rw-r--r--services/surfaceflinger/LayerBase.cpp5
-rw-r--r--services/surfaceflinger/LayerBase.h5
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp42
11 files changed, 283 insertions, 89 deletions
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 2c06a0b..72f73f7 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -183,6 +183,32 @@ void DisplayDevice::flip(const Region& dirty) const
mPageFlipCount++;
}
+void DisplayDevice::swapBuffers(HWComposer& hwc) const {
+ if (hwc.initCheck() != NO_ERROR) {
+ // no HWC, we call eglSwapBuffers()
+ eglSwapBuffers(mDisplay, mSurface);
+ } else {
+ if (hwc.hasGlesComposition(mType)) {
+ if (hwc.supportsFramebufferTarget() ||
+ mType >= DisplayDevice::DISPLAY_VIRTUAL) {
+ // as of hwc 1.1 we always call eglSwapBuffers, however,
+ // on older versions of HWC, we need to call it only on
+ // virtual displays
+ eglSwapBuffers(mDisplay, mSurface);
+ }
+ }
+ }
+}
+
+void DisplayDevice::onSwapBuffersCompleted(HWComposer& hwc) const {
+ if (hwc.initCheck() == NO_ERROR) {
+ if (hwc.supportsFramebufferTarget()) {
+ int fd = hwc.getAndResetReleaseFenceFd(mType);
+ mFramebufferSurface->setReleaseFenceFd(fd);
+ }
+ }
+}
+
uint32_t DisplayDevice::getFlags() const
{
return mFlags;
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 8122b9d..4a3f0a0 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -40,6 +40,7 @@ class DisplayInfo;
class FramebufferSurface;
class LayerBase;
class SurfaceFlinger;
+class HWComposer;
class DisplayDevice : public LightRefBase<DisplayDevice>
{
@@ -106,8 +107,12 @@ public:
int32_t getHwcDisplayId() const { return mHwcDisplayId; }
const wp<IBinder>& getDisplayToken() const { return mDisplayToken; }
+ void swapBuffers(HWComposer& hwc) const;
status_t compositionComplete() const;
+ // called after h/w composer has completed its set() call
+ void onSwapBuffersCompleted(HWComposer& hwc) const;
+
Rect getBounds() const {
return Rect(mDisplayWidth, mDisplayHeight);
}
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 92a3fcc..a4f8fb6 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -74,15 +74,13 @@ FramebufferSurface::FramebufferSurface(HWComposer& hwc) :
mBufferQueue->setDefaultMaxBufferCount(NUM_FRAME_BUFFERS);
}
-status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>* buffer) {
+status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence) {
Mutex::Autolock lock(mMutex);
BufferQueue::BufferItem item;
status_t err = acquireBufferLocked(&item);
if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
- if (buffer != NULL) {
- *buffer = mCurrentBuffer;
- }
+ outBuffer = mCurrentBuffer;
return NO_ERROR;
} else if (err != NO_ERROR) {
ALOGE("error acquiring buffer: %s (%d)", strerror(-err), err);
@@ -107,32 +105,24 @@ status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>* buffer) {
return err;
}
}
-
mCurrentBufferSlot = item.mBuf;
mCurrentBuffer = mSlots[mCurrentBufferSlot].mGraphicBuffer;
- if (item.mFence != NULL) {
- item.mFence->wait(Fence::TIMEOUT_NEVER);
- }
-
- if (buffer != NULL) {
- *buffer = mCurrentBuffer;
- }
-
+ outFence = item.mFence;
+ outBuffer = mCurrentBuffer;
return NO_ERROR;
}
// Overrides ConsumerBase::onFrameAvailable(), does not call base class impl.
void FramebufferSurface::onFrameAvailable() {
- // XXX: The following code is here temporarily as part of the transition
- // away from the framebuffer HAL.
sp<GraphicBuffer> buf;
- status_t err = nextBuffer(&buf);
+ sp<Fence> acquireFence;
+ status_t err = nextBuffer(buf, acquireFence);
if (err != NO_ERROR) {
- ALOGE("error latching next FramebufferSurface buffer: %s (%d)",
+ ALOGE("error latching nnext FramebufferSurface buffer: %s (%d)",
strerror(-err), err);
return;
}
- err = mHwc.fbPost(buf->handle);
+ err = mHwc.fbPost(0, acquireFence, buf); // FIXME: use real display id
if (err != NO_ERROR) {
ALOGE("error posting framebuffer: %d", err);
}
@@ -145,6 +135,19 @@ void FramebufferSurface::freeBufferLocked(int slotIndex) {
}
}
+status_t FramebufferSurface::setReleaseFenceFd(int fenceFd) {
+ status_t err = NO_ERROR;
+ if (fenceFd >= 0) {
+ sp<Fence> fence(new Fence(fenceFd));
+ if (mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT) {
+ status_t err = addReleaseFence(mCurrentBufferSlot, fence);
+ ALOGE_IF(err, "setReleaseFenceFd: failed to add the fence: %s (%d)",
+ strerror(-err), err);
+ }
+ }
+ return err;
+}
+
status_t FramebufferSurface::setUpdateRectangle(const Rect& r)
{
return INVALID_OPERATION;
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index fd7c520..717a3f1 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -44,10 +44,13 @@ public:
virtual void dump(String8& result);
- // nextBuffer waits for and then latches the next buffer from the
- // BufferQueue and releases the previously latched buffer to the
- // BufferQueue. The new buffer is returned in the 'buffer' argument.
- status_t nextBuffer(sp<GraphicBuffer>* buffer);
+ // setReleaseFenceFd stores a fence file descriptor that will signal when the
+ // current buffer is no longer being read. This fence will be returned to
+ // the producer when the current buffer is released by updateTexImage().
+ // Multiple fences can be set for a given buffer; they will be merged into
+ // a single union fence. The SurfaceTexture will close the file descriptor
+ // when finished with it.
+ status_t setReleaseFenceFd(int fenceFd);
private:
virtual ~FramebufferSurface() { }; // this class cannot be overloaded
@@ -55,6 +58,11 @@ private:
virtual void onFrameAvailable();
virtual void freeBufferLocked(int slotIndex);
+ // nextBuffer waits for and then latches the next buffer from the
+ // BufferQueue and releases the previously latched buffer to the
+ // BufferQueue. The new buffer is returned in the 'buffer' argument.
+ status_t nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence);
+
// mCurrentBufferIndex is the slot index of the current buffer or
// INVALID_BUFFER_SLOT to indicate that either there is no current buffer
// or the buffer is not associated with a slot.
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 81640af..9c04fc0 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -26,6 +26,7 @@
#include <sys/types.h>
#include <utils/Errors.h>
+#include <utils/misc.h>
#include <utils/String8.h>
#include <utils/Thread.h>
#include <utils/Trace.h>
@@ -43,6 +44,7 @@
#include "LayerBase.h"
#include "HWComposer.h"
#include "SurfaceFlinger.h"
+#include <utils/CallStack.h>
namespace android {
@@ -111,6 +113,14 @@ HWComposer::HWComposer(
loadFbHalModule();
loadHwcModule();
+ if (mFbDev && mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
+ // close FB HAL if we don't needed it.
+ // FIXME: this is temporary until we're not forced to open FB HAL
+ // before HWC.
+ framebuffer_close(mFbDev);
+ mFbDev = NULL;
+ }
+
// If we have no HWC, or a pre-1.1 HWC, an FB dev is mandatory.
if ((!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
&& !mFbDev) {
@@ -310,7 +320,7 @@ static const uint32_t DISPLAY_ATTRIBUTES[] = {
#define ANDROID_DENSITY_XHIGH 320
void HWComposer::queryDisplayProperties(int disp) {
- ALOG_ASSERT(mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1));
+ LOG_ALWAYS_FATAL_IF(!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1));
// use zero as default value for unspecified attributes
int32_t values[NUM_DISPLAY_ATTRIBUTES - 1];
@@ -319,7 +329,11 @@ void HWComposer::queryDisplayProperties(int disp) {
uint32_t config;
size_t numConfigs = 1;
status_t err = mHwc->getDisplayConfigs(mHwc, disp, &config, &numConfigs);
+ LOG_ALWAYS_FATAL_IF(err, "getDisplayAttributes failed (%s)", strerror(-err));
+
if (err == NO_ERROR) {
+ ALOGD("config=%d, numConfigs=%d, NUM_DISPLAY_ATTRIBUTES=%d",
+ config, numConfigs, NUM_DISPLAY_ATTRIBUTES);
mHwc->getDisplayAttributes(mHwc, disp, config, DISPLAY_ATTRIBUTES,
values);
}
@@ -343,8 +357,8 @@ void HWComposer::queryDisplayProperties(int disp) {
mDisplayData[disp].ydpi = values[i] / 1000.0f;
break;
default:
- ALOG_ASSERT(false, "unknown display attribute %#x",
- DISPLAY_ATTRIBUTES[i]);
+ ALOG_ASSERT(false, "unknown display attribute[%d] %#x",
+ i, DISPLAY_ATTRIBUTES[i]);
break;
}
}
@@ -439,13 +453,35 @@ status_t HWComposer::createWorkList(int32_t id, size_t numLayers) {
if (mHwc) {
DisplayData& disp(mDisplayData[id]);
+ if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
+ // we need space for the HWC_FRAMEBUFFER_TARGET
+ numLayers++;
+ }
if (disp.capacity < numLayers || disp.list == NULL) {
- const size_t size = sizeof(hwc_display_contents_1_t)
+ size_t size = sizeof(hwc_display_contents_1_t)
+ numLayers * sizeof(hwc_layer_1_t);
free(disp.list);
disp.list = (hwc_display_contents_1_t*)malloc(size);
disp.capacity = numLayers;
}
+ if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
+ disp.framebufferTarget = &disp.list->hwLayers[numLayers - 1];
+ memset(disp.framebufferTarget, 0, sizeof(hwc_layer_1_t));
+ const hwc_rect_t r = { 0, 0, disp.width, disp.height };
+ disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET;
+ disp.framebufferTarget->hints = 0;
+ disp.framebufferTarget->flags = 0;
+ disp.framebufferTarget->handle = disp.fbTargetHandle;
+ disp.framebufferTarget->transform = 0;
+ disp.framebufferTarget->blending = HWC_BLENDING_PREMULT;
+ disp.framebufferTarget->sourceCrop = r;
+ disp.framebufferTarget->displayFrame = r;
+ disp.framebufferTarget->visibleRegionScreen.numRects = 1;
+ disp.framebufferTarget->visibleRegionScreen.rects =
+ &disp.framebufferTarget->displayFrame;
+ disp.framebufferTarget->acquireFenceFd = -1;
+ disp.framebufferTarget->releaseFenceFd = -1;
+ }
disp.list->retireFenceFd = -1;
disp.list->flags = HWC_GEOMETRY_CHANGED;
disp.list->numHwLayers = numLayers;
@@ -453,9 +489,46 @@ status_t HWComposer::createWorkList(int32_t id, size_t numLayers) {
return NO_ERROR;
}
+status_t HWComposer::setFramebufferTarget(int32_t id,
+ const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buf) {
+ if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {
+ return BAD_INDEX;
+ }
+ DisplayData& disp(mDisplayData[id]);
+ if (!disp.framebufferTarget) {
+ // this should never happen, but apparently eglCreateWindowSurface()
+ // triggers a SurfaceTextureClient::queueBuffer() on some
+ // devices (!?) -- log and ignore.
+ ALOGE("HWComposer: framebufferTarget is null");
+ CallStack stack;
+ stack.update();
+ stack.dump("");
+ return NO_ERROR;
+ }
+
+ int acquireFenceFd = -1;
+ if (acquireFence != NULL) {
+ acquireFenceFd = acquireFence->dup();
+ }
+
+ // ALOGD("fbPost: handle=%p, fence=%d", buf->handle, acquireFenceFd);
+ disp.fbTargetHandle = buf->handle;
+ disp.framebufferTarget->handle = disp.fbTargetHandle;
+ disp.framebufferTarget->acquireFenceFd = acquireFenceFd;
+ return NO_ERROR;
+}
+
status_t HWComposer::prepare() {
for (size_t i=0 ; i<mNumDisplays ; i++) {
- mLists[i] = mDisplayData[i].list;
+ DisplayData& disp(mDisplayData[i]);
+ if (disp.framebufferTarget) {
+ // make sure to reset the type to HWC_FRAMEBUFFER_TARGET
+ // DO NOT reset the handle field to NULL, because it's possible
+ // that we have nothing to redraw (eg: eglSwapBuffers() not called)
+ // in which case, we should continue to use the same buffer.
+ disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET;
+ }
+ mLists[i] = disp.list;
if (mLists[i]) {
if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_2)) {
mLists[i]->outbuf = NULL;
@@ -472,6 +545,8 @@ status_t HWComposer::prepare() {
}
int err = mHwc->prepare(mHwc, mNumDisplays, mLists);
+ ALOGE_IF(err, "HWComposer: prepare failed (%s)", strerror(-err));
+
if (err == NO_ERROR) {
// here we're just making sure that "skip" layers are set
// to HWC_FRAMEBUFFER and we're also counting how many layers
@@ -483,6 +558,10 @@ status_t HWComposer::prepare() {
if (disp.list) {
for (size_t i=0 ; i<disp.list->numHwLayers ; i++) {
hwc_layer_1_t& l = disp.list->hwLayers[i];
+
+ //ALOGD("prepare: %d, type=%d, handle=%p",
+ // i, l.compositionType, l.handle);
+
if (l.flags & HWC_SKIP_LAYER) {
l.compositionType = HWC_FRAMEBUFFER;
}
@@ -511,6 +590,21 @@ bool HWComposer::hasGlesComposition(int32_t id) const {
return mDisplayData[id].hasFbComp;
}
+int HWComposer::getAndResetReleaseFenceFd(int32_t id) {
+ if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
+ return BAD_INDEX;
+
+ int fd = INVALID_OPERATION;
+ if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
+ const DisplayData& disp(mDisplayData[id]);
+ if (disp.framebufferTarget) {
+ fd = disp.framebufferTarget->releaseFenceFd;
+ disp.framebufferTarget->releaseFenceFd = -1;
+ }
+ }
+ return fd;
+}
+
status_t HWComposer::commit() {
int err = NO_ERROR;
if (mHwc) {
@@ -553,38 +647,43 @@ status_t HWComposer::acquire() const {
return NO_ERROR;
}
-size_t HWComposer::getNumLayers(int32_t id) const {
- if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {
- return 0;
- }
- return (mHwc && mDisplayData[id].list) ?
- mDisplayData[id].list->numHwLayers : 0;
-}
-
int HWComposer::getVisualID() const {
if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
- return HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
+ // FIXME: temporary hack until HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED
+ // is supported by the implementation. we can only be in this case
+ // if we have HWC 1.1
+ return HAL_PIXEL_FORMAT_RGBA_8888;
+ //return HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
} else {
return mFbDev->format;
}
}
-int HWComposer::fbPost(buffer_handle_t buffer) {
- if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) {
- return mFbDev->post(mFbDev, buffer);
+bool HWComposer::supportsFramebufferTarget() const {
+ return (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1));
+}
+
+int HWComposer::fbPost(int32_t id,
+ const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buffer) {
+ if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
+ return setFramebufferTarget(id, acquireFence, buffer);
+ } else {
+ if (acquireFence != NULL) {
+ acquireFence->wait(Fence::TIMEOUT_NEVER);
+ }
+ return mFbDev->post(mFbDev, buffer->handle);
}
- return NO_ERROR;
}
int HWComposer::fbCompositionComplete() {
- if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) {
- if (mFbDev->compositionComplete) {
- return mFbDev->compositionComplete(mFbDev);
- } else {
- return INVALID_OPERATION;
- }
+ if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
+ return NO_ERROR;
+
+ if (mFbDev->compositionComplete) {
+ return mFbDev->compositionComplete(mFbDev);
+ } else {
+ return INVALID_OPERATION;
}
- return NO_ERROR;
}
void HWComposer::fbDump(String8& result) {
@@ -596,7 +695,6 @@ void HWComposer::fbDump(String8& result) {
}
}
-
/*
* Helper template to implement a concrete HWCLayer
* This holds the pointer to the concrete hwc layer type
@@ -733,7 +831,22 @@ HWComposer::LayerListIterator HWComposer::begin(int32_t id) {
* returns an iterator on the end of the layer list
*/
HWComposer::LayerListIterator HWComposer::end(int32_t id) {
- return getLayerIterator(id, getNumLayers(id));
+ size_t numLayers = 0;
+ if (uint32_t(id) <= 31 && mAllocatedDisplayIDs.hasBit(id)) {
+ const DisplayData& disp(mDisplayData[id]);
+ if (mHwc && disp.list) {
+ numLayers = disp.list->numHwLayers;
+ if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
+ // with HWC 1.1, the last layer is always the HWC_FRAMEBUFFER_TARGET,
+ // which we ignore when iterating through the layer list.
+ ALOGE_IF(!numLayers, "mDisplayData[%d].list->numHwLayers is 0", id);
+ if (numLayers) {
+ numLayers--;
+ }
+ }
+ }
+ }
+ return getLayerIterator(id, numLayers);
}
void HWComposer::dump(String8& result, char* buffer, size_t SIZE,
@@ -747,27 +860,47 @@ void HWComposer::dump(String8& result, char* buffer, size_t SIZE,
result.appendFormat(" id=%d, numHwLayers=%u, flags=%08x\n",
i, disp.list->numHwLayers, disp.list->flags);
result.append(
- " type | handle | hints | flags | tr | blend | format | source crop | frame name \n"
- "----------+----------+----------+----------+----+-------+----------+---------------------------+--------------------------------\n");
- // " ________ | ________ | ________ | ________ | __ | _____ | ________ | [_____,_____,_____,_____] | [_____,_____,_____,_____]
+ " type | handle | hints | flags | tr | blend | format | source crop | frame name \n"
+ "------------+----------+----------+----------+----+-------+----------+---------------------------+--------------------------------\n");
+ // " __________ | ________ | ________ | ________ | __ | _____ | ________ | [_____,_____,_____,_____] | [_____,_____,_____,_____]
for (size_t i=0 ; i<disp.list->numHwLayers ; i++) {
const hwc_layer_1_t&l = disp.list->hwLayers[i];
- const sp<LayerBase> layer(visibleLayersSortedByZ[i]);
int32_t format = -1;
- if (layer->getLayer() != NULL) {
- const sp<GraphicBuffer>& buffer(
+ String8 name("unknown");
+ if (i < visibleLayersSortedByZ.size()) {
+ const sp<LayerBase>& layer(visibleLayersSortedByZ[i]);
+ if (layer->getLayer() != NULL) {
+ const sp<GraphicBuffer>& buffer(
layer->getLayer()->getActiveBuffer());
- if (buffer != NULL) {
- format = buffer->getPixelFormat();
+ if (buffer != NULL) {
+ format = buffer->getPixelFormat();
+ }
}
+ name = layer->getName();
+ }
+
+ int type = l.compositionType;
+ if (type == HWC_FRAMEBUFFER_TARGET) {
+ name = "HWC_FRAMEBUFFER_TARGET";
+ format = disp.format;
}
+
+ static char const* compositionTypeName[] = {
+ "GLES",
+ "HWC",
+ "BACKGROUND",
+ "FB TARGET",
+ "UNKNOWN"};
+ if (type >= NELEM(compositionTypeName))
+ type = NELEM(compositionTypeName) - 1;
+
result.appendFormat(
- " %8s | %08x | %08x | %08x | %02x | %05x | %08x | [%5d,%5d,%5d,%5d] | [%5d,%5d,%5d,%5d] %s\n",
- l.compositionType ? "OVERLAY" : "FB",
+ " %10s | %08x | %08x | %08x | %02x | %05x | %08x | [%5d,%5d,%5d,%5d] | [%5d,%5d,%5d,%5d] %s\n",
+ compositionTypeName[type],
intptr_t(l.handle), l.hints, l.flags, l.transform, l.blending, format,
l.sourceCrop.left, l.sourceCrop.top, l.sourceCrop.right, l.sourceCrop.bottom,
l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom,
- layer->getName().string());
+ name.string());
}
}
}
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index fe928c5..f253ecc 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -36,6 +36,7 @@ extern "C" int clock_nanosleep(clockid_t clock_id, int flags,
struct hwc_composer_device_1;
struct hwc_display_contents_1;
+struct hwc_layer_1;
struct hwc_procs;
struct framebuffer_device_t;
@@ -43,6 +44,7 @@ namespace android {
// ---------------------------------------------------------------------------
class GraphicBuffer;
+class Fence;
class LayerBase;
class Region;
class String8;
@@ -97,12 +99,18 @@ public:
// create a work list for numLayers layer. sets HWC_GEOMETRY_CHANGED.
status_t createWorkList(int32_t id, size_t numLayers);
+ bool supportsFramebufferTarget() const;
+
// does this display have layers handled by HWC
bool hasHwcComposition(int32_t id) const;
// does this display have layers handled by GLES
bool hasGlesComposition(int32_t id) const;
+ // get the releaseFence file descriptor for the given display
+ // the release fence is only valid after commit()
+ int getAndResetReleaseFenceFd(int32_t id);
+
// needed forward declarations
class LayerListIterator;
@@ -111,7 +119,7 @@ public:
int getVisualID() const;
// Forwarding to FB HAL for pre-HWC-1.1 code (see FramebufferSurface).
- int fbPost(buffer_handle_t buffer);
+ int fbPost(int32_t id, const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buf);
int fbCompositionComplete();
void fbDump(String8& result);
@@ -253,7 +261,6 @@ private:
void loadFbHalModule();
LayerListIterator getLayerIterator(int32_t id, size_t index);
- size_t getNumLayers(int32_t id) const;
struct cb_context;
@@ -269,10 +276,15 @@ private:
void queryDisplayProperties(int disp);
+ status_t setFramebufferTarget(int32_t id,
+ const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buf);
+
+
struct DisplayData {
DisplayData() : xdpi(0), ydpi(0), refresh(0),
hasFbComp(false), hasOvComp(false),
- capacity(0), list(NULL) { }
+ capacity(0), list(NULL),
+ framebufferTarget(NULL), fbTargetHandle(NULL) { }
~DisplayData() {
free(list);
}
@@ -286,6 +298,8 @@ private:
bool hasOvComp;
size_t capacity;
hwc_display_contents_1* list;
+ hwc_layer_1* framebufferTarget;
+ buffer_handle_t fbTargetHandle;
};
sp<SurfaceFlinger> mFlinger;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 6785ba8..569f6bb 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -523,6 +523,10 @@ void Layer::onPostComposition() {
}
}
+bool Layer::isVisible() const {
+ return LayerBaseClient::isVisible() && (mActiveBuffer != NULL);
+}
+
Region Layer::latchBuffer(bool& recomputeVisibleRegions)
{
ATRACE_CALL();
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index b839f8c..6f75d8c 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -82,6 +82,7 @@ public:
virtual void onRemoved();
virtual sp<Layer> getLayer() const { return const_cast<Layer*>(this); }
virtual void setName(const String8& name);
+ virtual bool isVisible() const;
// LayerBaseClient interface
virtual wp<IBinder> getSurfaceTextureBinder() const;
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index b61770c..99cb8f3 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -321,6 +321,11 @@ bool LayerBase::getFiltering() const
return mFiltering;
}
+bool LayerBase::isVisible() const {
+ const Layer::State& s(mDrawingState);
+ return !(s.flags & layer_state_t::eLayerHidden) && s.alpha;
+}
+
void LayerBase::draw(const sp<const DisplayDevice>& hw, const Region& clip) const
{
onDraw(hw, clip);
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index 7326f53..9994994 100644
--- a/services/surfaceflinger/LayerBase.h
+++ b/services/surfaceflinger/LayerBase.h
@@ -211,6 +211,11 @@ public:
*/
virtual bool isProtected() const { return false; }
+ /*
+ * isVisible - true if this layer is visibile, false otherwise
+ */
+ virtual bool isVisible() const;
+
/** called with the state lock when the surface is removed from the
* current list */
virtual void onRemoved() { }
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index f62f075..bdd8c67 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -245,15 +245,6 @@ status_t SurfaceFlinger::selectConfigForPixelFormat(
EGLConfig* const configs = new EGLConfig[numConfigs];
eglChooseConfig(dpy, attrs, configs, numConfigs, &n);
- if (format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
- // FIXME: temporary hack until HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED
- // is supported by the implementation. we can only be in this case
- // if we have HWC 1.1
- *outConfig = configs[0];
- delete [] configs;
- return NO_ERROR;
- }
-
for (int i=0 ; i<n ; i++) {
EGLint nativeVisualId = 0;
eglGetConfigAttrib(dpy, configs[i], EGL_NATIVE_VISUAL_ID, &nativeVisualId);
@@ -273,6 +264,7 @@ EGLConfig SurfaceFlinger::selectEGLConfig(EGLDisplay display, EGLint nativeVisua
EGLConfig config;
EGLint dummy;
status_t err;
+
EGLint attribs[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RED_SIZE, 8,
@@ -390,6 +382,9 @@ status_t SurfaceFlinger::readyToRun()
mEGLConfig = selectEGLConfig(mEGLDisplay, format);
mEGLContext = createGLContext(mEGLDisplay, mEGLConfig);
+ LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,
+ "couldn't create EGLContext");
+
// initialize our non-virtual displays
for (size_t i=0 ; i<DisplayDevice::NUM_DISPLAY_TYPES ; i++) {
mDefaultDisplays[i] = new BBinder();
@@ -725,10 +720,7 @@ void SurfaceFlinger::doDebugFlashRegions()
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
hw->compositionComplete();
- // FIXME
- if (hw->getDisplayType() >= DisplayDevice::DISPLAY_VIRTUAL) {
- eglSwapBuffers(mEGLDisplay, hw->getEGLSurface());
- }
+ hw->swapBuffers(getHwComposer());
}
}
}
@@ -885,6 +877,7 @@ void SurfaceFlinger::postFramebuffer()
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
sp<const DisplayDevice> hw(mDisplays[dpy]);
const Vector< sp<LayerBase> >& currentLayers(hw->getVisibleLayersSortedByZ());
+ hw->onSwapBuffersCompleted(hwc);
const size_t count = currentLayers.size();
int32_t id = hw->getHwcDisplayId();
if (id >=0 && hwc.initCheck() == NO_ERROR) {
@@ -1160,7 +1153,7 @@ void SurfaceFlinger::computeVisibleRegions(
// handle hidden surfaces by setting the visible region to empty
- if (CC_LIKELY(!(s.flags & layer_state_t::eLayerHidden) && s.alpha)) {
+ if (CC_LIKELY(layer->isVisible())) {
const bool translucent = !layer->isOpaque();
Rect bounds(layer->computeBounds());
visibleRegion.set(bounds);
@@ -1308,20 +1301,11 @@ void SurfaceFlinger::doDisplayComposition(const sp<const DisplayDevice>& hw,
doComposeSurfaces(hw, dirtyRegion);
- // FIXME: we need to call eglSwapBuffers() on displays that have
- // GL composition and only on those.
- // however, currently hwc.commit() already does that for the main
- // display (if there is a hwc) and never for the other ones
- if (hw->getDisplayType() >= DisplayDevice::DISPLAY_VIRTUAL ||
- getHwComposer().initCheck() != NO_ERROR) {
- // FIXME: EGL spec says:
- // "surface must be bound to the calling thread's current context,
- // for the current rendering API."
- eglSwapBuffers(mEGLDisplay, hw->getEGLSurface());
- }
-
// update the swap region and clear the dirty region
hw->swapRegion.orSelf(dirtyRegion);
+
+ // swap buffers (presentation)
+ hw->swapBuffers(getHwComposer());
}
void SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const Region& dirty)
@@ -1388,6 +1372,12 @@ void SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const
layer->draw(hw, clip);
break;
}
+ case HWC_FRAMEBUFFER_TARGET: {
+ // this should not happen as the iterator shouldn't
+ // let us get there.
+ ALOGW("HWC_FRAMEBUFFER_TARGET found in hwc list (index=%d)", i);
+ break;
+ }
}
}
layer->setAcquireFence(hw, *cur);