Merge "hwc: Use 1 pipe if rotator downscale reduces dimensions"
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
index 1e99d1a..c054fae 100644
--- a/displayengine/include/core/display_interface.h
+++ b/displayengine/include/core/display_interface.h
@@ -284,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
diff --git a/displayengine/include/core/layer_buffer.h b/displayengine/include/core/layer_buffer.h
old mode 100755
new mode 100644
index 51fa5c5..9f7110a
--- a/displayengine/include/core/layer_buffer.h
+++ b/displayengine/include/core/layer_buffer.h
@@ -96,6 +96,8 @@
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
@@ -123,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..0a37c79
--- 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"
@@ -137,6 +138,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 +197,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..04a5f77 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,9 @@
#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))
namespace sde {
diff --git a/displayengine/include/utils/debug.h b/displayengine/include/utils/debug.h
index 7983c84..65079a9 100644
--- a/displayengine/include/utils/debug.h
+++ b/displayengine/include/utils/debug.h
@@ -1,25 +1,30 @@
/*
* 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,12 +47,18 @@
#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();
@@ -55,18 +67,21 @@
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/libs/core/Android.mk b/displayengine/libs/core/Android.mk
index 92569a5..1623c13 100644
--- a/displayengine/libs/core/Android.mk
+++ b/displayengine/libs/core/Android.mk
@@ -23,6 +23,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 c35a4db..7e888ee 100644
--- a/displayengine/libs/core/comp_manager.cpp
+++ b/displayengine/libs/core/comp_manager.cpp
@@ -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;
}
@@ -223,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);
@@ -240,9 +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) {
diff --git a/displayengine/libs/core/comp_manager.h b/displayengine/libs/core/comp_manager.h
index 674f0d0..24a0fff 100644
--- a/displayengine/libs/core/comp_manager.h
+++ b/displayengine/libs/core/comp_manager.h
@@ -36,15 +36,16 @@
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);
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 95e15d5..058bacc 100644
--- a/displayengine/libs/core/display_base.cpp
+++ b/displayengine/libs/core/display_base.cpp
@@ -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() {
@@ -83,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_);
@@ -100,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;
@@ -118,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;
@@ -130,11 +148,17 @@
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_);
@@ -159,11 +183,18 @@
DLOGE("Commit: Corresponding Prepare() is not called for display = %d", display_type_);
return kErrorUndefined;
}
- error = hw_intf_->Commit(hw_device_, &hw_layers_);
+
+ error = offline_ctrl_->Commit(display_offline_ctx_, &hw_layers_);
if (error == kErrorNone) {
- comp_manager_->PostCommit(display_comp_ctx_, &hw_layers_);
- } else {
- DLOGE("Unexpected error. Commit failed on driver.");
+ 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;
@@ -276,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:
@@ -305,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;
@@ -315,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;
}
@@ -388,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",
@@ -395,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 5ff219b..d2b67e3 100644
--- a/displayengine/libs/core/display_base.h
+++ b/displayengine/libs/core/display_base.h
@@ -31,13 +31,18 @@
#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();
@@ -51,6 +56,7 @@
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);
@@ -73,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 07bbca0..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;
@@ -77,29 +76,5 @@
return best_config_mode;
}
-DisplayError DisplayHDMI::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_->Flush(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_hdmi.h b/displayengine/libs/core/display_hdmi.h
index 8de7fdf..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,9 +31,9 @@
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();
- virtual DisplayError SetDisplayState(DisplayState state);
};
} // namespace sde
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 57a2b69..5d1f725 100644
--- a/displayengine/libs/core/hw_framebuffer.cpp
+++ b/displayengine/libs/core/hw_framebuffer.cpp
@@ -1,25 +1,30 @@
/*
* 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
@@ -59,9 +65,10 @@
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;
@@ -165,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:
@@ -190,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_) {
@@ -225,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;
@@ -247,6 +262,7 @@
switch (hw_context->type) {
case kDevicePrimary:
+ case kDeviceVirtual:
break;
case kDeviceHDMI:
hdmi_mode_count_ = 0;
@@ -268,6 +284,7 @@
switch (hw_context->type) {
case kDevicePrimary:
+ case kDeviceVirtual:
*count = 1;
break;
case kDeviceHDMI:
@@ -286,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
@@ -294,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;
}
@@ -302,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;
}
@@ -357,6 +376,9 @@
}
break;
+ case kDeviceVirtual:
+ break;
+
default:
return kErrorParameters;
}
@@ -365,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;
}
@@ -402,7 +427,7 @@
STRUCT_VAR(msmfb_metadata, 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;
}
@@ -413,7 +438,7 @@
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;
}
@@ -455,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;
}
@@ -471,11 +498,14 @@
}
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;
}
@@ -500,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;
}
@@ -510,65 +542,222 @@
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;
+ }
+ }
+
+ 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);
+ 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;
}
@@ -576,67 +765,305 @@
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;
+ 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_context->ResetMDPCommit();
- mdp_layer_commit_v1 &mdp_commit = hw_context->mdp_commit.commit_v1;
+ 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_context->mdp_commit) == -1) {
+ 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;
}
@@ -670,6 +1097,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;
@@ -685,6 +1153,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();
@@ -718,7 +1211,7 @@
pthread_exit(0);
}
- typedef void (HWFrameBuffer::*EventHandler)(int, char *);
+ typedef void (HWFrameBuffer::*EventHandler)(int, char*);
EventHandler event_handler[kNumDisplayEvents] = { &HWFrameBuffer::HandleVSync,
&HWFrameBuffer::HandleBlank,
&HWFrameBuffer::HandleIdleTimeout };
diff --git a/displayengine/libs/core/hw_framebuffer.h b/displayengine/libs/core/hw_framebuffer.h
index 54f44a1..6df705d 100644
--- a/displayengine/libs/core/hw_framebuffer.h
+++ b/displayengine/libs/core/hw_framebuffer.h
@@ -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,28 +56,64 @@
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_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));
+
+ 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;
+ }
+ };
+
+ 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 {
@@ -120,9 +156,20 @@
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);
@@ -172,6 +219,7 @@
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 6e87edd..1217b95 100644
--- a/displayengine/libs/core/hw_interface.h
+++ b/displayengine/libs/core/hw_interface.h
@@ -28,6 +28,8 @@
#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>
namespace sde {
@@ -44,7 +46,8 @@
kDevicePrimary,
kDeviceHDMI,
kDeviceVirtual,
- kDeviceMax
+ kDeviceRotator,
+ kDeviceMax,
};
struct HWResourceInfo {
@@ -90,48 +93,68 @@
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;
+ 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,6 +162,8 @@
uint32_t split_left;
HWDisplayAttributes() : is_device_split(false), split_left(0) { }
+
+ void Reset() { *this = HWDisplayAttributes(); }
};
// HWEventHandler - Implemented in DisplayBase and HWInterface implementation
@@ -148,12 +173,12 @@
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;
@@ -168,6 +193,8 @@
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;
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 0c8859f..cf2a5c7 100644
--- a/displayengine/libs/core/res_config.cpp
+++ b/displayengine/libs/core/res_config.cpp
@@ -58,7 +58,7 @@
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;
@@ -72,21 +72,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) {
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;
}
@@ -94,12 +93,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);
@@ -123,9 +123,8 @@
// 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;
+ 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",
@@ -135,14 +134,13 @@
// 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();
@@ -150,16 +148,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 {
@@ -230,12 +227,12 @@
// 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);
}
@@ -421,6 +418,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;
diff --git a/displayengine/libs/core/res_manager.cpp b/displayengine/libs/core/res_manager.cpp
index e3fbdda..16fc8b4 100644
--- a/displayengine/libs/core/res_manager.cpp
+++ b/displayengine/libs/core/res_manager.cpp
@@ -33,12 +33,23 @@
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 +91,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;
@@ -143,6 +157,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 +275,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 +300,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 +315,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;
@@ -336,6 +358,12 @@
goto CleanupOnError;
}
+ error = AllocRotatorBuffer(display_ctx, hw_layers);
+ if (error != kErrorNone) {
+ DLOGV_IF(kTagResources, "Rotator buffer allocation failed");
+ goto CleanupOnError;
+ }
+
return kErrorNone;
CleanupOnError:
@@ -348,6 +376,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 +393,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 +589,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 +735,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) {
@@ -798,8 +955,10 @@
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)
@@ -840,7 +999,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)) {
@@ -869,5 +1028,43 @@
}
}
+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;
+}
+
+
} // namespace sde
diff --git a/displayengine/libs/core/res_manager.h b/displayengine/libs/core/res_manager.h
index 1f65c50..926b2b7 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 {
@@ -184,6 +196,9 @@
void AssignRotator(HWRotateInfo *rotate, uint32_t *rotate_cnt);
void ClearRotator(DisplayResourceContext *display_resource_ctx);
void NormalizeRect(const uint32_t &factor, LayerRect *rect);
+ DisplayError AllocRotatorBuffer(Handle display_ctx, HWLayers *hw_layers);
+ void SetRotatorOutputFormat(const LayerBufferFormat &input_format, bool bwc, bool rot90,
+ LayerBufferFormat *output_format);
template <class T>
inline void Swap(T &a, T &b) {
@@ -217,6 +232,9 @@
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
};
} // 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 5294faa..452bff1 100644
--- a/displayengine/libs/hwc/hwc_display.cpp
+++ b/displayengine/libs/hwc/hwc_display.cpp
@@ -1,33 +1,40 @@
/*
* 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"
@@ -36,13 +43,15 @@
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),
- flush_(false) {
+ 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;
}
@@ -56,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;
@@ -174,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;
@@ -186,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);
@@ -296,7 +318,8 @@
LayerBuffer *layer_buffer = layer.input_buffer;
if (pvt_handle) {
- if (SetFormat(pvt_handle->format, pvt_handle->flags, &layer_buffer->format)) {
+ layer_buffer->format = GetSDEFormat(pvt_handle->format, pvt_handle->flags);
+ if (layer_buffer->format == kFormatInvalid) {
return -EINVAL;
}
@@ -310,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);
@@ -386,6 +416,8 @@
size_t num_hw_layers = content_list->numHwLayers;
+ 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];
@@ -411,13 +443,18 @@
}
}
+ return status;
+}
+
+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);
}
-
- flush_ = false;
}
for (size_t i = 0; i < num_hw_layers; i++) {
@@ -425,7 +462,7 @@
Layer &layer = layer_stack_.layers[i];
LayerBuffer *layer_buffer = layer_stack_.layers[i].input_buffer;
- if ((status == 0) && (layer.composition == kCompositionSDE ||
+ if (!flush_ && (layer.composition == kCompositionSDE ||
layer.composition == kCompositionGPUTarget)) {
hwc_layer.releaseFenceFd = layer_buffer->release_fence_fd;
}
@@ -435,9 +472,21 @@
}
}
+ if (!flush_) {
+ 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;
@@ -526,44 +575,160 @@
}
}
-int HWCDisplay::SetFormat(const int32_t &source, const int flags, LayerBufferFormat *target) {
-
- if (flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
- switch (source) {
- case HAL_PIXEL_FORMAT_RGBA_8888: *target = kFormatRGBA8888Ubwc; break;
- case HAL_PIXEL_FORMAT_RGB_565: *target = 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: *target = kFormatYCbCr420SPVenusUbwc; break;
- default:
- DLOGE("Unsupported format type for UBWC %d", source);
- return -EINVAL;
- }
- return 0;
- }
-
- 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;
- case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC: *target = kFormatYCbCr420SPVenusUbwc; break;
- default:
- DLOGW("Unsupported format type = %d", source);
- return -EINVAL;
- }
-
- return 0;
-}
-
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;
+ }
+
+ 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 262c719..3934078 100644
--- a/displayengine/libs/hwc/hwc_display.h
+++ b/displayengine/libs/hwc/hwc_display.h
@@ -43,6 +43,8 @@
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.
@@ -81,6 +83,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);
@@ -88,7 +91,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, const int flags, 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_;
@@ -99,6 +111,10 @@
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 8fd72b8..3bc4fd1 100644
--- a/displayengine/libs/hwc/hwc_session.cpp
+++ b/displayengine/libs/hwc/hwc_session.cpp
@@ -1,25 +1,30 @@
/*
* 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);
@@ -450,6 +576,11 @@
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;
@@ -458,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);
@@ -465,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();
@@ -532,7 +700,6 @@
return -1;
}
-
int HWCSession::HotPlugHandler(bool connected) {
if (!hwc_procs_) {
DLOGW("Ignore hotplug - hwc_proc not registered");
@@ -540,7 +707,7 @@
}
if (connected) {
- SCOPE_LOCK(locker_);
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
if (display_external_) {
DLOGE("HDMI already connected");
return -1;
@@ -557,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/debug_android.cpp b/displayengine/libs/utils/debug_android.cpp
index 447a88d..1b08fe9 100644
--- a/displayengine/libs/utils/debug_android.cpp
+++ b/displayengine/libs/utils/debug_android.cpp
@@ -1,25 +1,30 @@
/*
* 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);
diff --git a/libgralloc/gpu.cpp b/libgralloc/gpu.cpp
index 48da09e..df7be41 100644
--- a/libgralloc/gpu.cpp
+++ b/libgralloc/gpu.cpp
@@ -289,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/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index 546a67b..f1edf5d 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,
@@ -472,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) {
@@ -480,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;
}
}
@@ -533,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)) {
@@ -555,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) {
@@ -857,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
@@ -1213,6 +1219,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_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index b17bdaf..caa1344 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -528,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
@@ -626,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
@@ -1759,7 +1767,7 @@
fbRect = getUnion(fbRect, dst);
}
}
- trimAgainstROI(ctx, fbRect);
+ trimAgainstROI(ctx, fbRect, fbRect);
return fbRect;
}
@@ -2606,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;
@@ -2614,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
@@ -2703,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_utils.cpp b/libhwcomposer/hwc_utils.cpp
index f53e8c4..8fb622f 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -74,7 +74,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
@@ -2577,6 +2577,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;
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 797f9b0..d419213 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -352,6 +352,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);
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 ca599ed..a34e599 100644
--- a/liboverlay/overlay.cpp
+++ b/liboverlay/overlay.cpp
@@ -306,14 +306,20 @@
if(leftType == rightType) {
//Safe. Onus on driver to assign correct pipes within same type
return false;
- } else if(leftType == OV_MDP_PIPE_DMA or rightType == OV_MDP_PIPE_VG) {
- //If we are here, right is definitely a higher prio type.
+ } else {
//This check takes advantage of having only 3 types and avoids 3
//different failure combination checks.
- return true;
- } else {
- //Types are correct priority-wise
- return false;
+ // 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.
@@ -321,8 +327,7 @@
// If RIGHT has highest priority(lowest id), swap it.
return (pipe2Id == PipeBook::pipeMinID[leftType]);
} else {
- // Swap if needs lowest priority type pipe.
- return (leftType == OV_MDP_PIPE_DMA);
+ return (leftType == OV_MDP_PIPE_DMA or rightType == OV_MDP_PIPE_VG);
}
} else { /* if (pipe2Id < 0) */
// RIGHT needs new allocation.
@@ -330,8 +335,7 @@
// If LEFT has lowest priority(highest id), swap it.
return (pipe1Id == PipeBook::pipeMaxID[leftType]);
} else {
- // Swap if needs highest priority type pipe.
- return (rightType == OV_MDP_PIPE_VG);
+ return (leftType == OV_MDP_PIPE_DMA or rightType == OV_MDP_PIPE_VG);
}
}
}
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/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