display: Update to AU 269
am: f1fe88efc1
Change-Id: Ib84b004a908d8155cd1800f01b82521386688f12
This commit is contained in:
commit
3533a776b5
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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)
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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__
|
|
@ -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__
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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!");
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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, ...) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
|
@ -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__
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue