Merge "sdm: Reject bit clk updates in inactive state."
diff --git a/composer/Android.mk b/composer/Android.mk
index 306a03a..f4ddbe5 100644
--- a/composer/Android.mk
+++ b/composer/Android.mk
@@ -25,6 +25,7 @@
libsdmcore libqservice libqdutils libqdMetaData \
libdisplaydebug libsdmutils libgrallocutils libui \
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 \
@@ -68,7 +69,13 @@
hwc_tonemapper.cpp \
display_null.cpp \
hwc_socket_handler.cpp \
- hwc_buffer_allocator.cpp
+ hwc_buffer_allocator.cpp \
+ hwc_display_virtual_factory.cpp \
+ hwc_display_virtual_dpu.cpp \
+ hwc_display_virtual_gpu.cpp \
+ gl_common.cpp \
+ gl_color_convert.cpp \
+ gl_color_convert_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/gl_color_convert.cpp b/composer/gl_color_convert.cpp
new file mode 100644
index 0000000..03f7377
--- /dev/null
+++ b/composer/gl_color_convert.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_color_convert_impl.h"
+#include "gl_color_convert.h"
+
+#define __CLASS__ "GLColorConvert"
+
+namespace sdm {
+
+GLColorConvert* GLColorConvert::GetInstance(GLRenderTarget target, bool 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;
+ }
+
+ int status = color_convert->Init();
+ if (status != 0) {
+ DLOGE("Failed to initialize GL Color convert instance %d", status);
+ delete color_convert;
+ return nullptr;
+ }
+
+ DLOGI("Created instance successfully");
+
+ return color_convert;
+}
+
+void GLColorConvert::Destroy(GLColorConvert* intf) {
+ GLColorConvertImpl* color_convert = static_cast<GLColorConvertImpl*>(intf);
+ if (color_convert->Deinit() != 0) {
+ DLOGE("De Init failed");
+ }
+
+ delete color_convert;
+}
+
+} // namespace sdm
diff --git a/composer/gl_color_convert.h b/composer/gl_color_convert.h
new file mode 100644
index 0000000..2080a97
--- /dev/null
+++ b/composer/gl_color_convert.h
@@ -0,0 +1,63 @@
+/*
+ * 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_COLOR_CONVERT_H__
+#define __GL_COLOR_CONVERT_H__
+
+#include <gralloc_priv.h>
+
+namespace sdm {
+
+enum GLRenderTarget {
+ kTargetRGBA,
+ 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);
+ static void Destroy(GLColorConvert* 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 ~GLColorConvert() { }
+};
+
+} // namespace sdm
+
+#endif // __GL_COLOR_CONVERT_H__
diff --git a/composer/gl_color_convert_impl.cpp b/composer/gl_color_convert_impl.cpp
new file mode 100644
index 0000000..fb5d060
--- /dev/null
+++ b/composer/gl_color_convert_impl.cpp
@@ -0,0 +1,203 @@
+/*
+ * 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_color_convert_impl.h"
+
+#define __CLASS__ "GLColorConvertImpl"
+
+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* kVertexShader = ""
+ "#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* kConvertRgbToYuvShader = ""
+ "#extension GL_EXT_YUV_target : require \n"
+ "precision highp float; \n"
+ " \n"
+ "layout(binding = 0) uniform sampler2D u_sTexture; \n"
+ " \n"
+ "in vec2 uv; \n"
+ "layout (yuv) out vec4 color; \n"
+ " \n"
+ "void main() \n"
+ "{ \n"
+ " vec3 rgbColor = texture(u_sTexture, uv).rgb; \n"
+ " color = vec4(rgb_2_yuv(rgbColor, itu_601_full_range), 1.0); \n"
+ "} \n";
+
+int GLColorConvertImpl::CreateContext(GLRenderTarget target, bool secure) {
+ if (target != kTargetRGBA && target != kTargetYUV) {
+ DLOGE("Invalid GLRenderTarget: %d", target);
+ return -1;
+ }
+
+ 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;
+ if (target == kTargetRGBA) {
+ 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));
+ } else {
+ EGLint eglConfigAttribList[] = {EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_COLOR_BUFFER_TYPE, EGL_YUV_BUFFER_EXT,
+ EGL_YUV_ORDER_EXT, EGL_YUV_ORDER_YUV_EXT,
+ EGL_YUV_NUMBER_OF_PLANES_EXT, 2,
+ EGL_YUV_SUBSAMPLE_EXT, EGL_YUV_SUBSAMPLE_4_2_0_EXT,
+ EGL_YUV_DEPTH_RANGE_EXT, EGL_YUV_DEPTH_RANGE_LIMITED_EXT,
+ EGL_YUV_CSC_STANDARD_EXT, EGL_YUV_CSC_STANDARD_601_EXT,
+ EGL_YUV_PLANE_BPP_EXT, EGL_YUV_PLANE_BPP_8_EXT,
+ 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++] = kConvertRgbToYuvShader;
+
+ ctx_.program_id = LoadProgram(1, &kVertexShader, count, fragment_shaders);
+
+ return 0;
+}
+
+int GLColorConvertImpl::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);
+
+ 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 GLColorConvertImpl::Init() {
+ return CreateContext(target_, secure_);
+}
+
+int GLColorConvertImpl::Deinit() {
+ MakeCurrent(&ctx_);
+ DestroyContext(&ctx_);
+
+ return 0;
+}
+
+GLColorConvertImpl::~GLColorConvertImpl() {}
+
+GLColorConvertImpl::GLColorConvertImpl(GLRenderTarget target, bool secure) {
+ target_ = target;
+ secure_ = secure;
+}
+
+} // namespace sdm
+
diff --git a/composer/gl_color_convert_impl.h b/composer/gl_color_convert_impl.h
new file mode 100644
index 0000000..d684f92
--- /dev/null
+++ b/composer/gl_color_convert_impl.h
@@ -0,0 +1,58 @@
+/*
+ * 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_COLOR_CONVERT_IMPL_H__
+#define __GL_COLOR_CONVERT_IMPL_H__
+
+#include <sync/sync.h>
+
+#include "gl_color_convert.h"
+#include "gl_common.h"
+
+namespace sdm {
+
+class GLColorConvertImpl : public GLColorConvert, public GLCommon {
+ public:
+ GLColorConvertImpl(GLRenderTarget target, bool secure);
+ virtual ~GLColorConvertImpl();
+ 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(GLRenderTarget target, bool secure);
+ virtual int Init();
+ virtual int Deinit();
+ private:
+ GLRenderTarget target_ = kTargetRGBA;
+ bool secure_ = false;
+ GLContext ctx_;
+};
+
+} // namespace sdm
+
+#endif // __GL_COLOR_CONVERT_IMPL_H__
diff --git a/composer/gl_common.cpp b/composer/gl_common.cpp
new file mode 100644
index 0000000..d45b5d9
--- /dev/null
+++ b/composer/gl_common.cpp
@@ -0,0 +1,158 @@
+/*
+ * 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_common.h"
+
+#define __CLASS__ "GLCommon"
+
+namespace sdm {
+
+GLuint GLCommon::LoadProgram(int vertex_entries, const char **vertex, int fragment_entries,
+ const char **fragment) {
+ GLuint prog_id = glCreateProgram();
+
+ int vert_id = glCreateShader(GL_VERTEX_SHADER);
+ int frag_id = glCreateShader(GL_FRAGMENT_SHADER);
+
+ GL(glShaderSource(vert_id, vertex_entries, vertex, 0));
+ GL(glCompileShader(vert_id));
+ DumpShaderLog(vert_id);
+
+ GL(glShaderSource(frag_id, fragment_entries, fragment, 0));
+ GL(glCompileShader(frag_id));
+ DumpShaderLog(frag_id);
+
+ GL(glAttachShader(prog_id, vert_id));
+ GL(glAttachShader(prog_id, frag_id));
+
+ GL(glLinkProgram(prog_id));
+
+ GL(glDetachShader(prog_id, vert_id));
+ GL(glDetachShader(prog_id, frag_id));
+
+ GL(glDeleteShader(vert_id));
+ GL(glDeleteShader(frag_id));
+
+ return prog_id;
+}
+
+void GLCommon::DumpShaderLog(int shader) {
+ int success = 0;
+ GLchar infoLog[512];
+ GL(glGetShaderiv(shader, GL_COMPILE_STATUS, &success));
+ if (!success) {
+ glGetShaderInfoLog(shader, 512, NULL, infoLog);
+ DLOGI("Shader Failed to compile: %s\n", infoLog);
+ }
+}
+
+void GLCommon::MakeCurrent(const GLContext* ctx) {
+ DTRACE_SCOPED();
+ EGL(eglMakeCurrent(ctx->egl_display, ctx->egl_surface, ctx->egl_surface, ctx->egl_context));
+}
+
+void GLCommon::SetProgram(uint32_t id) {
+ DTRACE_SCOPED();
+ GL(glUseProgram(id));
+}
+
+void GLCommon::DeleteProgram(uint32_t id) {
+ DTRACE_SCOPED();
+ GL(glDeleteProgram(id));
+}
+
+void GLCommon::SetSourceBuffer(const private_handle_t *src_hnd) {
+ DTRACE_SCOPED();
+ EGLImageBuffer *src_buffer = image_wrapper_.wrap(reinterpret_cast<const void *>(src_hnd));
+
+ GL(glActiveTexture(GL_TEXTURE0));
+ if (src_buffer) {
+ GL(glBindTexture(GL_TEXTURE_2D, src_buffer->getTexture(GL_TEXTURE_2D)));
+ }
+}
+
+void GLCommon::SetDestinationBuffer(const private_handle_t *dst_hnd) {
+ 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()));
+ }
+}
+
+int GLCommon::WaitOnInputFence(const 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,
+ attribs);
+
+ if (sync == EGL_NO_SYNC_KHR) {
+ DLOGE("Failed to create sync from source fd: %d", in_fence_fd);
+ return -1;
+ } else {
+ EGL(eglWaitSyncKHR(eglGetCurrentDisplay(), sync, 0));
+ EGL(eglDestroySyncKHR(eglGetCurrentDisplay(), sync));
+ }
+
+ return 0;
+}
+
+int GLCommon::CreateOutputFence() {
+ DTRACE_SCOPED();
+ int fd = -1;
+ EGLSyncKHR sync = eglCreateSyncKHR(eglGetCurrentDisplay(), EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
+
+ // Swap buffer.
+ GL(glFlush());
+
+ if (sync == EGL_NO_SYNC_KHR) {
+ DLOGE("Failed to create egl sync fence");
+ } else {
+ fd = eglDupNativeFenceFDANDROID(eglGetCurrentDisplay(), sync);
+ if (fd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
+ DLOGE("Failed to dup sync");
+ }
+ EGL(eglDestroySyncKHR(eglGetCurrentDisplay(), sync));
+ }
+
+ return fd;
+}
+
+void GLCommon::DestroyContext(const GLContext* ctx) {
+ DTRACE_SCOPED();
+ 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));
+}
+
+} // namespace sdm
+
diff --git a/composer/gl_common.h b/composer/gl_common.h
new file mode 100644
index 0000000..4089e87
--- /dev/null
+++ b/composer/gl_common.h
@@ -0,0 +1,70 @@
+/*
+ * 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_COMMON_H__
+#define __GL_COMMON_H__
+
+#include <utils/debug.h>
+
+#include "glengine.h"
+#include "EGLImageWrapper.h"
+
+namespace sdm {
+
+struct GLContext {
+ EGLDisplay egl_display = EGL_NO_DISPLAY;
+ EGLContext egl_context = EGL_NO_CONTEXT;
+ EGLSurface egl_surface = EGL_NO_SURFACE;
+ uint32_t program_id = 0;
+};
+
+class GLCommon {
+ public:
+ virtual GLuint LoadProgram(int vertex_entries, const char **vertex, int fragment_entries,
+ const char **fragment);
+ 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 SetSourceBuffer(const private_handle_t *src_hnd);
+ virtual void DestroyContext(const GLContext *ctx);
+ virtual void DeleteProgram(uint32_t id);
+ virtual int WaitOnInputFence(const int in_fence_fd);
+ virtual int CreateOutputFence();
+
+ protected:
+ virtual ~GLCommon() { }
+
+ private:
+ EGLImageWrapper image_wrapper_;
+};
+
+} // namespace sdm
+
+#endif // __GL_COMMON_H__
diff --git a/composer/hwc_display.h b/composer/hwc_display.h
index 8fea114..bca6f5a 100644
--- a/composer/hwc_display.h
+++ b/composer/hwc_display.h
@@ -458,6 +458,7 @@
std::vector<uint32_t> hwc_config_map_;
bool client_connected_ = true;
bool pending_config_ = false;
+ bool has_client_composition_ = false;
private:
void DumpInputBuffers(void);
@@ -470,7 +471,6 @@
uint32_t geometry_changes_ = GeometryChanges::kNone;
bool animating_ = false;
int null_display_mode_ = 0;
- bool has_client_composition_ = false;
DisplayValidateState validate_state_ = kNormalValidate;
bool fast_path_enabled_ = true;
bool first_cycle_ = true; // false if a display commit has succeeded on the device.
diff --git a/composer/hwc_display_virtual.cpp b/composer/hwc_display_virtual.cpp
index 470d7d2..b2eedc3 100644
--- a/composer/hwc_display_virtual.cpp
+++ b/composer/hwc_display_virtual.cpp
@@ -39,142 +39,45 @@
namespace sdm {
-int HWCDisplayVirtual::Create(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
- HWCCallbacks *callbacks, hwc2_display_t id, int32_t sdm_id,
- uint32_t width, uint32_t height, int32_t *format,
- HWCDisplay **hwc_display, float min_lum, float max_lum) {
- int status = 0;
- HWCDisplayVirtual *hwc_display_virtual = new HWCDisplayVirtual(core_intf, buffer_allocator,
- callbacks, id, sdm_id);
-
- // TODO(user): Populate format correctly
- DLOGI("Creating virtual display: w: %d h:%d format:0x%x", width, height, *format);
-
- status = hwc_display_virtual->Init();
- if (status) {
- DLOGW("Failed to initialize virtual display");
- delete hwc_display_virtual;
- return status;
- }
-
- if (max_lum != -1.0 || min_lum != -1.0) {
- hwc_display_virtual->SetPanelLuminanceAttributes(min_lum, max_lum);
- }
-
- status = hwc_display_virtual->SetConfig(width, height);
- if (status) {
- Destroy(hwc_display_virtual);
- return status;
- }
-
- status = INT32(hwc_display_virtual->SetPowerMode(HWC2::PowerMode::On, false /* teardown */));
- if (status) {
- DLOGW("Failed to set power mode on virtual display");
- Destroy(hwc_display_virtual);
- return status;
- }
-
- // TODO(user): Validate that we support this width/height
- status = hwc_display_virtual->SetFrameBufferResolution(width, height);
-
- if (status) {
- DLOGW("Failed to set virtual display FB resolution");
- Destroy(hwc_display_virtual);
- return status;
- }
-
- *hwc_display = static_cast<HWCDisplay *>(hwc_display_virtual);
-
- return 0;
-}
-
void HWCDisplayVirtual::Destroy(HWCDisplay *hwc_display) {
hwc_display->Deinit();
delete hwc_display;
}
HWCDisplayVirtual::HWCDisplayVirtual(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
- HWCCallbacks *callbacks, hwc2_display_t id, int32_t sdm_id) :
+ HWCCallbacks *callbacks, hwc2_display_t id, int32_t sdm_id,
+ uint32_t width, uint32_t height) :
HWCDisplay(core_intf, buffer_allocator, callbacks, nullptr, nullptr, kVirtual, id, sdm_id,
- DISPLAY_CLASS_VIRTUAL) {
+ DISPLAY_CLASS_VIRTUAL), width_(width), height_(height) {
}
int HWCDisplayVirtual::Init() {
- output_buffer_ = new LayerBuffer();
flush_on_error_ = true;
- return HWCDisplay::Init();
+ return 0;
}
int HWCDisplayVirtual::Deinit() {
- int status = 0;
- if (output_buffer_) {
- if (output_buffer_->acquire_fence_fd >= 0) {
- close(output_buffer_->acquire_fence_fd);
- }
- delete output_buffer_;
- output_buffer_ = nullptr;
+ if (output_buffer_.acquire_fence_fd >= 0) {
+ close(output_buffer_.acquire_fence_fd);
}
- status = HWCDisplay::Deinit();
- return status;
+ return HWCDisplay::Deinit();
}
-HWC2::Error HWCDisplayVirtual::Validate(uint32_t *out_num_types, uint32_t *out_num_requests) {
- auto status = HWC2::Error::None;
-
- if (display_paused_ || active_secure_sessions_.any()) {
- MarkLayersForGPUBypass();
- return status;
- }
-
- BuildLayerStack();
- layer_stack_.output_buffer = output_buffer_;
- // If Output buffer of Virtual Display is not secure, set SKIP flag on the secure layers.
- if (output_buffer_ && !output_buffer_->flags.secure && layer_stack_.flags.secure_present) {
- for (auto hwc_layer : layer_set_) {
- Layer *layer = hwc_layer->GetSDMLayer();
- if (layer->input_buffer.flags.secure) {
- layer_stack_.flags.skip_present = true;
- layer->flags.skip = true;
- }
- }
- }
-
- if (layer_set_.empty()) {
- DLOGI("Skipping Validate and Commit");
- return status;
- }
- status = PrepareLayerStack(out_num_types, out_num_requests);
- return status;
+bool HWCDisplayVirtual::NeedsGPUBypass() {
+ return display_paused_ || active_secure_sessions_.any() || layer_set_.empty();
}
HWC2::Error HWCDisplayVirtual::Present(int32_t *out_retire_fence) {
- auto status = HWC2::Error::None;
+ return HWC2::Error::None;
+}
- if (!output_buffer_->buffer_id) {
- return HWC2::Error::NoResources;
- }
-
- if (active_secure_sessions_.any()) {
- return status;
- }
-
- layer_stack_.output_buffer = output_buffer_;
- if (display_paused_) {
- validated_ = false;
- flush_ = true;
- }
-
- status = HWCDisplay::CommitLayerStack();
- if (status != HWC2::Error::None) {
- return status;
- }
-
+HWC2::Error HWCDisplayVirtual::DumpVDSBuffer() {
if (dump_frame_count_ && !flush_ && dump_output_layer_) {
if (output_handle_) {
BufferInfo buffer_info;
const private_handle_t *output_handle =
- reinterpret_cast<const private_handle_t *>(output_buffer_->buffer_id);
+ reinterpret_cast<const private_handle_t *>(output_buffer_.buffer_id);
DisplayError error = kErrorNone;
if (!output_handle->base) {
error = buffer_allocator_->MapBuffer(output_handle, -1);
@@ -200,30 +103,6 @@
}
}
- status = HWCDisplay::PostCommitLayerStack(out_retire_fence);
-
- return status;
-}
-
-int HWCDisplayVirtual::SetConfig(uint32_t width, uint32_t height) {
- DisplayConfigVariableInfo variable_info;
- variable_info.x_pixels = width;
- variable_info.y_pixels = height;
- // TODO(user): Need to get the framerate of primary display and update it.
- variable_info.fps = 60;
- DisplayError err = display_intf_->SetActiveConfig(&variable_info);
- if (err != kErrorNone) {
- return -EINVAL;
- }
- return 0;
-}
-
-
-HWC2::Error HWCDisplayVirtual::SetPanelLuminanceAttributes(float min_lum, float max_lum) {
- DisplayError err = display_intf_->SetPanelLuminanceAttributes(min_lum, max_lum);
- if (err != kErrorNone) {
- return HWC2::Error::BadParameter;
- }
return HWC2::Error::None;
}
@@ -235,10 +114,7 @@
if (output_handle) {
int output_handle_format = output_handle->format;
- int active_aligned_w, active_aligned_h;
- int new_width, new_height;
- int new_aligned_w, new_aligned_h;
- uint32_t active_width, active_height;
+ int aligned_w, aligned_h;
ColorMetaData color_metadata = {};
if (output_handle_format == HAL_PIXEL_FORMAT_RGBA_8888) {
@@ -255,54 +131,38 @@
return HWC2::Error::BadParameter;
}
- GetMixerResolution(&active_width, &active_height);
- buffer_allocator_->GetCustomWidthAndHeight(output_handle, &new_width, &new_height);
- buffer_allocator_->GetAlignedWidthAndHeight(INT(new_width), INT(new_height),
- output_handle_format, 0, &new_aligned_w,
- &new_aligned_h);
- buffer_allocator_->GetAlignedWidthAndHeight(INT(active_width), INT(active_height),
- output_handle_format, 0, &active_aligned_w,
- &active_aligned_h);
- if (new_aligned_w != active_aligned_w || new_aligned_h != active_aligned_h) {
- int status = SetConfig(UINT32(new_width), UINT32(new_height));
- if (status) {
- DLOGE("SetConfig failed custom WxH %dx%d", new_width, new_height);
- return HWC2::Error::BadParameter;
- }
- validated_ = false;
- }
-
- output_buffer_->width = UINT32(new_aligned_w);
- output_buffer_->height = UINT32(new_aligned_h);
- output_buffer_->unaligned_width = UINT32(new_width);
- output_buffer_->unaligned_height = UINT32(new_height);
- output_buffer_->flags.secure = 0;
- output_buffer_->flags.video = 0;
- output_buffer_->buffer_id = reinterpret_cast<uint64_t>(output_handle);
- output_buffer_->format = new_sdm_format;
- output_buffer_->color_metadata = color_metadata;
+ buffer_allocator_->GetCustomWidthAndHeight(output_handle, &aligned_w, &aligned_h);
+ output_buffer_.width = UINT32(width_);
+ output_buffer_.height = UINT32(height_);
+ output_buffer_.unaligned_width = UINT32(aligned_w);
+ output_buffer_.unaligned_height = UINT32(aligned_h);
+ output_buffer_.flags.secure = 0;
+ output_buffer_.flags.video = 0;
+ output_buffer_.buffer_id = reinterpret_cast<uint64_t>(output_handle);
+ output_buffer_.format = new_sdm_format;
+ output_buffer_.color_metadata = color_metadata;
output_handle_ = output_handle;
// TZ Protected Buffer - L1
if (output_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
- output_buffer_->flags.secure = 1;
+ output_buffer_.flags.secure = 1;
}
// ToDo: Need to extend for non-RGB formats
- output_buffer_->planes[0].fd = output_handle->fd;
- output_buffer_->planes[0].offset = output_handle->offset;
- output_buffer_->planes[0].stride = UINT32(output_handle->width);
+ output_buffer_.planes[0].fd = output_handle->fd;
+ output_buffer_.planes[0].offset = output_handle->offset;
+ output_buffer_.planes[0].stride = UINT32(output_handle->width);
}
// Close the previous acquire fence and update with the latest release fence to avoid fence leak
// in case if this function gets invoked multiple times from the client.
- if (output_buffer_->acquire_fence_fd >= 0) {
- close(output_buffer_->acquire_fence_fd);
+ if (output_buffer_.acquire_fence_fd >= 0) {
+ close(output_buffer_.acquire_fence_fd);
}
// Fill output buffer parameters (width, height, format, plane information, fence)
// release_fence will be closed by QtiComposerClient::CommandReader::parseSetOutputBuffer() if
// this::SetOutputBuffer() fails.
- output_buffer_->acquire_fence_fd = release_fence;
+ output_buffer_.acquire_fence_fd = release_fence;
return HWC2::Error::None;
}
diff --git a/composer/hwc_display_virtual.h b/composer/hwc_display_virtual.h
index 010c805..e699146 100644
--- a/composer/hwc_display_virtual.h
+++ b/composer/hwc_display_virtual.h
@@ -39,30 +39,29 @@
class HWCDisplayVirtual : public HWCDisplay {
public:
- static int Create(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
- HWCCallbacks *callbacks, hwc2_display_t id, int32_t sdm_id, uint32_t width,
- uint32_t height, int32_t *format, HWCDisplay **hwc_display, float min_lum,
- float max_lum);
static void Destroy(HWCDisplay *hwc_display);
virtual int Init();
virtual int Deinit();
- virtual HWC2::Error Validate(uint32_t *out_num_types, uint32_t *out_num_requests);
virtual HWC2::Error Present(int32_t *out_retire_fence);
virtual HWC2::Error SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type,
int32_t format, bool post_processed);
virtual HWC2::Error GetDisplayType(int32_t *out_type);
- virtual HWC2::Error SetPanelLuminanceAttributes(float min_lum, float max_lum);
virtual HWC2::Error SetColorMode(ColorMode mode);
- HWC2::Error SetOutputBuffer(buffer_handle_t buf, int32_t release_fence);
+ virtual HWC2::Error SetOutputBuffer(buffer_handle_t buf, int32_t release_fence);
+ virtual HWC2::Error DumpVDSBuffer();
+ bool NeedsGPUBypass();
+ HWCDisplayVirtual(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
+ HWCCallbacks *callbacks, hwc2_display_t id, int32_t sdm_id,
+ uint32_t width, uint32_t height);
+
+ protected:
+ uint32_t width_ = 0;
+ uint32_t height_ = 0;
+ LayerBuffer output_buffer_ = {};
+ const private_handle_t *output_handle_ = nullptr;
private:
- HWCDisplayVirtual(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
- HWCCallbacks *callbacks, hwc2_display_t id, int32_t sdm_id);
- int SetConfig(uint32_t width, uint32_t height);
-
bool dump_output_layer_ = false;
- LayerBuffer *output_buffer_ = NULL;
- const private_handle_t *output_handle_ = nullptr;
};
} // namespace sdm
diff --git a/composer/hwc_display_virtual_dpu.cpp b/composer/hwc_display_virtual_dpu.cpp
new file mode 100644
index 0000000..451b132
--- /dev/null
+++ b/composer/hwc_display_virtual_dpu.cpp
@@ -0,0 +1,191 @@
+/*
+ * 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 <hwc_display_virtual_dpu.h>
+
+#define __CLASS__ "HWCDisplayVirtualDPU"
+
+namespace sdm {
+
+HWCDisplayVirtualDPU::HWCDisplayVirtualDPU(CoreInterface *core_intf, HWCBufferAllocator
+ *buffer_allocator, HWCCallbacks *callbacks,
+ hwc2_display_t id, int32_t sdm_id, uint32_t width,
+ uint32_t height, float min_lum, float max_lum)
+ : HWCDisplayVirtual(core_intf, buffer_allocator, callbacks, id, sdm_id, width, height),
+ min_lum_(min_lum), max_lum_(max_lum) {
+}
+
+int HWCDisplayVirtualDPU::Init() {
+ int status = HWCDisplay::Init();
+ if (status) {
+ DLOGE("Init failed: %d", status);
+ return status;
+ }
+
+ if (max_lum_ != -1.0 || min_lum_ != -1.0) {
+ SetPanelLuminanceAttributes(min_lum_, max_lum_);
+ }
+
+ status = SetConfig(width_, height_);
+ if (status) {
+ DLOGE("Failed to set width: %d height: %d", width_, height_);
+ return status;
+ }
+
+ status = INT32(SetPowerMode(HWC2::PowerMode::On, false /* teardown */));
+ if (status) {
+ DLOGW("Failed to set power mode on virtual display");
+ return status;
+ }
+
+ // TODO(user): Validate that we support this width/height
+ status = SetFrameBufferResolution(width_, height_);
+ if (status) {
+ DLOGW("Failed to set FrameBuffer resolution on virtual display");
+ return status;
+ }
+
+ return HWCDisplayVirtual::Init();
+}
+
+int HWCDisplayVirtualDPU::SetConfig(uint32_t width, uint32_t height) {
+ DisplayConfigVariableInfo variable_info;
+ variable_info.x_pixels = width;
+ variable_info.y_pixels = height;
+ // TODO(user): Need to get the framerate of primary display and update it.
+ variable_info.fps = 60;
+
+ DisplayError err = display_intf_->SetActiveConfig(&variable_info);
+ if (err != kErrorNone) {
+ return -EINVAL;
+ }
+ return 0;
+}
+
+HWC2::Error HWCDisplayVirtualDPU::SetOutputBuffer(buffer_handle_t buf, int32_t release_fence) {
+ HWC2::Error error = HWCDisplayVirtual::SetOutputBuffer(buf, release_fence);
+ if (error != HWC2::Error::None) {
+ return error;
+ }
+
+ const private_handle_t *output_handle = static_cast<const private_handle_t *>(buf);
+ if (output_handle) {
+ int output_handle_format = output_handle->format;
+ int active_aligned_w, active_aligned_h;
+ int new_width, new_height;
+ int new_aligned_w, new_aligned_h;
+ uint32_t active_width, active_height;
+
+ GetMixerResolution(&active_width, &active_height);
+ buffer_allocator_->GetCustomWidthAndHeight(output_handle, &new_width, &new_height);
+ buffer_allocator_->GetAlignedWidthAndHeight(INT(new_width), INT(new_height),
+ output_handle_format, 0, &new_aligned_w,
+ &new_aligned_h);
+ buffer_allocator_->GetAlignedWidthAndHeight(INT(active_width), INT(active_height),
+ output_handle_format, 0, &active_aligned_w,
+ &active_aligned_h);
+ if (new_aligned_w != active_aligned_w || new_aligned_h != active_aligned_h) {
+ int status = SetConfig(UINT32(new_width), UINT32(new_height));
+ if (status) {
+ DLOGE("SetConfig failed custom WxH %dx%d", new_width, new_height);
+ return HWC2::Error::BadParameter;
+ }
+ validated_ = false;
+ }
+
+ output_buffer_.width = UINT32(new_aligned_w);
+ output_buffer_.height = UINT32(new_aligned_h);
+ output_buffer_.unaligned_width = UINT32(new_width);
+ output_buffer_.unaligned_height = UINT32(new_height);
+ }
+
+ return HWC2::Error::None;
+}
+
+HWC2::Error HWCDisplayVirtualDPU::Validate(uint32_t *out_num_types, uint32_t *out_num_requests) {
+ if (NeedsGPUBypass()) {
+ MarkLayersForGPUBypass();
+ return HWC2::Error::None;
+ }
+
+ BuildLayerStack();
+ layer_stack_.output_buffer = &output_buffer_;
+ // If Output buffer of Virtual Display is not secure, set SKIP flag on the secure layers.
+ if (!output_buffer_.flags.secure && layer_stack_.flags.secure_present) {
+ for (auto hwc_layer : layer_set_) {
+ Layer *layer = hwc_layer->GetSDMLayer();
+ if (layer->input_buffer.flags.secure) {
+ layer_stack_.flags.skip_present = true;
+ layer->flags.skip = true;
+ }
+ }
+ }
+
+ return PrepareLayerStack(out_num_types, out_num_requests);
+}
+
+HWC2::Error HWCDisplayVirtualDPU::Present(int32_t *out_retire_fence) {
+ auto status = HWC2::Error::None;
+
+ if (!output_buffer_.buffer_id) {
+ return HWC2::Error::NoResources;
+ }
+
+ if (active_secure_sessions_.any()) {
+ return status;
+ }
+
+ layer_stack_.output_buffer = &output_buffer_;
+ if (display_paused_) {
+ validated_ = false;
+ flush_ = true;
+ }
+
+ status = HWCDisplay::CommitLayerStack();
+ if (status != HWC2::Error::None) {
+ return status;
+ }
+
+ DumpVDSBuffer();
+
+ status = HWCDisplay::PostCommitLayerStack(out_retire_fence);
+
+ return status;
+}
+
+HWC2::Error HWCDisplayVirtualDPU::SetPanelLuminanceAttributes(float min_lum, float max_lum) {
+ DisplayError err = display_intf_->SetPanelLuminanceAttributes(min_lum, max_lum);
+ if (err != kErrorNone) {
+ return HWC2::Error::BadParameter;
+ }
+ return HWC2::Error::None;
+}
+
+} // namespace sdm
+
diff --git a/composer/hwc_display_virtual_dpu.h b/composer/hwc_display_virtual_dpu.h
new file mode 100644
index 0000000..e74bc9d
--- /dev/null
+++ b/composer/hwc_display_virtual_dpu.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 __HWC_DISPLAY_VIRTUAL_DPU_H__
+#define __HWC_DISPLAY_VIRTUAL_DPU_H__
+
+#include "hwc_display_virtual.h"
+
+namespace sdm {
+
+class HWCDisplayVirtualDPU : public HWCDisplayVirtual {
+ public:
+ HWCDisplayVirtualDPU(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
+ HWCCallbacks *callbacks, hwc2_display_t id, int32_t sdm_id,
+ uint32_t width, uint32_t height, float min_lum, float max_lum);
+ virtual int Init();
+ virtual HWC2::Error Validate(uint32_t *out_num_types, uint32_t *out_num_requests);
+ virtual HWC2::Error Present(int32_t *out_retire_fence);
+ virtual HWC2::Error SetOutputBuffer(buffer_handle_t buf, int32_t release_fence);
+ virtual HWC2::Error SetPanelLuminanceAttributes(float min_lum, float max_lum);
+
+ private:
+ int SetConfig(uint32_t width, uint32_t height);
+
+ float min_lum_ = 0.0f;
+ float max_lum_ = 0.0f;
+};
+
+} // namespace sdm
+
+#endif // __HWC_DISPLAY_VIRTUAL_DPU_H__
diff --git a/composer/hwc_display_virtual_factory.cpp b/composer/hwc_display_virtual_factory.cpp
new file mode 100644
index 0000000..8767d14
--- /dev/null
+++ b/composer/hwc_display_virtual_factory.cpp
@@ -0,0 +1,96 @@
+/*
+ * 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 "hwc_display_virtual_factory.h"
+#include "hwc_display_virtual_dpu.h"
+#include "hwc_display_virtual_gpu.h"
+
+#define __CLASS__ "HWCVirtualDisplayFactory"
+
+namespace sdm {
+
+int HWCVirtualDisplayFactory::Create(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
+ HWCCallbacks *callbacks, hwc2_display_t id, int32_t sdm_id,
+ uint32_t width, uint32_t height, int32_t *format,
+ float min_lum, float max_lum, HWCDisplay **hwc_display) {
+ int supported_virtual_displays = 0;
+ DisplayError error = core_intf->GetMaxDisplaysSupported(kVirtual, &supported_virtual_displays);
+ if (error != kErrorNone) {
+ DLOGE("Could not find maximum virtual displays supported. Error = %d", error);
+ return -1;
+ }
+
+ HWCDisplayVirtual *hwc_display_virtual = nullptr;
+ if (supported_virtual_displays) {
+ hwc_display_virtual = new HWCDisplayVirtualDPU(core_intf, buffer_allocator, callbacks, id,
+ sdm_id, width, height, min_lum, max_lum);
+ } else {
+ // Create GPU based virtual display.
+ hwc_display_virtual = new HWCDisplayVirtualGPU(core_intf, buffer_allocator, callbacks, id,
+ sdm_id, width, height, min_lum, max_lum);
+ }
+
+ if (hwc_display_virtual == nullptr) {
+ DLOGE("Failed to create instance");
+ return -1;
+ } else {
+ DLOGI("Created %s based virtual display", (supported_virtual_displays ? "DPU" : "GPU"));
+ }
+
+ int status = hwc_display_virtual->Init();
+ if (status) {
+ DLOGW("Failed to initialize virtual display");
+ Destroy(hwc_display_virtual);
+ return status;
+ }
+
+ // TODO(user): Populate format correctly
+ DLOGI("Creating virtual display: w: %d h:%d format:0x%x", width, height, *format);
+
+ *hwc_display = hwc_display_virtual;
+
+ return status;
+}
+
+bool HWCVirtualDisplayFactory::IsGPUColorConvertSupported() {
+ int value = 0;
+ HWCDebugHandler::Get()->GetProperty(DISABLE_GPU_COLOR_CONVERT, &value);
+ return (value == 0);
+}
+
+void HWCVirtualDisplayFactory::Destroy(HWCDisplay *hwc_display) {
+ DLOGI("Destroying virtual display instance");
+ if (hwc_display->Deinit() != 0) {
+ DLOGE("Failed to destroy instance");
+ }
+
+ delete hwc_display;
+}
+
+} // namespace sdm
diff --git a/composer/hwc_display_virtual_factory.h b/composer/hwc_display_virtual_factory.h
new file mode 100644
index 0000000..38f6a80
--- /dev/null
+++ b/composer/hwc_display_virtual_factory.h
@@ -0,0 +1,53 @@
+/*
+ * 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 __HWC_DISPLAY_VIRTUAL_FACTORY_H__
+#define __HWC_DISPLAY_VIRTUAL_FACTORY_H__
+
+#include <core/core_interface.h>
+
+#include "hwc_callbacks.h"
+#include "hwc_debugger.h"
+#include "hwc_display.h"
+#include "hwc_buffer_allocator.h"
+
+namespace sdm {
+
+class HWCVirtualDisplayFactory {
+ public:
+ int Create(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
+ HWCCallbacks *callbacks, hwc2_display_t id, int32_t sdm_id, uint32_t width,
+ uint32_t height, int32_t *format, float min_lum, float max_lum,
+ HWCDisplay **hwc_display);
+ void Destroy(HWCDisplay *hwc_display);
+ bool IsGPUColorConvertSupported();
+};
+
+} // namespace sdm
+
+#endif // __HWC_DISPLAY_VIRTUAL_FACTORY_H__
diff --git a/composer/hwc_display_virtual_gpu.cpp b/composer/hwc_display_virtual_gpu.cpp
new file mode 100644
index 0000000..5845e78
--- /dev/null
+++ b/composer/hwc_display_virtual_gpu.cpp
@@ -0,0 +1,187 @@
+/*
+ * 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 "hwc_display_virtual_gpu.h"
+#include "hwc_session.h"
+
+#define __CLASS__ "HWCDisplayVirtualGPU"
+
+namespace sdm {
+
+int HWCDisplayVirtualGPU::Init() {
+ // Create client target.
+ client_target_ = new HWCLayer(id_, buffer_allocator_);
+
+ // Calls into SDM need to be dropped. Create Null Display interface.
+ display_intf_ = new DisplayNull();
+
+ return HWCDisplayVirtual::Init();
+}
+
+int HWCDisplayVirtualGPU::Deinit() {
+ // Destory color convert instance. This destroys thread and underlying GL resources.
+ if (gl_color_convert_) {
+ color_convert_task_.PerformTask(ColorConvertTaskCode::kCodeDestroyInstance, nullptr);
+ }
+
+ delete static_cast<DisplayNull *>(display_intf_);
+ delete client_target_;
+
+ for (auto hwc_layer : layer_set_) {
+ delete hwc_layer;
+ }
+
+ return 0;
+}
+
+HWCDisplayVirtualGPU::HWCDisplayVirtualGPU(CoreInterface *core_intf, HWCBufferAllocator
+ *buffer_allocator, HWCCallbacks *callbacks,
+ hwc2_display_t id, int32_t sdm_id, uint32_t width,
+ uint32_t height, float min_lum, float max_lum) :
+ HWCDisplayVirtual(core_intf, buffer_allocator, callbacks, id, sdm_id, width, height),
+ color_convert_task_(*this) {
+}
+
+HWC2::Error HWCDisplayVirtualGPU::Validate(uint32_t *out_num_types, uint32_t *out_num_requests) {
+ DTRACE_SCOPED();
+
+ // Mark all layers to GPU if there is no need to bypass.
+ bool needs_gpu_bypass = NeedsGPUBypass();
+ for (auto hwc_layer : layer_set_) {
+ auto layer = hwc_layer->GetSDMLayer();
+ layer->composition = needs_gpu_bypass ? kCompositionSDE : kCompositionGPU;
+
+ if (needs_gpu_bypass) {
+ if (hwc_layer->GetClientRequestedCompositionType() == HWC2::Composition::Client) {
+ layer_changes_[hwc_layer->GetId()] = HWC2::Composition::Device;
+ layer_requests_[hwc_layer->GetId()] = HWC2::LayerRequest::ClearClientTarget;
+ }
+ } else {
+ if (hwc_layer->GetClientRequestedCompositionType() != HWC2::Composition::Client) {
+ layer_changes_[hwc_layer->GetId()] = HWC2::Composition::Client;
+ }
+ }
+ }
+
+ // Derive client target dataspace based on the color mode - bug/115482728
+ int32_t client_target_dataspace = GetDataspaceFromColorMode(GetCurrentColorMode());
+ SetClientTargetDataSpace(client_target_dataspace);
+
+ *out_num_types = UINT32(layer_changes_.size());
+ *out_num_requests = UINT32(layer_requests_.size());;
+ has_client_composition_ = !needs_gpu_bypass;
+ client_target_->ResetValidation();
+
+ validated_ = true;
+
+ return ((*out_num_types > 0) ? HWC2::Error::HasChanges : HWC2::Error::None);
+}
+
+HWC2::Error HWCDisplayVirtualGPU::Present(int32_t *out_retire_fence) {
+ DTRACE_SCOPED();
+
+ auto status = HWC2::Error::None;
+
+ if (!validated_) {
+ return HWC2::Error::NotValidated;
+ }
+
+ if (!output_buffer_.buffer_id) {
+ return HWC2::Error::NoResources;
+ }
+
+ if (active_secure_sessions_.any() || layer_set_.empty()) {
+ return status;
+ }
+
+ layer_stack_.output_buffer = &output_buffer_;
+ if (display_paused_) {
+ validated_ = false;
+ }
+
+ // Ensure that blit is initialized.
+ // GPU context gets in secure or non-secure mode depending on output buffer provided.
+ if (!gl_color_convert_) {
+ // Get instance.
+ color_convert_task_.PerformTask(ColorConvertTaskCode::kCodeGetInstance, nullptr);
+ if (gl_color_convert_ == nullptr) {
+ DLOGE("Failed to get Color Convert Instance");
+ return HWC2::Error::NoResources;
+ } else {
+ DLOGI("Created ColorConvert instance: %p", gl_color_convert_);
+ }
+ }
+
+ ColorConvertBlitContext ctx = {};
+
+ Layer *sdm_layer = client_target_->GetSDMLayer();
+ LayerBuffer &input_buffer = sdm_layer->input_buffer;
+ ctx.src_hnd = reinterpret_cast<const private_handle_t *>(input_buffer.buffer_id);
+ ctx.dst_hnd = reinterpret_cast<const private_handle_t *>(output_handle_);
+ ctx.dst_rect = {0, 0, FLOAT(output_buffer_.width), FLOAT(output_buffer_.height)};
+ ctx.src_acquire_fence_fd = input_buffer.acquire_fence_fd;
+ ctx.dst_acquire_fence_fd = output_buffer_.acquire_fence_fd;
+ ctx.release_fence_fd = -1;
+
+ color_convert_task_.PerformTask(ColorConvertTaskCode::kCodeBlit, &ctx);
+
+ // todo blit
+ DumpVDSBuffer();
+
+ *out_retire_fence = ctx.release_fence_fd;
+
+ return status;
+}
+
+void HWCDisplayVirtualGPU::OnTask(const ColorConvertTaskCode &task_code,
+ SyncTask<ColorConvertTaskCode>::TaskContext *task_context) {
+ switch (task_code) {
+ case ColorConvertTaskCode::kCodeGetInstance: {
+ gl_color_convert_ = GLColorConvert::GetInstance(kTargetYUV, output_buffer_.flags.secure);
+ }
+ break;
+ case ColorConvertTaskCode::kCodeBlit: {
+ DTRACE_SCOPED();
+ ColorConvertBlitContext* ctx = reinterpret_cast<ColorConvertBlitContext*>(task_context);
+ gl_color_convert_->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 ColorConvertTaskCode::kCodeDestroyInstance: {
+ if (gl_color_convert_) {
+ GLColorConvert::Destroy(gl_color_convert_);
+ }
+ }
+ break;
+ }
+}
+
+} // namespace sdm
+
diff --git a/composer/hwc_display_virtual_gpu.h b/composer/hwc_display_virtual_gpu.h
new file mode 100644
index 0000000..3c85cd2
--- /dev/null
+++ b/composer/hwc_display_virtual_gpu.h
@@ -0,0 +1,81 @@
+/*
+ * 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 __HWC_DISPLAY_VIRTUAL_GPU_H__
+#define __HWC_DISPLAY_VIRTUAL_GPU_H__
+
+#include "utils/sync_task.h"
+#include "hwc_display_virtual.h"
+#include "gl_color_convert.h"
+
+namespace sdm {
+
+enum class ColorConvertTaskCode : int32_t {
+ kCodeGetInstance,
+ kCodeBlit,
+ kCodeDestroyInstance,
+};
+
+struct ColorConvertGetInstanceContext : public SyncTask<ColorConvertTaskCode>::TaskContext {
+ LayerBuffer *output_buffer = NULL;
+};
+
+struct ColorConvertBlitContext : public SyncTask<ColorConvertTaskCode>::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 HWCDisplayVirtualGPU : public HWCDisplayVirtual,
+ public SyncTask<ColorConvertTaskCode>::TaskHandler {
+ public:
+ HWCDisplayVirtualGPU(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
+ HWCCallbacks *callbacks, hwc2_display_t id, int32_t sdm_id,
+ uint32_t width, uint32_t height, float min_lum, float max_lum);
+ virtual int Init();
+ virtual int Deinit();
+ virtual HWC2::Error Validate(uint32_t *out_num_types, uint32_t *out_num_requests);
+ virtual HWC2::Error Present(int32_t *out_retire_fence);
+
+ private:
+ // SyncTask methods.
+ void OnTask(const ColorConvertTaskCode &task_code,
+ SyncTask<ColorConvertTaskCode>::TaskContext *task_context);
+
+ SyncTask<ColorConvertTaskCode> color_convert_task_;
+ GLColorConvert *gl_color_convert_;
+};
+
+} // namespace sdm
+
+#endif // __HWC_DISPLAY_VIRTUAL_GPU_H__
diff --git a/composer/hwc_session.cpp b/composer/hwc_session.cpp
index d405bbc..b4dd15e 100644
--- a/composer/hwc_session.cpp
+++ b/composer/hwc_session.cpp
@@ -286,6 +286,11 @@
return;
}
+ if (max_virtual == 0) {
+ // Check if WB using GPU is supported.
+ max_virtual += virtual_display_factory_.IsGPUColorConvertSupported() ? 1 : 0;
+ }
+
if (kPluggable == hw_disp_info.type) {
// If primary is a pluggable display, we have already used one pluggable display interface.
max_pluggable--;
@@ -1115,9 +1120,9 @@
continue;
}
- status = HWCDisplayVirtual::Create(core_intf_, &buffer_allocator_, &callbacks_, client_id,
- info.display_id, width, height, format, &hwc_display,
- set_min_lum_, set_max_lum_);
+ 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;
@@ -2703,7 +2708,7 @@
HWCDisplayBuiltIn::Destroy(hwc_display);
break;
default:
- HWCDisplayVirtual::Destroy(hwc_display);
+ virtual_display_factory_.Destroy(hwc_display);
break;
}
diff --git a/composer/hwc_session.h b/composer/hwc_session.h
index 87ebbe0..b4c9fea 100644
--- a/composer/hwc_session.h
+++ b/composer/hwc_session.h
@@ -45,6 +45,7 @@
#include "hwc_socket_handler.h"
#include "hwc_display_event_handler.h"
#include "hwc_buffer_sync_handler.h"
+#include "hwc_display_virtual_factory.h"
namespace sdm {
@@ -453,6 +454,7 @@
HWCCallbacks callbacks_;
HWCBufferAllocator buffer_allocator_;
HWCBufferSyncHandler buffer_sync_handler_;
+ HWCVirtualDisplayFactory virtual_display_factory_;
HWCColorManager *color_mgr_ = nullptr;
DisplayMapInfo map_info_primary_; // Primary display (either builtin or pluggable)
std::vector<DisplayMapInfo> map_info_builtin_; // Builtin displays excluding primary
diff --git a/composer/hwc_session_services.cpp b/composer/hwc_session_services.cpp
index 4ff1bdf..cba4481 100644
--- a/composer/hwc_session_services.cpp
+++ b/composer/hwc_session_services.cpp
@@ -739,7 +739,7 @@
int32_t error = -EINVAL;
vendor_prop_name += prop_name.c_str();
- if (HWCDebugHandler::Get()->GetProperty(vendor_prop_name.c_str(), value) != kErrorNone) {
+ if (HWCDebugHandler::Get()->GetProperty(vendor_prop_name.c_str(), value) == kErrorNone) {
result = value;
error = 0;
}
diff --git a/gpu_tonemapper/EGLImageBuffer.cpp b/gpu_tonemapper/EGLImageBuffer.cpp
index eeb0273..92817ef 100644
--- a/gpu_tonemapper/EGLImageBuffer.cpp
+++ b/gpu_tonemapper/EGLImageBuffer.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017, 2019 The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright 2015 The Android Open Source Project
@@ -97,11 +97,11 @@
}
//-----------------------------------------------------------------------------
-unsigned int EGLImageBuffer::getTexture()
+unsigned int EGLImageBuffer::getTexture(int target)
//-----------------------------------------------------------------------------
{
if (textureID == 0) {
- bindAsTexture();
+ bindAsTexture(target);
}
return textureID;
@@ -119,22 +119,21 @@
}
//-----------------------------------------------------------------------------
-void EGLImageBuffer::bindAsTexture()
+void EGLImageBuffer::bindAsTexture(int target)
//-----------------------------------------------------------------------------
{
if (textureID == 0) {
GL(glGenTextures(1, &textureID));
- int target = 0x8D65;
GL(glBindTexture(target, textureID));
GL(glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
GL(glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
GL(glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
GL(glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
- GL(glEGLImageTargetTexture2DOES(0x8D65, eglImageID));
+ GL(glEGLImageTargetTexture2DOES(target, eglImageID));
}
- GL(glBindTexture(0x8D65, textureID));
+ GL(glBindTexture(target, textureID));
}
//-----------------------------------------------------------------------------
diff --git a/gpu_tonemapper/EGLImageBuffer.h b/gpu_tonemapper/EGLImageBuffer.h
index 23af573..1433fdd 100644
--- a/gpu_tonemapper/EGLImageBuffer.h
+++ b/gpu_tonemapper/EGLImageBuffer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 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
@@ -38,13 +38,13 @@
int getWidth();
int getHeight();
EGLImageBuffer(android::sp<android::GraphicBuffer>);
- unsigned int getTexture();
+ unsigned int getTexture(int target);
unsigned int getFramebuffer();
- void bindAsTexture();
+ void bindAsTexture(int target);
void bindAsFramebuffer();
~EGLImageBuffer();
static EGLImageBuffer *from(const private_handle_t *src);
static void clear();
};
-#endif //__EGLIMAGE_BUFFER_H__
\ No newline at end of file
+#endif //__EGLIMAGE_BUFFER_H_
diff --git a/gpu_tonemapper/Tonemapper.cpp b/gpu_tonemapper/Tonemapper.cpp
index 2605c7f..aa86a3c 100644
--- a/gpu_tonemapper/Tonemapper.cpp
+++ b/gpu_tonemapper/Tonemapper.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
@@ -143,7 +143,7 @@
}
// set source
if (src_buffer) {
- engine_setExternalInputBuffer(0, src_buffer->getTexture());
+ engine_setExternalInputBuffer(0, src_buffer->getTexture(0x8D65 /* target texture */));
}
// set 3d lut
engine_set3DInputBuffer(1, tonemapTexture);
diff --git a/include/display_properties.h b/include/display_properties.h
index 91e7696..75a4b67 100644
--- a/include/display_properties.h
+++ b/include/display_properties.h
@@ -111,6 +111,7 @@
#define ENABLE_ASYNC_POWERMODE DISPLAY_PROP("enable_async_powermode")
#define ENABLE_GPU_TONEMAPPER_PROP DISPLAY_PROP("enable_gpu_tonemapper")
#define ENABLE_FORCE_SPLIT DISPLAY_PROP("enable_force_split")
+#define DISABLE_GPU_COLOR_CONVERT DISPLAY_PROP("disable_gpu_color_convert")
// Add all vendor.display properties above
diff --git a/sdm/libs/core/drm/hw_tv_drm.cpp b/sdm/libs/core/drm/hw_tv_drm.cpp
index e324d7b..162e3f0 100644
--- a/sdm/libs/core/drm/hw_tv_drm.cpp
+++ b/sdm/libs/core/drm/hw_tv_drm.cpp
@@ -341,6 +341,7 @@
// will cause flicker.
InitMaxHDRMetaData();
in_multiset_ = true;
+ reset_hdr_flag_ = false;
drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_HDR_METADATA, token_.conn_id, &hdr_metadata_);
DumpHDRMetaData(hdr_op);
} else if (hdr_op == HWHDRLayerInfo::kReset) {