summaryrefslogtreecommitdiffstats
path: root/services/surfaceflinger/DisplayHardware
diff options
context:
space:
mode:
Diffstat (limited to 'services/surfaceflinger/DisplayHardware')
-rw-r--r--services/surfaceflinger/DisplayHardware/DisplaySurface.h68
-rw-r--r--services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp67
-rw-r--r--services/surfaceflinger/DisplayHardware/FramebufferSurface.h26
-rw-r--r--services/surfaceflinger/DisplayHardware/GraphicBufferAlloc.cpp53
-rw-r--r--services/surfaceflinger/DisplayHardware/GraphicBufferAlloc.h44
-rw-r--r--services/surfaceflinger/DisplayHardware/HWComposer.cpp252
-rw-r--r--services/surfaceflinger/DisplayHardware/HWComposer.h45
-rw-r--r--services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp56
-rw-r--r--services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h55
9 files changed, 434 insertions, 232 deletions
diff --git a/services/surfaceflinger/DisplayHardware/DisplaySurface.h b/services/surfaceflinger/DisplayHardware/DisplaySurface.h
new file mode 100644
index 0000000..2eca3cb
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/DisplaySurface.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2013 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_SF_DISPLAY_SURFACE_H
+#define ANDROID_SF_DISPLAY_SURFACE_H
+
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <utils/StrongPointer.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+class IGraphicBufferProducer;
+class String8;
+
+class DisplaySurface : public virtual RefBase {
+public:
+ virtual sp<IGraphicBufferProducer> getIGraphicBufferProducer() const = 0;
+
+ // Should be called when composition rendering is complete for a frame (but
+ // eglSwapBuffers hasn't necessarily been called). Required by certain
+ // older drivers for synchronization.
+ // TODO: Remove this when we drop support for HWC 1.0.
+ virtual status_t compositionComplete() = 0;
+
+ // Inform the surface that GLES composition is complete for this frame, and
+ // the surface should make sure that HWComposer has the correct buffer for
+ // this frame. Some implementations may only push a new buffer to
+ // HWComposer if GLES composition took place, others need to push a new
+ // buffer on every frame.
+ //
+ // advanceFrame must be followed by a call to onFrameCommitted before
+ // advanceFrame may be called again.
+ virtual status_t advanceFrame() = 0;
+
+ // onFrameCommitted is called after the frame has been committed to the
+ // hardware composer. The surface collects the release fence for this
+ // frame's buffer.
+ virtual void onFrameCommitted() = 0;
+
+ virtual void dump(String8& result) const = 0;
+
+protected:
+ DisplaySurface() {}
+ virtual ~DisplaySurface() {}
+};
+
+// ---------------------------------------------------------------------------
+} // namespace android
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_SF_DISPLAY_SURFACE_H
+
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 6c86a53..54a3ce8 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -29,12 +29,12 @@
#include <EGL/egl.h>
#include <hardware/hardware.h>
-#include <gui/SurfaceTextureClient.h>
+#include <gui/Surface.h>
+#include <gui/GraphicBufferAlloc.h>
#include <ui/GraphicBuffer.h>
-#include "DisplayHardware/FramebufferSurface.h"
-#include "DisplayHardware/GraphicBufferAlloc.h"
-#include "DisplayHardware/HWComposer.h"
+#include "FramebufferSurface.h"
+#include "HWComposer.h"
#ifndef NUM_FRAMEBUFFER_SURFACE_BUFFERS
#define NUM_FRAMEBUFFER_SURFACE_BUFFERS (2)
@@ -68,6 +68,17 @@ FramebufferSurface::FramebufferSurface(HWComposer& hwc, int disp) :
mBufferQueue->setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS);
}
+sp<IGraphicBufferProducer> FramebufferSurface::getIGraphicBufferProducer() const {
+ return getBufferQueue();
+}
+
+status_t FramebufferSurface::advanceFrame() {
+ // Once we remove FB HAL support, we can call nextBuffer() from here
+ // instead of using onFrameAvailable(). No real benefit, except it'll be
+ // more like VirtualDisplaySurface.
+ return NO_ERROR;
+}
+
status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence) {
Mutex::Autolock lock(mMutex);
@@ -129,22 +140,14 @@ 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);
- }
+void FramebufferSurface::onFrameCommitted() {
+ sp<Fence> fence = mHwc.getAndResetReleaseFence(mDisplayType);
+ if (fence->isValid() &&
+ 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;
}
status_t FramebufferSurface::compositionComplete()
@@ -152,11 +155,33 @@ status_t FramebufferSurface::compositionComplete()
return mHwc.fbCompositionComplete();
}
-void FramebufferSurface::dump(String8& result) {
- mHwc.fbDump(result);
+// Since DisplaySurface and ConsumerBase both have a method with this
+// signature, results will vary based on the static pointer type the caller is
+// using:
+// void dump(FrameBufferSurface* fbs, String8& s) {
+// // calls FramebufferSurface::dump()
+// fbs->dump(s);
+//
+// // calls ConsumerBase::dump() since it is non-virtual
+// static_cast<ConsumerBase*>(fbs)->dump(s);
+//
+// // calls FramebufferSurface::dump() since it is virtual
+// static_cast<DisplaySurface*>(fbs)->dump(s);
+// }
+// To make sure that all of these end up doing the same thing, we just redirect
+// to ConsumerBase::dump() here. It will take the internal lock, and then call
+// virtual dumpLocked(), which is where the real work happens.
+void FramebufferSurface::dump(String8& result) const {
ConsumerBase::dump(result);
}
+void FramebufferSurface::dumpLocked(String8& result, const char* prefix,
+ char* buffer, size_t SIZE) const
+{
+ mHwc.fbDump(result);
+ ConsumerBase::dumpLocked(result, prefix, buffer, SIZE);
+}
+
// ----------------------------------------------------------------------------
}; // namespace android
// ----------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index 6336345..2fde789 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -22,6 +22,8 @@
#include <gui/ConsumerBase.h>
+#include "DisplaySurface.h"
+
// ---------------------------------------------------------------------------
namespace android {
// ---------------------------------------------------------------------------
@@ -32,23 +34,20 @@ class HWComposer;
// ---------------------------------------------------------------------------
-class FramebufferSurface : public ConsumerBase {
+class FramebufferSurface : public ConsumerBase,
+ public DisplaySurface {
public:
FramebufferSurface(HWComposer& hwc, int disp);
- bool isUpdateOnDemand() const { return false; }
- status_t setUpdateRectangle(const Rect& updateRect);
- status_t compositionComplete();
+ virtual sp<IGraphicBufferProducer> getIGraphicBufferProducer() const;
- virtual void dump(String8& result);
+ virtual status_t compositionComplete();
+ virtual status_t advanceFrame();
+ virtual void onFrameCommitted();
- // 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);
+ // Implementation of DisplaySurface::dump(). Note that ConsumerBase also
+ // has a non-virtual dump() with the same signature.
+ virtual void dump(String8& result) const;
private:
virtual ~FramebufferSurface() { }; // this class cannot be overloaded
@@ -56,6 +55,9 @@ private:
virtual void onFrameAvailable();
virtual void freeBufferLocked(int slotIndex);
+ virtual void dumpLocked(String8& result, const char* prefix,
+ char* buffer, size_t SIZE) const;
+
// 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.
diff --git a/services/surfaceflinger/DisplayHardware/GraphicBufferAlloc.cpp b/services/surfaceflinger/DisplayHardware/GraphicBufferAlloc.cpp
deleted file mode 100644
index 965ff01..0000000
--- a/services/surfaceflinger/DisplayHardware/GraphicBufferAlloc.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- **
- ** Copyright 2012 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 <cutils/log.h>
-
-#include <ui/GraphicBuffer.h>
-
-#include "DisplayHardware/GraphicBufferAlloc.h"
-
-// ----------------------------------------------------------------------------
-namespace android {
-// ----------------------------------------------------------------------------
-
-GraphicBufferAlloc::GraphicBufferAlloc() {
-}
-
-GraphicBufferAlloc::~GraphicBufferAlloc() {
-}
-
-sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h,
- PixelFormat format, uint32_t usage, status_t* error) {
- sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage));
- status_t err = graphicBuffer->initCheck();
- *error = err;
- if (err != 0 || graphicBuffer->handle == 0) {
- if (err == NO_MEMORY) {
- GraphicBuffer::dumpAllocationsToSystemLog();
- }
- ALOGE("GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d) "
- "failed (%s), handle=%p",
- w, h, strerror(-err), graphicBuffer->handle);
- return 0;
- }
- return graphicBuffer;
-}
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-// ----------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayHardware/GraphicBufferAlloc.h b/services/surfaceflinger/DisplayHardware/GraphicBufferAlloc.h
deleted file mode 100644
index b08750c..0000000
--- a/services/surfaceflinger/DisplayHardware/GraphicBufferAlloc.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2012 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_SF_GRAPHIC_BUFFER_ALLOC_H
-#define ANDROID_SF_GRAPHIC_BUFFER_ALLOC_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <gui/IGraphicBufferAlloc.h>
-#include <ui/PixelFormat.h>
-#include <utils/Errors.h>
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-class GraphicBuffer;
-
-class GraphicBufferAlloc : public BnGraphicBufferAlloc {
-public:
- GraphicBufferAlloc();
- virtual ~GraphicBufferAlloc();
- virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
- PixelFormat format, uint32_t usage, status_t* error);
-};
-
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_SF_GRAPHIC_BUFFER_ALLOC_H
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 068fdcd..a9afbe5 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -25,6 +25,7 @@
#include <string.h>
#include <sys/types.h>
+#include <utils/CallStack.h>
#include <utils/Errors.h>
#include <utils/misc.h>
#include <utils/String8.h>
@@ -37,19 +38,27 @@
#include <hardware/hardware.h>
#include <hardware/hwcomposer.h>
+#include <android/configuration.h>
+
#include <cutils/log.h>
#include <cutils/properties.h>
-#include "Layer.h" // needed only for debugging
-#include "LayerBase.h"
#include "HWComposer.h"
-#include "SurfaceFlinger.h"
-#include <utils/CallStack.h>
+
+#include "../Layer.h" // needed only for debugging
+#include "../SurfaceFlinger.h"
namespace android {
+// This is not a real HWC version. It's used for in-development features that
+// haven't been committed to a specific real HWC version.
+#define HWC_DEVICE_API_VERSION_1_EXP HARDWARE_DEVICE_API_VERSION_2(1, 0xFF, HWC_HEADER_VERSION)
+
#define MIN_HWC_HEADER_VERSION HWC_HEADER_VERSION
+#define NUM_PHYSICAL_DISPLAYS HWC_NUM_DISPLAY_TYPES
+#define VIRTUAL_DISPLAY_ID_BASE HWC_NUM_DISPLAY_TYPES
+
static uint32_t hwcApiVersion(const hwc_composer_device_1_t* hwc) {
uint32_t hwcVersion = hwc->common.version;
return hwcVersion & HARDWARE_API_VERSION_2_MAJ_MIN_MASK;
@@ -100,7 +109,7 @@ HWComposer::HWComposer(
bool needVSyncThread = true;
// Note: some devices may insist that the FB HAL be opened before HWC.
- loadFbHalModule();
+ int fberr = loadFbHalModule();
loadHwcModule();
if (mFbDev && mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
@@ -114,12 +123,13 @@ HWComposer::HWComposer(
// 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) {
- ALOGE("ERROR: failed to open framebuffer, aborting");
+ ALOGE("ERROR: failed to open framebuffer (%s), aborting",
+ strerror(-fberr));
abort();
}
// these display IDs are always reserved
- for (size_t i=0 ; i<HWC_NUM_DISPLAY_TYPES ; i++) {
+ for (size_t i=0 ; i<NUM_PHYSICAL_DISPLAYS ; i++) {
mAllocatedDisplayIDs.markBit(i);
}
@@ -146,12 +156,12 @@ HWComposer::HWComposer(
// the number of displays we actually have depends on the
// hw composer version
- if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_2)) {
- // 1.2 adds support for virtual displays
+ if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_EXP)) {
+ // 1.?? adds support for virtual displays
mNumDisplays = MAX_DISPLAYS;
} else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
// 1.1 adds support for multiple displays
- mNumDisplays = HWC_NUM_DISPLAY_TYPES;
+ mNumDisplays = NUM_PHYSICAL_DISPLAYS;
} else {
mNumDisplays = 1;
}
@@ -179,7 +189,7 @@ HWComposer::HWComposer(
}
} else if (mHwc) {
// here we're guaranteed to have at least HWC 1.1
- for (size_t i =0 ; i<HWC_NUM_DISPLAY_TYPES ; i++) {
+ for (size_t i =0 ; i<NUM_PHYSICAL_DISPLAYS ; i++) {
queryDisplayProperties(i);
}
}
@@ -235,20 +245,17 @@ void HWComposer::loadHwcModule()
}
// Load and prepare the FB HAL, which uses the gralloc module. Sets mFbDev.
-void HWComposer::loadFbHalModule()
+int HWComposer::loadFbHalModule()
{
hw_module_t const* module;
- if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) != 0) {
+ int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
+ if (err != 0) {
ALOGE("%s module not found", GRALLOC_HARDWARE_MODULE_ID);
- return;
+ return err;
}
- int err = framebuffer_open(module, &mFbDev);
- if (err) {
- ALOGE("framebuffer_open failed (%s)", strerror(-err));
- return;
- }
+ return framebuffer_open(module, &mFbDev);
}
status_t HWComposer::initCheck() const {
@@ -287,7 +294,7 @@ void HWComposer::vsync(int disp, int64_t timestamp) {
}
void HWComposer::hotplug(int disp, int connected) {
- if (disp == HWC_DISPLAY_PRIMARY || disp >= HWC_NUM_DISPLAY_TYPES) {
+ if (disp == HWC_DISPLAY_PRIMARY || disp >= VIRTUAL_DISPLAY_ID_BASE) {
ALOGE("hotplug event received for invalid display: disp=%d connected=%d",
disp, connected);
return;
@@ -296,6 +303,11 @@ void HWComposer::hotplug(int disp, int connected) {
mEventHandler.onHotplugReceived(disp, bool(connected));
}
+static float getDefaultDensity(uint32_t height) {
+ if (height >= 1080) return ACONFIGURATION_DENSITY_XHIGH;
+ else return ACONFIGURATION_DENSITY_TV;
+}
+
static const uint32_t DISPLAY_ATTRIBUTES[] = {
HWC_DISPLAY_VSYNC_PERIOD,
HWC_DISPLAY_WIDTH,
@@ -306,10 +318,6 @@ static const uint32_t DISPLAY_ATTRIBUTES[] = {
};
#define NUM_DISPLAY_ATTRIBUTES (sizeof(DISPLAY_ATTRIBUTES) / sizeof(DISPLAY_ATTRIBUTES)[0])
-// http://developer.android.com/reference/android/util/DisplayMetrics.html
-#define ANDROID_DENSITY_TV 213
-#define ANDROID_DENSITY_XHIGH 320
-
status_t HWComposer::queryDisplayProperties(int disp) {
LOG_ALWAYS_FATAL_IF(!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1));
@@ -363,15 +371,23 @@ status_t HWComposer::queryDisplayProperties(int disp) {
mDisplayData[disp].format = HAL_PIXEL_FORMAT_RGBA_8888;
mDisplayData[disp].connected = true;
if (mDisplayData[disp].xdpi == 0.0f || mDisplayData[disp].ydpi == 0.0f) {
- // is there anything smarter we can do?
- if (h >= 1080) {
- mDisplayData[disp].xdpi = ANDROID_DENSITY_XHIGH;
- mDisplayData[disp].ydpi = ANDROID_DENSITY_XHIGH;
- } else {
- mDisplayData[disp].xdpi = ANDROID_DENSITY_TV;
- mDisplayData[disp].ydpi = ANDROID_DENSITY_TV;
- }
+ float dpi = getDefaultDensity(h);
+ mDisplayData[disp].xdpi = dpi;
+ mDisplayData[disp].ydpi = dpi;
+ }
+ return NO_ERROR;
+}
+
+status_t HWComposer::setVirtualDisplayProperties(int32_t id,
+ uint32_t w, uint32_t h, uint32_t format) {
+ if (id < VIRTUAL_DISPLAY_ID_BASE || id >= int32_t(mNumDisplays) ||
+ !mAllocatedDisplayIDs.hasBit(id)) {
+ return BAD_INDEX;
}
+ mDisplayData[id].width = w;
+ mDisplayData[id].height = h;
+ mDisplayData[id].format = format;
+ mDisplayData[id].xdpi = mDisplayData[id].ydpi = getDefaultDensity(h);
return NO_ERROR;
}
@@ -381,11 +397,12 @@ int32_t HWComposer::allocateDisplayId() {
}
int32_t id = mAllocatedDisplayIDs.firstUnmarkedBit();
mAllocatedDisplayIDs.markBit(id);
+ mDisplayData[id].connected = true;
return id;
}
status_t HWComposer::freeDisplayId(int32_t id) {
- if (id < HWC_NUM_DISPLAY_TYPES) {
+ if (id < NUM_PHYSICAL_DISPLAYS) {
// cannot free the reserved IDs
return BAD_VALUE;
}
@@ -393,6 +410,7 @@ status_t HWComposer::freeDisplayId(int32_t id) {
return BAD_INDEX;
}
mAllocatedDisplayIDs.clearBit(id);
+ mDisplayData[id].connected = false;
return NO_ERROR;
}
@@ -409,6 +427,10 @@ nsecs_t HWComposer::getRefreshTimestamp(int disp) const {
return now - ((now - mLastHwVSync) % mDisplayData[disp].refresh);
}
+sp<Fence> HWComposer::getDisplayFence(int disp) const {
+ return mDisplayData[disp].lastDisplayFence;
+}
+
uint32_t HWComposer::getWidth(int disp) const {
return mDisplayData[disp].width;
}
@@ -494,7 +516,7 @@ status_t HWComposer::createWorkList(int32_t id, size_t 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 };
+ const hwc_rect_t r = { 0, 0, (int) disp.width, (int) disp.height };
disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET;
disp.framebufferTarget->hints = 0;
disp.framebufferTarget->flags = 0;
@@ -508,6 +530,7 @@ status_t HWComposer::createWorkList(int32_t id, size_t numLayers) {
&disp.framebufferTarget->displayFrame;
disp.framebufferTarget->acquireFenceFd = -1;
disp.framebufferTarget->releaseFenceFd = -1;
+ disp.framebufferTarget->planeAlpha = 0xFF;
}
disp.list->retireFenceFd = -1;
disp.list->flags = HWC_GEOMETRY_CHANGED;
@@ -524,7 +547,7 @@ status_t HWComposer::setFramebufferTarget(int32_t id,
DisplayData& disp(mDisplayData[id]);
if (!disp.framebufferTarget) {
// this should never happen, but apparently eglCreateWindowSurface()
- // triggers a SurfaceTextureClient::queueBuffer() on some
+ // triggers a Surface::queueBuffer() on some
// devices (!?) -- log and ignore.
ALOGE("HWComposer: framebufferTarget is null");
// CallStack stack;
@@ -534,7 +557,7 @@ status_t HWComposer::setFramebufferTarget(int32_t id,
}
int acquireFenceFd = -1;
- if (acquireFence != NULL) {
+ if (acquireFence->isValid()) {
acquireFenceFd = acquireFence->dup();
}
@@ -562,7 +585,7 @@ status_t HWComposer::prepare() {
}
mLists[i] = disp.list;
if (mLists[i]) {
- if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_2)) {
+ if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_EXP)) {
mLists[i]->outbuf = NULL;
mLists[i]->outbufAcquireFenceFd = -1;
} else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
@@ -611,20 +634,20 @@ status_t HWComposer::prepare() {
}
bool HWComposer::hasHwcComposition(int32_t id) const {
- if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
+ if (!mHwc || uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
return false;
return mDisplayData[id].hasOvComp;
}
bool HWComposer::hasGlesComposition(int32_t id) const {
- if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
- return false;
+ if (!mHwc || uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
+ return true;
return mDisplayData[id].hasFbComp;
}
-int HWComposer::getAndResetReleaseFenceFd(int32_t id) {
+sp<Fence> HWComposer::getAndResetReleaseFence(int32_t id) {
if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
- return BAD_INDEX;
+ return Fence::NO_FENCE;
int fd = INVALID_OPERATION;
if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
@@ -635,7 +658,7 @@ int HWComposer::getAndResetReleaseFenceFd(int32_t id) {
disp.framebufferTarget->releaseFenceFd = -1;
}
}
- return fd;
+ return fd >= 0 ? new Fence(fd) : Fence::NO_FENCE;
}
status_t HWComposer::commit() {
@@ -649,13 +672,24 @@ status_t HWComposer::commit() {
mLists[0]->sur = eglGetCurrentSurface(EGL_DRAW);
}
+ for (size_t i=VIRTUAL_DISPLAY_ID_BASE; i<mNumDisplays; i++) {
+ DisplayData& disp(mDisplayData[i]);
+ if (disp.outbufHandle) {
+ mLists[i]->outbuf = disp.outbufHandle;
+ mLists[i]->outbufAcquireFenceFd =
+ disp.outbufAcquireFence->dup();
+ }
+ }
+
err = mHwc->set(mHwc, mNumDisplays, mLists);
for (size_t i=0 ; i<mNumDisplays ; i++) {
DisplayData& disp(mDisplayData[i]);
+ disp.lastDisplayFence = disp.lastRetireFence;
+ disp.lastRetireFence = Fence::NO_FENCE;
if (disp.list) {
if (disp.list->retireFenceFd != -1) {
- close(disp.list->retireFenceFd);
+ disp.lastRetireFence = new Fence(disp.list->retireFenceFd);
disp.list->retireFenceFd = -1;
}
disp.list->flags &= ~HWC_GEOMETRY_CHANGED;
@@ -666,7 +700,7 @@ status_t HWComposer::commit() {
}
status_t HWComposer::release(int disp) {
- LOG_FATAL_IF(disp >= HWC_NUM_DISPLAY_TYPES);
+ LOG_FATAL_IF(disp >= VIRTUAL_DISPLAY_ID_BASE);
if (mHwc) {
eventControl(disp, HWC_EVENT_VSYNC, 0);
return (status_t)mHwc->blank(mHwc, disp, 1);
@@ -675,7 +709,7 @@ status_t HWComposer::release(int disp) {
}
status_t HWComposer::acquire(int disp) {
- LOG_FATAL_IF(disp >= HWC_NUM_DISPLAY_TYPES);
+ LOG_FATAL_IF(disp >= VIRTUAL_DISPLAY_ID_BASE);
if (mHwc) {
return (status_t)mHwc->blank(mHwc, disp, 0);
}
@@ -684,17 +718,15 @@ status_t HWComposer::acquire(int disp) {
void HWComposer::disconnectDisplay(int disp) {
LOG_ALWAYS_FATAL_IF(disp < 0 || disp == HWC_DISPLAY_PRIMARY);
- if (disp >= HWC_NUM_DISPLAY_TYPES) {
- // nothing to do for these yet
- return;
- }
DisplayData& dd(mDisplayData[disp]);
- if (dd.list != NULL) {
- free(dd.list);
- dd.list = NULL;
- dd.framebufferTarget = NULL; // points into dd.list
- dd.fbTargetHandle = NULL;
- }
+ free(dd.list);
+ dd.list = NULL;
+ dd.framebufferTarget = NULL; // points into dd.list
+ dd.fbTargetHandle = NULL;
+ dd.outbufHandle = NULL;
+ dd.lastRetireFence = Fence::NO_FENCE;
+ dd.lastDisplayFence = Fence::NO_FENCE;
+ dd.outbufAcquireFence = Fence::NO_FENCE;
}
int HWComposer::getVisualID() const {
@@ -718,9 +750,7 @@ int HWComposer::fbPost(int32_t id,
if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
return setFramebufferTarget(id, acquireFence, buffer);
} else {
- if (acquireFence != NULL) {
- acquireFence->waitForever(1000, "HWComposer::fbPost");
- }
+ acquireFence->waitForever("HWComposer::fbPost");
return mFbDev->post(mFbDev, buffer->handle);
}
}
@@ -745,6 +775,25 @@ void HWComposer::fbDump(String8& result) {
}
}
+status_t HWComposer::setOutputBuffer(int32_t id, const sp<Fence>& acquireFence,
+ const sp<GraphicBuffer>& buf) {
+ if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
+ return BAD_INDEX;
+ if (id < VIRTUAL_DISPLAY_ID_BASE)
+ return INVALID_OPERATION;
+
+ DisplayData& disp(mDisplayData[id]);
+ disp.outbufHandle = buf->handle;
+ disp.outbufAcquireFence = acquireFence;
+ return NO_ERROR;
+}
+
+sp<Fence> HWComposer::getLastRetireFence(int32_t id) {
+ if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
+ return Fence::NO_FENCE;
+ return mDisplayData[id].lastRetireFence;
+}
+
/*
* Helper template to implement a concrete HWCLayer
* This holds the pointer to the concrete hwc layer type
@@ -775,9 +824,10 @@ private:
* This implements the HWCLayer side of HWCIterableLayer.
*/
class HWCLayerVersion1 : public Iterable<HWCLayerVersion1, hwc_layer_1_t> {
+ struct hwc_composer_device_1* mHwc;
public:
- HWCLayerVersion1(hwc_layer_1_t* layer)
- : Iterable<HWCLayerVersion1, hwc_layer_1_t>(layer) { }
+ HWCLayerVersion1(struct hwc_composer_device_1* hwc, hwc_layer_1_t* layer)
+ : Iterable<HWCLayerVersion1, hwc_layer_1_t>(layer), mHwc(hwc) { }
virtual int32_t getCompositionType() const {
return getLayer()->compositionType;
@@ -785,10 +835,10 @@ public:
virtual uint32_t getHints() const {
return getLayer()->hints;
}
- virtual int getAndResetReleaseFenceFd() {
+ virtual sp<Fence> getAndResetReleaseFence() {
int fd = getLayer()->releaseFenceFd;
getLayer()->releaseFenceFd = -1;
- return fd;
+ return fd >= 0 ? new Fence(fd) : Fence::NO_FENCE;
}
virtual void setAcquireFenceFd(int fenceFd) {
getLayer()->acquireFenceFd = fenceFd;
@@ -796,17 +846,28 @@ public:
virtual void setPerFrameDefaultState() {
//getLayer()->compositionType = HWC_FRAMEBUFFER;
}
+ virtual void setPlaneAlpha(uint8_t alpha) {
+ if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_2)) {
+ getLayer()->planeAlpha = alpha;
+ } else {
+ if (alpha < 0xFF) {
+ getLayer()->flags |= HWC_SKIP_LAYER;
+ }
+ }
+ }
virtual void setDefaultState() {
- getLayer()->compositionType = HWC_FRAMEBUFFER;
- getLayer()->hints = 0;
- getLayer()->flags = HWC_SKIP_LAYER;
- getLayer()->handle = 0;
- getLayer()->transform = 0;
- getLayer()->blending = HWC_BLENDING_NONE;
- getLayer()->visibleRegionScreen.numRects = 0;
- getLayer()->visibleRegionScreen.rects = NULL;
- getLayer()->acquireFenceFd = -1;
- getLayer()->releaseFenceFd = -1;
+ hwc_layer_1_t* const l = getLayer();
+ l->compositionType = HWC_FRAMEBUFFER;
+ l->hints = 0;
+ l->flags = HWC_SKIP_LAYER;
+ l->handle = 0;
+ l->transform = 0;
+ l->blending = HWC_BLENDING_NONE;
+ l->visibleRegionScreen.numRects = 0;
+ l->visibleRegionScreen.rects = NULL;
+ l->acquireFenceFd = -1;
+ l->releaseFenceFd = -1;
+ l->planeAlpha = 0xFF;
}
virtual void setSkip(bool skip) {
if (skip) {
@@ -869,7 +930,7 @@ HWComposer::LayerListIterator HWComposer::getLayerIterator(int32_t id, size_t in
if (!mHwc || !disp.list || index > disp.list->numHwLayers) {
return LayerListIterator();
}
- return LayerListIterator(new HWCLayerVersion1(disp.list->hwLayers), index);
+ return LayerListIterator(new HWCLayerVersion1(mHwc, disp.list->hwLayers), index);
}
/*
@@ -907,17 +968,17 @@ void HWComposer::dump(String8& result, char* buffer, size_t SIZE) const {
result.appendFormat(" mDebugForceFakeVSync=%d\n", mDebugForceFakeVSync);
for (size_t i=0 ; i<mNumDisplays ; i++) {
const DisplayData& disp(mDisplayData[i]);
+ if (!disp.connected)
+ continue;
- const Vector< sp<LayerBase> >& visibleLayersSortedByZ =
+ const Vector< sp<Layer> >& visibleLayersSortedByZ =
mFlinger->getLayerSortedByZForHwcDisplay(i);
- if (disp.connected) {
- result.appendFormat(
- " Display[%d] : %ux%u, xdpi=%f, ydpi=%f, refresh=%lld\n",
- i, disp.width, disp.height, disp.xdpi, disp.ydpi, disp.refresh);
- }
+ result.appendFormat(
+ " Display[%d] : %ux%u, xdpi=%f, ydpi=%f, refresh=%lld\n",
+ i, disp.width, disp.height, disp.xdpi, disp.ydpi, disp.refresh);
- if (disp.list && disp.connected) {
+ if (disp.list) {
result.appendFormat(
" numHwLayers=%u, flags=%08x\n",
disp.list->numHwLayers, disp.list->flags);
@@ -932,13 +993,11 @@ void HWComposer::dump(String8& result, char* buffer, size_t SIZE) const {
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();
- }
+ const sp<Layer>& layer(visibleLayersSortedByZ[i]);
+ const sp<GraphicBuffer>& buffer(
+ layer->getActiveBuffer());
+ if (buffer != NULL) {
+ format = buffer->getPixelFormat();
}
name = layer->getName();
}
@@ -1032,5 +1091,22 @@ bool HWComposer::VSyncThread::threadLoop() {
return true;
}
+HWComposer::DisplayData::DisplayData()
+: width(0), height(0), format(0),
+ xdpi(0.0f), ydpi(0.0f),
+ refresh(0),
+ connected(false),
+ hasFbComp(false), hasOvComp(false),
+ capacity(0), list(NULL),
+ framebufferTarget(NULL), fbTargetHandle(0),
+ lastRetireFence(Fence::NO_FENCE), lastDisplayFence(Fence::NO_FENCE),
+ outbufHandle(NULL), outbufAcquireFence(Fence::NO_FENCE),
+ events(0)
+{}
+
+HWComposer::DisplayData::~DisplayData() {
+ free(list);
+}
+
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 7c67407..604de38 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -22,13 +22,15 @@
#include <hardware/hwcomposer_defs.h>
+#include <ui/Fence.h>
+
+#include <utils/BitSet.h>
#include <utils/Condition.h>
#include <utils/Mutex.h>
#include <utils/StrongPointer.h>
#include <utils/Thread.h>
#include <utils/Timers.h>
#include <utils/Vector.h>
-#include <utils/BitSet.h>
extern "C" int clock_nanosleep(clockid_t clock_id, int flags,
const struct timespec *request,
@@ -45,7 +47,6 @@ namespace android {
class GraphicBuffer;
class Fence;
-class LayerBase;
class Region;
class String8;
class SurfaceFlinger;
@@ -111,9 +112,9 @@ public:
// does this display have layers handled by GLES
bool hasGlesComposition(int32_t id) const;
- // get the releaseFence file descriptor for the given display
+ // get the releaseFence file descriptor for a display's framebuffer layer.
// the release fence is only valid after commit()
- int getAndResetReleaseFenceFd(int32_t id);
+ sp<Fence> getAndResetReleaseFence(int32_t id);
// needed forward declarations
class LayerListIterator;
@@ -127,6 +128,17 @@ public:
int fbCompositionComplete();
void fbDump(String8& result);
+ // Set the output buffer and acquire fence for a virtual display.
+ // Returns INVALID_OPERATION if id is not a virtual display.
+ status_t setOutputBuffer(int32_t id, const sp<Fence>& acquireFence,
+ const sp<GraphicBuffer>& buf);
+
+ // Get the retire fence for the last committed frame. This fence will
+ // signal when the h/w composer is completely finished with the frame.
+ // For physical displays, it is no longer being displayed. For virtual
+ // displays, writes to the output buffer are complete.
+ sp<Fence> getLastRetireFence(int32_t id);
+
/*
* Interface to hardware composer's layers functionality.
* This abstracts the HAL interface to layers which can evolve in
@@ -140,8 +152,7 @@ public:
public:
virtual int32_t getCompositionType() const = 0;
virtual uint32_t getHints() const = 0;
- virtual int getAndResetReleaseFenceFd() = 0;
- virtual void setPerFrameDefaultState() = 0;
+ virtual sp<Fence> getAndResetReleaseFence() = 0;
virtual void setDefaultState() = 0;
virtual void setSkip(bool skip) = 0;
virtual void setBlending(uint32_t blending) = 0;
@@ -151,6 +162,7 @@ public:
virtual void setVisibleRegionScreen(const Region& reg) = 0;
virtual void setBuffer(const sp<GraphicBuffer>& buffer) = 0;
virtual void setAcquireFenceFd(int fenceFd) = 0;
+ virtual void setPlaneAlpha(uint8_t alpha) = 0;
virtual void onDisplayed() = 0;
};
@@ -233,6 +245,7 @@ public:
// HWC_DISPLAY_PRIMARY).
nsecs_t getRefreshPeriod(int disp) const;
nsecs_t getRefreshTimestamp(int disp) const;
+ sp<Fence> getDisplayFence(int disp) const;
uint32_t getWidth(int disp) const;
uint32_t getHeight(int disp) const;
uint32_t getFormat(int disp) const;
@@ -240,6 +253,9 @@ public:
float getDpiY(int disp) const;
bool isConnected(int disp) const;
+ status_t setVirtualDisplayProperties(int32_t id, uint32_t w, uint32_t h,
+ uint32_t format);
+
// this class is only used to fake the VSync event on systems that don't
// have it.
class VSyncThread : public Thread {
@@ -263,7 +279,7 @@ public:
private:
void loadHwcModule();
- void loadFbHalModule();
+ int loadFbHalModule();
LayerListIterator getLayerIterator(int32_t id, size_t index);
@@ -286,13 +302,8 @@ private:
struct DisplayData {
- DisplayData() : xdpi(0), ydpi(0), refresh(0),
- connected(false), hasFbComp(false), hasOvComp(false),
- capacity(0), list(NULL),
- framebufferTarget(NULL), fbTargetHandle(NULL), events(0) { }
- ~DisplayData() {
- free(list);
- }
+ DisplayData();
+ ~DisplayData();
uint32_t width;
uint32_t height;
uint32_t format; // pixel format from FB hal, for pre-hwc-1.1
@@ -306,6 +317,12 @@ private:
hwc_display_contents_1* list;
hwc_layer_1* framebufferTarget;
buffer_handle_t fbTargetHandle;
+ sp<Fence> lastRetireFence; // signals when the last set op retires
+ sp<Fence> lastDisplayFence; // signals when the last set op takes
+ // effect on screen
+ buffer_handle_t outbufHandle;
+ sp<Fence> outbufAcquireFence;
+
// protected by mEventControlLock
int32_t events;
};
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
new file mode 100644
index 0000000..2838b23
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2013 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 "VirtualDisplaySurface.h"
+
+#include <cutils/log.h>
+#include <gui/IGraphicBufferProducer.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int32_t dispId,
+ const sp<IGraphicBufferProducer>& sink, const String8& name)
+: mSink(sink)
+{
+ LOG_ALWAYS_FATAL_IF(dispId >= 0);
+}
+
+VirtualDisplaySurface::~VirtualDisplaySurface() {
+}
+
+sp<IGraphicBufferProducer> VirtualDisplaySurface::getIGraphicBufferProducer() const {
+ return mSink;
+}
+
+status_t VirtualDisplaySurface::compositionComplete() {
+ return NO_ERROR;
+}
+
+status_t VirtualDisplaySurface::advanceFrame() {
+ return NO_ERROR;
+}
+
+void VirtualDisplaySurface::onFrameCommitted() {
+}
+
+void VirtualDisplaySurface::dump(String8& result) const {
+}
+
+// ---------------------------------------------------------------------------
+} // namespace android
+// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
new file mode 100644
index 0000000..f321795
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2013 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_SF_VIRTUAL_DISPLAY_SURFACE_H
+#define ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H
+
+#include "DisplaySurface.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+class HWComposer;
+
+/* This DisplaySurface implementation is a stub used for developing HWC
+ * virtual display support. It is currently just a passthrough.
+ */
+class VirtualDisplaySurface : public DisplaySurface {
+public:
+ VirtualDisplaySurface(HWComposer& hwc, int32_t dispId,
+ const sp<IGraphicBufferProducer>& sink,
+ const String8& name);
+
+ virtual sp<IGraphicBufferProducer> getIGraphicBufferProducer() const;
+
+ virtual status_t compositionComplete();
+ virtual status_t advanceFrame();
+ virtual void onFrameCommitted();
+ virtual void dump(String8& result) const;
+
+private:
+ virtual ~VirtualDisplaySurface();
+
+ sp<IGraphicBufferProducer> mSink;
+};
+
+// ---------------------------------------------------------------------------
+} // namespace android
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H
+