Merge "sdm: Change log level to warning"
diff --git a/Android.mk b/Android.mk
index 3471e0a..aa34895 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,10 +1,9 @@
-ifneq ($(TARGET_DISABLE_DISPLAY),true)
sdm-libs := sdm/libs
-display-hals := include $(sdm-libs)/utils $(sdm-libs)/core libdebug
+display-hals := include $(sdm-libs)/utils $(sdm-libs)/core libdebug gpu_tonemapper
ifneq ($(TARGET_IS_HEADLESS), true)
display-hals += libcopybit liblight libmemtrack hdmi_cec \
- gpu_tonemapper libdrmutils
+ libdrmutils
endif
display-hals += gralloc
@@ -18,4 +17,3 @@
include $(call all-named-subdir-makefiles,$(display-hals))
endif
endif
-endif #TARGET_DISABLE_DISPLAY
diff --git a/composer/Android.mk b/composer/Android.mk
index 9278fc2..306a7dc 100644
--- a/composer/Android.mk
+++ b/composer/Android.mk
@@ -21,7 +21,7 @@
liblog libfmq libhardware_legacy \
libsdmcore libqservice libqdutils libqdMetaData \
libdisplaydebug libsdmutils libgrallocutils libui \
- libEGL libGLESv2 libGLESv3 \
+ libgpu_tonemapper libEGL libGLESv2 libGLESv3 \
vendor.qti.hardware.display.composer@1.0 \
vendor.qti.hardware.display.composer@2.0 \
android.hardware.graphics.composer@2.1 \
@@ -45,12 +45,8 @@
vendor.display.config@1.10 \
vendor.display.config@1.11 \
vendor.display.config@1.12 \
- vendor.display.config@1.13
-
-ifneq ($(TARGET_IS_HEADLESS), true)
- LOCAL_SHARED_LIBRARIES += libgpu_tonemapper
-endif
-
+ vendor.display.config@1.13 \
+ vendor.display.config@1.14
LOCAL_SRC_FILES := QtiComposer.cpp QtiComposerClient.cpp service.cpp \
QtiComposerHandleImporter.cpp \
@@ -77,7 +73,9 @@
hwc_display_virtual_gpu.cpp \
gl_common.cpp \
gl_color_convert.cpp \
- gl_color_convert_impl.cpp
+ gl_color_convert_impl.cpp \
+ gl_layer_stitch.cpp \
+ gl_layer_stitch_impl.cpp
LOCAL_INIT_RC := vendor.qti.hardware.display.composer-service.rc
LOCAL_VINTF_FRAGMENTS := vendor.qti.hardware.display.composer-service.xml
diff --git a/composer/QtiComposerClient.cpp b/composer/QtiComposerClient.cpp
index 9b66951..253978d 100644
--- a/composer/QtiComposerClient.cpp
+++ b/composer/QtiComposerClient.cpp
@@ -134,7 +134,8 @@
}
auto ret = client->mCallback->onHotplug(display, connect);
- ALOGE_IF(!ret.isOk(), "failed to send onHotplug: %s", ret.description().c_str());
+ ALOGW_IF(!ret.isOk(), "failed to send onHotplug: %s. SF likely unavailable.",
+ ret.description().c_str());
if (connect == composer_V2_1::IComposerCallback::Connection::DISCONNECTED) {
// Trigger refresh to make sure disconnect event received/updated properly by SurfaceFlinger.
@@ -152,14 +153,16 @@
void QtiComposerClient::onRefresh(hwc2_callback_data_t callbackData, hwc2_display_t display) {
auto client = reinterpret_cast<QtiComposerClient*>(callbackData);
auto ret = client->mCallback->onRefresh(display);
- ALOGE_IF(!ret.isOk(), "failed to send onRefresh: %s", ret.description().c_str());
+ ALOGW_IF(!ret.isOk(), "failed to send onRefresh: %s. SF likely unavailable.",
+ ret.description().c_str());
}
void QtiComposerClient::onVsync(hwc2_callback_data_t callbackData, hwc2_display_t display,
int64_t timestamp) {
auto client = reinterpret_cast<QtiComposerClient*>(callbackData);
auto ret = client->mCallback->onVsync(display, timestamp);
- ALOGI_IF(!ret.isOk(), "failed to send onVsync: %s", ret.description().c_str());
+ ALOGW_IF(!ret.isOk(), "failed to send onVsync: %s. SF likely unavailable.",
+ ret.description().c_str());
}
// convert fenceFd to or from hidl_handle
@@ -1724,10 +1727,45 @@
return false;
}
- // SetLayerPerFrameMetadataBlobs is not supported
- auto err = Error::UNSUPPORTED;
- mWriter.setError(getCommandLoc(), static_cast<Error>(err));
+ uint32_t numBlobs = read();
+ length--;
+ std::vector<IComposerClient::PerFrameMetadataBlob> metadata;
+ for (size_t i = 0; i < numBlobs; i++) {
+ IComposerClient::PerFrameMetadataKey key =
+ static_cast<IComposerClient::PerFrameMetadataKey>(readSigned());
+ uint32_t blobSize = read();
+ length -= 2;
+
+ if (length * sizeof(uint32_t) < blobSize) {
+ return false;
+ }
+
+ metadata.push_back({key, std::vector<uint8_t>()});
+ IComposerClient::PerFrameMetadataBlob& metadataBlob = metadata.back();
+ metadataBlob.blob.resize(blobSize);
+ readBlob(blobSize, metadataBlob.blob.data());
+ }
+
+ std::vector<int32_t> keys;
+ std::vector<uint32_t> sizes_of_metablob_;
+ std::vector<uint8_t> blob_of_data_;
+ keys.reserve(metadata.size());
+ sizes_of_metablob_.reserve(metadata.size());
+ for (const auto& m : metadata) {
+ keys.push_back(static_cast<int32_t>(m.key));
+ sizes_of_metablob_.push_back(m.blob.size());
+ for (uint8_t i = 0; i < m.blob.size(); i++) {
+ blob_of_data_.push_back(m.blob[i]);
+ }
+ }
+ auto err = mClient.hwc_session_->SetLayerPerFrameMetadataBlobs(mDisplay, mLayer, metadata.size(),
+ keys.data(),
+ sizes_of_metablob_.data(),
+ blob_of_data_.data());
+ if (static_cast<Error>(err) != Error::NONE) {
+ mWriter.setError(getCommandLoc(), static_cast<Error>(err));
+ }
return true;
}
diff --git a/composer/QtiComposerCommandBuffer.h b/composer/QtiComposerCommandBuffer.h
index b352670..5461c56 100644
--- a/composer/QtiComposerCommandBuffer.h
+++ b/composer/QtiComposerCommandBuffer.h
@@ -763,6 +763,13 @@
return (static_cast<uint64_t>(hi) << 32) | lo;
}
+ void readBlob(uint32_t size, void* blob) {
+ memcpy(blob, &mData[mDataRead], size);
+ uint32_t numElements = size / sizeof(uint32_t);
+ mDataRead += numElements;
+ mDataRead += (size - numElements * sizeof(uint32_t) != 0) ? 1 : 0;
+ }
+
IQtiComposerClient::Color readColor() {
uint32_t val = read();
return IQtiComposerClient::Color{
diff --git a/composer/display_null.h b/composer/display_null.h
index 24fc00c..7222faa 100644
--- a/composer/display_null.h
+++ b/composer/display_null.h
@@ -95,6 +95,7 @@
MAKE_NO_OP(SetCursorPosition(int, int))
MAKE_NO_OP(SetRefreshRate(uint32_t, bool))
MAKE_NO_OP(GetPanelBrightness(float *))
+ MAKE_NO_OP(GetPanelMaxBrightness(uint32_t *))
MAKE_NO_OP(GetRefreshRate(uint32_t *))
MAKE_NO_OP(SetVSyncState(bool))
MAKE_NO_OP(SetMixerResolution(uint32_t, uint32_t))
diff --git a/composer/gl_color_convert.cpp b/composer/gl_color_convert.cpp
index 03f7377..f398059 100644
--- a/composer/gl_color_convert.cpp
+++ b/composer/gl_color_convert.cpp
@@ -35,7 +35,7 @@
namespace sdm {
GLColorConvert* GLColorConvert::GetInstance(GLRenderTarget target, bool secure) {
- GLColorConvertImpl* color_convert = new GLColorConvertImpl(target, secure);
+ GLColorConvertImpl* color_convert = new GLColorConvertImpl(target, secure);
if (color_convert == nullptr) {
DLOGE("Failed to create color convert instance for %d target %d secure", target, secure);
return nullptr;
diff --git a/composer/gl_color_convert.h b/composer/gl_color_convert.h
index 2080a97..a4c31ce 100644
--- a/composer/gl_color_convert.h
+++ b/composer/gl_color_convert.h
@@ -31,6 +31,7 @@
#define __GL_COLOR_CONVERT_H__
#include <gralloc_priv.h>
+#include "gl_common.h"
namespace sdm {
@@ -39,13 +40,6 @@
kTargetYUV,
};
-struct GLRect {
- float left = 0.0f;
- float top = 0.0f;
- float right = 0.0f;
- float bottom = 0.0f;
-};
-
class GLColorConvert {
public:
static GLColorConvert* GetInstance(GLRenderTarget target, bool secure);
diff --git a/composer/gl_color_convert_impl.cpp b/composer/gl_color_convert_impl.cpp
index fb5d060..9aa22e1 100644
--- a/composer/gl_color_convert_impl.cpp
+++ b/composer/gl_color_convert_impl.cpp
@@ -162,7 +162,7 @@
SetProgram(ctx_.program_id);
SetSourceBuffer(src_hnd);
- SetDestinationBuffer(dst_hnd);
+ SetDestinationBuffer(dst_hnd, dst_rect);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, kFullScreenVertices);
diff --git a/composer/gl_common.cpp b/composer/gl_common.cpp
index d45b5d9..aa3bc45 100644
--- a/composer/gl_common.cpp
+++ b/composer/gl_common.cpp
@@ -97,17 +97,19 @@
}
}
-void GLCommon::SetDestinationBuffer(const private_handle_t *dst_hnd) {
+void GLCommon::SetDestinationBuffer(const private_handle_t *dst_hnd, const GLRect &dst_rect) {
DTRACE_SCOPED();
EGLImageBuffer *dst_buffer = image_wrapper_.wrap(reinterpret_cast<const void *>(dst_hnd));
if (dst_buffer) {
GL(glBindFramebuffer(GL_FRAMEBUFFER, dst_buffer->getFramebuffer()));
- GL(glViewport(0, 0, dst_buffer->getWidth(), dst_buffer->getHeight()));
+ float width = dst_rect.right - dst_rect.left;
+ float height = dst_rect.bottom - dst_rect.top;
+ GL(glViewport(dst_rect.left, dst_rect.top, width, height));
}
}
-int GLCommon::WaitOnInputFence(const int in_fence_fd) {
+int GLCommon::WaitOnInputFence(int in_fence_fd) {
DTRACE_SCOPED();
EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, in_fence_fd, EGL_NONE};
EGLSyncKHR sync = eglCreateSyncKHR(eglGetCurrentDisplay(), EGL_SYNC_NATIVE_FENCE_ANDROID,
@@ -145,12 +147,16 @@
return fd;
}
-void GLCommon::DestroyContext(const GLContext* ctx) {
+void GLCommon::DestroyContext(GLContext* ctx) {
DTRACE_SCOPED();
+
+ // Clear egl image buffers.
+ image_wrapper_.Deinit();
+
+ EGL(DeleteProgram(ctx->program_id));
EGL(eglMakeCurrent(ctx->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
EGL(eglDestroySurface(ctx->egl_display, ctx->egl_surface));
EGL(eglDestroyContext(ctx->egl_display, ctx->egl_context));
- EGL(DeleteProgram(ctx->program_id));
EGL(eglTerminate(ctx->egl_display));
}
diff --git a/composer/gl_common.h b/composer/gl_common.h
index 4089e87..c77988b 100644
--- a/composer/gl_common.h
+++ b/composer/gl_common.h
@@ -37,6 +37,13 @@
namespace sdm {
+struct GLRect {
+ float left = 0.0f;
+ float top = 0.0f;
+ float right = 0.0f;
+ float bottom = 0.0f;
+};
+
struct GLContext {
EGLDisplay egl_display = EGL_NO_DISPLAY;
EGLContext egl_context = EGL_NO_CONTEXT;
@@ -51,11 +58,11 @@
virtual void DumpShaderLog(int shader);
virtual void MakeCurrent(const GLContext *ctx);
virtual void SetProgram(uint32_t id);
- virtual void SetDestinationBuffer(const private_handle_t *dst_hnd);
+ virtual void SetDestinationBuffer(const private_handle_t *dst_hnd, const GLRect &dst_rect);
virtual void SetSourceBuffer(const private_handle_t *src_hnd);
- virtual void DestroyContext(const GLContext *ctx);
+ virtual void DestroyContext(GLContext *ctx);
virtual void DeleteProgram(uint32_t id);
- virtual int WaitOnInputFence(const int in_fence_fd);
+ virtual int WaitOnInputFence(int in_fence_fd);
virtual int CreateOutputFence();
protected:
diff --git a/composer/gl_layer_stitch.cpp b/composer/gl_layer_stitch.cpp
new file mode 100644
index 0000000..4d54a2c
--- /dev/null
+++ b/composer/gl_layer_stitch.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "gl_layer_stitch_impl.h"
+#include "gl_layer_stitch.h"
+
+#define __CLASS__ "GLLayerStitch"
+
+namespace sdm {
+
+GLLayerStitch* GLLayerStitch::GetInstance(bool secure) {
+ GLLayerStitchImpl *layer_stitch = new GLLayerStitchImpl(secure);
+ if (layer_stitch == nullptr) {
+ DLOGE("Failed to create layer stitch instance. secure: %d", secure);
+ return nullptr;
+ }
+
+ int status = layer_stitch->Init();
+ if (status != 0) {
+ DLOGE("Failed to initialize GL layer stitch instance %d", status);
+ delete layer_stitch;
+ return nullptr;
+ }
+
+ DLOGI("Created instance successfully");
+
+ return layer_stitch;
+}
+
+void GLLayerStitch::Destroy(GLLayerStitch *intf) {
+ GLLayerStitchImpl *layer_stitch = static_cast<GLLayerStitchImpl *>(intf);
+ if (layer_stitch->Deinit() != 0) {
+ DLOGE("De Init failed");
+ }
+
+ delete layer_stitch;
+}
+
+} // namespace sdm
diff --git a/composer/gl_layer_stitch.h b/composer/gl_layer_stitch.h
new file mode 100644
index 0000000..35eb92d
--- /dev/null
+++ b/composer/gl_layer_stitch.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __GL_LAYER_STITCH_H__
+#define __GL_LAYER_STITCH_H__
+
+#include <gralloc_priv.h>
+#include "gl_common.h"
+
+namespace sdm {
+
+class GLLayerStitch {
+ public:
+ static GLLayerStitch* GetInstance(bool secure);
+ static void Destroy(GLLayerStitch *intf);
+
+ virtual int Blit(const private_handle_t *src_hnd, const private_handle_t *dst_hnd,
+ const GLRect &src_rect, const GLRect &dst_rect, int src_acquire_fence_fd,
+ int dst_acquire_fence_fd, int *release_fence_fd) = 0;
+ protected:
+ virtual ~GLLayerStitch() { }
+};
+
+} // namespace sdm
+
+#endif // __GL_LAYER_STITCH_H__
diff --git a/composer/gl_layer_stitch_impl.cpp b/composer/gl_layer_stitch_impl.cpp
new file mode 100644
index 0000000..f8e33cd
--- /dev/null
+++ b/composer/gl_layer_stitch_impl.cpp
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "gl_layer_stitch_impl.h"
+
+#define __CLASS__ "GLLayerStitchImpl"
+
+namespace sdm {
+
+const float kFullScreenVertices[] = {
+ -1.0f, 3.0f,
+ -1.0f, -1.0f,
+ 3.0f, -1.0f
+};
+
+const float kFullScreenTexCoords[] = {
+ 0.0f, 2.0f,
+ 0.0f, 0.0f,
+ 2.0f, 0.0f
+};
+
+const char *kVertexShader1 = ""
+ "#version 300 es \n"
+ "precision highp float; \n"
+ "layout(location = 0) in vec2 in_pos; \n"
+ "layout(location = 1) in vec2 in_uv; \n"
+ " \n"
+ "out vec2 uv; \n"
+ " \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = vec4(in_pos, 0.0, 1.0); \n"
+ " uv = in_uv; \n"
+ "} \n";
+
+const char *kConvertRenderRGBShader = ""
+ "precision highp float; \n"
+ " \n"
+ "layout(binding = 0) uniform sampler2D u_sTexture; \n"
+ " \n"
+ "in vec2 uv; \n"
+ "out vec4 color; \n"
+ " \n"
+ "void main() \n"
+ "{ \n"
+ " color = texture(u_sTexture, uv); \n"
+ "} \n";
+
+int GLLayerStitchImpl::CreateContext(bool secure) {
+ ctx_.egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ EGL(eglBindAPI(EGL_OPENGL_ES_API));
+
+ // Initialize current display.
+ EGL(eglInitialize(ctx_.egl_display, nullptr, nullptr));
+
+ // Get attributes corresponing to render target.
+ // Describes Framebuffer attributes like buffer depth, color space etc;
+ EGLConfig eglConfig;
+ int numConfig = 0;
+ EGLint eglConfigAttribList[] = {EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 8,
+ EGL_NONE};
+ EGL(eglChooseConfig(ctx_.egl_display, eglConfigAttribList, &eglConfig, 1, &numConfig));
+
+ // When GPU runs in protected context it can read from
+ // - Protected sources
+ // - UnProtected source
+ // and writes into Protected buffer.
+ // VS in UnProtected context it can read/write happen from/to Unprotected sources.
+ EGLint egl_contextAttribList[] = {EGL_CONTEXT_CLIENT_VERSION, 3,
+ secure ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
+ secure ? EGL_TRUE : EGL_NONE,
+ EGL_NONE};
+ ctx_.egl_context = eglCreateContext(ctx_.egl_display, eglConfig, NULL, egl_contextAttribList);
+
+ // eglCreatePbufferSurface creates an off-screen pixel buffer surface and returns its handle
+ EGLint egl_surfaceAttribList[] = {EGL_WIDTH, 1,
+ EGL_HEIGHT, 1,
+ secure ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
+ secure ? EGL_TRUE : EGL_NONE,
+ EGL_NONE};
+ ctx_.egl_surface = eglCreatePbufferSurface(ctx_.egl_display, eglConfig, egl_surfaceAttribList);
+
+ // eglMakeCurrent attaches rendering context to rendering surface.
+ MakeCurrent(&ctx_);
+
+ DLOGI("Created context = %p", (void *)(&ctx_.egl_context));
+
+ // Load Vertex and Fragment shaders.
+ const char *fragment_shaders[2] = { };
+ int count = 0;
+ const char *version = "#version 300 es\n";
+
+ fragment_shaders[count++] = version;
+
+ // ToDo: Add support to yuv_to_rgb shader.
+ fragment_shaders[count++] = kConvertRenderRGBShader;
+
+ ctx_.program_id = LoadProgram(1, &kVertexShader1, count, fragment_shaders);
+
+ return 0;
+}
+
+int GLLayerStitchImpl::Blit(const private_handle_t *src_hnd, const private_handle_t *dst_hnd,
+ const GLRect &src_rect, const GLRect &dst_rect,
+ int src_acquire_fence_fd, int dst_acquire_fence_fd,
+ int *release_fence_fd) {
+ DTRACE_SCOPED();
+ // eglMakeCurrent attaches rendering context to rendering surface.
+ MakeCurrent(&ctx_);
+
+ SetProgram(ctx_.program_id);
+
+ SetSourceBuffer(src_hnd);
+ SetDestinationBuffer(dst_hnd, dst_rect);
+
+ glEnableVertexAttribArray(0);
+ glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, kFullScreenVertices);
+ glEnableVertexAttribArray(1);
+ glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, kFullScreenTexCoords);
+ glDrawArrays(GL_TRIANGLES, 0, 3);
+
+ int in_fence_fd = sync_merge(__CLASS__, src_acquire_fence_fd, dst_acquire_fence_fd);
+ if (in_fence_fd >= 0) {
+ WaitOnInputFence(in_fence_fd);
+ }
+
+ // Create output fence for client to wait on.
+ *release_fence_fd = CreateOutputFence();
+
+ return 0;
+}
+
+int GLLayerStitchImpl::Init() {
+ return CreateContext(secure_);
+}
+
+int GLLayerStitchImpl::Deinit() {
+ MakeCurrent(&ctx_);
+ DestroyContext(&ctx_);
+
+ return 0;
+}
+
+GLLayerStitchImpl::~GLLayerStitchImpl() {}
+
+GLLayerStitchImpl::GLLayerStitchImpl(bool secure) {
+ secure_ = secure;
+}
+
+} // namespace sdm
+
diff --git a/composer/gl_layer_stitch_impl.h b/composer/gl_layer_stitch_impl.h
new file mode 100644
index 0000000..f4d438d
--- /dev/null
+++ b/composer/gl_layer_stitch_impl.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __GL_LAYER_STITCH_IMPL_H__
+#define __GL_LAYER_STITCH_IMPL_H__
+
+#include <sync/sync.h>
+
+#include "gl_layer_stitch.h"
+#include "gl_common.h"
+
+namespace sdm {
+
+class GLLayerStitchImpl : public GLLayerStitch, public GLCommon {
+ public:
+ explicit GLLayerStitchImpl(bool secure);
+ virtual ~GLLayerStitchImpl();
+ virtual int Blit(const private_handle_t *src_hnd, const private_handle_t *dst_hnd,
+ const GLRect &src_rect, const GLRect &dst_rect,
+ int src_acquire_fence_fd, int dst_acquire_fence_fd, int *release_fence_fd);
+ virtual int CreateContext(bool secure);
+ virtual int Init();
+ virtual int Deinit();
+ private:
+ bool secure_ = false;
+ GLContext ctx_;
+};
+
+} // namespace sdm
+
+#endif // __GL_LAYER_STITCH_IMPL_H__
diff --git a/composer/hwc_buffer_allocator.cpp b/composer/hwc_buffer_allocator.cpp
index f9fef97..1b033db 100644
--- a/composer/hwc_buffer_allocator.cpp
+++ b/composer/hwc_buffer_allocator.cpp
@@ -36,6 +36,7 @@
#include "gr_utils.h"
#include "hwc_buffer_allocator.h"
#include "hwc_debugger.h"
+#include "hwc_layers.h"
#define __CLASS__ "HWCBufferAllocator"
@@ -209,6 +210,7 @@
alloc_buffer_info->aligned_height = UINT32(hnd->height);
alloc_buffer_info->size = hnd->size;
alloc_buffer_info->id = hnd->id;
+ alloc_buffer_info->format = HWCLayer::GetSDMFormat(hnd->format, hnd->flags);
buffer_info->private_data = reinterpret_cast<void *>(hnd);
return kErrorNone;
diff --git a/composer/hwc_buffer_sync_handler.cpp b/composer/hwc_buffer_sync_handler.cpp
index 7cab4c0..24c8336 100644
--- a/composer/hwc_buffer_sync_handler.cpp
+++ b/composer/hwc_buffer_sync_handler.cpp
@@ -49,7 +49,7 @@
if (fd >= 0) {
error = sync_wait(fd, timeout);
if (error < 0) {
- DLOGE("sync_wait() error on fd = %d, timeout = %dms. (errno = %d \"%s\")", fd, timeout, errno,
+ DLOGW("sync_wait() error on fd = %d, timeout = %dms. (errno = %d \"%s\")", fd, timeout, errno,
strerror(errno));
return kErrorTimeOut;
}
diff --git a/composer/hwc_callbacks.cpp b/composer/hwc_callbacks.cpp
index 857716b..e36a60f 100644
--- a/composer/hwc_callbacks.cpp
+++ b/composer/hwc_callbacks.cpp
@@ -105,9 +105,6 @@
return HWC2::Error::BadParameter;
}
- if (!pointer) {
- return HWC2::Error::NoResources;
- }
return HWC2::Error::None;
}
diff --git a/composer/hwc_display.cpp b/composer/hwc_display.cpp
index 9687858..94bce1f 100644
--- a/composer/hwc_display.cpp
+++ b/composer/hwc_display.cpp
@@ -1133,20 +1133,22 @@
if (out_num_keys == nullptr) {
return HWC2::Error::BadParameter;
}
- *out_num_keys = UINT32(PerFrameMetadataKey::MAX_FRAME_AVERAGE_LIGHT_LEVEL) + 1;
- if (out_keys != nullptr) {
- out_keys[0] = PerFrameMetadataKey::DISPLAY_RED_PRIMARY_X;
- out_keys[1] = PerFrameMetadataKey::DISPLAY_RED_PRIMARY_Y;
- out_keys[2] = PerFrameMetadataKey::DISPLAY_GREEN_PRIMARY_X;
- out_keys[3] = PerFrameMetadataKey::DISPLAY_GREEN_PRIMARY_Y;
- out_keys[4] = PerFrameMetadataKey::DISPLAY_BLUE_PRIMARY_X;
- out_keys[5] = PerFrameMetadataKey::DISPLAY_BLUE_PRIMARY_Y;
- out_keys[6] = PerFrameMetadataKey::WHITE_POINT_X;
- out_keys[7] = PerFrameMetadataKey::WHITE_POINT_Y;
- out_keys[8] = PerFrameMetadataKey::MAX_LUMINANCE;
- out_keys[9] = PerFrameMetadataKey::MIN_LUMINANCE;
- out_keys[10] = PerFrameMetadataKey::MAX_CONTENT_LIGHT_LEVEL;
- out_keys[11] = PerFrameMetadataKey::MAX_FRAME_AVERAGE_LIGHT_LEVEL;
+
+ DisplayConfigFixedInfo fixed_info = {};
+ display_intf_->GetConfig(&fixed_info);
+ uint32_t num_keys = 0;
+ if (fixed_info.hdr_plus_supported) {
+ num_keys = UINT32(PerFrameMetadataKey::HDR10_PLUS_SEI) + 1;
+ } else {
+ num_keys = UINT32(PerFrameMetadataKey::MAX_FRAME_AVERAGE_LIGHT_LEVEL) + 1;
+ }
+ if (out_keys == nullptr) {
+ *out_num_keys = num_keys;
+ } else {
+ uint32_t max_out_key_elements = std::min(*out_num_keys, num_keys);
+ for (int32_t i = 0; i < max_out_key_elements; i++) {
+ out_keys[i] = static_cast<PerFrameMetadataKey>(i);
+ }
}
return HWC2::Error::None;
}
@@ -1282,8 +1284,16 @@
} break;
case kPanelDeadEvent:
case kDisplayPowerResetEvent: {
- SEQUENCE_WAIT_SCOPE_LOCK(HWCSession::locker_[id_]);
- validated_ = false;
+ // Mutex scope
+ {
+ SEQUENCE_WAIT_SCOPE_LOCK(HWCSession::locker_[id_]);
+ validated_ = false;
+ }
+ // TODO(user): Following scenario need to be addressed
+ // If panel or HW is in bad state for either ESD or HWR, there is no acquired lock between
+ // this scope and call to DisplayPowerReset.
+ // Prepare or commit could operate on the display since locker_[id_] is free and most likely
+ // result in a failure since ESD/HWR has been requested during this time period.
if (event_handler_) {
event_handler_->DisplayPowerReset();
} else {
@@ -1343,7 +1353,7 @@
Layer *layer = hwc_layer->GetSDMLayer();
LayerComposition &composition = layer->composition;
- if (composition == kCompositionSDE) {
+ if (composition == kCompositionSDE || composition == kCompositionStitch) {
layer_requests_[hwc_layer->GetId()] = HWC2::LayerRequest::ClearClientTarget;
}
@@ -1494,13 +1504,29 @@
return HWC2::Error::None;
}
- if (out_types == nullptr) {
- // We support HDR10 and HLG
- *out_num_types = 2;
+ uint32_t num_types = 0;
+ if (fixed_info.hdr_plus_supported) {
+ num_types = UINT32(Hdr::HDR10_PLUS) - 1;
} else {
- // HDR10 and HLG are supported
- out_types[0] = HAL_HDR_HDR10;
- out_types[1] = HAL_HDR_HLG;
+ num_types = UINT32(Hdr::HLG) - 1;
+ }
+
+ // We support HDR10, HLG and HDR10_PLUS.
+ if (out_types == nullptr) {
+ *out_num_types = num_types;
+ } else {
+ uint32_t max_out_types = std::min(*out_num_types, num_types);
+ int32_t type = static_cast<int32_t>(Hdr::DOLBY_VISION);
+ for (int32_t i = 0; i < max_out_types; i++) {
+ while (type == static_cast<int32_t>(Hdr::DOLBY_VISION) /* Skip list */) {
+ // Skip the type
+ type++;
+ }
+ if (type > (num_types + 1)) {
+ break;
+ }
+ out_types[i] = type++;
+ }
*out_max_luminance = fixed_info.max_luminance;
*out_max_average_luminance = fixed_info.average_luminance;
*out_min_luminance = fixed_info.min_luminance;
diff --git a/composer/hwc_display.h b/composer/hwc_display.h
index 84a0581..6323847 100644
--- a/composer/hwc_display.h
+++ b/composer/hwc_display.h
@@ -44,6 +44,7 @@
using android::hardware::graphics::common::V1_2::ColorMode;
using android::hardware::graphics::common::V1_1::Dataspace;
using android::hardware::graphics::common::V1_1::RenderIntent;
+using android::hardware::graphics::common::V1_2::Hdr;
namespace sdm {
@@ -311,6 +312,9 @@
virtual HWC2::Error GetPanelBrightness(float *brightness) {
return HWC2::Error::Unsupported;
}
+ virtual HWC2::Error GetPanelMaxBrightness(uint32_t *max_brightness_level) {
+ return HWC2::Error::Unsupported;
+ }
virtual HWC2::Error GetDisplayConfigs(uint32_t *out_num_configs, hwc2_config_t *out_configs);
virtual HWC2::Error GetDisplayAttribute(hwc2_config_t config, HWC2::Attribute attribute,
int32_t *out_value);
diff --git a/composer/hwc_display_builtin.cpp b/composer/hwc_display_builtin.cpp
index 85cdda6..439170a 100644
--- a/composer/hwc_display_builtin.cpp
+++ b/composer/hwc_display_builtin.cpp
@@ -47,6 +47,13 @@
namespace sdm {
+static void SetRect(LayerRect &src_rect, GLRect *target) {
+ target->left = src_rect.left;
+ target->top = src_rect.top;
+ target->right = src_rect.right;
+ target->bottom = src_rect.bottom;
+}
+
int HWCDisplayBuiltIn::Create(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
qService::QService *qservice, hwc2_display_t id, int32_t sdm_id,
@@ -96,7 +103,7 @@
: HWCDisplay(core_intf, buffer_allocator, callbacks, event_handler, qservice, kBuiltIn, id,
sdm_id, DISPLAY_CLASS_BUILTIN),
buffer_allocator_(buffer_allocator),
- cpu_hint_(NULL) {
+ cpu_hint_(NULL), layer_stitch_task_(*this) {
}
int HWCDisplayBuiltIn::Init() {
@@ -129,6 +136,10 @@
is_primary_ = display_intf_->IsPrimaryDisplay();
+ if (!InitLayerStitch()) {
+ DLOGW("Failed to initialize Layer Stitch context");
+ }
+
return status;
}
@@ -150,6 +161,10 @@
// Fill in the remaining blanks in the layers and add them to the SDM layerstack
BuildLayerStack();
+
+ // Add stitch layer to layer stack.
+ AppendStitchLayer();
+
// Checks and replaces layer stack for solid fill
SolidFillPrepare();
@@ -242,13 +257,52 @@
return skip_commit;
}
+HWC2::Error HWCDisplayBuiltIn::CommitStitchLayers() {
+ if (!validated_ || skip_commit_) {
+ return HWC2::Error::None;
+ }
+
+ if (disable_layer_stitch_) {
+ return HWC2::Error::None;
+ }
+
+ for (auto &layer : layer_stack_.layers) {
+ LayerComposition &composition = layer->composition;
+ if (composition != kCompositionStitch) {
+ continue;
+ }
+
+ LayerStitchStitchContext ctx = {};
+ // Stitch target doesn't have an input fence.
+ // Render all layers at specified destination.
+ LayerBuffer &input_buffer = layer->input_buffer;
+ ctx.src_hnd = reinterpret_cast<const private_handle_t *>(input_buffer.buffer_id);
+ Layer *stitch_layer = stitch_target_->GetSDMLayer();
+ LayerBuffer &output_buffer = stitch_layer->input_buffer;
+ ctx.dst_hnd = reinterpret_cast<const private_handle_t *>(output_buffer.buffer_id);
+ SetRect(layer->stitch_dst_rect, &ctx.dst_rect);
+ ctx.src_acquire_fence_fd = input_buffer.acquire_fence_fd;
+
+ layer_stitch_task_.PerformTask(LayerStitchTaskCode::kCodeStitch, &ctx);
+
+ // Merge with current fence and close previous one.
+ int acquire_fence = sync_merge(__CLASS__, output_buffer.acquire_fence_fd, ctx.release_fence_fd);
+ CloseFd(&output_buffer.acquire_fence_fd);
+ CloseFd(&ctx.release_fence_fd);
+
+ output_buffer.acquire_fence_fd = acquire_fence;
+ }
+
+ return HWC2::Error::None;
+}
+
HWC2::Error HWCDisplayBuiltIn::Present(int32_t *out_retire_fence) {
auto status = HWC2::Error::None;
DTRACE_SCOPED();
if (!is_primary_ && active_secure_sessions_[kSecureDisplay]) {
- return status;
+ return status;
} else if (display_paused_) {
DisplayError error = display_intf_->Flush(&layer_stack_);
validated_ = false;
@@ -256,12 +310,26 @@
DLOGE("Flush failed. Error = %d", error);
}
} else {
+ status = CommitStitchLayers();
+ if (status != HWC2::Error::None) {
+ DLOGE("Stitch failed: %d", status);
+ return status;
+ }
+
status = CommitLayerStack();
if (status == HWC2::Error::None) {
HandleFrameOutput();
SolidFillCommit();
status = HWCDisplay::PostCommitLayerStack(out_retire_fence);
}
+
+ if (stitch_target_) {
+ // Close Stitch buffer acquire fence.
+ Layer *stitch_layer = stitch_target_->GetSDMLayer();
+ LayerBuffer &output_buffer = stitch_layer->input_buffer;
+ CloseFd(&output_buffer.acquire_fence_fd);
+ CloseFd(&output_buffer.release_fence_fd);
+ }
}
CloseFd(&output_buffer_.acquire_fence_fd);
@@ -943,6 +1011,15 @@
return HWC2::Error::None;
}
+HWC2::Error HWCDisplayBuiltIn::GetPanelMaxBrightness(uint32_t *max_brightness_level) {
+ DisplayError ret = display_intf_->GetPanelMaxBrightness(max_brightness_level);
+ if (ret != kErrorNone) {
+ return HWC2::Error::NoResources;
+ }
+
+ return HWC2::Error::None;
+}
+
HWC2::Error HWCDisplayBuiltIn::SetBLScale(uint32_t level) {
DisplayError ret = display_intf_->SetBLScale(level);
if (ret != kErrorNone) {
@@ -989,4 +1066,142 @@
return false;
}
+int HWCDisplayBuiltIn::Deinit() {
+ // Destory color convert instance. This destroys thread and underlying GL resources.
+ if (gl_layer_stitch_) {
+ layer_stitch_task_.PerformTask(LayerStitchTaskCode::kCodeDestroyInstance, nullptr);
+ }
+
+ return HWCDisplay::Deinit();
+}
+
+void HWCDisplayBuiltIn::OnTask(const LayerStitchTaskCode &task_code,
+ SyncTask<LayerStitchTaskCode>::TaskContext *task_context) {
+ switch (task_code) {
+ case LayerStitchTaskCode::kCodeGetInstance: {
+ gl_layer_stitch_ = GLLayerStitch::GetInstance(false /* Non-secure */);
+ }
+ break;
+ case LayerStitchTaskCode::kCodeStitch: {
+ DTRACE_SCOPED();
+ LayerStitchStitchContext* ctx = reinterpret_cast<LayerStitchStitchContext*>(task_context);
+ gl_layer_stitch_->Blit(ctx->src_hnd, ctx->dst_hnd, ctx->src_rect, ctx->dst_rect,
+ ctx->src_acquire_fence_fd, ctx->dst_acquire_fence_fd,
+ &(ctx->release_fence_fd));
+ }
+ break;
+ case LayerStitchTaskCode::kCodeDestroyInstance: {
+ if (gl_layer_stitch_) {
+ GLLayerStitch::Destroy(gl_layer_stitch_);
+ }
+ }
+ break;
+ }
+}
+
+bool HWCDisplayBuiltIn::InitLayerStitch() {
+ if (!is_primary_) {
+ // Disable on all non-primary builtins.
+ DLOGI("Non-primary builtin.");
+ disable_layer_stitch_ = true;
+ return true;
+ }
+
+ // Disable by default.
+ int value = 1;
+ Debug::Get()->GetProperty(DISABLE_LAYER_STITCH, &value);
+ disable_layer_stitch_ = (value == 1);
+
+ if (disable_layer_stitch_) {
+ DLOGI("Layer Stitch Disabled !!!");
+ return true;
+ }
+
+ // Initialize stitch context. This will be non-secure.
+ layer_stitch_task_.PerformTask(LayerStitchTaskCode::kCodeGetInstance, nullptr);
+ if (gl_layer_stitch_ == nullptr) {
+ DLOGE("Failed to get LayerStitch Instance");
+ return false;
+ }
+
+ if (!AllocateStitchBuffer()) {
+ return true;
+ }
+
+ stitch_target_ = new HWCLayer(id_, static_cast<HWCBufferAllocator *>(buffer_allocator_));
+
+ // Populate buffer params and pvt handle.
+ InitStitchTarget();
+
+ DLOGI("Created LayerStitch instance: %p", gl_layer_stitch_);
+
+ return true;
+}
+
+bool HWCDisplayBuiltIn::AllocateStitchBuffer() {
+ // Buffer dimensions: FB width * (1.5 * height)
+
+ DisplayError error = display_intf_->GetFrameBufferConfig(&fb_config_);
+ if (error != kErrorNone) {
+ DLOGE("Get frame buffer config failed. Error = %d", error);
+ return false;
+ }
+
+ BufferConfig &config = buffer_info_.buffer_config;
+ config.width = fb_config_.x_pixels;
+ config.height = fb_config_.y_pixels * kBufferHeightFactor;
+
+ // By default UBWC is enabled and below property is global enable/disable for all
+ // buffers allocated through gralloc , including framebuffer targets.
+ int ubwc_disabled = 0;
+ HWCDebugHandler::Get()->GetProperty(DISABLE_UBWC_PROP, &ubwc_disabled);
+ config.format = ubwc_disabled ? kFormatRGBA8888 : kFormatRGBA8888Ubwc;
+
+ config.gfx_client = true;
+
+ // Populate default params.
+ config.secure = false;
+ config.cache = false;
+ config.secure_camera = false;
+
+ error = buffer_allocator_->AllocateBuffer(&buffer_info_);
+
+ if (error != kErrorNone) {
+ DLOGE("Failed to allocate buffer. Error: %d", error);
+ return false;
+ }
+
+ return true;
+}
+
+void HWCDisplayBuiltIn::InitStitchTarget() {
+ LayerBuffer buffer = {};
+ buffer.planes[0].fd = buffer_info_.alloc_buffer_info.fd;
+ buffer.planes[0].offset = 0;
+ buffer.planes[0].stride = buffer_info_.alloc_buffer_info.stride;
+ buffer.size = buffer_info_.alloc_buffer_info.size;
+ buffer.handle_id = buffer_info_.alloc_buffer_info.id;
+ buffer.width = buffer_info_.alloc_buffer_info.aligned_width;
+ buffer.height = buffer_info_.alloc_buffer_info.aligned_height;
+ buffer.unaligned_width = fb_config_.x_pixels;
+ buffer.unaligned_height = fb_config_.y_pixels;
+ buffer.format = buffer_info_.alloc_buffer_info.format;
+
+ Layer *sdm_stitch_target = stitch_target_->GetSDMLayer();
+ sdm_stitch_target->composition = kCompositionStitchTarget;
+ sdm_stitch_target->input_buffer = buffer;
+ sdm_stitch_target->input_buffer.buffer_id = reinterpret_cast<uint64_t>(buffer_info_.private_data);
+}
+
+void HWCDisplayBuiltIn::AppendStitchLayer() {
+ if (disable_layer_stitch_) {
+ return;
+ }
+
+ // Append stitch target buffer to layer stack.
+ Layer *sdm_stitch_target = stitch_target_->GetSDMLayer();
+ sdm_stitch_target->composition = kCompositionStitchTarget;
+ layer_stack_.layers.push_back(sdm_stitch_target);
+}
+
} // namespace sdm
diff --git a/composer/hwc_display_builtin.h b/composer/hwc_display_builtin.h
index a3ed162..b1c0421 100644
--- a/composer/hwc_display_builtin.h
+++ b/composer/hwc_display_builtin.h
@@ -33,12 +33,37 @@
#include <string>
#include <vector>
+#include "utils/sync_task.h"
+#include "utils/constants.h"
#include "cpuhint.h"
#include "hwc_display.h"
+#include "hwc_layers.h"
+
+#include "gl_layer_stitch.h"
namespace sdm {
-class HWCDisplayBuiltIn : public HWCDisplay {
+enum class LayerStitchTaskCode : int32_t {
+ kCodeGetInstance,
+ kCodeStitch,
+ kCodeDestroyInstance,
+};
+
+struct LayerStitchGetInstanceContext : public SyncTask<LayerStitchTaskCode>::TaskContext {
+ LayerBuffer *output_buffer = NULL;
+};
+
+struct LayerStitchStitchContext : public SyncTask<LayerStitchTaskCode>::TaskContext {
+ const private_handle_t* src_hnd = nullptr;
+ const private_handle_t* dst_hnd = nullptr;
+ GLRect src_rect = {};
+ GLRect dst_rect = {};
+ int src_acquire_fence_fd = -1;
+ int dst_acquire_fence_fd = -1;
+ int release_fence_fd = -1;
+};
+
+class HWCDisplayBuiltIn : public HWCDisplay, public SyncTask<LayerStitchTaskCode>::TaskHandler {
public:
enum {
SET_METADATA_DYN_REFRESH_RATE,
@@ -91,6 +116,7 @@
virtual HWC2::Error SetPendingRefresh();
virtual HWC2::Error SetPanelBrightness(float brightness);
virtual HWC2::Error GetPanelBrightness(float *brightness);
+ virtual HWC2::Error GetPanelMaxBrightness(uint32_t *max_brightness_level);
virtual DisplayError TeardownConcurrentWriteback(void);
virtual void SetFastPathComposition(bool enable) {
fast_path_composition_ = enable && !readback_buffer_queued_;
@@ -101,6 +127,7 @@
virtual HWC2::Error SetClientTarget(buffer_handle_t target, int32_t acquire_fence,
int32_t dataspace, hwc_region_t damage);
virtual bool IsSmartPanelConfig(uint32_t config_id);
+ virtual int Deinit();
private:
HWCDisplayBuiltIn(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
@@ -120,6 +147,15 @@
bool CanSkipCommit();
DisplayError SetMixerResolution(uint32_t width, uint32_t height);
DisplayError GetMixerResolution(uint32_t *width, uint32_t *height);
+ HWC2::Error CommitStitchLayers();
+ void AppendStitchLayer();
+ bool InitLayerStitch();
+ void InitStitchTarget();
+ bool AllocateStitchBuffer();
+
+ // SyncTask methods.
+ void OnTask(const LayerStitchTaskCode &task_code,
+ SyncTask<LayerStitchTaskCode>::TaskContext *task_context);
BufferAllocator *buffer_allocator_ = nullptr;
CPUHint *cpu_hint_ = nullptr;
@@ -142,6 +178,12 @@
bool frame_capture_buffer_queued_ = false;
int frame_capture_status_ = -EAGAIN;
bool is_primary_ = false;
+ bool disable_layer_stitch_ = false;
+ HWCLayer* stitch_target_ = nullptr;
+ SyncTask<LayerStitchTaskCode> layer_stitch_task_;
+ GLLayerStitch* gl_layer_stitch_ = nullptr;
+ BufferInfo buffer_info_ = {};
+ DisplayConfigVariableInfo fb_config_ = {};
};
} // namespace sdm
diff --git a/composer/hwc_display_dummy.cpp b/composer/hwc_display_dummy.cpp
index eff0ed6..315a22c 100644
--- a/composer/hwc_display_dummy.cpp
+++ b/composer/hwc_display_dummy.cpp
@@ -59,6 +59,10 @@
return HWC2::Error::None;
}
+HWC2::Error HWCDisplayDummy::SetColorMode(ColorMode mode) {
+ return HWC2::Error::None;
+}
+
HWCDisplayDummy::HWCDisplayDummy(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
qService::QService *qservice, hwc2_display_t id,
diff --git a/composer/hwc_display_dummy.h b/composer/hwc_display_dummy.h
index bf28a03..8f78303 100644
--- a/composer/hwc_display_dummy.h
+++ b/composer/hwc_display_dummy.h
@@ -46,6 +46,7 @@
virtual HWC2::Error Present(int32_t *out_retire_fence);
virtual HWC2::Error GetActiveConfig(hwc2_config_t *out_config);
virtual HWC2::Error UpdatePowerMode(HWC2::PowerMode mode);
+ virtual HWC2::Error SetColorMode(ColorMode mode);
private:
HWCDisplayDummy(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
diff --git a/composer/hwc_layers.cpp b/composer/hwc_layers.cpp
index 426c397..ee8207b 100644
--- a/composer/hwc_layers.cpp
+++ b/composer/hwc_layers.cpp
@@ -234,7 +234,7 @@
if (!buffer) {
if (client_requested_ == HWC2::Composition::Device ||
client_requested_ == HWC2::Composition::Cursor) {
- DLOGE("Invalid buffer handle: %p on layer: %d client requested comp type %d", buffer, id_,
+ DLOGW("Invalid buffer handle: %p on layer: %d client requested comp type %d", buffer, id_,
client_requested_);
::close(acquire_fence);
return HWC2::Error::BadParameter;
@@ -588,6 +588,8 @@
HWC2::Error HWCLayer::SetLayerPerFrameMetadata(uint32_t num_elements,
const PerFrameMetadataKey *keys,
const float *metadata) {
+ auto old_mastering_display = layer_->input_buffer.color_metadata.masteringDisplayInfo;
+ auto old_content_light = layer_->input_buffer.color_metadata.contentLightLevel;
auto &mastering_display = layer_->input_buffer.color_metadata.masteringDisplayInfo;
auto &content_light = layer_->input_buffer.color_metadata.contentLightLevel;
for (uint32_t i = 0; i < num_elements; i++) {
@@ -630,6 +632,51 @@
case PerFrameMetadataKey::MAX_FRAME_AVERAGE_LIGHT_LEVEL:
content_light.minPicAverageLightLevel = UINT32(metadata[i] * 10000);
break;
+ default:
+ break;
+ }
+ }
+ if ((!SameConfig(&old_mastering_display, &mastering_display, UINT32(sizeof(MasteringDisplay)))) ||
+ (!SameConfig(&old_content_light, &content_light, UINT32(sizeof(ContentLightLevel))))) {
+ per_frame_hdr_metadata_ = true;
+ layer_->update_mask.set(kMetadataUpdate);
+ geometry_changes_ |= kDataspace;
+ }
+ return HWC2::Error::None;
+}
+
+HWC2::Error HWCLayer::SetLayerPerFrameMetadataBlobs(uint32_t num_elements,
+ const PerFrameMetadataKey *keys,
+ const uint32_t *sizes,
+ const uint8_t* metadata) {
+ if (!keys || !sizes || !metadata) {
+ DLOGE("metadata or sizes or keys is null");
+ return HWC2::Error::BadParameter;
+ }
+
+ ColorMetaData &color_metadata = layer_->input_buffer.color_metadata;
+ for (uint32_t i = 0; i < num_elements; i++) {
+ switch (keys[i]) {
+ case PerFrameMetadataKey::HDR10_PLUS_SEI:
+ if (sizes[i] > HDR_DYNAMIC_META_DATA_SZ) {
+ DLOGE("Size of HDR10_PLUS_SEI = %d", sizes[i]);
+ return HWC2::Error::BadParameter;
+ }
+ per_frame_hdr_metadata_ = false;
+ // if dynamic metadata changes, store and set needs validate
+ if (!SameConfig(static_cast<const uint8_t*>(color_metadata.dynamicMetaDataPayload),
+ metadata, sizes[i])) {
+ geometry_changes_ |= kDataspace;
+ color_metadata.dynamicMetaDataValid = true;
+ color_metadata.dynamicMetaDataLen = sizes[i];
+ std::memcpy(color_metadata.dynamicMetaDataPayload, metadata, sizes[i]);
+ per_frame_hdr_metadata_ = true;
+ layer_->update_mask.set(kMetadataUpdate);
+ }
+ break;
+ default:
+ DLOGW("Invalid key = %d", keys[i]);
+ return HWC2::Error::BadParameter;
}
}
return HWC2::Error::None;
@@ -945,7 +992,9 @@
use_color_metadata = true;
}
- if (use_color_metadata) {
+ // Since client has set PerFrameMetadata, dataspace will be valid
+ // so we can skip reading from ColorMetaData.
+ if (use_color_metadata && !per_frame_hdr_metadata_) {
ColorMetaData new_metadata = {};
if (sdm::SetCSC(handle, &new_metadata) == kErrorNone) {
// If dataspace is KNOWN, overwrite the gralloc metadata CSC using the previously derived CSC
@@ -960,7 +1009,10 @@
(layer_buffer->color_metadata.range != new_metadata.range)) {
layer_->update_mask.set(kMetadataUpdate);
}
- if (new_metadata.dynamicMetaDataValid &&
+ DLOGV_IF(kTagClient, "Dynamic Metadata valid = %d size = %d",
+ layer_buffer->color_metadata.dynamicMetaDataValid,
+ layer_buffer->color_metadata.dynamicMetaDataLen);
+ if (layer_buffer->color_metadata.dynamicMetaDataValid &&
!SameConfig(layer_buffer->color_metadata.dynamicMetaDataPayload,
new_metadata.dynamicMetaDataPayload, HDR_DYNAMIC_META_DATA_SZ)) {
layer_->update_mask.set(kMetadataUpdate);
diff --git a/composer/hwc_layers.h b/composer/hwc_layers.h
index ac6c21f..fc05433 100644
--- a/composer/hwc_layers.h
+++ b/composer/hwc_layers.h
@@ -33,7 +33,7 @@
#include <hardware/hwcomposer2.h>
#undef HWC2_INCLUDE_STRINGIFICATION
#undef HWC2_USE_CPP11
-#include <android/hardware/graphics/composer/2.2/IComposerClient.h>
+#include <android/hardware/graphics/composer/2.3/IComposerClient.h>
#include <vendor/qti/hardware/display/composer/2.0/IQtiComposerClient.h>
#include <deque>
#include <map>
@@ -42,7 +42,7 @@
#include "hwc_buffer_allocator.h"
using PerFrameMetadataKey =
- android::hardware::graphics::composer::V2_2::IComposerClient::PerFrameMetadataKey;
+ android::hardware::graphics::composer::V2_3::IComposerClient::PerFrameMetadataKey;
using vendor::qti::hardware::display::composer::V2_0::IQtiComposerClient;
namespace sdm {
@@ -100,6 +100,8 @@
HWC2::Error SetLayerVisibleRegion(hwc_region_t visible);
HWC2::Error SetLayerPerFrameMetadata(uint32_t num_elements, const PerFrameMetadataKey *keys,
const float *metadata);
+ HWC2::Error SetLayerPerFrameMetadataBlobs(uint32_t num_elements, const PerFrameMetadataKey *keys,
+ const uint32_t *sizes, const uint8_t* metadata);
HWC2::Error SetLayerZOrder(uint32_t z);
HWC2::Error SetLayerType(IQtiComposerClient::LayerType type);
HWC2::Error SetLayerColorTransform(const float *matrix);
@@ -152,6 +154,7 @@
bool color_transform_matrix_set_ = false;
bool buffer_flipped_ = false;
bool secure_ = false;
+ bool per_frame_hdr_metadata_ = false; // used to track if perframe metadata and blob is set.
// Composition requested by client(SF)
HWC2::Composition client_requested_ = HWC2::Composition::Device;
diff --git a/composer/hwc_session.cpp b/composer/hwc_session.cpp
index 1edb547..b91d229 100644
--- a/composer/hwc_session.cpp
+++ b/composer/hwc_session.cpp
@@ -57,6 +57,7 @@
Locker HWCSession::locker_[HWCCallbacks::kNumDisplays];
bool HWCSession::pending_power_mode_[HWCCallbacks::kNumDisplays];
Locker HWCSession::power_state_[HWCCallbacks::kNumDisplays];
+Locker HWCSession::hdr_locker_[HWCCallbacks::kNumDisplays];
Locker HWCSession::display_config_locker_;
static const int kSolidFillDelay = 100 * 1000;
int HWCSession::null_display_mode_ = 0;
@@ -494,6 +495,21 @@
return HWC2_ERROR_NONE;
}
+int32_t HWCSession::GetVirtualDisplayId() {
+ HWDisplaysInfo hw_displays_info = {};
+ core_intf_->GetDisplaysStatus(&hw_displays_info);
+ for (auto &iter : hw_displays_info) {
+ auto &info = iter.second;
+ if (info.display_type != kVirtual) {
+ continue;
+ }
+
+ return info.display_id;
+ }
+
+ return -1;
+}
+
void HWCSession::Dump(uint32_t *out_size, char *out_buffer) {
if (!out_size) {
return;
@@ -517,7 +533,7 @@
}
uint32_t HWCSession::GetMaxVirtualDisplayCount() {
- return 1;
+ return map_info_virtual_.size();
}
int32_t HWCSession::GetActiveConfig(hwc2_display_t display, hwc2_config_t *out_config) {
@@ -603,6 +619,15 @@
keys, metadata);
}
+int32_t HWCSession:: SetLayerPerFrameMetadataBlobs(hwc2_display_t display,
+ hwc2_layer_t layer, uint32_t num_elements,
+ const int32_t *int_keys, const uint32_t *sizes,
+ const uint8_t *metadata) {
+ auto keys = reinterpret_cast<const PerFrameMetadataKey *>(int_keys);
+ return CallLayerFunction(display, layer, &HWCLayer::SetLayerPerFrameMetadataBlobs,
+ num_elements, keys, sizes, metadata);
+}
+
int32_t HWCSession::GetDisplayAttribute(hwc2_display_t display, hwc2_config_t config,
int32_t int_attribute, int32_t *out_value) {
if (out_value == nullptr || int_attribute < HWC2_ATTRIBUTE_INVALID ||
@@ -795,6 +820,9 @@
callbacks_.Hotplug(client_id, HWC2::Connection::Connected);
}
}
+ }
+
+ if (descriptor == HWC2_CALLBACK_HOTPLUG) {
client_connected_ = !!pointer;
// Notfify all displays.
NotifyClientStatus(client_connected_);
@@ -1112,46 +1140,37 @@
}
}
- HWDisplaysInfo hw_displays_info = {};
- DisplayError error = core_intf_->GetDisplaysStatus(&hw_displays_info);
- if (error != kErrorNone) {
- DLOGE("Failed to get connected display list. Error = %d", error);
- return HWC2::Error::BadDisplay;
- }
-
// Lock confined to this scope
int status = -EINVAL;
- for (auto &iter : hw_displays_info) {
- auto &info = iter.second;
- if (info.display_type != kVirtual) {
- continue;
- }
-
- for (auto &map_info : map_info_virtual_) {
- client_id = map_info.client_id;
- {
- SCOPE_LOCK(locker_[client_id]);
- auto &hwc_display = hwc_display_[client_id];
- if (hwc_display) {
- continue;
- }
-
- status = virtual_display_factory_.Create(core_intf_, &buffer_allocator_, &callbacks_,
- client_id, info.display_id, width, height,
- format, set_min_lum_, set_max_lum_, &hwc_display);
- // TODO(user): validate width and height support
- if (status) {
- return HWC2::Error::NoResources;
- }
-
- is_hdr_display_[UINT32(client_id)] = HasHDRSupport(hwc_display);
- DLOGI("Created virtual display id:% " PRIu64 " with res: %dx%d", client_id, width, height);
-
- *out_display_id = client_id;
- map_info.disp_type = info.display_type;
- map_info.sdm_id = info.display_id;
- break;
+ for (auto &map_info : map_info_virtual_) {
+ client_id = map_info.client_id;
+ {
+ SCOPE_LOCK(locker_[client_id]);
+ auto &hwc_display = hwc_display_[client_id];
+ if (hwc_display) {
+ continue;
}
+
+ int32_t display_id = GetVirtualDisplayId();
+ status = virtual_display_factory_.Create(core_intf_, &buffer_allocator_, &callbacks_,
+ client_id, display_id, width, height,
+ format, set_min_lum_, set_max_lum_, &hwc_display);
+ // TODO(user): validate width and height support
+ if (status) {
+ return HWC2::Error::NoResources;
+ }
+
+ {
+ SCOPE_LOCK(hdr_locker_[client_id]);
+ is_hdr_display_[UINT32(client_id)] = HasHDRSupport(hwc_display);
+ }
+
+ DLOGI("Created virtual display id:% " PRIu64 " with res: %dx%d", client_id, width, height);
+
+ *out_display_id = client_id;
+ map_info.disp_type = kVirtual;
+ map_info.sdm_id = display_id;
+ break;
}
}
@@ -1340,13 +1359,23 @@
DLOGE("QService command = %d: output_parcel needed.", command);
break;
}
- float brightness = -1.0f;
+
uint32_t display = input_parcel->readUint32();
- status = getDisplayBrightness(display, &brightness);
- if (brightness == -1.0f) {
+ uint32_t max_brightness_level = 0;
+ status = getDisplayMaxBrightness(display, &max_brightness_level);
+ if (status || !max_brightness_level) {
+ output_parcel->writeInt32(max_brightness_level);
+ DLOGE("Failed to get max brightness %u, status %d", max_brightness_level, status);
+ break;
+ }
+ DLOGV("Panel Max brightness is %u", max_brightness_level);
+
+ float brightness_precent = -1.0f;
+ status = getDisplayBrightness(display, &brightness_precent);
+ if (brightness_precent == -1.0f) {
output_parcel->writeInt32(0);
} else {
- output_parcel->writeInt32(INT32(brightness*254 + 1));
+ output_parcel->writeInt32(INT32(brightness_precent*(max_brightness_level - 1) + 1));
}
}
break;
@@ -1356,11 +1385,23 @@
DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
break;
}
+
+ uint32_t max_brightness_level = 0;
+ uint32_t display = HWC_DISPLAY_PRIMARY;
+ status = getDisplayMaxBrightness(display, &max_brightness_level);
+ if (status || max_brightness_level <= 1) {
+ output_parcel->writeInt32(max_brightness_level);
+ DLOGE("Failed to get max brightness %u, status %d", max_brightness_level, status);
+ break;
+ }
+ DLOGV("Panel Max brightness is %u", max_brightness_level);
+
int level = input_parcel->readInt32();
if (level == 0) {
- status = SetDisplayBrightness(HWC_DISPLAY_PRIMARY, -1.0f);
+ status = SetDisplayBrightness(display, -1.0f);
} else {
- status = SetDisplayBrightness(HWC_DISPLAY_PRIMARY, (level - 1)/254.0f);
+ status = SetDisplayBrightness(display,
+ (level - 1)/(static_cast<float>(max_brightness_level - 1)));
}
output_parcel->writeInt32(status);
}
@@ -2349,8 +2390,12 @@
if (!status) {
DLOGI("Created primary display type = %d, sdm id = %d, client id = %d", info.display_type,
- info.display_id, client_id);
- is_hdr_display_[UINT32(client_id)] = HasHDRSupport(*hwc_display);
+ info.display_id, client_id);
+ {
+ SCOPE_LOCK(hdr_locker_[client_id]);
+ is_hdr_display_[UINT32(client_id)] = HasHDRSupport(*hwc_display);
+ }
+
map_info_primary_.disp_type = info.display_type;
map_info_primary_.sdm_id = info.display_id;
CreateDummyDisplay(HWC_DISPLAY_PRIMARY);
@@ -2423,7 +2468,12 @@
DLOGE("Builtin display creation failed.");
break;
}
- is_hdr_display_[UINT32(client_id)] = HasHDRSupport(hwc_display_[client_id]);
+
+ {
+ SCOPE_LOCK(hdr_locker_[client_id]);
+ is_hdr_display_[UINT32(client_id)] = HasHDRSupport(hwc_display_[client_id]);
+ }
+
DLOGI("Builtin display created: sdm id = %d, client id = %d", info.display_id, client_id);
map_info.disp_type = info.display_type;
map_info.sdm_id = info.display_id;
@@ -2575,7 +2625,11 @@
break;
}
- is_hdr_display_[UINT32(client_id)] = HasHDRSupport(hwc_display);
+ {
+ SCOPE_LOCK(hdr_locker_[client_id]);
+ is_hdr_display_[UINT32(client_id)] = HasHDRSupport(hwc_display);
+ }
+
DLOGI("Created pluggable display successfully: sdm id = %d, client id = %d",
info.display_id, client_id);
CreateDummyDisplay(client_id);
@@ -2674,8 +2728,11 @@
}
DLOGI("Destroy display %d-%d, client id = %d", map_info->sdm_id, map_info->disp_type,
client_id);
+ {
+ SCOPE_LOCK(hdr_locker_[client_id]);
+ is_hdr_display_[UINT32(client_id)] = false;
+ }
- is_hdr_display_[UINT32(client_id)] = false;
if (!map_info->test_pattern) {
HWCDisplayPluggable::Destroy(hwc_display);
} else {
@@ -2707,7 +2764,11 @@
}
DLOGI("Destroy display %d-%d, client id = %d", map_info->sdm_id, map_info->disp_type,
client_id);
- is_hdr_display_[UINT32(client_id)] = false;
+ {
+ SCOPE_LOCK(hdr_locker_[client_id]);
+ is_hdr_display_[UINT32(client_id)] = false;
+ }
+
switch (map_info->disp_type) {
case kBuiltIn:
HWCDisplayBuiltIn::Destroy(hwc_display);
diff --git a/composer/hwc_session.h b/composer/hwc_session.h
index 3d13424..0bfa281 100644
--- a/composer/hwc_session.h
+++ b/composer/hwc_session.h
@@ -20,7 +20,7 @@
#ifndef __HWC_SESSION_H__
#define __HWC_SESSION_H__
-#include <vendor/display/config/1.13/IDisplayConfig.h>
+#include <vendor/display/config/1.14/IDisplayConfig.h>
#include <vendor/qti/hardware/display/composer/2.0/IQtiComposerClient.h>
#include <core/core_interface.h>
@@ -49,7 +49,7 @@
namespace sdm {
-using vendor::display::config::V1_13::IDisplayConfig;
+using vendor::display::config::V1_14::IDisplayConfig;
using vendor::display::config::V1_10::IDisplayCWBCallback;
using ::android::hardware::Return;
@@ -249,7 +249,9 @@
uint32_t num_elements, const int32_t *int_keys,
const float *metadata);
int32_t SetLayerColorTransform(hwc2_display_t display, hwc2_layer_t layer, const float *matrix);
-
+ int32_t SetLayerPerFrameMetadataBlobs(hwc2_display_t display, hwc2_layer_t layer,
+ uint32_t num_elements, const int32_t *int_keys,
+ const uint32_t *sizes, const uint8_t *metadata);
// HWCDisplayEventHandler
virtual void DisplayPowerReset();
@@ -262,6 +264,7 @@
static Locker locker_[HWCCallbacks::kNumDisplays];
static Locker power_state_[HWCCallbacks::kNumDisplays];
+ static Locker hdr_locker_[HWCCallbacks::kNumDisplays];
static Locker display_config_locker_;
private:
@@ -340,6 +343,7 @@
int32_t SetDynamicDSIClock(int64_t disp_id, uint32_t bitrate);
int32_t getDisplayBrightness(uint32_t display, float *brightness);
int32_t setDisplayBrightness(uint32_t display, float brightness);
+ int32_t getDisplayMaxBrightness(uint32_t display, uint32_t *max_brightness_level);
bool HasHDRSupport(HWCDisplay *hwc_display);
// Uevent handler
@@ -406,6 +410,7 @@
const hidl_handle& buffer) override;
Return<int32_t> setQsyncMode(uint32_t disp_id, IDisplayConfig::QsyncMode mode) override;
Return<bool> isSmartPanelConfig(uint32_t disp_id, uint32_t config_id) override;
+ Return<bool> isRotatorSupportedFormat(int hal_format, bool ubwc) override;
// QClient methods
virtual android::status_t notifyCallback(uint32_t command, const android::Parcel *input_parcel,
@@ -454,6 +459,7 @@
hwc2_display_t GetActiveBuiltinDisplay();
void HandlePendingRefresh();
void NotifyClientStatus(bool connected);
+ int32_t GetVirtualDisplayId();
CoreInterface *core_intf_ = nullptr;
HWCDisplay *hwc_display_[HWCCallbacks::kNumDisplays] = {nullptr};
diff --git a/composer/hwc_session_services.cpp b/composer/hwc_session_services.cpp
index 638cba3..a9c340a 100644
--- a/composer/hwc_session_services.cpp
+++ b/composer/hwc_session_services.cpp
@@ -708,7 +708,7 @@
DLOGE("Not valid display");
return false;
}
- SCOPE_LOCK(locker_[disp_id]);
+ SCOPE_LOCK(hdr_locker_[disp_id]);
if (is_hdr_display_.size() <= disp_id) {
DLOGW("is_hdr_display_ is not initialized for display %d!! Reporting it as HDR not supported",
@@ -824,6 +824,27 @@
return error;
}
+int32_t HWCSession::getDisplayMaxBrightness(uint32_t display, uint32_t *max_brightness_level) {
+ if (!max_brightness_level) {
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
+
+ if (display >= HWCCallbacks::kNumDisplays) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ int32_t error = -EINVAL;
+ HWCDisplay *hwc_display = hwc_display_[display];
+ if (hwc_display && hwc_display_[display]->GetDisplayClass() == DISPLAY_CLASS_BUILTIN) {
+ error = INT32(hwc_display_[display]->GetPanelMaxBrightness(max_brightness_level));
+ if (error) {
+ DLOGE("Failed to get the panel max brightness, display %u error %d", display, error);
+ }
+ }
+
+ return error;
+}
+
int32_t HWCSession::setDisplayBrightness(uint32_t display, float brightness) {
return SetDisplayBrightness(static_cast<hwc2_display_t>(display), brightness);
}
@@ -1027,6 +1048,7 @@
if (release_fence >= 0) {
status = sync_wait(release_fence, 1000);
+ close(release_fence);
} else {
DLOGE("CWB release fence could not be retrieved.");
status = -1;
@@ -1126,4 +1148,16 @@
return INT32(status);
}
+Return<bool> HWCSession::isRotatorSupportedFormat(int hal_format, bool ubwc) {
+ if (!core_intf_) {
+ DLOGW("core_intf_ not initialized.");
+ return false;
+ }
+ int flag = ubwc ? private_handle_t::PRIV_FLAGS_UBWC_ALIGNED : 0;
+
+ LayerBufferFormat sdm_format = HWCLayer::GetSDMFormat(hal_format, flag);
+
+ return core_intf_->IsRotatorSupportedFormat(sdm_format);
+}
+
} // namespace sdm
diff --git a/composer/vendor.qti.hardware.display.composer-service.xml b/composer/vendor.qti.hardware.display.composer-service.xml
index 5184413..0d4ef00 100644
--- a/composer/vendor.qti.hardware.display.composer-service.xml
+++ b/composer/vendor.qti.hardware.display.composer-service.xml
@@ -48,7 +48,7 @@
<hal format="hidl">
<name>vendor.display.config</name>
<transport>hwbinder</transport>
- <version>1.13</version>
+ <version>1.14</version>
<interface>
<name>IDisplayConfig</name>
<instance>default</instance>
diff --git a/config/display-product.mk b/config/display-product.mk
index 98a2d8d..5ede20e 100644
--- a/config/display-product.mk
+++ b/config/display-product.mk
@@ -29,6 +29,7 @@
vendor.display.config@1.11.vendor \
vendor.display.config@1.12.vendor \
vendor.display.config@1.13.vendor \
+ vendor.display.config@1.14.vendor \
vendor.qti.hardware.display.mapper@2.0.vendor \
vendor.qti.hardware.display.mapper@3.0.vendor \
modetest
@@ -46,6 +47,15 @@
#QDCM calibration xml file for dual panel
PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_default.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_sharp_1080p_cmd_mode_dsi_panel.xml
PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_default.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_nt35695b_truly_fhd_command_mode_dsi_panel.xml
+#QDCM calibration xml file for td4330 panel
+PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_bengal_default.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_td4330_v2_cmd_mode_dsi_truly_panel.xml
+PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_bengal_default.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_td4330_v2_video_mode_dsi_truly_panel.xml
+#QDCM calibration xml file for Sharp fhd panel
+PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_default.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_Sharp_fhd_cmd_mode_qsync_dsi_panel.xml
+PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_default.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_Sharp_fhd_video_mode_qsync_dsi_panel.xml
+#QDCM calibration xml file for Sharp 2k panel
+PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_default.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_Sharp_2k_cmd_mode_qsync_dsi_panel.xml
+PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_default.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_Sharp_2k_video_mode_qsync_dsi_panel.xml
PRODUCT_PROPERTY_OVERRIDES += \
persist.demo.hdmirotationlock=false \
@@ -54,26 +64,34 @@
debug.sf.hw=0 \
debug.egl.hw=0 \
debug.sf.latch_unsignaled=1 \
- debug.sf.enable_gl_backpressure=1 \
+ debug.sf.high_fps_late_app_phase_offset_ns=1000000 \
debug.mdpcomp.logs=0 \
vendor.gralloc.disable_ubwc=0 \
vendor.display.disable_scaler=0 \
- vendor.display.disable_offline_rotator=1 \
vendor.display.disable_excl_rect=0 \
vendor.display.comp_mask=0 \
vendor.display.enable_posted_start_dyn=1 \
vendor.display.enable_optimize_refresh=1 \
vendor.display.use_smooth_motion=1
+# Enable offline rotator for Bengal.
+ifneq ($(TARGET_BOARD_PLATFORM),bengal)
+PRODUCT_PROPERTY_OVERRIDES += \
+ vendor.display.disable_offline_rotator=1
+else
+PRODUCT_PROPERTY_OVERRIDES += \
+ vendor.display.disable_rotator_ubwc=1
+endif
+
ifeq ($(TARGET_BOARD_PLATFORM),kona)
PRODUCT_PROPERTY_OVERRIDES += \
+ debug.sf.enable_gl_backpressure=1 \
debug.sf.early_phase_offset_ns=500000 \
debug.sf.early_app_phase_offset_ns=500000 \
debug.sf.early_gl_phase_offset_ns=3000000 \
debug.sf.early_gl_app_phase_offset_ns=15000000 \
debug.sf.high_fps_early_phase_offset_ns=6100000 \
- debug.sf.high_fps_early_gl_phase_offset_ns=9000000 \
- debug.sf.high_fps_late_app_phase_offset_ns=1000000 \
+ debug.sf.high_fps_early_gl_phase_offset_ns=6500000 \
debug.sf.phase_offset_threshold_for_next_vsync_ns=6100000
endif
@@ -86,6 +104,7 @@
PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.surface_flinger.has_HDR_display=true
PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.surface_flinger.use_color_management=true
PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.surface_flinger.wcg_composition_dataspace=143261696
+PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.surface_flinger.protected_contents=true
ifneq (,$(filter userdebug eng, $(TARGET_BUILD_VARIANT)))
# Recovery is enabled, logging is enabled
diff --git a/config/qdcm_calib_data_bengal_default.xml b/config/qdcm_calib_data_bengal_default.xml
new file mode 100644
index 0000000..c954946
--- /dev/null
+++ b/config/qdcm_calib_data_bengal_default.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2019, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<Calib_Data>
+ <Disp_Modes NumModes="1" DefaultMode="0">
+ <Mode ModeID="0" DisplayID="0" IsDefaultMode="0" IsAppMode="0" Name="native" NumOfFeatures="13" WhitePoint="0" EValue="255" BValue="100" RValue="100" DynamicRange="sdr" ColorGamut="native">
+ <Feature FeatureType="2" Disable="true" DataSize="272">00000000000000000000000000000000000000000000F03F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F03F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F03F0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</Feature>
+ <Feature FeatureType="7" Disable="true" DataSize="12300">00000000000100000600000000000000100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F000000001010000110100002101000031010000410100005101000061010000710100008101000091010000A1010000B1010000C1010000D1010000E1010000F101000002020000120200002202000032020000420200005202000062020000720200008202000092020000A2020000B2020000C2020000D2020000E2020000F202000003030000130300002303000033030000430300005303000063030000730300008303000093030000A3030000B3030000C3030000D3030000E3030000F303000004040000140400002404000034040000440400005404000064040000740400008404000094040000A4040000B4040000C4040000D4040000E4040000F404000005050000150500002505000035050000450500005505000065050000750500008505000095050000A5050000B5050000C5050000D5050000E5050000F505000006060000160600002606000036060000460600005606000066060000760600008606000096060000A6060000B6060000C6060000D6060000E6060000F606000007070000170700002707000037070000470700005707000067070000770700008707000097070000A7070000B7070000C7070000D7070000E7070000F707000008080000180800002808000038080000480800005808000068080000780800008808000098080000A8080000B8080000C8080000D8080000E8080000F808000009090000190900002909000039090000490900005909000069090000790900008909000099090000A9090000B9090000C9090000D9090000E9090000F90900000A0A00001A0A00002A0A00003A0A00004A0A00005A0A00006A0A00007A0A00008A0A00009A0A0000AA0A0000BA0A0000CA0A0000DA0A0000EA0A0000FA0A00000B0B00001B0B00002B0B00003B0B00004B0B00005B0B00006B0B00007B0B00008B0B00009B0B0000AB0B0000BB0B0000CB0B0000DB0B0000EB0B0000FB0B00000C0C00001C0C00002C0C00003C0C00004C0C00005C0C00006C0C00007C0C00008C0C00009C0C0000AC0C0000BC0C0000CC0C0000DC0C0000EC0C0000FC0C00000D0D00001D0D00002D0D00003D0D00004D0D00005D0D00006D0D00007D0D00008D0D00009D0D0000AD0D0000BD0D0000CD0D0000DD0D0000ED0D0000FD0D00000E0E00001E0E00002E0E00003E0E00004E0E00005E0E00006E0E00007E0E00008E0E00009E0E0000AE0E0000BE0E0000CE0E0000DE0E0000EE0E0000FE0E00000F0F00001F0F00002F0F00003F0F00004F0F00005F0F00006F0F00007F0F00008F0F00009F0F0000AF0F0000BF0F0000CF0F0000DF0F0000EF0F0000FF0F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F000000001010000110100002101000031010000410100005101000061010000710100008101000091010000A1010000B1010000C1010000D1010000E1010000F101000002020000120200002202000032020000420200005202000062020000720200008202000092020000A2020000B2020000C2020000D2020000E2020000F202000003030000130300002303000033030000430300005303000063030000730300008303000093030000A3030000B3030000C3030000D3030000E3030000F303000004040000140400002404000034040000440400005404000064040000740400008404000094040000A4040000B4040000C4040000D4040000E4040000F404000005050000150500002505000035050000450500005505000065050000750500008505000095050000A5050000B5050000C5050000D5050000E5050000F505000006060000160600002606000036060000460600005606000066060000760600008606000096060000A6060000B6060000C6060000D6060000E6060000F606000007070000170700002707000037070000470700005707000067070000770700008707000097070000A7070000B7070000C7070000D7070000E7070000F707000008080000180800002808000038080000480800005808000068080000780800008808000098080000A8080000B8080000C8080000D8080000E8080000F808000009090000190900002909000039090000490900005909000069090000790900008909000099090000A9090000B9090000C9090000D9090000E9090000F90900000A0A00001A0A00002A0A00003A0A00004A0A00005A0A00006A0A00007A0A00008A0A00009A0A0000AA0A0000BA0A0000CA0A0000DA0A0000EA0A0000FA0A00000B0B00001B0B00002B0B00003B0B00004B0B00005B0B00006B0B00007B0B00008B0B00009B0B0000AB0B0000BB0B0000CB0B0000DB0B0000EB0B0000FB0B00000C0C00001C0C00002C0C00003C0C00004C0C00005C0C00006C0C00007C0C00008C0C00009C0C0000AC0C0000BC0C0000CC0C0000DC0C0000EC0C0000FC0C00000D0D00001D0D00002D0D00003D0D00004D0D00005D0D00006D0D00007D0D00008D0D00009D0D0000AD0D0000BD0D0000CD0D0000DD0D0000ED0D0000FD0D00000E0E00001E0E00002E0E00003E0E00004E0E00005E0E00006E0E00007E0E00008E0E00009E0E0000AE0E0000BE0E0000CE0E0000DE0E0000EE0E0000FE0E00000F0F00001F0F00002F0F00003F0F00004F0F00005F0F00006F0F00007F0F00008F0F00009F0F0000AF0F0000BF0F0000CF0F0000DF0F0000EF0F0000FF0F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F000000001010000110100002101000031010000410100005101000061010000710100008101000091010000A1010000B1010000C1010000D1010000E1010000F101000002020000120200002202000032020000420200005202000062020000720200008202000092020000A2020000B2020000C2020000D2020000E2020000F202000003030000130300002303000033030000430300005303000063030000730300008303000093030000A3030000B3030000C3030000D3030000E3030000F303000004040000140400002404000034040000440400005404000064040000740400008404000094040000A4040000B4040000C4040000D4040000E4040000F404000005050000150500002505000035050000450500005505000065050000750500008505000095050000A5050000B5050000C5050000D5050000E5050000F505000006060000160600002606000036060000460600005606000066060000760600008606000096060000A6060000B6060000C6060000D6060000E6060000F606000007070000170700002707000037070000470700005707000067070000770700008707000097070000A7070000B7070000C7070000D7070000E7070000F707000008080000180800002808000038080000480800005808000068080000780800008808000098080000A8080000B8080000C8080000D8080000E8080000F808000009090000190900002909000039090000490900005909000069090000790900008909000099090000A9090000B9090000C9090000D9090000E9090000F90900000A0A00001A0A00002A0A00003A0A00004A0A00005A0A00006A0A00007A0A00008A0A00009A0A0000AA0A0000BA0A0000CA0A0000DA0A0000EA0A0000FA0A00000B0B00001B0B00002B0B00003B0B00004B0B00005B0B00006B0B00007B0B00008B0B00009B0B0000AB0B0000BB0B0000CB0B0000DB0B0000EB0B0000FB0B00000C0C00001C0C00002C0C00003C0C00004C0C00005C0C00006C0C00007C0C00008C0C00009C0C0000AC0C0000BC0C0000CC0C0000DC0C0000EC0C0000FC0C00000D0D00001D0D00002D0D00003D0D00004D0D00005D0D00006D0D00007D0D00008D0D00009D0D0000AD0D0000BD0D0000CD0D0000DD0D0000ED0D0000FD0D00000E0E00001E0E00002E0E00003E0E00004E0E00005E0E00006E0E00007E0E00008E0E00009E0E0000AE0E0000BE0E0000CE0E0000DE0E0000EE0E0000FE0E00000F0F00001F0F00002F0F00003F0F00004F0F00005F0F00006F0F00007F0F00008F0F00009F0F0000AF0F0000BF0F0000CF0F0000DF0F0000EF0F0000FF0F0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</Feature>
+ <Feature FeatureType="8" Disable="true" DataSize="12300">010000000004000006000000000000000100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F000000100000001100000012000000130000001400000015000000160000001700000018000000190000001A0000001B0000001C0000001D0000001E0000001F000000200000002100000022000000230000002400000025000000260000002700000028000000290000002A0000002B0000002C0000002D0000002E0000002F000000300000003100000032000000330000003400000035000000360000003700000038000000390000003A0000003B0000003C0000003D0000003E0000003F000000400000004100000042000000430000004400000045000000460000004700000048000000490000004A0000004B0000004C0000004D0000004E0000004F000000500000005100000052000000530000005400000055000000560000005700000058000000590000005A0000005B0000005C0000005D0000005E0000005F000000600000006100000062000000630000006400000065000000660000006700000068000000690000006A0000006B0000006C0000006D0000006E0000006F000000700000007100000072000000730000007400000075000000760000007700000078000000790000007A0000007B0000007C0000007D0000007E0000007F000000800000008100000082000000830000008400000085000000860000008700000088000000890000008A0000008B0000008C0000008D0000008E0000008F000000900000009100000092000000930000009400000095000000960000009700000098000000990000009A0000009B0000009C0000009D0000009E0000009F000000A0000000A1000000A2000000A3000000A4000000A5000000A6000000A7000000A8000000A9000000AA000000AB000000AC000000AD000000AE000000AF000000B0000000B1000000B2000000B3000000B4000000B5000000B6000000B7000000B8000000B9000000BA000000BB000000BC000000BD000000BE000000BF000000C0000000C1000000C2000000C3000000C4000000C5000000C6000000C7000000C8000000C9000000CA000000CB000000CC000000CD000000CE000000CF000000D0000000D1000000D2000000D3000000D4000000D5000000D6000000D7000000D8000000D9000000DA000000DB000000DC000000DD000000DE000000DF000000E0000000E1000000E2000000E3000000E4000000E5000000E6000000E7000000E8000000E9000000EA000000EB000000EC000000ED000000EE000000EF000000F0000000F1000000F2000000F3000000F4000000F5000000F6000000F7000000F8000000F9000000FA000000FB000000FC000000FD000000FE000000FF000000000100000101000002010000030100000401000005010000060100000701000008010000090100000A0100000B0100000C0100000D0100000E0100000F010000100100001101000012010000130100001401000015010000160100001701000018010000190100001A0100001B0100001C0100001D0100001E0100001F010000200100002101000022010000230100002401000025010000260100002701000028010000290100002A0100002B0100002C0100002D0100002E0100002F010000300100003101000032010000330100003401000035010000360100003701000038010000390100003A0100003B0100003C0100003D0100003E0100003F010000400100004101000042010000430100004401000045010000460100004701000048010000490100004A0100004B0100004C0100004D0100004E0100004F010000500100005101000052010000530100005401000055010000560100005701000058010000590100005A0100005B0100005C0100005D0100005E0100005F010000600100006101000062010000630100006401000065010000660100006701000068010000690100006A0100006B0100006C0100006D0100006E0100006F010000700100007101000072010000730100007401000075010000760100007701000078010000790100007A0100007B0100007C0100007D0100007E0100007F010000800100008101000082010000830100008401000085010000860100008701000088010000890100008A0100008B0100008C0100008D0100008E0100008F010000900100009101000092010000930100009401000095010000960100009701000098010000990100009A0100009B0100009C0100009D0100009E0100009F010000A0010000A1010000A2010000A3010000A4010000A5010000A6010000A7010000A8010000A9010000AA010000AB010000AC010000AD010000AE010000AF010000B0010000B1010000B2010000B3010000B4010000B5010000B6010000B7010000B8010000B9010000BA010000BB010000BC010000BD010000BE010000BF010000C0010000C1010000C2010000C3010000C4010000C5010000C6010000C7010000C8010000C9010000CA010000CB010000CC010000CD010000CE010000CF010000D0010000D1010000D2010000D3010000D4010000D5010000D6010000D7010000D8010000D9010000DA010000DB010000DC010000DD010000DE010000DF010000E0010000E1010000E2010000E3010000E4010000E5010000E6010000E7010000E8010000E9010000EA010000EB010000EC010000ED010000EE010000EF010000F0010000F1010000F2010000F3010000F4010000F5010000F6010000F7010000F8010000F9010000FA010000FB010000FC010000FD010000FE010000FF010000000200000102000002020000030200000402000005020000060200000702000008020000090200000A0200000B0200000C0200000D0200000E0200000F020000100200001102000012020000130200001402000015020000160200001702000018020000190200001A0200001B0200001C0200001D0200001E0200001F020000200200002102000022020000230200002402000025020000260200002702000028020000290200002A0200002B0200002C0200002D0200002E0200002F020000300200003102000032020000330200003402000035020000360200003702000038020000390200003A0200003B0200003C0200003D0200003E0200003F020000400200004102000042020000430200004402000045020000460200004702000048020000490200004A0200004B0200004C0200004D0200004E0200004F020000500200005102000052020000530200005402000055020000560200005702000058020000590200005A0200005B0200005C0200005D0200005E0200005F020000600200006102000062020000630200006402000065020000660200006702000068020000690200006A0200006B0200006C0200006D0200006E0200006F020000700200007102000072020000730200007402000075020000760200007702000078020000790200007A0200007B0200007C0200007D0200007E0200007F020000800200008102000082020000830200008402000085020000860200008702000088020000890200008A0200008B0200008C0200008D0200008E0200008F020000900200009102000092020000930200009402000095020000960200009702000098020000990200009A0200009B0200009C0200009D0200009E0200009F020000A0020000A1020000A2020000A3020000A4020000A5020000A6020000A7020000A8020000A9020000AA020000AB020000AC020000AD020000AE020000AF020000B0020000B1020000B2020000B3020000B4020000B5020000B6020000B7020000B8020000B9020000BA020000BB020000BC020000BD020000BE020000BF020000C0020000C1020000C2020000C3020000C4020000C5020000C6020000C7020000C8020000C9020000CA020000CB020000CC020000CD020000CE020000CF020000D0020000D1020000D2020000D3020000D4020000D5020000D6020000D7020000D8020000D9020000DA020000DB020000DC020000DD020000DE020000DF020000E0020000E1020000E2020000E3020000E4020000E5020000E6020000E7020000E8020000E9020000EA020000EB020000EC020000ED020000EE020000EF020000F0020000F1020000F2020000F3020000F4020000F5020000F6020000F7020000F8020000F9020000FA020000FB020000FC020000FD020000FE020000FF020000000300000103000002030000030300000403000005030000060300000703000008030000090300000A0300000B0300000C0300000D0300000E0300000F030000100300001103000012030000130300001403000015030000160300001703000018030000190300001A0300001B0300001C0300001D0300001E0300001F030000200300002103000022030000230300002403000025030000260300002703000028030000290300002A0300002B0300002C0300002D0300002E0300002F030000300300003103000032030000330300003403000035030000360300003703000038030000390300003A0300003B0300003C0300003D0300003E0300003F030000400300004103000042030000430300004403000045030000460300004703000048030000490300004A0300004B0300004C0300004D0300004E0300004F030000500300005103000052030000530300005403000055030000560300005703000058030000590300005A0300005B0300005C0300005D0300005E0300005F030000600300006103000062030000630300006403000065030000660300006703000068030000690300006A0300006B0300006C0300006D0300006E0300006F030000700300007103000072030000730300007403000075030000760300007703000078030000790300007A0300007B0300007C0300007D0300007E0300007F030000800300008103000082030000830300008403000085030000860300008703000088030000890300008A0300008B0300008C0300008D0300008E0300008F030000900300009103000092030000930300009403000095030000960300009703000098030000990300009A0300009B0300009C0300009D0300009E0300009F030000A0030000A1030000A2030000A3030000A4030000A5030000A6030000A7030000A8030000A9030000AA030000AB030000AC030000AD030000AE030000AF030000B0030000B1030000B2030000B3030000B4030000B5030000B6030000B7030000B8030000B9030000BA030000BB030000BC030000BD030000BE030000BF030000C0030000C1030000C2030000C3030000C4030000C5030000C6030000C7030000C8030000C9030000CA030000CB030000CC030000CD030000CE030000CF030000D0030000D1030000D2030000D3030000D4030000D5030000D6030000D7030000D8030000D9030000DA030000DB030000DC030000DD030000DE030000DF030000E0030000E1030000E2030000E3030000E4030000E5030000E6030000E7030000E8030000E9030000EA030000EB030000EC030000ED030000EE030000EF030000F0030000F1030000F2030000F3030000F4030000F5030000F6030000F7030000F8030000F9030000FA030000FB030000FC030000FD030000FE030000FF030000000000000100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F000000100000001100000012000000130000001400000015000000160000001700000018000000190000001A0000001B0000001C0000001D0000001E0000001F000000200000002100000022000000230000002400000025000000260000002700000028000000290000002A0000002B0000002C0000002D0000002E0000002F000000300000003100000032000000330000003400000035000000360000003700000038000000390000003A0000003B0000003C0000003D0000003E0000003F000000400000004100000042000000430000004400000045000000460000004700000048000000490000004A0000004B0000004C0000004D0000004E0000004F000000500000005100000052000000530000005400000055000000560000005700000058000000590000005A0000005B0000005C0000005D0000005E0000005F000000600000006100000062000000630000006400000065000000660000006700000068000000690000006A0000006B0000006C0000006D0000006E0000006F000000700000007100000072000000730000007400000075000000760000007700000078000000790000007A0000007B0000007C0000007D0000007E0000007F000000800000008100000082000000830000008400000085000000860000008700000088000000890000008A0000008B0000008C0000008D0000008E0000008F000000900000009100000092000000930000009400000095000000960000009700000098000000990000009A0000009B0000009C0000009D0000009E0000009F000000A0000000A1000000A2000000A3000000A4000000A5000000A6000000A7000000A8000000A9000000AA000000AB000000AC000000AD000000AE000000AF000000B0000000B1000000B2000000B3000000B4000000B5000000B6000000B7000000B8000000B9000000BA000000BB000000BC000000BD000000BE000000BF000000C0000000C1000000C2000000C3000000C4000000C5000000C6000000C7000000C8000000C9000000CA000000CB000000CC000000CD000000CE000000CF000000D0000000D1000000D2000000D3000000D4000000D5000000D6000000D7000000D8000000D9000000DA000000DB000000DC000000DD000000DE000000DF000000E0000000E1000000E2000000E3000000E4000000E5000000E6000000E7000000E8000000E9000000EA000000EB000000EC000000ED000000EE000000EF000000F0000000F1000000F2000000F3000000F4000000F5000000F6000000F7000000F8000000F9000000FA000000FB000000FC000000FD000000FE000000FF000000000100000101000002010000030100000401000005010000060100000701000008010000090100000A0100000B0100000C0100000D0100000E0100000F010000100100001101000012010000130100001401000015010000160100001701000018010000190100001A0100001B0100001C0100001D0100001E0100001F010000200100002101000022010000230100002401000025010000260100002701000028010000290100002A0100002B0100002C0100002D0100002E0100002F010000300100003101000032010000330100003401000035010000360100003701000038010000390100003A0100003B0100003C0100003D0100003E0100003F010000400100004101000042010000430100004401000045010000460100004701000048010000490100004A0100004B0100004C0100004D0100004E0100004F010000500100005101000052010000530100005401000055010000560100005701000058010000590100005A0100005B0100005C0100005D0100005E0100005F010000600100006101000062010000630100006401000065010000660100006701000068010000690100006A0100006B0100006C0100006D0100006E0100006F010000700100007101000072010000730100007401000075010000760100007701000078010000790100007A0100007B0100007C0100007D0100007E0100007F010000800100008101000082010000830100008401000085010000860100008701000088010000890100008A0100008B0100008C0100008D0100008E0100008F010000900100009101000092010000930100009401000095010000960100009701000098010000990100009A0100009B0100009C0100009D0100009E0100009F010000A0010000A1010000A2010000A3010000A4010000A5010000A6010000A7010000A8010000A9010000AA010000AB010000AC010000AD010000AE010000AF010000B0010000B1010000B2010000B3010000B4010000B5010000B6010000B7010000B8010000B9010000BA010000BB010000BC010000BD010000BE010000BF010000C0010000C1010000C2010000C3010000C4010000C5010000C6010000C7010000C8010000C9010000CA010000CB010000CC010000CD010000CE010000CF010000D0010000D1010000D2010000D3010000D4010000D5010000D6010000D7010000D8010000D9010000DA010000DB010000DC010000DD010000DE010000DF010000E0010000E1010000E2010000E3010000E4010000E5010000E6010000E7010000E8010000E9010000EA010000EB010000EC010000ED010000EE010000EF010000F0010000F1010000F2010000F3010000F4010000F5010000F6010000F7010000F8010000F9010000FA010000FB010000FC010000FD010000FE010000FF010000000200000102000002020000030200000402000005020000060200000702000008020000090200000A0200000B0200000C0200000D0200000E0200000F020000100200001102000012020000130200001402000015020000160200001702000018020000190200001A0200001B0200001C0200001D0200001E0200001F020000200200002102000022020000230200002402000025020000260200002702000028020000290200002A0200002B0200002C0200002D0200002E0200002F020000300200003102000032020000330200003402000035020000360200003702000038020000390200003A0200003B0200003C0200003D0200003E0200003F020000400200004102000042020000430200004402000045020000460200004702000048020000490200004A0200004B0200004C0200004D0200004E0200004F020000500200005102000052020000530200005402000055020000560200005702000058020000590200005A0200005B0200005C0200005D0200005E0200005F020000600200006102000062020000630200006402000065020000660200006702000068020000690200006A0200006B0200006C0200006D0200006E0200006F020000700200007102000072020000730200007402000075020000760200007702000078020000790200007A0200007B0200007C0200007D0200007E0200007F020000800200008102000082020000830200008402000085020000860200008702000088020000890200008A0200008B0200008C0200008D0200008E0200008F020000900200009102000092020000930200009402000095020000960200009702000098020000990200009A0200009B0200009C0200009D0200009E0200009F020000A0020000A1020000A2020000A3020000A4020000A5020000A6020000A7020000A8020000A9020000AA020000AB020000AC020000AD020000AE020000AF020000B0020000B1020000B2020000B3020000B4020000B5020000B6020000B7020000B8020000B9020000BA020000BB020000BC020000BD020000BE020000BF020000C0020000C1020000C2020000C3020000C4020000C5020000C6020000C7020000C8020000C9020000CA020000CB020000CC020000CD020000CE020000CF020000D0020000D1020000D2020000D3020000D4020000D5020000D6020000D7020000D8020000D9020000DA020000DB020000DC020000DD020000DE020000DF020000E0020000E1020000E2020000E3020000E4020000E5020000E6020000E7020000E8020000E9020000EA020000EB020000EC020000ED020000EE020000EF020000F0020000F1020000F2020000F3020000F4020000F5020000F6020000F7020000F8020000F9020000FA020000FB020000FC020000FD020000FE020000FF020000000300000103000002030000030300000403000005030000060300000703000008030000090300000A0300000B0300000C0300000D0300000E0300000F030000100300001103000012030000130300001403000015030000160300001703000018030000190300001A0300001B0300001C0300001D0300001E0300001F030000200300002103000022030000230300002403000025030000260300002703000028030000290300002A0300002B0300002C0300002D0300002E0300002F030000300300003103000032030000330300003403000035030000360300003703000038030000390300003A0300003B0300003C0300003D0300003E0300003F030000400300004103000042030000430300004403000045030000460300004703000048030000490300004A0300004B0300004C0300004D0300004E0300004F030000500300005103000052030000530300005403000055030000560300005703000058030000590300005A0300005B0300005C0300005D0300005E0300005F030000600300006103000062030000630300006403000065030000660300006703000068030000690300006A0300006B0300006C0300006D0300006E0300006F030000700300007103000072030000730300007403000075030000760300007703000078030000790300007A0300007B0300007C0300007D0300007E0300007F030000800300008103000082030000830300008403000085030000860300008703000088030000890300008A0300008B0300008C0300008D0300008E0300008F030000900300009103000092030000930300009403000095030000960300009703000098030000990300009A0300009B0300009C0300009D0300009E0300009F030000A0030000A1030000A2030000A3030000A4030000A5030000A6030000A7030000A8030000A9030000AA030000AB030000AC030000AD030000AE030000AF030000B0030000B1030000B2030000B3030000B4030000B5030000B6030000B7030000B8030000B9030000BA030000BB030000BC030000BD030000BE030000BF030000C0030000C1030000C2030000C3030000C4030000C5030000C6030000C7030000C8030000C9030000CA030000CB030000CC030000CD030000CE030000CF030000D0030000D1030000D2030000D3030000D4030000D5030000D6030000D7030000D8030000D9030000DA030000DB030000DC030000DD030000DE030000DF030000E0030000E1030000E2030000E3030000E4030000E5030000E6030000E7030000E8030000E9030000EA030000EB030000EC030000ED030000EE030000EF030000F0030000F1030000F2030000F3030000F4030000F5030000F6030000F7030000F8030000F9030000FA030000FB030000FC030000FD030000FE030000FF030000000000000100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F000000100000001100000012000000130000001400000015000000160000001700000018000000190000001A0000001B0000001C0000001D0000001E0000001F000000200000002100000022000000230000002400000025000000260000002700000028000000290000002A0000002B0000002C0000002D0000002E0000002F000000300000003100000032000000330000003400000035000000360000003700000038000000390000003A0000003B0000003C0000003D0000003E0000003F000000400000004100000042000000430000004400000045000000460000004700000048000000490000004A0000004B0000004C0000004D0000004E0000004F000000500000005100000052000000530000005400000055000000560000005700000058000000590000005A0000005B0000005C0000005D0000005E0000005F000000600000006100000062000000630000006400000065000000660000006700000068000000690000006A0000006B0000006C0000006D0000006E0000006F000000700000007100000072000000730000007400000075000000760000007700000078000000790000007A0000007B0000007C0000007D0000007E0000007F000000800000008100000082000000830000008400000085000000860000008700000088000000890000008A0000008B0000008C0000008D0000008E0000008F000000900000009100000092000000930000009400000095000000960000009700000098000000990000009A0000009B0000009C0000009D0000009E0000009F000000A0000000A1000000A2000000A3000000A4000000A5000000A6000000A7000000A8000000A9000000AA000000AB000000AC000000AD000000AE000000AF000000B0000000B1000000B2000000B3000000B4000000B5000000B6000000B7000000B8000000B9000000BA000000BB000000BC000000BD000000BE000000BF000000C0000000C1000000C2000000C3000000C4000000C5000000C6000000C7000000C8000000C9000000CA000000CB000000CC000000CD000000CE000000CF000000D0000000D1000000D2000000D3000000D4000000D5000000D6000000D7000000D8000000D9000000DA000000DB000000DC000000DD000000DE000000DF000000E0000000E1000000E2000000E3000000E4000000E5000000E6000000E7000000E8000000E9000000EA000000EB000000EC000000ED000000EE000000EF000000F0000000F1000000F2000000F3000000F4000000F5000000F6000000F7000000F8000000F9000000FA000000FB000000FC000000FD000000FE000000FF000000000100000101000002010000030100000401000005010000060100000701000008010000090100000A0100000B0100000C0100000D0100000E0100000F010000100100001101000012010000130100001401000015010000160100001701000018010000190100001A0100001B0100001C0100001D0100001E0100001F010000200100002101000022010000230100002401000025010000260100002701000028010000290100002A0100002B0100002C0100002D0100002E0100002F010000300100003101000032010000330100003401000035010000360100003701000038010000390100003A0100003B0100003C0100003D0100003E0100003F010000400100004101000042010000430100004401000045010000460100004701000048010000490100004A0100004B0100004C0100004D0100004E0100004F010000500100005101000052010000530100005401000055010000560100005701000058010000590100005A0100005B0100005C0100005D0100005E0100005F010000600100006101000062010000630100006401000065010000660100006701000068010000690100006A0100006B0100006C0100006D0100006E0100006F010000700100007101000072010000730100007401000075010000760100007701000078010000790100007A0100007B0100007C0100007D0100007E0100007F010000800100008101000082010000830100008401000085010000860100008701000088010000890100008A0100008B0100008C0100008D0100008E0100008F010000900100009101000092010000930100009401000095010000960100009701000098010000990100009A0100009B0100009C0100009D0100009E0100009F010000A0010000A1010000A2010000A3010000A4010000A5010000A6010000A7010000A8010000A9010000AA010000AB010000AC010000AD010000AE010000AF010000B0010000B1010000B2010000B3010000B4010000B5010000B6010000B7010000B8010000B9010000BA010000BB010000BC010000BD010000BE010000BF010000C0010000C1010000C2010000C3010000C4010000C5010000C6010000C7010000C8010000C9010000CA010000CB010000CC010000CD010000CE010000CF010000D0010000D1010000D2010000D3010000D4010000D5010000D6010000D7010000D8010000D9010000DA010000DB010000DC010000DD010000DE010000DF010000E0010000E1010000E2010000E3010000E4010000E5010000E6010000E7010000E8010000E9010000EA010000EB010000EC010000ED010000EE010000EF010000F0010000F1010000F2010000F3010000F4010000F5010000F6010000F7010000F8010000F9010000FA010000FB010000FC010000FD010000FE010000FF010000000200000102000002020000030200000402000005020000060200000702000008020000090200000A0200000B0200000C0200000D0200000E0200000F020000100200001102000012020000130200001402000015020000160200001702000018020000190200001A0200001B0200001C0200001D0200001E0200001F020000200200002102000022020000230200002402000025020000260200002702000028020000290200002A0200002B0200002C0200002D0200002E0200002F020000300200003102000032020000330200003402000035020000360200003702000038020000390200003A0200003B0200003C0200003D0200003E0200003F020000400200004102000042020000430200004402000045020000460200004702000048020000490200004A0200004B0200004C0200004D0200004E0200004F020000500200005102000052020000530200005402000055020000560200005702000058020000590200005A0200005B0200005C0200005D0200005E0200005F020000600200006102000062020000630200006402000065020000660200006702000068020000690200006A0200006B0200006C0200006D0200006E0200006F020000700200007102000072020000730200007402000075020000760200007702000078020000790200007A0200007B0200007C0200007D0200007E0200007F020000800200008102000082020000830200008402000085020000860200008702000088020000890200008A0200008B0200008C0200008D0200008E0200008F020000900200009102000092020000930200009402000095020000960200009702000098020000990200009A0200009B0200009C0200009D0200009E0200009F020000A0020000A1020000A2020000A3020000A4020000A5020000A6020000A7020000A8020000A9020000AA020000AB020000AC020000AD020000AE020000AF020000B0020000B1020000B2020000B3020000B4020000B5020000B6020000B7020000B8020000B9020000BA020000BB020000BC020000BD020000BE020000BF020000C0020000C1020000C2020000C3020000C4020000C5020000C6020000C7020000C8020000C9020000CA020000CB020000CC020000CD020000CE020000CF020000D0020000D1020000D2020000D3020000D4020000D5020000D6020000D7020000D8020000D9020000DA020000DB020000DC020000DD020000DE020000DF020000E0020000E1020000E2020000E3020000E4020000E5020000E6020000E7020000E8020000E9020000EA020000EB020000EC020000ED020000EE020000EF020000F0020000F1020000F2020000F3020000F4020000F5020000F6020000F7020000F8020000F9020000FA020000FB020000FC020000FD020000FE020000FF020000000300000103000002030000030300000403000005030000060300000703000008030000090300000A0300000B0300000C0300000D0300000E0300000F030000100300001103000012030000130300001403000015030000160300001703000018030000190300001A0300001B0300001C0300001D0300001E0300001F030000200300002103000022030000230300002403000025030000260300002703000028030000290300002A0300002B0300002C0300002D0300002E0300002F030000300300003103000032030000330300003403000035030000360300003703000038030000390300003A0300003B0300003C0300003D0300003E0300003F030000400300004103000042030000430300004403000045030000460300004703000048030000490300004A0300004B0300004C0300004D0300004E0300004F030000500300005103000052030000530300005403000055030000560300005703000058030000590300005A0300005B0300005C0300005D0300005E0300005F030000600300006103000062030000630300006403000065030000660300006703000068030000690300006A0300006B0300006C0300006D0300006E0300006F030000700300007103000072030000730300007403000075030000760300007703000078030000790300007A0300007B0300007C0300007D0300007E0300007F030000800300008103000082030000830300008403000085030000860300008703000088030000890300008A0300008B0300008C0300008D0300008E0300008F030000900300009103000092030000930300009403000095030000960300009703000098030000990300009A0300009B0300009C0300009D0300009E0300009F030000A0030000A1030000A2030000A3030000A4030000A5030000A6030000A7030000A8030000A9030000AA030000AB030000AC030000AD030000AE030000AF030000B0030000B1030000B2030000B3030000B4030000B5030000B6030000B7030000B8030000B9030000BA030000BB030000BC030000BD030000BE030000BF030000C0030000C1030000C2030000C3030000C4030000C5030000C6030000C7030000C8030000C9030000CA030000CB030000CC030000CD030000CE030000CF030000D0030000D1030000D2030000D3030000D4030000D5030000D6030000D7030000D8030000D9030000DA030000DB030000DC030000DD030000DE030000DF030000E0030000E1030000E2030000E3030000E4030000E5030000E6030000E7030000E8030000E9030000EA030000EB030000EC030000ED030000EE030000EF030000F0030000F1030000F2030000F3030000F4030000F5030000F6030000F7030000F8030000F9030000FA030000FB030000FC030000FD030000FE030000FF030000</Feature>
+ <Feature FeatureType="14" Disable="false" DataSize="9560">00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F00000021000000210000000300000003000000000000002D00000000000000010000000000C842000000000000803F0000C842000000000000803F0100000000000000000000000000000000000000000000000F0000002100000021000000030000000300000000000000FF000000C3000000010000000000C842000000000000803F0000C842000000000000803F0200000000000000000000000000000000000000000000000F0000002100000021000000030000000300000000000000870000004B000000010000000000C842000000000000803F0000C842000000000000803F0000000000000000640000000A0000000100000064000000000000000100000021000000210000000300000003000000000000000000000080010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</Feature>
+ <Feature FeatureType="20" Disable="true" DataSize="88">0000000008000000080000000800000000000000100000000F000000070000000D00000005000000030000000B00000001000000090000000C000000040000000E000000060000000000000008000000020000000A000000</Feature>
+ <Feature FeatureType="22" Disable="true" DataSize="0"/>
+ </Mode>
+ </Disp_Modes>
+ <Luts NumLuts="1">
+ <Lut Type="0" NumPackets="41">ECFFFFFF0000803F936F163FDA1AB13DEDFFFFFF0000803F87501D3FB9530A3EEEFFFFFF0000803FAAEE213FD1912C3EEFFFFFFF0000803F8CBC283F8C82603EF0FFFFFF0000803F473C2D3FD1E9813EF1FFFFFF0000803F5C02343FFE0E9D3EF2FFFFFF0000803F6E6E383FE04DAF3EF3FFFFFF0000803F31093F3F3C16CB3EF4FFFFFF0000803F3960433F73BDDD3EF5FFFFFF0000803F91D5493F6519FA3EF6FFFFFF0000803F840E4E3F957E063FF7FFFFFF0000803F1B62543FCEDF143FF8FFFFFF0000803F828C583F90871E3FF9FFFFFF0000803FF2B65E3F1A182D3FFAFFFFFF0000803FE7C4623FABCE363FFBFFFFFF0000803FD7BE683F8E5A453FFCFFFFFF0000803F41B66C3FD6194F3FFDFFFFFF0000803F1E8A723F8AAC5D3FFEFFFFFF0000803F516B763F6475673FFFFFFFFF0000803F8A227C3FB41E763F000000000000803F0000803F0000803F01000000836B723F6189773F0000803F02000000BF0C6A3F484E723F0000803F03000000CD945E3F191E6B3F0000803F04000000B988573FEFAB663F0000803F0500000084D44D3F5E81603F0000803F0600000045D9473FEBAA5C3F0000803F07000000CA883F3F2651573F0000803F080000005C593A3FADFB533F0000803F09000000802D333F05514F3F0000803F0A00000083C02E3FC3624C3F0000803F0B0000005986283FE04C483F0000803F0C0000008C9D243F18B3453F0000803F0D000000431C1F3F8909423F0000803F0E000000ABB21B3FE4C03F3F0000803F0F0000003DD4163FC07A3C3F0000803F1000000009C0133FE4683A3F0000803F110000008A740F3FF27B373F0000803F1200000039B80C3FCB9D353F0000803F130000005DDE083FBAF9323F0000803F140000009467063F3448313F0000803F</Lut>
+ </Luts>
+</Calib_Data>
diff --git a/gpu_tonemapper/Android.mk b/gpu_tonemapper/Android.mk
index ec59eef..fe98897 100644
--- a/gpu_tonemapper/Android.mk
+++ b/gpu_tonemapper/Android.mk
@@ -1,7 +1,6 @@
LOCAL_PATH := $(call my-dir)
include $(LOCAL_PATH)/../common.mk
-ifneq ($(TARGET_IS_HEADLESS), true)
include $(CLEAR_VARS)
LOCAL_COPY_HEADERS_TO := $(common_header_export_path)
LOCAL_COPY_HEADERS := TonemapFactory.h Tonemapper.h
@@ -28,4 +27,3 @@
Tonemapper.cpp
include $(BUILD_SHARED_LIBRARY)
-endif
diff --git a/gpu_tonemapper/EGLImageWrapper.cpp b/gpu_tonemapper/EGLImageWrapper.cpp
index 19bf093..560fd5a 100644
--- a/gpu_tonemapper/EGLImageWrapper.cpp
+++ b/gpu_tonemapper/EGLImageWrapper.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright 2015 The Android Open Source Project
@@ -32,36 +32,6 @@
static string pidString = std::to_string(getpid());
-#ifndef TARGET_ION_ABI_VERSION
-//-----------------------------------------------------------------------------
-static void free_ion_cookie(int ion_fd, int cookie)
-//-----------------------------------------------------------------------------
-{
- if (ion_fd && !ioctl(ion_fd, ION_IOC_FREE, &cookie)) {
- } else {
- ALOGE("ION_IOC_FREE failed: ion_fd = %d, cookie = %d", ion_fd, cookie);
- }
-}
-
-//-----------------------------------------------------------------------------
-static int get_ion_cookie(int ion_fd, int fd)
-//-----------------------------------------------------------------------------
-{
- int cookie = fd;
-
- struct ion_fd_data fdData;
- memset(&fdData, 0, sizeof(fdData));
- fdData.fd = fd;
-
- if (ion_fd && !ioctl(ion_fd, ION_IOC_IMPORT, &fdData)) {
- cookie = fdData.handle;
- } else {
- ALOGE("ION_IOC_IMPORT failed: ion_fd = %d, fd = %d", ion_fd, fd);
- }
-
- return cookie;
-}
-#else
//-----------------------------------------------------------------------------
static string get_ion_buff_str(int buff_fd)
//-----------------------------------------------------------------------------
@@ -80,7 +50,6 @@
return retStr;
}
-#endif
//-----------------------------------------------------------------------------
void EGLImageWrapper::DeleteEGLImageCallback::operator()(int& buffInt, EGLImageBuffer*& eglImage)
@@ -90,9 +59,6 @@
delete eglImage;
}
-#ifndef TARGET_ION_ABI_VERSION
- free_ion_cookie(ion_fd, buffInt /* cookie */);
-#else
if (!mapClearPending) {
for (auto it = buffStrbuffIntMapPtr->begin(); it != buffStrbuffIntMapPtr->end(); it++) {
if (it->second == buffInt /* counter */) {
@@ -101,7 +67,6 @@
}
}
}
-#endif
}
//-----------------------------------------------------------------------------
@@ -111,17 +76,19 @@
eglImageBufferCache = new android::LruCache<int, EGLImageBuffer*>(32);
callback = new DeleteEGLImageCallback(&buffStrbuffIntMap);
eglImageBufferCache->setOnEntryRemovedListener(callback);
-
-#ifndef TARGET_ION_ABI_VERSION
- ion_fd = open("/dev/ion", O_RDONLY);
- callback->ion_fd = ion_fd;
-#endif
}
//-----------------------------------------------------------------------------
EGLImageWrapper::~EGLImageWrapper()
//-----------------------------------------------------------------------------
{
+ Deinit();
+}
+
+//-----------------------------------------------------------------------------
+void EGLImageWrapper::Deinit()
+//-----------------------------------------------------------------------------
+{
if (eglImageBufferCache != 0) {
if (callback != 0) {
callback->mapClearPending = true;
@@ -137,12 +104,6 @@
callback = 0;
}
-#ifndef TARGET_ION_ABI_VERSION
- if (ion_fd > 0) {
- close(ion_fd);
- ion_fd = -1;
- }
-#endif
}
//-----------------------------------------------------------------------------
@@ -180,17 +141,6 @@
{
const private_handle_t *src = static_cast<const private_handle_t *>(pvt_handle);
-#ifndef TARGET_ION_ABI_VERSION
- int ion_cookie = get_ion_cookie(ion_fd, src->fd);
- EGLImageBuffer* eglImage = nullptr;
- eglImage = eglImageBufferCache->get(ion_cookie);
- if (eglImage == 0) {
- eglImage = L_wrap(src);
- eglImageBufferCache->put(ion_cookie, eglImage);
- } else {
- free_ion_cookie(ion_fd, ion_cookie);
- }
-#else
string buffStr = get_ion_buff_str(src->fd);
EGLImageBuffer* eglImage = nullptr;
if (!buffStr.empty()) {
@@ -206,7 +156,6 @@
} else {
ALOGE("Could not provide an eglImage for fd = %d, EGLImageWrapper = %p", src->fd, this);
}
-#endif
return eglImage;
}
diff --git a/gpu_tonemapper/EGLImageWrapper.h b/gpu_tonemapper/EGLImageWrapper.h
index ce1b344..a0a7522 100644
--- a/gpu_tonemapper/EGLImageWrapper.h
+++ b/gpu_tonemapper/EGLImageWrapper.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright 2015 The Android Open Source Project
@@ -21,9 +21,6 @@
#define __TONEMAPPER_EGLIMAGEWRAPPER_H__
#include <utils/LruCache.h>
-#ifndef TARGET_HEADLESS
-#include <linux/msm_ion.h>
-#endif
#include <string>
#include <map>
#include "EGLImageBuffer.h"
@@ -39,24 +36,18 @@
void operator()(int& buffInt, EGLImageBuffer*& eglImage);
map<string, int>* buffStrbuffIntMapPtr = nullptr;
bool mapClearPending = false;
- #ifndef TARGET_ION_ABI_VERSION
- int ion_fd = -1;
- #endif
};
android::LruCache<int, EGLImageBuffer *>* eglImageBufferCache;
map<string, int> buffStrbuffIntMap = {};
DeleteEGLImageCallback* callback = 0;
- #ifndef TARGET_ION_ABI_VERSION
- int ion_fd = -1;
- #else
- uint64_t buffInt = 0;
- #endif
+ uint64_t buffInt = 0;
public:
EGLImageWrapper();
~EGLImageWrapper();
EGLImageBuffer* wrap(const void *pvt_handle);
+ void Deinit();
};
#endif // __TONEMAPPER_EGLIMAGEWRAPPER_H__
diff --git a/gralloc/QtiMapperExtensions.cpp b/gralloc/QtiMapperExtensions.cpp
index cace7ba..33cd23d 100644
--- a/gralloc/QtiMapperExtensions.cpp
+++ b/gralloc/QtiMapperExtensions.cpp
@@ -344,7 +344,7 @@
getFormatLayout_cb hidl_cb) {
ALOGD_IF(DEBUG, "%s: Input parameters - wxh: %dx%d usage: 0x%" PRIu64 " format: %d", __FUNCTION__,
width, height, usage, format);
- auto err = Error::BAD_BUFFER;
+ auto err = Error::NONE;
hidl_vec<PlaneLayout> plane_info;
unsigned int alignedw = 0, alignedh = 0;
int plane_count = 0;
@@ -353,34 +353,41 @@
BufferInfo info(width, height, custom_format, usage);
gralloc::GetAlignedWidthAndHeight(info, &alignedw, &alignedh);
size = gralloc::GetSize(info, alignedw, alignedh);
+ gralloc::PlaneLayoutInfo plane_layout[8] = {};
ALOGD_IF(DEBUG, "%s: Aligned width and height - wxh: %ux%u custom_format = %d", __FUNCTION__,
alignedw, alignedh, custom_format);
if (gralloc::IsYuvFormat(custom_format)) {
- gralloc::PlaneLayoutInfo yuv_plane_info[8] = {};
gralloc::GetYUVPlaneInfo(info, custom_format, alignedw, alignedh, flags, &plane_count,
- yuv_plane_info);
- ALOGD_IF(DEBUG, "%s: Number of plane - %d, custom_format - %d", __FUNCTION__, plane_count,
- custom_format);
- plane_info.resize(plane_count);
- for (int i = 0; i < plane_count; i++) {
- plane_info[i].component = yuv_plane_info[i].component;
- plane_info[i].h_subsampling = yuv_plane_info[i].h_subsampling;
- plane_info[i].v_subsampling = yuv_plane_info[i].v_subsampling;
- plane_info[i].offset = yuv_plane_info[i].offset;
- plane_info[i].pixel_increment = yuv_plane_info[i].step;
- plane_info[i].stride = yuv_plane_info[i].stride;
- plane_info[i].stride_bytes = yuv_plane_info[i].stride_bytes;
- plane_info[i].scanlines = yuv_plane_info[i].scanlines;
- plane_info[i].size = yuv_plane_info[i].size;
- ALOGD_IF(DEBUG, "%s: plane info: component - %d", __FUNCTION__, plane_info[i].component);
- ALOGD_IF(DEBUG, "h_subsampling - %u, v_subsampling - %u, offset - %u, pixel_increment - %d",
- plane_info[i].h_subsampling, plane_info[i].v_subsampling, plane_info[i].offset,
- plane_info[i].pixel_increment);
- ALOGD_IF(DEBUG, "stride_pixel - %d, stride_bytes - %d, scanlines - %d, size - %u",
- plane_info[i].stride, plane_info[i].stride_bytes, plane_info[i].scanlines,
- plane_info[i].size);
- }
- err = Error::NONE;
+ plane_layout);
+ } else if (gralloc::IsUncompressedRGBFormat(custom_format) ||
+ gralloc::IsCompressedRGBFormat(custom_format)) {
+ gralloc::GetRGBPlaneInfo(info, custom_format, alignedw, alignedh, flags, &plane_count,
+ plane_layout);
+ } else {
+ err = Error::BAD_BUFFER;
+ hidl_cb(err, size, plane_info);
+ return Void();
+ }
+ ALOGD_IF(DEBUG, "%s: Number of plane - %d, custom_format - %d", __FUNCTION__, plane_count,
+ custom_format);
+ plane_info.resize(plane_count);
+ for (int i = 0; i < plane_count; i++) {
+ plane_info[i].component = plane_layout[i].component;
+ plane_info[i].h_subsampling = plane_layout[i].h_subsampling;
+ plane_info[i].v_subsampling = plane_layout[i].v_subsampling;
+ plane_info[i].offset = plane_layout[i].offset;
+ plane_info[i].pixel_increment = plane_layout[i].step;
+ plane_info[i].stride = plane_layout[i].stride;
+ plane_info[i].stride_bytes = plane_layout[i].stride_bytes;
+ plane_info[i].scanlines = plane_layout[i].scanlines;
+ plane_info[i].size = plane_layout[i].size;
+ ALOGD_IF(DEBUG, "%s: plane info: component - %d", __FUNCTION__, plane_info[i].component);
+ ALOGD_IF(DEBUG, "h_subsampling - %u, v_subsampling - %u, offset - %u, pixel_increment - %d",
+ plane_info[i].h_subsampling, plane_info[i].v_subsampling, plane_info[i].offset,
+ plane_info[i].pixel_increment);
+ ALOGD_IF(DEBUG, "stride_pixel - %d, stride_bytes - %d, scanlines - %d, size - %u",
+ plane_info[i].stride, plane_info[i].stride_bytes, plane_info[i].scanlines,
+ plane_info[i].size);
}
hidl_cb(err, size, plane_info);
return Void();
diff --git a/gralloc/gr_allocator.cpp b/gralloc/gr_allocator.cpp
index ef350b6..5b7efaa 100644
--- a/gralloc/gr_allocator.cpp
+++ b/gralloc/gr_allocator.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2019, The Linux Foundation. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -32,6 +32,10 @@
#include <algorithm>
#include <vector>
+#ifndef QMAA
+#include <linux/msm_ion.h>
+#endif
+
#include "gr_allocator.h"
#include "gr_utils.h"
#include "gralloc_priv.h"
diff --git a/gralloc/gr_ion_alloc.cpp b/gralloc/gr_ion_alloc.cpp
index c9a74ce..68d3083 100644
--- a/gralloc/gr_ion_alloc.cpp
+++ b/gralloc/gr_ion_alloc.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2019, The Linux Foundation. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -31,15 +31,9 @@
#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
#include <sys/ioctl.h>
#include <sys/mman.h>
-#include <linux/ion.h>
-#ifndef QMAA
-#include <linux/msm_ion.h>
-#endif
-#if TARGET_ION_ABI_VERSION >= 2
#include <linux/dma-buf.h>
#include <ion/ion.h>
-#endif
#include <stdlib.h>
#include <fcntl.h>
#include <log/log.h>
@@ -68,8 +62,6 @@
return true;
}
-#if TARGET_ION_ABI_VERSION >= 2 // Use libion APIs for new ion
-
int IonAlloc::OpenIonDevice() {
return ion_open();
}
@@ -162,169 +154,6 @@
return 0;
}
-#else
-#ifndef TARGET_ION_ABI_VERSION // Use old ion apis directly
-
-int IonAlloc::OpenIonDevice() {
- return open(kIonDevice, O_RDONLY);
-}
-
-void IonAlloc::CloseIonDevice() {
- if (ion_dev_fd_ > FD_INIT) {
- close(ion_dev_fd_);
- }
-
- ion_dev_fd_ = FD_INIT;
-}
-
-int IonAlloc::AllocBuffer(AllocData *data) {
- ATRACE_CALL();
- int err = 0;
- struct ion_handle_data handle_data;
- struct ion_fd_data fd_data;
- struct ion_allocation_data ion_alloc_data;
-
- ion_alloc_data.len = data->size;
- ion_alloc_data.align = data->align;
- ion_alloc_data.heap_id_mask = data->heap_id;
- ion_alloc_data.flags = data->flags;
- ion_alloc_data.flags |= data->uncached ? 0 : ION_FLAG_CACHED;
- std::string tag_name{};
- if (ATRACE_ENABLED()) {
- tag_name = "ION_IOC_ALLOC size: " + std::to_string(data->size);
- }
-
- ATRACE_BEGIN(tag_name.c_str());
- if (ioctl(ion_dev_fd_, INT(ION_IOC_ALLOC), &ion_alloc_data)) {
- err = -errno;
- ALOGE("ION_IOC_ALLOC failed with error - %s", strerror(errno));
- return err;
- }
- ATRACE_END();
-
- fd_data.handle = ion_alloc_data.handle;
- handle_data.handle = ion_alloc_data.handle;
- ATRACE_BEGIN("ION_IOC_MAP");
- if (ioctl(ion_dev_fd_, INT(ION_IOC_MAP), &fd_data)) {
- err = -errno;
- ALOGE("%s: ION_IOC_MAP failed with error - %s", __FUNCTION__, strerror(errno));
- ioctl(ion_dev_fd_, INT(ION_IOC_FREE), &handle_data);
- return err;
- }
- ATRACE_END();
-
- data->fd = fd_data.fd;
- data->ion_handle = handle_data.handle;
- ALOGD_IF(DEBUG, "ion: Allocated buffer size:%zu fd:%d handle:0x%x", ion_alloc_data.len, data->fd,
- data->ion_handle);
-
- return 0;
-}
-
-int IonAlloc::FreeBuffer(void *base, unsigned int size, unsigned int offset, int fd,
- int ion_handle) {
- ATRACE_CALL();
- int err = 0;
- ALOGD_IF(DEBUG, "ion: Freeing buffer base:%p size:%u fd:%d handle:0x%x", base, size, fd,
- ion_handle);
-
- if (base) {
- err = UnmapBuffer(base, size, offset);
- }
-
- if (ion_handle > 0) {
- struct ion_handle_data handle_data;
- handle_data.handle = ion_handle;
- ioctl(ion_dev_fd_, INT(ION_IOC_FREE), &handle_data);
- }
- close(fd);
- return err;
-}
-
-int IonAlloc::ImportBuffer(int fd) {
- struct ion_fd_data fd_data;
- int err = 0;
- fd_data.fd = fd;
- if (ioctl(ion_dev_fd_, INT(ION_IOC_IMPORT), &fd_data)) {
- err = -errno;
- ALOGE("%s: ION_IOC_IMPORT failed with error - %s", __FUNCTION__, strerror(errno));
- return err;
- }
- return fd_data.handle;
-}
-
-int IonAlloc::CleanBuffer(void *base, unsigned int size, unsigned int offset, int handle, int op,
- int /*fd*/) {
- if (op == CACHE_READ_DONE) {
- return 0;
- }
-
-#ifndef QMAA
- ATRACE_CALL();
- ATRACE_INT("operation id", op);
- struct ion_flush_data flush_data;
- int err = 0;
-
- flush_data.handle = handle;
- flush_data.vaddr = base;
- // offset and length are unsigned int
- flush_data.offset = offset;
- flush_data.length = size;
-
- struct ion_custom_data d;
- switch (op) {
- case CACHE_CLEAN:
- d.cmd = ION_IOC_CLEAN_CACHES;
- break;
- case CACHE_INVALIDATE:
- d.cmd = ION_IOC_INV_CACHES;
- break;
- case CACHE_CLEAN_AND_INVALIDATE:
- default:
- d.cmd = ION_IOC_CLEAN_INV_CACHES;
- }
-
- d.arg = (unsigned long)(&flush_data); // NOLINT
- if (ioctl(ion_dev_fd_, INT(ION_IOC_CUSTOM), &d)) {
- err = -errno;
- ALOGE("%s: ION_IOC_CLEAN_INV_CACHES failed with error - %s", __FUNCTION__, strerror(errno));
- return err;
- }
-#endif
- return 0;
-}
-
-#else // This ion version is not supported
-
-int IonAlloc::OpenIonDevice() {
- return -EINVAL;
-}
-
-void IonAlloc::CloseIonDevice() {
-}
-
-int IonAlloc::AllocBuffer(AllocData * /*data*/) {
- return -EINVAL;
-}
-
-int IonAlloc::FreeBuffer(void * /*base*/, unsigned int /*size*/, unsigned int /*offset*/,
- int /*fd*/, int /*ion_handle*/) {
- return -EINVAL;
-}
-
-int IonAlloc::ImportBuffer(int /*fd*/) {
- return -EINVAL;
-}
-
-int IonAlloc::CleanBuffer(void * /*base*/, unsigned int /*size*/, unsigned int /*offset*/,
- int /*handle*/, int /*op*/, int /*fd*/) {
- return -EINVAL;
-}
-
-#endif
-#endif // TARGET_ION_ABI_VERSION
-
-
int IonAlloc::MapBuffer(void **base, unsigned int size, unsigned int offset, int fd) {
ATRACE_CALL();
int err = 0;
diff --git a/gralloc/gr_ion_alloc.h b/gralloc/gr_ion_alloc.h
index 13474f5..e84a510 100644
--- a/gralloc/gr_ion_alloc.h
+++ b/gralloc/gr_ion_alloc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2019, The Linux Foundation. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -30,10 +30,6 @@
#ifndef __GR_ION_ALLOC_H__
#define __GR_ION_ALLOC_H__
-#ifndef QMAA
-#include <linux/msm_ion.h>
-#endif
-
#define FD_INIT -1
namespace gralloc {
@@ -74,10 +70,6 @@
int CleanBuffer(void *base, unsigned int size, unsigned int offset, int handle, int op, int fd);
private:
-#ifndef TARGET_ION_ABI_VERSION
- const char *kIonDevice = "/dev/ion";
-#endif
-
int OpenIonDevice();
void CloseIonDevice();
diff --git a/gralloc/gr_utils.cpp b/gralloc/gr_utils.cpp
index 49dcfb4..16e41b1 100644
--- a/gralloc/gr_utils.cpp
+++ b/gralloc/gr_utils.cpp
@@ -853,6 +853,28 @@
return size;
}
+unsigned int GetRgbMetaSize(int format, uint32_t width, uint32_t height, uint64_t usage) {
+ unsigned int meta_size = 0;
+ if (!IsUBwcEnabled(format, usage)) {
+ return meta_size;
+ }
+ uint32_t bpp = GetBppForUncompressedRGB(format);
+ switch (format) {
+ case HAL_PIXEL_FORMAT_BGR_565:
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ case HAL_PIXEL_FORMAT_RGBA_1010102:
+ case HAL_PIXEL_FORMAT_RGBX_1010102:
+ case HAL_PIXEL_FORMAT_RGBA_FP16:
+ meta_size = GetRgbUBwcMetaBufferSize(width, height, bpp);
+ break;
+ default:
+ ALOGE("%s:Unsupported RGB format: 0x%x", __FUNCTION__, format);
+ break;
+ }
+ return meta_size;
+}
+
int GetRgbDataAddress(private_handle_t *hnd, void **rgb_data) {
int err = 0;
@@ -866,23 +888,8 @@
*rgb_data = reinterpret_cast<void *>(hnd->base);
return err;
}
+ unsigned int meta_size = GetRgbMetaSize(hnd->format, hnd->width, hnd->height, hnd->usage);
- unsigned int meta_size = 0;
- uint32_t bpp = GetBppForUncompressedRGB(hnd->format);
- switch (hnd->format) {
- case HAL_PIXEL_FORMAT_BGR_565:
- case HAL_PIXEL_FORMAT_RGBA_8888:
- case HAL_PIXEL_FORMAT_RGBX_8888:
- case HAL_PIXEL_FORMAT_RGBA_1010102:
- case HAL_PIXEL_FORMAT_RGBX_1010102:
- case HAL_PIXEL_FORMAT_RGBA_FP16:
- meta_size = GetRgbUBwcMetaBufferSize(hnd->width, hnd->height, bpp);
- break;
- default:
- ALOGE("%s:Unsupported RGB format: 0x%x", __FUNCTION__, hnd->format);
- err = -EINVAL;
- break;
- }
*rgb_data = reinterpret_cast<void *>(hnd->base + meta_size);
return err;
@@ -1652,4 +1659,40 @@
}
}
+bool HasAlphaComponent(int32_t format) {
+ switch (format) {
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ case HAL_PIXEL_FORMAT_RGBA_5551:
+ case HAL_PIXEL_FORMAT_RGBA_4444:
+ case HAL_PIXEL_FORMAT_RGBA_1010102:
+ case HAL_PIXEL_FORMAT_ARGB_2101010:
+ case HAL_PIXEL_FORMAT_BGRA_1010102:
+ case HAL_PIXEL_FORMAT_ABGR_2101010:
+ case HAL_PIXEL_FORMAT_RGBA_FP16:
+ return true;
+ default:
+ return false;
+ }
+}
+
+void GetRGBPlaneInfo(const BufferInfo &info, int32_t format, int32_t width, int32_t height,
+ int32_t /* flags */, int *plane_count, PlaneLayoutInfo *plane_info) {
+ uint64_t usage = info.usage;
+ *plane_count = 1;
+ plane_info->component =
+ (PlaneComponent)(PLANE_COMPONENT_R | PLANE_COMPONENT_G | PLANE_COMPONENT_B);
+ if (HasAlphaComponent(format)) {
+ plane_info->component = (PlaneComponent)(plane_info->component | PLANE_COMPONENT_A);
+ }
+ plane_info->size = GetSize(info, width, height);
+ plane_info->step = GetBpp(format);
+ plane_info->offset = GetRgbMetaSize(format, width, height, usage);
+ plane_info->h_subsampling = 0;
+ plane_info->v_subsampling = 0;
+ plane_info->stride = width;
+ plane_info->stride_bytes = width * plane_info->step;
+ plane_info->scanlines = height;
+}
+
} // namespace gralloc
diff --git a/gralloc/gr_utils.h b/gralloc/gr_utils.h
index bc5a670..6dbe889 100644
--- a/gralloc/gr_utils.h
+++ b/gralloc/gr_utils.h
@@ -145,6 +145,9 @@
int GetYUVPlaneInfo(const private_handle_t *hnd, struct android_ycbcr ycbcr[2]);
int GetYUVPlaneInfo(const BufferInfo &info, int32_t format, int32_t width, int32_t height,
int32_t flags, int *plane_count, PlaneLayoutInfo plane_info[8]);
+void GetRGBPlaneInfo(const BufferInfo &info, int32_t format, int32_t width, int32_t height,
+ int32_t flags, int *plane_count, PlaneLayoutInfo *plane_info);
+unsigned int GetRgbMetaSize(int format, uint32_t width, uint32_t height, uint64_t usage);
void GetYuvSubSamplingFactor(int32_t format, int *h_subsampling, int *v_subsampling);
void CopyPlaneLayoutInfotoAndroidYcbcr(uint64_t base, int plane_count, PlaneLayoutInfo *plane_info,
struct android_ycbcr *ycbcr);
@@ -180,6 +183,7 @@
int GetCustomFormatFlags(int format, uint64_t usage, int *custom_format, uint64_t *priv_flags);
int GetBufferType(int inputFormat);
bool IsGPUFlagSupported(uint64_t usage);
+bool HasAlphaComponent(int32_t format);
} // namespace gralloc
#endif // __GR_UTILS_H__
diff --git a/include/display_properties.h b/include/display_properties.h
index 163f7ca..5c647b5 100644
--- a/include/display_properties.h
+++ b/include/display_properties.h
@@ -105,6 +105,7 @@
#define DISABLE_DEFER_POWER_STATE DISPLAY_PROP("disable_defer_power_state")
#define ENABLE_OPTIMIZE_REFRESH DISPLAY_PROP("enable_optimize_refresh")
#define DISABLE_PARALLEL_CACHE DISPLAY_PROP("disable_parallel_cache")
+#define DISABLE_LAYER_STITCH DISPLAY_PROP("disable_layer_stitch")
// Disable 3d tonemap support for UI layers
#define DISABLE_UI_3D_TONEMAP DISPLAY_PROP("disable_ui_3d_tonemap")
#define QDCM_DISABLE_FACTORY_MODE_PROP DISPLAY_PROP("qdcm.disable_factory_mode")
diff --git a/libdrmutils/drm_interface.h b/libdrmutils/drm_interface.h
index 4f8edb3..41543d0 100644
--- a/libdrmutils/drm_interface.h
+++ b/libdrmutils/drm_interface.h
@@ -152,6 +152,12 @@
*/
PLANE_SET_MULTIRECT_MODE,
/*
+ * Op: Sets sspp layout on this plane.
+ * Arg: uint32_t - Plane ID
+ * uint32_t - SSPP Layout Index
+ */
+ PLANE_SET_SSPP_LAYOUT,
+ /*
* Op: Sets rotator output frame buffer ID for plane.
* Arg: uint32_t - Plane ID
* uint32_t - Framebuffer ID
@@ -519,6 +525,8 @@
uint32_t rotation_limit_index = 0;
uint32_t line_width_constraints_count = 0;
std::vector< std::pair <uint32_t, uint32_t> > line_width_limits;
+ uint32_t num_mnocports;
+ uint32_t mnoc_bus_width;
};
enum struct DRMPlaneType {
@@ -580,6 +588,9 @@
DUAL_LM_MERGE,
DUAL_LM_MERGE_DSC,
DUAL_LM_DSCMERGE,
+ QUAD_LM_MERGE,
+ QUAD_LM_DSCMERGE,
+ QUAD_LM_MERGE_DSC,
PPSPLIT,
};
@@ -811,6 +822,12 @@
SERIAL = 2,
};
+enum struct DRMSSPPLayoutIndex {
+ NONE = 0,
+ LEFT = 1,
+ RIGHT = 2,
+};
+
enum struct DRMCWbCaptureMode {
MIXER_OUT = 0,
DSPP_OUT = 1,
diff --git a/sde-drm/drm_atomic_req.cpp b/sde-drm/drm_atomic_req.cpp
index a33bb8d..8f38133 100644
--- a/sde-drm/drm_atomic_req.cpp
+++ b/sde-drm/drm_atomic_req.cpp
@@ -83,7 +83,8 @@
case DRMOps::PLANE_SET_EXCL_RECT:
case DRMOps::PLANE_SET_INVERSE_PMA:
case DRMOps::PLANE_SET_DGM_CSC_CONFIG:
- case DRMOps::PLANE_SET_POST_PROC: {
+ case DRMOps::PLANE_SET_POST_PROC:
+ case DRMOps::PLANE_SET_SSPP_LAYOUT: {
drm_mgr_->GetPlaneMgr()->Perform(opcode, obj_id, drm_atomic_req_, args);
} break;
case DRMOps::CRTC_SET_POST_PROC:
diff --git a/sde-drm/drm_connector.cpp b/sde-drm/drm_connector.cpp
index 9ae5d0a..aeb9d7c 100644
--- a/sde-drm/drm_connector.cpp
+++ b/sde-drm/drm_connector.cpp
@@ -159,6 +159,9 @@
if (topology == "sde_dualpipemerge") return DRMTopology::DUAL_LM_MERGE;
if (topology == "sde_dualpipemerge_dsc") return DRMTopology::DUAL_LM_MERGE_DSC;
if (topology == "sde_dualpipe_dscmerge") return DRMTopology::DUAL_LM_DSCMERGE;
+ if (topology == "sde_quadpipemerge") return DRMTopology::QUAD_LM_MERGE;
+ if (topology == "sde_quadpipe_dscmerge") return DRMTopology::QUAD_LM_DSCMERGE;
+ if (topology == "sde_quadpipe_3dmerge_dsc") return DRMTopology::QUAD_LM_MERGE_DSC;
if (topology == "sde_ppsplit") return DRMTopology::PPSPLIT;
return DRMTopology::UNKNOWN;
}
diff --git a/sde-drm/drm_crtc.cpp b/sde-drm/drm_crtc.cpp
index ef1e692..f8890d1 100644
--- a/sde-drm/drm_crtc.cpp
+++ b/sde-drm/drm_crtc.cpp
@@ -349,6 +349,8 @@
string solidfill_stages = "dim_layer_v1_max_layers=";
string has_hdr = "has_hdr=";
string min_prefill_lines = "min_prefill_lines=";
+ string num_mnocports = "num_mnoc_ports=";
+ string mnoc_bus_width = "axi_bus_width=";
crtc_info_.max_solidfill_stages = 0; // default _
string dest_scaler_count = "dest_scaler_count=";
@@ -439,6 +441,10 @@
crtc_info_.min_prefill_lines = std::stoi(string(line, min_prefill_lines.length()));
} else if (line.find(sec_ui_blendstage) != string::npos) {
crtc_info_.secure_disp_blend_stage = std::stoi(string(line, (sec_ui_blendstage).length()));
+ } else if (line.find(num_mnocports) != string::npos) {
+ crtc_info_.num_mnocports = std::stoi(string(line, num_mnocports.length()));
+ } else if (line.find(mnoc_bus_width) != string::npos) {
+ crtc_info_.mnoc_bus_width = std::stoi(string(line, mnoc_bus_width.length()));
} else if (line.find(linewidth_constraints) != string::npos) {
crtc_info_.line_width_constraints_count =
std::stoi(string(line, (linewidth_constraints).length()));
diff --git a/sde-drm/drm_dpps_mgr_imp.cpp b/sde-drm/drm_dpps_mgr_imp.cpp
index 68ed4a5..99a690b 100644
--- a/sde-drm/drm_dpps_mgr_imp.cpp
+++ b/sde-drm/drm_dpps_mgr_imp.cpp
@@ -203,6 +203,7 @@
}
void DRMDppsManagerImp::Init(int fd, drmModeRes* res) {
+ std::lock_guard<std::mutex> guard(api_lock_);
int ret = 0;
if (fd < 0 || !res) {
@@ -315,6 +316,7 @@
}
void DRMDppsManagerImp::CacheDppsFeature(uint32_t obj_id, va_list args) {
+ std::lock_guard<std::mutex> guard(api_lock_);
uint32_t feature_id = va_arg(args, uint32_t);
uint64_t value = va_arg(args, uint64_t);
struct DRMDppsPropInfo* info;
@@ -341,6 +343,7 @@
}
void DRMDppsManagerImp::CommitDppsFeatures(drmModeAtomicReq *req, const DRMDisplayToken &tok) {
+ std::lock_guard<std::mutex> guard(api_lock_);
int ret = 0;
if (!req)
@@ -398,6 +401,7 @@
void DRMDppsManagerImp::GetDppsFeatureInfo(DRMDppsFeatureInfo *info)
{
+ std::lock_guard<std::mutex> guard(api_lock_);
int ret = 0;
struct DRMDppsPropInfo* prop_info;
diff --git a/sde-drm/drm_dpps_mgr_imp.h b/sde-drm/drm_dpps_mgr_imp.h
index eefb213..a264e01 100644
--- a/sde-drm/drm_dpps_mgr_imp.h
+++ b/sde-drm/drm_dpps_mgr_imp.h
@@ -33,6 +33,7 @@
#include "drm_interface.h"
#include "drm_property.h"
#include "drm_dpps_mgr_intf.h"
+#include <mutex>
namespace sde_drm {
@@ -73,6 +74,7 @@
int drm_fd_ = -1;
std::vector<std::pair<uint32_t, drm_msm_ltm_buffers_ctrl>> ltm_buffers_ctrl_map_;
std::vector<std::pair<uint32_t, DRMDppsLtmBuffers>> ltm_buffers_map_;
+ std::mutex api_lock_;
};
class DRMDppsManagerDummyImp : public DRMDppsManagerIntf {
diff --git a/sde-drm/drm_plane.cpp b/sde-drm/drm_plane.cpp
index 2939df2..459ba67 100644
--- a/sde-drm/drm_plane.cpp
+++ b/sde-drm/drm_plane.cpp
@@ -969,6 +969,18 @@
}
} break;
+ case DRMOps::PLANE_SET_SSPP_LAYOUT: {
+ if (!prop_mgr_.IsPropertyAvailable(DRMProperty::SDE_SSPP_LAYOUT)) {
+ DRM_LOGD("SSPP_LAYOUT property isn't exposed");
+ break;
+ }
+ DRMSSPPLayoutIndex layout_index = (DRMSSPPLayoutIndex) va_arg(args, uint32_t);
+ prop_id = prop_mgr_.GetPropertyId(DRMProperty::SDE_SSPP_LAYOUT);
+ AddProperty(req, obj_id, prop_id, (uint32_t)layout_index , true /* cache */,
+ tmp_prop_val_map_);
+ DRM_LOGD("Plane %d: Setting SSPP Layout to %d", obj_id, layout_index);
+ } break;
+
default:
DRM_LOGE("Invalid opcode %d for DRM Plane %d", code, obj_id);
}
diff --git a/sde-drm/drm_property.cpp b/sde-drm/drm_property.cpp
index c144aad..5dadd2b 100644
--- a/sde-drm/drm_property.cpp
+++ b/sde-drm/drm_property.cpp
@@ -162,6 +162,7 @@
if (name == "frame_trigger_mode") { return DRMProperty::FRAME_TRIGGER; }
if (name == "Colorspace") { return DRMProperty::COLORSPACE; }
if (name == "supported_colorspaces") { return DRMProperty::SUPPORTED_COLORSPACES; }
+ if (name == "sspp_layout") { return DRMProperty::SDE_SSPP_LAYOUT; }
return DRMProperty::INVALID;
}
diff --git a/sde-drm/drm_property.h b/sde-drm/drm_property.h
index dcda7aa..9ec8a83 100644
--- a/sde-drm/drm_property.h
+++ b/sde-drm/drm_property.h
@@ -167,6 +167,7 @@
FRAME_TRIGGER,
COLORSPACE,
SUPPORTED_COLORSPACES,
+ SDE_SSPP_LAYOUT,
// Insert above
MAX
diff --git a/sdm/include/core/core_interface.h b/sdm/include/core/core_interface.h
index 90b496d..072b677 100644
--- a/sdm/include/core/core_interface.h
+++ b/sdm/include/core/core_interface.h
@@ -258,6 +258,14 @@
*/
virtual DisplayError GetMaxDisplaysSupported(DisplayType type, int32_t *max_displays) = 0;
+ /*! @brief Method which returns true if the given format is supported by rotator otherwise false
+
+ @param[in] \link LayerBufferFormat \endlink
+
+ @return returns true if the given format is supported by rotator otherwise false
+ */
+ virtual bool IsRotatorSupportedFormat(LayerBufferFormat format) = 0;
+
protected:
virtual ~CoreInterface() { }
};
diff --git a/sdm/include/core/display_interface.h b/sdm/include/core/display_interface.h
index ee2b731..c1dc190 100644
--- a/sdm/include/core/display_interface.h
+++ b/sdm/include/core/display_interface.h
@@ -670,6 +670,14 @@
*/
virtual DisplayError GetPanelBrightness(float *brightness) = 0;
+ /*! @brief Method to get the max brightness level of the display
+
+ @param[out] max_brightness level
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError GetPanelMaxBrightness(uint32_t *max_brightness_level) = 0;
+
/*! @brief Method to set layer mixer resolution.
@param[in] width layer mixer width
diff --git a/sdm/include/core/layer_stack.h b/sdm/include/core/layer_stack.h
index 8a03bfc..ec3b38e 100644
--- a/sdm/include/core/layer_stack.h
+++ b/sdm/include/core/layer_stack.h
@@ -80,6 +80,9 @@
//!< This composition type is used only if GPUTarget layer is provided
//!< in a composition cycle.
+ kCompositionStitch, //!< This layer will be drawn onto the target buffer by GPU. No blend
+ //!< required.
+
kCompositionSDE, //!< This layer will be composed by SDE. It must not be composed by
//!< GPU or Blit.
@@ -104,6 +107,9 @@
//!< Only one layer shall be marked as target buffer by the caller.
//!< GPU target layer shall be placed after all application layers
//!< in the layer stack.
+
+ kCompositionStitchTarget, //!< This layer will hold result of composition for layers marked fo
+ //!< Blit composition.
};
enum LayerUpdate {
@@ -341,6 +347,9 @@
//!< fit into this rectangle. The origin is the
//!< top-left corner of the screen.
+ LayerRect stitch_dst_rect = {}; //!< The target position where the frame will be
+ //!< rendered onto internal FrameBuffer.
+
std::vector<LayerRect> visible_regions = {}; //!< Visible rectangular areas in screen space.
//!< The visible region includes areas overlapped
//!< by a translucent layer.
diff --git a/sdm/include/private/extension_interface.h b/sdm/include/private/extension_interface.h
index b889cab..6545c41 100644
--- a/sdm/include/private/extension_interface.h
+++ b/sdm/include/private/extension_interface.h
@@ -63,6 +63,7 @@
virtual DisplayError CreateStrategyExtn(int32_t display_id, DisplayType type,
BufferAllocator *buffer_allocator,
+ BufferSyncHandler *buffer_sync_handler,
const HWResourceInfo &hw_resource_info,
const HWPanelInfo &hw_panel_info,
const HWMixerAttributes &mixer_attributes,
diff --git a/sdm/include/private/hw_info_types.h b/sdm/include/private/hw_info_types.h
index 42822a0..8997cc6 100644
--- a/sdm/include/private/hw_info_types.h
+++ b/sdm/include/private/hw_info_types.h
@@ -145,9 +145,18 @@
kDualLMMerge,
kDualLMMergeDSC,
kDualLMDSCMerge,
+ kQuadLMMerge,
+ kQuadLMDSCMerge,
+ kQuadLMMergeDSC,
kPPSplit,
};
+enum HWMixerSplit {
+ kNoSplit,
+ kDualSplit,
+ kQuadSplit,
+};
+
enum HwHdrEotf {
kHdrEOTFInvalid = 0,
kHdrEOTFSDR = 0x1,
@@ -333,6 +342,8 @@
uint32_t line_width_constraints_count = 0;
vector< pair <uint32_t, uint32_t> > line_width_limits;
vector< pair <uint32_t, uint32_t> > line_width_constraints;
+ uint32_t num_mnocports = 2;
+ uint32_t mnoc_bus_width = 32;
};
struct HWSplitInfo {
@@ -656,9 +667,10 @@
};
struct HWLayersInfo {
- LayerStack *stack = NULL; // Input layer stack. Set by the caller.
- uint32_t app_layer_count = 0; // Total number of app layers. Must not be 0.
- uint32_t gpu_target_index = 0; // GPU target layer index. 0 if not present.
+ LayerStack *stack = NULL; // Input layer stack. Set by the caller.
+ uint32_t app_layer_count = 0; // Total number of app layers. Must not be 0.
+ uint32_t gpu_target_index = 0; // GPU target layer index. 0 if not present.
+ uint32_t stitch_target_index = 0; // Blit target layer index. 0 if not present.
std::vector<ColorPrimaries> wide_color_primaries = {}; // list of wide color primaries
std::vector<Layer> hw_layers = {}; // Layers which need to be programmed on the HW
@@ -760,12 +772,14 @@
struct HWMixerAttributes {
uint32_t width = 0; // Layer mixer width
uint32_t height = 0; // Layer mixer height
- uint32_t split_left = 0;
+ uint32_t split_left = 0; // Left portion of layer mixer
+ HWMixerSplit split_type = kNoSplit; // Mixer topology
LayerBufferFormat output_format = kFormatRGB101010; // Layer mixer output format
bool operator !=(const HWMixerAttributes &mixer_attributes) {
return ((width != mixer_attributes.width) ||
(height != mixer_attributes.height) ||
+ (split_type != mixer_attributes.split_type) ||
(output_format != mixer_attributes.output_format) ||
(split_left != mixer_attributes.split_left));
}
diff --git a/sdm/include/private/resource_interface.h b/sdm/include/private/resource_interface.h
index 56db4ce..4baef57 100644
--- a/sdm/include/private/resource_interface.h
+++ b/sdm/include/private/resource_interface.h
@@ -73,6 +73,7 @@
virtual DisplayError SetDetailEnhancerData(Handle display_ctx,
const DisplayDetailEnhancerData &de_data) = 0;
virtual DisplayError Perform(int cmd, ...) = 0;
+ virtual bool IsRotatorSupportedFormat(LayerBufferFormat format) = 0;
virtual ~ResourceInterface() { }
};
diff --git a/sdm/include/utils/constants.h b/sdm/include/utils/constants.h
index 691e88c..83f198b 100644
--- a/sdm/include/utils/constants.h
+++ b/sdm/include/utils/constants.h
@@ -84,6 +84,7 @@
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0 };
+ const float kBufferHeightFactor = 1.5f;
typedef void * Handle;
diff --git a/sdm/include/utils/fence.h b/sdm/include/utils/fence.h
new file mode 100644
index 0000000..94bb01b
--- /dev/null
+++ b/sdm/include/utils/fence.h
@@ -0,0 +1,77 @@
+/*
+* Copyright (c) 2019, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __FENCE_H__
+#define __FENCE_H__
+
+#include <core/buffer_sync_handler.h>
+#include <unistd.h>
+#include <utility>
+#include <memory>
+#include <string>
+
+namespace sdm {
+
+using std::shared_ptr;
+using std::string;
+
+class Fence {
+ public:
+ ~Fence();
+
+ static void Set(BufferSyncHandler *buffer_sync_handler);
+
+ // Ownership of the file descriptor is transferred to this method.
+ // Client must not close the file descriptor anymore regardless of the object creation status.
+ // nullptr will be retured for invalid fd i.e. -1.
+ static shared_ptr<Fence> Create(int fd);
+
+ // Ownership of returned fd lies with caller. Caller must explicitly close the fd.
+ static int Dup(const shared_ptr<Fence> &fence);
+
+ static shared_ptr<Fence> Merge(const shared_ptr<Fence> &fence1, const shared_ptr<Fence> &fence2);
+ static DisplayError Wait(const shared_ptr<Fence> &fence);
+ static DisplayError Wait(const shared_ptr<Fence> &fence, int timeout);
+ static string GetStr(const shared_ptr<Fence> &fence);
+
+ private:
+ explicit Fence(int fd);
+ Fence(const Fence &fence) = delete;
+ Fence& operator=(const Fence &fence) = delete;
+ Fence(Fence &&fence) = delete;
+ Fence& operator=(Fence &&fence) = delete;
+ static int Get(const shared_ptr<Fence> &fence);
+
+ static BufferSyncHandler *buffer_sync_handler_;
+ int fd_ = -1;
+};
+
+} // namespace sdm
+
+#endif // __FENCE_H__
diff --git a/sdm/libs/core/comp_manager.cpp b/sdm/libs/core/comp_manager.cpp
index 6ee5032..2500bd5 100644
--- a/sdm/libs/core/comp_manager.cpp
+++ b/sdm/libs/core/comp_manager.cpp
@@ -63,6 +63,7 @@
hw_res_info_ = hw_res_info;
buffer_allocator_ = buffer_allocator;
extension_intf_ = extension_intf;
+ sync_handler_ = buffer_sync_handler;
return error;
}
@@ -96,8 +97,9 @@
}
Strategy *&strategy = display_comp_ctx->strategy;
- strategy = new Strategy(extension_intf_, buffer_allocator_, display_id, type, hw_res_info_,
- hw_panel_info, mixer_attributes, display_attributes, fb_config);
+ strategy = new Strategy(extension_intf_, buffer_allocator_, sync_handler_, display_id, type,
+ hw_res_info_, hw_panel_info, mixer_attributes, display_attributes,
+ fb_config);
if (!strategy) {
DLOGE("Unable to create strategy");
delete display_comp_ctx;
@@ -348,8 +350,6 @@
return error;
}
- error = resource_intf_->Stop(display_resource_ctx, hw_layers);
-
return error;
}
@@ -411,6 +411,12 @@
DisplayCompositionContext *display_comp_ctx =
reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+ Handle &display_resource_ctx = display_comp_ctx->display_resource_ctx;
+ error = resource_intf_->Stop(display_resource_ctx, hw_layers);
+ if (error != kErrorNone) {
+ DLOGE("Resource stop failed for display = %d", display_comp_ctx->display_type);
+ }
+
error = resource_intf_->PostCommit(display_comp_ctx->display_resource_ctx, hw_layers);
if (error != kErrorNone) {
return error;
@@ -684,4 +690,12 @@
return res_wait_needed;
}
+bool CompManager::IsRotatorSupportedFormat(LayerBufferFormat format) {
+ if (resource_intf_) {
+ return resource_intf_->IsRotatorSupportedFormat(format);
+ }
+
+ return false;
+}
+
} // namespace sdm
diff --git a/sdm/libs/core/comp_manager.h b/sdm/libs/core/comp_manager.h
index 8a6b665..6846eda 100644
--- a/sdm/libs/core/comp_manager.h
+++ b/sdm/libs/core/comp_manager.h
@@ -89,6 +89,7 @@
DisplayError CheckEnforceSplit(Handle comp_handle, uint32_t new_refresh_rate);
DppsControlInterface* GetDppsControlIntf() { return dpps_ctrl_intf_; }
bool CheckResourceState(Handle display_ctx);
+ bool IsRotatorSupportedFormat(LayerBufferFormat format);
private:
static const int kMaxThermalLevel = 3;
@@ -131,6 +132,7 @@
uint32_t max_sde_ext_layers_ = 0;
uint32_t max_sde_builtin_layers_ = 2;
DppsControlInterface *dpps_ctrl_intf_ = NULL;
+ BufferSyncHandler *sync_handler_ = NULL;
};
} // namespace sdm
diff --git a/sdm/libs/core/core_impl.cpp b/sdm/libs/core/core_impl.cpp
index 8aaac7c..9b0eaec 100644
--- a/sdm/libs/core/core_impl.cpp
+++ b/sdm/libs/core/core_impl.cpp
@@ -254,5 +254,10 @@
return hw_info_intf_->GetMaxDisplaysSupported(type, max_displays);
}
+bool CoreImpl::IsRotatorSupportedFormat(LayerBufferFormat format) {
+ SCOPE_LOCK(locker_);
+ return comp_mgr_.IsRotatorSupportedFormat(format);
+}
+
} // namespace sdm
diff --git a/sdm/libs/core/core_impl.h b/sdm/libs/core/core_impl.h
index 94e61d7..4af2311 100644
--- a/sdm/libs/core/core_impl.h
+++ b/sdm/libs/core/core_impl.h
@@ -62,6 +62,7 @@
virtual DisplayError GetFirstDisplayInterfaceType(HWDisplayInterfaceInfo *hw_disp_info);
virtual DisplayError GetDisplaysStatus(HWDisplaysInfo *hw_displays_info);
virtual DisplayError GetMaxDisplaysSupported(DisplayType type, int32_t *max_displays);
+ virtual bool IsRotatorSupportedFormat(LayerBufferFormat format);
protected:
Locker locker_;
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index 3087280..b355749 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -216,24 +216,27 @@
}
if (layer->composition == kCompositionGPUTarget) {
hw_layers_info.gpu_target_index = hw_layers_info.app_layer_count;
+ } else if (layer->composition == kCompositionStitchTarget) {
+ hw_layers_info.stitch_target_index = hw_layers_info.gpu_target_index + 1;
break;
+ } else {
+ hw_layers_info.app_layer_count++;
}
- hw_layers_info.app_layer_count++;
if (IsWideColor(layer->input_buffer.color_metadata.colorPrimaries)) {
hw_layers_info.wide_color_primaries.push_back(
layer->input_buffer.color_metadata.colorPrimaries);
}
if (layer->flags.is_game) {
- hw_layers_info.game_present = true;
+ hw_layers_info.game_present = true;
}
}
- DLOGD_IF(kTagDisplay,
- "LayerStack layer_count: %d, app_layer_count: %d, "
- "gpu_target_index: %d, game_present: %d, display: %d-%d",
- layers.size(), hw_layers_info.app_layer_count,
- hw_layers_info.gpu_target_index, hw_layers_info.game_present,
- display_id_, display_type_);
+ hw_layers_info.stitch_target_index = hw_layers_info.gpu_target_index + 1;
+ DLOGD_IF(kTagDisplay, "LayerStack layer_count: %d, app_layer_count: %d, "
+ "gpu_target_index: %d, stitch_index: %d game_present: %d, display: %d-%d",
+ layers.size(), hw_layers_info.app_layer_count,
+ hw_layers_info.gpu_target_index, hw_layers_info.stitch_target_index,
+ hw_layers_info.game_present, display_id_, display_type_);
if (!hw_layers_info.app_layer_count) {
DLOGW("Layer count is zero");
@@ -435,6 +438,7 @@
return error;
}
+ comp_manager_->SetSafeMode(false);
DLOGI_IF(kTagDisplay, "Exiting commit for display: %d-%d", display_id_, display_type_);
@@ -628,6 +632,11 @@
active_ = active;
state_ = state;
comp_manager_->SetDisplayState(display_comp_ctx_, state, release_fence ? *release_fence : -1);
+ // If previously requested doze state is still pending reset it on any new display state request
+ // and handle the new request.
+ if (state_ != kStateDoze) {
+ pending_doze_ = false;
+ }
}
// Handle vsync pending on resume, Since the power on commit is synchronous we pass -1 as retire
@@ -898,11 +907,13 @@
const char * DisplayBase::GetName(const LayerComposition &composition) {
switch (composition) {
- case kCompositionGPU: return "GPU";
- case kCompositionSDE: return "SDE";
- case kCompositionCursor: return "CURSOR";
- case kCompositionGPUTarget: return "GPU_TARGET";
- default: return "UNKNOWN";
+ case kCompositionGPU: return "GPU";
+ case kCompositionSDE: return "SDE";
+ case kCompositionCursor: return "CURSOR";
+ case kCompositionStitch: return "STITCH";
+ case kCompositionGPUTarget: return "GPU_TARGET";
+ case kCompositionStitchTarget: return "STITCH_TARGET";
+ default: return "UNKNOWN";
}
}
@@ -980,6 +991,10 @@
return kErrorNotSupported;
}
+ if (color_mode.empty()) {
+ return kErrorParameters;
+ }
+
DisplayError error = kErrorNone;
std::string dynamic_range = kSdr, str_render_intent;
if (IsSupportColorModeAttribute(color_mode)) {
@@ -1963,6 +1978,11 @@
PrimariesTransfer DisplayBase::GetBlendSpaceFromColorMode() {
PrimariesTransfer pt = {};
auto current_color_attr_ = color_mode_attr_map_.find(current_color_mode_);
+ if (current_color_attr_ == color_mode_attr_map_.end()) {
+ DLOGE("The attritbutes is not present in color mode: %s", current_color_mode_.c_str());
+ return pt;
+ }
+
AttrVal attr = current_color_attr_->second;
std::string color_gamut = kNative, dynamic_range = kSdr, pic_quality = kStandard;
std::string transfer = {};
diff --git a/sdm/libs/core/display_base.h b/sdm/libs/core/display_base.h
index 1151ce6..00d1799 100644
--- a/sdm/libs/core/display_base.h
+++ b/sdm/libs/core/display_base.h
@@ -120,6 +120,9 @@
virtual DisplayError GetPanelBrightness(float *brightness) {
return kErrorNotSupported;
}
+ virtual DisplayError GetPanelMaxBrightness(uint32_t *max_brightness_level) {
+ return kErrorNotSupported;
+ }
virtual DisplayError SetVSyncState(bool enable);
virtual void SetIdleTimeoutMs(uint32_t active_ms) {}
virtual DisplayError SetMixerResolution(uint32_t width, uint32_t height);
diff --git a/sdm/libs/core/display_builtin.cpp b/sdm/libs/core/display_builtin.cpp
index 3a5a8a1..076e2ef 100644
--- a/sdm/libs/core/display_builtin.cpp
+++ b/sdm/libs/core/display_builtin.cpp
@@ -523,6 +523,20 @@
return kErrorNone;
}
+DisplayError DisplayBuiltIn::GetPanelMaxBrightness(uint32_t *max_brightness_level) {
+ lock_guard<recursive_mutex> obj(brightness_lock_);
+
+ if (!max_brightness_level) {
+ DLOGE("Invalid input pointer is null");
+ return kErrorParameters;
+ }
+
+ *max_brightness_level = static_cast<uint32_t>(hw_panel_info_.panel_max_brightness);
+
+ DLOGI_IF(kTagDisplay, "Get panel max_brightness_level %u", *max_brightness_level);
+ return kErrorNone;
+}
+
DisplayError DisplayBuiltIn::ControlPartialUpdate(bool enable, uint32_t *pending) {
lock_guard<recursive_mutex> obj(recursive_mutex_);
if (!pending) {
@@ -535,6 +549,12 @@
return kErrorNotSupported;
}
+ if (dpps_info_.disable_pu_ && enable) {
+ // Nothing to be done.
+ DLOGI("partial update is disabled by DPPS for display id = %d", display_id_);
+ return kErrorNotSupported;
+ }
+
*pending = 0;
if (enable == partial_update_control_) {
DLOGI("Same state transition is requested.");
@@ -596,6 +616,7 @@
break;
}
enable = *(reinterpret_cast<bool *>(payload));
+ dpps_info_.disable_pu_ = !enable;
ControlPartialUpdate(enable, &pending);
event_handler_->HandleEvent(kInvalidateDisplay);
event_handler_->Refresh();
diff --git a/sdm/libs/core/display_builtin.h b/sdm/libs/core/display_builtin.h
index b59752e..8494091 100644
--- a/sdm/libs/core/display_builtin.h
+++ b/sdm/libs/core/display_builtin.h
@@ -39,6 +39,7 @@
void Init(DppsPropIntf *intf, const std::string &panel_name);
void Deinit();
void DppsNotifyOps(enum DppsNotifyOps op, void *payload, size_t size);
+ bool disable_pu_ = false;
private:
const char *kDppsLib_ = "libdpps.so";
@@ -71,6 +72,7 @@
virtual DisplayError SetRefreshRate(uint32_t refresh_rate, bool final_rate);
virtual DisplayError SetPanelBrightness(float brightness);
virtual DisplayError GetPanelBrightness(float *brightness);
+ virtual DisplayError GetPanelMaxBrightness(uint32_t *max_brightness_level);
virtual DisplayError GetRefreshRate(uint32_t *refresh_rate);
virtual DisplayError HandleSecureEvent(SecureEvent secure_event, LayerStack *layer_stack);
virtual DisplayError SetDisplayDppsAdROI(void *payload);
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index 8929fc9..761a016 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -105,6 +105,7 @@
using sde_drm::DRMSecurityLevel;
using sde_drm::DRMCscType;
using sde_drm::DRMMultiRectMode;
+using sde_drm::DRMSSPPLayoutIndex;
namespace sdm {
@@ -617,7 +618,8 @@
display_attributes_[index].is_device_split =
(topology == DRMTopology::DUAL_LM || topology == DRMTopology::DUAL_LM_MERGE ||
topology == DRMTopology::DUAL_LM_MERGE_DSC || topology == DRMTopology::DUAL_LM_DSC ||
- topology == DRMTopology::DUAL_LM_DSCMERGE);
+ topology == DRMTopology::DUAL_LM_DSCMERGE || topology == DRMTopology::QUAD_LM_MERGE ||
+ topology == DRMTopology::QUAD_LM_DSCMERGE || topology == DRMTopology::QUAD_LM_MERGE_DSC);
display_attributes_[index].clock_khz = mode.clock;
// If driver doesn't return panel width/height information, default to 320 dpi
@@ -632,14 +634,15 @@
SetTopology(topology, &display_attributes_[index].topology);
DLOGI("Display attributes[%d]: WxH: %dx%d, DPI: %fx%f, FPS: %d, LM_SPLIT: %d, V_BACK_PORCH: %d," \
- " V_FRONT_PORCH: %d, V_PULSE_WIDTH: %d, V_TOTAL: %d, H_TOTAL: %d, CLK: %dKHZ, TOPOLOGY: %d",
- index, display_attributes_[index].x_pixels, display_attributes_[index].y_pixels,
- display_attributes_[index].x_dpi, display_attributes_[index].y_dpi,
- display_attributes_[index].fps, display_attributes_[index].is_device_split,
- display_attributes_[index].v_back_porch, display_attributes_[index].v_front_porch,
- display_attributes_[index].v_pulse_width, display_attributes_[index].v_total,
- display_attributes_[index].h_total, display_attributes_[index].clock_khz,
- display_attributes_[index].topology);
+ " V_FRONT_PORCH: %d, V_PULSE_WIDTH: %d, V_TOTAL: %d, H_TOTAL: %d, CLK: %dKHZ," \
+ " TOPOLOGY: %d, HW_SPLIT: %d", index, display_attributes_[index].x_pixels,
+ display_attributes_[index].y_pixels, display_attributes_[index].x_dpi,
+ display_attributes_[index].y_dpi, display_attributes_[index].fps,
+ display_attributes_[index].is_device_split, display_attributes_[index].v_back_porch,
+ display_attributes_[index].v_front_porch, display_attributes_[index].v_pulse_width,
+ display_attributes_[index].v_total, display_attributes_[index].h_total,
+ display_attributes_[index].clock_khz, display_attributes_[index].topology,
+ mixer_attributes_.split_type);
return kErrorNone;
}
@@ -1155,8 +1158,34 @@
DRMRect dst = {};
SetRect(pipe_info->dst_roi, &dst);
+ LayerRect right_mixer = {FLOAT(mixer_attributes_.split_left), 0,
+ FLOAT(mixer_attributes_.width), FLOAT(mixer_attributes_.height)};
+ LayerRect dst_roi = pipe_info->dst_roi;
+
+ // For larget displays ie; 2 * 2k * 2k * 90 fps 4 LM's get programmed.
+ // Each pair of LM's drive independent displays.
+ // Layout Index indicates the panel onto which pipe gets staged.
+ DRMSSPPLayoutIndex layout_index = DRMSSPPLayoutIndex::NONE;
+ if (mixer_attributes_.split_type == kQuadSplit) {
+ layout_index = DRMSSPPLayoutIndex::LEFT;
+ if (IsValid(Intersection(dst_roi, right_mixer))) {
+ dst_roi = Reposition(dst_roi, -INT(mixer_attributes_.split_left), 0);
+ layout_index = DRMSSPPLayoutIndex::RIGHT;
+ DLOGV_IF(kTagDriverConfig, "Layer index = %d sspp layout = RIGHT", i);
+ DLOGV_IF(kTagDriverConfig, "Right dst_roi l = %f t = %f r = %f b = %f",
+ dst_roi.left, dst_roi.top, dst_roi.right, dst_roi.bottom);
+ } else {
+ DLOGV_IF(kTagDriverConfig, "Layer index = %d sspp layout = LEFT", i);
+ DLOGV_IF(kTagDriverConfig, "Left dst_roi l = %f t = %f r = %f b = %f",
+ dst_roi.left, dst_roi.top, dst_roi.right, dst_roi.bottom);
+ }
+ }
+ SetRect(dst_roi, &dst);
drm_atomic_intf_->Perform(DRMOps::PLANE_SET_DST_RECT, pipe_id, dst);
+ // Update Layout index.
+ drm_atomic_intf_->Perform(DRMOps::PLANE_SET_SSPP_LAYOUT, pipe_id, layout_index);
+
DRMRect excl = {};
SetRect(pipe_info->excl_rect, &excl);
drm_atomic_intf_->Perform(DRMOps::PLANE_SET_EXCL_RECT, pipe_id, excl);
@@ -1218,15 +1247,16 @@
SetSolidfillStages();
SetQOSData(qos_data);
drm_atomic_intf_->Perform(DRMOps::CRTC_SET_SECURITY_LEVEL, token_.crtc_id, crtc_security_level);
- if (hw_layers->hw_avr_info.update) {
- sde_drm::DRMQsyncMode mode = sde_drm::DRMQsyncMode::NONE;
- if (hw_layers->hw_avr_info.mode == kContinuousMode) {
- mode = sde_drm::DRMQsyncMode::CONTINUOUS;
- } else if (hw_layers->hw_avr_info.mode == kOneShotMode) {
- mode = sde_drm::DRMQsyncMode::ONESHOT;
- }
- drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_QSYNC_MODE, token_.conn_id, mode);
+ }
+
+ if (hw_layers->hw_avr_info.update) {
+ sde_drm::DRMQsyncMode mode = sde_drm::DRMQsyncMode::NONE;
+ if (hw_layers->hw_avr_info.mode == kContinuousMode) {
+ mode = sde_drm::DRMQsyncMode::CONTINUOUS;
+ } else if (hw_layers->hw_avr_info.mode == kOneShotMode) {
+ mode = sde_drm::DRMQsyncMode::ONESHOT;
}
+ drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_QSYNC_MODE, token_.conn_id, mode);
}
drm_atomic_intf_->Perform(DRMOps::DPPS_COMMIT_FEATURE, 0 /* argument is not used */);
@@ -1868,8 +1898,15 @@
mixer_attributes_ = mixer_attributes;
mixer_attributes_.split_left = mixer_attributes_.width;
+ mixer_attributes_.split_type = kNoSplit;
if (display_attributes_[index].is_device_split) {
mixer_attributes_.split_left = UINT32(FLOAT(mixer_attributes.width) * mixer_split_ratio);
+ mixer_attributes_.split_type = kDualSplit;
+ if (display_attributes_[index].topology == kQuadLMMerge ||
+ display_attributes_[index].topology == kQuadLMDSCMerge ||
+ display_attributes_[index].topology == kQuadLMMergeDSC) {
+ mixer_attributes_.split_type = kQuadSplit;
+ }
}
return kErrorNone;
@@ -1955,7 +1992,18 @@
mixer_attributes_.split_left = display_attributes_[index].is_device_split
? hw_panel_info_.split_info.left_split
: mixer_attributes_.width;
- DLOGI("Mixer WxH %dx%d for %s", mixer_attributes_.width, mixer_attributes_.height, device_name_);
+ mixer_attributes_.split_type = kNoSplit;
+ if (display_attributes_[index].is_device_split) {
+ mixer_attributes_.split_type = kDualSplit;
+ if (display_attributes_[index].topology == kQuadLMMerge ||
+ display_attributes_[index].topology == kQuadLMDSCMerge ||
+ display_attributes_[index].topology == kQuadLMMergeDSC) {
+ mixer_attributes_.split_type = kQuadSplit;
+ }
+ }
+
+ DLOGI("Mixer WxH %dx%d-%d for %s", mixer_attributes_.width, mixer_attributes_.height,
+ mixer_attributes_.split_type, device_name_);
update_mode_ = true;
}
@@ -1994,6 +2042,9 @@
case DRMTopology::DUAL_LM_MERGE: *hw_topology = kDualLMMerge; break;
case DRMTopology::DUAL_LM_MERGE_DSC: *hw_topology = kDualLMMergeDSC; break;
case DRMTopology::DUAL_LM_DSCMERGE: *hw_topology = kDualLMDSCMerge; break;
+ case DRMTopology::QUAD_LM_MERGE: *hw_topology = kQuadLMMerge; break;
+ case DRMTopology::QUAD_LM_DSCMERGE: *hw_topology = kQuadLMDSCMerge; break;
+ case DRMTopology::QUAD_LM_MERGE_DSC: *hw_topology = kQuadLMMergeDSC; break;
case DRMTopology::PPSPLIT: *hw_topology = kPPSplit; break;
default: *hw_topology = kUnknown; break;
}
diff --git a/sdm/libs/core/drm/hw_events_drm.cpp b/sdm/libs/core/drm/hw_events_drm.cpp
index 25bad21..16a7249 100644
--- a/sdm/libs/core/drm/hw_events_drm.cpp
+++ b/sdm/libs/core/drm/hw_events_drm.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -332,6 +332,11 @@
prctl(PR_SET_NAME, event_thread_name_.c_str(), 0, 0, 0);
setpriority(PRIO_PROCESS, 0, kThreadPriorityUrgent);
+ // Real Time task with lowest priority.
+ struct sched_param param = {0};
+ param.sched_priority = sched_get_priority_min(SCHED_FIFO);
+ sched_setscheduler(0, SCHED_FIFO, ¶m);
+
while (!exit_threads_) {
int error = Sys::poll_(poll_fds_.data(), UINT32(poll_fds_.size()), -1);
if (error <= 0) {
diff --git a/sdm/libs/core/drm/hw_info_drm.cpp b/sdm/libs/core/drm/hw_info_drm.cpp
index eaa065c..44fddcb 100644
--- a/sdm/libs/core/drm/hw_info_drm.cpp
+++ b/sdm/libs/core/drm/hw_info_drm.cpp
@@ -336,6 +336,9 @@
width_constraints.push_back(std::make_pair(kPipeScalingLimit, info.scaling_limit_index));
width_constraints.push_back(std::make_pair(kPipeRotationLimit, info.rotation_limit_index));
}
+ // In case driver doesn't report bus width default to 256 bit bus.
+ hw_resource->num_mnocports = info.num_mnocports ? info.num_mnocports : 2;
+ hw_resource->mnoc_bus_width = info.mnoc_bus_width ? info.mnoc_bus_width : 32;
}
void HWInfoDRM::GetHWPlanesInfo(HWResourceInfo *hw_resource) {
diff --git a/sdm/libs/core/fb/hw_info.cpp b/sdm/libs/core/fb/hw_info.cpp
index b076aad..fef95fd 100644
--- a/sdm/libs/core/fb/hw_info.cpp
+++ b/sdm/libs/core/fb/hw_info.cpp
@@ -126,7 +126,7 @@
if (!strncmp(tokens[j], "fmts_supported", strlen("fmts_supported"))) {
char *tokens_fmt[max_count] = { NULL };
// uint32_t token_fmt_count = 0;
- if (tokens_fmt == NULL) {}
+ if (&tokens_fmt[0] == NULL) {}
}
}
hw_resource_->hw_pipes.push_back(pipe_caps);
diff --git a/sdm/libs/core/resource_default.cpp b/sdm/libs/core/resource_default.cpp
index 7686caa..a66a003 100644
--- a/sdm/libs/core/resource_default.cpp
+++ b/sdm/libs/core/resource_default.cpp
@@ -195,8 +195,6 @@
const HWDisplayAttributes &display_attributes,
const HWPanelInfo &hw_panel_info,
const HWMixerAttributes &mixer_attributes) {
- SCOPE_LOCK(locker_);
-
DisplayResourceContext *display_resource_ctx =
reinterpret_cast<DisplayResourceContext *>(display_ctx);
@@ -207,14 +205,10 @@
}
DisplayError ResourceDefault::Start(Handle display_ctx) {
- locker_.Lock();
-
return kErrorNone;
}
DisplayError ResourceDefault::Stop(Handle display_ctx, HWLayers *hw_layers) {
- locker_.Unlock();
-
return kErrorNone;
}
@@ -323,19 +317,14 @@
}
DisplayError ResourceDefault::PostPrepare(Handle display_ctx, HWLayers *hw_layers) {
- SCOPE_LOCK(locker_);
-
return kErrorNone;
}
DisplayError ResourceDefault::Commit(Handle display_ctx, HWLayers *hw_layers) {
- SCOPE_LOCK(locker_);
-
return kErrorNone;
}
DisplayError ResourceDefault::PostCommit(Handle display_ctx, HWLayers *hw_layers) {
- SCOPE_LOCK(locker_);
DisplayResourceContext *display_resource_ctx =
reinterpret_cast<DisplayResourceContext *>(display_ctx);
HWBlockType hw_block_type = display_resource_ctx->hw_block_type;
@@ -363,8 +352,6 @@
}
void ResourceDefault::Purge(Handle display_ctx) {
- SCOPE_LOCK(locker_);
-
DisplayResourceContext *display_resource_ctx =
reinterpret_cast<DisplayResourceContext *>(display_ctx);
HWBlockType hw_block_type = display_resource_ctx->hw_block_type;
@@ -378,8 +365,6 @@
}
DisplayError ResourceDefault::SetMaxMixerStages(Handle display_ctx, uint32_t max_mixer_stages) {
- SCOPE_LOCK(locker_);
-
return kErrorNone;
}
diff --git a/sdm/libs/core/resource_default.h b/sdm/libs/core/resource_default.h
index ead2ae6..6a2c90c 100644
--- a/sdm/libs/core/resource_default.h
+++ b/sdm/libs/core/resource_default.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014 - 2018, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2019, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
@@ -67,6 +67,7 @@
const DisplayDetailEnhancerData &de_data);
virtual DisplayError Perform(int cmd, ...) { return kErrorNone; }
DisplayError SetDisplayState(int32_t display_id, DisplayState state) { return kErrorNone; }
+ virtual bool IsRotatorSupportedFormat(LayerBufferFormat format) { return false; }
private:
enum PipeOwner {
@@ -143,7 +144,6 @@
DisplayError CalculateDecimation(float downscale, uint8_t *decimation);
DisplayError GetScaleLutConfig(HWScaleLutInfo *lut_info);
- Locker locker_;
HWResourceInfo hw_res_info_;
HWBlockContext hw_block_ctx_[kHWBlockMax];
std::vector<SourcePipe> src_pipes_;
diff --git a/sdm/libs/core/strategy.cpp b/sdm/libs/core/strategy.cpp
index 7c3f033..c6e0448 100644
--- a/sdm/libs/core/strategy.cpp
+++ b/sdm/libs/core/strategy.cpp
@@ -33,7 +33,9 @@
namespace sdm {
-Strategy::Strategy(ExtensionInterface *extension_intf, BufferAllocator *buffer_allocator,
+Strategy::Strategy(ExtensionInterface *extension_intf,
+ BufferAllocator *buffer_allocator,
+ BufferSyncHandler *buffer_sync_handler,
int32_t display_id, DisplayType type, const HWResourceInfo &hw_resource_info,
const HWPanelInfo &hw_panel_info, const HWMixerAttributes &mixer_attributes,
const HWDisplayAttributes &display_attributes,
@@ -46,14 +48,15 @@
mixer_attributes_(mixer_attributes),
display_attributes_(display_attributes),
fb_config_(fb_config),
- buffer_allocator_(buffer_allocator) {}
+ buffer_allocator_(buffer_allocator),
+ sync_handler_(buffer_sync_handler) {}
DisplayError Strategy::Init() {
DisplayError error = kErrorNone;
if (extension_intf_) {
error = extension_intf_->CreateStrategyExtn(display_id_, display_type_, buffer_allocator_,
- hw_resource_info_, hw_panel_info_,
+ sync_handler_, hw_resource_info_, hw_panel_info_,
mixer_attributes_, fb_config_, &strategy_intf_);
if (error != kErrorNone) {
DLOGE("Failed to create strategy");
diff --git a/sdm/libs/core/strategy.h b/sdm/libs/core/strategy.h
index f4dbcfe..ecc6810 100644
--- a/sdm/libs/core/strategy.h
+++ b/sdm/libs/core/strategy.h
@@ -35,6 +35,7 @@
class Strategy {
public:
Strategy(ExtensionInterface *extension_intf, BufferAllocator *buffer_allocator,
+ BufferSyncHandler *buffer_sync_handler,
int32_t display_id, DisplayType type, const HWResourceInfo &hw_resource_info,
const HWPanelInfo &hw_panel_info, const HWMixerAttributes &mixer_attributes,
const HWDisplayAttributes &display_attributes,
@@ -75,6 +76,7 @@
bool extn_start_success_ = false;
bool disable_gpu_comp_ = false;
BufferAllocator *buffer_allocator_ = NULL;
+ BufferSyncHandler *sync_handler_ = NULL;
};
} // namespace sdm
diff --git a/sdm/libs/utils/Android.mk b/sdm/libs/utils/Android.mk
index f4b09c6..c474193 100644
--- a/sdm/libs/utils/Android.mk
+++ b/sdm/libs/utils/Android.mk
@@ -12,6 +12,7 @@
LOCAL_SRC_FILES := debug.cpp \
rect.cpp \
sys.cpp \
+ fence.cpp \
formats.cpp \
utils.cpp
@@ -30,6 +31,7 @@
$(SDM_HEADER_PATH)/utils/sys.h \
$(SDM_HEADER_PATH)/utils/sync_task.h \
$(SDM_HEADER_PATH)/utils/utils.h \
+ $(SDM_HEADER_PATH)/utils/fence.h \
$(SDM_HEADER_PATH)/utils/factory.h
include $(BUILD_COPY_HEADERS)
diff --git a/sdm/libs/utils/fence.cpp b/sdm/libs/utils/fence.cpp
new file mode 100644
index 0000000..3cf26e4
--- /dev/null
+++ b/sdm/libs/utils/fence.cpp
@@ -0,0 +1,110 @@
+/*
+* Copyright (c) 2019, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <utils/fence.h>
+#include <string>
+
+#define __CLASS__ "Fence"
+
+namespace sdm {
+
+BufferSyncHandler* Fence::buffer_sync_handler_ = nullptr;
+
+Fence::Fence(int fd) : fd_(fd) {
+}
+
+Fence::~Fence() {
+ close(fd_);
+}
+
+void Fence::Set(BufferSyncHandler *buffer_sync_handler) {
+ buffer_sync_handler_ = buffer_sync_handler;
+}
+
+shared_ptr<Fence> Fence::Create(int fd) {
+ // Do not create Fence object for invalid fd, so that nullptr can be used for invalid fences.
+ if (fd < 0) {
+ return nullptr;
+ }
+
+ shared_ptr<Fence> fence(new Fence(fd));
+ if (!fence) {
+ close(fd);
+ }
+
+ return fence;
+}
+
+int Fence::Dup(const shared_ptr<Fence> &fence) {
+ if (!fence) {
+ return -1;
+ }
+
+ return dup(fence->fd_);
+}
+
+shared_ptr<Fence> Fence::Merge(const shared_ptr<Fence> &fence1, const shared_ptr<Fence> &fence2) {
+ if (!buffer_sync_handler_) {
+ return nullptr;
+ }
+
+ int fd1 = fence1 ? fence1->fd_ : -1;
+ int fd2 = fence2 ? fence2->fd_ : -1;
+ int merged = -1;
+
+ buffer_sync_handler_->SyncMerge(fd1, fd2, &merged);
+
+ return Create(merged);
+}
+
+DisplayError Fence::Wait(const shared_ptr<Fence> &fence) {
+ if (!buffer_sync_handler_) {
+ return kErrorUndefined;
+ }
+
+ return buffer_sync_handler_->SyncWait(Fence::Get(fence));
+}
+
+DisplayError Fence::Wait(const shared_ptr<Fence> &fence, int timeout) {
+ if (!buffer_sync_handler_) {
+ return kErrorUndefined;
+ }
+
+ return buffer_sync_handler_->SyncWait(Fence::Get(fence), timeout);
+}
+
+string Fence::GetStr(const shared_ptr<Fence> &fence) {
+ return std::to_string(Fence::Get(fence));
+}
+
+int Fence::Get(const shared_ptr<Fence> &fence) {
+ return (fence ? fence->fd_ : -1);
+}
+
+} // namespace sdm