Merge "hwc: Fix scaling issue in copybit."
diff --git a/Android.mk b/Android.mk
index b3015af..a128327 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,13 +1,16 @@
-# This flag will be set to true during migration to Snapdragon Display Engine.
-TARGET_USES_SDE = false
+ifeq ($(call is-board-platform-in-list, thulium),true)
+ TARGET_USES_SDE = true
+else
+ TARGET_USES_SDE = false
+endif
-display-hals := libgralloc libcopybit liblight libmemtrack libqservice
+display-hals := libgralloc libcopybit liblight libmemtrack libqservice libqdutils
ifeq ($(TARGET_USES_SDE), true)
sde-libs := displayengine/libs
display-hals += $(sde-libs)/utils $(sde-libs)/core $(sde-libs)/hwc
else
- display-hals += libgenlock libhwcomposer liboverlay libqdutils libhdmi
+ display-hals += libgenlock libhwcomposer liboverlay libhdmi
endif
ifeq ($(call is-vendor-board-platform,QCOM),true)
diff --git a/displayengine/include/core/buffer_allocator.h b/displayengine/include/core/buffer_allocator.h
new file mode 100644
index 0000000..4081c54
--- /dev/null
+++ b/displayengine/include/core/buffer_allocator.h
@@ -0,0 +1,130 @@
+/*
+* Copyright (c) 2015, 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.
+*/
+
+/*! @file buffer_allocator.h
+ @brief Interface file for platform specific buffer allocator.
+
+ @details Buffer manager in display engine uses this interface to allocate buffer for internal
+ usage.
+*/
+
+#ifndef __BUFFER_ALLOCATOR_H__
+#define __BUFFER_ALLOCATOR_H__
+
+#include <core/layer_buffer.h>
+
+namespace sde {
+ /*! @brief Input configuration set by the client for buffer allocation.
+
+ @sa BufferInfo::BufferConfig
+ */
+
+struct BufferConfig {
+ uint32_t width; //!< Specifies buffer width for buffer allocation.
+ uint32_t height; //!< Specifies buffer height for buffer allocation.
+ LayerBufferFormat format; //!< Specifies buffer format for buffer allocation.
+ uint32_t buffer_count; //!< Specifies number of buffers to be allocated.
+ bool secure; //!< Specifies buffer to be allocated from secure region.
+ bool cache; //!< Specifies whether the buffer needs to be cache.
+
+ BufferConfig() : width(0), height(0), format(kFormatInvalid), buffer_count(0), secure(false),
+ cache(false) { }
+};
+
+/*! @brief Holds the information about the allocated buffer.
+
+ @sa BufferAllocator::AllocateBuffer
+ @sa BufferAllocator::FreeBuffer
+*/
+struct AllocatedBufferInfo {
+ int fd; //!< Specifies the fd of the allocated buffer.
+ uint32_t stride; //!< Specifies aligned buffer width of the allocated buffer.
+ uint32_t size; //!< Specifies the size of the allocated buffer.
+
+ AllocatedBufferInfo() : fd(-1), stride(0), size(0) { }
+};
+
+/*! @brief Holds the information about the input/output configuration of an output buffer.
+
+ @sa BufferAllocator::AllocateBuffer
+ @sa BufferAllocator::FreeBuffer
+*/
+struct BufferInfo {
+ BufferConfig buffer_config; //!< Specifies configuration of a buffer to be allocated.
+ AllocatedBufferInfo alloc_buffer_info; //!< Specifies buffer information of allocated buffer.
+
+ void *private_data; //!< Pointer to private data.
+
+ BufferInfo() : private_data(NULL) { }
+};
+
+/*! @brief Buffer allocator implemented by the client
+
+ @details This class declares prototype for BufferAllocator methods which must be
+ implemented by the client. Buffer manager in display engine will use these methods to
+ allocate/deallocate buffers for display engine.
+
+ @sa CompManager::Init
+ @sa ResManager::Init
+*/
+class BufferAllocator {
+ public:
+ /*! @brief Method to allocate ouput buffer for the given input configuration.
+
+ @details This method allocates memory based on input configuration.
+
+ @param[in] buffer_info \link BufferInfo \endlink
+
+ @return \link DisplayError \endlink
+
+ @sa BufferManager
+ */
+ virtual DisplayError AllocateBuffer(BufferInfo *buffer_info) = 0;
+
+
+ /*! @brief Method to deallocate the ouput buffer.
+
+ @details This method deallocates the memory allocated using AllocateBuffer method.
+
+ @param[in] buffer_info \link BufferInfo \endlink
+
+ @return \link DisplayError \endlink
+
+ @sa BufferManager
+ */
+ virtual DisplayError FreeBuffer(BufferInfo *buffer_info) = 0;
+
+ protected:
+ virtual ~BufferAllocator() { }
+};
+
+} // namespace sde
+
+#endif // __BUFFER_ALLOCATOR_H__
+
diff --git a/displayengine/include/core/buffer_sync_handler.h b/displayengine/include/core/buffer_sync_handler.h
new file mode 100644
index 0000000..d0d062e
--- /dev/null
+++ b/displayengine/include/core/buffer_sync_handler.h
@@ -0,0 +1,90 @@
+/*
+* Copyright (c) 2015, 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.
+*/
+
+/*! @file buffer_sync_handler.h
+ @brief Interface file for platform specific buffer allocator.
+
+ @details Buffer manager in display engine uses this interface to wait for buffer sync fd to be
+ signaled/merge the two buffer sync fds into one
+*/
+
+#ifndef __BUFFER_SYNC_HANDLER_H__
+#define __BUFFER_SYNC_HANDLER_H__
+
+namespace sde {
+
+/*! @brief Buffer sync handler implemented by the client
+
+ @details This class declares prototype for BufferSyncHandler methods which must be
+ implemented by the client. Buffer manager and HWFramebuffer in display engine will use these
+ methods to wait for buffer sync fd to be signaled/merge two buffer sync fds into one.
+
+ @sa CompManager::Init
+ @sa ResManager::Init
+ @sa HWInterface::Create
+*/
+class BufferSyncHandler {
+ public:
+ /*! @brief Method to wait for ouput buffer to be released.
+
+ @details This method waits for fd to be signaled by the producer/consumer.
+
+ @param[in] fd
+
+ @return \link DisplayError \endlink
+
+ @sa BufferManager::GetNextBuffer
+ */
+
+ virtual DisplayError SyncWait(int fd) = 0;
+
+ /*! @brief Method to merge two sync fds into one sync fd
+
+ @details This method merges two buffer sync fds into one sync fd, if a producer/consumer
+ requires to wait for more than one sync fds.
+
+ @param[in] fd1
+ @param[in] fd2
+ @param[out] merged_fd
+
+ @return \link DisplayError \endlink
+
+ @sa HWFrameBuffer::RotatorCommit
+ */
+
+ virtual DisplayError SyncMerge(int fd1, int fd2, int *merged_fd) = 0;
+
+ protected:
+ virtual ~BufferSyncHandler() { }
+};
+
+} // namespace sde
+
+#endif // __BUFFER_SYNC_HANDLER_H__
+
diff --git a/displayengine/include/core/core_interface.h b/displayengine/include/core/core_interface.h
old mode 100755
new mode 100644
index 2229d1e..114d9aa
--- a/displayengine/include/core/core_interface.h
+++ b/displayengine/include/core/core_interface.h
@@ -1,25 +1,30 @@
/*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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.
+* 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.
+* 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.
*/
/*! @file core_interface.h
@@ -36,6 +41,9 @@
#include "display_interface.h"
#include "sde_types.h"
+#include "buffer_allocator.h"
+
+class BufferSyncHandler;
/*! @brief Display engine interface version.
@@ -65,6 +73,11 @@
namespace sde {
+/*! @brief Forward declaration for debug handler.
+*/
+class DebugHandler;
+
+
/*! @brief Event data associated with hotplug event.
@sa CoreEventHandler::Hotplug
@@ -120,7 +133,9 @@
This interface shall be called only once.
@param[in] event_handler \link CoreEventHandler \endlink
- @param[in] log_handler \link LogHandler \endlink
+ @param[in] debug_handler \link DebugHandler \endlink
+ @param[in] buffer_allocator \link BufferAllocator \endlink
+ @param[in] buffer_sync_handler \link BufferSyncHandler \endlink
@param[out] interface \link CoreInterface \endlink
@param[in] version \link SDE_VERSION_TAG \endlink. Client must not override this argument.
@@ -128,8 +143,10 @@
@sa DestroyCore
*/
- static DisplayError CreateCore(CoreEventHandler *event_handler, LogHandler *log_handler,
- CoreInterface **interface, uint32_t version = SDE_VERSION_TAG);
+ static DisplayError CreateCore(CoreEventHandler *event_handler, DebugHandler *debug_handler,
+ BufferAllocator *buffer_allocator,
+ BufferSyncHandler *buffer_sync_handler, CoreInterface **interface,
+ uint32_t version = SDE_VERSION_TAG);
/*! @brief Method to release handle to display core interface.
diff --git a/displayengine/include/core/debug_interface.h b/displayengine/include/core/debug_interface.h
new file mode 100644
index 0000000..c90e1ff
--- /dev/null
+++ b/displayengine/include/core/debug_interface.h
@@ -0,0 +1,128 @@
+/*
+* Copyright (c) 2015, 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.
+*/
+
+/*! @file debug_interface.h
+ @brief This file provides the debug interface for display engine.
+*/
+#ifndef __DEBUG_INTERFACE_H__
+#define __DEBUG_INTERFACE_H__
+
+namespace sde {
+
+/*! @brief This enum represents different modules/logical unit tags that a log message may
+ be associated with. Client may use this to filter messages for dynamic logging.
+
+ @sa DisplayLogHandler
+*/
+enum DebugTag {
+ kTagNone, //!< Debug log is not tagged. This type of logs should always be printed.
+ kTagResources, //!< Debug log is tagged for resource management.
+ kTagStrategy, //!< Debug log is tagged for strategy decisions.
+ kTagCompManager, //!< Debug log is tagged for composition manager.
+ kTagDriverConfig, //!< Debug log is tagged for driver config.
+ kTagBufferManager, //!< Debug log is tagged for buffer manager state transitions.
+ kTagOfflineCtrl, //!< Debug log is tagged for offline controller.
+};
+
+/*! @brief Display debug handler class.
+
+ @details This class defines display debug handler. The handle contains methods which client
+ should implement to get different levels of logging/tracing from display engine. Display engine
+ will call into these methods at appropriate times to send logging/tracing information.
+
+ @sa CoreInterface::CreateCore
+*/
+class DebugHandler {
+ public:
+ /*! @brief Method to handle error messages.
+
+ @param[in] tag \link DebugTag \endlink
+ @param[in] format \link message format with variable argument list \endlink
+ */
+ virtual void Error(DebugTag tag, const char *format, ...) = 0;
+
+ /*! @brief Method to handle warning messages.
+
+ @param[in] tag \link DebugTag \endlink
+ @param[in] format \link message format with variable argument list \endlink
+ */
+ virtual void Warning(DebugTag tag, const char *format, ...) = 0;
+
+ /*! @brief Method to handle informative messages.
+
+ @param[in] tag \link DebugTag \endlink
+ @param[in] format \link message format with variable argument list \endlink
+ */
+ virtual void Info(DebugTag tag, const char *format, ...) = 0;
+
+ /*! @brief Method to handle verbose messages.
+
+ @param[in] tag \link DebugTag \endlink
+ @param[in] format \link message format with variable argument list \endlink
+ */
+ virtual void Verbose(DebugTag tag, const char *format, ...) = 0;
+
+ /*! @brief Method to begin trace for a module/logical unit.
+
+ @param[in] class_name \link name of the class that the function belongs to \endlink
+ @param[in] function_name \link name of the function to be traced \endlink
+ @param[in] custom_string \link custom string for multiple traces within a function \endlink
+ */
+ virtual void BeginTrace(const char *class_name, const char *function_name,
+ const char *custom_string) = 0;
+
+ /*! @brief Method to end trace for a module/logical unit.
+ */
+ virtual void EndTrace() = 0;
+
+ protected:
+ virtual ~DebugHandler() { }
+};
+
+/*! @brief Scope tracer template class.
+
+ @details This class template implements the funtionality to capture the trace for function/
+ module. It starts the trace upon object creation and ends the trace upon object destruction.
+*/
+template <class T>
+class ScopeTracer {
+ public:
+ ScopeTracer(const char *class_name, const char *function_name) {
+ T::Get()->BeginTrace(class_name, function_name, "");
+ }
+
+ ~ScopeTracer() { T::Get()->EndTrace(); }
+};
+
+} // namespace sde
+
+#endif // __DEBUG_INTERFACE_H__
+
+
+
diff --git a/displayengine/include/core/display_interface.h b/displayengine/include/core/display_interface.h
old mode 100755
new mode 100644
index bdeb8a3..c054fae
--- a/displayengine/include/core/display_interface.h
+++ b/displayengine/include/core/display_interface.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -207,6 +207,19 @@
*/
virtual DisplayError Commit(LayerStack *layer_stack) = 0;
+ /*! @brief Method to flush any pending buffers/fences submitted previously via Commit() call.
+
+ @details Client shall call this method to request the Display Engine to release all buffers and
+ respective fences currently in use. This operation may result in a blank display on the panel
+ until a new frame is submitted for composition.
+
+ @return \link DisplayError \endlink
+
+ @sa Prepare
+ @sa Commit
+ */
+ virtual DisplayError Flush() = 0;
+
/*! @brief Method to get current state of the display device.
@param[out] state \link DisplayState \endlink
@@ -271,6 +284,14 @@
/*! @brief Method to set active configuration for variable properties of the display device.
+ @param[in] variable_info \link DisplayConfigVariableInfo \endlink
+
+ @return \link DisplayError \endlink
+ */
+ virtual DisplayError SetActiveConfig(DisplayConfigVariableInfo *variable_info) = 0;
+
+ /*! @brief Method to set active configuration for variable properties of the display device.
+
@param[in] index index of the mode corresponding to variable properties.
@return \link DisplayError \endlink
@@ -285,6 +306,14 @@
*/
virtual DisplayError SetVSyncState(bool enable) = 0;
+ /*! @brief Method to set idle timeout value. Idle fallback is disabled with timeout value 0.
+
+ @param[in] timeout value in milliseconds.
+
+ @return \link void \endlink
+ */
+ virtual void SetIdleTimeoutMs(uint32_t timeout_ms) = 0;
+
protected:
virtual ~DisplayInterface() { }
};
diff --git a/displayengine/include/core/layer_buffer.h b/displayengine/include/core/layer_buffer.h
old mode 100755
new mode 100644
index c069c60..9f7110a
--- a/displayengine/include/core/layer_buffer.h
+++ b/displayengine/include/core/layer_buffer.h
@@ -87,6 +87,17 @@
//!< factor of 2
//!< u(0), y(0), v(0), y(1), u(2), y(2), v(2), y(3)
//!< u(n-1), y(n-1), v(n-1), y(n)
+
+ /* All UBWC aligned formats. Any new format will be added towards end of this group to maintain
+ backward compatibility.
+ */
+ kFormatRGBA8888Ubwc = 0x400, //!< UBWC aligned RGBA8888 format
+
+ kFormatRGB565Ubwc, //!< UBWC aligned RGB565 format
+
+ kFormatYCbCr420SPVenusUbwc, //!< UBWC aligned Venus NV12 format
+
+ kFormatInvalid = 0xFFFFFFFF,
};
/*! @brief This structure defines a color sample plane belonging to a buffer format. RGB buffer
@@ -114,6 +125,7 @@
//!< video/ui buffer
uint64_t macro_tile : 1; //!< This flag shall be set by client to indicate that the buffer format
//!< is macro tiled.
+
LayerBufferFlags() : secure(0), video(0), macro_tile(0) { }
};
diff --git a/displayengine/include/core/layer_stack.h b/displayengine/include/core/layer_stack.h
old mode 100755
new mode 100644
index 67a812d..96ec20f
--- a/displayengine/include/core/layer_stack.h
+++ b/displayengine/include/core/layer_stack.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -32,6 +32,7 @@
#define __LAYER_STACK_H__
#include <stdint.h>
+#include <utils/constants.h>
#include "layer_buffer.h"
#include "sde_types.h"
@@ -123,7 +124,11 @@
uint64_t secure_present : 1; //!< This flag will be set to true, if the current layer stack
//!< contains secure layers.
- LayerStackFlags() : geometry_changed(0), skip_present(0), video_present(0), secure_present(0) { }
+ uint64_t animating : 1; //!< This flag shall be set by client to indicate that the current
+ //!< frame is animating.
+
+ LayerStackFlags()
+ : geometry_changed(0), skip_present(0), video_present(0), secure_present(0), animating(0) { }
};
/*! @brief This structure defines a rectanglular area inside a display layer.
@@ -137,6 +142,8 @@
float bottom; //!< Bottom-most pixel coordinate.
LayerRect() : left(0.0f), top(0.0f), right(0.0f), bottom(0.0f) { }
+
+ LayerRect(float l, float t, float r, float b) : left(l), top(t), right(r), bottom(b) { }
};
/*! @brief This structure defines an array of display layer rectangles.
@@ -194,8 +201,10 @@
LayerFlags flags; //!< Flags associated with this layer.
+ uint32_t frame_rate; //!< Rate at which frames are being updated for this layer.
+
Layer() : input_buffer(NULL), composition(kCompositionGPU), blending(kBlendingNone),
- plane_alpha(0) { }
+ plane_alpha(0), frame_rate(0) { }
};
/*! @brief This structure defines a layer stack that contains layers which need to be composed and
diff --git a/displayengine/include/core/sde_types.h b/displayengine/include/core/sde_types.h
old mode 100755
new mode 100644
index 6090889..0055306
--- a/displayengine/include/core/sde_types.h
+++ b/displayengine/include/core/sde_types.h
@@ -1,25 +1,30 @@
/*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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.
+* 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.
+* 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.
*/
/*! @file sde_types.h
@@ -48,59 +53,6 @@
kErrorTimeOut, //!< The operation has timed out to prevent client from waiting forever.
};
-/*! @brief This enum represents different modules/logical unit tags that a log message may be
- associated with. Client may use this to filter messages for dynamic logging.
-
- @sa DisplayLogHandler
-*/
-enum LogTag {
- kTagNone, //!< Log is not tagged. This type of logs should always be printed.
- kTagResources, //!< Log is tagged for resource management.
- kTagStrategy, //!< Log is tagged for strategy decisions.
-};
-
-/*! @brief Display log handler class.
-
- @details This class defines display log handler. The handle contains methods which client should
- implement to get different levels of logging from display engine. Display engine will call into
- these methods at appropriate times to send logging information.
-
- @sa CoreInterface::CreateCore
-*/
-class LogHandler {
- public:
- /*! @brief Method to handle error messages.
-
- @param[in] tag \link LogTag \endlink
- @param[in] format \link message format with variable argument list \endlink
- */
- virtual void Error(LogTag tag, const char *format, ...) = 0;
-
- /*! @brief Method to handle warning messages.
-
- @param[in] tag \link LogTag \endlink
- @param[in] format \link message format with variable argument list \endlink
- */
- virtual void Warning(LogTag tag, const char *format, ...) = 0;
-
- /*! @brief Method to handle informative messages.
-
- @param[in] tag \link LogTag \endlink
- @param[in] format \link message format with variable argument list \endlink
- */
- virtual void Info(LogTag tag, const char *format, ...) = 0;
-
- /*! @brief Method to handle verbose messages.
-
- @param[in] tag \link LogTag \endlink
- @param[in] format \link message format with variable argument list \endlink
- */
- virtual void Verbose(LogTag tag, const char *format, ...) = 0;
-
- protected:
- virtual ~LogHandler() { }
-};
-
/*! @brief This structure is defined for client and library compatibility check purpose only. This
structure is used in SDE_VERSION_TAG definition only. Client should not refer it directly for
any purpose.
diff --git a/displayengine/include/utils/constants.h b/displayengine/include/utils/constants.h
index a7b9f0f..6f98b07 100644
--- a/displayengine/include/utils/constants.h
+++ b/displayengine/include/utils/constants.h
@@ -25,6 +25,8 @@
#ifndef __CONSTANTS_H__
#define __CONSTANTS_H__
+#include <stdlib.h>
+
#define LIKELY(exp) __builtin_expect((exp) != 0, true)
#define UNLIKELY(exp) __builtin_expect((exp) != 0, false)
@@ -47,7 +49,27 @@
#define SET_BIT(value, bit) (value |= (1 << (bit)))
#define CLEAR_BIT(value, bit) (value &= (~(1 << (bit))))
#define IS_BIT_SET(value, bit) (value & (1 << (bit)))
+
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+template <class T>
+inline void Swap(T &a, T &b) {
+ T c(a);
+ a = b;
+ b = c;
+}
+
+// factor value should be in powers of 2(eg: 1, 2, 4, 8)
+template <class T1, class T2>
+inline T1 FloorToMultipleOf(const T1 &value, const T2 &factor) {
+ return (T1)(value & (~(factor - 1)));
+}
+
+template <class T1, class T2>
+inline T1 CeilToMultipleOf(const T1 &value, const T2 &factor) {
+ return (T1)((value + (factor - 1)) & (~(factor - 1)));
+}
namespace sde {
diff --git a/displayengine/include/utils/debug.h b/displayengine/include/utils/debug.h
old mode 100755
new mode 100644
index 99d3968..65079a9
--- a/displayengine/include/utils/debug.h
+++ b/displayengine/include/utils/debug.h
@@ -1,25 +1,30 @@
/*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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.
+* 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.
+* 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 __DEBUG_H__
@@ -27,9 +32,10 @@
#include <stdint.h>
#include <core/sde_types.h>
+#include <core/debug_interface.h>
-#define DLOG(tag, method, format, ...) Debug::GetLogHandler()->method(tag, \
- __CLASS__ "::%s: " format, __FUNCTION__, ##__VA_ARGS__)
+#define DLOG(tag, method, format, ...) Debug::Get()->method(tag, __CLASS__ "::%s: " format, \
+ __FUNCTION__, ##__VA_ARGS__)
#define DLOGE_IF(tag, format, ...) DLOG(tag, Error, format, ##__VA_ARGS__)
#define DLOGW_IF(tag, format, ...) DLOG(tag, Warning, format, ##__VA_ARGS__)
@@ -41,31 +47,41 @@
#define DLOGI(format, ...) DLOGI_IF(kTagNone, format, ##__VA_ARGS__)
#define DLOGV(format, ...) DLOGV_IF(kTagNone, format, ##__VA_ARGS__)
+#define DTRACE_BEGIN(custom_string) Debug::Get()->BeginTrace(__CLASS__, __FUNCTION__, custom_string)
+#define DTRACE_END() Debug::Get()->EndTrace()
+#define DTRACE_SCOPED() ScopeTracer <Debug> scope_tracer(__CLASS__, __FUNCTION__)
+
namespace sde {
class Debug {
public:
- static inline void SetLogHandler(LogHandler *log_handler) { debug_.log_handler_ = log_handler; }
- static inline LogHandler* GetLogHandler() { return debug_.log_handler_; }
+ static inline void SetDebugHandler(DebugHandler *debug_handler) {
+ debug_.debug_handler_ = debug_handler;
+ }
+ static inline DebugHandler* Get() { return debug_.debug_handler_; }
static inline bool IsVirtualDriver() { return debug_.virtual_driver_; }
static uint32_t GetSimulationFlag();
static uint32_t GetHDMIResolution();
+ static uint32_t GetIdleTimeoutMs();
private:
Debug();
- // By default, drop any log messages coming from Display Engine. It will be overriden by Display
- // Engine client when core is successfully initialized.
- class DefaultLogHandler : public LogHandler {
+ // By default, drop any log messages/traces coming from Display Engine. It will be overriden by
+ // Display Engine client when core is successfully initialized.
+ class DefaultDebugHandler : public DebugHandler {
public:
- virtual void Error(LogTag /*tag*/, const char */*format*/, ...) { }
- virtual void Warning(LogTag /*tag*/, const char */*format*/, ...) { }
- virtual void Info(LogTag /*tag*/, const char */*format*/, ...) { }
- virtual void Verbose(LogTag /*tag*/, const char */*format*/, ...) { }
+ virtual void Error(DebugTag /*tag*/, const char */*format*/, ...) { }
+ virtual void Warning(DebugTag /*tag*/, const char */*format*/, ...) { }
+ virtual void Info(DebugTag /*tag*/, const char */*format*/, ...) { }
+ virtual void Verbose(DebugTag /*tag*/, const char */*format*/, ...) { }
+ virtual void BeginTrace(const char */*class_name*/, const char */*function_name*/,
+ const char */*custom_string*/) { }
+ virtual void EndTrace() { }
};
- DefaultLogHandler default_log_handler_;
- LogHandler *log_handler_;
+ DefaultDebugHandler default_debug_handler_;
+ DebugHandler *debug_handler_;
bool virtual_driver_;
static Debug debug_;
};
diff --git a/displayengine/include/utils/locker.h b/displayengine/include/utils/locker.h
index 2c1ef9a..549a282 100644
--- a/displayengine/include/utils/locker.h
+++ b/displayengine/include/utils/locker.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -28,7 +28,11 @@
#include <stdint.h>
#include <pthread.h>
-#define SCOPE_LOCK(locker) Locker::ScopeLock scopeLock(locker)
+#define SCOPE_LOCK(locker) Locker::ScopeLock lock(locker)
+#define SEQUENCE_ENTRY_SCOPE_LOCK(locker) Locker::SequenceEntryScopeLock lock(locker)
+#define SEQUENCE_EXIT_SCOPE_LOCK(locker) Locker::SequenceExitScopeLock lock(locker)
+#define SEQUENCE_WAIT_SCOPE_LOCK(locker) Locker::SequenceWaitScopeLock lock(locker)
+#define SEQUENCE_CANCEL_SCOPE_LOCK(locker) Locker::SequenceCancelScopeLock lock(locker)
namespace sde {
@@ -48,7 +52,78 @@
Locker &locker_;
};
- Locker() {
+ class SequenceEntryScopeLock {
+ public:
+ explicit SequenceEntryScopeLock(Locker& locker) : locker_(locker) {
+ locker_.Lock();
+ locker_.sequence_wait_ = 1;
+ }
+
+ ~SequenceEntryScopeLock() {
+ locker_.Unlock();
+ }
+
+ private:
+ Locker &locker_;
+ };
+
+ class SequenceExitScopeLock {
+ public:
+ explicit SequenceExitScopeLock(Locker& locker) : locker_(locker) {
+ locker_.Lock();
+ locker_.sequence_wait_ = 0;
+ }
+
+ ~SequenceExitScopeLock() {
+ locker_.Broadcast();
+ locker_.Unlock();
+ }
+
+ private:
+ Locker &locker_;
+ };
+
+ class SequenceWaitScopeLock {
+ public:
+ explicit SequenceWaitScopeLock(Locker& locker) : locker_(locker), error_(false) {
+ locker_.Lock();
+
+ if (locker_.sequence_wait_ == 1) {
+ locker_.Wait();
+ error_ = (locker_.sequence_wait_ == -1);
+ }
+ }
+
+ ~SequenceWaitScopeLock() {
+ locker_.Unlock();
+ }
+
+ bool IsError() {
+ return error_;
+ }
+
+ private:
+ Locker &locker_;
+ bool error_;
+ };
+
+ class SequenceCancelScopeLock {
+ public:
+ explicit SequenceCancelScopeLock(Locker& locker) : locker_(locker) {
+ locker_.Lock();
+ locker_.sequence_wait_ = -1;
+ }
+
+ ~SequenceCancelScopeLock() {
+ locker_.Broadcast();
+ locker_.Unlock();
+ }
+
+ private:
+ Locker &locker_;
+ };
+
+ Locker() : sequence_wait_(0) {
pthread_mutex_init(&mutex_, 0);
pthread_cond_init(&condition_, 0);
}
@@ -63,7 +138,7 @@
void Signal() { pthread_cond_signal(&condition_); }
void Broadcast() { pthread_cond_broadcast(&condition_); }
void Wait() { pthread_cond_wait(&condition_, &mutex_); }
- int WaitFinite(long int ms) {
+ int WaitFinite(int ms) {
struct timespec ts;
struct timeval tv;
gettimeofday(&tv, NULL);
@@ -77,6 +152,11 @@
private:
pthread_mutex_t mutex_;
pthread_cond_t condition_;
+ int sequence_wait_; // This flag is set to 1 on sequence entry, 0 on exit, and -1 on cancel.
+ // Some routines will wait for sequence of function calls to finish
+ // so that capturing a transitionary snapshot of context is prevented.
+ // If flag is set to -1, these routines will exit without doing any
+ // further processing.
};
} // namespace sde
diff --git a/displayengine/include/utils/rect.h b/displayengine/include/utils/rect.h
new file mode 100644
index 0000000..f009cfd
--- /dev/null
+++ b/displayengine/include/utils/rect.h
@@ -0,0 +1,48 @@
+/*
+* Copyright (c) 2015, 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 __RECT_H__
+#define __RECT_H__
+
+#include <stdint.h>
+#include <core/sde_types.h>
+#include <core/layer_stack.h>
+#include <utils/debug.h>
+
+namespace sde {
+
+ bool IsValidRect(const LayerRect &rect);
+ LayerRect GetIntersection(const LayerRect &rect1, const LayerRect &rect2);
+ void LogRect(DebugTag debug_tag, const char *prefix, const LayerRect &roi);
+ void NormalizeRect(const uint32_t &factor, LayerRect *rect);
+
+} // namespace sde
+
+#endif // __RECT_H__
+
diff --git a/displayengine/libs/core/Android.mk b/displayengine/libs/core/Android.mk
index 92569a5..56167e1 100644
--- a/displayengine/libs/core/Android.mk
+++ b/displayengine/libs/core/Android.mk
@@ -4,7 +4,8 @@
LOCAL_MODULE := libsde
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := hardware/qcom/display/displayengine/include/ \
- $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+ $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include \
+ $(TARGET_OUT_HEADERS)/scalar/inc
LOCAL_CFLAGS := -Wno-missing-field-initializers -Wno-unused-parameter \
-Wconversion -Wall -Werror \
-DLOG_TAG=\"SDE\"
@@ -23,6 +24,7 @@
offline_ctrl.cpp \
hw_interface.cpp \
hw_framebuffer.cpp \
- dump_impl.cpp
+ dump_impl.cpp \
+ buffer_manager.cpp
include $(BUILD_SHARED_LIBRARY)
diff --git a/displayengine/libs/core/buffer_manager.cpp b/displayengine/libs/core/buffer_manager.cpp
new file mode 100644
index 0000000..95c310a
--- /dev/null
+++ b/displayengine/libs/core/buffer_manager.cpp
@@ -0,0 +1,293 @@
+/*
+* Copyright (c) 2015, 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/debug.h>
+#include <utils/constants.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+
+#include "buffer_manager.h"
+
+#define __CLASS__ "BufferManager"
+
+namespace sde {
+
+// --------------------------------- BufferSlot Implementation -------------------------------------
+
+DisplayError BufferManager::BufferSlot::Init() {
+ uint32_t buffer_count = hw_buffer_info.buffer_config.buffer_count;
+ size_t buffer_size = hw_buffer_info.alloc_buffer_info.size;
+
+ release_fd = new int[buffer_count];
+ if (release_fd == NULL) {
+ return kErrorMemory;
+ }
+
+ offset = new uint32_t[buffer_count];
+ if (offset == NULL) {
+ delete[] release_fd;
+ release_fd = NULL;
+ return kErrorMemory;
+ }
+
+ for (uint32_t idx = 0; idx < buffer_count; idx++) {
+ release_fd[idx] = -1;
+ offset[idx] = UINT32((buffer_size / buffer_count) * idx);
+ }
+ curr_index = 0;
+
+ return kErrorNone;
+}
+
+DisplayError BufferManager::BufferSlot::Deinit() {
+ uint32_t buffer_count = hw_buffer_info.buffer_config.buffer_count;
+
+ for (uint32_t idx = 0; idx < buffer_count; idx++) {
+ if (release_fd[idx] >= 0) {
+ close(release_fd[idx]);
+ release_fd[idx] = -1;
+ }
+ }
+
+ if (offset) {
+ delete[] offset;
+ offset = NULL;
+ }
+
+ if (release_fd) {
+ delete[] release_fd;
+ release_fd = NULL;
+ }
+
+ state = kBufferSlotFree;
+ hw_buffer_info = HWBufferInfo();
+
+ return kErrorNone;
+}
+
+// BufferManager State Transition
+// *******************************************************
+// Current State * Next State
+// *****************************************
+// * FREE READY ACQUIRED
+// *******************************************************
+// FREE * NA NA GetNextBuffer()
+// READY * Stop() NA GetNextBuffer()
+// ACQUIRED * NA Start() NA
+//********************************************************
+
+// ------------------------------- BufferManager Implementation ------------------------------------
+
+BufferManager::BufferManager(BufferAllocator *buffer_allocator,
+ BufferSyncHandler *buffer_sync_handler)
+ : buffer_allocator_(buffer_allocator), buffer_sync_handler_(buffer_sync_handler),
+ num_used_slot_(0) {
+}
+
+void BufferManager::Start() {
+ uint32_t slot = 0, num_ready_slot = 0;
+
+ // Change the state of acquired buffer_slot to kBufferSlotReady
+ while ((num_ready_slot < num_used_slot_) && (slot < kMaxBufferSlotCount)) {
+ if (buffer_slot_[slot].state == kBufferSlotFree) {
+ slot++;
+ continue;
+ }
+
+ buffer_slot_[slot++].state = kBufferSlotReady;
+ num_ready_slot++;
+ }
+}
+
+DisplayError BufferManager::GetNextBuffer(HWBufferInfo *hw_buffer_info) {
+ DisplayError error = kErrorNone;
+ const BufferConfig &buffer_config = hw_buffer_info->buffer_config;
+
+ DLOGI_IF(kTagBufferManager, "Input: w = %d h = %d f = %d", buffer_config.width,
+ buffer_config.height, buffer_config.format);
+
+ uint32_t free_slot = num_used_slot_;
+ uint32_t acquired_slot = kMaxBufferSlotCount;
+ uint32_t num_used_slot = 0;
+
+ // First look for a buffer slot in ready state, if no buffer slot found in ready state matching
+ // with current input config, assign a buffer slot in free state and allocate buffers for it.
+ for (uint32_t slot = 0; slot < kMaxBufferSlotCount && num_used_slot < num_used_slot_; slot++) {
+ HWBufferInfo &hw_buffer_info = buffer_slot_[slot].hw_buffer_info;
+
+ if (buffer_slot_[slot].state == kBufferSlotFree) {
+ free_slot = slot;
+ } else {
+ if ((buffer_slot_[slot].state == kBufferSlotReady)) {
+ if ((::memcmp(&buffer_config, &hw_buffer_info.buffer_config, sizeof(BufferConfig)) == 0)) {
+ buffer_slot_[slot].state = kBufferSlotAcquired;
+ acquired_slot = slot;
+ break;
+ }
+ }
+ num_used_slot++;
+ }
+ }
+
+ // If the input config does not match with existing config, then allocate buffers for the new
+ // buffer slot and change the state to kBufferSlotAcquired
+ if (acquired_slot == kMaxBufferSlotCount) {
+ if (free_slot >= kMaxBufferSlotCount) {
+ return kErrorMemory;
+ }
+
+ buffer_slot_[free_slot].hw_buffer_info.buffer_config = hw_buffer_info->buffer_config;
+
+ error = buffer_allocator_->AllocateBuffer(&buffer_slot_[free_slot].hw_buffer_info);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ buffer_slot_[free_slot].Init();
+ buffer_slot_[free_slot].state = kBufferSlotAcquired;
+ acquired_slot = free_slot;
+ num_used_slot_++;
+
+ DLOGI_IF(kTagBufferManager, "Allocate Buffer acquired_slot = %d ", acquired_slot);
+ }
+
+ const AllocatedBufferInfo &alloc_buffer_info =
+ buffer_slot_[acquired_slot].hw_buffer_info.alloc_buffer_info;
+ uint32_t curr_index = buffer_slot_[acquired_slot].curr_index;
+
+ // Wait for the release fence fd before buffer slot being given to the client.
+ buffer_sync_handler_->SyncWait(buffer_slot_[acquired_slot].release_fd[curr_index]);
+ buffer_slot_[acquired_slot].release_fd[curr_index] = -1;
+
+ hw_buffer_info->output_buffer.width = buffer_config.width;
+ hw_buffer_info->output_buffer.height = buffer_config.height;
+ hw_buffer_info->output_buffer.format = buffer_config.format;
+ hw_buffer_info->output_buffer.flags.secure = buffer_config.secure;
+
+ hw_buffer_info->output_buffer.planes[0].stride = alloc_buffer_info.stride;
+ hw_buffer_info->output_buffer.planes[0].fd = alloc_buffer_info.fd;
+ hw_buffer_info->output_buffer.planes[0].offset = buffer_slot_[acquired_slot].offset[curr_index];
+ hw_buffer_info->slot = acquired_slot;
+
+ DLOGI_IF(kTagBufferManager, "Output: w = %d h = %d f = %d session_id %d acquired slot = %d " \
+ "num_used_slot %d curr_index = %d offset %d", hw_buffer_info->output_buffer.width,
+ hw_buffer_info->output_buffer.height, hw_buffer_info->output_buffer.format,
+ hw_buffer_info->session_id, acquired_slot, num_used_slot_, curr_index,
+ hw_buffer_info->output_buffer.planes[0].offset);
+
+ return kErrorNone;
+}
+
+DisplayError BufferManager::Stop(int *session_ids) {
+ DisplayError error = kErrorNone;
+ uint32_t slot = 0, count = 0;
+
+ // Free all the buffer slots which were not acquired in the current cycle and deallocate the
+ // buffers associated with it.
+ while ((num_used_slot_ > 0) && (slot < kMaxBufferSlotCount)) {
+ if (buffer_slot_[slot].state == kBufferSlotReady) {
+ if (buffer_slot_[slot].hw_buffer_info.session_id != -1) {
+ session_ids[count++] = buffer_slot_[slot].hw_buffer_info.session_id;
+ }
+
+ error = FreeBufferSlot(slot);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ num_used_slot_--;
+ }
+ slot++;
+ }
+
+ session_ids[count] = -1;
+
+ return kErrorNone;
+}
+
+DisplayError BufferManager::SetReleaseFd(uint32_t slot, int fd) {
+ if ((slot >= kMaxBufferSlotCount) || (buffer_slot_[slot].state != kBufferSlotAcquired)) {
+ DLOGE("Invalid Parameters slot %d state %s", slot, buffer_slot_[slot].state);
+ kErrorParameters;
+ }
+
+ uint32_t &curr_index = buffer_slot_[slot].curr_index;
+ const HWBufferInfo &hw_buffer_info = buffer_slot_[slot].hw_buffer_info;
+ uint32_t buffer_count = hw_buffer_info.buffer_config.buffer_count;
+
+ // 1. Store the release fence fd, so that buffer manager waits for the release fence fd to be
+ // signaled and gives the buffer slot to the client.
+ // 2. Modify the curr_index to point to next buffer.
+ buffer_slot_[slot].release_fd[curr_index] = fd;
+ curr_index = (curr_index + 1) % buffer_count;
+
+ DLOGI_IF(kTagBufferManager, "w = %d h = %d f = %d session_id %d slot = %d curr_index = %d " \
+ "sync fd %d", hw_buffer_info.output_buffer.width, hw_buffer_info.output_buffer.height,
+ hw_buffer_info.output_buffer.format, hw_buffer_info.session_id, slot, curr_index, fd);
+
+ return kErrorNone;
+}
+
+
+DisplayError BufferManager::SetSessionId(uint32_t slot, int session_id) {
+ if ((slot >= kMaxBufferSlotCount) || (buffer_slot_[slot].state != kBufferSlotAcquired)) {
+ DLOGE("Invalid Parameters slot %d state %s", slot, buffer_slot_[slot].state);
+ kErrorParameters;
+ }
+
+ HWBufferInfo *hw_buffer_info = &buffer_slot_[slot].hw_buffer_info;
+
+ hw_buffer_info->session_id = session_id;
+
+ DLOGI_IF(kTagBufferManager, "w = %d h = %d f = %d session_id %d slot = %d",
+ hw_buffer_info->output_buffer.width, hw_buffer_info->output_buffer.height,
+ hw_buffer_info->output_buffer.format, hw_buffer_info->session_id, slot);
+
+ return kErrorNone;
+}
+
+DisplayError BufferManager::FreeBufferSlot(uint32_t slot) {
+ DisplayError error = kErrorNone;
+
+ HWBufferInfo *hw_buffer_info = &buffer_slot_[slot].hw_buffer_info;
+
+ error = buffer_allocator_->FreeBuffer(hw_buffer_info);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ DLOGI_IF(kTagBufferManager, "session_id %d slot = %d num_used_slot %d",
+ hw_buffer_info->session_id, slot, num_used_slot_);
+
+ buffer_slot_[slot].Deinit();
+
+ return kErrorNone;
+}
+
+} // namespace sde
diff --git a/displayengine/libs/core/buffer_manager.h b/displayengine/libs/core/buffer_manager.h
new file mode 100644
index 0000000..29bcd03
--- /dev/null
+++ b/displayengine/libs/core/buffer_manager.h
@@ -0,0 +1,82 @@
+/*
+* Copyright (c) 2015, 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 __BUFFER_MANAGER_H__
+#define __BUFFER_MANAGER_H__
+
+#include <utils/locker.h>
+#include <core/buffer_allocator.h>
+#include "hw_interface.h"
+
+namespace sde {
+
+class BufferManager {
+ public:
+ BufferManager(BufferAllocator *buffer_allocator, BufferSyncHandler *buffer_sync_handler);
+
+ void Start();
+ DisplayError GetNextBuffer(HWBufferInfo *hw_buffer_info);
+ DisplayError Stop(int *session_ids);
+ DisplayError SetReleaseFd(uint32_t slot, int fd);
+ DisplayError SetSessionId(uint32_t slot, int session_id);
+
+ private:
+ static const uint32_t kMaxBufferSlotCount = 32;
+
+ enum kBufferSlotState {
+ kBufferSlotFree = 0,
+ kBufferSlotReady = 1,
+ kBufferSlotAcquired = 2,
+ };
+
+ struct BufferSlot {
+ HWBufferInfo hw_buffer_info;
+ kBufferSlotState state;
+ int *release_fd;
+ uint32_t *offset;
+ uint32_t curr_index;
+
+ BufferSlot() : state(kBufferSlotFree), release_fd(NULL), offset(NULL), curr_index(0) { }
+ DisplayError Init();
+ DisplayError Deinit();
+ };
+
+ DisplayError FreeBufferSlot(uint32_t index);
+
+ BufferSlot buffer_slot_[kMaxBufferSlotCount];
+ BufferAllocator *buffer_allocator_;
+ BufferSyncHandler *buffer_sync_handler_;
+ uint32_t num_used_slot_;
+};
+
+} // namespace sde
+
+#endif // __BUFFER_MANAGER_H__
+
+
diff --git a/displayengine/libs/core/comp_manager.cpp b/displayengine/libs/core/comp_manager.cpp
index 40191e5..7e888ee 100644
--- a/displayengine/libs/core/comp_manager.cpp
+++ b/displayengine/libs/core/comp_manager.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -25,6 +25,7 @@
#include <dlfcn.h>
#include <utils/constants.h>
#include <utils/debug.h>
+#include <core/buffer_allocator.h>
#include "comp_manager.h"
#include "strategy_default.h"
@@ -38,12 +39,13 @@
registered_displays_(0), configured_displays_(0), safe_mode_(false) {
}
-DisplayError CompManager::Init(const HWResourceInfo &hw_res_info) {
+DisplayError CompManager::Init(const HWResourceInfo &hw_res_info, BufferAllocator *buffer_allocator,
+ BufferSyncHandler *buffer_sync_handler) {
SCOPE_LOCK(locker_);
DisplayError error = kErrorNone;
- error = res_mgr_.Init(hw_res_info);
+ error = res_mgr_.Init(hw_res_info, buffer_allocator, buffer_sync_handler);
if (error != kErrorNone) {
return error;
}
@@ -108,6 +110,7 @@
&display_comp_ctx->strategy_intf) != kErrorNone) {
DLOGW("Unable to create strategy interface");
delete display_comp_ctx;
+ display_comp_ctx = NULL;
return kErrorUndefined;
}
@@ -115,15 +118,22 @@
if (error != kErrorNone) {
destroy_strategy_intf_(display_comp_ctx->strategy_intf);
delete display_comp_ctx;
+ display_comp_ctx = NULL;
return error;
}
SET_BIT(registered_displays_, type);
display_comp_ctx->display_type = type;
*display_ctx = display_comp_ctx;
- // New display device has been added, so move the composition mode to safe mode until unless
+ // New non-primary display device has been added, so move the composition mode to safe mode until
// resources for the added display is configured properly.
- safe_mode_ = true;
+ if (type != kPrimary) {
+ safe_mode_ = true;
+ }
+
+ DLOGV_IF(kTagCompManager, "registered display bit mask 0x%x, configured display bit mask 0x%x, " \
+ "display type %d", registered_displays_, configured_displays_,
+ display_comp_ctx->display_type);
return kErrorNone;
}
@@ -140,7 +150,14 @@
CLEAR_BIT(registered_displays_, display_comp_ctx->display_type);
CLEAR_BIT(configured_displays_, display_comp_ctx->display_type);
- delete display_comp_ctx;
+ DLOGV_IF(kTagCompManager, "registered display bit mask 0x%x, configured display bit mask 0x%x, " \
+ "display type %d", registered_displays_, configured_displays_,
+ display_comp_ctx->display_type);
+
+ if (display_comp_ctx) {
+ delete display_comp_ctx;
+ display_comp_ctx = NULL;
+ }
return kErrorNone;
}
@@ -161,6 +178,10 @@
if (display_comp_ctx->remaining_strategies != display_comp_ctx->max_strategies) {
constraints->safe_mode = true;
}
+
+ if (display_comp_ctx->idle_fallback) {
+ constraints->safe_mode = true;
+ }
}
void CompManager::PrePrepare(Handle display_ctx, HWLayers *hw_layers) {
@@ -170,6 +191,13 @@
display_comp_ctx->strategy_intf->Start(&hw_layers->info,
&display_comp_ctx->max_strategies);
display_comp_ctx->remaining_strategies = display_comp_ctx->max_strategies;
+
+ // Avoid idle fallback, if there is only one app layer.
+ // TODO(user): App layer count will change for hybrid composition
+ uint32_t app_layer_count = hw_layers->info.stack->layer_count - 1;
+ if (!display_comp_ctx->idle_fallback && app_layer_count > 1) {
+ display_comp_ctx->handle_idle_timeout = true;
+ }
}
DisplayError CompManager::Prepare(Handle display_ctx, HWLayers *hw_layers) {
@@ -212,16 +240,27 @@
return error;
}
-void CompManager::PostPrepare(Handle display_ctx, HWLayers *hw_layers) {
+DisplayError CompManager::PostPrepare(Handle display_ctx, HWLayers *hw_layers) {
SCOPE_LOCK(locker_);
DisplayCompositionContext *display_comp_ctx =
reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+ Handle &display_resource_ctx = display_comp_ctx->display_resource_ctx;
+
+ DisplayError error = kErrorNone;
+ error = res_mgr_.PostPrepare(display_resource_ctx, hw_layers);
+ if (error != kErrorNone) {
+ return error;
+ }
+
display_comp_ctx->strategy_intf->Stop();
+
+ return kErrorNone;
}
-void CompManager::PostCommit(Handle display_ctx, HWLayers *hw_layers) {
+DisplayError CompManager::PostCommit(Handle display_ctx, HWLayers *hw_layers) {
SCOPE_LOCK(locker_);
+ DisplayError error = kErrorNone;
DisplayCompositionContext *display_comp_ctx =
reinterpret_cast<DisplayCompositionContext *>(display_ctx);
SET_BIT(configured_displays_, display_comp_ctx->display_type);
@@ -229,7 +268,18 @@
safe_mode_ = false;
}
- res_mgr_.PostCommit(display_comp_ctx->display_resource_ctx, hw_layers);
+ error = res_mgr_.PostCommit(display_comp_ctx->display_resource_ctx, hw_layers);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ display_comp_ctx->idle_fallback = false;
+
+ DLOGV_IF(kTagCompManager, "registered display bit mask 0x%x, configured display bit mask 0x%x, " \
+ "display type %d", registered_displays_, configured_displays_,
+ display_comp_ctx->display_type);
+
+ return kErrorNone;
}
void CompManager::Purge(Handle display_ctx) {
@@ -241,6 +291,32 @@
res_mgr_.Purge(display_comp_ctx->display_resource_ctx);
}
+bool CompManager::ProcessIdleTimeout(Handle display_ctx) {
+ SCOPE_LOCK(locker_);
+
+ DisplayCompositionContext *display_comp_ctx =
+ reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+
+ if (!display_comp_ctx) {
+ return false;
+ }
+
+ // 1. handle_idle_timeout flag is set to true on start of every draw call, if the current
+ // composition is not due to idle fallback.
+ // 2. idle_fallback flag will be set only if handle_idle_timeout flag is true and there is no
+ // update to the screen for specified amount of time.
+ // 3. handle_idle_timeout flag helps us handle the very first idle timeout event and
+ // ignore the next idle timeout event on consecutive two idle timeout events.
+ if (display_comp_ctx->handle_idle_timeout) {
+ display_comp_ctx->idle_fallback = true;
+ display_comp_ctx->handle_idle_timeout = false;
+
+ return true;
+ }
+
+ return false;
+}
+
void CompManager::AppendDump(char *buffer, uint32_t length) {
SCOPE_LOCK(locker_);
}
diff --git a/displayengine/libs/core/comp_manager.h b/displayengine/libs/core/comp_manager.h
index aed357b..24a0fff 100644
--- a/displayengine/libs/core/comp_manager.h
+++ b/displayengine/libs/core/comp_manager.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -36,16 +36,18 @@
class CompManager : public DumpImpl {
public:
CompManager();
- DisplayError Init(const HWResourceInfo &hw_res_info_);
+ DisplayError Init(const HWResourceInfo &hw_res_info_, BufferAllocator *buffer_allocator,
+ BufferSyncHandler *buffer_sync_handler_);
DisplayError Deinit();
DisplayError RegisterDisplay(DisplayType type, const HWDisplayAttributes &attributes,
Handle *res_mgr_hnd);
DisplayError UnregisterDisplay(Handle res_mgr_hnd);
void PrePrepare(Handle display_ctx, HWLayers *hw_layers);
DisplayError Prepare(Handle display_ctx, HWLayers *hw_layers);
- void PostPrepare(Handle display_ctx, HWLayers *hw_layers);
- void PostCommit(Handle display_ctx, HWLayers *hw_layers);
+ DisplayError PostPrepare(Handle display_ctx, HWLayers *hw_layers);
+ DisplayError PostCommit(Handle display_ctx, HWLayers *hw_layers);
void Purge(Handle display_ctx);
+ bool ProcessIdleTimeout(Handle display_ctx);
// DumpImpl method
virtual void AppendDump(char *buffer, uint32_t length);
@@ -60,6 +62,12 @@
DisplayType display_type;
uint32_t max_strategies;
uint32_t remaining_strategies;
+ bool idle_fallback;
+ bool handle_idle_timeout;
+
+ DisplayCompositionContext()
+ : display_resource_ctx(NULL), display_type(kPrimary), max_strategies(0),
+ remaining_strategies(0), idle_fallback(false), handle_idle_timeout(true) { }
};
Locker locker_;
diff --git a/displayengine/libs/core/core_impl.cpp b/displayengine/libs/core/core_impl.cpp
old mode 100755
new mode 100644
index 0669f9f..bd6ab9a
--- a/displayengine/libs/core/core_impl.cpp
+++ b/displayengine/libs/core/core_impl.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -35,8 +35,10 @@
namespace sde {
-CoreImpl::CoreImpl(CoreEventHandler *event_handler)
- : event_handler_(event_handler), hw_intf_(NULL) {
+CoreImpl::CoreImpl(CoreEventHandler *event_handler, BufferAllocator *buffer_allocator,
+ BufferSyncHandler *buffer_sync_handler)
+ : event_handler_(event_handler), buffer_allocator_(buffer_allocator),
+ buffer_sync_handler_(buffer_sync_handler), hw_intf_(NULL) {
}
DisplayError CoreImpl::Init() {
@@ -44,7 +46,7 @@
DisplayError error = kErrorNone;
- error = HWInterface::Create(&hw_intf_);
+ error = HWInterface::Create(&hw_intf_, buffer_sync_handler_);
if (UNLIKELY(error != kErrorNone)) {
return error;
}
@@ -56,7 +58,7 @@
return error;
}
- error = comp_mgr_.Init(hw_res_info);
+ error = comp_mgr_.Init(hw_res_info, buffer_allocator_, buffer_sync_handler_);
if (UNLIKELY(error != kErrorNone)) {
HWInterface::Destroy(hw_intf_);
return error;
@@ -83,7 +85,7 @@
}
DisplayError CoreImpl::CreateDisplay(DisplayType type, DisplayEventHandler *event_handler,
- DisplayInterface **intf) {
+ DisplayInterface **intf) {
SCOPE_LOCK(locker_);
if (UNLIKELY(!event_handler || !intf)) {
@@ -93,15 +95,15 @@
DisplayBase *display_base = NULL;
switch (type) {
case kPrimary:
- display_base = new DisplayPrimary(event_handler, hw_intf_, &comp_mgr_);
+ display_base = new DisplayPrimary(event_handler, hw_intf_, &comp_mgr_, &offline_ctrl_);
break;
case kHDMI:
- display_base = new DisplayHDMI(event_handler, hw_intf_, &comp_mgr_);
+ display_base = new DisplayHDMI(event_handler, hw_intf_, &comp_mgr_, &offline_ctrl_);
break;
case kVirtual:
- display_base = new DisplayVirtual(event_handler, hw_intf_, &comp_mgr_);
+ display_base = new DisplayVirtual(event_handler, hw_intf_, &comp_mgr_, &offline_ctrl_);
break;
default:
@@ -116,6 +118,7 @@
DisplayError error = display_base->Init();
if (UNLIKELY(error != kErrorNone)) {
delete display_base;
+ display_base = NULL;
return error;
}
@@ -133,6 +136,7 @@
DisplayBase *display_base = static_cast<DisplayBase *>(intf);
display_base->Deinit();
delete display_base;
+ display_base = NULL;
return kErrorNone;
}
diff --git a/displayengine/libs/core/core_impl.h b/displayengine/libs/core/core_impl.h
index ad86c60..e289a23 100644
--- a/displayengine/libs/core/core_impl.h
+++ b/displayengine/libs/core/core_impl.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -42,7 +42,8 @@
// This class implements display core interface revision 1.0.
static const uint16_t kRevision = SET_REVISION(1, 0);
- explicit CoreImpl(CoreEventHandler *event_handler);
+ CoreImpl(CoreEventHandler *event_handler, BufferAllocator *buffer_allocator,
+ BufferSyncHandler *buffer_sync_handler);
virtual ~CoreImpl() { }
// This method returns the interface revision for the current display core object.
@@ -59,6 +60,8 @@
protected:
Locker locker_;
CoreEventHandler *event_handler_;
+ BufferAllocator *buffer_allocator_;
+ BufferSyncHandler *buffer_sync_handler_;
HWInterface *hw_intf_;
CompManager comp_mgr_;
OfflineCtrl offline_ctrl_;
diff --git a/displayengine/libs/core/core_interface.cpp b/displayengine/libs/core/core_interface.cpp
old mode 100755
new mode 100644
index fb8700a..c982b4d
--- a/displayengine/libs/core/core_interface.cpp
+++ b/displayengine/libs/core/core_interface.cpp
@@ -1,30 +1,36 @@
/*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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.
+* 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.
+* 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/locker.h>
#include <utils/constants.h>
#include <utils/debug.h>
+#include <core/buffer_sync_handler.h>
#include "core_impl.h"
@@ -45,11 +51,14 @@
Locker locker;
} g_core;
-DisplayError CoreInterface::CreateCore(CoreEventHandler *event_handler, LogHandler *log_handler,
+// TODO(user): Have a single structure handle carries all the interface pointers.
+DisplayError CoreInterface::CreateCore(CoreEventHandler *event_handler, DebugHandler *debug_handler,
+ BufferAllocator *buffer_allocator,
+ BufferSyncHandler *buffer_sync_handler,
CoreInterface **interface, uint32_t client_version) {
SCOPE_LOCK(g_core.locker);
- if (UNLIKELY(!event_handler || !log_handler || !interface)) {
+ if (!event_handler || !debug_handler || !buffer_allocator || !buffer_sync_handler || !interface) {
return kErrorParameters;
}
@@ -68,11 +77,11 @@
return kErrorUndefined;
}
- Debug::SetLogHandler(log_handler);
+ Debug::SetDebugHandler(debug_handler);
// Create appropriate CoreImpl object based on client version.
if (GET_REVISION(client_version) == CoreImpl::kRevision) {
- core_impl = new CoreImpl(event_handler);
+ core_impl = new CoreImpl(event_handler, buffer_allocator, buffer_sync_handler);
} else {
return kErrorNotSupported;
}
diff --git a/displayengine/libs/core/display_base.cpp b/displayengine/libs/core/display_base.cpp
index 080deb7..058bacc 100644
--- a/displayengine/libs/core/display_base.cpp
+++ b/displayengine/libs/core/display_base.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -26,17 +26,20 @@
#include <utils/debug.h>
#include "display_base.h"
+#include "offline_ctrl.h"
#define __CLASS__ "DisplayBase"
namespace sde {
+// TODO(user): Have a single structure handle carries all the interface pointers and variables.
DisplayBase::DisplayBase(DisplayType display_type, DisplayEventHandler *event_handler,
- HWDeviceType hw_device_type, HWInterface *hw_intf, CompManager *comp_manager)
+ HWDeviceType hw_device_type, HWInterface *hw_intf,
+ CompManager *comp_manager, OfflineCtrl *offline_ctrl)
: display_type_(display_type), event_handler_(event_handler), hw_device_type_(hw_device_type),
- hw_intf_(hw_intf), comp_manager_(comp_manager), state_(kStateOff), hw_device_(0),
- display_comp_ctx_(0), display_attributes_(NULL), num_modes_(0), active_mode_index_(0),
- pending_commit_(false), vsync_enable_(false) {
+ hw_intf_(hw_intf), comp_manager_(comp_manager), offline_ctrl_(offline_ctrl), state_(kStateOff),
+ hw_device_(0), display_comp_ctx_(0), display_attributes_(NULL), num_modes_(0),
+ active_mode_index_(0), pending_commit_(false), vsync_enable_(false) {
}
DisplayError DisplayBase::Init() {
@@ -49,6 +52,9 @@
return error;
}
+ // Set the idle timeout value to driver through sysfs node
+ hw_intf_->SetIdleTimeoutMs(hw_device_, Debug::GetIdleTimeoutMs());
+
error = hw_intf_->GetNumDisplayAttributes(hw_device_, &num_modes_);
if (error != kErrorNone) {
goto CleanupOnError;
@@ -80,13 +86,21 @@
goto CleanupOnError;
}
+ error = offline_ctrl_->RegisterDisplay(display_type_, &display_offline_ctx_);
+ if (UNLIKELY(error != kErrorNone)) {
+ goto CleanupOnError;
+ }
+
return kErrorNone;
CleanupOnError:
- comp_manager_->UnregisterDisplay(display_comp_ctx_);
+ if (display_comp_ctx_) {
+ comp_manager_->UnregisterDisplay(display_comp_ctx_);
+ }
if (display_attributes_) {
delete[] display_attributes_;
+ display_attributes_ = NULL;
}
hw_intf_->Close(hw_device_);
@@ -97,8 +111,15 @@
DisplayError DisplayBase::Deinit() {
SCOPE_LOCK(locker_);
+ offline_ctrl_->UnregisterDisplay(display_offline_ctx_);
+
comp_manager_->UnregisterDisplay(display_comp_ctx_);
- delete[] display_attributes_;
+
+ if (display_attributes_) {
+ delete[] display_attributes_;
+ display_attributes_ = NULL;
+ }
+
hw_intf_->Close(hw_device_);
return kErrorNone;
@@ -115,7 +136,7 @@
pending_commit_ = false;
- if ((state_ == kStateOn)) {
+ if (state_ == kStateOn) {
// Clean hw layers for reuse.
hw_layers_.info = HWLayersInfo();
hw_layers_.info.stack = layer_stack;
@@ -127,14 +148,22 @@
break;
}
- error = hw_intf_->Validate(hw_device_, &hw_layers_);
+ error = offline_ctrl_->Prepare(display_offline_ctx_, &hw_layers_);
if (error == kErrorNone) {
- // Strategy is successful now, wait for Commit().
- pending_commit_ = true;
- break;
+ error = hw_intf_->Validate(hw_device_, &hw_layers_);
+ if (error == kErrorNone) {
+ error = comp_manager_->PostPrepare(display_comp_ctx_, &hw_layers_);
+ if (error == kErrorNone) {
+ // Strategy is successful now, wait for Commit().
+ pending_commit_ = true;
+ break;
+ }
+ }
}
}
comp_manager_->PostPrepare(display_comp_ctx_, &hw_layers_);
+ } else {
+ return kErrorNotSupported;
}
return error;
@@ -149,18 +178,26 @@
return kErrorParameters;
}
- if (!pending_commit_) {
- DLOGE("Commit: Corresponding Prepare() is not called for display = %d", display_type_);
- return kErrorUndefined;
- }
-
if (state_ == kStateOn) {
- error = hw_intf_->Commit(hw_device_, &hw_layers_);
- if (error == kErrorNone) {
- comp_manager_->PostCommit(display_comp_ctx_, &hw_layers_);
- } else {
- DLOGE("Unexpected error. Commit failed on driver.");
+ if (!pending_commit_) {
+ DLOGE("Commit: Corresponding Prepare() is not called for display = %d", display_type_);
+ return kErrorUndefined;
}
+
+ error = offline_ctrl_->Commit(display_offline_ctx_, &hw_layers_);
+ if (error == kErrorNone) {
+ error = hw_intf_->Commit(hw_device_, &hw_layers_);
+ if (error == kErrorNone) {
+ error = comp_manager_->PostCommit(display_comp_ctx_, &hw_layers_);
+ if (error != kErrorNone) {
+ DLOGE("Composition manager PostCommit failed");
+ }
+ } else {
+ DLOGE("Unexpected error. Commit failed on driver.");
+ }
+ }
+ } else {
+ return kErrorNotSupported;
}
pending_commit_ = false;
@@ -168,6 +205,27 @@
return kErrorNone;
}
+DisplayError DisplayBase::Flush() {
+ SCOPE_LOCK(locker_);
+
+ DisplayError error = kErrorNone;
+
+ if (state_ != kStateOn) {
+ return kErrorNone;
+ }
+
+ hw_layers_.info.count = 0;
+ error = hw_intf_->Flush(hw_device_);
+ if (error == kErrorNone) {
+ comp_manager_->Purge(display_comp_ctx_);
+ pending_commit_ = false;
+ } else {
+ DLOGV("Failed to flush device.");
+ }
+
+ return error;
+}
+
DisplayError DisplayBase::GetDisplayState(DisplayState *state) {
SCOPE_LOCK(locker_);
@@ -249,9 +307,14 @@
switch (state) {
case kStateOff:
- hw_layers_.info.count = 0;
- comp_manager_->Purge(display_comp_ctx_);
- error = hw_intf_->PowerOff(hw_device_);
+ // Invoke flush during suspend for HDMI and virtual displays. StateOff is handled
+ // separately for primary in DisplayPrimary::SetDisplayState() function.
+ error = hw_intf_->Flush(hw_device_);
+ if (error == kErrorNone) {
+ comp_manager_->Purge(display_comp_ctx_);
+ state_ = state;
+ hw_layers_.info.count = 0;
+ }
break;
case kStateOn:
@@ -278,6 +341,36 @@
return error;
}
+DisplayError DisplayBase::SetActiveConfig(DisplayConfigVariableInfo *variable_info) {
+ SCOPE_LOCK(locker_);
+ DisplayError error = kErrorNone;
+
+ if (!variable_info) {
+ return kErrorParameters;
+ }
+
+ HWDisplayAttributes display_attributes = display_attributes_[active_mode_index_];
+
+ display_attributes.x_pixels = variable_info->x_pixels;
+ display_attributes.y_pixels = variable_info->y_pixels;
+ display_attributes.fps = variable_info->fps;
+
+ // if display is already connected, unregister display from composition manager and register
+ // the display with new configuration.
+ if (display_comp_ctx_) {
+ comp_manager_->UnregisterDisplay(display_comp_ctx_);
+ }
+
+ error = comp_manager_->RegisterDisplay(display_type_, display_attributes, &display_comp_ctx_);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ display_attributes_[active_mode_index_] = display_attributes;
+
+ return kErrorNone;
+}
+
DisplayError DisplayBase::SetActiveConfig(uint32_t index) {
SCOPE_LOCK(locker_);
DisplayError error = kErrorNone;
@@ -288,9 +381,18 @@
error = hw_intf_->SetDisplayAttributes(hw_device_, index);
if (error != kErrorNone) {
- active_mode_index_ = index;
+ return error;
}
+ active_mode_index_ = index;
+
+ if (display_comp_ctx_) {
+ comp_manager_->UnregisterDisplay(display_comp_ctx_);
+ }
+
+ error = comp_manager_->RegisterDisplay(display_type_, display_attributes_[index],
+ &display_comp_ctx_);
+
return error;
}
@@ -307,6 +409,10 @@
return error;
}
+void DisplayBase::SetIdleTimeoutMs(uint32_t timeout_ms) {
+ hw_intf_->SetIdleTimeoutMs(hw_device_, timeout_ms);
+}
+
DisplayError DisplayBase::VSync(int64_t timestamp) {
if (vsync_enable_) {
DisplayEventVSync vsync;
@@ -321,6 +427,13 @@
return kErrorNone;
}
+void DisplayBase::IdleTimeout() {
+ bool need_refresh = comp_manager_->ProcessIdleTimeout(display_comp_ctx_);
+ if (need_refresh) {
+ event_handler_->Refresh();
+ }
+}
+
void DisplayBase::AppendDump(char *buffer, uint32_t length) {
SCOPE_LOCK(locker_);
@@ -350,6 +463,8 @@
HWLayerConfig &layer_config = hw_layers_.config[i];
HWPipeInfo &left_pipe = hw_layers_.config[i].left_pipe;
HWPipeInfo &right_pipe = hw_layers_.config[i].right_pipe;
+ HWRotateInfo &left_rotate = hw_layers_.config[i].rotates[0];
+ HWRotateInfo &right_rotate = hw_layers_.config[i].rotates[1];
AppendString(buffer, length, "\n\nsde idx: %u, actual idx: %u", i, hw_layers_.info.index[i]);
AppendString(buffer, length, "\nw: %u, h: %u, fmt: %u",
@@ -357,13 +472,29 @@
AppendRect(buffer, length, "\nsrc_rect:", &layer.src_rect);
AppendRect(buffer, length, "\ndst_rect:", &layer.dst_rect);
- AppendString(buffer, length, "\n\tleft split =>");
- AppendString(buffer, length, "\n\t pipe id: 0x%x", left_pipe.pipe_id);
- AppendRect(buffer, length, "\n\t src_roi:", &left_pipe.src_roi);
- AppendRect(buffer, length, "\n\t dst_roi:", &left_pipe.dst_roi);
+ if (left_rotate.valid) {
+ AppendString(buffer, length, "\n\tleft rotate =>");
+ AppendString(buffer, length, "\n\t pipe id: 0x%x", left_rotate.pipe_id);
+ AppendRect(buffer, length, "\n\t src_roi:", &left_rotate.src_roi);
+ AppendRect(buffer, length, "\n\t dst_roi:", &left_rotate.dst_roi);
+ }
- if (layer_config.is_right_pipe) {
- AppendString(buffer, length, "\n\tright split =>");
+ if (right_rotate.valid) {
+ AppendString(buffer, length, "\n\tright rotate =>");
+ AppendString(buffer, length, "\n\t pipe id: 0x%x", right_rotate.pipe_id);
+ AppendRect(buffer, length, "\n\t src_roi:", &right_rotate.src_roi);
+ AppendRect(buffer, length, "\n\t dst_roi:", &right_rotate.dst_roi);
+ }
+
+ if (left_pipe.valid) {
+ AppendString(buffer, length, "\n\tleft pipe =>");
+ AppendString(buffer, length, "\n\t pipe id: 0x%x", left_pipe.pipe_id);
+ AppendRect(buffer, length, "\n\t src_roi:", &left_pipe.src_roi);
+ AppendRect(buffer, length, "\n\t dst_roi:", &left_pipe.dst_roi);
+ }
+
+ if (right_pipe.valid) {
+ AppendString(buffer, length, "\n\tright pipe =>");
AppendString(buffer, length, "\n\t pipe id: 0x%x", right_pipe.pipe_id);
AppendRect(buffer, length, "\n\t src_roi:", &right_pipe.src_roi);
AppendRect(buffer, length, "\n\t dst_roi:", &right_pipe.dst_roi);
diff --git a/displayengine/libs/core/display_base.h b/displayengine/libs/core/display_base.h
index 3f0e24f..d2b67e3 100644
--- a/displayengine/libs/core/display_base.h
+++ b/displayengine/libs/core/display_base.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -31,18 +31,24 @@
#include "hw_interface.h"
#include "comp_manager.h"
+#include "buffer_manager.h"
+
namespace sde {
+class OfflineCtrl;
+
class DisplayBase : public DisplayInterface, HWEventHandler, DumpImpl {
public:
DisplayBase(DisplayType display_type, DisplayEventHandler *event_handler,
- HWDeviceType hw_device_type, HWInterface *hw_intf, CompManager *comp_manager);
+ HWDeviceType hw_device_type, HWInterface *hw_intf, CompManager *comp_manager,
+ OfflineCtrl *offline_ctrl);
virtual ~DisplayBase() { }
virtual DisplayError Init();
virtual DisplayError Deinit();
virtual DisplayError Prepare(LayerStack *layer_stack);
virtual DisplayError Commit(LayerStack *layer_stack);
+ virtual DisplayError Flush();
virtual DisplayError GetDisplayState(DisplayState *state);
virtual DisplayError GetNumVariableInfoConfigs(uint32_t *count);
virtual DisplayError GetConfig(DisplayConfigFixedInfo *fixed_info);
@@ -50,12 +56,15 @@
virtual DisplayError GetActiveConfig(uint32_t *index);
virtual DisplayError GetVSyncState(bool *enabled);
virtual DisplayError SetDisplayState(DisplayState state);
+ virtual DisplayError SetActiveConfig(DisplayConfigVariableInfo *variable_info);
virtual DisplayError SetActiveConfig(uint32_t index);
virtual DisplayError SetVSyncState(bool enable);
+ virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
// Implement the HWEventHandlers
virtual DisplayError VSync(int64_t timestamp);
virtual DisplayError Blank(bool blank);
+ virtual void IdleTimeout();
// DumpImpl method
virtual void AppendDump(char *buffer, uint32_t length);
@@ -70,9 +79,11 @@
HWDeviceType hw_device_type_;
HWInterface *hw_intf_;
CompManager *comp_manager_;
+ OfflineCtrl *offline_ctrl_;
DisplayState state_;
Handle hw_device_;
Handle display_comp_ctx_;
+ Handle display_offline_ctx_;
HWDisplayAttributes *display_attributes_;
uint32_t num_modes_;
uint32_t active_mode_index_;
diff --git a/displayengine/libs/core/display_hdmi.cpp b/displayengine/libs/core/display_hdmi.cpp
index 14a09f1..ed2a859 100644
--- a/displayengine/libs/core/display_hdmi.cpp
+++ b/displayengine/libs/core/display_hdmi.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -32,9 +32,8 @@
namespace sde {
DisplayHDMI::DisplayHDMI(DisplayEventHandler *event_handler, HWInterface *hw_intf,
- CompManager *comp_manager)
- : DisplayBase(kHDMI, event_handler, kDeviceHDMI, hw_intf, comp_manager) {
-}
+ CompManager *comp_manager, OfflineCtrl *offline_ctrl)
+ : DisplayBase(kHDMI, event_handler, kDeviceHDMI, hw_intf, comp_manager, offline_ctrl) { }
int DisplayHDMI::GetBestConfig() {
uint32_t best_config_mode = 0;
diff --git a/displayengine/libs/core/display_hdmi.h b/displayengine/libs/core/display_hdmi.h
index 0bb9dc8..91e4797 100644
--- a/displayengine/libs/core/display_hdmi.h
+++ b/displayengine/libs/core/display_hdmi.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -31,7 +31,8 @@
class DisplayHDMI : public DisplayBase {
public:
- DisplayHDMI(DisplayEventHandler *event_handler, HWInterface *hw_intf, CompManager *comp_manager);
+ DisplayHDMI(DisplayEventHandler *event_handler, HWInterface *hw_intf, CompManager *comp_manager,
+ OfflineCtrl *offline_ctrl);
virtual int GetBestConfig();
};
diff --git a/displayengine/libs/core/display_primary.cpp b/displayengine/libs/core/display_primary.cpp
old mode 100755
new mode 100644
index e4bd031..ac44fe3
--- a/displayengine/libs/core/display_primary.cpp
+++ b/displayengine/libs/core/display_primary.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -32,8 +32,31 @@
namespace sde {
DisplayPrimary::DisplayPrimary(DisplayEventHandler *event_handler, HWInterface *hw_intf,
- CompManager *comp_manager)
- : DisplayBase(kPrimary, event_handler, kDevicePrimary, hw_intf, comp_manager) {
+ CompManager *comp_manager, OfflineCtrl *offline_ctrl)
+ : DisplayBase(kPrimary, event_handler, kDevicePrimary, hw_intf, comp_manager, offline_ctrl) { }
+
+DisplayError DisplayPrimary::SetDisplayState(DisplayState state) {
+ DisplayError error = kErrorNone;
+
+ DLOGI("Set state = %d", state);
+
+ if (state == kStateOff) {
+ SCOPE_LOCK(locker_);
+ if (state == state_) {
+ DLOGI("Same state transition is requested.");
+ return kErrorNone;
+ }
+ error = hw_intf_->PowerOff(hw_device_);
+ if (error == kErrorNone) {
+ comp_manager_->Purge(display_comp_ctx_);
+ state_ = state;
+ hw_layers_.info.count = 0;
+ }
+ } else {
+ error = DisplayBase::SetDisplayState(state);
+ }
+
+ return error;
}
} // namespace sde
diff --git a/displayengine/libs/core/display_primary.h b/displayengine/libs/core/display_primary.h
index 183e964..79fbddf 100644
--- a/displayengine/libs/core/display_primary.h
+++ b/displayengine/libs/core/display_primary.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -32,7 +32,8 @@
class DisplayPrimary : public DisplayBase {
public:
DisplayPrimary(DisplayEventHandler *event_handler, HWInterface *hw_intf,
- CompManager *comp_manager);
+ CompManager *comp_manager, OfflineCtrl *offline_ctrl);
+ virtual DisplayError SetDisplayState(DisplayState state);
};
} // namespace sde
diff --git a/displayengine/libs/core/display_virtual.cpp b/displayengine/libs/core/display_virtual.cpp
old mode 100755
new mode 100644
index 2fef178..84a825f
--- a/displayengine/libs/core/display_virtual.cpp
+++ b/displayengine/libs/core/display_virtual.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -32,9 +32,8 @@
namespace sde {
DisplayVirtual::DisplayVirtual(DisplayEventHandler *event_handler, HWInterface *hw_intf,
- CompManager *comp_manager)
- : DisplayBase(kVirtual, event_handler, kDeviceVirtual, hw_intf, comp_manager) {
-}
+ CompManager *comp_manager, OfflineCtrl *offline_ctrl)
+ : DisplayBase(kVirtual, event_handler, kDeviceVirtual, hw_intf, comp_manager, offline_ctrl) { }
} // namespace sde
diff --git a/displayengine/libs/core/display_virtual.h b/displayengine/libs/core/display_virtual.h
index a8e29e7..9697702 100644
--- a/displayengine/libs/core/display_virtual.h
+++ b/displayengine/libs/core/display_virtual.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -32,7 +32,7 @@
class DisplayVirtual : public DisplayBase {
public:
DisplayVirtual(DisplayEventHandler *event_handler, HWInterface *hw_intf,
- CompManager *comp_manager);
+ CompManager *comp_manager, OfflineCtrl *offline_ctrl);
};
} // namespace sde
diff --git a/displayengine/libs/core/hw_framebuffer.cpp b/displayengine/libs/core/hw_framebuffer.cpp
index 38320a4..4a361da 100644
--- a/displayengine/libs/core/hw_framebuffer.cpp
+++ b/displayengine/libs/core/hw_framebuffer.cpp
@@ -1,25 +1,30 @@
/*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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.
+* 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.
+* 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.
*/
#define __STDC_FORMAT_MACROS
@@ -39,9 +44,10 @@
#include "hw_framebuffer.h"
+
#define __CLASS__ "HWFrameBuffer"
-#define IOCTL_LOGE(ioctl, type) DLOGE("ioctl %s, display = %d errno = %d, desc = %s", #ioctl, \
+#define IOCTL_LOGE(ioctl, type) DLOGE("ioctl %s, device = %d errno = %d, desc = %s", #ioctl, \
type, errno, strerror(errno))
#ifdef DISPLAY_CORE_VIRTUAL_DRIVER
@@ -50,30 +56,29 @@
extern int virtual_close(int fd);
extern int virtual_poll(struct pollfd *fds, nfds_t num, int timeout);
extern ssize_t virtual_pread(int fd, void *data, size_t count, off_t offset);
+extern ssize_t virtual_pwrite(int fd, const void *data, size_t count, off_t offset);
extern FILE* virtual_fopen(const char *fname, const char *mode);
extern int virtual_fclose(FILE* fileptr);
extern ssize_t virtual_getline(char **lineptr, size_t *linelen, FILE *stream);
-extern ssize_t virtual_read(int fd, void *buf, size_t count);
-extern ssize_t virtual_write(int fd, const void *buf, size_t count);
#endif
namespace sde {
-HWFrameBuffer::HWFrameBuffer() : event_thread_name_("SDE_EventThread"), fake_vsync_(false),
- exit_threads_(false), fb_path_("/sys/devices/virtual/graphics/fb"),
- hotplug_enabled_(false) {
+HWFrameBuffer::HWFrameBuffer(BufferSyncHandler *buffer_sync_handler)
+ : event_thread_name_("SDE_EventThread"), fake_vsync_(false), exit_threads_(false),
+ fb_path_("/sys/devices/virtual/graphics/fb"), hotplug_enabled_(false),
+ buffer_sync_handler_(buffer_sync_handler) {
// Pointer to actual driver interfaces.
ioctl_ = ::ioctl;
open_ = ::open;
close_ = ::close;
poll_ = ::poll;
pread_ = ::pread;
+ pwrite_ = ::pwrite;
fopen_ = ::fopen;
fclose_ = ::fclose;
getline_ = ::getline;
- read_ = ::read;
- write_ = ::write;
#ifdef DISPLAY_CORE_VIRTUAL_DRIVER
// If debug property to use virtual driver is set, point to virtual driver interfaces.
@@ -83,11 +88,10 @@
close_ = virtual_close;
poll_ = virtual_poll;
pread_ = virtual_pread;
+ pwrite_ = virtual_pwrite;
fopen_ = virtual_fopen;
fclose_ = virtual_fclose;
getline_ = virtual_getline;
- read_ = virtual_read;
- write_ = virtual_write;
}
#endif
for (int i = 0; i < kDeviceMax; i++) {
@@ -99,7 +103,7 @@
DisplayError error = kErrorNone;
char node_path[kMaxStringLength] = {0};
char data[kMaxStringLength] = {0};
- const char* event_name[kNumDisplayEvents] = {"vsync_event", "show_blank_event"};
+ const char* event_name[kNumDisplayEvents] = {"vsync_event", "show_blank_event", "idle_notify"};
// Read the fb node index
PopulateFBNodeIndex();
@@ -129,6 +133,11 @@
for (int event = 0; event < kNumDisplayEvents; event++) {
pollfd &poll_fd = poll_fds_[display][event];
+ if ((primary_panel_info_.type == kCommandModePanel) && (display == kDevicePrimary) &&
+ (!strncmp(event_name[event], "idle_notify", strlen("idle_notify")))) {
+ continue;
+ }
+
snprintf(node_path, sizeof(node_path), "%s%d/%s", fb_path_, fb_node_index_[display],
event_name[event]);
@@ -163,6 +172,10 @@
goto CleanupOnError;
}
+ // Disable HPD at start if HDMI is external, it will be enabled later when the display powers on
+ // This helps for framework reboot or adb shell stop/start
+ EnableHotPlugDetection(0);
+
return kErrorNone;
CleanupOnError:
@@ -188,7 +201,7 @@
for (int display = 0; display < kNumPhysicalDisplays; display++) {
for (int event = 0; event < kNumDisplayEvents; event++) {
- close(poll_fds_[display][event].fd);
+ close_(poll_fds_[display][event].fd);
}
}
if (supported_video_modes_) {
@@ -223,16 +236,20 @@
case kDeviceVirtual:
snprintf(device_name, sizeof(device_name), "%s%d", "/dev/graphics/fb", fb_node_index_[type]);
break;
+ case kDeviceRotator:
+ snprintf(device_name, sizeof(device_name), "%s", "/dev/mdss_rotator");
+ break;
default:
break;
}
hw_context->device_fd = open_(device_name, O_RDWR);
if (hw_context->device_fd < 0) {
- DLOGE("open %s failed.", device_name);
- error = kErrorResources;
+ DLOGE("open %s failed err = %d errstr = %s", device_name, errno, strerror(errno));
delete hw_context;
+ return kErrorResources;
}
+
hw_context->type = type;
*device = hw_context;
@@ -245,6 +262,7 @@
switch (hw_context->type) {
case kDevicePrimary:
+ case kDeviceVirtual:
break;
case kDeviceHDMI:
hdmi_mode_count_ = 0;
@@ -266,6 +284,7 @@
switch (hw_context->type) {
case kDevicePrimary:
+ case kDeviceVirtual:
*count = 1;
break;
case kDeviceHDMI:
@@ -284,6 +303,8 @@
DisplayError HWFrameBuffer::GetDisplayAttributes(Handle device,
HWDisplayAttributes *display_attributes,
uint32_t index) {
+ DTRACE_SCOPED();
+
HWContext *hw_context = reinterpret_cast<HWContext *>(device);
int &device_fd = hw_context->device_fd;
// Variable screen info
@@ -292,7 +313,7 @@
switch (hw_context->type) {
case kDevicePrimary:
{
- if (ioctl_(device_fd, FBIOGET_VSCREENINFO, &var_screeninfo) == -1) {
+ if (ioctl_(device_fd, FBIOGET_VSCREENINFO, &var_screeninfo) < 0) {
IOCTL_LOGE(FBIOGET_VSCREENINFO, hw_context->type);
return kErrorHardware;
}
@@ -300,7 +321,7 @@
// Frame rate
STRUCT_VAR(msmfb_metadata, meta_data);
meta_data.op = metadata_op_frame_rate;
- if (ioctl_(device_fd, MSMFB_METADATA_GET, &meta_data) == -1) {
+ if (ioctl_(device_fd, MSMFB_METADATA_GET, &meta_data) < 0) {
IOCTL_LOGE(MSMFB_METADATA_GET, hw_context->type);
return kErrorHardware;
}
@@ -355,6 +376,9 @@
}
break;
+ case kDeviceVirtual:
+ break;
+
default:
return kErrorParameters;
}
@@ -363,18 +387,21 @@
}
DisplayError HWFrameBuffer::SetDisplayAttributes(Handle device, uint32_t index) {
+ DTRACE_SCOPED();
+
HWContext *hw_context = reinterpret_cast<HWContext *>(device);
DisplayError error = kErrorNone;
switch (hw_context->type) {
case kDevicePrimary:
+ case kDeviceVirtual:
break;
case kDeviceHDMI:
{
// Variable screen info
STRUCT_VAR(fb_var_screeninfo, vscreeninfo);
- if (ioctl_(hw_context->device_fd, FBIOGET_VSCREENINFO, &vscreeninfo) == -1) {
+ if (ioctl_(hw_context->device_fd, FBIOGET_VSCREENINFO, &vscreeninfo) < 0) {
IOCTL_LOGE(FBIOGET_VSCREENINFO, hw_context->type);
return kErrorHardware;
}
@@ -392,24 +419,26 @@
break;
}
}
+
if (MapHDMIDisplayTiming(timing_mode, &vscreeninfo) == false) {
return kErrorParameters;
}
+
STRUCT_VAR(msmfb_metadata, metadata);
- memset(&metadata, 0 , sizeof(metadata));
metadata.op = metadata_op_vic;
metadata.data.video_info_code = timing_mode->video_format;
- if (ioctl(hw_context->device_fd, MSMFB_METADATA_SET, &metadata) == -1) {
+ if (ioctl(hw_context->device_fd, MSMFB_METADATA_SET, &metadata) < 0) {
IOCTL_LOGE(MSMFB_METADATA_SET, hw_context->type);
return kErrorHardware;
}
+
DLOGI("SetInfo<Mode=%d %dx%d (%d,%d,%d),(%d,%d,%d) %dMHz>", vscreeninfo.reserved[3] & 0xFF00,
vscreeninfo.xres, vscreeninfo.yres, vscreeninfo.right_margin, vscreeninfo.hsync_len,
vscreeninfo.left_margin, vscreeninfo.lower_margin, vscreeninfo.vsync_len,
vscreeninfo.upper_margin, vscreeninfo.pixclock/1000000);
vscreeninfo.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_ALL | FB_ACTIVATE_FORCE;
- if (ioctl_(hw_context->device_fd, FBIOPUT_VSCREENINFO, &vscreeninfo) == -1) {
+ if (ioctl_(hw_context->device_fd, FBIOPUT_VSCREENINFO, &vscreeninfo) < 0) {
IOCTL_LOGE(FBIOGET_VSCREENINFO, hw_context->type);
return kErrorHardware;
}
@@ -451,9 +480,11 @@
DisplayError HWFrameBuffer::PowerOn(Handle device) {
+ DTRACE_SCOPED();
+
HWContext *hw_context = reinterpret_cast<HWContext *>(device);
- if (ioctl_(hw_context->device_fd, FBIOBLANK, FB_BLANK_UNBLANK) == -1) {
+ if (ioctl_(hw_context->device_fd, FBIOBLANK, FB_BLANK_UNBLANK) < 0) {
IOCTL_LOGE(FB_BLANK_UNBLANK, hw_context->type);
return kErrorHardware;
}
@@ -467,28 +498,18 @@
}
DisplayError HWFrameBuffer::PowerOff(Handle device) {
+ DTRACE_SCOPED();
+
HWContext *hw_context = reinterpret_cast<HWContext *>(device);
+ HWDisplay *hw_display = &hw_context->hw_display;
switch (hw_context->type) {
case kDevicePrimary:
- if (ioctl_(hw_context->device_fd, FBIOBLANK, FB_BLANK_POWERDOWN) == -1) {
+ if (ioctl_(hw_context->device_fd, FBIOBLANK, FB_BLANK_POWERDOWN) < 0) {
IOCTL_LOGE(FB_BLANK_POWERDOWN, hw_context->type);
return kErrorHardware;
}
break;
- case kDeviceHDMI:
- {
- hw_context->ResetMDPCommit();
- mdp_layer_commit_v1 &mdp_commit = hw_context->mdp_commit.commit_v1;
- mdp_commit.input_layer_cnt = 0;
- mdp_commit.flags &= ~MDP_VALIDATE_LAYER;
- if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_context->mdp_commit) == -1) {
- IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, hw_context->type);
- return kErrorHardware;
- }
- }
- break;
- case kDeviceVirtual:
default:
break;
}
@@ -509,9 +530,11 @@
}
DisplayError HWFrameBuffer::SetVSyncState(Handle device, bool enable) {
+ DTRACE_SCOPED();
+
HWContext *hw_context = reinterpret_cast<HWContext *>(device);
int vsync_on = enable ? 1 : 0;
- if (ioctl_(hw_context->device_fd, MSMFB_OVERLAY_VSYNC_CTRL, &vsync_on) == -1) {
+ if (ioctl_(hw_context->device_fd, MSMFB_OVERLAY_VSYNC_CTRL, &vsync_on) < 0) {
IOCTL_LOGE(MSMFB_OVERLAY_VSYNC_CTRL, hw_context->type);
return kErrorHardware;
}
@@ -519,65 +542,243 @@
return kErrorNone;
}
-DisplayError HWFrameBuffer::Validate(Handle device, HWLayers *hw_layers) {
- DisplayError error = kErrorNone;
+DisplayError HWFrameBuffer::OpenRotatorSession(Handle device, HWLayers *hw_layers) {
+ HWContext *hw_context = reinterpret_cast<HWContext *>(device);
+ HWRotator *hw_rotator = &hw_context->hw_rotator;
+
+ hw_rotator->Reset();
+
+ HWLayersInfo &hw_layer_info = hw_layers->info;
+
+ for (uint32_t i = 0; i < hw_layer_info.count; i++) {
+ Layer& layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
+ LayerBuffer *input_buffer = layer.input_buffer;
+ bool rot90 = (layer.transform.rotation == 90.0f);
+
+ for (uint32_t count = 0; count < 2; count++) {
+ HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
+
+ if (rotate_info->valid) {
+ HWBufferInfo *rot_buf_info = &rotate_info->hw_buffer_info;
+
+ if (rot_buf_info->session_id < 0) {
+ STRUCT_VAR(mdp_rotation_config, mdp_rot_config);
+ mdp_rot_config.version = MDP_ROTATION_REQUEST_VERSION_1_0;
+ mdp_rot_config.input.width = input_buffer->width;
+ mdp_rot_config.input.height = input_buffer->height;
+ SetFormat(input_buffer->format, &mdp_rot_config.input.format);
+ mdp_rot_config.output.width = rot_buf_info->output_buffer.width;
+ mdp_rot_config.output.height = rot_buf_info->output_buffer.height;
+ SetFormat(rot_buf_info->output_buffer.format, &mdp_rot_config.output.format);
+ mdp_rot_config.frame_rate = layer.frame_rate;
+
+ if (ioctl_(hw_context->device_fd, MDSS_ROTATION_OPEN, &mdp_rot_config) < 0) {
+ IOCTL_LOGE(MDSS_ROTATION_OPEN, hw_context->type);
+ return kErrorHardware;
+ }
+
+ rot_buf_info->session_id = mdp_rot_config.session_id;
+
+ DLOGV_IF(kTagDriverConfig, "session_id %d", rot_buf_info->session_id);
+ }
+ }
+ }
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWFrameBuffer::CloseRotatorSession(Handle device, int32_t session_id) {
HWContext *hw_context = reinterpret_cast<HWContext *>(device);
- hw_context->ResetMDPCommit();
+ if (ioctl_(hw_context->device_fd, MDSS_ROTATION_CLOSE, (uint32_t)session_id) < 0) {
+ IOCTL_LOGE(MDSS_ROTATION_CLOSE, hw_context->type);
+ return kErrorHardware;
+ }
+
+ DLOGV_IF(kTagDriverConfig, "session_id %d", session_id);
+
+ return kErrorNone;
+}
+
+DisplayError HWFrameBuffer::Validate(Handle device, HWLayers *hw_layers) {
+ DTRACE_SCOPED();
+
+ DisplayError error = kErrorNone;
+
+ HWContext *hw_context = reinterpret_cast<HWContext *>(device);
+ switch (hw_context->type) {
+ case kDevicePrimary:
+ case kDeviceHDMI:
+ case kDeviceVirtual:
+ error = DisplayValidate(hw_context, hw_layers);
+ if (error != kErrorNone) {
+ return error;
+ }
+ break;
+ case kDeviceRotator:
+ error = RotatorValidate(hw_context, hw_layers);
+ if (error != kErrorNone) {
+ return error;
+ }
+ break;
+ default:
+ break;
+ }
+ return error;
+}
+
+DisplayError HWFrameBuffer::Commit(Handle device, HWLayers *hw_layers) {
+ DisplayError error = kErrorNone;
+
+ HWContext *hw_context = reinterpret_cast<HWContext *>(device);
+ switch (hw_context->type) {
+ case kDevicePrimary:
+ case kDeviceHDMI:
+ case kDeviceVirtual:
+ error = DisplayCommit(hw_context, hw_layers);
+ if (error != kErrorNone) {
+ return error;
+ }
+ break;
+ case kDeviceRotator:
+ error = RotatorCommit(hw_context, hw_layers);
+ if (error != kErrorNone) {
+ return error;
+ }
+ break;
+ default:
+ break;
+ }
+ return error;
+}
+
+DisplayError HWFrameBuffer::DisplayValidate(HWContext *hw_context, HWLayers *hw_layers) {
+ DisplayError error = kErrorNone;
+ HWDisplay *hw_display = &hw_context->hw_display;
+
+ hw_display->Reset();
HWLayersInfo &hw_layer_info = hw_layers->info;
LayerStack *stack = hw_layer_info.stack;
- mdp_layer_commit_v1 &mdp_commit = hw_context->mdp_commit.commit_v1;
- mdp_input_layer *mdp_layers = hw_context->mdp_layers;
+ DLOGV_IF(kTagDriverConfig, "************************** %s Validate Input ***********************",
+ GetDeviceString(hw_context->type));
+ DLOGV_IF(kTagDriverConfig, "SDE layer count is %d", hw_layer_info.count);
+
+ mdp_layer_commit_v1 &mdp_commit = hw_display->mdp_disp_commit.commit_v1;
+ mdp_input_layer *mdp_layers = hw_display->mdp_in_layers;
+ mdp_output_layer *mdp_out_layer = &hw_display->mdp_out_layer;
uint32_t &mdp_layer_count = mdp_commit.input_layer_cnt;
for (uint32_t i = 0; i < hw_layer_info.count; i++) {
uint32_t layer_index = hw_layer_info.index[i];
Layer &layer = stack->layers[layer_index];
LayerBuffer *input_buffer = layer.input_buffer;
- HWLayerConfig &config = hw_layers->config[i];
+ HWPipeInfo *left_pipe = &hw_layers->config[i].left_pipe;
+ HWPipeInfo *right_pipe = &hw_layers->config[i].right_pipe;
+ mdp_input_layer mdp_layer;
- uint32_t split_count = hw_layers->config[i].is_right_pipe ? 2 : 1;
- for (uint32_t j = 0; j < split_count; j++) {
- HWPipeInfo &pipe = (j == 0) ? config.left_pipe : config.right_pipe;
- mdp_input_layer &mdp_layer = mdp_layers[mdp_layer_count];
- mdp_layer.alpha = layer.plane_alpha;
- mdp_layer.z_order = static_cast<uint16_t>(i);
- mdp_layer.transp_mask = 0xffffffff;
- mdp_layer.horz_deci = pipe.horizontal_decimation;
- mdp_layer.vert_deci = pipe.vertical_decimation;
+ for (uint32_t count = 0; count < 2; count++) {
+ HWPipeInfo *pipe_info = (count == 0) ? left_pipe : right_pipe;
+ HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
- SetBlending(layer.blending, &mdp_layer.blend_op);
-
- SetRect(pipe.src_roi, &mdp_layer.src_rect);
- SetRect(pipe.dst_roi, &mdp_layer.dst_rect);
-
- mdp_layer.pipe_ndx = pipe.pipe_id;
-
- mdp_layer_buffer &mdp_buffer_left = mdp_layer.buffer;
- mdp_buffer_left.width = input_buffer->width;
- mdp_buffer_left.height = input_buffer->height;
-
- error = SetFormat(layer.input_buffer->format, &mdp_buffer_left.format);
- if (error != kErrorNone) {
- return error;
+ if (rotate_info->valid) {
+ input_buffer = &rotate_info->hw_buffer_info.output_buffer;
}
- if (layer.transform.flip_vertical) {
- mdp_layer.flags |= MDP_LAYER_FLIP_UD;
- }
+ if (pipe_info->valid) {
+ mdp_input_layer &mdp_layer = mdp_layers[mdp_layer_count];
+ mdp_layer_buffer &mdp_buffer = mdp_layer.buffer;
- if (layer.transform.flip_horizontal) {
- mdp_layer.flags |= MDP_LAYER_FLIP_LR;
- }
+ mdp_buffer.width = input_buffer->width;
+ mdp_buffer.height = input_buffer->height;
- mdp_layer_count++;
+ error = SetFormat(input_buffer->format, &mdp_buffer.format);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ mdp_layer.alpha = layer.plane_alpha;
+ mdp_layer.z_order = static_cast<uint16_t>(i);
+ mdp_layer.transp_mask = 0xffffffff;
+ SetBlending(layer.blending, &mdp_layer.blend_op);
+ mdp_layer.pipe_ndx = pipe_info->pipe_id;
+ mdp_layer.horz_deci = pipe_info->horizontal_decimation;
+ mdp_layer.vert_deci = pipe_info->vertical_decimation;
+
+ SetRect(pipe_info->src_roi, &mdp_layer.src_rect);
+ SetRect(pipe_info->dst_roi, &mdp_layer.dst_rect);
+
+ // Flips will be taken care by rotator, if layer requires 90 rotation. So Dont use MDP for
+ // flip operation, if layer transform is 90.
+ if (!layer.transform.rotation) {
+ if (layer.transform.flip_vertical) {
+ mdp_layer.flags |= MDP_LAYER_FLIP_UD;
+ }
+
+ if (layer.transform.flip_horizontal) {
+ mdp_layer.flags |= MDP_LAYER_FLIP_LR;
+ }
+ }
+
+ if (pipe_info->scale_data.enable_pxl_ext) {
+ if ((mdp_layer.flags & MDP_LAYER_DEINTERLACE) && (layer.transform.rotation == 90.0f))
+ mdp_buffer.width = pipe_info->scale_data.src_width;
+ hw_display->SetScaleData(pipe_info->scale_data, mdp_layer_count);
+ }
+
+ // Send scale data to MDP driver
+ mdp_layer.scale = hw_display->GetScaleRef(mdp_layer_count);
+ mdp_layer_count++;
+
+ DLOGV_IF(kTagDriverConfig, "******************* Layer[%d] %s pipe Input ******************",
+ i, count ? "Right" : "Left");
+ DLOGV_IF(kTagDriverConfig, "in_w %d, in_h %d, in_f %d", mdp_buffer.width, mdp_buffer.height,
+ mdp_buffer.format);
+ DLOGV_IF(kTagDriverConfig, "plane_alpha %d, zorder %d, blending %d, horz_deci %d, "
+ "vert_deci %d", mdp_layer.alpha, mdp_layer.z_order, mdp_layer.blend_op,
+ mdp_layer.horz_deci, mdp_layer.vert_deci);
+ DLOGV_IF(kTagDriverConfig, "src_rect [%d, %d, %d, %d]", mdp_layer.src_rect.x,
+ mdp_layer.src_rect.y, mdp_layer.src_rect.w, mdp_layer.src_rect.h);
+ DLOGV_IF(kTagDriverConfig, "dst_rect [%d, %d, %d, %d]", mdp_layer.dst_rect.x,
+ mdp_layer.dst_rect.y, mdp_layer.dst_rect.w, mdp_layer.dst_rect.h);
+ for (int j = 0; j < MAX_PLANES; j++) {
+ DLOGV_IF(kTagDriverConfig, "Scale Data[%d]: Phase=[%x %x %x %x] Pixel_Ext=[%d %d %d %d]",
+ j, mdp_layer.scale->init_phase_x[j], mdp_layer.scale->phase_step_x[j],
+ mdp_layer.scale->init_phase_y[j], mdp_layer.scale->phase_step_y[j],
+ mdp_layer.scale->num_ext_pxls_left[j], mdp_layer.scale->num_ext_pxls_top[j],
+ mdp_layer.scale->num_ext_pxls_right[j], mdp_layer.scale->num_ext_pxls_btm[j]);
+ DLOGV_IF(kTagDriverConfig, "Fetch=[%d %d %d %d] Repeat=[%d %d %d %d] roi_width = %d",
+ mdp_layer.scale->left_ftch[j], mdp_layer.scale->top_ftch[j],
+ mdp_layer.scale->right_ftch[j], mdp_layer.scale->btm_ftch[j],
+ mdp_layer.scale->left_rpt[j], mdp_layer.scale->top_rpt[j],
+ mdp_layer.scale->right_rpt[j], mdp_layer.scale->btm_rpt[j],
+ mdp_layer.scale->roi_w[j]);
+ }
+ DLOGV_IF(kTagDriverConfig, "*************************************************************");
+ }
}
}
+ if (hw_context->type == kDeviceVirtual) {
+ LayerBuffer *output_buffer = hw_layers->info.stack->output_buffer;
+ // TODO(user): Need to assign the writeback id from the resource manager, since the support
+ // has not been added hard coding it to 2 for now.
+ mdp_out_layer->writeback_ndx = 2;
+ mdp_out_layer->buffer.width = output_buffer->width;
+ mdp_out_layer->buffer.height = output_buffer->height;
+ SetFormat(output_buffer->format, &mdp_out_layer->buffer.format);
+
+ DLOGI_IF(kTagDriverConfig, "******************* Output buffer Info **********************");
+ DLOGI_IF(kTagDriverConfig, "out_w %d, out_h %d, out_f %d, wb_id %d",
+ mdp_out_layer->buffer.width, mdp_out_layer->buffer.height,
+ mdp_out_layer->buffer.format, mdp_out_layer->writeback_ndx);
+ DLOGI_IF(kTagDriverConfig, "*************************************************************");
+ }
+
mdp_commit.flags |= MDP_VALIDATE_LAYER;
- if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_context->mdp_commit) == -1) {
+ if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_display->mdp_disp_commit) < 0) {
IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, hw_context->type);
return kErrorHardware;
}
@@ -585,55 +786,308 @@
return kErrorNone;
}
-DisplayError HWFrameBuffer::Commit(Handle device, HWLayers *hw_layers) {
- HWContext *hw_context = reinterpret_cast<HWContext *>(device);
+DisplayError HWFrameBuffer::DisplayCommit(HWContext *hw_context, HWLayers *hw_layers) {
+ DTRACE_SCOPED();
+
+ HWDisplay *hw_display = &hw_context->hw_display;
HWLayersInfo &hw_layer_info = hw_layers->info;
LayerStack *stack = hw_layer_info.stack;
- mdp_layer_commit_v1 &mdp_commit = hw_context->mdp_commit.commit_v1;
- mdp_input_layer *mdp_layers = hw_context->mdp_layers;
+ DLOGV_IF(kTagDriverConfig, "*************************** %s Commit Input ************************",
+ GetDeviceString(hw_context->type));
+ DLOGV_IF(kTagDriverConfig, "SDE layer count is %d", hw_layer_info.count);
+
+ mdp_layer_commit_v1 &mdp_commit = hw_display->mdp_disp_commit.commit_v1;
+ mdp_input_layer *mdp_layers = hw_display->mdp_in_layers;
+ mdp_output_layer *mdp_out_layer = &hw_display->mdp_out_layer;
uint32_t mdp_layer_index = 0;
for (uint32_t i = 0; i < hw_layer_info.count; i++) {
uint32_t layer_index = hw_layer_info.index[i];
LayerBuffer *input_buffer = stack->layers[layer_index].input_buffer;
+ HWPipeInfo *left_pipe = &hw_layers->config[i].left_pipe;
+ HWPipeInfo *right_pipe = &hw_layers->config[i].right_pipe;
- uint32_t split_count = hw_layers->config[i].is_right_pipe ? 2 : 1;
- for (uint32_t j = 0; j < split_count; j++) {
- mdp_layer_buffer &mdp_buffer = mdp_layers[mdp_layer_index].buffer;
+ for (uint32_t count = 0; count < 2; count++) {
+ HWPipeInfo *pipe_info = (count == 0) ? left_pipe : right_pipe;
+ HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
- if (input_buffer->planes[0].fd >= 0) {
- mdp_buffer.plane_count = 1;
- mdp_buffer.planes[0].fd = input_buffer->planes[0].fd;
- mdp_buffer.planes[0].offset = input_buffer->planes[0].offset;
- mdp_buffer.planes[0].stride = input_buffer->planes[0].stride;
- } else {
- DLOGW("Invalid buffer fd, setting plane count to 0");
- mdp_buffer.plane_count = 0;
+ if (rotate_info->valid) {
+ input_buffer = &rotate_info->hw_buffer_info.output_buffer;
}
- mdp_buffer.fence = input_buffer->acquire_fence_fd;
- mdp_layer_index++;
+ if (pipe_info->valid) {
+ mdp_layer_buffer &mdp_buffer = mdp_layers[mdp_layer_index].buffer;
+ mdp_input_layer &mdp_layer = mdp_layers[mdp_layer_index];
+ if (input_buffer->planes[0].fd >= 0) {
+ mdp_buffer.plane_count = 1;
+ mdp_buffer.planes[0].fd = input_buffer->planes[0].fd;
+ mdp_buffer.planes[0].offset = input_buffer->planes[0].offset;
+ SetStride(hw_context->type, input_buffer->format, input_buffer->planes[0].stride,
+ &mdp_buffer.planes[0].stride);
+ } else {
+ DLOGW("Invalid buffer fd, setting plane count to 0");
+ mdp_buffer.plane_count = 0;
+ }
+
+ mdp_buffer.fence = input_buffer->acquire_fence_fd;
+ mdp_layer_index++;
+
+ DLOGV_IF(kTagDriverConfig, "****************** Layer[%d] %s pipe Input *******************",
+ i, count ? "Right" : "Left");
+ DLOGI_IF(kTagDriverConfig, "in_w %d, in_h %d, in_f %d, horz_deci %d, vert_deci %d",
+ mdp_buffer.width, mdp_buffer.height, mdp_buffer.format, mdp_layer.horz_deci,
+ mdp_layer.vert_deci);
+ DLOGI_IF(kTagDriverConfig, "in_buf_fd %d, in_buf_offset %d, in_buf_stride %d, " \
+ "in_plane_count %d, in_fence %d, layer count %d", mdp_buffer.planes[0].fd,
+ mdp_buffer.planes[0].offset, mdp_buffer.planes[0].stride, mdp_buffer.plane_count,
+ mdp_buffer.fence, mdp_commit.input_layer_cnt);
+ DLOGV_IF(kTagDriverConfig, "*************************************************************");
+ }
}
}
+ if (hw_context->type == kDeviceVirtual) {
+ LayerBuffer *output_buffer = hw_layers->info.stack->output_buffer;
- mdp_commit.flags |= MDP_COMMIT_RETIRE_FENCE;
+ if (output_buffer->planes[0].fd >= 0) {
+ mdp_out_layer->buffer.planes[0].fd = output_buffer->planes[0].fd;
+ mdp_out_layer->buffer.planes[0].offset = output_buffer->planes[0].offset;
+ SetStride(hw_context->type, output_buffer->format, output_buffer->planes[0].stride,
+ &mdp_out_layer->buffer.planes[0].stride);
+ mdp_out_layer->buffer.plane_count = 1;
+ } else {
+ DLOGW("Invalid output buffer fd, setting plane count to 0");
+ mdp_out_layer->buffer.plane_count = 0;
+ }
+
+ mdp_out_layer->buffer.fence = output_buffer->acquire_fence_fd;
+
+ DLOGI_IF(kTagDriverConfig, "******************* Output buffer Info **********************");
+ DLOGI_IF(kTagDriverConfig, "out_fd %d, out_offset %d, out_stride %d, acquire_fence %d",
+ mdp_out_layer->buffer.planes[0].fd, mdp_out_layer->buffer.planes[0].offset,
+ mdp_out_layer->buffer.planes[0].stride, mdp_out_layer->buffer.fence);
+ DLOGI_IF(kTagDriverConfig, "*************************************************************");
+ }
+
+ mdp_commit.release_fence = -1;
mdp_commit.flags &= ~MDP_VALIDATE_LAYER;
- if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_context->mdp_commit) == -1) {
+ if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_display->mdp_disp_commit) < 0) {
IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, hw_context->type);
return kErrorHardware;
}
+ stack->retire_fence_fd = mdp_commit.retire_fence;
+
// MDP returns only one release fence for the entire layer stack. Duplicate this fence into all
// layers being composed by MDP.
- stack->retire_fence_fd = mdp_commit.retire_fence;
for (uint32_t i = 0; i < hw_layer_info.count; i++) {
uint32_t layer_index = hw_layer_info.index[i];
LayerBuffer *input_buffer = stack->layers[layer_index].input_buffer;
+ HWRotateInfo *left_rotate = &hw_layers->config[i].rotates[0];
+ HWRotateInfo *right_rotate = &hw_layers->config[i].rotates[1];
- input_buffer->release_fence_fd = dup(mdp_commit.release_fence);
+ if (!left_rotate->valid && !right_rotate->valid) {
+ input_buffer->release_fence_fd = dup(mdp_commit.release_fence);
+ continue;
+ }
+
+ for (uint32_t count = 0; count < 2; count++) {
+ HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
+ if (rotate_info->valid) {
+ input_buffer = &rotate_info->hw_buffer_info.output_buffer;
+ input_buffer->release_fence_fd = dup(mdp_commit.release_fence);
+ close_(input_buffer->acquire_fence_fd);
+ input_buffer->acquire_fence_fd = -1;
+ }
+ }
}
- close(mdp_commit.release_fence);
+ DLOGI_IF(kTagDriverConfig, "*************************** %s Commit Input ************************",
+ GetDeviceString(hw_context->type));
+ DLOGI_IF(kTagDriverConfig, "retire_fence_fd %d", stack->retire_fence_fd);
+ DLOGI_IF(kTagDriverConfig, "*************************************************************");
+
+ close_(mdp_commit.release_fence);
+
+ return kErrorNone;
+}
+
+DisplayError HWFrameBuffer::RotatorValidate(HWContext *hw_context, HWLayers *hw_layers) {
+ HWRotator *hw_rotator = &hw_context->hw_rotator;
+ DLOGV_IF(kTagDriverConfig, "************************* %s Validate Input ************************",
+ GetDeviceString(hw_context->type));
+
+ hw_rotator->Reset();
+
+ mdp_rotation_request *mdp_rot_request = &hw_rotator->mdp_rot_req;
+ HWLayersInfo &hw_layer_info = hw_layers->info;
+
+ uint32_t &rot_count = mdp_rot_request->count;
+ for (uint32_t i = 0; i < hw_layer_info.count; i++) {
+ Layer& layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
+
+ for (uint32_t count = 0; count < 2; count++) {
+ HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
+
+ if (rotate_info->valid) {
+ HWBufferInfo *rot_buf_info = &rotate_info->hw_buffer_info;
+ mdp_rotation_item *mdp_rot_item = &mdp_rot_request->list[rot_count];
+ bool rot90 = (layer.transform.rotation == 90.0f);
+
+ if (rot90) {
+ mdp_rot_item->flags |= MDP_ROTATION_90;
+ }
+
+ if (layer.transform.flip_horizontal) {
+ mdp_rot_item->flags |= MDP_ROTATION_FLIP_LR;
+ }
+
+ if (layer.transform.flip_vertical) {
+ mdp_rot_item->flags |= MDP_ROTATION_FLIP_UD;
+ }
+
+ SetRect(rotate_info->src_roi, &mdp_rot_item->src_rect);
+ SetRect(rotate_info->dst_roi, &mdp_rot_item->dst_rect);
+
+ // TODO(user): Need to assign the writeback id and pipe id returned from resource manager.
+ mdp_rot_item->pipe_idx = 0;
+ mdp_rot_item->wb_idx = 0;
+
+ mdp_rot_item->input.width = layer.input_buffer->width;
+ mdp_rot_item->input.height = layer.input_buffer->height;
+ SetFormat(layer.input_buffer->format, &mdp_rot_item->input.format);
+
+ mdp_rot_item->output.width = rot_buf_info->output_buffer.width;
+ mdp_rot_item->output.height = rot_buf_info->output_buffer.height;
+ SetFormat(rot_buf_info->output_buffer.format, &mdp_rot_item->output.format);
+
+ rot_count++;
+
+ DLOGV_IF(kTagDriverConfig, "******************** Layer[%d] %s rotate ********************",
+ i, count ? "Right" : "Left");
+ DLOGV_IF(kTagDriverConfig, "in_w %d, in_h %d, in_f %d,\t out_w %d, out_h %d, out_f %d",
+ mdp_rot_item->input.width, mdp_rot_item->input.height, mdp_rot_item->input.format,
+ mdp_rot_item->output.width, mdp_rot_item->output.height,
+ mdp_rot_item->output.format);
+ DLOGV_IF(kTagDriverConfig, "pipe_id %d, wb_id %d, rot_flag %d", mdp_rot_item->pipe_idx,
+ mdp_rot_item->wb_idx, mdp_rot_item->flags);
+ DLOGV_IF(kTagDriverConfig, "src_rect [%d, %d, %d, %d]", mdp_rot_item->src_rect.x,
+ mdp_rot_item->src_rect.y, mdp_rot_item->src_rect.w, mdp_rot_item->src_rect.h);
+ DLOGV_IF(kTagDriverConfig, "dst_rect [%d, %d, %d, %d]", mdp_rot_item->dst_rect.x,
+ mdp_rot_item->dst_rect.y, mdp_rot_item->dst_rect.w, mdp_rot_item->dst_rect.h);
+ DLOGV_IF(kTagDriverConfig, "*************************************************************");
+ }
+ }
+ }
+
+ mdp_rot_request->flags = MDSS_ROTATION_REQUEST_VALIDATE;
+ if (ioctl_(hw_context->device_fd, MDSS_ROTATION_REQUEST, mdp_rot_request) < 0) {
+ IOCTL_LOGE(MDSS_ROTATION_REQUEST, hw_context->type);
+ return kErrorHardware;
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWFrameBuffer::RotatorCommit(HWContext *hw_context, HWLayers *hw_layers) {
+ HWRotator *hw_rotator = &hw_context->hw_rotator;
+ mdp_rotation_request *mdp_rot_request = &hw_rotator->mdp_rot_req;
+ HWLayersInfo &hw_layer_info = hw_layers->info;
+ uint32_t rot_count = 0;
+
+ DLOGV_IF(kTagDriverConfig, "************************* %s Commit Input **************************",
+ GetDeviceString(hw_context->type));
+ DLOGV_IF(kTagDriverConfig, "Rotate layer count is %d", mdp_rot_request->count);
+
+ mdp_rot_request->list = hw_rotator->mdp_rot_layers;
+
+ for (uint32_t i = 0; i < hw_layer_info.count; i++) {
+ Layer& layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
+
+ for (uint32_t count = 0; count < 2; count++) {
+ HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
+
+ if (rotate_info->valid) {
+ HWBufferInfo *rot_buf_info = &rotate_info->hw_buffer_info;
+ mdp_rotation_item *mdp_rot_item = &mdp_rot_request->list[rot_count];
+
+ mdp_rot_item->input.planes[0].fd = layer.input_buffer->planes[0].fd;
+ mdp_rot_item->input.planes[0].offset = layer.input_buffer->planes[0].offset;
+ SetStride(hw_context->type, layer.input_buffer->format, layer.input_buffer->width,
+ &mdp_rot_item->input.planes[0].stride);
+ mdp_rot_item->input.plane_count = 1;
+ mdp_rot_item->input.fence = layer.input_buffer->acquire_fence_fd;
+
+ mdp_rot_item->output.planes[0].fd = rot_buf_info->output_buffer.planes[0].fd;
+ mdp_rot_item->output.planes[0].offset = rot_buf_info->output_buffer.planes[0].offset;
+ SetStride(hw_context->type, rot_buf_info->output_buffer.format,
+ rot_buf_info->output_buffer.planes[0].stride,
+ &mdp_rot_item->output.planes[0].stride);
+ mdp_rot_item->output.plane_count = 1;
+ mdp_rot_item->output.fence = -1;
+
+ rot_count++;
+
+ DLOGV_IF(kTagDriverConfig, "******************** Layer[%d] %s rotate ********************",
+ i, count ? "Right" : "Left");
+ DLOGV_IF(kTagDriverConfig, "in_buf_fd %d, in_buf_offset %d, in_stride %d, " \
+ "in_plane_count %d, in_fence %d", mdp_rot_item->input.planes[0].fd,
+ mdp_rot_item->input.planes[0].offset, mdp_rot_item->input.planes[0].stride,
+ mdp_rot_item->input.plane_count, mdp_rot_item->input.fence);
+ DLOGV_IF(kTagDriverConfig, "out_fd %d, out_offset %d, out_stride %d, out_plane_count %d, " \
+ "out_fence %d", mdp_rot_item->output.planes[0].fd,
+ mdp_rot_item->output.planes[0].offset, mdp_rot_item->output.planes[0].stride,
+ mdp_rot_item->output.plane_count, mdp_rot_item->output.fence);
+ DLOGV_IF(kTagDriverConfig, "*************************************************************");
+ }
+ }
+ }
+
+ mdp_rot_request->flags &= ~MDSS_ROTATION_REQUEST_VALIDATE;
+ if (ioctl_(hw_context->device_fd, MDSS_ROTATION_REQUEST, mdp_rot_request) < 0) {
+ IOCTL_LOGE(MDSS_ROTATION_REQUEST, hw_context->type);
+ return kErrorHardware;
+ }
+
+ rot_count = 0;
+ for (uint32_t i = 0; i < hw_layer_info.count; i++) {
+ Layer& layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
+
+ layer.input_buffer->release_fence_fd = -1;
+
+ for (uint32_t count = 0; count < 2; count++) {
+ HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
+
+ if (rotate_info->valid) {
+ HWBufferInfo *rot_buf_info = &rotate_info->hw_buffer_info;
+ mdp_rotation_item *mdp_rot_item = &mdp_rot_request->list[rot_count];
+
+ SyncMerge(layer.input_buffer->release_fence_fd, dup(mdp_rot_item->output.fence),
+ &layer.input_buffer->release_fence_fd);
+
+ rot_buf_info->output_buffer.acquire_fence_fd = dup(mdp_rot_item->output.fence);
+
+ close_(mdp_rot_item->output.fence);
+ rot_count++;
+ }
+ }
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWFrameBuffer::Flush(Handle device) {
+ HWContext *hw_context = reinterpret_cast<HWContext *>(device);
+ HWDisplay *hw_display = &hw_context->hw_display;
+
+ hw_display->Reset();
+ mdp_layer_commit_v1 &mdp_commit = hw_display->mdp_disp_commit.commit_v1;
+ mdp_commit.input_layer_cnt = 0;
+ mdp_commit.flags &= ~MDP_VALIDATE_LAYER;
+
+ if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_display->mdp_disp_commit) == -1) {
+ IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, hw_context->type);
+ return kErrorHardware;
+ }
return kErrorNone;
}
@@ -653,6 +1107,9 @@
case kFormatYCrCb420SemiPlanar: *target = MDP_Y_CRCB_H2V2; break;
case kFormatYCbCr422Packed: *target = MDP_YCBYCR_H2V1; break;
case kFormatYCbCr420SemiPlanarVenus: *target = MDP_Y_CBCR_H2V2_VENUS; break;
+ case kFormatRGBA8888Ubwc: *target = MDP_RGBA_8888_UBWC; break;
+ case kFormatRGB565Ubwc: *target = MDP_RGB_565_UBWC; break;
+ case kFormatYCbCr420SPVenusUbwc: *target = MDP_Y_CBCR_H2V2_UBWC; break;
default:
DLOGE("Unsupported format type %d", source);
return kErrorParameters;
@@ -661,6 +1118,47 @@
return kErrorNone;
}
+DisplayError HWFrameBuffer::SetStride(HWDeviceType device_type, LayerBufferFormat format,
+ uint32_t width, uint32_t *target) {
+ // TODO(user): This SetStride function is an workaround to satisfy the driver expectation for
+ // rotator and virtual devices. Eventually this will be taken care in the driver.
+ if (device_type != kDeviceRotator && device_type != kDeviceVirtual) {
+ *target = width;
+ return kErrorNone;
+ }
+
+ switch (format) {
+ case kFormatARGB8888:
+ case kFormatRGBA8888:
+ case kFormatBGRA8888:
+ case kFormatRGBX8888:
+ case kFormatBGRX8888:
+ *target = width * 4;
+ break;
+ case kFormatRGB888:
+ *target = width * 3;
+ break;
+ case kFormatRGB565:
+ *target = width * 3;
+ break;
+ case kFormatYCbCr420SemiPlanarVenus:
+ case kFormatYCbCr420Planar:
+ case kFormatYCrCb420Planar:
+ case kFormatYCbCr420SemiPlanar:
+ case kFormatYCrCb420SemiPlanar:
+ *target = width;
+ break;
+ case kFormatYCbCr422Packed:
+ *target = width * 2;
+ break;
+ default:
+ DLOGE("Unsupported format type %d", format);
+ return kErrorParameters;
+ }
+
+ return kErrorNone;
+}
+
void HWFrameBuffer::SetBlending(const LayerBlending &source, mdss_mdp_blend_op *target) {
switch (source) {
case kBlendingPremultiplied: *target = BLEND_OP_PREMULTIPLIED; break;
@@ -676,6 +1174,31 @@
target->h = UINT32(source.bottom) - target->y;
}
+void HWFrameBuffer::SyncMerge(const int &fd1, const int &fd2, int *target) {
+ if (fd1 >= 0 && fd2 >= 0) {
+ buffer_sync_handler_->SyncMerge(fd1, fd2, target);
+ } else if (fd1 >= 0) {
+ *target = fd1;
+ } else if (fd2 >= 0) {
+ *target = fd2;
+ }
+}
+
+const char *HWFrameBuffer::GetDeviceString(HWDeviceType type) {
+ switch (type) {
+ case kDevicePrimary:
+ return "Primary Display Device";
+ case kDeviceHDMI:
+ return "HDMI Display Device";
+ case kDeviceVirtual:
+ return "Virtual Display Device";
+ case kDeviceRotator:
+ return "Rotator Device";
+ default:
+ return "Invalid Device";
+ }
+}
+
void* HWFrameBuffer::DisplayEventThread(void *context) {
if (context) {
return reinterpret_cast<HWFrameBuffer *>(context)->DisplayEventThreadHandler();
@@ -709,9 +1232,10 @@
pthread_exit(0);
}
- typedef void (HWFrameBuffer::*EventHandler)(int, char *);
+ typedef void (HWFrameBuffer::*EventHandler)(int, char*);
EventHandler event_handler[kNumDisplayEvents] = { &HWFrameBuffer::HandleVSync,
- &HWFrameBuffer::HandleBlank };
+ &HWFrameBuffer::HandleBlank,
+ &HWFrameBuffer::HandleIdleTimeout };
while (!exit_threads_) {
int error = poll_(poll_fds_[0], kNumPhysicalDisplays * kNumDisplayEvents, -1);
@@ -756,6 +1280,10 @@
// TODO(user): Need to send blank Event
}
+void HWFrameBuffer::HandleIdleTimeout(int display_id, char *data) {
+ event_handler_[display_id]->IdleTimeout();
+}
+
void HWFrameBuffer::PopulateFBNodeIndex() {
char stringbuffer[kMaxStringLength];
DisplayError error = kErrorNone;
@@ -779,16 +1307,16 @@
// TODO(user): For now, assume primary to be cmd/video/lvds/edp mode panel only
// Need more concrete info from driver
if ((strncmp(line, "mipi dsi cmd panel", strlen("mipi dsi cmd panel")) == 0)) {
- pri_panel_info_.type = kCommandModePanel;
+ primary_panel_info_.type = kCommandModePanel;
fb_node_index_[kDevicePrimary] = i;
} else if ((strncmp(line, "mipi dsi video panel", strlen("mipi dsi video panel")) == 0)) {
- pri_panel_info_.type = kVideoModePanel;
+ primary_panel_info_.type = kVideoModePanel;
fb_node_index_[kDevicePrimary] = i;
} else if ((strncmp(line, "lvds panel", strlen("lvds panel")) == 0)) {
- pri_panel_info_.type = kLVDSPanel;
+ primary_panel_info_.type = kLVDSPanel;
fb_node_index_[kDevicePrimary] = i;
} else if ((strncmp(line, "edp panel", strlen("edp panel")) == 0)) {
- pri_panel_info_.type = kEDPPanel;
+ primary_panel_info_.type = kEDPPanel;
fb_node_index_[kDevicePrimary] = i;
} else if ((strncmp(line, "dtv panel", strlen("dtv panel")) == 0)) {
fb_node_index_[kDeviceHDMI] = i;
@@ -820,27 +1348,27 @@
char *tokens[max_count] = { NULL };
if (!ParseLine(line, tokens, max_count, &token_count)) {
if (!strncmp(tokens[0], "pu_en", strlen("pu_en"))) {
- pri_panel_info_.partial_update = atoi(tokens[1]);
+ primary_panel_info_.partial_update = atoi(tokens[1]);
} else if (!strncmp(tokens[0], "xstart", strlen("xstart"))) {
- pri_panel_info_.left_align = atoi(tokens[1]);
+ primary_panel_info_.left_align = atoi(tokens[1]);
} else if (!strncmp(tokens[0], "walign", strlen("walign"))) {
- pri_panel_info_.width_align = atoi(tokens[1]);
+ primary_panel_info_.width_align = atoi(tokens[1]);
} else if (!strncmp(tokens[0], "ystart", strlen("ystart"))) {
- pri_panel_info_.top_align = atoi(tokens[1]);
+ primary_panel_info_.top_align = atoi(tokens[1]);
} else if (!strncmp(tokens[0], "halign", strlen("halign"))) {
- pri_panel_info_.height_align = atoi(tokens[1]);
+ primary_panel_info_.height_align = atoi(tokens[1]);
} else if (!strncmp(tokens[0], "min_w", strlen("min_w"))) {
- pri_panel_info_.min_roi_width = atoi(tokens[1]);
+ primary_panel_info_.min_roi_width = atoi(tokens[1]);
} else if (!strncmp(tokens[0], "min_h", strlen("min_h"))) {
- pri_panel_info_.min_roi_height = atoi(tokens[1]);
+ primary_panel_info_.min_roi_height = atoi(tokens[1]);
} else if (!strncmp(tokens[0], "roi_merge", strlen("roi_merge"))) {
- pri_panel_info_.needs_roi_merge = atoi(tokens[1]);
+ primary_panel_info_.needs_roi_merge = atoi(tokens[1]);
} else if (!strncmp(tokens[0], "dynamic_fps_en", strlen("dyn_fps_en"))) {
- pri_panel_info_.dynamic_fps = atoi(tokens[1]);
+ primary_panel_info_.dynamic_fps = atoi(tokens[1]);
} else if (!strncmp(tokens[0], "min_fps", strlen("min_fps"))) {
- pri_panel_info_.min_fps = atoi(tokens[1]);
+ primary_panel_info_.min_fps = atoi(tokens[1]);
} else if (!strncmp(tokens[0], "max_fps", strlen("max_fps"))) {
- pri_panel_info_.max_fps= atoi(tokens[1]);
+ primary_panel_info_.max_fps= atoi(tokens[1]);
}
}
}
@@ -1000,7 +1528,7 @@
return kErrorHardware;
}
char value = enable ? '1' : '0';
- ssize_t length = write_(hpdfd, &value, 1);
+ ssize_t length = pwrite_(hpdfd, &value, 1, 0);
if (length <= 0) {
DLOGE("Write failed 'hpd' = %d", enable);
ret_value = false;
@@ -1021,7 +1549,7 @@
return -1;
}
- length = read_(edid_file, edid_str, sizeof(edid_str)-1);
+ length = pread_(edid_file, edid_str, sizeof(edid_str)-1, 0);
if (length <= 0) {
DLOGE("%s: edid_modes file empty");
edid_str[0] = '\0';
@@ -1073,4 +1601,46 @@
return true;
}
+void HWFrameBuffer::SetIdleTimeoutMs(Handle device, uint32_t timeout_ms) {
+ char node_path[kMaxStringLength] = {0};
+ HWContext *hw_context = reinterpret_cast<HWContext *>(device);
+
+ DLOGI("idle timeout = %d ms", timeout_ms);
+
+ switch (hw_context->type) {
+ case kDevicePrimary:
+ {
+ // Idle fallback feature is supported only for video mode panel.
+ if (primary_panel_info_.type == kCommandModePanel) {
+ return;
+ }
+
+ snprintf(node_path, sizeof(node_path), "%s%d/idle_time", fb_path_,
+ fb_node_index_[hw_context->type]);
+
+ // Open a sysfs node to send the timeout value to driver.
+ int fd = open_(node_path, O_WRONLY);
+ if (fd < 0) {
+ DLOGE("Unable to open %s, node %s", node_path, strerror(errno));
+ return;
+ }
+
+ char timeout_string[64];
+ snprintf(timeout_string, sizeof(timeout_string), "%d", timeout_ms);
+
+ // Notify driver about the timeout value
+ ssize_t length = pwrite_(fd, timeout_string, strlen(timeout_string), 0);
+ if (length < -1) {
+ DLOGE("Unable to write into %s, node %s", node_path, strerror(errno));
+ }
+
+ close_(fd);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
} // namespace sde
+
diff --git a/displayengine/libs/core/hw_framebuffer.h b/displayengine/libs/core/hw_framebuffer.h
index 2fe5078..5c01e5f 100644
--- a/displayengine/libs/core/hw_framebuffer.h
+++ b/displayengine/libs/core/hw_framebuffer.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -30,7 +30,7 @@
#include <stdlib.h>
#include <linux/msm_mdp_ext.h>
#include <video/msm_hdmi_modes.h>
-
+#include <linux/mdss_rotator.h>
#include <poll.h>
#include <pthread.h>
@@ -40,7 +40,7 @@
class HWFrameBuffer : public HWInterface {
public:
- HWFrameBuffer();
+ explicit HWFrameBuffer(BufferSyncHandler *buffer_sync_handler);
DisplayError Init();
DisplayError Deinit();
virtual DisplayError GetHWCapabilities(HWResourceInfo *hw_res_info);
@@ -56,26 +56,97 @@
virtual DisplayError Doze(Handle device);
virtual DisplayError SetVSyncState(Handle device, bool enable);
virtual DisplayError Standby(Handle device);
+ virtual DisplayError OpenRotatorSession(Handle device, HWLayers *hw_layers);
+ virtual DisplayError CloseRotatorSession(Handle device, int32_t session_id);
virtual DisplayError Validate(Handle device, HWLayers *hw_layers);
virtual DisplayError Commit(Handle device, HWLayers *hw_layers);
+ virtual DisplayError Flush(Handle device);
+ virtual void SetIdleTimeoutMs(Handle device, uint32_t timeout_ms);
private:
+ struct HWDisplay {
+ mdp_layer_commit mdp_disp_commit;
+ mdp_input_layer mdp_in_layers[kMaxSDELayers * 2]; // split panel (left + right)
+ mdp_scale_data scale_data[kMaxSDELayers * 2];
+ mdp_output_layer mdp_out_layer;
+
+ HWDisplay() { Reset(); }
+
+ void Reset() {
+ memset(&mdp_disp_commit, 0, sizeof(mdp_disp_commit));
+ memset(&mdp_in_layers, 0, sizeof(mdp_in_layers));
+ memset(&mdp_out_layer, 0, sizeof(mdp_out_layer));
+ memset(&scale_data, 0, sizeof(scale_data));
+
+ for (uint32_t i = 0; i < kMaxSDELayers * 2; i++) {
+ mdp_in_layers[i].buffer.fence = -1;
+ }
+
+ mdp_disp_commit.version = MDP_COMMIT_VERSION_1_0;
+ mdp_disp_commit.commit_v1.input_layers = mdp_in_layers;
+ mdp_disp_commit.commit_v1.output_layer = &mdp_out_layer;
+ mdp_disp_commit.commit_v1.release_fence = -1;
+ }
+
+ mdp_scale_data* GetScaleRef(uint32_t index) { return &scale_data[index]; }
+
+ void SetScaleData(scalar::Scale scale, uint32_t index) {
+ mdp_scale_data *mdp_scale = &scale_data[index];
+ mdp_scale->enable_pxl_ext = scale.enable_pxl_ext;
+
+ for (int i = 0; i < MAX_PLANES; i++) {
+ mdp_scale->init_phase_x[i] = scale.init_phase_x[i];
+ mdp_scale->phase_step_x[i] = scale.phase_step_x[i];
+ mdp_scale->init_phase_y[i] = scale.init_phase_y[i];
+ mdp_scale->phase_step_y[i] = scale.phase_step_y[i];
+
+ mdp_scale->num_ext_pxls_left[i] = scale.left.extension[i];
+ mdp_scale->num_ext_pxls_top[i] = scale.top.extension[i];
+ mdp_scale->num_ext_pxls_right[i] = scale.right.extension[i];
+ mdp_scale->num_ext_pxls_btm[i] = scale.bottom.extension[i];
+
+ mdp_scale->left_ftch[i] = scale.left.overfetch[i];
+ mdp_scale->top_ftch[i] = scale.top.overfetch[i];
+ mdp_scale->right_ftch[i] = scale.right.overfetch[i];
+ mdp_scale->btm_ftch[i] = scale.bottom.overfetch[i];
+
+ mdp_scale->left_rpt[i] = scale.left.repeat[i];
+ mdp_scale->top_rpt[i] = scale.top.repeat[i];
+ mdp_scale->right_rpt[i] = scale.right.repeat[i];
+ mdp_scale->btm_rpt[i] = scale.bottom.repeat[i];
+
+ mdp_scale->roi_w[i] = scale.roi_width[i];
+ }
+ }
+ };
+
+ struct HWRotator {
+ struct mdp_rotation_request mdp_rot_req;
+ struct mdp_rotation_item mdp_rot_layers[kMaxSDELayers * 2]; // split panel (left + right)
+
+ HWRotator() { Reset(); }
+
+ void Reset() {
+ memset(&mdp_rot_req, 0, sizeof(mdp_rot_req));
+ memset(&mdp_rot_layers, 0, sizeof(mdp_rot_layers));
+
+ for (uint32_t i = 0; i < kMaxSDELayers * 2; i++) {
+ mdp_rot_layers[i].input.fence = -1;
+ mdp_rot_layers[i].output.fence = -1;
+ }
+
+ mdp_rot_req.version = MDP_ROTATION_REQUEST_VERSION_1_0;
+ mdp_rot_req.list = mdp_rot_layers;
+ }
+ };
+
struct HWContext {
HWDeviceType type;
int device_fd;
- mdp_layer_commit mdp_commit;
- mdp_input_layer mdp_layers[kMaxSDELayers * 2]; // split panel (left + right) for worst case
+ HWRotator hw_rotator;
+ HWDisplay hw_display;
- HWContext() : type(kDeviceMax), device_fd(-1) {
- ResetMDPCommit();
- }
-
- void ResetMDPCommit() {
- memset(&mdp_commit, 0, sizeof(mdp_commit));
- memset(&mdp_layers, 0, sizeof(mdp_layers));
- mdp_commit.version = MDP_COMMIT_VERSION_1_0;
- mdp_commit.commit_v1.input_layers = mdp_layers;
- }
+ HWContext() : type(kDeviceMax), device_fd(-1) { }
};
enum PanelType {
@@ -115,12 +186,23 @@
static const int kMaxStringLength = 1024;
static const int kNumPhysicalDisplays = 2;
- static const int kNumDisplayEvents = 2;
+ static const int kNumDisplayEvents = 3;
static const int kHWMdssVersion5 = 500; // MDSS_V5
+ DisplayError DisplayValidate(HWContext *device_ctx, HWLayers *hw_layers);
+ DisplayError DisplayCommit(HWContext *device_ctx, HWLayers *hw_layers);
+
+ DisplayError RotatorValidate(HWContext *device_ctx, HWLayers *hw_layers);
+ DisplayError RotatorCommit(HWContext *device_ctx, HWLayers *hw_layers);
+
inline DisplayError SetFormat(const LayerBufferFormat &source, uint32_t *target);
+ inline DisplayError SetStride(HWDeviceType device_type, LayerBufferFormat format,
+ uint32_t width, uint32_t *target);
inline void SetBlending(const LayerBlending &source, mdss_mdp_blend_op *target);
inline void SetRect(const LayerRect &source, mdp_rect *target);
+ inline void SyncMerge(const int &fd1, const int &fd2, int *target);
+
+ inline const char *GetDeviceString(HWDeviceType type);
// Event Thread to receive vsync/blank events
static void* DisplayEventThread(void *context);
@@ -128,6 +210,7 @@
void HandleVSync(int display_id, char *data);
void HandleBlank(int display_id, char *data);
+ void HandleIdleTimeout(int display_id, char *data);
// Populates HW FrameBuffer Node Index
void PopulateFBNodeIndex();
@@ -141,7 +224,6 @@
bool EnableHotPlugDetection(int enable);
int GetHDMIModeCount();
bool MapHDMIDisplayTiming(const msm_hdmi_mode_timing_info *mode, fb_var_screeninfo *info);
- void ResetHDMIModes();
// Pointers to system calls which are either mapped to actual system call or virtual driver.
int (*ioctl_)(int, int, ...);
@@ -149,12 +231,10 @@
int (*close_)(int);
int (*poll_)(struct pollfd *, nfds_t, int);
ssize_t (*pread_)(int, void *, size_t, off_t);
+ ssize_t (*pwrite_)(int, const void *, size_t, off_t);
FILE* (*fopen_)( const char *fname, const char *mode);
int (*fclose_)(FILE* fileptr);
ssize_t (*getline_)(char **lineptr, size_t *linelen, FILE *stream);
- ssize_t (*read_)(int fd, void *buf, size_t count);
- ssize_t (*write_)(int fd, const void *buf, size_t count);
-
// Store the Device EventHandlers - used for callback
HWEventHandler *event_handler_[kNumPhysicalDisplays];
@@ -166,12 +246,13 @@
HWResourceInfo hw_resource_;
int fb_node_index_[kDeviceMax];
const char* fb_path_;
- PanelInfo pri_panel_info_;
+ PanelInfo primary_panel_info_;
bool hotplug_enabled_;
uint32_t hdmi_mode_count_;
uint32_t hdmi_modes_[256];
// Holds the hdmi timing information. Ex: resolution, fps etc.,
msm_hdmi_mode_timing_info *supported_video_modes_;
+ BufferSyncHandler *buffer_sync_handler_;
};
} // namespace sde
diff --git a/displayengine/libs/core/hw_interface.cpp b/displayengine/libs/core/hw_interface.cpp
old mode 100755
new mode 100644
index 3ab0c7e..6b99a73
--- a/displayengine/libs/core/hw_interface.cpp
+++ b/displayengine/libs/core/hw_interface.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -29,11 +29,11 @@
namespace sde {
-DisplayError HWInterface::Create(HWInterface **intf) {
+DisplayError HWInterface::Create(HWInterface **intf, BufferSyncHandler *buffer_sync_handler) {
DisplayError error = kErrorNone;
HWFrameBuffer *hw_frame_buffer = NULL;
- hw_frame_buffer = new HWFrameBuffer();
+ hw_frame_buffer = new HWFrameBuffer(buffer_sync_handler);
error = hw_frame_buffer->Init();
if (UNLIKELY(error != kErrorNone)) {
delete hw_frame_buffer;
diff --git a/displayengine/libs/core/hw_interface.h b/displayengine/libs/core/hw_interface.h
index c8611f9..084768e 100644
--- a/displayengine/libs/core/hw_interface.h
+++ b/displayengine/libs/core/hw_interface.h
@@ -28,6 +28,9 @@
#include <core/display_interface.h>
#include <private/strategy_interface.h>
#include <utils/constants.h>
+#include <core/buffer_allocator.h>
+#include <core/buffer_sync_handler.h>
+#include <scalar.h>
namespace sde {
@@ -44,7 +47,8 @@
kDevicePrimary,
kDeviceHDMI,
kDeviceVirtual,
- kDeviceMax
+ kDeviceRotator,
+ kDeviceMax,
};
struct HWResourceInfo {
@@ -90,48 +94,69 @@
max_pipe_bw(0), max_sde_clk(0), clk_fudge_factor(1.0f), has_bwc(false),
has_decimation(false), has_macrotile(false), has_rotator_downscale(false),
has_non_scalar_rgb(false), is_src_split(false), always_src_split(false) { }
+
+ void Reset() { *this = HWResourceInfo(); }
+};
+
+struct HWBufferInfo : public BufferInfo {
+ LayerBuffer output_buffer;
+ int session_id;
+ uint32_t slot;
+
+ HWBufferInfo() : session_id(-1), slot(0) { }
};
struct HWRotateInfo {
- int pipe_id;
+ uint32_t pipe_id;
LayerRect src_roi;
LayerRect dst_roi;
+ LayerBufferFormat dst_format;
HWBlockType writeback_id;
float downscale_ratio_x;
float downscale_ratio_y;
+ HWBufferInfo hw_buffer_info;
+ bool valid;
- HWRotateInfo() : pipe_id(0), writeback_id(kHWWriteback0), downscale_ratio_x(1.0f),
- downscale_ratio_y(1.0f) { }
+ HWRotateInfo() : pipe_id(0), dst_format(kFormatInvalid), writeback_id(kHWWriteback0),
+ downscale_ratio_x(1.0f), downscale_ratio_y(1.0f), valid(false) { }
- inline void Reset() { *this = HWRotateInfo(); }
+ void Reset() { *this = HWRotateInfo(); }
};
struct HWPipeInfo {
- int pipe_id;
+ uint32_t pipe_id;
LayerRect src_roi;
LayerRect dst_roi;
uint8_t horizontal_decimation;
uint8_t vertical_decimation;
+ scalar::Scale scale_data;
+ bool valid;
- HWPipeInfo() : pipe_id(0), horizontal_decimation(0), vertical_decimation(0) { }
+ HWPipeInfo() : pipe_id(0), horizontal_decimation(0), vertical_decimation(0), valid(false) { }
- inline void Reset() { *this = HWPipeInfo(); }
+ void Reset() { *this = HWPipeInfo(); }
};
struct HWLayerConfig {
bool use_non_dma_pipe; // set by client
- bool is_right_pipe; // indicate if right pipe is valid
HWPipeInfo left_pipe; // pipe for left side of the buffer
HWPipeInfo right_pipe; // pipe for right side of the buffer
uint32_t num_rotate; // number of rotate
HWRotateInfo rotates[kMaxRotatePerLayer]; // rotation for the buffer
- HWLayerConfig() : use_non_dma_pipe(false), is_right_pipe(false), num_rotate(0) { }
+ HWLayerConfig() : use_non_dma_pipe(false), num_rotate(0) { }
+
+ void Reset() { *this = HWLayerConfig(); }
};
struct HWLayers {
HWLayersInfo info;
HWLayerConfig config[kMaxSDELayers];
+ int closed_session_ids[kMaxSDELayers * 2]; // split panel (left + right)
+
+ HWLayers() { memset(closed_session_ids, -1, sizeof(closed_session_ids)); }
+
+ void Reset() { *this = HWLayers(); }
};
struct HWDisplayAttributes : DisplayConfigVariableInfo {
@@ -139,20 +164,23 @@
uint32_t split_left;
HWDisplayAttributes() : is_device_split(false), split_left(0) { }
+
+ void Reset() { *this = HWDisplayAttributes(); }
};
// HWEventHandler - Implemented in DisplayBase and HWInterface implementation
class HWEventHandler {
public:
virtual DisplayError VSync(int64_t timestamp) = 0;
- virtual DisplayError Blank(bool blank)= 0;
+ virtual DisplayError Blank(bool blank) = 0;
+ virtual void IdleTimeout() = 0;
protected:
- virtual ~HWEventHandler() {}
+ virtual ~HWEventHandler() { }
};
class HWInterface {
public:
- static DisplayError Create(HWInterface **intf);
+ static DisplayError Create(HWInterface **intf, BufferSyncHandler *buffer_sync_handler);
static DisplayError Destroy(HWInterface *intf);
virtual DisplayError GetHWCapabilities(HWResourceInfo *hw_res_info) = 0;
virtual DisplayError Open(HWDeviceType type, Handle *device, HWEventHandler *eventhandler) = 0;
@@ -167,8 +195,12 @@
virtual DisplayError Doze(Handle device) = 0;
virtual DisplayError SetVSyncState(Handle device, bool enable) = 0;
virtual DisplayError Standby(Handle device) = 0;
+ virtual DisplayError OpenRotatorSession(Handle device, HWLayers *hw_layers) = 0;
+ virtual DisplayError CloseRotatorSession(Handle device, int32_t session_id) = 0;
virtual DisplayError Validate(Handle device, HWLayers *hw_layers) = 0;
virtual DisplayError Commit(Handle device, HWLayers *hw_layers) = 0;
+ virtual DisplayError Flush(Handle device) = 0;
+ virtual void SetIdleTimeoutMs(Handle device, uint32_t timeout_ms) = 0;
protected:
virtual ~HWInterface() { }
diff --git a/displayengine/libs/core/offline_ctrl.cpp b/displayengine/libs/core/offline_ctrl.cpp
old mode 100755
new mode 100644
index c380d52..5ffaf22
--- a/displayengine/libs/core/offline_ctrl.cpp
+++ b/displayengine/libs/core/offline_ctrl.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -31,17 +31,131 @@
namespace sde {
-OfflineCtrl::OfflineCtrl() : hw_intf_(NULL) {
+// TODO(user): Move this offline controller under composition manager like other modules
+// [resource manager]. Implement session management and buffer management in offline controller.
+OfflineCtrl::OfflineCtrl() : hw_intf_(NULL), hw_rotator_device_(NULL) {
}
DisplayError OfflineCtrl::Init(HWInterface *hw_intf, HWResourceInfo hw_res_info) {
hw_intf_ = hw_intf;
+ DisplayError error = kErrorNone;
+
+ error = hw_intf_->Open(kDeviceRotator, &hw_rotator_device_, NULL);
+ if (error != kErrorNone) {
+ DLOGW("Failed to open rotator device");
+ }
+
return kErrorNone;
}
DisplayError OfflineCtrl::Deinit() {
+ DisplayError error = kErrorNone;
+
+ error = hw_intf_->Close(hw_rotator_device_);
+ if (error != kErrorNone) {
+ DLOGW("Failed to close rotator device");
+ return error;
+ }
+
return kErrorNone;
}
+DisplayError OfflineCtrl::RegisterDisplay(DisplayType type, Handle *display_ctx) {
+ DisplayOfflineContext *disp_offline_ctx = new DisplayOfflineContext();
+ if (disp_offline_ctx == NULL) {
+ return kErrorMemory;
+ }
+
+ disp_offline_ctx->display_type = type;
+ *display_ctx = disp_offline_ctx;
+
+ return kErrorNone;
+}
+
+void OfflineCtrl::UnregisterDisplay(Handle display_ctx) {
+ DisplayOfflineContext *disp_offline_ctx = reinterpret_cast<DisplayOfflineContext *>(display_ctx);
+
+ delete disp_offline_ctx;
+ disp_offline_ctx = NULL;
+}
+
+
+DisplayError OfflineCtrl::Prepare(Handle display_ctx, HWLayers *hw_layers) {
+ DisplayError error = kErrorNone;
+
+ DisplayOfflineContext *disp_offline_ctx = reinterpret_cast<DisplayOfflineContext *>(display_ctx);
+
+ if (!hw_rotator_device_ && IsRotationRequired(hw_layers)) {
+ DLOGV_IF(kTagOfflineCtrl, "No Rotator device found");
+ return kErrorHardware;
+ }
+
+ disp_offline_ctx->pending_rot_commit = false;
+
+ uint32_t i = 0;
+ while (hw_layers->closed_session_ids[i] >= 0) {
+ error = hw_intf_->CloseRotatorSession(hw_rotator_device_, hw_layers->closed_session_ids[i]);
+ if (LIKELY(error != kErrorNone)) {
+ DLOGE("Rotator close session failed");
+ return error;
+ }
+ hw_layers->closed_session_ids[i++] = -1;
+ }
+
+
+ if (IsRotationRequired(hw_layers)) {
+ error = hw_intf_->OpenRotatorSession(hw_rotator_device_, hw_layers);
+ if (LIKELY(error != kErrorNone)) {
+ DLOGE("Rotator open session failed");
+ return error;
+ }
+
+ error = hw_intf_->Validate(hw_rotator_device_, hw_layers);
+ if (LIKELY(error != kErrorNone)) {
+ DLOGE("Rotator validation failed");
+ return error;
+ }
+ disp_offline_ctx->pending_rot_commit = true;
+ }
+
+ return kErrorNone;
+}
+
+DisplayError OfflineCtrl::Commit(Handle display_ctx, HWLayers *hw_layers) {
+ DisplayError error = kErrorNone;
+
+ DisplayOfflineContext *disp_offline_ctx = reinterpret_cast<DisplayOfflineContext *>(display_ctx);
+
+ if (disp_offline_ctx->pending_rot_commit) {
+ error = hw_intf_->Commit(hw_rotator_device_, hw_layers);
+ if (error != kErrorNone) {
+ DLOGE("Rotator commit failed");
+ return error;
+ }
+ disp_offline_ctx->pending_rot_commit = false;
+ }
+
+ return kErrorNone;
+}
+
+bool OfflineCtrl::IsRotationRequired(HWLayers *hw_layers) {
+ HWLayersInfo &layer_info = hw_layers->info;
+
+ for (uint32_t i = 0; i < layer_info.count; i++) {
+ Layer& layer = layer_info.stack->layers[layer_info.index[i]];
+
+ HWRotateInfo *rotate = &hw_layers->config[i].rotates[0];
+ if (rotate->valid) {
+ return true;
+ }
+
+ rotate = &hw_layers->config[i].rotates[1];
+ if (rotate->valid) {
+ return true;
+ }
+ }
+ return false;
+}
+
} // namespace sde
diff --git a/displayengine/libs/core/offline_ctrl.h b/displayengine/libs/core/offline_ctrl.h
index 8987bb3..fafdf7c 100644
--- a/displayengine/libs/core/offline_ctrl.h
+++ b/displayengine/libs/core/offline_ctrl.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -26,6 +26,7 @@
#define __OFFLINE_CTRL_H__
#include <utils/locker.h>
+#include <utils/debug.h>
#include "hw_interface.h"
@@ -36,9 +37,23 @@
OfflineCtrl();
DisplayError Init(HWInterface *hw_intf, HWResourceInfo hw_res_info);
DisplayError Deinit();
+ DisplayError RegisterDisplay(DisplayType type, Handle *display_ctx);
+ void UnregisterDisplay(Handle display_ctx);
+ DisplayError Prepare(Handle display_ctx, HWLayers *hw_layers);
+ DisplayError Commit(Handle display_ctx, HWLayers *hw_layers);
private:
+ struct DisplayOfflineContext {
+ DisplayType display_type;
+ bool pending_rot_commit;
+
+ DisplayOfflineContext() : display_type(kPrimary), pending_rot_commit(false) { }
+ };
+
+ bool IsRotationRequired(HWLayers *hw_layers);
+
HWInterface *hw_intf_;
+ Handle hw_rotator_device_;
};
} // namespace sde
diff --git a/displayengine/libs/core/res_config.cpp b/displayengine/libs/core/res_config.cpp
index 1fc1598..d3c2d26 100644
--- a/displayengine/libs/core/res_config.cpp
+++ b/displayengine/libs/core/res_config.cpp
@@ -25,11 +25,15 @@
#include <math.h>
#include <utils/constants.h>
#include <utils/debug.h>
+#include <utils/rect.h>
#include "res_manager.h"
#define __CLASS__ "ResManager"
+using scalar::PipeInfo;
+using scalar::LayerInfo;
+
namespace sde {
void ResManager::RotationConfig(const LayerTransform &transform, const float &scale_x,
@@ -47,11 +51,18 @@
rotate->downscale_ratio_y = scale_y;
// downscale when doing rotation
- dst_rect.right = src_height / rotate->downscale_ratio_x;
- dst_rect.bottom = src_width / rotate->downscale_ratio_y;
+ if (IsRotationNeeded(transform.rotation)) {
+ dst_rect.right = src_height / rotate->downscale_ratio_x;
+ dst_rect.bottom = src_width / rotate->downscale_ratio_y;
+ } else {
+ dst_rect.right = src_width / rotate->downscale_ratio_x;
+ dst_rect.bottom = src_height / rotate->downscale_ratio_y;
+ }
+ dst_rect.right = floorf(dst_rect.right);
+ dst_rect.bottom = floorf(dst_rect.bottom);
rotate->src_roi = *src_rect;
- rotate->pipe_id = kPipeIdNeedsAssignment;
+ rotate->valid = true;
rotate->dst_roi = dst_rect;
*src_rect = dst_rect;
@@ -65,21 +76,20 @@
HWDisplayAttributes &display_attributes = display_resource_ctx->display_attributes;
HWPipeInfo *left_pipe = &layer_config->left_pipe;
HWPipeInfo *right_pipe = &layer_config->right_pipe;
- layer_config->is_right_pipe = false;
- if ((src_rect.right - src_rect.left) >= kMaxSourcePipeWidth ||
- (dst_rect.right - dst_rect.left) >= kMaxInterfaceWidth || hw_res_info_.always_src_split) {
+ if ((src_rect.right - src_rect.left) > kMaxSourcePipeWidth ||
+ (dst_rect.right - dst_rect.left) > kMaxInterfaceWidth || hw_res_info_.always_src_split) {
SplitRect(transform.flip_horizontal, src_rect, dst_rect, &left_pipe->src_roi,
&left_pipe->dst_roi, &right_pipe->src_roi, &right_pipe->dst_roi);
- left_pipe->pipe_id = kPipeIdNeedsAssignment;
- right_pipe->pipe_id = kPipeIdNeedsAssignment;
- layer_config->is_right_pipe = true;
+ left_pipe->valid = true;
+ right_pipe->valid = true;
} else {
left_pipe->src_roi = src_rect;
left_pipe->dst_roi = dst_rect;
- left_pipe->pipe_id = kPipeIdNeedsAssignment;
+ left_pipe->valid = true;
right_pipe->Reset();
}
+
return kErrorNone;
}
@@ -87,12 +97,13 @@
const LayerTransform &transform,
const LayerRect &src_rect, const LayerRect &dst_rect,
HWLayerConfig *layer_config) {
+ LayerRect scissor_dst_left, scissor_dst_right;
HWDisplayAttributes &display_attributes = display_resource_ctx->display_attributes;
+
// for display split case
HWPipeInfo *left_pipe = &layer_config->left_pipe;
HWPipeInfo *right_pipe = &layer_config->right_pipe;
LayerRect scissor, dst_left, crop_left, crop_right, dst_right;
- layer_config->is_right_pipe = false;
scissor.right = FLOAT(display_attributes.split_left);
scissor.bottom = FLOAT(display_attributes.y_pixels);
@@ -107,29 +118,33 @@
scissor.right = FLOAT(display_attributes.x_pixels);
scissor.bottom = FLOAT(display_attributes.y_pixels);
CalculateCropRects(scissor, transform, &crop_right, &dst_right);
- if ((crop_left.right - crop_left.left) >= kMaxSourcePipeWidth) {
- if (crop_right.right != crop_right.left)
+ if ((crop_left.right - crop_left.left) > kMaxSourcePipeWidth) {
+ if (crop_right.right != crop_right.left) {
+ DLOGV_IF(kTagResources, "Need more than 2 pipes: left width = %.0f, right width = %.0f",
+ crop_left.right - crop_left.left, crop_right.right - crop_right.left);
return kErrorNotSupported;
+ }
// 2 pipes both are on the left
SplitRect(transform.flip_horizontal, crop_left, dst_left, &left_pipe->src_roi,
&left_pipe->dst_roi, &right_pipe->src_roi, &right_pipe->dst_roi);
- left_pipe->pipe_id = kPipeIdNeedsAssignment;
- right_pipe->pipe_id = kPipeIdNeedsAssignment;
- layer_config->is_right_pipe = true;
- } else if ((crop_right.right - crop_right.left) >= kMaxSourcePipeWidth) {
- if (crop_left.right != crop_left.left)
+ left_pipe->valid = true;
+ right_pipe->valid = true;
+ } else if ((crop_right.right - crop_right.left) > kMaxSourcePipeWidth) {
+ if (crop_left.right != crop_left.left) {
+ DLOGV_IF(kTagResources, "Need more than 2 pipes: left width = %.0f, right width = %.0f",
+ crop_left.right - crop_left.left, crop_right.right - crop_right.left);
return kErrorNotSupported;
+ }
// 2 pipes both are on the right
SplitRect(transform.flip_horizontal, crop_right, dst_right, &left_pipe->src_roi,
&left_pipe->dst_roi, &right_pipe->src_roi, &right_pipe->dst_roi);
- left_pipe->pipe_id = kPipeIdNeedsAssignment;
- right_pipe->pipe_id = kPipeIdNeedsAssignment;
- layer_config->is_right_pipe = true;
+ left_pipe->valid = true;
+ right_pipe->valid = true;
} else if (UINT32(dst_left.right) > UINT32(dst_left.left)) {
// assign left pipe
left_pipe->src_roi = crop_left;
left_pipe->dst_roi = dst_left;
- left_pipe->pipe_id = kPipeIdNeedsAssignment;
+ left_pipe->valid = true;
} else {
// Set default value, left_pipe is not needed.
left_pipe->Reset();
@@ -137,16 +152,15 @@
// assign right pipe if needed
if (UINT32(dst_right.right) > UINT32(dst_right.left)) {
- if (left_pipe->pipe_id) {
+ if (left_pipe->valid) {
right_pipe->src_roi = crop_right;
right_pipe->dst_roi = dst_right;
- right_pipe->pipe_id = kPipeIdNeedsAssignment;
- layer_config->is_right_pipe = true;
+ right_pipe->valid = true;
} else {
// If left pipe is not used, use left pipe first.
left_pipe->src_roi = crop_right;
left_pipe->dst_roi = dst_right;
- left_pipe->pipe_id = kPipeIdNeedsAssignment;
+ left_pipe->valid = true;
right_pipe->Reset();
}
} else {
@@ -168,9 +182,9 @@
Layer& layer = layer_info.stack->layers[layer_info.index[i]];
float rot_scale_x = 1.0f, rot_scale_y = 1.0f;
if (!IsValidDimension(layer.src_rect, layer.dst_rect)) {
- DLOGE_IF(kTagResources, "Input is invalid");
- LogRectVerbose("input layer src_rect", layer.src_rect);
- LogRectVerbose("input layer dst_rect", layer.dst_rect);
+ DLOGV_IF(kTagResources, "Input is invalid");
+ LogRect(kTagResources, "input layer src_rect", layer.src_rect);
+ LogRect(kTagResources, "input layer dst_rect", layer.dst_rect);
return kErrorNotSupported;
}
@@ -217,27 +231,33 @@
// rectangle of video layer to be even.
// 2. Normalize source and destination rect of a layer to multiple of 1.
uint32_t factor = (1 << layer.input_buffer->flags.video);
- if (left_pipe.pipe_id == kPipeIdNeedsAssignment) {
+ if (left_pipe.valid) {
NormalizeRect(factor, &left_pipe.src_roi);
NormalizeRect(1, &left_pipe.dst_roi);
}
- if (right_pipe.pipe_id == kPipeIdNeedsAssignment) {
+ if (right_pipe.valid) {
NormalizeRect(factor, &right_pipe.src_roi);
NormalizeRect(1, &right_pipe.dst_roi);
}
DLOGV_IF(kTagResources, "layer = %d, left pipe_id = %x",
i, layer_config->left_pipe.pipe_id);
- LogRectVerbose("input layer src_rect", layer.src_rect);
- LogRectVerbose("input layer dst_rect", layer.dst_rect);
- LogRectVerbose("cropped src_rect", src_rect);
- LogRectVerbose("cropped dst_rect", dst_rect);
- LogRectVerbose("left pipe src", layer_config->left_pipe.src_roi);
- LogRectVerbose("left pipe dst", layer_config->left_pipe.dst_roi);
+ LogRect(kTagResources, "input layer src_rect", layer.src_rect);
+ LogRect(kTagResources, "input layer dst_rect", layer.dst_rect);
+ for (uint32_t k = 0; k < layer_config->num_rotate; k++) {
+ DLOGV_IF(kTagResources, "rotate num = %d, scale_x = %.2f, scale_y = %.2f",
+ k, rot_scale_x, rot_scale_y);
+ LogRect(kTagResources, "rotate src", layer_config->rotates[k].src_roi);
+ LogRect(kTagResources, "rotate dst", layer_config->rotates[k].dst_roi);
+ }
+ LogRect(kTagResources, "cropped src_rect", src_rect);
+ LogRect(kTagResources, "cropped dst_rect", dst_rect);
+ LogRect(kTagResources, "left pipe src", layer_config->left_pipe.src_roi);
+ LogRect(kTagResources, "left pipe dst", layer_config->left_pipe.dst_roi);
if (hw_layers->config[i].right_pipe.pipe_id) {
- LogRectVerbose("right pipe src", layer_config->right_pipe.src_roi);
- LogRectVerbose("right pipe dst", layer_config->right_pipe.dst_roi);
+ LogRect(kTagResources, "right pipe src", layer_config->right_pipe.src_roi);
+ LogRect(kTagResources, "right pipe dst", layer_config->right_pipe.dst_roi);
}
}
@@ -402,6 +422,7 @@
return;
CalculateCut(transform, &left_cut_ratio, &top_cut_ratio, &right_cut_ratio, &bottom_cut_ratio);
+
crop_left += crop_width * left_cut_ratio;
crop_top += crop_height * top_cut_ratio;
crop_right -= crop_width * right_cut_ratio;
@@ -414,7 +435,7 @@
src.top - roundf(src.top) ||
src.right - roundf(src.right) ||
src.bottom - roundf(src.bottom)) {
- DLOGE_IF(kTagResources, "Input ROI is not integral");
+ DLOGV_IF(kTagResources, "Input ROI is not integral");
return false;
}
@@ -512,21 +533,123 @@
}
}
-void ResManager::LogRectVerbose(const char *prefix, const LayerRect &roi) {
- DLOGV_IF(kTagResources, "%s: left = %.0f, top = %.0f, right = %.0f, bottom = %.0f",
- prefix, roi.left, roi.top, roi.right, roi.bottom);
+// Scalar helper functions
+static void SetPipeInfo(HWPipeInfo* hw_pipe, PipeInfo* pipe) {
+ pipe->id = hw_pipe->pipe_id;
+ pipe->scale_data = &hw_pipe->scale_data;
+ pipe->horz_deci = hw_pipe->horizontal_decimation;
+ pipe->vert_deci = hw_pipe->vertical_decimation;
+
+ pipe->src_rect.x = UINT32(hw_pipe->src_roi.left);
+ pipe->src_rect.y = UINT32(hw_pipe->src_roi.top);
+ pipe->src_rect.w = UINT32(hw_pipe->src_roi.right) - pipe->src_rect.x;
+ pipe->src_rect.h = UINT32(hw_pipe->src_roi.bottom) - pipe->src_rect.y;
+
+ pipe->dst_rect.x = UINT32(hw_pipe->dst_roi.left);
+ pipe->dst_rect.y = UINT32(hw_pipe->dst_roi.top);
+ pipe->dst_rect.w = UINT32(hw_pipe->dst_roi.right) - pipe->dst_rect.x;
+ pipe->dst_rect.h = UINT32(hw_pipe->dst_roi.bottom) - pipe->dst_rect.y;
}
-void ResManager::NormalizeRect(const uint32_t &factor, LayerRect *rect) {
- uint32_t left = UINT32(ceilf(rect->left));
- uint32_t top = UINT32(ceilf(rect->top));
- uint32_t right = UINT32(floorf(rect->right));
- uint32_t bottom = UINT32(floorf(rect->bottom));
+static void UpdateSrcRoi(PipeInfo* pipe, HWPipeInfo* hw_pipe) {
+ hw_pipe->src_roi.left = FLOAT(pipe->src_rect.x);
+ hw_pipe->src_roi.top = FLOAT(pipe->src_rect.y);
+ hw_pipe->src_roi.right = FLOAT(pipe->src_rect.x + pipe->src_rect.w);
+ hw_pipe->src_roi.bottom = FLOAT(pipe->src_rect.y + pipe->src_rect.h);
+}
- rect->left = FLOAT(CeilToMultipleOf(left, factor));
- rect->top = FLOAT(CeilToMultipleOf(top, factor));
- rect->right = FLOAT(FloorToMultipleOf(right, factor));
- rect->bottom = FLOAT(FloorToMultipleOf(bottom, factor));
+static uint32_t GetScalarFormat(LayerBufferFormat source) {
+ uint32_t format = scalar::UNKNOWN_FORMAT;
+
+ switch (source) {
+ case kFormatARGB8888: format = scalar::ARGB_8888; break;
+ case kFormatRGBA8888: format = scalar::RGBA_8888; break;
+ case kFormatBGRA8888: format = scalar::BGRA_8888; break;
+ case kFormatXRGB8888: format = scalar::XRGB_8888; break;
+ case kFormatRGBX8888: format = scalar::RGBX_8888; break;
+ case kFormatBGRX8888: format = scalar::BGRX_8888; break;
+ case kFormatRGB888: format = scalar::RGB_888; break;
+ case kFormatRGB565: format = scalar::RGB_565; break;
+ case kFormatYCbCr420Planar: format = scalar::Y_CB_CR_H2V2; break;
+ case kFormatYCrCb420Planar: format = scalar::Y_CR_CB_H2V2; break;
+ case kFormatYCbCr420SemiPlanar: format = scalar::Y_CBCR_H2V2; break;
+ case kFormatYCrCb420SemiPlanar: format = scalar::Y_CRCB_H2V2; break;
+ case kFormatYCbCr422Packed: format = scalar::YCBYCR_H2V1; break;
+ case kFormatYCbCr420SemiPlanarVenus: format = scalar::Y_CBCR_H2V2_VENUS; break;
+ case kFormatRGBA8888Ubwc: format = scalar::RGBA_8888_UBWC; break;
+ case kFormatRGB565Ubwc: format = scalar::RGB_565_UBWC; break;
+ case kFormatYCbCr420SPVenusUbwc: format = scalar::Y_CBCR_H2V2_UBWC; break;
+ default:
+ DLOGE("Unsupported source format: %x", source);
+ break;
+ }
+
+ return format;
+}
+
+bool ResManager::ConfigureScaling(HWLayers *hw_layers) {
+ HWLayersInfo &hw_layer_info = hw_layers->info;
+
+ for (uint32_t i = 0; i < hw_layer_info.count; i++) {
+ Layer &layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
+ LayerBuffer *input_buffer = layer.input_buffer;
+ HWPipeInfo* left_pipe = &hw_layers->config[i].left_pipe;
+ HWPipeInfo* right_pipe = &hw_layers->config[i].right_pipe;
+
+ // Prepare data structure for lib scalar
+ uint32_t flags = 0;
+ struct LayerInfo layer_info;
+
+ if (layer.transform.rotation == 90.0f) {
+ // Flips will be taken care by rotator, if layer requires 90 rotation
+ flags |= scalar::SCALAR_SOURCE_ROTATED_90;
+ } else {
+ flags |= layer.transform.flip_vertical ? scalar::SCALAR_FLIP_UD : 0;
+ flags |= layer.transform.flip_horizontal ? scalar::SCALAR_FLIP_LR : 0;
+ }
+
+ for (uint32_t count = 0; count < 2; count++) {
+ HWPipeInfo* hw_pipe = (count == 0) ? left_pipe : right_pipe;
+ HWRotateInfo* rotate_info = &hw_layers->config[i].rotates[count];
+ PipeInfo* scalar_pipe = (count == 0) ? &layer_info.left_pipe : &layer_info.right_pipe;
+
+ if (rotate_info->valid)
+ input_buffer = &rotate_info->hw_buffer_info.output_buffer;
+
+ scalar_pipe->flags = flags;
+ hw_pipe->scale_data.src_width = input_buffer->width;
+ SetPipeInfo(hw_pipe, scalar_pipe);
+ }
+ layer_info.src_format = GetScalarFormat(input_buffer->format);
+
+ DLOGV_IF(kTagResources, "Scalar Input[%d] flags=%x format=%x", i, flags, layer_info.src_format);
+ DLOGV_IF(kTagResources, "Left: id=%d hD=%d vD=%d srcRect=[%d %d %d %d] dstRect=[%d %d %d %d]",
+ layer_info.left_pipe.id, layer_info.left_pipe.horz_deci, layer_info.left_pipe.vert_deci,
+ layer_info.left_pipe.src_rect.x, layer_info.left_pipe.src_rect.y,
+ layer_info.left_pipe.src_rect.w, layer_info.left_pipe.src_rect.h,
+ layer_info.left_pipe.dst_rect.x, layer_info.left_pipe.dst_rect.y,
+ layer_info.left_pipe.dst_rect.w, layer_info.left_pipe.dst_rect.h);
+ DLOGV_IF(kTagResources, "Right: id=%d hD=%d vD=%d srcRect=[%d %d %d %d] dstRect=[%d %d %d %d]",
+ layer_info.right_pipe.id, layer_info.right_pipe.horz_deci, layer_info.right_pipe.vert_deci,
+ layer_info.right_pipe.src_rect.x, layer_info.right_pipe.src_rect.y,
+ layer_info.right_pipe.src_rect.w, layer_info.right_pipe.src_rect.h,
+ layer_info.right_pipe.dst_rect.x, layer_info.right_pipe.dst_rect.y,
+ layer_info.right_pipe.dst_rect.w, layer_info.right_pipe.dst_rect.h);
+
+ // Configure scale data structure
+ if (ScalarConfigureScale(&layer_info) < 0) {
+ DLOGE("Scalar library failed to configure scale data!");
+ return false;
+ }
+
+ // Update Src Roi in HWPipeInfo
+ if (left_pipe->scale_data.enable_pxl_ext)
+ UpdateSrcRoi(&layer_info.left_pipe, left_pipe);
+ if (right_pipe->scale_data.enable_pxl_ext)
+ UpdateSrcRoi(&layer_info.right_pipe, right_pipe);
+ }
+
+ return true;
}
} // namespace sde
diff --git a/displayengine/libs/core/res_manager.cpp b/displayengine/libs/core/res_manager.cpp
index 12ef5bd..fb8f2eb 100644
--- a/displayengine/libs/core/res_manager.cpp
+++ b/displayengine/libs/core/res_manager.cpp
@@ -25,20 +25,33 @@
#include <math.h>
#include <utils/constants.h>
#include <utils/debug.h>
+#include <dlfcn.h>
#include "res_manager.h"
#define __CLASS__ "ResManager"
+#define SCALAR_LIBRARY_NAME "libscalar.so"
namespace sde {
ResManager::ResManager()
- : num_pipe_(0), vig_pipes_(NULL), rgb_pipes_(NULL), dma_pipes_(NULL), virtual_count_(0) {
+ : num_pipe_(0), vig_pipes_(NULL), rgb_pipes_(NULL), dma_pipes_(NULL), virtual_count_(0),
+ buffer_allocator_(NULL), buffer_sync_handler_(NULL) {
}
-DisplayError ResManager::Init(const HWResourceInfo &hw_res_info) {
+DisplayError ResManager::Init(const HWResourceInfo &hw_res_info, BufferAllocator *buffer_allocator,
+ BufferSyncHandler *buffer_sync_handler) {
hw_res_info_ = hw_res_info;
+ buffer_sync_handler_ = buffer_sync_handler;
+
+ if (!hw_res_info_.max_mixer_width)
+ hw_res_info_.max_mixer_width = kMaxSourcePipeWidth;
+
+ buffer_allocator_ = buffer_allocator;
+
+ buffer_sync_handler_ = buffer_sync_handler;
+
DisplayError error = kErrorNone;
// TODO(user): Remove this. Disable src_split as kernel not supported yet
@@ -80,6 +93,9 @@
DLOGI("hw_rev=%x, DMA=%d RGB=%d VIG=%d", hw_res_info_.hw_revision, hw_res_info_.num_dma_pipe,
hw_res_info_.num_rgb_pipe, hw_res_info_.num_vig_pipe);
+ // TODO(user): Need to get it from HW capability
+ hw_res_info_.num_rotator = 2;
+
if (hw_res_info_.num_rotator > kMaxNumRotator) {
DLOGE("Number of rotator is over the limit! %d", hw_res_info_.num_rotator);
return kErrorParameters;
@@ -98,10 +114,23 @@
rgb_pipes_[0].state = kPipeStateOwnedByKernel;
rgb_pipes_[1].state = kPipeStateOwnedByKernel;
+ ScalarConfigureScale = NULL;
+ lib_scalar_handle_ = dlopen(SCALAR_LIBRARY_NAME, RTLD_NOW);
+ if (lib_scalar_handle_) {
+ void **scalar_func = reinterpret_cast<void **>(&ScalarConfigureScale);
+ *scalar_func = ::dlsym(lib_scalar_handle_, "configureScale");
+ } else {
+ DLOGW("Unable to load %s !", SCALAR_LIBRARY_NAME);
+ }
+
return kErrorNone;
}
DisplayError ResManager::Deinit() {
+ if (lib_scalar_handle_) {
+ dlclose(lib_scalar_handle_);
+ lib_scalar_handle_ = NULL;
+ }
return kErrorNone;
}
@@ -143,6 +172,13 @@
return kErrorMemory;
}
+ display_resource_ctx->buffer_manager = new BufferManager(buffer_allocator_, buffer_sync_handler_);
+ if (display_resource_ctx->buffer_manager == NULL) {
+ delete display_resource_ctx;
+ display_resource_ctx = NULL;
+ return kErrorMemory;
+ }
+
hw_block_ctx_[hw_block_id].is_in_use = true;
display_resource_ctx->display_attributes = attributes;
@@ -254,8 +290,9 @@
// allocate rotator
error = AcquireRotator(display_resource_ctx, rotate_count);
- if (error != kErrorNone)
+ if (error != kErrorNone) {
return error;
+ }
rotate_count = 0;
for (uint32_t i = 0; i < layer_info.count; i++) {
@@ -278,7 +315,7 @@
bool is_yuv = IsYuvFormat(layer.input_buffer->format);
// left pipe is needed
- if (pipe_info->pipe_id) {
+ if (pipe_info->valid) {
need_scale = IsScalingNeeded(pipe_info);
left_index = GetPipe(hw_block_id, is_yuv, need_scale, false, use_non_dma_pipe);
if (left_index >= num_pipe_) {
@@ -293,7 +330,7 @@
}
pipe_info = &layer_config.right_pipe;
- if (pipe_info->pipe_id == 0) {
+ if (!pipe_info->valid) {
// assign single pipe
if (left_index < num_pipe_) {
layer_config.left_pipe.pipe_id = src_pipes_[left_index].mdss_pipe_id;
@@ -331,6 +368,19 @@
i, layer_config.left_pipe.pipe_id, pipe_info->pipe_id);
}
+ error = AllocRotatorBuffer(display_ctx, hw_layers);
+ if (error != kErrorNone) {
+ DLOGV_IF(kTagResources, "Rotator buffer allocation failed");
+ goto CleanupOnError;
+ }
+
+ if (lib_scalar_handle_ && ScalarConfigureScale) {
+ if (!ConfigureScaling(hw_layers)) {
+ DLOGV_IF(kTagResources, "Scale data configuration has failed!");
+ goto CleanupOnError;
+ }
+ }
+
if (!CheckBandwidth(display_resource_ctx, hw_layers)) {
DLOGV_IF(kTagResources, "Bandwidth check failed!");
goto CleanupOnError;
@@ -348,6 +398,11 @@
}
bool ResManager::CheckBandwidth(DisplayResourceContext *display_ctx, HWLayers *hw_layers) {
+ // No need to check bandwidth for virtual displays
+ if (display_ctx->display_type == kVirtual) {
+ return true;
+ }
+
float max_pipe_bw = FLOAT(hw_res_info_.max_pipe_bw) / 1000000; // KBps to GBps
float max_sde_clk = FLOAT(hw_res_info_.max_sde_clk) / 1000000; // Hz to MHz
const struct HWLayersInfo &layer_info = hw_layers->info;
@@ -360,19 +415,19 @@
for (uint32_t i = 0; i < layer_info.count; i++) {
Layer &layer = layer_info.stack->layers[layer_info.index[i]];
float bpp = GetBpp(layer.input_buffer->format);
- uint32_t left_id = hw_layers->config[i].left_pipe.pipe_id;
- uint32_t right_id = hw_layers->config[i].right_pipe.pipe_id;
+ HWPipeInfo *left_pipe = &hw_layers->config[i].left_pipe;
+ HWPipeInfo *right_pipe = &hw_layers->config[i].right_pipe;
- left_pipe_bw[i] = left_id ? GetPipeBw(display_ctx, &hw_layers->config[i].left_pipe, bpp) : 0;
- right_pipe_bw[i] = right_id ? GetPipeBw(display_ctx, &hw_layers->config[i].right_pipe, bpp) : 0;
+ left_pipe_bw[i] = left_pipe->valid ? GetPipeBw(display_ctx, left_pipe, bpp) : 0;
+ right_pipe_bw[i] = right_pipe->valid ? GetPipeBw(display_ctx, right_pipe, bpp) : 0;
if ((left_pipe_bw[i] > max_pipe_bw) || (right_pipe_bw[i] > max_pipe_bw)) {
DLOGV_IF(kTagResources, "Pipe bandwidth exceeds limit for layer index = %d", i);
return false;
}
- float left_clk = left_id ? GetClockForPipe(display_ctx, &hw_layers->config[i].left_pipe) : 0;
- float right_clk = right_id ? GetClockForPipe(display_ctx, &hw_layers->config[i].right_pipe) : 0;
+ float left_clk = left_pipe->valid ? GetClockForPipe(display_ctx, left_pipe) : 0;
+ float right_clk = right_pipe->valid ? GetClockForPipe(display_ctx, right_pipe) : 0;
left_max_clk = MAX(left_clk, left_max_clk);
right_max_clk = MAX(right_clk, right_max_clk);
@@ -556,12 +611,105 @@
}
}
-void ResManager::PostCommit(Handle display_ctx, HWLayers *hw_layers) {
+DisplayError ResManager::AllocRotatorBuffer(Handle display_ctx, HWLayers *hw_layers) {
+ DisplayResourceContext *display_resource_ctx =
+ reinterpret_cast<DisplayResourceContext *>(display_ctx);
+ DisplayError error = kErrorNone;
+
+ BufferManager *buffer_manager = display_resource_ctx->buffer_manager;
+ HWLayersInfo &layer_info = hw_layers->info;
+
+ // TODO(user): Do session management during prepare and allocate buffer and associate that with
+ // the session during commit.
+ buffer_manager->Start();
+
+ for (uint32_t i = 0; i < layer_info.count; i++) {
+ Layer& layer = layer_info.stack->layers[layer_info.index[i]];
+ HWRotateInfo *rotate = &hw_layers->config[i].rotates[0];
+
+ if (rotate->valid) {
+ LayerBufferFormat rot_ouput_format;
+ SetRotatorOutputFormat(layer.input_buffer->format, false, true, &rot_ouput_format);
+
+ HWBufferInfo *hw_buffer_info = &rotate->hw_buffer_info;
+ hw_buffer_info->buffer_config.width = UINT32(rotate->dst_roi.right - rotate->dst_roi.left);
+ hw_buffer_info->buffer_config.height = UINT32(rotate->dst_roi.bottom - rotate->dst_roi.top);
+ hw_buffer_info->buffer_config.format = rot_ouput_format;
+ hw_buffer_info->buffer_config.buffer_count = 2;
+ hw_buffer_info->buffer_config.secure = layer.input_buffer->flags.secure;
+
+ error = buffer_manager->GetNextBuffer(hw_buffer_info);
+ if (error != kErrorNone) {
+ return error;
+ }
+ }
+
+ rotate = &hw_layers->config[i].rotates[1];
+ if (rotate->valid) {
+ LayerBufferFormat rot_ouput_format;
+ SetRotatorOutputFormat(layer.input_buffer->format, false, true, &rot_ouput_format);
+
+ HWBufferInfo *hw_buffer_info = &rotate->hw_buffer_info;
+ hw_buffer_info->buffer_config.width = UINT32(rotate->dst_roi.right - rotate->dst_roi.left);
+ hw_buffer_info->buffer_config.height = UINT32(rotate->dst_roi.bottom - rotate->dst_roi.top);
+ hw_buffer_info->buffer_config.format = rot_ouput_format;
+ hw_buffer_info->buffer_config.buffer_count = 2;
+ hw_buffer_info->buffer_config.secure = layer.input_buffer->flags.secure;
+
+ error = buffer_manager->GetNextBuffer(hw_buffer_info);
+ if (error != kErrorNone) {
+ return error;
+ }
+ }
+ }
+ buffer_manager->Stop(hw_layers->closed_session_ids);
+
+ return kErrorNone;
+}
+
+DisplayError ResManager::PostPrepare(Handle display_ctx, HWLayers *hw_layers) {
+ SCOPE_LOCK(locker_);
+ DisplayResourceContext *display_resource_ctx =
+ reinterpret_cast<DisplayResourceContext *>(display_ctx);
+ DisplayError error = kErrorNone;
+
+ BufferManager *buffer_manager = display_resource_ctx->buffer_manager;
+ HWLayersInfo &layer_info = hw_layers->info;
+
+ for (uint32_t i = 0; i < layer_info.count; i++) {
+ Layer& layer = layer_info.stack->layers[layer_info.index[i]];
+ HWRotateInfo *rotate = &hw_layers->config[i].rotates[0];
+
+ if (rotate->valid) {
+ HWBufferInfo *hw_buffer_info = &rotate->hw_buffer_info;
+
+ error = buffer_manager->SetSessionId(hw_buffer_info->slot, hw_buffer_info->session_id);
+ if (error != kErrorNone) {
+ return error;
+ }
+ }
+
+ rotate = &hw_layers->config[i].rotates[1];
+ if (rotate->valid) {
+ HWBufferInfo *hw_buffer_info = &rotate->hw_buffer_info;
+
+ error = buffer_manager->SetSessionId(hw_buffer_info->slot, hw_buffer_info->session_id);
+ if (error != kErrorNone) {
+ return error;
+ }
+ }
+ }
+
+ return kErrorNone;
+}
+
+DisplayError ResManager::PostCommit(Handle display_ctx, HWLayers *hw_layers) {
SCOPE_LOCK(locker_);
DisplayResourceContext *display_resource_ctx =
reinterpret_cast<DisplayResourceContext *>(display_ctx);
HWBlockType hw_block_id = display_resource_ctx->hw_block_id;
uint64_t frame_count = display_resource_ctx->frame_count;
+ DisplayError error = kErrorNone;
DLOGV_IF(kTagResources, "Resource for hw_block = %d, frame_count = %d", hw_block_id, frame_count);
@@ -609,6 +757,37 @@
}
}
display_resource_ctx->frame_start = false;
+
+ BufferManager *buffer_manager = display_resource_ctx->buffer_manager;
+ HWLayersInfo &layer_info = hw_layers->info;
+
+ for (uint32_t i = 0; i < layer_info.count; i++) {
+ Layer& layer = layer_info.stack->layers[layer_info.index[i]];
+ HWRotateInfo *rotate = &hw_layers->config[i].rotates[0];
+
+ if (rotate->valid) {
+ HWBufferInfo *rot_buf_info = &rotate->hw_buffer_info;
+
+ error = buffer_manager->SetReleaseFd(rot_buf_info->slot,
+ rot_buf_info->output_buffer.release_fence_fd);
+ if (error != kErrorNone) {
+ return error;
+ }
+ }
+
+ rotate = &hw_layers->config[i].rotates[1];
+ if (rotate->valid) {
+ HWBufferInfo *rot_buf_info = &rotate->hw_buffer_info;
+
+ error = buffer_manager->SetReleaseFd(rot_buf_info->slot,
+ rot_buf_info->output_buffer.release_fence_fd);
+ if (error != kErrorNone) {
+ return error;
+ }
+ }
+ }
+
+ return kErrorNone;
}
void ResManager::Purge(Handle display_ctx) {
@@ -775,21 +954,33 @@
void ResManager::AppendDump(char *buffer, uint32_t length) {
SCOPE_LOCK(locker_);
AppendString(buffer, length, "\nresource manager pipe state");
- for (uint32_t i = 0; i < num_pipe_; i++) {
+ uint32_t i;
+ for (i = 0; i < num_pipe_; i++) {
SourcePipe *src_pipe = &src_pipes_[i];
AppendString(buffer, length,
"\nindex = %d, id = %x, reserved = %d, state = %d, hw_block = %d, dedicated = %d",
src_pipe->index, src_pipe->mdss_pipe_id, src_pipe->reserved_hw_block,
src_pipe->state, src_pipe->hw_block_id, src_pipe->dedicated_hw_block);
}
+
+ for (i = 0; i < hw_res_info_.num_rotator; i++) {
+ if (rotators_[i].client_bit_mask || rotators_[i].request_bit_mask) {
+ AppendString(buffer, length,
+ "\nrotator = %d, pipe index = %x, client_bit_mask = %x, request_bit_mask = %x",
+ i, rotators_[i].pipe_index, rotators_[i].client_bit_mask,
+ rotators_[i].request_bit_mask);
+ }
+ }
}
DisplayError ResManager::AcquireRotator(DisplayResourceContext *display_resource_ctx,
const uint32_t rotate_count) {
if (rotate_count == 0)
return kErrorNone;
- if (hw_res_info_.num_rotator == 0)
+ if (hw_res_info_.num_rotator == 0) {
+ DLOGV_IF(kTagResources, "Rotator hardware is not available");
return kErrorResources;
+ }
uint32_t i, j, pipe_index, num_rotator;
if (rotate_count > hw_res_info_.num_rotator)
@@ -830,7 +1021,7 @@
}
void ResManager::AssignRotator(HWRotateInfo *rotate, uint32_t *rotate_count) {
- if (!rotate->pipe_id)
+ if (!rotate->valid)
return;
// Interleave rotator assignment
if ((*rotate_count & 0x1) && (hw_res_info_.num_rotator > 1)) {
@@ -859,5 +1050,45 @@
}
}
+void ResManager::SetRotatorOutputFormat(const LayerBufferFormat &input_format, bool bwc, bool rot90,
+ LayerBufferFormat *output_format) {
+ switch (input_format) {
+ case kFormatRGB565:
+ if (rot90)
+ *output_format = kFormatRGB888;
+ else
+ *output_format = input_format;
+ break;
+ case kFormatRGBA8888:
+ if (bwc)
+ *output_format = kFormatBGRA8888;
+ else
+ *output_format = input_format;
+ break;
+ case kFormatYCbCr420SemiPlanarVenus:
+ case kFormatYCbCr420SemiPlanar:
+ if (rot90)
+ *output_format = kFormatYCrCb420SemiPlanar;
+ else
+ *output_format = input_format;
+ break;
+ case kFormatYCbCr420Planar:
+ case kFormatYCrCb420Planar:
+ *output_format = kFormatYCrCb420SemiPlanar;
+ break;
+ default:
+ *output_format = input_format;
+ break;
+ }
+
+ DLOGV_IF(kTagResources, "Input format %x, Output format = %x, rot90 %d", input_format,
+ *output_format, rot90);
+
+ return;
+}
+
+void* ResManager::lib_scalar_handle_ = NULL;
+int (*ResManager::ScalarConfigureScale)(struct scalar::LayerInfo* layer) = NULL;
+
} // namespace sde
diff --git a/displayengine/libs/core/res_manager.h b/displayengine/libs/core/res_manager.h
index cf0a55f..c80dc2c 100644
--- a/displayengine/libs/core/res_manager.h
+++ b/displayengine/libs/core/res_manager.h
@@ -30,13 +30,15 @@
#include "hw_interface.h"
#include "dump_impl.h"
+#include "buffer_manager.h"
namespace sde {
class ResManager : public DumpImpl {
public:
ResManager();
- DisplayError Init(const HWResourceInfo &hw_res_info);
+ DisplayError Init(const HWResourceInfo &hw_res_info, BufferAllocator *buffer_allocator,
+ BufferSyncHandler *buffer_sync_handler);
DisplayError Deinit();
DisplayError RegisterDisplay(DisplayType type, const HWDisplayAttributes &attributes,
Handle *display_ctx);
@@ -44,7 +46,8 @@
DisplayError Start(Handle display_ctx);
DisplayError Stop(Handle display_ctx);
DisplayError Acquire(Handle display_ctx, HWLayers *hw_layers);
- void PostCommit(Handle display_ctx, HWLayers *hw_layers);
+ DisplayError PostPrepare(Handle display_ctx, HWLayers *hw_layers);
+ DisplayError PostCommit(Handle display_ctx, HWLayers *hw_layers);
void Purge(Handle display_ctx);
// DumpImpl method
@@ -111,14 +114,23 @@
struct DisplayResourceContext {
HWDisplayAttributes display_attributes;
+ BufferManager *buffer_manager;
DisplayType display_type;
HWBlockType hw_block_id;
uint64_t frame_count;
int32_t session_id; // applicable for virtual display sessions only
uint32_t rotate_count;
bool frame_start;
+
DisplayResourceContext() : hw_block_id(kHWBlockMax), frame_count(0), session_id(-1),
rotate_count(0), frame_start(false) { }
+
+ ~DisplayResourceContext() {
+ if (buffer_manager) {
+ delete buffer_manager;
+ buffer_manager = NULL;
+ }
+ }
};
struct HWBlockContext {
@@ -175,33 +187,17 @@
bool IsYuvFormat(LayerBufferFormat format) { return (format >= kFormatYCbCr420Planar); }
bool IsRotationNeeded(float rotation)
{ return (UINT32(rotation) == 90 || UINT32(rotation) == 270); }
- void LogRectVerbose(const char *prefix, const LayerRect &roi);
void RotationConfig(const LayerTransform &transform, const float &scale_x,
- const float &scale_y,LayerRect *src_rect,
+ const float &scale_y, LayerRect *src_rect,
struct HWLayerConfig *layer_config, uint32_t *rotate_count);
DisplayError AcquireRotator(DisplayResourceContext *display_resource_ctx,
const uint32_t roate_cnt);
void AssignRotator(HWRotateInfo *rotate, uint32_t *rotate_cnt);
void ClearRotator(DisplayResourceContext *display_resource_ctx);
- void NormalizeRect(const uint32_t &factor, LayerRect *rect);
-
- template <class T>
- inline void Swap(T &a, T &b) {
- T c(a);
- a = b;
- b = c;
- }
-
- // factor value should be in powers of 2(eg: 1, 2, 4, 8)
- template <class T1, class T2>
- inline T1 FloorToMultipleOf(const T1 &value, const T2 &factor) {
- return (T1)(value & (~(factor - 1)));
- }
-
- template <class T1, class T2>
- inline T1 CeilToMultipleOf(const T1 &value, const T2 &factor) {
- return (T1)((value + (factor - 1)) & (~(factor - 1)));
- }
+ DisplayError AllocRotatorBuffer(Handle display_ctx, HWLayers *hw_layers);
+ void SetRotatorOutputFormat(const LayerBufferFormat &input_format, bool bwc, bool rot90,
+ LayerBufferFormat *output_format);
+ bool ConfigureScaling(HWLayers *hw_layers);
Locker locker_;
HWResourceInfo hw_res_info_;
@@ -217,6 +213,11 @@
float last_primary_bw_;
uint32_t virtual_count_;
struct HWRotator rotators_[kMaxNumRotator];
+ BufferAllocator *buffer_allocator_;
+ BufferSyncHandler *buffer_sync_handler_; // Pointer to buffer sync handler that was defined by
+ // the display engine's client
+ static void* lib_scalar_handle_; // Scalar library handle
+ static int (*ScalarConfigureScale)(struct scalar::LayerInfo* layer);
};
} // namespace sde
diff --git a/displayengine/libs/hwc/Android.mk b/displayengine/libs/hwc/Android.mk
old mode 100755
new mode 100644
index 1271e00..d31c71e
--- a/displayengine/libs/hwc/Android.mk
+++ b/displayengine/libs/hwc/Android.mk
@@ -6,17 +6,20 @@
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := hardware/qcom/display/displayengine/include/ \
hardware/qcom/display/libgralloc/ \
- hardware/qcom/display/libqservice/
+ hardware/qcom/display/libqservice/ \
+ hardware/qcom/display/libqdutils/
LOCAL_CFLAGS := -Wno-missing-field-initializers -Wno-unused-parameter \
-Wconversion -Wall -Werror \
-DLOG_TAG=\"SDE\"
LOCAL_SHARED_LIBRARIES := libsde libqservice libbinder libhardware libhardware_legacy \
- libutils libcutils
+ libutils libcutils libsync libmemalloc libqdutils
LOCAL_SRC_FILES := hwc_session.cpp \
hwc_display.cpp \
hwc_display_primary.cpp \
hwc_display_external.cpp \
hwc_display_virtual.cpp \
- hwc_logger.cpp
+ hwc_debugger.cpp \
+ hwc_buffer_allocator.cpp \
+ hwc_buffer_sync_handler.cpp
include $(BUILD_SHARED_LIBRARY)
diff --git a/displayengine/libs/hwc/hwc_buffer_allocator.cpp b/displayengine/libs/hwc/hwc_buffer_allocator.cpp
new file mode 100644
index 0000000..d4f4bac
--- /dev/null
+++ b/displayengine/libs/hwc/hwc_buffer_allocator.cpp
@@ -0,0 +1,171 @@
+/*
+* Copyright (c) 2015, 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 <gralloc_priv.h>
+#include <memalloc.h>
+#include <gr.h>
+#include <alloc_controller.h>
+#include <utils/constants.h>
+#include <core/buffer_allocator.h>
+
+#include "hwc_debugger.h"
+#include "hwc_buffer_allocator.h"
+
+#define __CLASS__ "HWCBufferAllocator"
+
+namespace sde {
+
+HWCBufferAllocator::HWCBufferAllocator() {
+ alloc_controller_ = gralloc::IAllocController::getInstance();
+}
+
+DisplayError HWCBufferAllocator::AllocateBuffer(BufferInfo *buffer_info) {
+ gralloc::alloc_data data;
+
+ const BufferConfig &buffer_config = buffer_info->buffer_config;
+ AllocatedBufferInfo *alloc_buffer_info = &buffer_info->alloc_buffer_info;
+ MetaBufferInfo *meta_buffer_info = new MetaBufferInfo();
+
+ if (!meta_buffer_info) {
+ return kErrorMemory;
+ }
+
+ int alloc_flags = GRALLOC_USAGE_PRIVATE_IOMMU_HEAP;
+ int error = 0;
+
+ int width = INT(buffer_config.width);
+ int height = INT(buffer_config.height);
+ int format;
+
+ error = SetHALFormat(buffer_config.format, &format);
+ if (error != 0) {
+ return kErrorParameters;
+ }
+
+ if (buffer_config.secure) {
+ alloc_flags = GRALLOC_USAGE_PRIVATE_MM_HEAP;
+ alloc_flags |= GRALLOC_USAGE_PROTECTED;
+ data.align = kSecureBufferAlignment;
+ } else {
+ data.align = getpagesize();
+ }
+
+ if (buffer_config.cache == false) {
+ // Allocate uncached buffers
+ alloc_flags |= GRALLOC_USAGE_PRIVATE_UNCACHED;
+ }
+
+ int aligned_width = 0, aligned_height = 0;
+ uint32_t buffer_size = getBufferSizeAndDimensions(width, height, format, alloc_flags,
+ aligned_width, aligned_height);
+
+ buffer_size = ROUND_UP((buffer_size * buffer_config.buffer_count), data.align);
+
+ data.base = 0;
+ data.fd = -1;
+ data.offset = 0;
+ data.size = buffer_size;
+ data.uncached = !buffer_config.cache;
+
+ error = alloc_controller_->allocate(data, alloc_flags);
+ if (error != 0) {
+ DLOGE("Error allocating memory size %d uncached %d", data.size, data.uncached);
+ return kErrorMemory;
+ }
+
+ alloc_buffer_info->fd = data.fd;
+ alloc_buffer_info->stride = aligned_width;
+ alloc_buffer_info->size = buffer_size;
+
+ meta_buffer_info->base_addr = data.base;
+ meta_buffer_info->alloc_type = data.allocType;
+
+ buffer_info->private_data = meta_buffer_info;
+
+ return kErrorNone;
+}
+
+DisplayError HWCBufferAllocator::FreeBuffer(BufferInfo *buffer_info) {
+ int ret = 0;
+
+ AllocatedBufferInfo *alloc_buffer_info = &buffer_info->alloc_buffer_info;
+ MetaBufferInfo *meta_buffer_info = static_cast<MetaBufferInfo *> (buffer_info->private_data);
+ if ((alloc_buffer_info->fd < 0) || (meta_buffer_info->base_addr == NULL)) {
+ return kErrorNone;
+ }
+
+ gralloc::IMemAlloc *memalloc = alloc_controller_->getAllocator(meta_buffer_info->alloc_type);
+ if (memalloc == NULL) {
+ DLOGE("Memalloc handle is NULL, alloc type %d", meta_buffer_info->alloc_type);
+ return kErrorResources;
+ }
+
+ ret = memalloc->free_buffer(meta_buffer_info->base_addr, alloc_buffer_info->size, 0,
+ alloc_buffer_info->fd);
+ if (ret != 0) {
+ DLOGE("Error freeing buffer base_addr %p size %d fd %d", meta_buffer_info->base_addr,
+ alloc_buffer_info->size, alloc_buffer_info->fd);
+ return kErrorMemory;
+ }
+
+ alloc_buffer_info->fd = -1;
+ alloc_buffer_info->stride = 0;
+ alloc_buffer_info->size = 0;
+
+ meta_buffer_info->base_addr = NULL;
+ meta_buffer_info->alloc_type = 0;
+
+ delete meta_buffer_info;
+ meta_buffer_info = NULL;
+
+ return kErrorNone;
+}
+
+int HWCBufferAllocator::SetHALFormat(LayerBufferFormat format, int *target) {
+ switch (format) {
+ case kFormatRGBA8888: *target = HAL_PIXEL_FORMAT_RGBA_8888; break;
+ case kFormatRGBX8888: *target = HAL_PIXEL_FORMAT_RGBX_8888; break;
+ case kFormatRGB888: *target = HAL_PIXEL_FORMAT_RGB_888; break;
+ case kFormatRGB565: *target = HAL_PIXEL_FORMAT_RGB_565; break;
+ case kFormatBGRA8888: *target = HAL_PIXEL_FORMAT_BGRA_8888; break;
+ case kFormatYCrCb420Planar: *target = HAL_PIXEL_FORMAT_YV12; break;
+ case kFormatYCrCb420SemiPlanar: *target = HAL_PIXEL_FORMAT_YCrCb_420_SP; break;
+ case kFormatYCbCr420SemiPlanar: *target = HAL_PIXEL_FORMAT_YCbCr_420_SP; break;
+ case kFormatYCbCr422Packed: *target = HAL_PIXEL_FORMAT_YCbCr_422_I; break;
+ case kFormatYCbCr420SemiPlanarVenus: *target = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS; break;
+
+ default:
+ DLOGE("Unsupported format = 0x%x", format);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+} // namespace sde
diff --git a/displayengine/libs/hwc/hwc_buffer_allocator.h b/displayengine/libs/hwc/hwc_buffer_allocator.h
new file mode 100644
index 0000000..123f04a
--- /dev/null
+++ b/displayengine/libs/hwc/hwc_buffer_allocator.h
@@ -0,0 +1,67 @@
+/*
+* Copyright (c) 2015, 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_BUFFER_ALLOCATOR_H__
+#define __HWC_BUFFER_ALLOCATOR_H__
+
+#include <sys/mman.h>
+#include <fcntl.h>
+
+namespace gralloc {
+
+class IAllocController;
+
+} // namespace gralloc
+
+namespace sde {
+
+class HWCBufferAllocator : public BufferAllocator {
+ public:
+ HWCBufferAllocator();
+
+ DisplayError AllocateBuffer(BufferInfo *buffer_info);
+ DisplayError FreeBuffer(BufferInfo *buffer_info);
+
+ private:
+ static const size_t kSecureBufferAlignment = 0x00100000;
+
+ struct MetaBufferInfo {
+ int alloc_type; //!< Specifies allocation type set by the buffer allocator.
+ void *base_addr; //!< Specifies the base address of the allocated output buffer.
+ };
+
+ int SetHALFormat(LayerBufferFormat format, int *target);
+
+ gralloc::IAllocController *alloc_controller_;
+};
+
+} // namespace sde
+#endif // __HWC_BUFFER_ALLOCATOR_H__
+
diff --git a/displayengine/libs/hwc/hwc_buffer_sync_handler.cpp b/displayengine/libs/hwc/hwc_buffer_sync_handler.cpp
new file mode 100644
index 0000000..31788ea
--- /dev/null
+++ b/displayengine/libs/hwc/hwc_buffer_sync_handler.cpp
@@ -0,0 +1,71 @@
+/*
+* Copyright (c) 2015, 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 <sync/sync.h>
+#include <utils/constants.h>
+
+#include "hwc_debugger.h"
+#include "hwc_buffer_sync_handler.h"
+
+#define __CLASS__ "HWCBufferSyncHandler"
+
+namespace sde {
+
+DisplayError HWCBufferSyncHandler::SyncWait(int fd) {
+ int error = 0;
+
+ if (fd >= 0) {
+ error = sync_wait(fd, 1000);
+ if (error < 0) {
+ DLOGE("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
+ close(fd);
+ return kErrorTimeOut;
+ }
+ close(fd);
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWCBufferSyncHandler::SyncMerge(int fd1, int fd2, int *merged_fd) {
+ DisplayError error = kErrorNone;
+
+ *merged_fd = sync_merge("SyncMerge", fd1, fd2);
+ if (*merged_fd == -1) {
+ DLOGE(" Sync merge error! fd1 %d fd2 %d", fd1, fd2);
+ error = kErrorFileDescriptor;
+ }
+ close(fd1);
+ close(fd2);
+
+ return error;
+}
+
+} // namespace sde
+
diff --git a/displayengine/libs/hwc/hwc_buffer_sync_handler.h b/displayengine/libs/hwc/hwc_buffer_sync_handler.h
new file mode 100644
index 0000000..26b1d33
--- /dev/null
+++ b/displayengine/libs/hwc/hwc_buffer_sync_handler.h
@@ -0,0 +1,52 @@
+/*
+* Copyright (c) 2015, 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_BUFFER_SYNC_HANDLER_H__
+#define __HWC_BUFFER_SYNC_HANDLER_H__
+
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <core/sde_types.h>
+#include <core/buffer_sync_handler.h>
+
+namespace sde {
+
+class HWCBufferSyncHandler : public BufferSyncHandler {
+ public:
+ HWCBufferSyncHandler() { }
+
+ virtual DisplayError SyncWait(int fd);
+ virtual DisplayError SyncMerge(int fd1, int fd2, int *merged_fd);
+};
+
+} // namespace sde
+#endif // __HWC_BUFFER_SYNC_HANDLER_H__
+
+
diff --git a/displayengine/libs/hwc/hwc_debugger.cpp b/displayengine/libs/hwc/hwc_debugger.cpp
new file mode 100644
index 0000000..d35e9cf
--- /dev/null
+++ b/displayengine/libs/hwc/hwc_debugger.cpp
@@ -0,0 +1,135 @@
+/*
+* Copyright (c) 2014 - 2015, 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/constants.h>
+
+#include "hwc_debugger.h"
+
+namespace sde {
+
+HWCDebugHandler HWCDebugHandler::debug_handler_;
+uint32_t HWCDebugHandler::debug_flags_ = 0x1;
+
+void HWCDebugHandler::DebugAll(bool enable) {
+ if (enable) {
+ debug_flags_ = 0xFFFFFFFF;
+ } else {
+ debug_flags_ = 0x1; // kTagNone should always be printed.
+ }
+}
+
+void HWCDebugHandler::DebugResources(bool enable) {
+ if (enable) {
+ SET_BIT(debug_flags_, kTagResources);
+ } else {
+ CLEAR_BIT(debug_flags_, kTagResources);
+ }
+}
+
+void HWCDebugHandler::DebugStrategy(bool enable) {
+ if (enable) {
+ SET_BIT(debug_flags_, kTagStrategy);
+ } else {
+ CLEAR_BIT(debug_flags_, kTagStrategy);
+ }
+}
+
+void HWCDebugHandler::DebugCompManager(bool enable) {
+ if (enable) {
+ SET_BIT(debug_flags_, kTagCompManager);
+ } else {
+ CLEAR_BIT(debug_flags_, kTagCompManager);
+ }
+}
+
+void HWCDebugHandler::DebugDriverConfig(bool enable) {
+ if (enable) {
+ SET_BIT(debug_flags_, kTagDriverConfig);
+ } else {
+ CLEAR_BIT(debug_flags_, kTagDriverConfig);
+ }
+}
+
+void HWCDebugHandler::DebugBufferManager(bool enable) {
+ if (enable) {
+ SET_BIT(debug_flags_, kTagBufferManager);
+ } else {
+ CLEAR_BIT(debug_flags_, kTagBufferManager);
+ }
+}
+
+void HWCDebugHandler::DebugOfflineCtrl(bool enable) {
+ if (enable) {
+ SET_BIT(debug_flags_, kTagOfflineCtrl);
+ } else {
+ CLEAR_BIT(debug_flags_, kTagOfflineCtrl);
+ }
+}
+
+void HWCDebugHandler::Error(DebugTag /*tag*/, const char *format, ...) {
+ va_list list;
+ va_start(list, format);
+ __android_log_vprint(ANDROID_LOG_ERROR, LOG_TAG, format, list);
+}
+
+void HWCDebugHandler::Warning(DebugTag /*tag*/, const char *format, ...) {
+ va_list list;
+ va_start(list, format);
+ __android_log_vprint(ANDROID_LOG_WARN, LOG_TAG, format, list);
+}
+
+void HWCDebugHandler::Info(DebugTag tag, const char *format, ...) {
+ if (IS_BIT_SET(debug_flags_, tag)) {
+ va_list list;
+ va_start(list, format);
+ __android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, format, list);
+ }
+}
+
+void HWCDebugHandler::Verbose(DebugTag tag, const char *format, ...) {
+ if (IS_BIT_SET(debug_flags_, tag)) {
+ va_list list;
+ va_start(list, format);
+ __android_log_vprint(ANDROID_LOG_VERBOSE, LOG_TAG, format, list);
+ }
+}
+
+void HWCDebugHandler::BeginTrace(const char *class_name, const char *function_name,
+ const char *custom_string) {
+ char name[PATH_MAX] = {0};
+ snprintf(name, sizeof(name), "%s::%s::%s", class_name, function_name, custom_string);
+ atrace_begin(ATRACE_TAG, name);
+}
+
+void HWCDebugHandler::EndTrace() {
+ atrace_end(ATRACE_TAG);
+}
+
+} // namespace sde
+
diff --git a/displayengine/libs/hwc/hwc_debugger.h b/displayengine/libs/hwc/hwc_debugger.h
new file mode 100644
index 0000000..def31db
--- /dev/null
+++ b/displayengine/libs/hwc/hwc_debugger.h
@@ -0,0 +1,81 @@
+/*
+* Copyright (c) 2014 - 2015, 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_DEBUGGER_H__
+#define __HWC_DEBUGGER_H__
+
+#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
+
+#include <core/sde_types.h>
+#include <core/debug_interface.h>
+#include <cutils/log.h>
+#include <utils/Trace.h>
+
+#define DLOG(Macro, format, ...) Macro(__CLASS__ "::%s: " format, __FUNCTION__, ##__VA_ARGS__)
+
+#define DLOGE(format, ...) DLOG(ALOGE, format, ##__VA_ARGS__)
+#define DLOGW(format, ...) DLOG(ALOGW, format, ##__VA_ARGS__)
+#define DLOGI(format, ...) DLOG(ALOGI, format, ##__VA_ARGS__)
+#define DLOGV(format, ...) DLOG(ALOGV, format, ##__VA_ARGS__)
+
+#define DTRACE_BEGIN(custom_string) HWCDebugHandler::Get()->BeginTrace(__CLASS__, __FUNCTION__, \
+ custom_string)
+#define DTRACE_END() HWCDebugHandler::Get()->EndTrace()
+#define DTRACE_SCOPED() ScopeTracer<HWCDebugHandler> scope_tracer(__CLASS__, __FUNCTION__)
+
+namespace sde {
+
+class HWCDebugHandler : public DebugHandler {
+ public:
+ static inline DebugHandler* Get() { return &debug_handler_; }
+ static void DebugAll(bool enable);
+ static void DebugResources(bool enable);
+ static void DebugStrategy(bool enable);
+ static void DebugCompManager(bool enable);
+ static void DebugDriverConfig(bool enable);
+ static void DebugBufferManager(bool enable);
+ static void DebugOfflineCtrl(bool enable);
+
+ virtual void Error(DebugTag tag, const char *format, ...);
+ virtual void Warning(DebugTag tag, const char *format, ...);
+ virtual void Info(DebugTag tag, const char *format, ...);
+ virtual void Verbose(DebugTag tag, const char *format, ...);
+ virtual void BeginTrace(const char *class_name, const char *function_name,
+ const char *custom_string);
+ virtual void EndTrace();
+
+ private:
+ static HWCDebugHandler debug_handler_;
+ static uint32_t debug_flags_;
+};
+
+} // namespace sde
+
+#endif // __HWC_DEBUGGER_H__
+
diff --git a/displayengine/libs/hwc/hwc_display.cpp b/displayengine/libs/hwc/hwc_display.cpp
index bf54a8a..dd1beac 100644
--- a/displayengine/libs/hwc/hwc_display.cpp
+++ b/displayengine/libs/hwc/hwc_display.cpp
@@ -1,33 +1,40 @@
/*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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.
+* 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.
+* 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 <errno.h>
#include <gralloc_priv.h>
#include <utils/constants.h>
+#include <qdMetaData.h>
+#include <sync/sync.h>
#include "hwc_display.h"
-#include "hwc_logger.h"
+#include "hwc_debugger.h"
#define __CLASS__ "HWCDisplay"
@@ -35,13 +42,16 @@
HWCDisplay::HWCDisplay(CoreInterface *core_intf, hwc_procs_t const **hwc_procs, DisplayType type,
int id)
- : core_intf_(core_intf), hwc_procs_(hwc_procs), type_(type), id_(id), display_intf_(NULL) {
+ : core_intf_(core_intf), hwc_procs_(hwc_procs), type_(type), id_(id), display_intf_(NULL),
+ flush_(false), output_buffer_(NULL), dump_frame_count_(0), dump_frame_index_(0),
+ dump_input_layers_(false) {
}
int HWCDisplay::Init() {
DisplayError error = core_intf_->CreateDisplay(type_, this, &display_intf_);
if (UNLIKELY(error != kErrorNone)) {
- DLOGE("Display create failed. Error = %d", error);
+ DLOGE("Display create failed. Error = %d display_type %d event_handler %p disp_intf %p",
+ error, type_, this, &display_intf_);
return -EINVAL;
}
@@ -55,8 +65,9 @@
return -EINVAL;
}
- if (LIKELY(layer_stack_memory_.raw)) {
+ if (layer_stack_memory_.raw) {
delete[] layer_stack_memory_.raw;
+ layer_stack_memory_.raw = NULL;
}
return 0;
@@ -173,6 +184,10 @@
return index;
}
+int HWCDisplay::SetActiveConfig(hwc_display_contents_1_t *content_list) {
+ return 0;
+}
+
int HWCDisplay::SetActiveConfig(int index) {
DisplayError error = kErrorNone;
@@ -185,6 +200,14 @@
return 0;
}
+void HWCDisplay::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
+ dump_frame_count_ = count;
+ dump_frame_index_ = 0;
+ dump_input_layers_ = ((bit_mask_layer_type & (1 << INPUT_LAYER_DUMP)) != 0);
+
+ DLOGI("num_frame_dump %d, input_layer_dump_enable %d", dump_frame_count_, dump_input_layers_);
+}
+
DisplayError HWCDisplay::VSync(const DisplayEventVSync &vsync) {
if (*hwc_procs_) {
(*hwc_procs_)->vsync(*hwc_procs_, id_, vsync.timestamp);
@@ -282,6 +305,7 @@
size_t num_hw_layers = content_list->numHwLayers;
if (num_hw_layers <= 1) {
+ flush_ = true;
return 0;
}
@@ -294,7 +318,8 @@
LayerBuffer *layer_buffer = layer.input_buffer;
if (pvt_handle) {
- if (SetFormat(pvt_handle->format, &layer_buffer->format)) {
+ layer_buffer->format = GetSDEFormat(pvt_handle->format, pvt_handle->flags);
+ if (layer_buffer->format == kFormatInvalid) {
return -EINVAL;
}
@@ -308,6 +333,13 @@
layer_stack_.flags.secure_present = true;
layer_buffer->flags.secure = true;
}
+
+ // TODO(user) : Initialize it to display refresh rate
+ layer.frame_rate = 60;
+ MetaData_t *meta_data = reinterpret_cast<MetaData_t *>(pvt_handle->base_metadata);
+ if (meta_data && meta_data->operation & UPDATE_REFRESH_RATE) {
+ layer.frame_rate = meta_data->refreshrate;
+ }
}
SetRect(hwc_layer.displayFrame, &layer.dst_rect);
@@ -329,6 +361,10 @@
layer.flags.skip = ((hwc_layer.flags & HWC_SKIP_LAYER) > 0);
layer.flags.updating = (layer_stack_cache_.layer_cache[i].handle != hwc_layer.handle);
+ if (hwc_layer.flags & HWC_SCREENSHOT_ANIMATOR_LAYER) {
+ layer_stack_.flags.animating = true;
+ }
+
if (layer.flags.skip) {
layer_stack_.flags.skip_present = true;
}
@@ -338,9 +374,14 @@
layer_stack_.flags.geometry_changed = ((content_list->flags & HWC_GEOMETRY_CHANGED) > 0);
DisplayError error = display_intf_->Prepare(&layer_stack_);
- if (UNLIKELY(error != kErrorNone)) {
+ if (error != kErrorNone) {
DLOGE("Prepare failed. Error = %d", error);
- return -EINVAL;
+
+ // To prevent surfaceflinger infinite wait, flush the previous frame during Commit() so that
+ // previous buffer and fences are released, and override the error.
+ flush_ = true;
+
+ return 0;
}
bool needs_fb_refresh = NeedsFrameBufferRefresh(content_list);
@@ -378,38 +419,46 @@
int status = 0;
size_t num_hw_layers = content_list->numHwLayers;
- if (num_hw_layers <= 1) {
- if (!num_hw_layers) {
- return 0;
+
+ DumpInputBuffers(content_list);
+
+ if (!flush_) {
+ for (size_t i = 0; i < num_hw_layers; i++) {
+ hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
+ const private_handle_t *pvt_handle = static_cast<const private_handle_t *>(hwc_layer.handle);
+ LayerBuffer *layer_buffer = layer_stack_.layers[i].input_buffer;
+
+ if (pvt_handle) {
+ layer_buffer->planes[0].fd = pvt_handle->fd;
+ layer_buffer->planes[0].offset = pvt_handle->offset;
+ layer_buffer->planes[0].stride = pvt_handle->width;
+ }
+
+ layer_buffer->acquire_fence_fd = hwc_layer.acquireFenceFd;
}
- // TODO(user): handle if only 1 layer(fb target) is received.
- int &acquireFenceFd = content_list->hwLayers[0].acquireFenceFd;
- if (acquireFenceFd >= 0) {
- close(acquireFenceFd);
- }
+ DisplayError error = display_intf_->Commit(&layer_stack_);
+ if (error != kErrorNone) {
+ DLOGE("Commit failed. Error = %d", error);
- return 0;
+ // To prevent surfaceflinger infinite wait, flush the previous frame during Commit() so that
+ // previous buffer and fences are released, and override the error.
+ flush_ = true;
+ }
}
- for (size_t i = 0; i < num_hw_layers; i++) {
- hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
- const private_handle_t *pvt_handle = static_cast<const private_handle_t *>(hwc_layer.handle);
- LayerBuffer *layer_buffer = layer_stack_.layers[i].input_buffer;
+ return status;
+}
- if (pvt_handle) {
- layer_buffer->planes[0].fd = pvt_handle->fd;
- layer_buffer->planes[0].offset = pvt_handle->offset;
- layer_buffer->planes[0].stride = pvt_handle->width;
+int HWCDisplay::PostCommitLayerStack(hwc_display_contents_1_t *content_list) {
+ size_t num_hw_layers = content_list->numHwLayers;
+ int status = 0;
+
+ if (flush_) {
+ DisplayError error = display_intf_->Flush();
+ if (error != kErrorNone) {
+ DLOGE("Flush failed. Error = %d", error);
}
-
- layer_buffer->acquire_fence_fd = hwc_layer.acquireFenceFd;
- }
-
- DisplayError error = display_intf_->Commit(&layer_stack_);
- if (UNLIKELY(error != kErrorNone)) {
- DLOGE("Commit failed. Error = %d", error);
- status = -EINVAL;
}
for (size_t i = 0; i < num_hw_layers; i++) {
@@ -417,19 +466,45 @@
Layer &layer = layer_stack_.layers[i];
LayerBuffer *layer_buffer = layer_stack_.layers[i].input_buffer;
- if ((status == 0) && (layer.composition == kCompositionSDE ||
- layer.composition == kCompositionGPUTarget)) {
- hwc_layer.releaseFenceFd = layer_buffer->release_fence_fd;
+ if (!flush_) {
+ if (layer.composition != kCompositionGPU) {
+ hwc_layer.releaseFenceFd = layer_buffer->release_fence_fd;
+ }
+
+ // During animation on external/virtual display, Display Engine will use the cached
+ // framebuffer layer throughout animation and do not allow framework to do eglswapbuffer on
+ // framebuffer target. So graphics doesn't close the release fence fd of framebuffer target,
+ // Hence close the release fencefd of framebuffer target here.
+ if (layer.composition == kCompositionGPUTarget && layer_stack_cache_.animating) {
+ close(hwc_layer.releaseFenceFd);
+ hwc_layer.releaseFenceFd = -1;
+ }
}
if (hwc_layer.acquireFenceFd >= 0) {
close(hwc_layer.acquireFenceFd);
+ hwc_layer.acquireFenceFd = -1;
}
}
+
+ if (!flush_) {
+ layer_stack_cache_.animating = layer_stack_.flags.animating;
+
+ content_list->retireFenceFd = layer_stack_.retire_fence_fd;
+
+ if (dump_frame_count_) {
+ dump_frame_count_--;
+ dump_frame_index_++;
+ }
+ }
+
+ flush_ = false;
+
return status;
}
+
bool HWCDisplay::NeedsFrameBufferRefresh(hwc_display_contents_1_t *content_list) {
uint32_t layer_count = layer_stack_.layer_count;
@@ -438,8 +513,8 @@
// 2. Any layer is added/removed/layer properties changes in the current layer stack.
// 3. Any layer handle is changed and it is marked for GPU composition
// 4. Any layer's current composition is different from previous composition.
- if ((layer_stack_cache_.layer_count != layer_count) || layer_stack_.flags.skip_present ||
- layer_stack_.flags.geometry_changed) {
+ if (((layer_stack_cache_.layer_count != layer_count) || layer_stack_.flags.skip_present ||
+ layer_stack_.flags.geometry_changed) && !layer_stack_cache_.animating) {
return true;
}
@@ -456,7 +531,8 @@
return true;
}
- if ((layer.composition == kCompositionGPU) && (layer_cache.handle != hwc_layer.handle)) {
+ if ((layer.composition == kCompositionGPU) && (layer_cache.handle != hwc_layer.handle) &&
+ !layer_stack_cache_.animating) {
return true;
}
}
@@ -518,21 +594,159 @@
}
}
-int HWCDisplay::SetFormat(const int32_t &source, LayerBufferFormat *target) {
- switch (source) {
- case HAL_PIXEL_FORMAT_RGBA_8888: *target = kFormatRGBA8888; break;
- case HAL_PIXEL_FORMAT_BGRA_8888: *target = kFormatBGRA8888; break;
- case HAL_PIXEL_FORMAT_RGBX_8888: *target = kFormatRGBX8888; break;
- case HAL_PIXEL_FORMAT_BGRX_8888: *target = kFormatBGRX8888; break;
- case HAL_PIXEL_FORMAT_RGB_888: *target = kFormatRGB888; break;
- case HAL_PIXEL_FORMAT_RGB_565: *target = kFormatRGB565; break;
- case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS: *target = kFormatYCbCr420SemiPlanarVenus; break;
- default:
- DLOGW("Unsupported format type = %d", source);
- return -EINVAL;
+void HWCDisplay::SetIdleTimeoutMs(uint32_t timeout_ms) {
+ if (display_intf_) {
+ display_intf_->SetIdleTimeoutMs(timeout_ms);
+ }
+}
+
+LayerBufferFormat HWCDisplay::GetSDEFormat(const int32_t &source, const int flags) {
+ LayerBufferFormat format = kFormatInvalid;
+ if (flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
+ switch (source) {
+ case HAL_PIXEL_FORMAT_RGBA_8888: format = kFormatRGBA8888Ubwc; break;
+ case HAL_PIXEL_FORMAT_RGB_565: format = kFormatRGB565Ubwc; break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+ case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: format = kFormatYCbCr420SPVenusUbwc; break;
+ default:
+ DLOGE("Unsupported format type for UBWC %d", source);
+ return kFormatInvalid;
+ }
+ return format;
}
- return 0;
+ switch (source) {
+ case HAL_PIXEL_FORMAT_RGBA_8888: format = kFormatRGBA8888; break;
+ case HAL_PIXEL_FORMAT_BGRA_8888: format = kFormatBGRA8888; break;
+ case HAL_PIXEL_FORMAT_RGBX_8888: format = kFormatRGBX8888; break;
+ case HAL_PIXEL_FORMAT_BGRX_8888: format = kFormatBGRX8888; break;
+ case HAL_PIXEL_FORMAT_RGB_888: format = kFormatRGB888; break;
+ case HAL_PIXEL_FORMAT_RGB_565: format = kFormatRGB565; break;
+ case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS: format = kFormatYCbCr420SemiPlanarVenus; break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC: format = kFormatYCbCr420SPVenusUbwc; break;
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP: format = kFormatYCrCb420SemiPlanar; break;
+ default:
+ DLOGW("Unsupported format type = %d", source);
+ return kFormatInvalid;
+ }
+
+ return format;
+}
+
+void HWCDisplay::DumpInputBuffers(hwc_display_contents_1_t *content_list) {
+ size_t num_hw_layers = content_list->numHwLayers;
+ char dir_path[PATH_MAX];
+
+ if (!dump_frame_count_ || flush_ || !dump_input_layers_) {
+ return;
+ }
+
+ snprintf(dir_path, sizeof(dir_path), "/data/misc/display/frame_dump_%s", GetDisplayString());
+
+ if (mkdir(dir_path, 0777) != 0 && errno != EEXIST) {
+ DLOGW("Failed to create %s directory errno = %d, desc = %s", dir_path, errno, strerror(errno));
+ return;
+ }
+
+ // if directory exists already, need to explicitly change the permission.
+ if (errno == EEXIST && chmod(dir_path, 0777) != 0) {
+ DLOGW("Failed to change permissions on %s directory", dir_path);
+ return;
+ }
+
+ for (uint32_t i = 0; i < num_hw_layers; i++) {
+ hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
+ const private_handle_t *pvt_handle = static_cast<const private_handle_t *>(hwc_layer.handle);
+
+ if (hwc_layer.acquireFenceFd >= 0) {
+ int error = sync_wait(hwc_layer.acquireFenceFd, 1000);
+ if (error < 0) {
+ DLOGW("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
+ return;
+ }
+ }
+
+ if (pvt_handle && pvt_handle->base) {
+ char dump_file_name[PATH_MAX];
+ size_t result = 0;
+
+ snprintf(dump_file_name, sizeof(dump_file_name), "%s/input_layer%d_%dx%d_%s_frame%d.raw",
+ dir_path, i, pvt_handle->width, pvt_handle->height,
+ GetHALPixelFormatString(pvt_handle->format), dump_frame_index_);
+
+ FILE* fp = fopen(dump_file_name, "w+");
+ if (fp) {
+ result = fwrite(reinterpret_cast<void *>(pvt_handle->base), pvt_handle->size, 1, fp);
+ fclose(fp);
+ }
+
+ DLOGI("Frame Dump %s: is %s", dump_file_name, result ? "Successful" : "Failed");
+ }
+ }
+}
+
+const char *HWCDisplay::GetHALPixelFormatString(int format) {
+ switch (format) {
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ return "RGBA_8888";
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ return "RGBX_8888";
+ case HAL_PIXEL_FORMAT_RGB_888:
+ return "RGB_888";
+ case HAL_PIXEL_FORMAT_RGB_565:
+ return "RGB_565";
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ return "BGRA_8888";
+ case HAL_PIXEL_FORMAT_RGBA_5551:
+ return "RGBA_5551";
+ case HAL_PIXEL_FORMAT_RGBA_4444:
+ return "RGBA_4444";
+ case HAL_PIXEL_FORMAT_YV12:
+ return "YV12";
+ case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+ return "YCbCr_422_SP_NV16";
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ return "YCrCb_420_SP_NV21";
+ case HAL_PIXEL_FORMAT_YCbCr_422_I:
+ return "YCbCr_422_I_YUY2";
+ case HAL_PIXEL_FORMAT_YCrCb_422_I:
+ return "YCrCb_422_I_YVYU";
+ case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+ return "NV12_ENCODEABLE";
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
+ return "YCbCr_420_SP_TILED_TILE_4x2";
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+ return "YCbCr_420_SP";
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
+ return "YCrCb_420_SP_ADRENO";
+ case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+ return "YCrCb_422_SP";
+ case HAL_PIXEL_FORMAT_R_8:
+ return "R_8";
+ case HAL_PIXEL_FORMAT_RG_88:
+ return "RG_88";
+ case HAL_PIXEL_FORMAT_INTERLACE:
+ return "INTERLACE";
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+ return "YCbCr_420_SP_VENUS";
+ default:
+ return "Unknown pixel format";
+ }
+}
+
+const char *HWCDisplay::GetDisplayString() {
+ switch (type_) {
+ case kPrimary:
+ return "primary";
+ case kHDMI:
+ return "hdmi";
+ case kVirtual:
+ return "virtual";
+ default:
+ return "invalid";
+ }
}
} // namespace sde
diff --git a/displayengine/libs/hwc/hwc_display.h b/displayengine/libs/hwc/hwc_display.h
index 0ba9ca7..a574d6b 100644
--- a/displayengine/libs/hwc/hwc_display.h
+++ b/displayengine/libs/hwc/hwc_display.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -42,6 +42,9 @@
virtual int GetDisplayAttributes(uint32_t config, const uint32_t *attributes, int32_t *values);
virtual int GetActiveConfig();
virtual int SetActiveConfig(int index);
+ virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
+ virtual int SetActiveConfig(hwc_display_contents_1_t *content_list);
+ virtual void SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
protected:
// Maximum number of layers supported by display engine.
@@ -66,8 +69,9 @@
struct LayerStackCache {
LayerCache layer_cache[kMaxLayerCount];
uint32_t layer_count;
+ bool animating;
- LayerStackCache() : layer_count(0) { }
+ LayerStackCache() : layer_count(0), animating(false) { }
};
HWCDisplay(CoreInterface *core_intf, hwc_procs_t const **hwc_procs, DisplayType type, int id);
@@ -80,6 +84,7 @@
virtual int AllocateLayerStack(hwc_display_contents_1_t *content_list);
virtual int PrepareLayerStack(hwc_display_contents_1_t *content_list);
virtual int CommitLayerStack(hwc_display_contents_1_t *content_list);
+ virtual int PostCommitLayerStack(hwc_display_contents_1_t *content_list);
bool NeedsFrameBufferRefresh(hwc_display_contents_1_t *content_list);
void CacheLayerStackInfo(hwc_display_contents_1_t *content_list);
inline void SetRect(const hwc_rect_t &source, LayerRect *target);
@@ -87,7 +92,16 @@
inline void SetComposition(const int32_t &source, LayerComposition *target);
inline void SetComposition(const int32_t &source, int32_t *target);
inline void SetBlending(const int32_t &source, LayerBlending *target);
- inline int SetFormat(const int32_t &source, LayerBufferFormat *target);
+ int SetFormat(const int32_t &source, const int flags, LayerBufferFormat *target);
+ LayerBufferFormat GetSDEFormat(const int32_t &source, const int flags);
+ void DumpInputBuffers(hwc_display_contents_1_t *content_list);
+ const char *GetHALPixelFormatString(int format);
+ const char *GetDisplayString();
+
+ enum {
+ INPUT_LAYER_DUMP,
+ OUTPUT_LAYER_DUMP,
+ };
CoreInterface *core_intf_;
hwc_procs_t const **hwc_procs_;
@@ -97,6 +111,11 @@
LayerStackMemory layer_stack_memory_;
LayerStack layer_stack_;
LayerStackCache layer_stack_cache_;
+ bool flush_;
+ LayerBuffer *output_buffer_;
+ uint32_t dump_frame_count_;
+ uint32_t dump_frame_index_;
+ bool dump_input_layers_;
};
} // namespace sde
diff --git a/displayengine/libs/hwc/hwc_display_external.cpp b/displayengine/libs/hwc/hwc_display_external.cpp
index 468478b..2758e3a 100644
--- a/displayengine/libs/hwc/hwc_display_external.cpp
+++ b/displayengine/libs/hwc/hwc_display_external.cpp
@@ -1,31 +1,36 @@
/*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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.
+* 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.
+* 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/constants.h>
#include "hwc_display_external.h"
-#include "hwc_logger.h"
+#include "hwc_debugger.h"
#define __CLASS__ "HWCDisplayExternal"
@@ -59,7 +64,10 @@
return status;
}
- content_list->retireFenceFd = layer_stack_.retire_fence_fd;
+ status = HWCDisplay::PostCommitLayerStack(content_list);
+ if (status) {
+ return status;
+ }
return 0;
}
diff --git a/displayengine/libs/hwc/hwc_display_primary.cpp b/displayengine/libs/hwc/hwc_display_primary.cpp
index b282ba6..6dbb723 100644
--- a/displayengine/libs/hwc/hwc_display_primary.cpp
+++ b/displayengine/libs/hwc/hwc_display_primary.cpp
@@ -1,31 +1,36 @@
/*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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.
+* 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.
+* 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/constants.h>
#include "hwc_display_primary.h"
-#include "hwc_logger.h"
+#include "hwc_debugger.h"
#define __CLASS__ "HWCDisplayPrimary"
@@ -59,7 +64,10 @@
return status;
}
- content_list->retireFenceFd = layer_stack_.retire_fence_fd;
+ status = HWCDisplay::PostCommitLayerStack(content_list);
+ if (status) {
+ return status;
+ }
return 0;
}
diff --git a/displayengine/libs/hwc/hwc_display_virtual.cpp b/displayengine/libs/hwc/hwc_display_virtual.cpp
old mode 100755
new mode 100644
index 88cd073..9601e63
--- a/displayengine/libs/hwc/hwc_display_virtual.cpp
+++ b/displayengine/libs/hwc/hwc_display_virtual.cpp
@@ -1,47 +1,238 @@
/*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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.
+* 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.
+* 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/constants.h>
+#include <gralloc_priv.h>
+#include <sync/sync.h>
#include "hwc_display_virtual.h"
-#include "hwc_logger.h"
+#include "hwc_debugger.h"
#define __CLASS__ "HWCDisplayVirtual"
namespace sde {
HWCDisplayVirtual::HWCDisplayVirtual(CoreInterface *core_intf, hwc_procs_t const **hwc_procs)
- : HWCDisplay(core_intf, hwc_procs, kVirtual, HWC_DISPLAY_VIRTUAL) {
+ : HWCDisplay(core_intf, hwc_procs, kVirtual, HWC_DISPLAY_VIRTUAL),
+ dump_output_layer_(false) {
+}
+
+int HWCDisplayVirtual::Init() {
+ int status = 0;
+
+ output_buffer_ = new LayerBuffer();
+ if (!output_buffer_) {
+ return -ENOMEM;
+ }
+
+ return HWCDisplay::Init();
+}
+
+int HWCDisplayVirtual::Deinit() {
+ int status = 0;
+
+ status = HWCDisplay::Deinit();
+ if (status) {
+ return status;
+ }
+
+ if (output_buffer_) {
+ delete output_buffer_;
+ }
+
+ return status;
}
int HWCDisplayVirtual::Prepare(hwc_display_contents_1_t *content_list) {
+ int status = 0;
+ status = AllocateLayerStack(content_list);
+ if (status) {
+ return status;
+ }
+
+ status = SetOutputBuffer(content_list);
+ if (status) {
+ return status;
+ }
+
+ status = PrepareLayerStack(content_list);
+ if (status) {
+ return status;
+ }
+
return 0;
}
int HWCDisplayVirtual::Commit(hwc_display_contents_1_t *content_list) {
+ int status = 0;
+
+ status = HWCDisplay::CommitLayerStack(content_list);
+ if (status) {
+ return status;
+ }
+
+ DumpOutputBuffer(content_list);
+
+ status = HWCDisplay::PostCommitLayerStack(content_list);
+ if (status) {
+ return status;
+ }
+
+ if (content_list->outbufAcquireFenceFd >= 0) {
+ close(content_list->outbufAcquireFenceFd);
+ content_list->outbufAcquireFenceFd = -1;
+ }
+
return 0;
}
+int HWCDisplayVirtual::SetActiveConfig(hwc_display_contents_1_t *content_list) {
+ const private_handle_t *output_handle =
+ static_cast<const private_handle_t *>(content_list->outbuf);
+ DisplayError error = kErrorNone;
+ int status = 0;
+
+ if (output_handle) {
+ LayerBufferFormat format = GetSDEFormat(output_handle->format, output_handle->flags);
+ if (format == kFormatInvalid) {
+ return -EINVAL;
+ }
+
+ if ((output_handle->width != INT(output_buffer_->width)) ||
+ (output_handle->height != INT(output_buffer_->height)) ||
+ (format != output_buffer_->format)) {
+ DisplayConfigVariableInfo variable_info;
+
+ variable_info.x_pixels = output_handle->width;
+ variable_info.y_pixels = output_handle->height;
+ // TODO(user): Need to get the framerate of primary display and update it.
+ variable_info.fps = 60;
+
+ error = display_intf_->SetActiveConfig(&variable_info);
+ if (error != kErrorNone) {
+ return -EINVAL;
+ }
+
+ status = SetOutputBuffer(content_list);
+ if (status) {
+ return status;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int HWCDisplayVirtual::SetOutputBuffer(hwc_display_contents_1_t *content_list) {
+ int status = 0;
+
+ const private_handle_t *output_handle =
+ static_cast<const private_handle_t *>(content_list->outbuf);
+
+ // Fill output buffer parameters (width, height, format, plane information, fence)
+ output_buffer_->acquire_fence_fd = content_list->outbufAcquireFenceFd;
+
+ if (output_handle) {
+ output_buffer_->format = GetSDEFormat(output_handle->format, output_handle->flags);
+ if (output_buffer_->format == kFormatInvalid) {
+ return -EINVAL;
+ }
+
+ output_buffer_->width = output_handle->width;
+ output_buffer_->height = output_handle->height;
+ output_buffer_->flags.secure = 0;
+ output_buffer_->flags.video = 0;
+
+ // 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 = output_handle->width;
+ }
+
+ layer_stack_.output_buffer = output_buffer_;
+
+ return status;
+}
+
+void HWCDisplayVirtual::DumpOutputBuffer(hwc_display_contents_1_t *content_list) {
+ const private_handle_t *output_handle = (const private_handle_t *)(content_list->outbuf);
+ char dir_path[PATH_MAX];
+
+ if (!dump_frame_count_ || flush_ || !dump_output_layer_) {
+ return;
+ }
+
+ snprintf(dir_path, sizeof(dir_path), "/data/misc/display/frame_dump_%s", GetDisplayString());
+
+ if (mkdir(dir_path, 777) != 0 && errno != EEXIST) {
+ DLOGW("Failed to create %s directory errno = %d, desc = %s", dir_path, errno, strerror(errno));
+ return;
+ }
+
+ // if directory exists already, need to explicitly change the permission.
+ if (errno == EEXIST && chmod(dir_path, 0777) != 0) {
+ DLOGW("Failed to change permissions on %s directory", dir_path);
+ return;
+ }
+
+ if (output_handle && output_handle->base) {
+ char dump_file_name[PATH_MAX];
+ size_t result = 0;
+
+ if (content_list->outbufAcquireFenceFd >= 0) {
+ int error = sync_wait(content_list->outbufAcquireFenceFd, 1000);
+ if (error < 0) {
+ DLOGW("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
+ return;
+ }
+ }
+
+ snprintf(dump_file_name, sizeof(dump_file_name), "%s/output_layer_%dx%d_%s_frame%d.raw",
+ dir_path, output_handle->width, output_handle->height,
+ GetHALPixelFormatString(output_handle->format), dump_frame_index_);
+
+ FILE* fp = fopen(dump_file_name, "w+");
+ if (fp) {
+ result = fwrite(reinterpret_cast<void *>(output_handle->base), output_handle->size, 1, fp);
+ fclose(fp);
+ }
+
+ DLOGI("Frame Dump of %s is %s", dump_file_name, result ? "Successful" : "Failed");
+ }
+}
+
+void HWCDisplayVirtual::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
+ HWCDisplay::SetFrameDumpConfig(count, bit_mask_layer_type);
+ dump_output_layer_ = ((bit_mask_layer_type & (1 << OUTPUT_LAYER_DUMP)) != 0);
+
+ DLOGI("output_layer_dump_enable %d", dump_output_layer_);
+}
+
} // namespace sde
diff --git a/displayengine/libs/hwc/hwc_display_virtual.h b/displayengine/libs/hwc/hwc_display_virtual.h
index 796ed32..7ac7c22 100644
--- a/displayengine/libs/hwc/hwc_display_virtual.h
+++ b/displayengine/libs/hwc/hwc_display_virtual.h
@@ -32,8 +32,18 @@
class HWCDisplayVirtual : public HWCDisplay {
public:
explicit HWCDisplayVirtual(CoreInterface *core_intf, hwc_procs_t const **hwc_procs);
+ virtual int Init();
+ virtual int Deinit();
virtual int Prepare(hwc_display_contents_1_t *content_list);
virtual int Commit(hwc_display_contents_1_t *content_list);
+ virtual int SetActiveConfig(hwc_display_contents_1_t *content_list);
+ virtual void SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
+
+ private:
+ int SetOutputBuffer(hwc_display_contents_1_t *content_list);
+ void DumpOutputBuffer(hwc_display_contents_1_t *content_list);
+
+ bool dump_output_layer_;
};
} // namespace sde
diff --git a/displayengine/libs/hwc/hwc_logger.cpp b/displayengine/libs/hwc/hwc_logger.cpp
deleted file mode 100755
index 9d65e1c..0000000
--- a/displayengine/libs/hwc/hwc_logger.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
-* Copyright (c) 2014, 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/constants.h>
-
-#include "hwc_logger.h"
-
-namespace sde {
-
-HWCLogHandler HWCLogHandler::log_handler_;
-uint32_t HWCLogHandler::log_flags_ = 0x1;
-
-void HWCLogHandler::LogAll(bool enable) {
- if (enable) {
- log_flags_ = 0xFFFFFFFF;
- } else {
- log_flags_ = 0x1; // kTagNone should always be printed.
- }
-}
-
-void HWCLogHandler::LogResources(bool enable) {
- if (enable) {
- SET_BIT(log_flags_, kTagResources);
- } else {
- CLEAR_BIT(log_flags_, kTagResources);
- }
-}
-
-void HWCLogHandler::LogStrategy(bool enable) {
- if (enable) {
- SET_BIT(log_flags_, kTagStrategy);
- } else {
- CLEAR_BIT(log_flags_, kTagStrategy);
- }
-}
-
-void HWCLogHandler::Error(LogTag /*tag*/, const char *format, ...) {
- va_list list;
- va_start(list, format);
- __android_log_vprint(ANDROID_LOG_ERROR, LOG_TAG, format, list);
-}
-
-void HWCLogHandler::Warning(LogTag /*tag*/, const char *format, ...) {
- va_list list;
- va_start(list, format);
- __android_log_vprint(ANDROID_LOG_WARN, LOG_TAG, format, list);
-}
-
-void HWCLogHandler::Info(LogTag tag, const char *format, ...) {
- if (IS_BIT_SET(log_flags_, tag)) {
- va_list list;
- va_start(list, format);
- __android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, format, list);
- }
-}
-
-void HWCLogHandler::Verbose(LogTag tag, const char *format, ...) {
- if (IS_BIT_SET(log_flags_, tag)) {
- va_list list;
- va_start(list, format);
- __android_log_vprint(ANDROID_LOG_VERBOSE, LOG_TAG, format, list);
- }
-}
-
-} // namespace sde
-
diff --git a/displayengine/libs/hwc/hwc_logger.h b/displayengine/libs/hwc/hwc_logger.h
deleted file mode 100755
index 7568990..0000000
--- a/displayengine/libs/hwc/hwc_logger.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
-* Copyright (c) 2014, 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_LOGGER_H__
-#define __HWC_LOGGER_H__
-
-#include <core/sde_types.h>
-#include <cutils/log.h>
-
-#define DLOG(Macro, format, ...) Macro(__CLASS__ "::%s: " format, __FUNCTION__, ##__VA_ARGS__)
-
-#define DLOGE(format, ...) DLOG(ALOGE, format, ##__VA_ARGS__)
-#define DLOGW(format, ...) DLOG(ALOGW, format, ##__VA_ARGS__)
-#define DLOGI(format, ...) DLOG(ALOGI, format, ##__VA_ARGS__)
-#define DLOGV(format, ...) DLOG(ALOGV, format, ##__VA_ARGS__)
-
-namespace sde {
-
-class HWCLogHandler : public LogHandler {
- public:
- static inline LogHandler* Get() { return &log_handler_; }
- static void LogAll(bool enable);
- static void LogResources(bool enable);
- static void LogStrategy(bool enable);
-
- virtual void Error(LogTag tag, const char *format, ...);
- virtual void Warning(LogTag tag, const char *format, ...);
- virtual void Info(LogTag tag, const char *format, ...);
- virtual void Verbose(LogTag tag, const char *format, ...);
-
- private:
- static HWCLogHandler log_handler_;
- static uint32_t log_flags_;
-};
-
-} // namespace sde
-
-#endif // __HWC_LOGGER_H__
-
diff --git a/displayengine/libs/hwc/hwc_session.cpp b/displayengine/libs/hwc/hwc_session.cpp
index 3f99a23..3bc4fd1 100644
--- a/displayengine/libs/hwc/hwc_session.cpp
+++ b/displayengine/libs/hwc/hwc_session.cpp
@@ -1,25 +1,30 @@
/*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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.
+* 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.
+* 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 <core/dump_interface.h>
@@ -30,9 +35,12 @@
#include <sys/prctl.h>
#include <binder/Parcel.h>
#include <QService.h>
+#include <core/buffer_allocator.h>
+#include "hwc_buffer_allocator.h"
+#include "hwc_buffer_sync_handler.h"
#include "hwc_session.h"
-#include "hwc_logger.h"
+#include "hwc_debugger.h"
#define __CLASS__ "HWCSession"
@@ -57,8 +65,8 @@
Locker HWCSession::locker_;
HWCSession::HWCSession(const hw_module_t *module) : core_intf_(NULL), hwc_procs_(NULL),
- display_primary_(NULL), display_external_(NULL), hotplug_thread_exit_(false),
- hotplug_thread_name_("HWC_HotPlugThread") {
+ display_primary_(NULL), display_external_(NULL), display_virtual_(NULL),
+ hotplug_thread_exit_(false), hotplug_thread_name_("HWC_HotPlugThread") {
hwc_composer_device_1_t::common.tag = HARDWARE_DEVICE_TAG;
hwc_composer_device_1_t::common.version = HWC_DEVICE_API_VERSION_1_4;
hwc_composer_device_1_t::common.module = const_cast<hw_module_t*>(module);
@@ -92,7 +100,20 @@
return -EINVAL;
}
- DisplayError error = CoreInterface::CreateCore(this, HWCLogHandler::Get(), &core_intf_);
+ buffer_allocator_ = new HWCBufferAllocator();
+ if (buffer_allocator_ == NULL) {
+ DLOGE("Display core initialization failed due to no memory");
+ return -ENOMEM;
+ }
+
+ buffer_sync_handler_ = new HWCBufferSyncHandler();
+ if (buffer_sync_handler_ == NULL) {
+ DLOGE("Display core initialization failed due to no memory");
+ return -ENOMEM;
+ }
+
+ DisplayError error = CoreInterface::CreateCore(this, HWCDebugHandler::Get(), buffer_allocator_,
+ buffer_sync_handler_, &core_intf_);
if (error != kErrorNone) {
DLOGE("Display core initialization failed. Error = %d", error);
return -EINVAL;
@@ -187,7 +208,9 @@
int HWCSession::Prepare(hwc_composer_device_1 *device, size_t num_displays,
hwc_display_contents_1_t **displays) {
- SCOPE_LOCK(locker_);
+ DTRACE_SCOPED();
+
+ SEQUENCE_ENTRY_SCOPE_LOCK(locker_);
if (!device || !displays) {
return -EINVAL;
@@ -208,6 +231,15 @@
}
break;
case HWC_DISPLAY_VIRTUAL:
+ if (hwc_session->ValidateContentList(content_list)) {
+ hwc_session->CreateVirtualDisplay(hwc_session, content_list);
+ } else {
+ hwc_session->DestroyVirtualDisplay(hwc_session);
+ }
+
+ if (hwc_session->display_virtual_) {
+ hwc_session->display_virtual_->Prepare(content_list);
+ }
break;
default:
break;
@@ -220,7 +252,9 @@
int HWCSession::Set(hwc_composer_device_1 *device, size_t num_displays,
hwc_display_contents_1_t **displays) {
- SCOPE_LOCK(locker_);
+ DTRACE_SCOPED();
+
+ SEQUENCE_EXIT_SCOPE_LOCK(locker_);
if (!device || !displays) {
return -EINVAL;
@@ -241,6 +275,9 @@
}
break;
case HWC_DISPLAY_VIRTUAL:
+ if (hwc_session->display_virtual_) {
+ hwc_session->display_virtual_->Commit(content_list);
+ }
break;
default:
break;
@@ -252,7 +289,7 @@
}
int HWCSession::EventControl(hwc_composer_device_1 *device, int disp, int event, int enable) {
- SCOPE_LOCK(locker_);
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
if (!device) {
return -EINVAL;
@@ -270,6 +307,8 @@
status = hwc_session->display_external_->EventControl(event, enable);
}
break;
+ case HWC_DISPLAY_VIRTUAL:
+ break;
default:
status = -EINVAL;
}
@@ -278,7 +317,7 @@
}
int HWCSession::SetPowerMode(hwc_composer_device_1 *device, int disp, int mode) {
- SCOPE_LOCK(locker_);
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
if (!device) {
return -EINVAL;
@@ -296,6 +335,11 @@
status = hwc_session->display_external_->SetPowerMode(mode);
}
break;
+ case HWC_DISPLAY_VIRTUAL:
+ if (hwc_session->display_virtual_) {
+ status = hwc_session->display_virtual_->SetPowerMode(mode);
+ }
+ break;
default:
status = -EINVAL;
}
@@ -304,6 +348,8 @@
}
int HWCSession::Query(hwc_composer_device_1 *device, int param, int *value) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
if (!device || !value) {
return -EINVAL;
}
@@ -321,7 +367,7 @@
}
void HWCSession::Dump(hwc_composer_device_1 *device, char *buffer, int length) {
- SCOPE_LOCK(locker_);
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
if (!device || !buffer || !length) {
return;
@@ -332,6 +378,8 @@
int HWCSession::GetDisplayConfigs(hwc_composer_device_1 *device, int disp, uint32_t *configs,
size_t *num_configs) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
if (!device || !configs || !num_configs) {
return -EINVAL;
}
@@ -348,6 +396,11 @@
status = hwc_session->display_external_->GetDisplayConfigs(configs, num_configs);
}
break;
+ case HWC_DISPLAY_VIRTUAL:
+ if (hwc_session->display_virtual_) {
+ status = hwc_session->display_virtual_->GetDisplayConfigs(configs, num_configs);
+ }
+ break;
default:
status = -EINVAL;
}
@@ -357,6 +410,8 @@
int HWCSession::GetDisplayAttributes(hwc_composer_device_1 *device, int disp, uint32_t config,
const uint32_t *attributes, int32_t *values) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
if (!device || !attributes || !values) {
return -EINVAL;
}
@@ -373,6 +428,11 @@
status = hwc_session->display_external_->GetDisplayAttributes(config, attributes, values);
}
break;
+ case HWC_DISPLAY_VIRTUAL:
+ if (hwc_session->display_virtual_) {
+ status = hwc_session->display_virtual_->GetDisplayAttributes(config, attributes, values);
+ }
+ break;
default:
status = -EINVAL;
}
@@ -381,6 +441,8 @@
}
int HWCSession::GetActiveConfig(hwc_composer_device_1 *device, int disp) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
if (!device) {
return -1;
}
@@ -397,6 +459,11 @@
active_config = hwc_session->display_external_->GetActiveConfig();
}
break;
+ case HWC_DISPLAY_VIRTUAL:
+ if (hwc_session->display_virtual_) {
+ active_config = hwc_session->display_virtual_->GetActiveConfig();
+ }
+ break;
default:
active_config = -1;
}
@@ -405,6 +472,8 @@
}
int HWCSession::SetActiveConfig(hwc_composer_device_1 *device, int disp, int index) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
if (!device) {
return -EINVAL;
}
@@ -422,6 +491,8 @@
status = 0; // hwc_session->display_external_->SetActiveConfig(index);
}
break;
+ case HWC_DISPLAY_VIRTUAL:
+ break;
default:
status = -EINVAL;
}
@@ -429,12 +500,67 @@
return status;
}
+bool HWCSession::ValidateContentList(hwc_display_contents_1_t *content_list) {
+ return (content_list && content_list->numHwLayers > 0 && content_list->outbuf);
+}
+
+int HWCSession::CreateVirtualDisplay(HWCSession *hwc_session,
+ hwc_display_contents_1_t *content_list) {
+ int status = 0;
+
+ if (!hwc_session->display_virtual_) {
+ // Create virtual display device
+ hwc_session->display_virtual_ = new HWCDisplayVirtual(hwc_session->core_intf_,
+ &hwc_session->hwc_procs_);
+ if (!hwc_session->display_virtual_) {
+ // This is not catastrophic. Leave a warning message for now.
+ DLOGW("Virtual Display creation failed");
+ return -ENOMEM;
+ }
+
+ status = hwc_session->display_virtual_->Init();
+ if (status) {
+ goto CleanupOnError;
+ }
+
+ status = hwc_session->display_virtual_->SetPowerMode(HWC_POWER_MODE_NORMAL);
+ if (status) {
+ goto CleanupOnError;
+ }
+ }
+
+ if (hwc_session->display_virtual_) {
+ status = hwc_session->display_virtual_->SetActiveConfig(content_list);
+ }
+
+ return status;
+
+CleanupOnError:
+ return hwc_session->DestroyVirtualDisplay(hwc_session);
+}
+
+int HWCSession::DestroyVirtualDisplay(HWCSession *hwc_session) {
+ int status = 0;
+
+ if (hwc_session->display_virtual_) {
+ status = hwc_session->display_virtual_->Deinit();
+ if (!status) {
+ delete hwc_session->display_virtual_;
+ hwc_session->display_virtual_ = NULL;
+ }
+ }
+
+ return status;
+}
+
DisplayError HWCSession::Hotplug(const CoreEventHotplug &hotplug) {
return kErrorNone;
}
android::status_t HWCSession::notifyCallback(uint32_t command, const android::Parcel *input_parcel,
android::Parcel */*output_parcel*/) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
switch (command) {
case qService::IQService::DYNAMIC_DEBUG:
DynamicDebug(input_parcel);
@@ -444,6 +570,17 @@
hwc_procs_->invalidate(hwc_procs_);
break;
+ case qService::IQService::SET_IDLE_TIMEOUT:
+ if (display_primary_) {
+ uint32_t timeout = (uint32_t)input_parcel->readInt32();
+ display_primary_->SetIdleTimeoutMs(timeout);
+ }
+ break;
+
+ case qService::IQService::SET_FRAME_DUMP_CONFIG:
+ SetFrameDumpConfig(input_parcel);
+ break;
+
default:
DLOGW("QService command = %d is not supported", command);
return -EINVAL;
@@ -452,6 +589,30 @@
return 0;
}
+void HWCSession::SetFrameDumpConfig(const android::Parcel *input_parcel) {
+ uint32_t frame_dump_count = UINT32(input_parcel->readInt32());
+ uint32_t bit_mask_display_type = UINT32(input_parcel->readInt32());
+ uint32_t bit_mask_layer_type = UINT32(input_parcel->readInt32());
+
+ if (bit_mask_display_type & (1 << qService::IQService::DUMP_PRIMARY_DISPLAY)) {
+ if (display_primary_) {
+ display_primary_->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
+ }
+ }
+
+ if (bit_mask_display_type & (1 << qService::IQService::DUMP_HDMI_DISPLAY)) {
+ if (display_external_) {
+ display_external_->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
+ }
+ }
+
+ if (bit_mask_display_type & (1 << qService::IQService::DUMP_VIRTUAL_DISPLAY)) {
+ if (display_virtual_) {
+ display_virtual_->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
+ }
+ }
+}
+
void HWCSession::DynamicDebug(const android::Parcel *input_parcel) {
int type = input_parcel->readInt32();
bool enable = (input_parcel->readInt32() > 0);
@@ -459,21 +620,34 @@
switch (type) {
case qService::IQService::DEBUG_ALL:
- HWCLogHandler::LogAll(enable);
+ HWCDebugHandler::DebugAll(enable);
break;
case qService::IQService::DEBUG_MDPCOMP:
- HWCLogHandler::LogStrategy(enable);
+ HWCDebugHandler::DebugStrategy(enable);
+ HWCDebugHandler::DebugCompManager(enable);
break;
case qService::IQService::DEBUG_PIPE_LIFECYCLE:
- HWCLogHandler::LogResources(enable);
+ HWCDebugHandler::DebugResources(enable);
+ break;
+
+ case qService::IQService::DEBUG_DRIVER_CONFIG:
+ HWCDebugHandler::DebugDriverConfig(enable);
+ break;
+
+ case qService::IQService::DEBUG_ROTATOR:
+ HWCDebugHandler::DebugResources(enable);
+ HWCDebugHandler::DebugDriverConfig(enable);
+ HWCDebugHandler::DebugBufferManager(enable);
+ HWCDebugHandler::DebugOfflineCtrl(enable);
break;
default:
DLOGW("type = %d is not supported", type);
}
}
+
void* HWCSession::HWCHotPlugThread(void *context) {
if (context) {
return reinterpret_cast<HWCSession *>(context)->HWCHotPlugThreadHandler();
@@ -526,7 +700,6 @@
return -1;
}
-
int HWCSession::HotPlugHandler(bool connected) {
if (!hwc_procs_) {
DLOGW("Ignore hotplug - hwc_proc not registered");
@@ -534,7 +707,7 @@
}
if (connected) {
- SCOPE_LOCK(locker_);
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
if (display_external_) {
DLOGE("HDMI already connected");
return -1;
@@ -551,7 +724,7 @@
return -1;
}
} else {
- SCOPE_LOCK(locker_);
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
if (!display_external_) {
DLOGE("HDMI not connected");
return -1;
diff --git a/displayengine/libs/hwc/hwc_session.h b/displayengine/libs/hwc/hwc_session.h
index 488da9d..4b8c8ce 100644
--- a/displayengine/libs/hwc/hwc_session.h
+++ b/displayengine/libs/hwc/hwc_session.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -32,6 +32,7 @@
#include "hwc_display_primary.h"
#include "hwc_display_external.h"
+#include "hwc_display_virtual.h"
namespace sde {
@@ -72,6 +73,9 @@
void* HWCHotPlugThreadHandler();
int GetHDMIConnectedState(const char *uevent_data, int length);
int HotPlugHandler(bool connected);
+ bool ValidateContentList(hwc_display_contents_1_t *content_list);
+ int CreateVirtualDisplay(HWCSession *hwc_session, hwc_display_contents_1_t *content_list);
+ int DestroyVirtualDisplay(HWCSession *hwc_session);
// CoreEventHandler methods
virtual DisplayError Hotplug(const CoreEventHotplug &hotplug);
@@ -80,15 +84,19 @@
virtual android::status_t notifyCallback(uint32_t command, const android::Parcel *input_parcel,
android::Parcel *output_parcel);
void DynamicDebug(const android::Parcel *input_parcel);
+ void SetFrameDumpConfig(const android::Parcel *input_parcel);
static Locker locker_;
CoreInterface *core_intf_;
hwc_procs_t const *hwc_procs_;
HWCDisplayPrimary *display_primary_;
HWCDisplayExternal *display_external_;
+ HWCDisplayVirtual *display_virtual_;
pthread_t hotplug_thread_;
bool hotplug_thread_exit_;
const char *hotplug_thread_name_;
+ HWCBufferAllocator *buffer_allocator_;
+ HWCBufferSyncHandler *buffer_sync_handler_;
};
} // namespace sde
diff --git a/displayengine/libs/utils/Android.mk b/displayengine/libs/utils/Android.mk
index db97dd5..264c40a 100644
--- a/displayengine/libs/utils/Android.mk
+++ b/displayengine/libs/utils/Android.mk
@@ -8,6 +8,6 @@
-Wconversion -Wall -Werror \
-DLOG_TAG=\"SDE\"
LOCAL_SHARED_LIBRARIES := libcutils
-LOCAL_SRC_FILES := debug_android.cpp
+LOCAL_SRC_FILES := debug_android.cpp rect.cpp
include $(BUILD_SHARED_LIBRARY)
diff --git a/displayengine/libs/utils/debug_android.cpp b/displayengine/libs/utils/debug_android.cpp
old mode 100755
new mode 100644
index 31bd40b..1b08fe9
--- a/displayengine/libs/utils/debug_android.cpp
+++ b/displayengine/libs/utils/debug_android.cpp
@@ -1,25 +1,30 @@
/*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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.
+* 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.
+* 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 <stdlib.h>
@@ -31,7 +36,7 @@
Debug Debug::debug_;
-Debug::Debug() : log_handler_(&default_log_handler_), virtual_driver_(false) {
+Debug::Debug() : debug_handler_(&default_debug_handler_), virtual_driver_(false) {
char property[PROPERTY_VALUE_MAX];
if (property_get("displaycore.virtualdriver", property, NULL) > 0) {
virtual_driver_ = (atoi(property) == 1);
@@ -56,5 +61,14 @@
return 0;
}
+uint32_t Debug::GetIdleTimeoutMs() {
+ char property[PROPERTY_VALUE_MAX];
+ if (property_get("debug.mdpcomp.idletime", property, NULL) > 0) {
+ return atoi(property);
+ }
+
+ return 0;
+}
+
} // namespace sde
diff --git a/displayengine/libs/utils/rect.cpp b/displayengine/libs/utils/rect.cpp
new file mode 100644
index 0000000..2725750
--- /dev/null
+++ b/displayengine/libs/utils/rect.cpp
@@ -0,0 +1,80 @@
+/*
+* Copyright (c) 2015, 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 <math.h>
+#include <utils/rect.h>
+#include <utils/constants.h>
+
+#define __CLASS__ "RectUtils"
+
+namespace sde {
+
+bool IsValidRect(const LayerRect &rect) {
+ return ((rect.bottom > rect.top) && (rect.right > rect.left));
+}
+
+
+LayerRect GetIntersection(const LayerRect &rect1, const LayerRect &rect2) {
+ LayerRect res;
+
+ if (!IsValidRect(rect1) || !IsValidRect(rect2)) {
+ return LayerRect();
+ }
+
+ res.left = MAX(rect1.left, rect2.left);
+ res.top = MAX(rect1.top, rect2.top);
+ res.right = MIN(rect1.right, rect2.right);
+ res.bottom = MIN(rect1.bottom, rect2.bottom);
+
+ if (!IsValidRect(res)) {
+ return LayerRect();
+ }
+
+ return res;
+}
+
+void LogRect(DebugTag debug_tag, const char *prefix, const LayerRect &roi) {
+ DLOGV_IF(debug_tag, "%s: left = %.0f, top = %.0f, right = %.0f, bottom = %.0f",
+ prefix, roi.left, roi.top, roi.right, roi.bottom);
+}
+
+void NormalizeRect(const uint32_t &factor, LayerRect *rect) {
+ uint32_t left = UINT32(ceilf(rect->left));
+ uint32_t top = UINT32(ceilf(rect->top));
+ uint32_t right = UINT32(floorf(rect->right));
+ uint32_t bottom = UINT32(floorf(rect->bottom));
+
+ rect->left = FLOAT(CeilToMultipleOf(left, factor));
+ rect->top = FLOAT(CeilToMultipleOf(top, factor));
+ rect->right = FLOAT(FloorToMultipleOf(right, factor));
+ rect->bottom = FLOAT(FloorToMultipleOf(bottom, factor));
+}
+
+} // namespace sde
+
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index a7c4a9a..fd98154 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -37,6 +37,7 @@
#include "gr.h"
#include "comptype.h"
#include "mdp_version.h"
+#include <qdMetaData.h>
#ifdef VENUS_COLOR_FORMAT
#include <media/msm_media_info.h>
@@ -623,9 +624,19 @@
int getYUVPlaneInfo(private_handle_t* hnd, struct android_ycbcr* ycbcr)
{
int err = 0;
+ int width = hnd->width;
+ int height = hnd->height;
unsigned int ystride, cstride;
+
memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
+ // Check metadata if the geometry has been updated.
+ MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+ if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
+ AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(metadata->bufferDim.sliceWidth,
+ metadata->bufferDim.sliceHeight, hnd->format, 0, width, height);
+ }
+
// Get the chroma offsets from the handle width/height. We take advantage
// of the fact the width _is_ the stride
switch (hnd->format) {
@@ -634,10 +645,10 @@
case HAL_PIXEL_FORMAT_YCbCr_422_SP:
case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: //Same as YCbCr_420_SP_VENUS
- ystride = cstride = hnd->width;
+ ystride = cstride = width;
ycbcr->y = (void*)hnd->base;
- ycbcr->cb = (void*)(hnd->base + ystride * hnd->height);
- ycbcr->cr = (void*)(hnd->base + ystride * hnd->height + 1);
+ ycbcr->cb = (void*)(hnd->base + ystride * height);
+ ycbcr->cr = (void*)(hnd->base + ystride * height + 1);
ycbcr->ystride = ystride;
ycbcr->cstride = cstride;
ycbcr->chroma_step = 2;
@@ -648,10 +659,10 @@
case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
case HAL_PIXEL_FORMAT_NV21_ZSL:
case HAL_PIXEL_FORMAT_RAW_SENSOR:
- ystride = cstride = hnd->width;
+ ystride = cstride = width;
ycbcr->y = (void*)hnd->base;
- ycbcr->cr = (void*)(hnd->base + ystride * hnd->height);
- ycbcr->cb = (void*)(hnd->base + ystride * hnd->height + 1);
+ ycbcr->cr = (void*)(hnd->base + ystride * height);
+ ycbcr->cb = (void*)(hnd->base + ystride * height + 1);
ycbcr->ystride = ystride;
ycbcr->cstride = cstride;
ycbcr->chroma_step = 2;
@@ -659,16 +670,15 @@
//Planar
case HAL_PIXEL_FORMAT_YV12:
- ystride = hnd->width;
- cstride = ALIGN(hnd->width/2, 16);
+ ystride = width;
+ cstride = ALIGN(width/2, 16);
ycbcr->y = (void*)hnd->base;
- ycbcr->cr = (void*)(hnd->base + ystride * hnd->height);
- ycbcr->cb = (void*)(hnd->base + ystride * hnd->height +
- cstride * hnd->height/2);
+ ycbcr->cr = (void*)(hnd->base + ystride * height);
+ ycbcr->cb = (void*)(hnd->base + ystride * height +
+ cstride * height/2);
ycbcr->ystride = ystride;
ycbcr->cstride = cstride;
ycbcr->chroma_step = 1;
-
break;
//Unsupported formats
case HAL_PIXEL_FORMAT_YCbCr_422_I:
@@ -764,12 +774,15 @@
bool isUBwcEnabled(int format, int usage)
{
- if (isUBwcFormat(format) ||
- ((usage & GRALLOC_USAGE_PRIVATE_ALLOC_UBWC) && isUBwcSupported(format)))
- {
- // Allow UBWC, only if GPU supports it and CPU usage flags are not set
- if (AdrenoMemInfo::getInstance().isUBWCSupportedByGPU(format) &&
- !(usage & (GRALLOC_USAGE_SW_READ_MASK |
+ // Allow UBWC, if client is using an explicitly defined UBWC pixel format.
+ if (isUBwcFormat(format))
+ return true;
+
+ // Allow UBWC, if client sets UBWC gralloc usage flag & GPU supports format.
+ if ((usage & GRALLOC_USAGE_PRIVATE_ALLOC_UBWC) && isUBwcSupported(format) &&
+ AdrenoMemInfo::getInstance().isUBWCSupportedByGPU(format)) {
+ // Allow UBWC, only if CPU usage flags are not set
+ if (!(usage & (GRALLOC_USAGE_SW_READ_MASK |
GRALLOC_USAGE_SW_WRITE_MASK))) {
return true;
}
diff --git a/libgralloc/gpu.cpp b/libgralloc/gpu.cpp
index 9ab9d09..df7be41 100644
--- a/libgralloc/gpu.cpp
+++ b/libgralloc/gpu.cpp
@@ -149,7 +149,8 @@
flags |= private_handle_t::PRIV_FLAGS_TILE_RENDERED;
}
- if (isUBwcEnabled(format, usage)) {
+ if (AdrenoMemInfo::getInstance().isUBWCSupportedByGPU(format) &&
+ isUBwcEnabled(format, usage)) {
flags |= private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
}
@@ -288,7 +289,9 @@
//the usage bits, gralloc assigns a format.
if(format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED ||
format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
- if(usage & GRALLOC_USAGE_HW_VIDEO_ENCODER)
+ if (usage & GRALLOC_USAGE_PRIVATE_ALLOC_UBWC)
+ grallocFormat = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC;
+ else if(usage & GRALLOC_USAGE_HW_VIDEO_ENCODER)
grallocFormat = HAL_PIXEL_FORMAT_NV12_ENCODEABLE; //NV12
else if((usage & GRALLOC_USAGE_HW_CAMERA_MASK)
== GRALLOC_USAGE_HW_CAMERA_ZSL)
diff --git a/libgralloc/gralloc_priv.h b/libgralloc/gralloc_priv.h
index 8b134ea..e9b9d9d 100755
--- a/libgralloc/gralloc_priv.h
+++ b/libgralloc/gralloc_priv.h
@@ -91,7 +91,6 @@
GRALLOC_USAGE_PRIVATE_ADSP_HEAP)
#define INTERLACE_MASK 0x80
-#define S3D_FORMAT_MASK 0xFF000
/*****************************************************************************/
/* OEM specific HAL formats */
@@ -155,15 +154,11 @@
/* possible formats for 3D content*/
enum {
- HAL_NO_3D = 0x0000,
- HAL_3D_IN_SIDE_BY_SIDE_L_R = 0x10000,
- HAL_3D_IN_TOP_BOTTOM = 0x20000,
- HAL_3D_IN_INTERLEAVE = 0x40000,
- HAL_3D_IN_SIDE_BY_SIDE_R_L = 0x80000,
- HAL_3D_OUT_SIDE_BY_SIDE = 0x1000,
- HAL_3D_OUT_TOP_BOTTOM = 0x2000,
- HAL_3D_OUT_INTERLEAVE = 0x4000,
- HAL_3D_OUT_MONOSCOPIC = 0x8000
+ HAL_NO_3D = 0x0,
+ HAL_3D_SIDE_BY_SIDE_L_R = 0x1,
+ HAL_3D_SIDE_BY_SIDE_R_L = 0x2,
+ HAL_3D_TOP_BOTTOM = 0x4,
+ HAL_3D_IN_SIDE_BY_SIDE_L_R = 0x10000, //unused legacy format
};
enum {
diff --git a/libhdmi/hdmi.cpp b/libhdmi/hdmi.cpp
index 7d709cb..bca7a0b 100644
--- a/libhdmi/hdmi.cpp
+++ b/libhdmi/hdmi.cpp
@@ -21,7 +21,6 @@
#define DEBUG 0
#include <fcntl.h>
#include <linux/msm_mdp.h>
-#include <video/msm_hdmi_modes.h>
#include <linux/fb.h>
#include <sys/ioctl.h>
#include <cutils/properties.h>
@@ -38,62 +37,6 @@
#define UNKNOWN_STRING "unknown"
#define SPD_NAME_LENGTH 16
-/* The array gEDIDData contains a list of modes currently
- * supported by HDMI and display, and modes that are not
- * supported i.e. interlaced modes.
-
- * In order to add support for a new mode, the mode must be
- * appended to the end of the array.
- *
- * Each new entry must contain the following:
- * -Mode: a video format defined in msm_hdmi_modes.h
- * -Width: x resolution for the mode
- * -Height: y resolution for the mode
- * -FPS: the frame rate for the mode
- * -Mode Order: the priority for the new mode that is used when determining
- * the best mode when the HDMI display is connected.
- */
-EDIDData gEDIDData [] = {
- EDIDData(HDMI_VFRMT_1440x480i60_4_3, 1440, 480, 60, 1),
- EDIDData(HDMI_VFRMT_1440x480i60_16_9, 1440, 480, 60, 2),
- EDIDData(HDMI_VFRMT_1440x576i50_4_3, 1440, 576, 50, 3),
- EDIDData(HDMI_VFRMT_1440x576i50_16_9, 1440, 576, 50, 4),
- EDIDData(HDMI_VFRMT_1920x1080i60_16_9, 1920, 1080, 60, 5),
- EDIDData(HDMI_VFRMT_640x480p60_4_3, 640, 480, 60, 6),
- EDIDData(HDMI_VFRMT_720x480p60_4_3, 720, 480, 60, 7),
- EDIDData(HDMI_VFRMT_720x480p60_16_9, 720, 480, 60, 8),
- EDIDData(HDMI_VFRMT_720x576p50_4_3, 720, 576, 50, 9),
- EDIDData(HDMI_VFRMT_720x576p50_16_9, 720, 576, 50, 10),
- EDIDData(HDMI_VFRMT_800x600p60_4_3, 800, 600, 60, 11),
- EDIDData(HDMI_VFRMT_848x480p60_16_9, 848, 480, 60, 12),
- EDIDData(HDMI_VFRMT_1024x768p60_4_3, 1024, 768, 60, 13),
- EDIDData(HDMI_VFRMT_1280x1024p60_5_4, 1280, 1024, 60, 14),
- EDIDData(HDMI_VFRMT_1280x720p50_16_9, 1280, 720, 50, 15),
- EDIDData(HDMI_VFRMT_1280x720p60_16_9, 1280, 720, 60, 16),
- EDIDData(HDMI_VFRMT_1280x800p60_16_10, 1280, 800, 60, 17),
- EDIDData(HDMI_VFRMT_1280x960p60_4_3, 1280, 960, 60, 18),
- EDIDData(HDMI_VFRMT_1360x768p60_16_9, 1360, 768, 60, 19),
- EDIDData(HDMI_VFRMT_1366x768p60_16_10, 1366, 768, 60, 20),
- EDIDData(HDMI_VFRMT_1440x900p60_16_10, 1440, 900, 60, 21),
- EDIDData(HDMI_VFRMT_1400x1050p60_4_3, 1400, 1050, 60, 22),
- EDIDData(HDMI_VFRMT_1680x1050p60_16_10, 1680, 1050, 60, 23),
- EDIDData(HDMI_VFRMT_1600x1200p60_4_3, 1600, 1200, 60, 24),
- EDIDData(HDMI_VFRMT_1920x1080p24_16_9, 1920, 1080, 24, 25),
- EDIDData(HDMI_VFRMT_1920x1080p25_16_9, 1920, 1080, 25, 26),
- EDIDData(HDMI_VFRMT_1920x1080p30_16_9, 1920, 1080, 30, 27),
- EDIDData(HDMI_VFRMT_1920x1080p50_16_9, 1920, 1080, 50, 28),
- EDIDData(HDMI_VFRMT_1920x1080p60_16_9, 1920, 1080, 60, 29),
- EDIDData(HDMI_VFRMT_1920x1200p60_16_10, 1920, 1200, 60, 30),
- EDIDData(HDMI_VFRMT_2560x1600p60_16_9, 2560, 1600, 60, 31),
- EDIDData(HDMI_VFRMT_3840x2160p24_16_9, 3840, 2160, 24, 32),
- EDIDData(HDMI_VFRMT_3840x2160p25_16_9, 3840, 2160, 25, 33),
- EDIDData(HDMI_VFRMT_3840x2160p30_16_9, 3840, 2160, 30, 34),
- EDIDData(HDMI_VFRMT_4096x2160p24_16_9, 4096, 2160, 24, 35),
-};
-
-// Number of modes in gEDIDData
-const int gEDIDCount = (sizeof(gEDIDData)/sizeof(gEDIDData)[0]);
-
int HDMIDisplay::configure() {
if(!openFrameBuffer()) {
ALOGE("%s: Failed to open FB: %d", __FUNCTION__, mFbNum);
@@ -135,8 +78,8 @@
}
void HDMIDisplay::getAttributes(uint32_t& width, uint32_t& height) {
- uint32_t fps = 0;
- getAttrForMode(width, height, fps);
+ uint32_t refresh = 0, fps = 0;
+ getAttrForConfig(mActiveConfig, width, height, refresh, fps);
}
int HDMIDisplay::teardown() {
@@ -167,14 +110,7 @@
writeHPDOption(0);
}
- // for HDMI - retreive all the modes supported by the driver
if(mFbNum != -1) {
- supported_video_mode_lut =
- new msm_hdmi_mode_timing_info[HDMI_VFRMT_MAX];
- // Populate the mode table for supported modes
- MSM_HDMI_MODES_INIT_TIMINGS(supported_video_mode_lut);
- MSM_HDMI_MODES_SET_SUPP_TIMINGS(supported_video_mode_lut,
- MSM_HDMI_MODES_ALL);
// Update the Source Product Information
// Vendor Name
setSPDInfo("vendor_name", "ro.product.manufacturer");
@@ -298,7 +234,6 @@
HDMIDisplay::~HDMIDisplay()
{
- delete [] supported_video_mode_lut;
closeFrameBuffer();
}
@@ -356,7 +291,7 @@
bool HDMIDisplay::readResolution()
{
ssize_t len = -1;
- char edidStr[128] = {'\0'};
+ char edidStr[PAGE_SIZE] = {'\0'};
int hdmiEDIDFile = openDeviceNode("edid_modes", O_RDONLY);
if (hdmiEDIDFile < 0) {
@@ -383,6 +318,25 @@
ALOGD_IF(DEBUG, "%s: mModeCount = %d", __FUNCTION__,
mModeCount);
}
+ // Populate the internal data structure with the timing information
+ // for each edid mode read from the driver
+ if (mModeCount > 0) {
+ mDisplayConfigs = new msm_hdmi_mode_timing_info[mModeCount];
+ readConfigs();
+ } else {
+ // If we fail to read from EDID when HDMI is connected, then
+ // mModeCount will be 0 and bestConfigIndex will be invalid.
+ // In this case, we populate the mEDIDModes structure with
+ // a default mode at config index 0.
+ uint32_t defaultConfigIndex = 0;
+ mModeCount = 1;
+ mEDIDModes[defaultConfigIndex] = HDMI_VFRMT_640x480p60_4_3;
+ struct msm_hdmi_mode_timing_info defaultMode =
+ HDMI_VFRMT_640x480p60_4_3_TIMING;
+ mDisplayConfigs = new msm_hdmi_mode_timing_info[mModeCount];
+ mDisplayConfigs[defaultConfigIndex] = defaultMode;
+ ALOGD("%s Defaulting to HDMI_VFRMT_640x480p60_4_3", __FUNCTION__);
+ }
return (len > 0);
}
@@ -421,30 +375,22 @@
mYres = 0;
mVsyncPeriod = 0;
mMDPScalingMode = false;
+ if (mDisplayConfigs) {
+ delete [] mDisplayConfigs;
+ mDisplayConfigs = 0;
+ }
// Reset the underscan supported system property
const char* prop = "0";
property_set("hw.underscan_supported", prop);
}
-int HDMIDisplay::getModeOrder(int mode)
-{
- for (int dataIndex = 0; dataIndex < gEDIDCount; dataIndex++) {
- if (gEDIDData[dataIndex].mMode == mode) {
- return gEDIDData[dataIndex].mModeOrder;
- }
- }
- ALOGE("%s Mode not found: %d", __FUNCTION__, mode);
- return -1;
-}
-
/// Returns the index of the user mode set(if any) using adb shell
int HDMIDisplay::getUserConfig() {
/* Based on the property set the resolution */
char property_value[PROPERTY_VALUE_MAX];
property_get("hw.hdmi.resolution", property_value, "-1");
int mode = atoi(property_value);
- // We dont support interlaced modes
- if(isValidMode(mode) && !isInterlacedMode(mode)) {
+ if(isValidMode(mode)) {
ALOGD_IF(DEBUG, "%s: setting the HDMI mode = %d", __FUNCTION__, mode);
return getModeIndex(mode);
}
@@ -453,61 +399,137 @@
// Get the index of the best mode for the current HD TV
int HDMIDisplay::getBestConfig() {
- int bestOrder = 0;
- int bestMode = HDMI_VFRMT_640x480p60_4_3;
- int bestModeIndex = -1;
- // for all the edid read, get the best mode
- for(int i = 0; i < mModeCount; i++) {
- int mode = mEDIDModes[i];
- int order = getModeOrder(mode);
- if (order > bestOrder) {
- bestOrder = order;
- bestMode = mode;
- bestModeIndex = i;
+ int bestConfigIndex = 0;
+ int edidMode = -1;
+ struct msm_hdmi_mode_timing_info currentModeInfo = {0};
+ struct msm_hdmi_mode_timing_info bestModeInfo = {0};
+ bestModeInfo.video_format = 0;
+ bestModeInfo.active_v = 0;
+ bestModeInfo.active_h = 0;
+ bestModeInfo.refresh_rate = 0;
+ bestModeInfo.ar = HDMI_RES_AR_INVALID;
+
+ // for all the timing info read, get the best config
+ for (int configIndex = 0; configIndex < mModeCount; configIndex++) {
+ currentModeInfo = mDisplayConfigs[configIndex];
+
+ if (!currentModeInfo.supported) {
+ ALOGD("%s EDID Mode %d is not supported", __FUNCTION__, edidMode);
+ continue;
+ }
+
+ ALOGD_IF(DEBUG, "%s Best (%d) : (%dx%d) @ %d;"
+ " Current (%d) (%dx%d) @ %d",
+ __FUNCTION__, bestConfigIndex, bestModeInfo.active_h,
+ bestModeInfo.active_v, bestModeInfo.refresh_rate, configIndex,
+ currentModeInfo.active_h, currentModeInfo.active_v,
+ currentModeInfo.refresh_rate);
+
+ // Compare two HDMI modes in order of height, width, refresh rate and
+ // aspect ratio.
+ if (currentModeInfo.active_v > bestModeInfo.active_v) {
+ bestConfigIndex = configIndex;
+ } else if (currentModeInfo.active_v == bestModeInfo.active_v) {
+ if (currentModeInfo.active_h > bestModeInfo.active_h) {
+ bestConfigIndex = configIndex;
+ } else if (currentModeInfo.active_h == bestModeInfo.active_h) {
+ if (currentModeInfo.refresh_rate > bestModeInfo.refresh_rate) {
+ bestConfigIndex = configIndex;
+ } else if (currentModeInfo.refresh_rate ==
+ bestModeInfo.refresh_rate) {
+ if (currentModeInfo.ar > bestModeInfo.ar) {
+ bestConfigIndex = configIndex;
+ }
+ }
+ }
+ }
+ if (bestConfigIndex == configIndex) {
+ bestModeInfo = mDisplayConfigs[bestConfigIndex];
}
}
- // If we fail to read from EDID when HDMI is connected, then
- // mModeCount will be 0 and bestModeIndex will be invalid.
- // In this case, we populate the mEDIDModes structure with
- // a default mode at index 0.
- if (bestModeIndex == -1) {
- bestModeIndex = 0;
- mModeCount = 1;
- mEDIDModes[bestModeIndex] = bestMode;
+ return bestConfigIndex;
+}
+
+// Utility function used to request HDMI driver to write a new page of timing
+// info into res_info node
+void HDMIDisplay::requestNewPage(int pageNumber) {
+ char pageString[PAGE_SIZE];
+ int fd = openDeviceNode("res_info", O_WRONLY);
+ if (fd >= 0) {
+ snprintf(pageString, sizeof(pageString), "%d", pageNumber);
+ ALOGD_IF(DEBUG, "%s: page=%s", __FUNCTION__, pageString);
+ ssize_t err = write(fd, pageString, sizeof(pageString));
+ if (err <= 0) {
+ ALOGE("%s: Write to res_info failed (%d)", __FUNCTION__, errno);
+ }
+ close(fd);
}
- return bestModeIndex;
+}
+
+// Reads the contents of res_info node into a buffer if the file is not empty
+bool HDMIDisplay::readResFile(char * configBuffer) {
+ bool fileRead = false;
+ size_t bytesRead = 0;
+ int fd = openDeviceNode("res_info", O_RDONLY);
+ if (fd >= 0 && (bytesRead = read(fd, configBuffer, PAGE_SIZE)) != 0) {
+ fileRead = true;
+ }
+ close(fd);
+ ALOGD_IF(DEBUG, "%s: bytesRead=%d fileRead=%d",
+ __FUNCTION__, bytesRead, fileRead);
+ return fileRead;
+}
+
+// Populates the internal timing info structure with the timing info obtained
+// from the HDMI driver
+void HDMIDisplay::readConfigs() {
+ int configIndex = 0;
+ int pageNumber = MSM_HDMI_INIT_RES_PAGE;
+ long unsigned int size = sizeof(msm_hdmi_mode_timing_info);
+
+ while (true) {
+ char configBuffer[PAGE_SIZE] = {0};
+ msm_hdmi_mode_timing_info *info =
+ (msm_hdmi_mode_timing_info*) configBuffer;
+
+ if (!readResFile(configBuffer))
+ break;
+
+ while (info->video_format && size < PAGE_SIZE) {
+ mDisplayConfigs[configIndex] = *info;
+ size += sizeof(msm_hdmi_mode_timing_info);
+ info++;
+ ALOGD_IF(DEBUG, "%s: Config=%d Mode %d: (%dx%d) @ %d",
+ __FUNCTION__, configIndex,
+ mDisplayConfigs[configIndex].video_format,
+ mDisplayConfigs[configIndex].active_h,
+ mDisplayConfigs[configIndex].active_v,
+ mDisplayConfigs[configIndex].refresh_rate);
+ configIndex++;
+ }
+ size = sizeof(msm_hdmi_mode_timing_info);
+ // Request HDMI driver to populate res_info with more
+ // timing information
+ pageNumber++;
+ requestNewPage(pageNumber);
+ }
}
inline bool HDMIDisplay::isValidMode(int ID)
{
bool valid = false;
- for (int i = 0; i < mModeCount; i++) {
- if(ID == mEDIDModes[i]) {
- valid = true;
- break;
- }
+ int modeIndex = getModeIndex(ID);
+ if (ID <= 0 || modeIndex < 0 || modeIndex > mModeCount) {
+ return false;
+ }
+ struct msm_hdmi_mode_timing_info* mode = &mDisplayConfigs[modeIndex];
+ // We dont support interlaced modes
+ if (mode->supported && !mode->interlaced) {
+ valid = true;
}
return valid;
}
-// returns true if the mode(ID) is interlaced mode format
-bool HDMIDisplay::isInterlacedMode(int ID) {
- bool interlaced = false;
- switch(ID) {
- case HDMI_VFRMT_1440x480i60_4_3:
- case HDMI_VFRMT_1440x480i60_16_9:
- case HDMI_VFRMT_1440x576i50_4_3:
- case HDMI_VFRMT_1440x576i50_16_9:
- case HDMI_VFRMT_1920x1080i60_16_9:
- interlaced = true;
- break;
- default:
- interlaced = false;
- break;
- }
- return interlaced;
-}
-
// Does a put_vscreen info on the HDMI interface which will update
// the configuration (resolution, timing info) to match mCurrentMode
void HDMIDisplay::activateDisplay()
@@ -525,16 +547,7 @@
mVInfo.lower_margin, mVInfo.vsync_len, mVInfo.upper_margin,
mVInfo.pixclock/1000/1000);
- const struct msm_hdmi_mode_timing_info *mode =
- &supported_video_mode_lut[0];
- for (unsigned int i = 0; i < HDMI_VFRMT_MAX; ++i) {
- const struct msm_hdmi_mode_timing_info *cur =
- &supported_video_mode_lut[i];
- if (cur->video_format == (uint32_t)mCurrentMode) {
- mode = cur;
- break;
- }
- }
+ struct msm_hdmi_mode_timing_info *mode = &mDisplayConfigs[mActiveConfig];
setDisplayTiming(mVInfo, mode);
ALOGD_IF(DEBUG, "%s: SET Info<ID=%d => Info<ID=%d %dx %d"
"(%d,%d,%d), (%d,%d,%d) %dMHz>", __FUNCTION__, mCurrentMode,
@@ -585,9 +598,9 @@
void HDMIDisplay::setAttributes() {
- uint32_t fps = 0;
+ uint32_t refresh = 0, fps = 0;
// Always set dpyAttr res to mVInfo res
- getAttrForMode(mXres, mYres, fps);
+ getAttrForConfig(mActiveConfig, mXres, mYres, refresh, fps);
mMDPScalingMode = false;
if(overlay::Overlay::getInstance()->isUIScalingOnExternalSupported()
@@ -653,19 +666,6 @@
ALOGD_IF(DEBUG, "%s xres=%d, yres=%d", __FUNCTION__, mXres, mYres);
}
-void HDMIDisplay::getAttrForMode(uint32_t& width, uint32_t& height,
- uint32_t& fps) {
- for (int dataIndex = 0; dataIndex < gEDIDCount; dataIndex++) {
- if (gEDIDData[dataIndex].mMode == mCurrentMode) {
- width = gEDIDData[dataIndex].mWidth;
- height = gEDIDData[dataIndex].mHeight;
- fps = gEDIDData[dataIndex].mFps;
- return;
- }
- }
- ALOGE("%s Unable to get attributes for %d", __FUNCTION__, mCurrentMode);
-}
-
/* returns the fd related to the node specified*/
int HDMIDisplay::openDeviceNode(const char* node, int fileMode) const {
char sysFsFilePath[MAX_SYSFS_FILE_PATH];
@@ -743,8 +743,8 @@
// not match the current config
bool HDMIDisplay::isValidConfigChange(int newConfig) {
int newMode = mEDIDModes[newConfig];
- uint32_t width = 0, height = 0, refresh = 0;
- getAttrForConfig(newConfig, width, height, refresh);
+ uint32_t width = 0, height = 0, refresh = 0, fps = 0;
+ getAttrForConfig(newConfig, width, height, refresh, fps);
return ((mXres == width) && (mYres == height)) || mEnableResolutionChange;
}
@@ -760,21 +760,16 @@
}
int HDMIDisplay::getAttrForConfig(int config, uint32_t& xres,
- uint32_t& yres, uint32_t& refresh) const {
+ uint32_t& yres, uint32_t& refresh, uint32_t& fps) const {
if(config < 0 || config > mModeCount) {
ALOGE("%s Invalid configuration %d", __FUNCTION__, config);
return -EINVAL;
}
- int mode = mEDIDModes[config];
- uint32_t fps = 0;
- // Retrieve the mode attributes from gEDIDData
- for (int dataIndex = 0; dataIndex < gEDIDCount; dataIndex++) {
- if (gEDIDData[dataIndex].mMode == mode) {
- xres = gEDIDData[dataIndex].mWidth;
- yres = gEDIDData[dataIndex].mHeight;
- fps = gEDIDData[dataIndex].mFps;
- }
- }
+
+ xres = mDisplayConfigs[config].active_h;
+ yres = mDisplayConfigs[config].active_v;
+ fps = (mDisplayConfigs[config].refresh_rate / 1000);
+
refresh = (uint32_t) 1000000000l / fps;
ALOGD_IF(DEBUG, "%s xres(%d) yres(%d) fps(%d) refresh(%d)", __FUNCTION__,
xres, yres, fps, refresh);
diff --git a/libhdmi/hdmi.h b/libhdmi/hdmi.h
index d262a63..32c48ff 100644
--- a/libhdmi/hdmi.h
+++ b/libhdmi/hdmi.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012-2014, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2012-2015, The Linux Foundation. All rights reserved.
*
* Not a Contribution, Apache license notifications and license are
* retained for attribution purposes only.
@@ -22,6 +22,7 @@
#define HWC_HDMI_DISPLAY_H
#include <linux/fb.h>
+#include <video/msm_hdmi_modes.h>
struct msm_hdmi_mode_timing_info;
@@ -35,16 +36,6 @@
HDMI_SCAN_BOTH_SUPPORTED = 3
};
-// Structure to store EDID related data
-struct EDIDData {
- int mMode, mWidth, mHeight, mFps;
- // Predetermined ordering for each mode
- int mModeOrder;
- EDIDData(int mode, int width, int height, int fps, int order)
- : mMode(mode), mWidth(width), mHeight(height), mFps(fps), mModeOrder(order)
- { }
-};
-
class HDMIDisplay
{
public:
@@ -71,7 +62,7 @@
int getActiveConfig() const { return mActiveConfig; };
int setActiveConfig(int newConfig);
int getAttrForConfig(int config, uint32_t& xres,
- uint32_t& yres, uint32_t& refresh) const;
+ uint32_t& yres, uint32_t& refresh, uint32_t& fps) const;
int getDisplayConfigs(uint32_t* configs, size_t* numConfigs) const;
private:
@@ -90,10 +81,12 @@
bool isInterlacedMode(int mode);
void resetInfo();
void setAttributes();
- void getAttrForMode(uint32_t& width, uint32_t& height, uint32_t& fps);
int openDeviceNode(const char* node, int fileMode) const;
int getModeIndex(int mode);
bool isValidConfigChange(int newConfig);
+ void requestNewPage(int pageNumber);
+ void readConfigs();
+ bool readResFile(char* configBuffer);
int mFd;
int mFbNum;
@@ -105,11 +98,11 @@
int mActiveConfig;
// mEDIDModes contains a list of HDMI video formats (modes) supported by the
// HDMI display
- int mEDIDModes[64];
+ int mEDIDModes[HDMI_VFRMT_MAX];
int mModeCount;
fb_var_screeninfo mVInfo;
// Holds all the HDMI modes and timing info supported by driver
- msm_hdmi_mode_timing_info* supported_video_mode_lut;
+ msm_hdmi_mode_timing_info *mDisplayConfigs;
uint32_t mXres, mYres, mVsyncPeriod, mPrimaryWidth, mPrimaryHeight;
bool mMDPScalingMode;
bool mUnderscanSupported;
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index fd3bb69..adf48e7 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -255,6 +255,8 @@
hwc_context_t* ctx = (hwc_context_t*)(dev);
const int dpy = HWC_DISPLAY_PRIMARY;
bool fbComp = false;
+ if (!ctx->mBootAnimCompleted)
+ processBootAnimCompleted(ctx);
if (LIKELY(list && list->numHwLayers > 1) && ctx->dpyAttr[dpy].connected &&
(ctx->dpyAttr[dpy].isActive ||
ctx->mHDMIDisplay->isHDMIPrimaryDisplay())
@@ -752,7 +754,7 @@
bool isVirtualDisplay = (disp == HWC_DISPLAY_VIRTUAL);
// If hotpluggable or virtual displays are inactive return error
if ((hotPluggable || isVirtualDisplay) && !ctx->dpyAttr[disp].connected) {
- ALOGE("%s display (%d) is inactive", __FUNCTION__, disp);
+ ALOGW("%s display (%d) is not connected anymore", __FUNCTION__, disp);
return -EINVAL;
}
@@ -809,10 +811,11 @@
const size_t NUM_DISPLAY_ATTRIBUTES = (sizeof(DISPLAY_ATTRIBUTES) /
sizeof(DISPLAY_ATTRIBUTES)[0]);
- uint32_t xres = 0, yres = 0, refresh = 0;
+ uint32_t xres = 0, yres = 0, refresh = 0, fps = 0;
int ret = 0;
if (hotPluggable) {
- ret = ctx->mHDMIDisplay->getAttrForConfig(config, xres, yres, refresh);
+ ret = ctx->mHDMIDisplay->getAttrForConfig(config, xres,
+ yres, refresh, fps);
if(ret < 0) {
ALOGE("%s Error getting attributes for config %d",
__FUNCTION__, config);
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index 41c7f62..7fcb9a7 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -131,6 +131,21 @@
return renderArea;
}
+bool CopyBit::isLayerChanging(hwc_display_contents_1_t *list, int k) {
+ if((mLayerCache.hnd[k] != list->hwLayers[k].handle) ||
+ (mLayerCache.displayFrame[k].left !=
+ list->hwLayers[k].displayFrame.left) ||
+ (mLayerCache.displayFrame[k].top !=
+ list->hwLayers[k].displayFrame.top) ||
+ (mLayerCache.displayFrame[k].right !=
+ list->hwLayers[k].displayFrame.right) ||
+ (mLayerCache.displayFrame[k].bottom !=
+ list->hwLayers[k].displayFrame.bottom)) {
+ return 1;
+ }
+ return 0;
+}
+
int CopyBit::getLayersChanging(hwc_context_t *ctx,
hwc_display_contents_1_t *list,
int dpy){
@@ -146,7 +161,7 @@
int updatingLayerCount = 0;
for (int k = ctx->listStats[dpy].numAppLayers-1; k >= 0 ; k--){
//swap rect will kick in only for single updating layer
- if(mLayerCache.hnd[k] != list->hwLayers[k].handle){
+ if(isLayerChanging(list, k)) {
updatingLayerCount ++;
if(updatingLayerCount == 1)
changingLayerIndex = k;
@@ -163,19 +178,20 @@
dirtyRect = list->hwLayers[changingLayerIndex].dirtyRect;
#endif
- for (int k = ctx->listStats[dpy].numAppLayers-1; k >= 0 ; k--){
- //disable swap rect for overlapping visible layer(s)
- hwc_rect_t displayFrame = list->hwLayers[k].displayFrame;
- hwc_rect_t result = getIntersection(displayFrame,dirtyRect);
- if((k != changingLayerIndex) && isValidRect(result)){
- return -1;
+ for (int k = ctx->listStats[dpy].numAppLayers-1; k >= 0 ; k--) {
+ //disable swap rect in case of scaling and video .
+ private_handle_t *hnd =(private_handle_t *)list->hwLayers[k].handle;
+ if(needsScaling(&list->hwLayers[k])||( hnd && isYuvBuffer(hnd))) {
+ mFbCache.reset();
+ return -1;
}
}
- mFbCache.insertAndUpdateFbCache(dirtyRect);
if(mFbCache.getUnchangedFbDRCount(dirtyRect) <
- NUM_RENDER_BUFFERS)
+ NUM_RENDER_BUFFERS) {
+ mFbCache.insertAndUpdateFbCache(dirtyRect);
changingLayerIndex = -1;
- }else {
+ }
+ } else {
mFbCache.reset();
changingLayerIndex = -1;
}
@@ -189,23 +205,11 @@
//dirty rect will enable only if
//1.Only single layer is updating.
- //2.No overlapping
- //3.No scaling
- //4.No video layer
+ //2.No scaling
+ //3.No video layer
if(mSwapRectEnable == false)
return -1;
- int changingLayerIndex = getLayersChanging(ctx, list, dpy);
- //swap rect will kick in only for single updating layer
- if(changingLayerIndex == -1){
- return -1;
- }
- if(!needsScaling(&list->hwLayers[changingLayerIndex])){
- private_handle_t *hnd =
- (private_handle_t *)list->hwLayers[changingLayerIndex].handle;
- if( hnd && !isYuvBuffer(hnd))
- return changingLayerIndex;
- }
- return -1;
+ return getLayersChanging(ctx, list, dpy);
}
bool CopyBit::prepareOverlap(hwc_context_t *ctx,
@@ -216,8 +220,13 @@
return false;
}
- if (mEngine == NULL || !(validateParams(ctx, list))) {
- ALOGE("%s: Invalid Params", __FUNCTION__);
+ if (mEngine == NULL) {
+ ALOGW("%s: Copybit HAL not enabled", __FUNCTION__);
+ return false;
+ }
+
+ if (!(validateParams(ctx, list))) {
+ ALOGE("%s: validateParams() failed", __FUNCTION__);
return false;
}
PtorInfo* ptorInfo = &(ctx->mPtorInfo);
@@ -467,6 +476,7 @@
list->hwLayers[abcRenderBufIdx].acquireFenceFd);
}
for(int i = abcRenderBufIdx + 1; i < layerCount; i++){
+ mDirtyLayerIndex = -1;
int retVal = drawLayerUsingCopybit(ctx,
&(list->hwLayers[i]),renderBuffer, 0);
if(retVal < 0) {
@@ -475,8 +485,8 @@
}
// Get Release Fence FD of copybit for the App layer(s)
copybit->flush_get_fence(copybit, copybitFd);
- close(list->hwLayers[abcRenderBufIdx].acquireFenceFd);
- list->hwLayers[abcRenderBufIdx].acquireFenceFd = -1;
+ close(list->hwLayers[last].acquireFenceFd);
+ list->hwLayers[last].acquireFenceFd = -1;
return true;
}
}
@@ -528,19 +538,16 @@
}
mDirtyLayerIndex = checkDirtyRect(ctx, list, dpy);
- if( mDirtyLayerIndex != -1){
- hwc_layer_1_t *layer = &list->hwLayers[mDirtyLayerIndex];
-#ifdef QCOM_BSP
- clear(renderBuffer,layer->dirtyRect);
-#else
- clear(renderBuffer,layer->displayFrame);
-#endif
- } else {
- hwc_rect_t clearRegion = {0,0,0,0};
- if(CBUtils::getuiClearRegion(list, clearRegion, layerProp))
- clear(renderBuffer, clearRegion);
- }
+ ALOGD_IF (DEBUG_COPYBIT, "%s:Dirty Layer Index: %d",
+ __FUNCTION__, mDirtyLayerIndex);
+ hwc_rect_t clearRegion = {0,0,0,0};
+ mDirtyRect = list->hwLayers[last].displayFrame;
+ if (mDirtyLayerIndex != -1)
+ mDirtyRect = list->hwLayers[mDirtyLayerIndex].displayFrame;
+ if (CBUtils::getuiClearRegion(list, clearRegion, layerProp,
+ mDirtyLayerIndex))
+ clear(renderBuffer, clearRegion);
// numAppLayers-1, as we iterate from 0th layer index with HWC_COPYBIT flag
for (int i = 0; i <= (ctx->listStats[dpy].numAppLayers-1); i++) {
if(!(layerProp[i].mFlags & HWC_COPYBIT)) {
@@ -550,9 +557,6 @@
if(ctx->copybitDrop[i]) {
continue;
}
- //skip non updating layers
- if((mDirtyLayerIndex != -1) && (mDirtyLayerIndex != i) )
- continue;
int ret = -1;
if (list->hwLayers[i].acquireFenceFd != -1
&& ctx->mMDP.version >= qdutils::MDP_V4_0) {
@@ -852,11 +856,18 @@
#ifdef QCOM_BSP
//change src and dst with dirtyRect
if(mDirtyLayerIndex != -1) {
- srcRect.l = layer->dirtyRect.left;
- srcRect.t = layer->dirtyRect.top;
- srcRect.r = layer->dirtyRect.right;
- srcRect.b = layer->dirtyRect.bottom;
- dstRect = srcRect;
+ hwc_rect_t result = getIntersection(displayFrame, mDirtyRect);
+ if(!isValidRect(result))
+ return true;
+ dstRect.l = result.left;
+ dstRect.t = result.top;
+ dstRect.r = result.right;
+ dstRect.b = result.bottom;
+
+ srcRect.l += (result.left - displayFrame.left);
+ srcRect.t += (result.top - displayFrame.top);
+ srcRect.r -= (displayFrame.right - result.right);
+ srcRect.b -= (displayFrame.bottom - result.bottom);
}
#endif
// Copybit dst
@@ -1210,6 +1221,7 @@
layerCount = ctx->listStats[dpy].numAppLayers;
for (int i=0; i<ctx->listStats[dpy].numAppLayers; i++){
hnd[i] = list->hwLayers[i].handle;
+ displayFrame[i] = list->hwLayers[i].displayFrame;
}
}
diff --git a/libhwcomposer/hwc_copybit.h b/libhwcomposer/hwc_copybit.h
index a7ce43e..6ead4a7 100644
--- a/libhwcomposer/hwc_copybit.h
+++ b/libhwcomposer/hwc_copybit.h
@@ -60,6 +60,7 @@
struct LayerCache {
int layerCount;
buffer_handle_t hnd[MAX_NUM_APP_LAYERS];
+ hwc_rect_t displayFrame[MAX_NUM_APP_LAYERS];
/* c'tor */
LayerCache();
/* clear caching info*/
@@ -129,10 +130,12 @@
int mDirtyLayerIndex;
LayerCache mLayerCache;
FbCache mFbCache;
+ hwc_rect_t mDirtyRect;
int getLayersChanging(hwc_context_t *ctx, hwc_display_contents_1_t *list,
int dpy);
int checkDirtyRect(hwc_context_t *ctx, hwc_display_contents_1_t *list,
int dpy);
+ bool isLayerChanging(hwc_display_contents_1_t *list, int k);
};
}; //namespace qhwc
diff --git a/libhwcomposer/hwc_dump_layers.cpp b/libhwcomposer/hwc_dump_layers.cpp
index 6a8feb2..aad984d 100644
--- a/libhwcomposer/hwc_dump_layers.cpp
+++ b/libhwcomposer/hwc_dump_layers.cpp
@@ -130,7 +130,7 @@
mDumpCntLimPng = (mDumpCntLimPng < 0) ? 0: mDumpCntLimPng;
if (mDumpCntLimPng) {
snprintf(mDumpDirPng, sizeof(mDumpDirPng),
- "/data/sfdump.png.%04d.%02d.%02d.%02d.%02d.%02d",
+ "/data/misc/display/sfdump.png.%04d.%02d.%02d.%02d.%02d.%02d",
dumpTime.tm_year + 1900, dumpTime.tm_mon + 1,
dumpTime.tm_mday, dumpTime.tm_hour,
dumpTime.tm_min, dumpTime.tm_sec);
@@ -160,7 +160,7 @@
mDumpCntLimRaw = (mDumpCntLimRaw < 0) ? 0: mDumpCntLimRaw;
if (mDumpCntLimRaw) {
snprintf(mDumpDirRaw, sizeof(mDumpDirRaw),
- "/data/sfdump.raw.%04d.%02d.%02d.%02d.%02d.%02d",
+ "/data/misc/display/sfdump.raw.%04d.%02d.%02d.%02d.%02d.%02d",
dumpTime.tm_year + 1900, dumpTime.tm_mon + 1,
dumpTime.tm_mday, dumpTime.tm_hour,
dumpTime.tm_min, dumpTime.tm_sec);
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index b63fb3a..8660740 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -541,7 +541,7 @@
return false;
}
- if(ctx->mOverlay->comparePipePriority(destL, destR) == -1) {
+ if(ctx->mOverlay->needsPrioritySwap(destL, destR)) {
qhwc::swap(destL, destR);
}
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index d2962a3..caa1344 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -217,6 +217,9 @@
mCurrentFrame.reset(numLayers);
ctx->mOverlay->clear(mDpy);
ctx->mLayerRotMap[mDpy]->clear();
+ resetROI(ctx, mDpy);
+ memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
+ mCurrentFrame.dropCount = 0;
}
void MDPComp::reset() {
@@ -390,9 +393,9 @@
bool MDPComp::isSupportedForMDPComp(hwc_context_t *ctx, hwc_layer_1_t* layer) {
private_handle_t *hnd = (private_handle_t *)layer->handle;
if((has90Transform(layer) and (not isRotationDoable(ctx, hnd))) ||
- (not isValidDimension(ctx,layer))
- //More conditions here, SKIP, sRGB+Blend etc
- ) {
+ (not isValidDimension(ctx,layer)) ||
+ isSkipLayer(layer)) {
+ //More conditions here, sRGB+Blend etc
return false;
}
return true;
@@ -525,9 +528,11 @@
return ret;
}
-void MDPCompNonSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect) {
+void MDPCompNonSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect &crop,
+ hwc_rect &dst) {
hwc_rect_t roi = ctx->listStats[mDpy].lRoi;
- fbRect = getIntersection(fbRect, roi);
+ dst = getIntersection(dst, roi);
+ crop = dst;
}
/* 1) Identify layers that are not visible or lying outside the updating ROI and
@@ -593,7 +598,8 @@
hwc_rect_t updatingRect = dst;
#ifdef QCOM_BSP
- if(!needsScaling(layer) && !layer->transform)
+ if(!needsScaling(layer) && !layer->transform &&
+ (!isYuvBuffer((private_handle_t *)layer->handle)))
{
hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
int x_off = dst.left - src.left;
@@ -622,14 +628,20 @@
ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom);
}
-void MDPCompSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect) {
- hwc_rect l_roi = ctx->listStats[mDpy].lRoi;
- hwc_rect r_roi = ctx->listStats[mDpy].rRoi;
-
- hwc_rect_t l_fbRect = getIntersection(fbRect, l_roi);
- hwc_rect_t r_fbRect = getIntersection(fbRect, r_roi);
- fbRect = getUnion(l_fbRect, r_fbRect);
+void MDPCompSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect &crop,
+ hwc_rect &dst) {
+ hwc_rect roi = getUnion(ctx->listStats[mDpy].lRoi,
+ ctx->listStats[mDpy].rRoi);
+ hwc_rect tmpDst = getIntersection(dst, roi);
+ if(!isSameRect(dst, tmpDst)) {
+ crop.left = crop.left + (tmpDst.left - dst.left);
+ crop.top = crop.top + (tmpDst.top - dst.top);
+ crop.right = crop.left + (tmpDst.right - tmpDst.left);
+ crop.bottom = crop.top + (tmpDst.bottom - tmpDst.top);
+ dst = tmpDst;
+ }
}
+
/* 1) Identify layers that are not visible or lying outside BOTH the updating
* ROI's and drop them from composition. If a layer is spanning across both
* the halves of the screen but needed by only ROI, the non-contributing
@@ -782,13 +794,6 @@
return false;
}
- if(isSkipPresent(ctx, mDpy)) {
- ALOGD_IF(isDebug(),"%s: SKIP present: %d",
- __FUNCTION__,
- isSkipPresent(ctx, mDpy));
- return false;
- }
-
// if secondary is configuring or Padding round, fall back to video only
// composition and release all assigned non VIG pipes from primary.
if(isSecondaryConfiguring(ctx)) {
@@ -1123,7 +1128,8 @@
}
bool ret = false;
- if(list->flags & HWC_GEOMETRY_CHANGED) { //Try load based first
+ if(isSkipPresent(ctx, mDpy) or list->flags & HWC_GEOMETRY_CHANGED) {
+ //Try load based first
ret = loadBasedComp(ctx, list) or
cacheBasedComp(ctx, list);
} else {
@@ -1761,7 +1767,7 @@
fbRect = getUnion(fbRect, dst);
}
}
- trimAgainstROI(ctx, fbRect);
+ trimAgainstROI(ctx, fbRect, fbRect);
return fbRect;
}
@@ -2608,6 +2614,122 @@
}
//================MDPCompSrcSplit==============================================
+
+bool MDPCompSrcSplit::validateAndApplyROI(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list) {
+ int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+ hwc_rect_t visibleRect = ctx->listStats[mDpy].lRoi;
+
+ for(int i = numAppLayers - 1; i >= 0; i--) {
+ if(!isValidRect(visibleRect)) {
+ mCurrentFrame.drop[i] = true;
+ mCurrentFrame.dropCount++;
+ continue;
+ }
+
+ const hwc_layer_1_t* layer = &list->hwLayers[i];
+ hwc_rect_t dstRect = layer->displayFrame;
+ hwc_rect_t res = getIntersection(visibleRect, dstRect);
+
+ if(!isValidRect(res)) {
+ mCurrentFrame.drop[i] = true;
+ mCurrentFrame.dropCount++;
+ } else {
+ /* Reset frame ROI when any layer which needs scaling also needs ROI
+ * cropping */
+ if(!isSameRect(res, dstRect) && needsScaling (layer)) {
+ ALOGI("%s: Resetting ROI due to scaling", __FUNCTION__);
+ memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
+ mCurrentFrame.dropCount = 0;
+ return false;
+ }
+
+ /* deduct any opaque region from visibleRect */
+ if (layer->blending == HWC_BLENDING_NONE &&
+ layer->planeAlpha == 0xFF)
+ visibleRect = deductRect(visibleRect, res);
+ }
+ }
+ return true;
+}
+
+/*
+ * HW Limitation: ping pong split can always split the ping pong output
+ * equally across two DSI's. So the ROI programmed should be of equal width
+ * for both the halves
+ */
+void MDPCompSrcSplit::generateROI(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list) {
+ int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+
+
+ if(!canPartialUpdate(ctx, list))
+ return;
+
+ struct hwc_rect roi = (struct hwc_rect){0, 0, 0, 0};
+ hwc_rect fullFrame = (struct hwc_rect) {0, 0,(int)ctx->dpyAttr[mDpy].xres,
+ (int)ctx->dpyAttr[mDpy].yres};
+
+ for(int index = 0; index < numAppLayers; index++ ) {
+ hwc_layer_1_t* layer = &list->hwLayers[index];
+
+ // If we have a RGB layer which needs rotation, no partial update
+ if(!isYuvBuffer((private_handle_t *)layer->handle) && layer->transform)
+ return;
+
+ if ((mCachedFrame.hnd[index] != layer->handle) ||
+ isYuvBuffer((private_handle_t *)layer->handle)) {
+ hwc_rect_t dst = layer->displayFrame;
+ hwc_rect_t updatingRect = dst;
+
+#ifdef QCOM_BSP
+ if(!needsScaling(layer) && !layer->transform)
+ {
+ hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
+ int x_off = dst.left - src.left;
+ int y_off = dst.top - src.top;
+ updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
+ }
+#endif
+
+ roi = getUnion(roi, updatingRect);
+ }
+ }
+
+ /* No layer is updating. Still SF wants a refresh.*/
+ if(!isValidRect(roi))
+ return;
+
+ roi = expandROIFromMidPoint(roi, fullFrame);
+
+ hwc_rect lFrame = fullFrame;
+ lFrame.right /= 2;
+ hwc_rect lRoi = getIntersection(roi, lFrame);
+
+ // Align ROI coordinates to panel restrictions
+ lRoi = getSanitizeROI(lRoi, lFrame);
+
+ hwc_rect rFrame = fullFrame;
+ rFrame.left = lFrame.right;
+ hwc_rect rRoi = getIntersection(roi, rFrame);
+
+ // Align ROI coordinates to panel restrictions
+ rRoi = getSanitizeROI(rRoi, rFrame);
+
+ roi = getUnion(lRoi, rRoi);
+
+ ctx->listStats[mDpy].lRoi = roi;
+ if(!validateAndApplyROI(ctx, list))
+ resetROI(ctx, mDpy);
+
+ ALOGD_IF(isDebug(),"%s: generated ROI: [%d, %d, %d, %d] [%d, %d, %d, %d]",
+ __FUNCTION__,
+ ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
+ ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom,
+ ctx->listStats[mDpy].rRoi.left, ctx->listStats[mDpy].rRoi.top,
+ ctx->listStats[mDpy].rRoi.right, ctx->listStats[mDpy].rRoi.bottom);
+}
+
bool MDPCompSrcSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
MdpPipeInfoSplit& pipe_info) {
private_handle_t *hnd = (private_handle_t *)layer->handle;
@@ -2616,6 +2738,9 @@
pipe_info.lIndex = ovutils::OV_INVALID;
pipe_info.rIndex = ovutils::OV_INVALID;
+ if(qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() && !mDpy)
+ trimAgainstROI(ctx,crop, dst);
+
//If 2 pipes are staged on a single stage of a mixer, then the left pipe
//should have a higher priority than the right one. Pipe priorities are
//starting with VG0, VG1 ... , RGB0 ..., DMA1
@@ -2647,19 +2772,21 @@
const uint32_t lSplit = getLeftSplit(ctx, mDpy);
const uint32_t dstWidth = dst.right - dst.left;
const uint32_t dstHeight = dst.bottom - dst.top;
- const uint32_t cropWidth = has90Transform(layer) ? crop.bottom - crop.top :
+ uint32_t cropWidth = has90Transform(layer) ? crop.bottom - crop.top :
crop.right - crop.left;
- const uint32_t cropHeight = has90Transform(layer) ? crop.right - crop.left :
+ uint32_t cropHeight = has90Transform(layer) ? crop.right - crop.left :
crop.bottom - crop.top;
//Approximation to actual clock, ignoring the common factors in pipe and
//mixer cases like line_time
const uint32_t layerClock = getLayerClock(dstWidth, dstHeight, cropHeight);
const uint32_t mixerClock = lSplit;
- //TODO Even if a 4k video is going to be rot-downscaled to dimensions under
- //pipe line length, we are still using 2 pipes. This is fine just because
- //this is source split where destination doesn't matter. Evaluate later to
- //see if going through all the calcs to save a pipe is worth it
+ const uint32_t downscale = getRotDownscale(ctx, layer);
+ if(downscale) {
+ cropWidth /= downscale;
+ cropHeight /= downscale;
+ }
+
if(dstWidth > mdpHw.getMaxPipeWidth() or
cropWidth > mdpHw.getMaxPipeWidth() or
(primarySplitAlways and
@@ -2669,12 +2796,8 @@
return false;
}
- // Return values
- // 1 Left pipe is higher priority, do nothing.
- // 0 Pipes of same priority.
- //-1 Right pipe is of higher priority, needs swap.
- if(ctx->mOverlay->comparePipePriority(pipe_info.lIndex,
- pipe_info.rIndex) == -1) {
+ if(ctx->mOverlay->needsPrioritySwap(pipe_info.lIndex,
+ pipe_info.rIndex)) {
qhwc::swap(pipe_info.lIndex, pipe_info.rIndex);
}
}
@@ -2707,6 +2830,17 @@
ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
"dest_pipeR: %d",__FUNCTION__, layer, z, lDest, rDest);
+ if(qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() && !mDpy) {
+ /* MDP driver crops layer coordinates against ROI in Non-Split
+ * and Split MDP comp. But HWC needs to crop them for source split.
+ * Reason: 1) Source split is efficient only when the final effective
+ * load is distributed evenly across mixers.
+ * 2) We have to know the effective width of the layer that
+ * the ROI needs to find the no. of pipes the layer needs.
+ */
+ trimAgainstROI(ctx, crop, dst);
+ }
+
// Handle R/B swap
if (layer->flags & HWC_FORMAT_RB_SWAP) {
if (hnd->format == HAL_PIXEL_FORMAT_RGBA_8888)
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index 302b047..7c46c1a 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -160,9 +160,9 @@
/* validates the ROI generated for fallback conditions */
virtual bool validateAndApplyROI(hwc_context_t *ctx,
hwc_display_contents_1_t* list) = 0;
- /* Trims fbRect calculated against ROI generated */
- virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect) = 0;
-
+ /* Trims layer coordinates against ROI generated */
+ virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& crop,
+ hwc_rect& dst) = 0;
/* set/reset flags for MDPComp */
void setMDPCompLayerFlags(hwc_context_t *ctx,
hwc_display_contents_1_t* list);
@@ -315,8 +315,9 @@
/* validates the ROI generated for fallback conditions */
virtual bool validateAndApplyROI(hwc_context_t *ctx,
hwc_display_contents_1_t* list);
- /* Trims fbRect calculated against ROI generated */
- virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect);
+ /* Trims layer coordinates against ROI generated */
+ virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& crop,
+ hwc_rect& dst);
};
class MDPCompSplit : public MDPComp {
@@ -342,6 +343,9 @@
/* allocates pipes to selected candidates */
virtual bool allocLayerPipes(hwc_context_t *ctx,
hwc_display_contents_1_t* list);
+ /* Trims layer coordinates against ROI generated */
+ virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& crop,
+ hwc_rect& dst);
private:
/* Increments mdpCount if 4k2k yuv layer split is enabled.
* updates framebuffer z order if fb lies above source-split layer */
@@ -357,8 +361,6 @@
/* validates the ROI generated for fallback conditions */
virtual bool validateAndApplyROI(hwc_context_t *ctx,
hwc_display_contents_1_t* list);
- /* Trims fbRect calculated against ROI generated */
- virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect);
};
class MDPCompSrcSplit : public MDPCompSplit {
@@ -371,6 +373,12 @@
virtual int configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
PipeLayerPair& pipeLayerPair);
+ /* generates ROI based on the modified area of the frame */
+ virtual void generateROI(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list);
+ /* validates the ROI generated for fallback conditions */
+ virtual bool validateAndApplyROI(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list);
};
}; //namespace
diff --git a/libhwcomposer/hwc_uevents.cpp b/libhwcomposer/hwc_uevents.cpp
index d1c68a5..c6179e4 100644
--- a/libhwcomposer/hwc_uevents.cpp
+++ b/libhwcomposer/hwc_uevents.cpp
@@ -121,10 +121,19 @@
/* We need to send hotplug to SF only when we are disconnecting
* HDMI as an external display. */
if(dpy == HWC_DISPLAY_EXTERNAL) {
- ALOGE_IF(UEVENT_DEBUG,"%s:Sending EXTERNAL OFFLINE hotplug"
- "event", __FUNCTION__);
+ ALOGI("%s: Sending EXTERNAL OFFLINE event", __FUNCTION__);
ctx->proc->hotplug(ctx->proc, dpy, EXTERNAL_OFFLINE);
}
+
+ //On 8994, 8992 due to hardware limitations, we disable bwc
+ //when HDMI intf is active
+ if((qdutils::MDPVersion::getInstance().is8994() or
+ qdutils::MDPVersion::getInstance().is8092()) and
+ qdutils::MDPVersion::getInstance().supportsBWC()) {
+ Locker::Autolock _l(ctx->mDrawLock);
+ ctx->mBWCEnabled = true;
+ }
+
break;
}
case EXTERNAL_ONLINE:
@@ -136,6 +145,15 @@
break;
}
+ //On 8994, 8992 due to hardware limitations, we disable bwc
+ //when HDMI intf is active
+ if((qdutils::MDPVersion::getInstance().is8994() or
+ qdutils::MDPVersion::getInstance().is8092()) and
+ qdutils::MDPVersion::getInstance().supportsBWC()) {
+ Locker::Autolock _l(ctx->mDrawLock);
+ ctx->mBWCEnabled = false;
+ }
+
if (ctx->mHDMIDisplay->isHDMIPrimaryDisplay()) {
ctx->mDrawLock.lock();
handle_online(ctx, dpy);
@@ -193,14 +211,13 @@
ctx->mDrawLock.unlock();
/* External display is HDMI */
- ALOGE_IF(UEVENT_DEBUG, "%s: Sending EXTERNAL ONLINE"
- "hotplug event", __FUNCTION__);
+ ALOGI("%s: Sending EXTERNAL ONLINE event", __FUNCTION__);
ctx->proc->hotplug(ctx->proc, dpy, EXTERNAL_ONLINE);
break;
}
default:
{
- ALOGE("%s: Invalid state to swtich:%d", __FUNCTION__, switch_state);
+ ALOGE("%s: Invalid state to switch:%d", __FUNCTION__, switch_state);
break;
}
}
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 8139013..9ea8246 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -44,6 +44,7 @@
#include "hwc_virtual.h"
#include "qd_utils.h"
#include <sys/sysinfo.h>
+#include <dlfcn.h>
using namespace qClient;
using namespace qService;
@@ -74,7 +75,7 @@
#endif
#endif
-#define PROP_DEFAULT_APPBUFFER "ro.sf.default_app_buffer"
+#define PROP_DEFAULT_APPBUFFER "sf.default.app_buffer_count"
#define MAX_RAM_SIZE 512*1024*1024
#define qHD_WIDTH 540
@@ -389,6 +390,9 @@
property_get("debug.sf.hwc.canUseABC", value, "0");
ctx->enableABC = atoi(value) ? true : false;
+ // Initializing boot anim completed check to false
+ ctx->mBootAnimCompleted = false;
+
// Initialize gpu perfomance hint related parameters
property_get("sys.hwc.gpu_perf_mode", value, "0");
#ifdef QCOM_BSP
@@ -1455,10 +1459,6 @@
nwr = getIntersection(nwr, fbDisplayFrame);
}
-bool isExternalActive(hwc_context_t* ctx) {
- return ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive;
-}
-
void closeAcquireFds(hwc_display_contents_1_t* list) {
if(LIKELY(list)) {
for(uint32_t i = 0; i < list->numHwLayers; i++) {
@@ -2352,10 +2352,9 @@
bool isDisplaySplit(hwc_context_t* ctx, int dpy) {
qdutils::MDPVersion& mdpHw = qdutils::MDPVersion::getInstance();
- if(ctx->dpyAttr[dpy].xres > mdpHw.getMaxPipeWidth()) {
+ if(ctx->dpyAttr[dpy].xres > mdpHw.getMaxMixerWidth()) {
return true;
}
- //For testing we could split primary via device tree values
if(dpy == HWC_DISPLAY_PRIMARY && mdpHw.getRightSplit()) {
return true;
}
@@ -2492,6 +2491,36 @@
return (eqBounds == 3);
}
+void processBootAnimCompleted(hwc_context_t *ctx) {
+ char value[PROPERTY_VALUE_MAX];
+ int boot_finished = 0, ret = -1;
+ int (*applyMode)(int) = NULL;
+ void *modeHandle = NULL;
+
+ // Reading property set on boot finish in SF
+ property_get("service.bootanim.exit", value, "0");
+ boot_finished = atoi(value);
+ if (!boot_finished)
+ return;
+
+ modeHandle = dlopen("libmm-qdcm.so", RTLD_NOW);
+ if (modeHandle) {
+ *(void **)&applyMode = dlsym(modeHandle, "applyDefaults");
+ if (applyMode) {
+ ret = applyMode(HWC_DISPLAY_PRIMARY);
+ if (ret)
+ ALOGD("%s: Not able to apply default mode", __FUNCTION__);
+ } else {
+ ALOGE("%s: No symbol applyDefaults found", __FUNCTION__);
+ }
+ dlclose(modeHandle);
+ } else {
+ ALOGE("%s: Not able to load libmm-qdcm.so", __FUNCTION__);
+ }
+
+ ctx->mBootAnimCompleted = true;
+}
+
void BwcPM::setBwc(const hwc_context_t *ctx, const int& dpy,
const private_handle_t *hnd,
const hwc_rect_t& crop, const hwc_rect_t& dst,
@@ -2578,6 +2607,30 @@
}
}
+hwc_rect expandROIFromMidPoint(hwc_rect roi, hwc_rect fullFrame) {
+ int lRoiWidth = 0, rRoiWidth = 0;
+ int half_frame_width = fullFrame.right/2;
+
+ hwc_rect lFrame = fullFrame;
+ hwc_rect rFrame = fullFrame;
+ lFrame.right = (lFrame.right - lFrame.left)/2;
+ rFrame.left = lFrame.right;
+
+ hwc_rect lRoi = getIntersection(roi, lFrame);
+ hwc_rect rRoi = getIntersection(roi, rFrame);
+
+ lRoiWidth = lRoi.right - lRoi.left;
+ rRoiWidth = rRoi.right - rRoi.left;
+
+ if(lRoiWidth && rRoiWidth) {
+ if(lRoiWidth < rRoiWidth)
+ roi.left = half_frame_width - rRoiWidth;
+ else
+ roi.right = half_frame_width + lRoiWidth;
+ }
+ return roi;
+}
+
void resetROI(hwc_context_t *ctx, const int dpy) {
const int fbXRes = (int)ctx->dpyAttr[dpy].xres;
const int fbYRes = (int)ctx->dpyAttr[dpy].yres;
@@ -2725,12 +2778,6 @@
// Handles online events when HDMI is the primary display. In particular,
// online events for hdmi connected before AND after boot up and HWC init.
void handle_online(hwc_context_t* ctx, int dpy) {
- //On 8994 due to hardware limitations, we disable bwc completely when HDMI
- //intf is active
- if(qdutils::MDPVersion::getInstance().is8994() and
- qdutils::MDPVersion::getInstance().supportsBWC()) {
- ctx->mBWCEnabled = false;
- }
// Close the current fd if it was opened earlier on when HWC
// was initialized.
if (ctx->dpyAttr[dpy].fd >= 0) {
@@ -2761,12 +2808,6 @@
resetDisplayInfo(ctx, dpy);
ctx->dpyAttr[dpy].connected = false;
ctx->dpyAttr[dpy].isActive = false;
- //On 8994 due to hardware limitations, we enable bwc only when HDMI
- //intf is inactive
- if(qdutils::MDPVersion::getInstance().is8994() and
- qdutils::MDPVersion::getInstance().supportsBWC()) {
- ctx->mBWCEnabled = true;
- }
}
};//namespace qhwc
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 797f9b0..a97c59b 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -245,10 +245,10 @@
inline hwc_rect_t integerizeSourceCrop(const hwc_frect_t& cropF) {
hwc_rect_t cropI = {0,0,0,0};
- cropI.left = int(ceilf(cropF.left));
- cropI.top = int(ceilf(cropF.top));
- cropI.right = int(floorf(cropF.right));
- cropI.bottom = int(floorf(cropF.bottom));
+ cropI.left = int(floorf(cropF.left));
+ cropI.top = int(floorf(cropF.top));
+ cropI.right = int(ceilf(cropF.right));
+ cropI.bottom = int(ceilf(cropF.bottom));
return cropI;
}
@@ -280,7 +280,6 @@
bool isRotatorSupportedFormat(private_handle_t *hnd);
//Returns true, if the layer is YUV or the layer has been rendered by CPU
bool isRotationDoable(hwc_context_t *ctx, private_handle_t *hnd);
-bool isExternalActive(hwc_context_t* ctx);
bool isAlphaScaled(hwc_layer_1_t const* layer);
bool needsScaling(hwc_layer_1_t const* layer);
bool isDownscaleRequired(hwc_layer_1_t const* layer);
@@ -352,6 +351,9 @@
// Resets display ROI to full panel resoluion
void resetROI(hwc_context_t *ctx, const int dpy);
+// Modifies ROI even from middle of the screen
+hwc_rect expandROIFromMidPoint(hwc_rect roi, hwc_rect fullFrame);
+
// Aligns updating ROI to panel restrictions
hwc_rect_t getSanitizeROI(struct hwc_rect roi, hwc_rect boundary);
@@ -439,6 +441,9 @@
// Returns true if rect1 is peripheral to rect2, false otherwise.
bool isPeripheral(const hwc_rect_t& rect1, const hwc_rect_t& rect2);
+// Checks if boot animation has completed and applies default mode
+void processBootAnimCompleted(hwc_context_t *ctx);
+
// Inline utility functions
static inline bool isSkipLayer(const hwc_layer_1_t* l) {
return (UNLIKELY(l && (l->flags & HWC_SKIP_LAYER)));
@@ -641,6 +646,8 @@
bool mUseMetaDataRefreshRate;
// Stores the hpd enabled status- avoids re-enabling HDP on suspend resume.
bool mHPDEnabled;
+ //Used to notify that boot has completed
+ bool mBootAnimCompleted;
};
namespace qhwc {
diff --git a/libhwcomposer/hwc_virtual.cpp b/libhwcomposer/hwc_virtual.cpp
index 06418bf..a294a75 100644
--- a/libhwcomposer/hwc_virtual.cpp
+++ b/libhwcomposer/hwc_virtual.cpp
@@ -223,13 +223,15 @@
private_handle_t* ohnd, int dpy) {
bool scalingMode = false;
int fbWidth = ctx->dpyAttr[dpy].xres;
- int fbHeight = ctx->dpyAttr[dpy].yres;
- if((getWidth(ohnd) != fbWidth) || (getHeight(ohnd) != fbHeight)) {
+ int fbHeight = ctx->dpyAttr[dpy].yres;
+ int alW = 0, alH = 0;
+ getBufferSizeAndDimensions(fbWidth, fbHeight, ohnd->format, alW, alH);
+ if((getWidth(ohnd) != alW) || (getHeight(ohnd) != alH)) {
scalingMode = true;
}
ctx->dpyAttr[dpy].mMDPScalingMode = scalingMode;
ALOGD_IF(HWCVIRTUAL_LOG, "%s fb(%dx%d) outputBuffer(%dx%d) scalingMode=%d",
- __FUNCTION__, fbWidth, fbHeight,
+ __FUNCTION__, alW, alH,
getWidth(ohnd), getHeight(ohnd), scalingMode);
}
diff --git a/libhwcomposer/hwc_vsync.cpp b/libhwcomposer/hwc_vsync.cpp
index 722916a..89f8044 100644
--- a/libhwcomposer/hwc_vsync.cpp
+++ b/libhwcomposer/hwc_vsync.cpp
@@ -157,7 +157,9 @@
}
}
- pread(pfd[dpy][ev].fd, vdata , MAX_DATA, 0);
+ memset(&vdata, '\0', sizeof(vdata));
+ // Read once from the fds to clear the first notify
+ pread(pfd[dpy][ev].fd, vdata , MAX_DATA - 1, 0);
if (pfd[dpy][ev].fd >= 0)
pfd[dpy][ev].events = POLLPRI | POLLERR;
}
@@ -170,7 +172,10 @@
for (int dpy = HWC_DISPLAY_PRIMARY; dpy < num_displays; dpy++) {
for(size_t ev = 0; ev < num_events; ev++) {
if (pfd[dpy][ev].revents & POLLPRI) {
- ssize_t len = pread(pfd[dpy][ev].fd, vdata, MAX_DATA, 0);
+ // Clear vdata before writing into it
+ memset(&vdata, '\0', sizeof(vdata));
+ ssize_t len = pread(pfd[dpy][ev].fd, vdata,
+ MAX_DATA - 1, 0);
if (UNLIKELY(len < 0)) {
// If the read was just interrupted - it is not
// a fatal error. Just continue in this case
@@ -179,6 +184,7 @@
__FUNCTION__, ev, dpy, strerror(errno));
continue;
}
+ vdata[len] = '\0';
event_list[ev].callback(ctx, dpy, vdata);
}
}
diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp
index c250919..a34e599 100644
--- a/liboverlay/overlay.cpp
+++ b/liboverlay/overlay.cpp
@@ -282,38 +282,62 @@
return false;
}
-int Overlay::comparePipePriority(utils::eDest pipe1Index,
+bool Overlay::needsPrioritySwap(utils::eDest pipe1Index,
utils::eDest pipe2Index) {
validate((int)pipe1Index);
validate((int)pipe2Index);
+
uint8_t pipe1Prio = mPipeBook[(int)pipe1Index].mPipe->getPriority();
uint8_t pipe2Prio = mPipeBook[(int)pipe2Index].mPipe->getPriority();
- if(pipe1Prio > pipe2Prio)
- return -1;
- else if(pipe1Prio < pipe2Prio)
- return 1;
- else {
+
+ int pipe1Id = mPipeBook[(int)pipe1Index].mPipe->getPipeId();
+ int pipe2Id = mPipeBook[(int)pipe2Index].mPipe->getPipeId();
+
+ utils::eMdpPipeType leftType = PipeBook::getPipeType(pipe1Index);
+ utils::eMdpPipeType rightType = PipeBook::getPipeType(pipe2Index);
+
+ if(pipe1Id >=0 && pipe2Id >=0) {
+ // LEFT priority should be higher then RIGHT
+ return (pipe1Prio > pipe2Prio);
+ } else if(pipe1Id < 0 && pipe2Id < 0) {
// If we are here, Source Split is enabled and both pipes are
// new requests. In this case left type should be of higher prio
// than right type
- utils::eMdpPipeType leftType = PipeBook::getPipeType(pipe1Index);
- utils::eMdpPipeType rightType = PipeBook::getPipeType(pipe2Index);
-
if(leftType == rightType) {
//Safe. Onus on driver to assign correct pipes within same type
- return 1;
- } else if(leftType == OV_MDP_PIPE_DMA or rightType == OV_MDP_PIPE_VG) {
- //If we are here, right is definitely a higher prio type.
+ return false;
+ } else {
//This check takes advantage of having only 3 types and avoids 3
//different failure combination checks.
- return -1;
+ // Swap IF:
+ // ----------------
+ // | Left | Right |
+ // ================
+ // | DMA | ViG |
+ // ----------------
+ // | DMA | RGB |
+ // ----------------
+ // | RGB | ViG |
+ // ----------------
+ return (leftType == OV_MDP_PIPE_DMA or rightType == OV_MDP_PIPE_VG);
+ }
+ } else if(pipe1Id < 0) {
+ //LEFT needs new allocation.
+ if(leftType == rightType) {
+ // If RIGHT has highest priority(lowest id), swap it.
+ return (pipe2Id == PipeBook::pipeMinID[leftType]);
} else {
- //Types are correct priority-wise
- return 1;
+ return (leftType == OV_MDP_PIPE_DMA or rightType == OV_MDP_PIPE_VG);
+ }
+ } else { /* if (pipe2Id < 0) */
+ // RIGHT needs new allocation.
+ if(leftType == rightType) {
+ // If LEFT has lowest priority(highest id), swap it.
+ return (pipe1Id == PipeBook::pipeMaxID[leftType]);
+ } else {
+ return (leftType == OV_MDP_PIPE_DMA or rightType == OV_MDP_PIPE_VG);
}
}
-
- return 0;
}
bool Overlay::commit(utils::eDest dest) {
@@ -413,6 +437,13 @@
}
}
+ PipeBook::pipeMinID[OV_MDP_PIPE_RGB] = 8;
+ PipeBook::pipeMaxID[OV_MDP_PIPE_RGB] = (numPipesXType[OV_MDP_PIPE_RGB] == 3)? 32 : 512;
+ PipeBook::pipeMinID[OV_MDP_PIPE_VG] = 1;
+ PipeBook::pipeMaxID[OV_MDP_PIPE_VG] = (numPipesXType[OV_MDP_PIPE_VG] == 3)? 4 : 256;
+ PipeBook::pipeMinID[OV_MDP_PIPE_DMA] = 64;
+ PipeBook::pipeMaxID[OV_MDP_PIPE_DMA] = 128;
+
FILE *displayDeviceFP = NULL;
char fbType[MAX_FRAME_BUFFER_NAME_SIZE];
char msmFbTypePath[MAX_FRAME_BUFFER_NAME_SIZE];
@@ -578,6 +609,8 @@
int Overlay::PipeBook::sAllocatedBitmap = 0;
utils::eMdpPipeType Overlay::PipeBook::pipeTypeLUT[utils::OV_MAX] =
{utils::OV_MDP_PIPE_ANY};
+int Overlay::PipeBook::pipeMinID[utils::OV_MDP_PIPE_ANY] = {0};
+int Overlay::PipeBook::pipeMaxID[utils::OV_MDP_PIPE_ANY] = {0};
void *Overlay::sLibScaleHandle = NULL;
int (*Overlay::sFnProgramScale)(struct mdp_overlay_list *) = NULL;
/* Dynamically link ABL library */
diff --git a/liboverlay/overlay.h b/liboverlay/overlay.h
index 984b439..45b5e57 100644
--- a/liboverlay/overlay.h
+++ b/liboverlay/overlay.h
@@ -123,11 +123,10 @@
*/
bool isPipeTypeAttached(utils::eMdpPipeType type);
/* Compare pipe priorities and return
- * 1 if 1st pipe has a higher priority
- * 0 if both have the same priority
- *-1 if 2nd pipe has a higher priority
+ * true - A swap is needed to fix the priority.
+ * false - Good, priority wise.
*/
- int comparePipePriority(utils::eDest pipe1Index, utils::eDest pipe2Index);
+ bool needsPrioritySwap(utils::eDest pipe1Index, utils::eDest pipe2Index);
/* Returns pipe dump. Expects a NULL terminated buffer of big enough size
* to populate.
*/
@@ -229,6 +228,9 @@
static int NUM_PIPES;
static utils::eMdpPipeType pipeTypeLUT[utils::OV_MAX];
+ static int pipeMinID[utils::OV_MDP_PIPE_ANY];
+ static int pipeMaxID[utils::OV_MDP_PIPE_ANY];
+
/* Session for reserved pipes */
enum Session {
NONE,
diff --git a/liboverlay/overlayMdp.cpp b/liboverlay/overlayMdp.cpp
index 3932c4c..1290f32 100644
--- a/liboverlay/overlayMdp.cpp
+++ b/liboverlay/overlayMdp.cpp
@@ -374,8 +374,21 @@
if(errVal) {
/* No dump for failure due to insufficient resource */
if(errVal != E2BIG) {
- mdp_wrapper::dump("Bad ov dump: ",
- *list.overlay_list[list.processed_overlays]);
+ //ENODEV is returned when the driver cannot satisfy a pipe request.
+ //This could happen if previous round's UNSET hasn't been commited
+ //yet, either because of a missed vsync or because of difference in
+ //vsyncs of primary and external. This is expected during
+ //transition scenarios, but should be considered fatal if seen
+ //continuously.
+ if(errVal == ENODEV) {
+ ALOGW("%s: Pipe unavailable. Likely previous UNSET pending. "
+ "Fatal if seen continuously.", __FUNCTION__);
+ } else {
+ ALOGE("%s failed, error %d: %s", __FUNCTION__, errVal,
+ strerror(errVal));
+ mdp_wrapper::dump("Bad ov dump: ",
+ *list.overlay_list[list.processed_overlays]);
+ }
}
return false;
}
diff --git a/libqdutils/cb_utils.cpp b/libqdutils/cb_utils.cpp
index ef66ac6..c17842a 100644
--- a/libqdutils/cb_utils.cpp
+++ b/libqdutils/cb_utils.cpp
@@ -41,13 +41,36 @@
namespace qdutils {
int CBUtils::getuiClearRegion(hwc_display_contents_1_t* list,
- hwc_rect_t &clearWormholeRect, LayerProp *layerProp) {
+ hwc_rect_t &clearWormholeRect, LayerProp *layerProp, int dirtyIndex) {
size_t last = list->numHwLayers - 1;
hwc_rect_t fbFrame = list->hwLayers[last].displayFrame;
Rect fbFrameRect(fbFrame.left,fbFrame.top,fbFrame.right,fbFrame.bottom);
Region wormholeRegion(fbFrameRect);
+ if (dirtyIndex != -1) {
+#ifdef QCOM_BSP
+ /*
+ * 1. Map dirty rect of updating layer to its display frame.
+ * 2. Use this display frame as wormholeRegion instead of full Frame
+ * */
+ hwc_rect_t dirtyRect = list->hwLayers[dirtyIndex].dirtyRect;
+ hwc_rect_t displayFrame = list->hwLayers[dirtyIndex].displayFrame;
+ hwc_frect_t sCropF = list->hwLayers[dirtyIndex].sourceCropf;
+ hwc_rect_t srcRect = {int(ceilf(sCropF.left)), int(ceilf(sCropF.top)),
+ int(ceilf(sCropF.right)), int(ceilf(sCropF.bottom))};
+
+ displayFrame.left += dirtyRect.left - srcRect.left;
+ displayFrame.top += dirtyRect.top - srcRect.top;
+ displayFrame.right -= srcRect.right - dirtyRect.right;
+ displayFrame.bottom -= srcRect.bottom - dirtyRect.bottom;
+
+ Rect tmpRect(displayFrame.left,displayFrame.top,displayFrame.right,
+ displayFrame.bottom);
+ Region tmpRegion(tmpRect);
+ wormholeRegion = wormholeRegion.intersect(tmpRegion);
+#endif
+ }
if(cb_swap_rect::getInstance().checkSwapRectFeature_on() == true){
wormholeRegion.set(0,0);
for(size_t i = 0 ; i < last; i++) {
diff --git a/libqdutils/cb_utils.h b/libqdutils/cb_utils.h
index 85dd78f..59f452b 100644
--- a/libqdutils/cb_utils.h
+++ b/libqdutils/cb_utils.h
@@ -38,7 +38,7 @@
public:
static int getuiClearRegion(hwc_display_contents_1_t* list,
hwc_rect_t &clearWormholeRec,
- LayerProp *layerProp);
+ LayerProp *layerProp, int dirtyIndex = -1);
};
}//namespace qdutils
#endif /* end of include guard: CB_UTIL_H*/
diff --git a/libqdutils/qdMetaData.cpp b/libqdutils/qdMetaData.cpp
index 88109c9..aae0a47 100644
--- a/libqdutils/qdMetaData.cpp
+++ b/libqdutils/qdMetaData.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2015, 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
@@ -93,6 +93,9 @@
case MAP_SECURE_BUFFER:
data->mapSecureBuffer = *((int32_t *)param);
break;
+ case S3D_FORMAT:
+ data->s3dFormat = *((uint32_t *)param);
+ break;
default:
ALOGE("Unknown paramType %d", paramType);
break;
diff --git a/libqdutils/qdMetaData.h b/libqdutils/qdMetaData.h
index 32d788e..a1afa38 100644
--- a/libqdutils/qdMetaData.h
+++ b/libqdutils/qdMetaData.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2015, 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
@@ -86,6 +86,9 @@
* for clients to set, and GPU will to read and know when to map the
* SECURE_BUFFER(ION) */
int32_t mapSecureBuffer;
+ /* The supported formats are defined in gralloc_priv.h to
+ * support legacy code*/
+ uint32_t s3dFormat;
};
enum DispParamType {
@@ -100,6 +103,7 @@
UPDATE_REFRESH_RATE = 0x0100,
UPDATE_COLOR_SPACE = 0x0200,
MAP_SECURE_BUFFER = 0x400,
+ S3D_FORMAT = 0x800,
};
struct private_handle_t;
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index ef47475..cd2d116 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -59,6 +59,7 @@
CONFIGURE_DYN_REFRESH_RATE = 18,
SET_PARTIAL_UPDATE = 19, // Preference on partial update feature
TOGGLE_SCREEN_UPDATE = 20, // Provides ability to disable screen updates
+ SET_FRAME_DUMP_CONFIG = 21, // Provides ability to set the frame dump config
COMMAND_LIST_END = 400,
};
@@ -73,6 +74,14 @@
DEBUG_VSYNC,
DEBUG_VD,
DEBUG_PIPE_LIFECYCLE,
+ DEBUG_DRIVER_CONFIG,
+ DEBUG_ROTATOR,
+ };
+
+ enum {
+ DUMP_PRIMARY_DISPLAY,
+ DUMP_HDMI_DISPLAY,
+ DUMP_VIRTUAL_DISPLAY,
};
// Register a client that can be notified