summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/media/hardware/HDCPAPI.h85
-rw-r--r--services/surfaceflinger/DisplayHardware/HWComposer.cpp48
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp121
3 files changed, 192 insertions, 62 deletions
diff --git a/include/media/hardware/HDCPAPI.h b/include/media/hardware/HDCPAPI.h
new file mode 100644
index 0000000..bb91540
--- /dev/null
+++ b/include/media/hardware/HDCPAPI.h
@@ -0,0 +1,85 @@
+/*
+ * 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 HDCP_API_H_
+
+#define HDCP_API_H_
+
+#include <utils/Errors.h>
+
+namespace android {
+
+struct HDCPModule {
+ typedef void (*ObserverFunc)(int msg, int ext1, int ext2);
+
+ // The msg argument in calls to the observer notification function.
+ enum {
+ // Sent in response to a call to "HDCPModule::initAsync" once
+ // initialization has either been successfully completed,
+ // i.e. the HDCP session is now fully setup (AKE, Locality Check,
+ // SKE and any authentication with repeaters completed) or failed.
+ // ext1 should be a suitable error code (status_t), ext2 is
+ // unused.
+ HDCP_INITIALIZATION_COMPLETE,
+
+ // Sent upon completion of a call to "HDCPModule::shutdownAsync".
+ // ext1 should be a suitable error code, ext2 is unused.
+ HDCP_SHUTDOWN_COMPLETE,
+ };
+
+ // Module can call the notification function to signal completion/failure
+ // of asynchronous operations (such as initialization) or out of band
+ // events.
+ HDCPModule(ObserverFunc observerNotify);
+
+ virtual ~HDCPModule();
+
+ // Request to setup an HDCP session with the specified host listening
+ // on the specified port.
+ virtual status_t initAsync(const char *host, unsigned port) = 0;
+
+ // Request to shutdown the active HDCP session.
+ virtual status_t shutdownAsync() = 0;
+
+ // Encrypt a data according to the HDCP spec. The data is to be
+ // encrypted in-place, only size bytes of data should be read/write,
+ // even if the size is not a multiple of 128 bit (16 bytes).
+ // This operation is to be synchronous, i.e. this call does not return
+ // until outData contains size bytes of encrypted data.
+ // streamCTR will be assigned by the caller (to 0 for the first PES stream,
+ // 1 for the second and so on)
+ // inputCTR will be maintained by the callee for each PES stream.
+ virtual status_t encrypt(
+ const void *inData, size_t size, uint32_t streamCTR,
+ uint64_t *outInputCTR, void *outData) = 0;
+
+private:
+ HDCPModule(const HDCPModule &);
+ HDCPModule &operator=(const HDCPModule &);
+};
+
+} // namespace android
+
+// A shared library exporting the following method should be included to
+// support HDCP functionality. The shared library must be called
+// "libstagefright_hdcp.so", it will be dynamically loaded into the
+// mediaserver process.
+extern "C" {
+ extern android::HDCPModule *createHDCPModule();
+}
+
+#endif // HDCP_API_H_
+
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 1678fe1..75c228d 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -46,8 +46,31 @@
namespace android {
-static bool hwcHasVersion(const hwc_composer_device_1_t* hwc, uint32_t version) {
- return hwc->common.version >= version;
+#define MIN_HWC_HEADER_VERSION 0
+
+static uint32_t hwcApiVersion(const hwc_composer_device_1_t* hwc) {
+ uint32_t hwcVersion = hwc->common.version;
+ if (MIN_HWC_HEADER_VERSION == 0 &&
+ (hwcVersion & HARDWARE_API_VERSION_2_MAJ_MIN_MASK) == 0) {
+ // legacy version encoding
+ hwcVersion <<= 16;
+ }
+ return hwcVersion & HARDWARE_API_VERSION_2_MAJ_MIN_MASK;
+}
+
+static uint32_t hwcHeaderVersion(const hwc_composer_device_1_t* hwc) {
+ uint32_t hwcVersion = hwc->common.version;
+ if (MIN_HWC_HEADER_VERSION == 0 &&
+ (hwcVersion & HARDWARE_API_VERSION_2_MAJ_MIN_MASK) == 0) {
+ // legacy version encoding
+ hwcVersion <<= 16;
+ }
+ return hwcVersion & HARDWARE_API_VERSION_2_HEADER_MASK;
+}
+
+static bool hwcHasApiVersion(const hwc_composer_device_1_t* hwc,
+ uint32_t version) {
+ return hwcApiVersion(hwc) >= (version & HARDWARE_API_VERSION_2_MAJ_MIN_MASK);
}
// ---------------------------------------------------------------------------
@@ -91,8 +114,10 @@ HWComposer::HWComposer(
ALOGE_IF(err, "%s device failed to initialize (%s)",
HWC_HARDWARE_COMPOSER, strerror(-err));
if (err == 0) {
- if (mHwc->common.version < HWC_DEVICE_API_VERSION_1_0) {
- ALOGE("%s device version %#x too old, will not be used",
+ if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0) ||
+ hwcHeaderVersion(mHwc) < MIN_HWC_HEADER_VERSION ||
+ hwcHeaderVersion(mHwc) > HWC_HEADER_VERSION) {
+ ALOGE("%s device version %#x unsupported, will not be used",
HWC_HARDWARE_COMPOSER, mHwc->common.version);
hwc_close_1(mHwc);
mHwc = NULL;
@@ -100,6 +125,9 @@ HWComposer::HWComposer(
}
if (mHwc) {
+ ALOGI("Using %s version %u.%u", HWC_HARDWARE_COMPOSER,
+ (hwcApiVersion(mHwc) >> 24) & 0xff,
+ (hwcApiVersion(mHwc) >> 16) & 0xff);
if (mHwc->registerProcs) {
mCBContext->hwc = this;
mCBContext->procs.invalidate = &hook_invalidate;
@@ -125,12 +153,14 @@ HWComposer::HWComposer(
// the number of displays we actually have depends on the
// hw composer version
- if (mHwc->common.version == HWC_DEVICE_API_VERSION_1_1) {
- // 1.1 adds support for multiple displays
- mNumDisplays = HWC_NUM_DISPLAY_TYPES;
- } else if (mHwc->common.version > HWC_DEVICE_API_VERSION_1_1) {
+ if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_2)) {
// 1.2 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;
+ } else {
+ mNumDisplays = 1;
}
}
}
@@ -326,7 +356,7 @@ bool HWComposer::hasGlesComposition(int32_t id) const {
status_t HWComposer::commit() {
int err = NO_ERROR;
if (mHwc) {
- if (mHwc->common.version == HWC_DEVICE_API_VERSION_1_0) {
+ if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
// On version 1.0, the OpenGL ES target surface is communicated
// by the (dpy, sur) fields and we are guaranteed to have only
// a single display.
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 1162432..cd1b336 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -944,7 +944,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
if (!curr.isIdenticalTo(draw)) {
mVisibleRegionsDirty = true;
const size_t cc = curr.size();
- const size_t dc = draw.size();
+ size_t dc = draw.size();
// find the displays that were removed
// (ie: in drawing state but not in current state)
@@ -965,27 +965,27 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
const wp<IBinder>& display(curr.keyAt(j));
if (state.surface->asBinder() != draw[i].surface->asBinder()) {
// changing the surface is like destroying and
- // recreating the DisplayDevice
- sp<SurfaceTextureClient> stc(
- new SurfaceTextureClient(state.surface));
- sp<DisplayDevice> disp = new DisplayDevice(this,
- state.type, display, stc, NULL, mEGLConfig);
-
- disp->setLayerStack(state.layerStack);
- disp->setOrientation(state.orientation);
- // TODO: take viewport and frame into account
- mDisplays.replaceValueFor(display, disp);
- }
- if (state.layerStack != draw[i].layerStack) {
- const sp<DisplayDevice>& disp(getDisplayDevice(display));
- disp->setLayerStack(state.layerStack);
+ // recreating the DisplayDevice, so we just remove it
+ // from the drawing state, so that it get re-added
+ // below.
+ mDisplays.removeItem(display);
+ mDrawingState.displays.removeItemsAt(i);
+ dc--; i--;
+ // at this point we must loop to the next item
+ continue;
}
- if (state.orientation != draw[i].orientation ||
- state.viewport != draw[i].viewport ||
- state.frame != draw[i].frame) {
- const sp<DisplayDevice>& disp(getDisplayDevice(display));
- disp->setOrientation(state.orientation);
- // TODO: take viewport and frame into account
+
+ const sp<DisplayDevice>& disp(getDisplayDevice(display));
+ if (disp != NULL) {
+ if (state.layerStack != draw[i].layerStack) {
+ disp->setLayerStack(state.layerStack);
+ }
+ if (state.orientation != draw[i].orientation ||
+ state.viewport != draw[i].viewport ||
+ state.frame != draw[i].frame) {
+ disp->setOrientation(state.orientation);
+ // TODO: take viewport and frame into account
+ }
}
}
}
@@ -995,12 +995,17 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
for (size_t i=0 ; i<cc ; i++) {
if (draw.indexOfKey(curr.keyAt(i)) < 0) {
const DisplayDeviceState& state(curr[i]);
- sp<SurfaceTextureClient> stc(
- new SurfaceTextureClient(state.surface));
- const wp<IBinder>& display(curr.keyAt(i));
- sp<DisplayDevice> disp = new DisplayDevice(this,
- state.type, display, stc, 0, mEGLConfig);
- mDisplays.add(display, disp);
+ if (state.surface != NULL) {
+ sp<SurfaceTextureClient> stc(
+ new SurfaceTextureClient(state.surface));
+ const wp<IBinder>& display(curr.keyAt(i));
+ sp<DisplayDevice> disp = new DisplayDevice(this,
+ state.type, display, stc, 0, mEGLConfig);
+ disp->setLayerStack(state.layerStack);
+ disp->setOrientation(state.orientation);
+ // TODO: take viewport and frame into account
+ mDisplays.add(display, disp);
+ }
}
}
}
@@ -1264,15 +1269,13 @@ void SurfaceFlinger::doDisplayComposition(const sp<const DisplayDevice>& hw,
void SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const Region& dirty)
{
+ const int32_t id = hw->getHwcDisplayId();
HWComposer& hwc(getHwComposer());
- int32_t id = hw->getHwcDisplayId();
HWComposer::LayerListIterator cur = hwc.begin(id);
const HWComposer::LayerListIterator end = hwc.end(id);
- const bool hasGlesComposition = hwc.hasGlesComposition(id);
- const bool hasHwcComposition = hwc.hasHwcComposition(id);
- if (cur==end || hasGlesComposition) {
-
+ const bool hasGlesComposition = hwc.hasGlesComposition(id) || (cur==end);
+ if (hasGlesComposition) {
DisplayDevice::makeCurrent(hw, mEGLContext);
// set the frame buffer
@@ -1280,6 +1283,7 @@ void SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const
glLoadIdentity();
// Never touch the framebuffer if we don't have any framebuffer layers
+ const bool hasHwcComposition = hwc.hasHwcComposition(id);
if (hasHwcComposition) {
// when using overlays, we assume a fully transparent framebuffer
// NOTE: we could reduce how much we need to clear, for instance
@@ -1296,39 +1300,50 @@ void SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const
drawWormhole(hw, region);
}
}
+ }
- /*
- * and then, render the layers targeted at the framebuffer
- */
+ /*
+ * and then, render the layers targeted at the framebuffer
+ */
- const Vector< sp<LayerBase> >& layers(hw->getVisibleLayersSortedByZ());
- const size_t count = layers.size();
- const Transform& tr = hw->getTransform();
- for (size_t i=0 ; i<count ; ++i) {
+ const Vector< sp<LayerBase> >& layers(hw->getVisibleLayersSortedByZ());
+ const size_t count = layers.size();
+ const Transform& tr = hw->getTransform();
+ if (cur != end) {
+ // we're using h/w composer
+ for (size_t i=0 ; i<count && cur!=end ; ++i, ++cur) {
const sp<LayerBase>& layer(layers[i]);
const Region clip(dirty.intersect(tr.transform(layer->visibleRegion)));
- if (cur != end) {
- // we're using h/w composer
- if (!clip.isEmpty()) {
- if (cur->getCompositionType() == HWC_OVERLAY) {
- if (i && (cur->getHints() & HWC_HINT_CLEAR_FB)
- && layer->isOpaque()) {
+ if (!clip.isEmpty()) {
+ switch (cur->getCompositionType()) {
+ case HWC_OVERLAY: {
+ if ((cur->getHints() & HWC_HINT_CLEAR_FB)
+ && i
+ && layer->isOpaque()
+ && hasGlesComposition) {
// never clear the very first layer since we're
// guaranteed the FB is already cleared
layer->clearWithOpenGL(hw, clip);
}
- } else {
+ break;
+ }
+ case HWC_FRAMEBUFFER: {
layer->draw(hw, clip);
+ break;
}
- layer->setAcquireFence(hw, *cur);
- }
- ++cur;
- } else {
- // we're not using h/w composer
- if (!clip.isEmpty()) {
- layer->draw(hw, clip);
}
}
+ layer->setAcquireFence(hw, *cur);
+ }
+ } else {
+ // we're not using h/w composer
+ for (size_t i=0 ; i<count ; ++i) {
+ const sp<LayerBase>& layer(layers[i]);
+ const Region clip(dirty.intersect(
+ tr.transform(layer->visibleRegion)));
+ if (!clip.isEmpty()) {
+ layer->draw(hw, clip);
+ }
}
}
}