display: Update to AU 269 am: f1fe88efc1

am: 3533a776b5

Change-Id: Icc4c6d0e1aa37bf4b37c1ff4a94bee0613f2de0a
This commit is contained in:
Naseer Ahmed 2017-07-13 05:43:21 +00:00 committed by android-build-merger
commit 634e7b4dac
39 changed files with 1066 additions and 93 deletions

View File

@ -2,7 +2,6 @@ LOCAL_PATH := $(call my-dir)
include $(LOCAL_PATH)/../common.mk
include $(CLEAR_VARS)
LOCAL_VENDOR_MODULE := true
LOCAL_COPY_HEADERS_TO := $(common_header_export_path)
LOCAL_COPY_HEADERS := TonemapFactory.h Tonemapper.h
include $(BUILD_COPY_HEADERS)

View File

@ -24,7 +24,6 @@
#include <map>
#include "EGLImageWrapper.h"
#include "glengine.h"
#define EGL_PROTECTED_CONTENT_EXT 0x32C0
//-----------------------------------------------------------------------------
EGLImageKHR create_eglImage(android::sp<android::GraphicBuffer> graphicBuffer)

View File

@ -121,7 +121,7 @@ static EGLImageBuffer* L_wrap(const private_handle_t *src)
}
android::sp<android::GraphicBuffer> graphicBuffer =
new android::GraphicBuffer(src->width, src->height, src->format,
new android::GraphicBuffer(src->unaligned_width, src->unaligned_height, src->format,
#ifndef __NOUGAT__
1, // Layer count
#endif

View File

@ -24,11 +24,11 @@
//----------------------------------------------------------------------------------------------------------------------------------------------------------
Tonemapper *TonemapperFactory_GetInstance(int type, void *colorMap, int colorMapSize,
void *lutXform, int lutXformSize)
void *lutXform, int lutXformSize, bool isSecure)
//----------------------------------------------------------------------------------------------------------------------------------------------------------
{
// build the tonemapper
Tonemapper *tonemapper = Tonemapper::build(type, colorMap, colorMapSize, lutXform, lutXformSize);
Tonemapper *tonemapper = Tonemapper::build(type, colorMap, colorMapSize, lutXform, lutXformSize, isSecure);
return tonemapper;
}

View File

@ -28,7 +28,7 @@ extern "C" {
// returns an instance of Tonemapper
Tonemapper *TonemapperFactory_GetInstance(int type, void *colorMap, int colorMapSize,
void *lutXform, int lutXformSize);
void *lutXform, int lutXformSize, bool isSecure);
#ifdef __cplusplus
}

View File

@ -33,12 +33,19 @@ Tonemapper::Tonemapper()
lutXformTexture = 0;
programID = 0;
eglImageWrapper = new EGLImageWrapper();
lutXformScaleOffset[0] = 1.0f;
lutXformScaleOffset[1] = 0.0f;
tonemapScaleOffset[0] = 1.0f;
tonemapScaleOffset[1] = 0.0f;
}
//-----------------------------------------------------------------------------
Tonemapper::~Tonemapper()
//-----------------------------------------------------------------------------
{
void* caller_context = engine_backup();
engine_bind(engineContext);
engine_deleteInputBuffer(tonemapTexture);
engine_deleteInputBuffer(lutXformTexture);
@ -51,11 +58,14 @@ Tonemapper::~Tonemapper()
}
engine_shutdown(engineContext);
// restore the caller context
engine_bind(caller_context);
engine_free_backup(caller_context);
}
//-----------------------------------------------------------------------------
Tonemapper *Tonemapper::build(int type, void *colorMap, int colorMapSize, void *lutXform,
int lutXformSize)
int lutXformSize, bool isSecure)
//-----------------------------------------------------------------------------
{
if (colorMapSize <= 0) {
@ -66,15 +76,24 @@ Tonemapper *Tonemapper::build(int type, void *colorMap, int colorMapSize, void *
// build new tonemapper
Tonemapper *tonemapper = new Tonemapper();
tonemapper->engineContext = engine_initialize();
tonemapper->engineContext = engine_initialize(isSecure);
void* caller_context = engine_backup();
engine_bind(tonemapper->engineContext);
// load the 3d lut
tonemapper->tonemapTexture = engine_load3DTexture(colorMap, colorMapSize, 0);
tonemapper->tonemapScaleOffset[0] = ((float)(colorMapSize-1))/((float)(colorMapSize));
tonemapper->tonemapScaleOffset[1] = 1.0f/(2.0f*colorMapSize);
// load the non-uniform xform
tonemapper->lutXformTexture = engine_load1DTexture(lutXform, lutXformSize, 0);
bool bUseXform = (tonemapper->lutXformTexture != 0) && (lutXformSize != 0);
if( bUseXform )
{
tonemapper->lutXformScaleOffset[0] = ((float)(lutXformSize-1))/((float)(lutXformSize));
tonemapper->lutXformScaleOffset[1] = 1.0f/(2.0f*lutXformSize);
}
// create the program
const char *fragmentShaders[3];
@ -98,6 +117,10 @@ Tonemapper *Tonemapper::build(int type, void *colorMap, int colorMapSize, void *
tonemapper->programID =
engine_loadProgram(1, &fullscreen_vertex_shader, fragmentShaderCount, fragmentShaders);
// restore the caller context
engine_bind(caller_context);
engine_free_backup(caller_context);
return tonemapper;
}
@ -105,6 +128,7 @@ Tonemapper *Tonemapper::build(int type, void *colorMap, int colorMapSize, void *
int Tonemapper::blit(const void *dst, const void *src, int srcFenceFd)
//-----------------------------------------------------------------------------
{
void* caller_context = engine_backup();
// make current
engine_bind(engineContext);
@ -115,6 +139,13 @@ int Tonemapper::blit(const void *dst, const void *src, int srcFenceFd)
// bind the program
engine_setProgram(programID);
engine_setData2f(3, tonemapScaleOffset);
bool bUseXform = (lutXformTexture != 0);
if( bUseXform )
{
engine_setData2f(4, lutXformScaleOffset);
}
// set destination
engine_setDestination(dst_buffer->getFramebuffer(), 0, 0, dst_buffer->getWidth(),
dst_buffer->getHeight());
@ -128,5 +159,10 @@ int Tonemapper::blit(const void *dst, const void *src, int srcFenceFd)
// perform
int fenceFD = engine_blit(srcFenceFd);
// restore the caller context
engine_bind(caller_context);
engine_free_backup(caller_context);
return fenceFD;
}

View File

@ -32,13 +32,15 @@ class Tonemapper {
unsigned int tonemapTexture;
unsigned int lutXformTexture;
unsigned int programID;
float lutXformScaleOffset[2];
float tonemapScaleOffset[2];
EGLImageWrapper* eglImageWrapper;
Tonemapper();
public:
~Tonemapper();
static Tonemapper *build(int type, void *colorMap, int colorMapSize, void *lutXform,
int lutXformSize);
int lutXformSize, bool isSecure);
int blit(const void *dst, const void *src, int srcFenceFd);
};

View File

@ -20,8 +20,10 @@
#ifndef __TONEMAPPER_ENGINE_H__
#define __TONEMAPPER_ENGINE_H__
void* engine_initialize();
void* engine_initialize(bool isSecure);
void engine_bind(void*);
void* engine_backup();
void engine_free_backup(void*);
void engine_shutdown(void*);
unsigned int engine_loadProgram(int, const char **, int, const char **);
@ -36,6 +38,7 @@ void engine_set2DInputBuffer(int binding, unsigned int textureID);
void engine_set3DInputBuffer(int binding, unsigned int textureID);
void engine_setExternalInputBuffer(int binding, unsigned int textureID);
void engine_setDestination(int id, int x, int y, int w, int h);
void engine_setData2f(int loc, float* data);
int engine_blit(int);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, The Linux Foundation. All rights reserved.
* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright 2015 The Android Open Source Project
@ -24,22 +24,32 @@ const char* forward_tonemap_shader = ""
"layout(binding = 0) uniform samplerExternalOES externalTexture; \n"
"layout(binding = 1) uniform sampler3D tonemapper; \n"
"layout(binding = 2) uniform sampler2D xform; \n"
"layout(location = 3) uniform vec2 tSO; \n"
"#ifdef USE_NONUNIFORM_SAMPLING \n"
"layout(location = 4) uniform vec2 xSO; \n"
"#endif \n"
"in vec2 uv; \n"
"out vec4 fs_color; \n"
" \n"
"vec3 ScaleOffset(in vec3 samplePt, in vec2 so) \n"
"{ \n"
" vec3 adjPt = so.x * samplePt + so.y; \n"
" return adjPt; \n"
"} \n"
" \n"
"void main() \n"
"{ \n"
"vec2 flipped = uv; \n"
"flipped.y = 1.0 - flipped.y; \n"
"flipped.x = flipped.x; \n"
"vec2 flipped = vec2(uv.x, 1.0f - uv.y); \n"
"vec4 rgb = texture(externalTexture, flipped); \n"
"#ifdef USE_NONUNIFORM_SAMPLING \n"
"float r = texture(xform, vec2(r, 0.0f)).r; \n"
"float g = texture(xform, vec2(g, 0.0f)).g; \n"
"float b = texture(xform, vec2(b, 0.0f)).b; \n"
"vec3 adj = ScaleOffset(rgb.xyz, xSO); \n"
"float r = texture(xform, vec2(adj.r, 0.5f)).r; \n"
"float g = texture(xform, vec2(adj.g, 0.5f)).g; \n"
"float b = texture(xform, vec2(adj.b, 0.5f)).b; \n"
"#else \n"
"float r = rgb.r; \n"
"float g = rgb.g; \n"
"float b = rgb.b; \n"
"#endif \n"
"fs_color.rgb = texture(tonemapper, vec3(r, g, b)).rgb; \n"
"fs_color.rgb = texture(tonemapper, ScaleOffset(vec3(r, g, b), tSO)).rgb; \n"
"} \n";

View File

@ -46,10 +46,31 @@ void engine_bind(void* context)
EGL(eglMakeCurrent(engineContext->eglDisplay, engineContext->eglSurface, engineContext->eglSurface, engineContext->eglContext));
}
//-----------------------------------------------------------------------------
// store the current context(caller)
void* engine_backup()
{
EngineContext* callerContext = new EngineContext();
// store the previous display/context
callerContext->eglDisplay = eglGetCurrentDisplay();
callerContext->eglContext = eglGetCurrentContext();
callerContext->eglSurface = eglGetCurrentSurface(EGL_DRAW);
return (void*)callerContext;
}
//-----------------------------------------------------------------------------
// frees the backed up caller context
void engine_free_backup(void* context)
{
EngineContext* callerContext = (EngineContext*)(context);
delete callerContext;
}
//-----------------------------------------------------------------------------
// initialize GL
//
void* engine_initialize()
void* engine_initialize(bool isSecure)
//-----------------------------------------------------------------------------
{
EngineContext* engineContext = new EngineContext();
@ -73,11 +94,18 @@ void* engine_initialize()
EGL(eglChooseConfig(engineContext->eglDisplay, eglConfigAttribList, &eglConfig, 1, &numConfig));
// context
EGLint eglContextAttribList[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
EGLint eglContextAttribList[] = {EGL_CONTEXT_CLIENT_VERSION, 3,
isSecure ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
isSecure ? EGL_TRUE : EGL_NONE,
EGL_NONE};
engineContext->eglContext = eglCreateContext(engineContext->eglDisplay, eglConfig, NULL, eglContextAttribList);
// surface
EGLint eglSurfaceAttribList[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_NONE};
EGLint eglSurfaceAttribList[] = {EGL_WIDTH, 1,
EGL_HEIGHT, 1,
isSecure ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
isSecure ? EGL_TRUE : EGL_NONE,
EGL_NONE};
engineContext->eglSurface = eglCreatePbufferSurface(engineContext->eglDisplay, eglConfig, eglSurfaceAttribList);
eglMakeCurrent(engineContext->eglDisplay, engineContext->eglSurface, engineContext->eglSurface, engineContext->eglContext);
@ -120,6 +148,13 @@ void engine_deleteProgram(unsigned int id)
}
}
//-----------------------------------------------------------------------------
void engine_setData2f(int location, float* data)
//-----------------------------------------------------------------------------
{
GL(glUniform2f(location, data[0], data[1]));
}
//-----------------------------------------------------------------------------
unsigned int engine_load3DTexture(void *colorMapData, int sz, int format)
//-----------------------------------------------------------------------------

View File

@ -39,7 +39,9 @@
checkEglError(__FILE__, __LINE__);
#endif
#define EGL_PROTECTED_CONTENT_EXT 0x32C0
void checkGlError(const char *file, int line);
void checkEglError(const char *file, int line);
#endif //__TONEMAPPER_GLENGINE_H__
#endif //__TONEMAPPER_GLENGINE_H__

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, The Linux Foundation. All rights reserved.
* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright 2015 The Android Open Source Project
@ -24,27 +24,37 @@ const char* rgba_inverse_tonemap_shader = ""
"layout(binding = 0) uniform samplerExternalOES externalTexture; \n"
"layout(binding = 1) uniform sampler3D tonemapper; \n"
"layout(binding = 2) uniform sampler2D xform; \n"
"layout(location = 3) uniform vec2 tSO; \n"
"#if defined(USE_NONUNIFORM_SAMPLING) \n"
"layout(location = 4) uniform vec2 xSO; \n"
"#endif \n"
"in vec2 uv; \n"
"out vec4 fs_color; \n"
" \n"
"vec3 ScaleOffset(in vec3 samplePt, in vec2 so) \n"
"{ \n"
" vec3 adjPt = so.x * samplePt + so.y; \n"
" return adjPt; \n"
"} \n"
" \n"
"void main() \n"
"{ \n"
"vec2 flipped = uv; \n"
"flipped.y = 1.0 - flipped.y; \n"
"flipped.x = flipped.x; \n"
"vec2 flipped = vec2(uv.x, 1.0f - uv.y); \n"
"vec4 rgb_premulalpha = texture(externalTexture, flipped); \n"
"fs_color = rgb_premulalpha; \n"
"if( rgb_premulalpha.a > 0.0 ) { \n"
"vec3 rgb = rgb_premulalpha.rgb/rgb_premulalpha.a; \n"
"#if defined(USE_NONUNIFORM_SAMPLING) \n"
"float r = texture(xform, vec2(rgb.r, 0.0f)).r; \n"
"float g = texture(xform, vec2(rgb.g, 0.0f)).g; \n"
"float b = texture(xform, vec2(rgb.b, 0.0f)).b; \n"
"vec3 adj = ScaleOffset(rgb.xyz, xSO); \n"
"float r = texture(xform, vec2(adj.r, 0.5f)).r; \n"
"float g = texture(xform, vec2(adj.g, 0.5f)).g; \n"
"float b = texture(xform, vec2(adj.b, 0.5f)).b; \n"
"#else \n"
"float r = rgb.r; \n"
"float g = rgb.g; \n"
"float b = rgb.b; \n"
"#endif \n"
"fs_color.rgb = texture(tonemapper, vec3(r, g, b)).rgb * rgb_premulalpha.a; \n"
"fs_color.rgb = texture(tonemapper, ScaleOffset(vec3(r, g, b), tSO)).rgb * rgb_premulalpha.a; \n"
"fs_color.a = rgb_premulalpha.a; \n"
"} \n"
"} \n";

View File

@ -10,12 +10,14 @@ include $(BUILD_COPY_HEADERS)
include $(CLEAR_VARS)
#TODO move all exported headers to this directory
LOCAL_MODULE := display_headers
LOCAL_MODULE := display_headers
LOCAL_VENDOR_MODULE := true
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH) \
$(display_top)/libcopybit \
$(display_top)/libdrmutils \
$(display_top)/libqdutils \
$(display_top)/libqservice \
$(display_top)/gpu_tonemapper \
$(display_top)/sdm/include
ifeq ($(TARGET_USES_GRALLOC1), true)

View File

@ -474,14 +474,14 @@ int BufferManager::AllocateBuffer(const BufferDescriptor &descriptor, buffer_han
int buffer_type = GetBufferType(gralloc_format);
allocator_->GetBufferSizeAndDimensions(descriptor, &size, &alignedw, &alignedh);
size = (bufferSize >= size) ? bufferSize : size;
size = size * layer_count;
int err = 0;
int flags = 0;
auto page_size = UINT(getpagesize());
AllocData data;
data.align = GetDataAlignment(format, prod_usage, cons_usage);
data.size = ALIGN(size, data.align);
size = ALIGN(size, data.align) * layer_count;
data.size = size;
data.handle = (uintptr_t) handle;
data.uncached = allocator_->UseUncached(prod_usage, cons_usage);

View File

@ -8,6 +8,7 @@ LOCAL_MODULE_TAGS := optional
LOCAL_SHARED_LIBRARIES := $(common_libs) libbinder libqservice
LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes)
LOCAL_HEADER_LIBRARIES := display_headers
LOCAL_HEADER_LIBRARIES += libhardware_headers
LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdutils\" -Wno-sign-conversion
LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
LOCAL_COPY_HEADERS_TO := $(common_header_export_path)
@ -15,7 +16,6 @@ LOCAL_COPY_HEADERS := display_config.h qd_utils.h
LOCAL_SRC_FILES := profiler.cpp \
qd_utils.cpp \
display_config.cpp
LOCAL_HEADER_LIBRARIES += libhardware_headers
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
@ -33,6 +33,5 @@ LOCAL_CFLAGS += -DLOG_TAG=\"DisplayMetaData\"
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := libqdMetaData
LOCAL_VENDOR_MODULE := true
LOCAL_HEADER_LIBRARIES += libhardware_headers
include $(BUILD_SHARED_LIBRARY)

View File

@ -54,6 +54,7 @@ struct BufferConfig {
bool cache = false; //!< Specifies whether the buffer needs to be cache.
bool secure_camera = false; //!< Specifies buffer to be allocated from specific
//!< secure heap and with a specific alignment.
bool gfx_client = false; //!< Specifies whether buffer is used by gfx.
};
/*! @brief Holds the information about the allocated buffer.

View File

@ -55,6 +55,7 @@ enum DisplayError {
kErrorShutDown, //!< Driver is processing shutdown sequence
kErrorPerfValidation, //!< Bandwidth or Clock requirement validation failure.
kErrorNoAppLayers, //!< No App layer(s) in the draw cycle.
kErrorNotValidated, //!< Draw cycle has not been validated.
};
/*! @brief This structure is defined for client and library compatibility check purpose only. This

View File

@ -75,6 +75,7 @@ namespace sdm {
const int kPageSize = 4096;
const uint32_t kGridSize = 129; // size used for non-linear transformation before Tone-mapping
const uint32_t kLutDim = 17; // Dim of the 3d LUT for tone-mapping.
const int kMaxThermalLevel = 3;
typedef void * Handle;

View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 2017, 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 __FACTORY_H__
#define __FACTORY_H__
#include <utility>
#include <map>
#include <string>
namespace sdm {
template <class Creator>
class Factory {
public:
int Add(const std::string &name, const Creator &creator) {
map_.insert(std::pair<std::string, Creator>(name, creator));
return 0;
}
Creator Get(const std::string &name) {
typename std::map<std::string, Creator>::iterator it = map_.find(name);
if (it != map_.end()) {
return it->second;
}
return nullptr;
}
private:
std::map<std::string, Creator> map_;
};
} // namespace sdm
#endif // __FACTORY_H__

View File

@ -0,0 +1,143 @@
/*
* Copyright (c) 2017, 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 __SYNC_TASK_H__
#define __SYNC_TASK_H__
#include <thread>
#include <mutex>
#include <condition_variable> // NOLINT
namespace sdm {
template <class TaskCode>
class SyncTask {
public:
// This class need to be overridden by caller to pass on a task context.
class TaskContext {
public:
virtual ~TaskContext() { }
};
// Methods to callback into caller for command codes executions in worker thread.
class TaskHandler {
public:
virtual ~TaskHandler() { }
virtual void OnTask(const TaskCode &task_code, TaskContext *task_context) = 0;
};
explicit SyncTask(TaskHandler &task_handler) : task_handler_(task_handler) {
// Block caller thread until worker thread has started and ready to listen to task commands.
// Worker thread will signal as soon as callback is received in the new thread.
std::unique_lock<std::mutex> caller_lock(caller_mutex_);
std::thread worker_thread(SyncTaskThread, this);
worker_thread_.swap(worker_thread);
caller_cv_.wait(caller_lock);
}
~SyncTask() {
// Task code does not matter here.
PerformTask(task_code_, nullptr, true);
worker_thread_.join();
}
void PerformTask(const TaskCode &task_code, TaskContext *task_context) {
PerformTask(task_code, task_context, false);
}
private:
void PerformTask(const TaskCode &task_code, TaskContext *task_context, bool terminate) {
std::unique_lock<std::mutex> caller_lock(caller_mutex_);
// New scope to limit scope of worker lock to this block.
{
// Set task command code and notify worker thread.
std::unique_lock<std::mutex> worker_lock(worker_mutex_);
task_code_ = task_code;
task_context_ = task_context;
worker_thread_exit_ = terminate;
pending_code_ = true;
worker_cv_.notify_one();
}
// Wait for worker thread to finish and signal.
caller_cv_.wait(caller_lock);
}
static void SyncTaskThread(SyncTask *sync_task) {
if (sync_task) {
sync_task->OnThreadCallback();
}
}
void OnThreadCallback() {
// Acquire worker lock and start waiting for events.
// Wait must start before caller thread can post events, otherwise posted events will be lost.
// Caller thread will be blocked until worker thread signals readiness.
std::unique_lock<std::mutex> worker_lock(worker_mutex_);
// New scope to limit scope of caller lock to this block.
{
// Signal caller thread that worker thread is ready to listen to events.
std::unique_lock<std::mutex> caller_lock(caller_mutex_);
caller_cv_.notify_one();
}
while (!worker_thread_exit_) {
// Add predicate to handle spurious interrupts.
// Wait for caller thread to signal new command codes.
worker_cv_.wait(worker_lock, [this] { return pending_code_; });
// Call task handler which is implemented by the caller.
if (!worker_thread_exit_) {
task_handler_.OnTask(task_code_, task_context_);
}
pending_code_ = false;
// Notify completion of current task to the caller thread which is blocked.
std::unique_lock<std::mutex> caller_lock(caller_mutex_);
caller_cv_.notify_one();
}
}
TaskHandler &task_handler_;
TaskCode task_code_;
TaskContext *task_context_ = nullptr;
std::thread worker_thread_;
std::mutex caller_mutex_;
std::mutex worker_mutex_;
std::condition_variable caller_cv_;
std::condition_variable worker_cv_;
bool worker_thread_exit_ = false;
bool pending_code_ = false;
};
} // namespace sdm
#endif // __SYNC_TASK_H__

View File

@ -80,7 +80,6 @@ class CompManager : public DumpImpl {
virtual void AppendDump(char *buffer, uint32_t length);
private:
static const int kMaxThermalLevel = 3;
static const int kSafeModeThreshold = 4;
void PrepareStrategyConstraints(Handle display_ctx, HWLayers *hw_layers);

View File

@ -38,6 +38,8 @@
namespace sdm {
std::bitset<kDisplayMax> DisplayBase::needs_validate_ = 0;
// 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, BufferSyncHandler *buffer_sync_handler,
@ -88,6 +90,10 @@ DisplayError DisplayBase::Init() {
goto CleanupOnError;
}
if (!IsPrimaryDisplay()) {
needs_validate_.set();
}
if (hw_info_intf_) {
HWResourceInfo hw_resource_info = HWResourceInfo();
hw_info_intf_->GetHWResourceInfo(&hw_resource_info);
@ -250,7 +256,7 @@ DisplayError DisplayBase::Prepare(LayerStack *layer_stack) {
error = hw_intf_->Validate(&hw_layers_);
if (error == kErrorNone) {
// Strategy is successful now, wait for Commit().
pending_commit_ = true;
needs_validate_.reset(display_type_);
break;
}
if (error == kErrorShutDown) {
@ -269,7 +275,7 @@ DisplayError DisplayBase::Commit(LayerStack *layer_stack) {
DisplayError error = kErrorNone;
if (!active_) {
pending_commit_ = false;
needs_validate_.set(display_type_);
return kErrorPermission;
}
@ -277,13 +283,11 @@ DisplayError DisplayBase::Commit(LayerStack *layer_stack) {
return kErrorParameters;
}
if (!pending_commit_) {
if (needs_validate_.test(display_type_)) {
DLOGE("Commit: Corresponding Prepare() is not called for display = %d", display_type_);
return kErrorUndefined;
return kErrorNotValidated;
}
pending_commit_ = false;
// Layer stack attributes has changed, need to Reconfigure, currently in use for Hybrid Comp
if (layer_stack->flags.attributes_changed) {
error = comp_manager_->ReConfigure(display_comp_ctx_, &hw_layers_);
@ -343,11 +347,11 @@ DisplayError DisplayBase::Flush() {
error = hw_intf_->Flush();
if (error == kErrorNone) {
comp_manager_->Purge(display_comp_ctx_);
pending_commit_ = false;
} else {
DLOGW("Unable to flush display = %d", display_type_);
}
needs_validate_.set(display_type_);
return error;
}
@ -421,6 +425,8 @@ DisplayError DisplayBase::SetDisplayState(DisplayState state) {
return kErrorNone;
}
needs_validate_.set(display_type_);
switch (state) {
case kStateOff:
hw_layers_.info.hw_layers.clear();

View File

@ -138,6 +138,7 @@ class DisplayBase : public DisplayInterface, DumpImpl {
DisplayError GetHdrColorMode(std::string *color_mode, bool *found_hdr);
bool IsSupportColorModeAttribute(const std::string &color_mode);
static std::bitset<kDisplayMax> needs_validate_;
recursive_mutex recursive_mutex_;
DisplayType display_type_;
DisplayEventHandler *event_handler_ = NULL;
@ -151,7 +152,6 @@ class DisplayBase : public DisplayInterface, DumpImpl {
Handle hw_device_ = 0;
Handle display_comp_ctx_ = 0;
HWLayers hw_layers_;
bool pending_commit_ = false;
bool vsync_enable_ = false;
uint32_t max_mixer_stages_ = 0;
HWInfoInterface *hw_info_intf_ = NULL;

View File

@ -294,6 +294,7 @@ DisplayError DisplayPrimary::VSync(int64_t timestamp) {
void DisplayPrimary::IdleTimeout() {
event_handler_->Refresh();
comp_manager_->ProcessIdleTimeout(display_comp_ctx_);
needs_validate_.set();
}
void DisplayPrimary::PingPongTimeout() {
@ -304,6 +305,9 @@ void DisplayPrimary::PingPongTimeout() {
void DisplayPrimary::ThermalEvent(int64_t thermal_level) {
lock_guard<recursive_mutex> obj(recursive_mutex_);
comp_manager_->ProcessThermalEvent(display_comp_ctx_, thermal_level);
if (thermal_level >= kMaxThermalLevel) {
needs_validate_.set();
}
}
void DisplayPrimary::IdlePowerCollapse() {

View File

@ -303,7 +303,8 @@ DisplayError HWCToneMapper::AcquireToneMapSession(Layer *layer, uint32_t *sessio
session->gpu_tone_mapper_ = TonemapperFactory_GetInstance(session->tone_map_config_.type,
layer->lut_3d.lutEntries,
layer->lut_3d.dim,
grid_entries, grid_size);
grid_entries, grid_size,
session->tone_map_config_.secure);
if (session->gpu_tone_mapper_ == NULL) {
DLOGE("Get Tonemapper failed!");

View File

@ -19,7 +19,7 @@ LOCAL_CLANG := true
LOCAL_SHARED_LIBRARIES := libsdmcore libqservice libbinder libhardware libhardware_legacy \
libutils libcutils libsync libqdutils libqdMetaData libdl \
libsdmutils libc++ liblog libdrmutils
libsdmutils libc++ liblog libdrmutils libui libgpu_tonemapper
ifneq ($(TARGET_USES_GRALLOC1), true)
LOCAL_SHARED_LIBRARIES += libmemalloc
@ -36,7 +36,8 @@ LOCAL_SRC_FILES := hwc_session.cpp \
hwc_layers.cpp \
hwc_callbacks.cpp \
../hwc/cpuhint.cpp \
../hwc/hwc_socket_handler.cpp
../hwc/hwc_socket_handler.cpp \
hwc_tonemapper.cpp
ifneq ($(TARGET_USES_GRALLOC1), true)
LOCAL_SRC_FILES += ../hwc/hwc_buffer_allocator.cpp

View File

@ -78,8 +78,14 @@ DisplayError HWCBufferAllocator::AllocateBuffer(BufferInfo *buffer_info) {
// Allocate uncached buffers
alloc_flags |= GRALLOC_USAGE_PRIVATE_UNCACHED;
}
if (buffer_config.gfx_client) {
alloc_flags |= GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE;
}
uint64_t producer_usage = UINT64(alloc_flags);
uint64_t consumer_usage = UINT64(alloc_flags);
// CreateBuffer
private_handle_t *hnd = nullptr;
Perform_(gralloc_device_, GRALLOC1_MODULE_PERFORM_ALLOCATE_BUFFER, width, height, format,

View File

@ -40,6 +40,8 @@
#include "hwc_display.h"
#include "hwc_debugger.h"
#include "blit_engine_c2d.h"
#include "hwc_tonemapper.h"
#ifndef USE_GRALLOC1
#include <gr.h>
#endif
@ -160,7 +162,7 @@ HWC2::Error HWCColorMode::HandleColorModeTransform(android_color_mode_t mode,
// if the mode count is 1, then only native mode is supported, so just apply matrix w/o
// setting mode
if (color_mode_transform_map_.size() > 1U) {
if (color_mode_transform_map_.size() > 1U && current_color_mode_ != mode) {
color_mode_transform = color_mode_transform_map_[mode][transform_hint];
DisplayError error = display_intf_->SetColorMode(color_mode_transform);
if (error != kErrorNone) {
@ -168,6 +170,7 @@ HWC2::Error HWCColorMode::HandleColorModeTransform(android_color_mode_t mode,
// failure to force client composition
return HWC2::Error::Unsupported;
}
DLOGI("Setting Color Mode = %d Transform Hint = %d Success", mode, hint);
}
if (use_matrix) {
@ -182,7 +185,6 @@ HWC2::Error HWCColorMode::HandleColorModeTransform(android_color_mode_t mode,
current_color_mode_ = mode;
current_color_transform_ = hint;
CopyColorTransformMatrix(matrix, color_matrix_);
DLOGI("Setting Color Mode = %d Transform Hint = %d Success", mode, hint);
return HWC2::Error::None;
}
@ -346,6 +348,11 @@ int HWCDisplay::Init() {
return -EINVAL;
}
HWCDebugHandler::Get()->GetProperty("sys.hwc_disable_hdr", &disable_hdr_handling_);
if (disable_hdr_handling_) {
DLOGI("HDR Handling disabled");
}
int property_swap_interval = 1;
HWCDebugHandler::Get()->GetProperty("debug.egl.swapinterval", &property_swap_interval);
if (property_swap_interval == 0) {
@ -360,8 +367,12 @@ int HWCDisplay::Init() {
// TODO(user): Add blit engine when needed
}
tone_mapper_ = new HWCToneMapper(buffer_allocator_);
display_intf_->GetRefreshRateRange(&min_refresh_rate_, &max_refresh_rate_);
current_refresh_rate_ = max_refresh_rate_;
GetUnderScanConfig();
DLOGI("Display created with id: %d", id_);
return 0;
}
@ -380,6 +391,9 @@ int HWCDisplay::Deinit() {
delete color_mode_;
}
delete tone_mapper_;
tone_mapper_ = nullptr;
return 0;
}
@ -389,6 +403,7 @@ HWC2::Error HWCDisplay::CreateLayer(hwc2_layer_t *out_layer_id) {
layer_map_.emplace(std::make_pair(layer->GetId(), layer));
*out_layer_id = layer->GetId();
geometry_changes_ |= GeometryChanges::kAdded;
validated_ = false;
return HWC2::Error::None;
}
@ -420,6 +435,7 @@ HWC2::Error HWCDisplay::DestroyLayer(hwc2_layer_t layer_id) {
}
geometry_changes_ |= GeometryChanges::kRemoved;
validated_ = false;
return HWC2::Error::None;
}
@ -493,6 +509,15 @@ void HWCDisplay::BuildLayerStack() {
}
}
bool hdr_layer = layer->input_buffer.color_metadata.colorPrimaries == ColorPrimaries_BT2020 &&
(layer->input_buffer.color_metadata.transfer == Transfer_SMPTE_ST2084 ||
layer->input_buffer.color_metadata.transfer == Transfer_HLG);
if (hdr_layer && !disable_hdr_handling_) {
// dont honor HDR when its handling is disabled
layer->input_buffer.flags.hdr = true;
layer_stack_.flags.hdr_present = true;
}
// TODO(user): Move to a getter if this is needed at other places
hwc_rect_t scaled_display_frame = {INT(layer->dst_rect.left), INT(layer->dst_rect.top),
INT(layer->dst_rect.right), INT(layer->dst_rect.bottom)};
@ -636,6 +661,9 @@ HWC2::Error HWCDisplay::SetPowerMode(HWC2::PowerMode mode) {
// Do not flush until a buffer is successfully submitted again.
flush_on_error = false;
state = kStateOff;
if (tone_mapper_) {
tone_mapper_->Terminate();
}
break;
case HWC2::PowerMode::On:
state = kStateOn;
@ -806,7 +834,7 @@ HWC2::Error HWCDisplay::SetClientTarget(buffer_handle_t target, int32_t acquire_
client_target_->SetLayerBuffer(target, acquire_fence);
client_target_->SetLayerSurfaceDamage(damage);
// Ignoring dataspace for now
client_target_->SetLayerDataspace(dataspace);
return HWC2::Error::None;
}
@ -827,6 +855,10 @@ void HWCDisplay::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type
dump_frame_index_ = 0;
dump_input_layers_ = ((bit_mask_layer_type & (1 << INPUT_LAYER_DUMP)) != 0);
if (tone_mapper_) {
tone_mapper_->SetFrameDumpConfig(count);
}
DLOGI("num_frame_dump %d, input_layer_dump_enable %d", dump_frame_count_, dump_input_layers_);
}
@ -900,10 +932,12 @@ HWC2::Error HWCDisplay::PrepareLayerStack(uint32_t *out_num_types, uint32_t *out
if (requested_composition != device_composition) {
layer_changes_[hwc_layer->GetId()] = device_composition;
}
hwc_layer->ResetValidation();
}
*out_num_types = UINT32(layer_changes_.size());
*out_num_requests = UINT32(layer_requests_.size());
validated_ = true;
skip_validate_ = false;
if (*out_num_types > 0) {
return HWC2::Error::HasChanges;
} else {
@ -1032,7 +1066,13 @@ HWC2::Error HWCDisplay::CommitLayerStack(void) {
}
if (!validated_) {
DLOGW("Display is not validated");
DLOGV_IF(kTagCompManager, "Display %d is not validated", id_);
return HWC2::Error::NotValidated;
}
if (skip_validate_ && !CanSkipValidate()) {
DLOGV_IF(kTagCompManager, "Cannot skip validate on display: %d", id_);
validated_ = false;
return HWC2::Error::NotValidated;
}
@ -1040,8 +1080,18 @@ HWC2::Error HWCDisplay::CommitLayerStack(void) {
if (!flush_) {
DisplayError error = kErrorUndefined;
int status = 0;
if (tone_mapper_) {
if (layer_stack_.flags.hdr_present) {
status = tone_mapper_->HandleToneMap(&layer_stack_);
if (status != 0) {
DLOGE("Error handling HDR in ToneMapper");
}
} else {
tone_mapper_->Terminate();
}
}
error = display_intf_->Commit(&layer_stack_);
validated_ = false;
if (error == kErrorNone) {
// A commit is successfully submitted, start flushing on failure now onwards.
@ -1050,6 +1100,9 @@ HWC2::Error HWCDisplay::CommitLayerStack(void) {
if (error == kErrorShutDown) {
shutdown_pending_ = true;
return HWC2::Error::Unsupported;
} else if (error == kErrorNotValidated) {
validated_ = false;
return HWC2::Error::NotValidated;
} else if (error != kErrorPermission) {
DLOGE("Commit failed. Error = %d", error);
// To prevent surfaceflinger infinite wait, flush the previous frame during Commit()
@ -1059,6 +1112,7 @@ HWC2::Error HWCDisplay::CommitLayerStack(void) {
}
}
skip_validate_ = true;
return HWC2::Error::None;
}
@ -1070,6 +1124,10 @@ HWC2::Error HWCDisplay::PostCommitLayerStack(int32_t *out_retire_fence) {
display_intf_->Flush();
}
if (tone_mapper_ && tone_mapper_->IsActive()) {
tone_mapper_->PostCommit(&layer_stack_);
}
// TODO(user): No way to set the client target release fence on SF
int32_t &client_target_release_fence =
client_target_->GetSDMLayer()->input_buffer.release_fence_fd;
@ -1111,6 +1169,7 @@ HWC2::Error HWCDisplay::PostCommitLayerStack(int32_t *out_retire_fence) {
layer_stack_.retire_fence_fd = -1;
}
*out_retire_fence = layer_stack_.retire_fence_fd;
layer_stack_.retire_fence_fd = -1;
if (dump_frame_count_) {
dump_frame_count_--;
@ -1121,6 +1180,8 @@ HWC2::Error HWCDisplay::PostCommitLayerStack(int32_t *out_retire_fence) {
geometry_changes_ = GeometryChanges::kNone;
flush_ = false;
ClearRequestFlags();
return status;
}
@ -1745,6 +1806,12 @@ void HWCDisplay::CloseAcquireFds() {
}
}
void HWCDisplay::ClearRequestFlags() {
for (Layer *layer : layer_stack_.layers) {
layer->request.flags = {};
}
}
std::string HWCDisplay::Dump() {
std::ostringstream os;
os << "-------------------------------" << std::endl;
@ -1773,4 +1840,25 @@ std::string HWCDisplay::Dump() {
os << "-------------------------------" << std::endl;
return os.str();
}
bool HWCDisplay::CanSkipValidate() {
// Layer Stack checks
if (layer_stack_.flags.hdr_present && (tone_mapper_ && tone_mapper_->IsActive())) {
return false;
}
for (auto hwc_layer : layer_set_) {
if (hwc_layer->NeedsValidation()) {
return false;
}
// Do not allow Skip Validate, if any layer needs GPU Composition.
if (hwc_layer->GetDeviceSelectedCompositionType() == HWC2::Composition::Client) {
return false;
}
}
return true;
}
} // namespace sdm

View File

@ -39,6 +39,7 @@
namespace sdm {
class BlitEngine;
class HWCToneMapper;
// Subclasses set this to their type. This has to be different from DisplayType.
// This is to avoid RTTI and dynamic_cast
@ -197,6 +198,10 @@ class HWCDisplay : public DisplayEventHandler {
float* out_max_average_luminance,
float* out_min_luminance);
bool validated_ = false;
bool skip_validate_ = false;
uint32_t geometry_changes_ = GeometryChanges::kNone;
protected:
enum DisplayStatus {
kDisplayStatusOffline = 0,
@ -233,6 +238,8 @@ class HWCDisplay : public DisplayEventHandler {
bool IsLayerUpdating(const Layer *layer);
uint32_t SanitizeRefreshRate(uint32_t req_refresh_rate);
virtual void CloseAcquireFds();
virtual void ClearRequestFlags();
virtual void GetUnderScanConfig() { }
enum {
INPUT_LAYER_DUMP,
@ -276,15 +283,16 @@ class HWCDisplay : public DisplayEventHandler {
LayerRect solid_fill_rect_ = {};
uint32_t solid_fill_color_ = 0;
LayerRect display_rect_;
bool validated_ = false;
bool color_tranform_failed_ = false;
HWCColorMode *color_mode_ = NULL;
HWCToneMapper *tone_mapper_ = nullptr;
int disable_hdr_handling_ = 0; // disables HDR handling.
private:
void DumpInputBuffers(void);
bool CanSkipValidate();
qService::QService *qservice_ = NULL;
DisplayClass display_class_;
uint32_t geometry_changes_ = GeometryChanges::kNone;
};
inline int HWCDisplay::Perform(uint32_t operation, ...) {

View File

@ -139,20 +139,12 @@ HWC2::Error HWCDisplayExternal::Present(int32_t *out_retire_fence) {
}
void HWCDisplayExternal::ApplyScanAdjustment(hwc_rect_t *display_frame) {
if (display_intf_->IsUnderscanSupported()) {
if ((underscan_width_ <= 0) || (underscan_height_ <= 0)) {
return;
}
// Read user defined width and height ratio
int width = 0, height = 0;
HWCDebugHandler::Get()->GetProperty("sdm.external_action_safe_width", &width);
float width_ratio = FLOAT(width) / 100.0f;
HWCDebugHandler::Get()->GetProperty("sdm.external_action_safe_height", &height);
float height_ratio = FLOAT(height) / 100.0f;
if (width_ratio == 0.0f || height_ratio == 0.0f) {
return;
}
float width_ratio = FLOAT(underscan_width_) / 100.0f;
float height_ratio = FLOAT(underscan_height_) / 100.0f;
uint32_t mixer_width = 0;
uint32_t mixer_height = 0;
@ -213,4 +205,12 @@ void HWCDisplayExternal::GetDownscaleResolution(uint32_t primary_width, uint32_t
}
}
void HWCDisplayExternal::GetUnderScanConfig() {
if (!display_intf_->IsUnderscanSupported()) {
// Read user defined underscan width and height
HWCDebugHandler::Get()->GetProperty("sdm.external_action_safe_width", &underscan_width_);
HWCDebugHandler::Get()->GetProperty("sdm.external_action_safe_height", &underscan_height_);
}
}
} // namespace sdm

View File

@ -54,6 +54,9 @@ class HWCDisplayExternal : public HWCDisplay {
void ApplyScanAdjustment(hwc_rect_t *display_frame);
static void GetDownscaleResolution(uint32_t primary_width, uint32_t primary_height,
uint32_t *virtual_width, uint32_t *virtual_height);
void GetUnderScanConfig();
int underscan_width_ = 0;
int underscan_height_ = 0;
};
} // namespace sdm

View File

@ -244,6 +244,7 @@ HWC2::Error HWCDisplayPrimary::GetColorModes(uint32_t *out_num_modes,
}
HWC2::Error HWCDisplayPrimary::SetColorMode(android_color_mode_t mode) {
validated_ = false;
auto status = color_mode_->SetColorMode(mode);
if (status != HWC2::Error::None) {
DLOGE("failed for mode = %d", mode);
@ -269,6 +270,7 @@ HWC2::Error HWCDisplayPrimary::SetColorModeById(int32_t color_mode_id) {
HWC2::Error HWCDisplayPrimary::SetColorTransform(const float *matrix,
android_color_transform_t hint) {
validated_ = false;
if (!matrix) {
return HWC2::Error::BadParameter;
}
@ -406,6 +408,7 @@ DisplayError HWCDisplayPrimary::Refresh() {
callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
handle_idle_timeout_ = true;
validated_ = false;
return error;
}
@ -581,6 +584,7 @@ DisplayError HWCDisplayPrimary::DisablePartialUpdateOneFrame() {
DisplayError HWCDisplayPrimary::SetMixerResolution(uint32_t width, uint32_t height) {
validated_ = false;
return display_intf_->SetMixerResolution(width, height);
}

View File

@ -91,8 +91,13 @@ HWCLayer::~HWCLayer() {
HWC2::Error HWCLayer::SetLayerBuffer(buffer_handle_t buffer, int32_t acquire_fence) {
if (!buffer) {
DLOGE("Invalid buffer handle: %p on layer: %d", buffer, id_);
return HWC2::Error::BadParameter;
if (client_requested_ == HWC2::Composition::Device ||
client_requested_ == HWC2::Composition::Cursor) {
DLOGE("Invalid buffer handle: %p on layer: %d", buffer, id_);
return HWC2::Error::BadParameter;
} else {
return HWC2::Error::None;
}
}
if (acquire_fence == 0) {
@ -119,35 +124,39 @@ HWC2::Error HWCLayer::SetLayerBuffer(buffer_handle_t buffer, int32_t acquire_fen
AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(handle, aligned_width, aligned_height);
#endif
LayerBufferFormat format = GetSDMFormat(handle->format, handle->flags);
if ((format != layer_buffer->format) || (UINT32(aligned_width) != layer_buffer->width) ||
(UINT32(aligned_height) != layer_buffer->height)) {
// Layer buffer geometry has changed.
geometry_changes_ |= kBufferGeometry;
}
layer_buffer->format = format;
layer_buffer->width = UINT32(aligned_width);
layer_buffer->height = UINT32(aligned_height);
layer_buffer->unaligned_width = UINT32(handle->unaligned_width);
layer_buffer->unaligned_height = UINT32(handle->unaligned_height);
layer_buffer->format = GetSDMFormat(handle->format, handle->flags);
if (SetMetaData(const_cast<private_handle_t *>(handle), layer_) != kErrorNone) {
return HWC2::Error::BadLayer;
}
#ifdef USE_GRALLOC1
// TODO(user): Clean this up
if (handle->buffer_type == BUFFER_TYPE_VIDEO) {
#else
if (handle->bufferType == BUFFER_TYPE_VIDEO) {
#endif
layer_buffer->flags.video = true;
}
layer_buffer->flags.video = (handle->buffer_type == BUFFER_TYPE_VIDEO) ? true : false;
// TZ Protected Buffer - L1
if (handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
layer_buffer->flags.secure = true;
if (handle->flags & private_handle_t::PRIV_FLAGS_CAMERA_WRITE) {
layer_buffer->flags.secure_camera = true;
}
}
if (handle->flags & private_handle_t::PRIV_FLAGS_SECURE_DISPLAY) {
layer_buffer->flags.secure_display = true;
bool secure = (handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER);
bool secure_camera = secure && (handle->flags & private_handle_t::PRIV_FLAGS_CAMERA_WRITE);
bool secure_display = (handle->flags & private_handle_t::PRIV_FLAGS_SECURE_DISPLAY);
if (secure != layer_buffer->flags.secure || secure_camera != layer_buffer->flags.secure_camera ||
secure_display != layer_buffer->flags.secure_display) {
// Secure attribute of layer buffer has changed.
needs_validate_ = true;
}
layer_buffer->flags.secure = secure;
layer_buffer->flags.secure_camera = secure_camera;
layer_buffer->flags.secure_display = secure_display;
layer_buffer->planes[0].fd = ion_fd_;
layer_buffer->planes[0].offset = handle->offset;
layer_buffer->planes[0].stride = UINT32(handle->width);
@ -160,6 +169,20 @@ HWC2::Error HWCLayer::SetLayerBuffer(buffer_handle_t buffer, int32_t acquire_fen
}
HWC2::Error HWCLayer::SetLayerSurfaceDamage(hwc_region_t damage) {
// Check if there is an update in SurfaceDamage rects
if (layer_->dirty_regions.size() != damage.numRects) {
needs_validate_ = true;
} else {
for (uint32_t j = 0; j < damage.numRects; j++) {
LayerRect damage_rect;
SetRect(damage.rects[j], &damage_rect);
if (damage_rect != layer_->dirty_regions.at(j)) {
needs_validate_ = true;
break;
}
}
}
layer_->dirty_regions.clear();
for (uint32_t i = 0; i < damage.numRects; i++) {
LayerRect rect;
@ -516,9 +539,14 @@ LayerBufferS3DFormat HWCLayer::GetS3DFormat(uint32_t s3d_format) {
DisplayError HWCLayer::SetMetaData(const private_handle_t *pvt_handle, Layer *layer) {
LayerBuffer *layer_buffer = &layer->input_buffer;
bool use_color_metadata = true;
#ifdef FEATURE_WIDE_COLOR
// Only use color metadata if Android framework metadata is not set
if (dataspace_ == HAL_DATASPACE_UNKNOWN) {
use_color_metadata = (dataspace_ == HAL_DATASPACE_UNKNOWN);
#endif
if (use_color_metadata) {
if (sdm::SetCSC(pvt_handle, &layer_buffer->color_metadata) != kErrorNone) {
return kErrorNotSupported;
}
@ -526,20 +554,23 @@ DisplayError HWCLayer::SetMetaData(const private_handle_t *pvt_handle, Layer *la
private_handle_t *handle = const_cast<private_handle_t *>(pvt_handle);
IGC_t igc = {};
LayerIGC layer_igc = layer_buffer->igc;
if (getMetaData(handle, GET_IGC, &igc) == 0) {
if (SetIGC(igc, &layer_buffer->igc) != kErrorNone) {
if (SetIGC(igc, &layer_igc) != kErrorNone) {
return kErrorNotSupported;
}
}
uint32_t fps = 0;
if (getMetaData(handle, GET_REFRESH_RATE , &fps) == 0) {
layer->frame_rate = RoundToStandardFPS(fps);
uint32_t frame_rate = layer->frame_rate;
if (getMetaData(handle, GET_REFRESH_RATE, &fps) == 0) {
frame_rate = RoundToStandardFPS(fps);
}
int32_t interlaced = 0;
bool interlace = layer_buffer->flags.interlace;
if (getMetaData(handle, GET_PP_PARAM_INTERLACED, &interlaced) == 0) {
layer_buffer->flags.interlace = interlaced ? true : false;
interlace = interlaced ? true : false;
}
uint32_t linear_format = 0;
@ -548,8 +579,19 @@ DisplayError HWCLayer::SetMetaData(const private_handle_t *pvt_handle, Layer *la
}
uint32_t s3d = 0;
LayerBufferS3DFormat s3d_format = layer_buffer->s3d_format;
if (getMetaData(handle, GET_S3D_FORMAT, &s3d) == 0) {
layer_buffer->s3d_format = GetS3DFormat(s3d);
s3d_format = GetS3DFormat(s3d);
}
if ((layer_igc != layer_buffer->igc) || (interlace != layer_buffer->flags.interlace) ||
(frame_rate != layer->frame_rate) || (s3d_format != layer_buffer->s3d_format)) {
// Layer buffer metadata has changed.
needs_validate_ = true;
layer_buffer->igc = layer_igc;
layer->frame_rate = frame_rate;
layer_buffer->s3d_format = s3d_format;
layer_buffer->flags.interlace = interlace;
}
return kErrorNone;

View File

@ -52,6 +52,7 @@ enum GeometryChanges {
kZOrder = 0x040,
kAdded = 0x080,
kRemoved = 0x100,
kBufferGeometry = 0x200,
};
class HWCLayer {
@ -85,6 +86,8 @@ class HWCLayer {
int32_t PopReleaseFence(void);
bool SupportedDataspace();
bool SupportLocalConversion(ColorPrimaries working_primaries);
void ResetValidation() { needs_validate_ = false; }
bool NeedsValidation() { return (needs_validate_ || geometry_changes_); }
private:
Layer *layer_ = nullptr;
@ -96,6 +99,7 @@ class HWCLayer {
int ion_fd_ = -1;
HWCBufferAllocator *buffer_allocator_ = NULL;
int32_t dataspace_ = HAL_DATASPACE_UNKNOWN;
bool needs_validate_ = true;
// Composition requested by client(SF)
HWC2::Composition client_requested_ = HWC2::Composition::Device;

View File

@ -217,10 +217,11 @@ int HWCSession::Close(hw_device_t *device) {
void HWCSession::GetCapabilities(struct hwc2_device *device, uint32_t *outCount,
int32_t *outCapabilities) {
if (outCapabilities != nullptr && *outCount >= 1) {
if (outCapabilities != nullptr && *outCount >= 2) {
outCapabilities[0] = HWC2_CAPABILITY_SKIP_CLIENT_COLOR_TRANSFORM;
outCapabilities[1] = HWC2_CAPABILITY_SKIP_VALIDATE;
}
*outCount = 1;
*outCount = 2;
}
template <typename PFN, typename T>

View File

@ -76,6 +76,9 @@ class HWCSession : hwc2_device_t, public qClient::BnQClient {
auto hwc_layer = hwc_session->hwc_display_[display]->GetHWCLayer(layer);
if (hwc_layer != nullptr) {
status = (hwc_layer->*member)(std::forward<Args>(args)...);
if (hwc_session->hwc_display_[display]->geometry_changes_) {
hwc_session->hwc_display_[display]->validated_ = false;
}
}
}
return INT32(status);

View File

@ -0,0 +1,369 @@
/*
* Copyright (c) 2016 - 2017, 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 <sync/sync.h>
#include <TonemapFactory.h>
#include <core/buffer_allocator.h>
#include <utils/constants.h>
#include <utils/debug.h>
#include <utils/formats.h>
#include <utils/rect.h>
#include <utils/utils.h>
#include <vector>
#include "hwc_debugger.h"
#include "hwc_tonemapper.h"
#define __CLASS__ "HWCToneMapper"
namespace sdm {
ToneMapSession::ToneMapSession(HWCBufferAllocator *buffer_allocator)
: tone_map_task_(*this), buffer_allocator_(buffer_allocator) {
buffer_info_.resize(kNumIntermediateBuffers);
}
ToneMapSession::~ToneMapSession() {
tone_map_task_.PerformTask(ToneMapTaskCode::kCodeDestroy, nullptr);
FreeIntermediateBuffers();
buffer_info_.clear();
}
void ToneMapSession::OnTask(const ToneMapTaskCode &task_code,
SyncTask<ToneMapTaskCode>::TaskContext *task_context) {
switch (task_code) {
case ToneMapTaskCode::kCodeGetInstance: {
ToneMapGetInstanceContext *ctx = static_cast<ToneMapGetInstanceContext *>(task_context);
Lut3d &lut_3d = ctx->layer->lut_3d;
Color10Bit *grid_entries = NULL;
int grid_size = 0;
if (lut_3d.validGridEntries) {
grid_entries = lut_3d.gridEntries;
grid_size = INT(lut_3d.gridSize);
}
gpu_tone_mapper_ = TonemapperFactory_GetInstance(tone_map_config_.type,
lut_3d.lutEntries, lut_3d.dim,
grid_entries, grid_size,
tone_map_config_.secure);
}
break;
case ToneMapTaskCode::kCodeBlit: {
ToneMapBlitContext *ctx = static_cast<ToneMapBlitContext *>(task_context);
uint8_t buffer_index = current_buffer_index_;
const void *dst_hnd = reinterpret_cast<const void *>
(buffer_info_[buffer_index].private_data);
const void *src_hnd = reinterpret_cast<const void *>
(ctx->layer->input_buffer.buffer_id);
ctx->fence_fd = gpu_tone_mapper_->blit(dst_hnd, src_hnd, ctx->merged_fd);
}
break;
case ToneMapTaskCode::kCodeDestroy: {
delete gpu_tone_mapper_;
}
break;
default:
break;
}
}
DisplayError ToneMapSession::AllocateIntermediateBuffers(const Layer *layer) {
DisplayError error = kErrorNone;
for (uint8_t i = 0; i < kNumIntermediateBuffers; i++) {
BufferInfo &buffer_info = buffer_info_[i];
buffer_info.buffer_config.width = layer->request.width;
buffer_info.buffer_config.height = layer->request.height;
buffer_info.buffer_config.format = layer->request.format;
buffer_info.buffer_config.secure = layer->request.flags.secure;
buffer_info.buffer_config.gfx_client = true;
error = buffer_allocator_->AllocateBuffer(&buffer_info);
if (error != kErrorNone) {
FreeIntermediateBuffers();
return error;
}
}
return kErrorNone;
}
void ToneMapSession::FreeIntermediateBuffers() {
for (uint8_t i = 0; i < kNumIntermediateBuffers; i++) {
// Free the valid fence
if (release_fence_fd_[i] >= 0) {
CloseFd(&release_fence_fd_[i]);
}
BufferInfo &buffer_info = buffer_info_[i];
if (buffer_info.private_data) {
buffer_allocator_->FreeBuffer(&buffer_info);
}
}
}
void ToneMapSession::UpdateBuffer(int acquire_fence, LayerBuffer *buffer) {
// Acquire fence will be closed by HWC Display.
// Fence returned by GPU will be closed in PostCommit.
buffer->acquire_fence_fd = acquire_fence;
buffer->size = buffer_info_[current_buffer_index_].alloc_buffer_info.size;
buffer->planes[0].fd = buffer_info_[current_buffer_index_].alloc_buffer_info.fd;
}
void ToneMapSession::SetReleaseFence(int fd) {
CloseFd(&release_fence_fd_[current_buffer_index_]);
// Used to give to GPU tonemapper along with input layer fd
release_fence_fd_[current_buffer_index_] = dup(fd);
}
void ToneMapSession::SetToneMapConfig(Layer *layer) {
// HDR -> SDR is FORWARD and SDR - > HDR is INVERSE
tone_map_config_.type = layer->input_buffer.flags.hdr ? TONEMAP_FORWARD : TONEMAP_INVERSE;
tone_map_config_.colorPrimaries = layer->input_buffer.color_metadata.colorPrimaries;
tone_map_config_.transfer = layer->input_buffer.color_metadata.transfer;
tone_map_config_.secure = layer->request.flags.secure;
tone_map_config_.format = layer->request.format;
}
bool ToneMapSession::IsSameToneMapConfig(Layer *layer) {
LayerBuffer& buffer = layer->input_buffer;
private_handle_t *handle = static_cast<private_handle_t *>(buffer_info_[0].private_data);
int tonemap_type = buffer.flags.hdr ? TONEMAP_FORWARD : TONEMAP_INVERSE;
return ((tonemap_type == tone_map_config_.type) &&
(buffer.color_metadata.colorPrimaries == tone_map_config_.colorPrimaries) &&
(buffer.color_metadata.transfer == tone_map_config_.transfer) &&
(layer->request.flags.secure == tone_map_config_.secure) &&
(layer->request.format == tone_map_config_.format) &&
(layer->request.width == UINT32(handle->unaligned_width)) &&
(layer->request.height == UINT32(handle->unaligned_height)));
}
int HWCToneMapper::HandleToneMap(LayerStack *layer_stack) {
uint32_t gpu_count = 0;
DisplayError error = kErrorNone;
for (uint32_t i = 0; i < layer_stack->layers.size(); i++) {
uint32_t session_index = 0;
Layer *layer = layer_stack->layers.at(i);
if (layer->composition == kCompositionGPU) {
gpu_count++;
}
if (layer->request.flags.tone_map) {
switch (layer->composition) {
case kCompositionGPUTarget:
if (!gpu_count) {
// When all layers are on FrameBuffer and if they do not update in the next draw cycle,
// then SDM marks them for SDE Composition because the cached FB layer gets displayed.
// GPU count will be 0 in this case. Try to use the existing tone-mapped frame buffer.
// No ToneMap/Blit is required. Just update the buffer & acquire fence fd of FB layer.
if (!tone_map_sessions_.empty()) {
ToneMapSession *fb_tone_map_session = tone_map_sessions_.at(fb_session_index_);
fb_tone_map_session->UpdateBuffer(-1 /* acquire_fence */, &layer->input_buffer);
fb_tone_map_session->layer_index_ = INT(i);
fb_tone_map_session->acquired_ = true;
return 0;
}
}
error = AcquireToneMapSession(layer, &session_index);
fb_session_index_ = session_index;
break;
default:
error = AcquireToneMapSession(layer, &session_index);
break;
}
if (error != kErrorNone) {
Terminate();
return -1;
}
ToneMapSession *session = tone_map_sessions_.at(session_index);
ToneMap(layer, session);
session->layer_index_ = INT(i);
}
}
return 0;
}
void HWCToneMapper::ToneMap(Layer* layer, ToneMapSession *session) {
ToneMapBlitContext ctx = {};
ctx.layer = layer;
uint8_t buffer_index = session->current_buffer_index_;
int &release_fence_fd = session->release_fence_fd_[buffer_index];
// use and close the layer->input_buffer acquire fence fd.
int acquire_fd = layer->input_buffer.acquire_fence_fd;
buffer_sync_handler_.SyncMerge(release_fence_fd, acquire_fd, &ctx.merged_fd);
if (acquire_fd >= 0) {
CloseFd(&acquire_fd);
}
if (release_fence_fd >= 0) {
CloseFd(&release_fence_fd);
}
DTRACE_BEGIN("GPU_TM_BLIT");
session->tone_map_task_.PerformTask(ToneMapTaskCode::kCodeBlit, &ctx);
DTRACE_END();
DumpToneMapOutput(session, &ctx.fence_fd);
session->UpdateBuffer(ctx.fence_fd, &layer->input_buffer);
}
void HWCToneMapper::PostCommit(LayerStack *layer_stack) {
auto it = tone_map_sessions_.begin();
while (it != tone_map_sessions_.end()) {
uint32_t session_index = UINT32(std::distance(tone_map_sessions_.begin(), it));
ToneMapSession *session = tone_map_sessions_.at(session_index);
if (session->acquired_) {
Layer *layer = layer_stack->layers.at(UINT32(session->layer_index_));
// Close the fd returned by GPU ToneMapper and set release fence.
LayerBuffer &layer_buffer = layer->input_buffer;
CloseFd(&layer_buffer.acquire_fence_fd);
session->SetReleaseFence(layer_buffer.release_fence_fd);
session->acquired_ = false;
it++;
} else {
delete session;
it = tone_map_sessions_.erase(it);
}
}
}
void HWCToneMapper::Terminate() {
if (tone_map_sessions_.size()) {
while (!tone_map_sessions_.empty()) {
delete tone_map_sessions_.back();
tone_map_sessions_.pop_back();
}
fb_session_index_ = 0;
}
}
void HWCToneMapper::SetFrameDumpConfig(uint32_t count) {
DLOGI("Dump FrameConfig count = %d", count);
dump_frame_count_ = count;
dump_frame_index_ = 0;
}
void HWCToneMapper::DumpToneMapOutput(ToneMapSession *session, int *acquire_fd) {
if (!dump_frame_count_) {
return;
}
BufferInfo &buffer_info = session->buffer_info_[session->current_buffer_index_];
private_handle_t *target_buffer = static_cast<private_handle_t *>(buffer_info.private_data);
if (*acquire_fd >= 0) {
int error = sync_wait(*acquire_fd, 1000);
if (error < 0) {
DLOGW("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
return;
}
}
size_t result = 0;
char dump_file_name[PATH_MAX];
snprintf(dump_file_name, sizeof(dump_file_name), "/data/misc/display/frame_dump_primary"
"/tonemap_%dx%d_frame%d.raw", target_buffer->width, target_buffer->height,
dump_frame_index_);
FILE* fp = fopen(dump_file_name, "w+");
if (fp) {
DLOGI("base addr = %x", target_buffer->base);
result = fwrite(reinterpret_cast<void *>(target_buffer->base), target_buffer->size, 1, fp);
fclose(fp);
}
dump_frame_count_--;
dump_frame_index_++;
CloseFd(acquire_fd);
}
DisplayError HWCToneMapper::AcquireToneMapSession(Layer *layer, uint32_t *session_index) {
// When the property sdm.disable_hdr_lut_gen is set, the lutEntries and gridEntries in
// the Lut3d will be NULL, clients needs to allocate the memory and set correct 3D Lut
// for Tonemapping.
if (!layer->lut_3d.lutEntries || !layer->lut_3d.dim) {
// Atleast lutEntries must be valid for GPU Tonemapper.
DLOGE("Invalid Lut Entries or lut dimension = %d", layer->lut_3d.dim);
return kErrorParameters;
}
// Check if we can re-use an existing tone map session.
for (uint32_t i = 0; i < tone_map_sessions_.size(); i++) {
ToneMapSession *tonemap_session = tone_map_sessions_.at(i);
if (!tonemap_session->acquired_ && tonemap_session->IsSameToneMapConfig(layer)) {
tonemap_session->current_buffer_index_ = (tonemap_session->current_buffer_index_ + 1) %
ToneMapSession::kNumIntermediateBuffers;
tonemap_session->acquired_ = true;
*session_index = i;
return kErrorNone;
}
}
ToneMapSession *session = new ToneMapSession(buffer_allocator_);
if (!session) {
return kErrorMemory;
}
session->SetToneMapConfig(layer);
ToneMapGetInstanceContext ctx;
ctx.layer = layer;
session->tone_map_task_.PerformTask(ToneMapTaskCode::kCodeGetInstance, &ctx);
if (session->gpu_tone_mapper_ == NULL) {
DLOGE("Get Tonemapper failed!");
delete session;
return kErrorNotSupported;
}
DisplayError error = session->AllocateIntermediateBuffers(layer);
if (error != kErrorNone) {
DLOGE("Allocation of Intermediate Buffers failed!");
delete session;
return error;
}
session->acquired_ = true;
tone_map_sessions_.push_back(session);
*session_index = UINT32(tone_map_sessions_.size() - 1);
return kErrorNone;
}
} // namespace sdm

View File

@ -0,0 +1,125 @@
/*
* Copyright (c) 2016 - 2017, 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_TONEMAPPER_H__
#define __HWC_TONEMAPPER_H__
#include <fcntl.h>
#include <sys/mman.h>
#include <hardware/hwcomposer.h>
#include <core/layer_stack.h>
#include <utils/sys.h>
#include <utils/sync_task.h>
#include <vector>
#include "hwc_buffer_sync_handler.h"
#include "hwc_buffer_allocator.h"
class Tonemapper;
namespace sdm {
enum class ToneMapTaskCode : int32_t {
kCodeGetInstance,
kCodeBlit,
kCodeDestroy,
};
struct ToneMapGetInstanceContext : public SyncTask<ToneMapTaskCode>::TaskContext {
Layer *layer = nullptr;
};
struct ToneMapBlitContext : public SyncTask<ToneMapTaskCode>::TaskContext {
Layer *layer = nullptr;
int merged_fd = -1;
int fence_fd = -1;
};
struct ToneMapConfig {
int type = 0;
ColorPrimaries colorPrimaries = ColorPrimaries_Max;
GammaTransfer transfer = Transfer_Max;
LayerBufferFormat format = kFormatRGBA8888;
bool secure = false;
};
class ToneMapSession : public SyncTask<ToneMapTaskCode>::TaskHandler {
public:
explicit ToneMapSession(HWCBufferAllocator *buffer_allocator);
~ToneMapSession();
DisplayError AllocateIntermediateBuffers(const Layer *layer);
void FreeIntermediateBuffers();
void UpdateBuffer(int acquire_fence, LayerBuffer *buffer);
void SetReleaseFence(int fd);
void SetToneMapConfig(Layer *layer);
bool IsSameToneMapConfig(Layer *layer);
// TaskHandler methods implementation.
virtual void OnTask(const ToneMapTaskCode &task_code,
SyncTask<ToneMapTaskCode>::TaskContext *task_context);
static const uint8_t kNumIntermediateBuffers = 2;
SyncTask<ToneMapTaskCode> tone_map_task_;
Tonemapper *gpu_tone_mapper_ = nullptr;
HWCBufferAllocator *buffer_allocator_ = nullptr;
ToneMapConfig tone_map_config_ = {};
uint8_t current_buffer_index_ = 0;
std::vector<BufferInfo> buffer_info_ = {};
int release_fence_fd_[kNumIntermediateBuffers] = {-1, -1};
bool acquired_ = false;
int layer_index_ = -1;
};
class HWCToneMapper {
public:
explicit HWCToneMapper(HWCBufferAllocator *allocator) : buffer_allocator_(allocator) {}
~HWCToneMapper() {}
int HandleToneMap(LayerStack *layer_stack);
bool IsActive() { return !tone_map_sessions_.empty(); }
void PostCommit(LayerStack *layer_stack);
void SetFrameDumpConfig(uint32_t count);
void Terminate();
private:
void ToneMap(Layer *layer, ToneMapSession *session);
DisplayError AcquireToneMapSession(Layer *layer, uint32_t *session_index);
void DumpToneMapOutput(ToneMapSession *session, int *acquire_fence);
std::vector<ToneMapSession*> tone_map_sessions_;
HWCBufferSyncHandler buffer_sync_handler_ = {};
HWCBufferAllocator *buffer_allocator_ = nullptr;
uint32_t dump_frame_count_ = 0;
uint32_t dump_frame_index_ = 0;
uint32_t fb_session_index_ = 0;
};
} // namespace sdm
#endif // __HWC_TONEMAPPER_H__

View File

@ -26,5 +26,8 @@ LOCAL_COPY_HEADERS = $(SDM_HEADER_PATH)/utils/constants.h \
$(SDM_HEADER_PATH)/utils/locker.h \
$(SDM_HEADER_PATH)/utils/rect.h \
$(SDM_HEADER_PATH)/utils/sys.h \
$(SDM_HEADER_PATH)/utils/utils.h
$(SDM_HEADER_PATH)/utils/sync_task.h \
$(SDM_HEADER_PATH)/utils/utils.h \
$(SDM_HEADER_PATH)/utils/factory.h
include $(BUILD_COPY_HEADERS)