sde: Add Support for UI/Video rotation using SDE rotator
1. Implement Buffer manager to allocate and deallocate output buffers
for rotator.
2. Assign buffer slot for each layer requires rotation and manage the
internal state of buffer slot in buffer manager.
3. Get the output buffer for each layer requires rotation from buffer
manager and associate the information along with that layer.
4. Create/Destroy the rotator session from the hint provided by buffer
manager. This is required to help driver to calculate the bandwidth
for the current frame.
5. Validate the rotator configurations and submit the rotation job
using rotator validate and rotator commit ioctl.
Change-Id: I1bc1de05042f64d5f32e95ac6226890fa4fabd24
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
index aee077e..114d9aa 100644
--- a/displayengine/include/core/core_interface.h
+++ b/displayengine/include/core/core_interface.h
@@ -41,6 +41,9 @@
#include "display_interface.h"
#include "sde_types.h"
+#include "buffer_allocator.h"
+
+class BufferSyncHandler;
/*! @brief Display engine interface version.
@@ -131,6 +134,8 @@
@param[in] event_handler \link CoreEventHandler \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.
@@ -139,7 +144,9 @@
@sa DestroyCore
*/
static DisplayError CreateCore(CoreEventHandler *event_handler, DebugHandler *debug_handler,
- CoreInterface **interface, uint32_t version = SDE_VERSION_TAG);
+ 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
index 96def76..b01e086 100644
--- a/displayengine/include/core/debug_interface.h
+++ b/displayengine/include/core/debug_interface.h
@@ -44,6 +44,9 @@
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.
+ 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.
@@ -104,7 +107,7 @@
/*! @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.
+ module. It starts the trace upon object creation and ends the trace upon object destruction.
*/
template <class T>
class ScopeTracer {
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/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/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..a9b4e6c 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,6 +118,7 @@
if (error != kErrorNone) {
destroy_strategy_intf_(display_comp_ctx->strategy_intf);
delete display_comp_ctx;
+ display_comp_ctx = NULL;
return error;
}
@@ -140,7 +144,10 @@
CLEAR_BIT(registered_displays_, display_comp_ctx->display_type);
CLEAR_BIT(configured_displays_, display_comp_ctx->display_type);
- delete display_comp_ctx;
+ if (display_comp_ctx) {
+ delete display_comp_ctx;
+ display_comp_ctx = NULL;
+ }
return kErrorNone;
}
@@ -223,16 +230,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 +258,14 @@
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;
+
+ 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..ccc9331
--- 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;
@@ -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
index d4a4079..c982b4d 100644
--- a/displayengine/libs/core/core_interface.cpp
+++ b/displayengine/libs/core/core_interface.cpp
@@ -30,6 +30,7 @@
#include <utils/locker.h>
#include <utils/constants.h>
#include <utils/debug.h>
+#include <core/buffer_sync_handler.h>
#include "core_impl.h"
@@ -50,11 +51,14 @@
Locker locker;
} g_core;
+// 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 || !debug_handler || !interface)) {
+ if (!event_handler || !debug_handler || !buffer_allocator || !buffer_sync_handler || !interface) {
return kErrorParameters;
}
@@ -77,7 +81,7 @@
// 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..fcb4d56 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;
@@ -388,6 +419,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 +428,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..5f9a8c8 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();
@@ -73,9 +78,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..a384385 100644
--- a/displayengine/libs/core/display_hdmi.cpp
+++ b/displayengine/libs/core/display_hdmi.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
@@ -32,9 +32,8 @@
namespace sde {
DisplayHDMI::DisplayHDMI(DisplayEventHandler *event_handler, HWInterface *hw_intf,
- CompManager *comp_manager)
- : DisplayBase(kHDMI, event_handler, kDeviceHDMI, hw_intf, comp_manager) {
-}
+ CompManager *comp_manager, OfflineCtrl *offline_ctrl)
+ : DisplayBase(kHDMI, event_handler, kDeviceHDMI, hw_intf, comp_manager, offline_ctrl) { }
int DisplayHDMI::GetBestConfig() {
uint32_t best_config_mode = 0;
diff --git a/displayengine/libs/core/display_hdmi.h b/displayengine/libs/core/display_hdmi.h
index 8de7fdf..94c40a1 100644
--- a/displayengine/libs/core/display_hdmi.h
+++ b/displayengine/libs/core/display_hdmi.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
@@ -31,7 +31,8 @@
class DisplayHDMI : public DisplayBase {
public:
- DisplayHDMI(DisplayEventHandler *event_handler, HWInterface *hw_intf, CompManager *comp_manager);
+ DisplayHDMI(DisplayEventHandler *event_handler, HWInterface *hw_intf, CompManager *comp_manager,
+ OfflineCtrl *offline_ctrl);
virtual int GetBestConfig();
virtual DisplayError SetDisplayState(DisplayState state);
};
diff --git a/displayengine/libs/core/display_primary.cpp b/displayengine/libs/core/display_primary.cpp
old mode 100755
new mode 100644
index e4bd031..8eed8ee
--- 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,9 +32,8 @@
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) { }
} // namespace sde
diff --git a/displayengine/libs/core/display_primary.h b/displayengine/libs/core/display_primary.h
index 183e964..ea4cf2b 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,7 @@
class DisplayPrimary : public DisplayBase {
public:
DisplayPrimary(DisplayEventHandler *event_handler, HWInterface *hw_intf,
- CompManager *comp_manager);
+ CompManager *comp_manager, OfflineCtrl *offline_ctrl);
};
} // 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 cafbddd..714e678 100644
--- a/displayengine/libs/core/hw_framebuffer.cpp
+++ b/displayengine/libs/core/hw_framebuffer.cpp
@@ -44,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
@@ -64,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;
@@ -195,7 +197,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_) {
@@ -230,16 +232,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;
@@ -301,7 +307,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;
}
@@ -309,7 +315,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;
}
@@ -385,7 +391,7 @@
{
// 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;
}
@@ -411,7 +417,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;
}
@@ -422,7 +428,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;
}
@@ -468,7 +474,7 @@
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;
}
@@ -485,10 +491,11 @@
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;
}
@@ -517,7 +524,7 @@
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;
}
@@ -525,67 +532,205 @@
return 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);
+
+ 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);
- hw_context->ResetMDPCommit();
+ 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_disp_layers;
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, "*************************************************************");
+ }
}
}
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;
}
@@ -593,42 +738,65 @@
return kErrorNone;
}
-DisplayError HWFrameBuffer::Commit(Handle device, HWLayers *hw_layers) {
+DisplayError HWFrameBuffer::DisplayCommit(HWContext *hw_context, HWLayers *hw_layers) {
DTRACE_SCOPED();
- HWContext *hw_context = reinterpret_cast<HWContext *>(device);
+ 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_disp_layers;
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;
+ 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;
+ }
+
+ mdp_buffer.fence = input_buffer->acquire_fence_fd;
+ mdp_layer_index++;
+
+ DLOGV_IF(kTagDriverConfig, "****************** Layer[%d] %s pipe Input *******************",
+ i, count ? "Right" : "Left");
+ DLOGV_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, "*************************************************************");
+ }
}
}
+ 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;
}
@@ -639,23 +807,202 @@
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);
+ 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(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(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;
}
@@ -689,6 +1036,39 @@
return kErrorNone;
}
+DisplayError HWFrameBuffer::SetStride(LayerBufferFormat format, uint32_t width, uint32_t *target) {
+ 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;
@@ -704,6 +1084,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();
@@ -737,7 +1142,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..d6b76b5 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,61 @@
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_disp_layers[kMaxSDELayers * 2]; // split panel (left + right)
+
+ HWDisplay() { Reset(); }
+
+ void Reset() {
+ memset(&mdp_disp_commit, 0, sizeof(mdp_disp_commit));
+ memset(&mdp_disp_layers, 0, sizeof(mdp_disp_layers));
+
+ for (uint32_t i = 0; i < kMaxSDELayers * 2; i++) {
+ mdp_disp_layers[i].buffer.fence = -1;
+ }
+
+ mdp_disp_commit.version = MDP_COMMIT_VERSION_1_0;
+ mdp_disp_commit.commit_v1.input_layers = mdp_disp_layers;
+ 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 +153,19 @@
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(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 +215,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..7eb2b87 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:
@@ -360,19 +388,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 +584,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 +730,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 +950,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 +994,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 +1023,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
index fe93502..d31c71e 100644
--- 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_debugger.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
index 9312010..6a6cf08 100644
--- a/displayengine/libs/hwc/hwc_debugger.cpp
+++ b/displayengine/libs/hwc/hwc_debugger.cpp
@@ -60,6 +60,30 @@
}
}
+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);
diff --git a/displayengine/libs/hwc/hwc_debugger.h b/displayengine/libs/hwc/hwc_debugger.h
index d4315c2..705ae3a 100644
--- a/displayengine/libs/hwc/hwc_debugger.h
+++ b/displayengine/libs/hwc/hwc_debugger.h
@@ -57,6 +57,9 @@
static void DebugAll(bool enable);
static void DebugResources(bool enable);
static void DebugStrategy(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, ...);
diff --git a/displayengine/libs/hwc/hwc_display.cpp b/displayengine/libs/hwc/hwc_display.cpp
index e094c80..a1f907c 100644
--- a/displayengine/libs/hwc/hwc_display.cpp
+++ b/displayengine/libs/hwc/hwc_display.cpp
@@ -30,6 +30,7 @@
#include <errno.h>
#include <gralloc_priv.h>
#include <utils/constants.h>
+#include <qdMetaData.h>
#include "hwc_display.h"
#include "hwc_debugger.h"
@@ -61,8 +62,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;
@@ -315,6 +317,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);
diff --git a/displayengine/libs/hwc/hwc_session.cpp b/displayengine/libs/hwc/hwc_session.cpp
index fb88afc..e5fe4c7 100644
--- a/displayengine/libs/hwc/hwc_session.cpp
+++ b/displayengine/libs/hwc/hwc_session.cpp
@@ -35,7 +35,10 @@
#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_debugger.h"
@@ -97,7 +100,20 @@
return -EINVAL;
}
- DisplayError error = CoreInterface::CreateCore(this, HWCDebugHandler::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;
@@ -485,10 +501,22 @@
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();
diff --git a/displayengine/libs/hwc/hwc_session.h b/displayengine/libs/hwc/hwc_session.h
index 488da9d..e65d51a 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:
@@ -89,6 +89,8 @@
pthread_t hotplug_thread_;
bool hotplug_thread_exit_;
const char *hotplug_thread_name_;
+ HWCBufferAllocator *buffer_allocator_;
+ HWCBufferSyncHandler *buffer_sync_handler_;
};
} // namespace sde