Support ColorGamut convertion.

Signed-off-by: xxfeng_hw <yuxiaofeng8@huawei.com>
Change-Id: I61081bf98c90ebaa89a4ca22d6c300bc96d1625f
This commit is contained in:
xxfeng_hw 2022-02-16 16:58:53 +08:00
parent cd6a4b1659
commit feee70db63
8 changed files with 531 additions and 91 deletions

View File

@ -14,17 +14,12 @@
*/
#include "pipeline/rs_hardware_processor.h"
#include <iterator>
#include "display_type.h"
#include "pipeline/rs_main_thread.h"
#include "pipeline/rs_render_service_util.h"
#include "platform/common/rs_log.h"
#include "common/rs_obj_abs_geometry.h"
namespace OHOS {
namespace Rosen {
RSHardwareProcessor::RSHardwareProcessor() {}
RSHardwareProcessor::~RSHardwareProcessor() {}
@ -45,14 +40,15 @@ void RSHardwareProcessor::Init(ScreenId id)
ROSEN_LOGE("RSHardwareProcessor::Init output_ is nullptr");
return;
}
screenManager_->GetScreenActiveMode(id, curScreenInfo_);
currScreenInfo_ = screenManager_->QueryScreenInfo(id);
ROSEN_LOGI("RSHardwareProcessor::Init screen w:%{public}d, w:%{public}d",
curScreenInfo_.GetScreenWidth(), curScreenInfo_.GetScreenHeight());
currScreenInfo_.width, currScreenInfo_.height);
IRect damageRect;
damageRect.x = 0;
damageRect.y = 0;
damageRect.w = curScreenInfo_.GetScreenWidth();
damageRect.h = curScreenInfo_.GetScreenHeight();
damageRect.w = currScreenInfo_.width;
damageRect.h = currScreenInfo_.height;
output_->SetOutputDamage(1, damageRect);
}
@ -81,8 +77,8 @@ void RSHardwareProcessor::CropLayers()
IRect dstRect = layer->GetLayerSize();
IRect srcRect = layer->GetCropRect();
IRect orgSrcRect = srcRect;
int32_t screenWidth = curScreenInfo_.GetScreenWidth();
int32_t screenHeight = curScreenInfo_.GetScreenHeight();
int32_t screenWidth = currScreenInfo_.width;
int32_t screenHeight = currScreenInfo_.height;
if (dstRect.x < 0 && dstRect.x + dstRect.w > 0) {
srcRect.w = srcRect.w * (dstRect.w + dstRect.x) / dstRect.w;
srcRect.x = orgSrcRect.w - srcRect.w;
@ -124,8 +120,8 @@ void RSHardwareProcessor::ProcessSurface(RSSurfaceRenderNode &node)
ROSEN_LOGE("RSHardwareProcessor::ProcessSurface output is nullptr");
return;
}
if (node.GetRenderProperties().GetBoundsPositionX() >= curScreenInfo_.GetScreenWidth() ||
node.GetRenderProperties().GetBoundsPositionY() >= curScreenInfo_.GetScreenHeight()) {
if (node.GetRenderProperties().GetBoundsPositionX() >= currScreenInfo_.width ||
node.GetRenderProperties().GetBoundsPositionY() >= currScreenInfo_.height) {
ROSEN_LOGE("RsDebug RSHardwareProcessor::ProcessSurface this node:%llu no need to composite", node.GetId());
return;
}
@ -136,7 +132,7 @@ void RSHardwareProcessor::ProcessSurface(RSSurfaceRenderNode &node)
ROSEN_LOGE("RsDebug RSHardwareProcessor::ProcessSurface consume buffer fail");
return;
}
if (node.IsBufferAvailable() == false) {
if (!node.IsBufferAvailable()) {
// Only ipc for one time.
ROSEN_LOGI("RsDebug RSHardwareProcessor::ProcessSurface id = %llu Notify RT buffer available", node.GetId());
node.NotifyBufferAvailable(true);
@ -162,8 +158,8 @@ void RSHardwareProcessor::ProcessSurface(RSSurfaceRenderNode &node)
.visibleRect = {
.x = 0,
.y = 0,
.w = curScreenInfo_.GetScreenWidth(),
.h = curScreenInfo_.GetScreenHeight(),
.w = currScreenInfo_.width,
.h = currScreenInfo_.height,
},
.zOrder = node.GetGlobalZOrder(),
.alpha = {
@ -187,6 +183,9 @@ void RSHardwareProcessor::ProcessSurface(RSSurfaceRenderNode &node)
node.GetBuffer()->GetSurfaceBufferHeight(), node.GetBuffer().GetRefPtr(),
node.GetRenderProperties().GetPositionZ(), info.zOrder, info.blendType);
RsRenderServiceUtil::ComposeSurface(layer, node.GetConsumer(), layers_, info, &node);
if (info.buffer->GetSurfaceBufferColorGamut() != static_cast<SurfaceColorGamut>(currScreenInfo_.colorGamut)) {
layer->SetCompositionType(CompositionType::COMPOSITION_CLIENT);
}
}
void RSHardwareProcessor::CalculateInfo(const std::unique_ptr<RSTransitionProperties>& transitionProperties,
@ -227,8 +226,8 @@ void RSHardwareProcessor::Redraw(sptr<Surface>& surface, const struct PrepareCom
}
ROSEN_LOGI("RsDebug RSHardwareProcessor::Redraw flush frame buffer start");
BufferRequestConfig requestConfig = {
.width = curScreenInfo_.GetScreenWidth(),
.height = curScreenInfo_.GetScreenHeight(),
.width = currScreenInfo_.width,
.height = currScreenInfo_.height,
.strideAlignment = 0x8,
.format = PIXEL_FMT_RGBA_8888, // [PLANNING] different soc need different format
.usage = HBM_USE_CPU_READ | HBM_USE_CPU_WRITE | HBM_USE_MEM_DMA | HBM_USE_MEM_FB,
@ -239,23 +238,35 @@ void RSHardwareProcessor::Redraw(sptr<Surface>& surface, const struct PrepareCom
ROSEN_LOGE("RSHardwareProcessor::Redraw: canvas is null.");
return;
}
std::vector<LayerInfoPtr>::const_reverse_iterator iter = param.layers.rbegin();
for (; iter != param.layers.rend(); ++iter) {
ROSEN_LOGD("RsDebug RSHardwareProcessor::Redraw layer composition Type:%d", (*iter)->GetCompositionType());
if ((*iter) == nullptr || (*iter)->GetCompositionType() == CompositionType::COMPOSITION_DEVICE) {
for (auto it = param.layers.rbegin(); it != param.layers.rend(); ++it) {
LayerInfoPtr layerInfo = *it;
if (layerInfo == nullptr || layerInfo->GetCompositionType() == CompositionType::COMPOSITION_DEVICE) {
continue;
}
ROSEN_LOGE("RsDebug RSHardwareProcessor::Redraw layer [%d %d %d %d]", (*iter)->GetLayerSize().x,
(*iter)->GetLayerSize().y, (*iter)->GetLayerSize().w, (*iter)->GetLayerSize().h);
RsRenderServiceUtil::DrawBuffer(canvas.get(), (*iter)->GetBuffer(),
*static_cast<RSSurfaceRenderNode *>((*iter)->GetLayerAdditionalInfo()));
ROSEN_LOGD("RsDebug RSHardwareProcessor::Redraw layer composition Type:%d, [%d %d %d %d]",
layerInfo->GetCompositionType(), layerInfo->GetLayerSize().x, layerInfo->GetLayerSize().y,
layerInfo->GetLayerSize().w, layerInfo->GetLayerSize().h);
sptr<SurfaceBuffer> buffer = layerInfo->GetBuffer();
SurfaceColorGamut bufferColorGamut = buffer->GetSurfaceBufferColorGamut();
if (bufferColorGamut == static_cast<SurfaceColorGamut>(currScreenInfo_.colorGamut)) {
RsRenderServiceUtil::DrawBuffer(canvas.get(), buffer,
*(static_cast<RSSurfaceRenderNode *>(layerInfo->GetLayerAdditionalInfo())));
} else {
ROSEN_LOGW("RSHardwareProcessor::Redraw: need to convert color gamut.");
RsRenderServiceUtil::DrawBuffer(canvas.get(), buffer,
*(static_cast<RSSurfaceRenderNode *>(layerInfo->GetLayerAdditionalInfo())),
static_cast<ColorGamut>(currScreenInfo_.colorGamut));
}
}
BufferFlushConfig flushConfig = {
.damage = {
.x = 0,
.y = 0,
.w = curScreenInfo_.GetScreenWidth(),
.h = curScreenInfo_.GetScreenHeight(),
.w = currScreenInfo_.width,
.h = currScreenInfo_.height,
},
};
FlushBuffer(surface, flushConfig);
@ -263,8 +274,8 @@ void RSHardwareProcessor::Redraw(sptr<Surface>& surface, const struct PrepareCom
void RSHardwareProcessor::OnRotate()
{
int32_t width = curScreenInfo_.GetScreenWidth();
int32_t height = curScreenInfo_.GetScreenHeight();
int32_t width = currScreenInfo_.width;
int32_t height = currScreenInfo_.height;
for (auto& layer: layers_) {
IRect rect = layer->GetLayerSize();
ROSEN_LOGI("RsDebug RSHardwareProcessor::OnRotate Before Rotate layer size [%d %d %d %d]",

View File

@ -50,7 +50,7 @@ private:
RSSurfaceRenderNode& node);
HdiBackend* backend_ = nullptr;
sptr<RSScreenManager> screenManager_;
RSScreenModeInfo curScreenInfo_;
ScreenInfo currScreenInfo_;
std::shared_ptr<HdiOutput> output_;
std::vector<LayerInfoPtr> layers_;
ScreenRotation rotation_ {ScreenRotation::ROTATION_0};

View File

@ -18,11 +18,10 @@
#include "pipeline/rs_main_thread.h"
#include "pipeline/rs_processor.h"
#include "display_type.h"
#include "platform/common/rs_log.h"
namespace OHOS {
namespace Rosen {
std::unique_ptr<SkCanvas> RSProcessor::CreateCanvas(sptr<Surface> producerSurface, BufferRequestConfig requestConfig)
{
auto ret = producerSurface->RequestBuffer(buffer_, releaseFence_, requestConfig);
@ -90,5 +89,5 @@ bool RSProcessor::ConsumeAndUpdateBuffer(RSSurfaceRenderNode& node, SpecialTask&
}
return true;
}
}
}
} // namespace Rosen
} // namespace OHOS

View File

@ -12,19 +12,399 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "pipeline/rs_render_service_util.h"
#include "common/rs_common_def.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPixmap.h"
#include "include/core/SkBitmap.h"
#include "rs_render_service_util.h"
#include <unordered_set>
#include "platform/common/rs_log.h"
#include "property/rs_properties.h"
#include "property/rs_properties_painter.h"
#include "render/rs_blur_filter.h"
#include "rs_trace.h"
namespace OHOS {
namespace Rosen {
namespace Detail {
// [PLANNING]: Use GPU to do the gamut convertion instead of these following works.
using PixelTransformFunc = std::function<float(float)>;
inline constexpr float PassThrough(float v)
{
return v;
}
template<typename T>
static constexpr T Saturate(T v) noexcept
{
return T(std::min(static_cast<T>(1), std::max(static_cast<T>(0), v)));
}
inline Vector3f ApplyTransForm(const Vector3f& val, const PixelTransformFunc& func)
{
return Vector3f {func(val.x_), func(val.y_), func(val.z_)};
}
inline float SafePow(float x, float e)
{
return powf(x < 0.0f ? 0.0f : x, e);
}
inline PixelTransformFunc GenOETF(float gamma)
{
if (gamma == 1.0f || gamma == 0.0f) {
return PassThrough;
}
return std::bind(SafePow, std::placeholders::_1, 1.0f / gamma);
}
inline PixelTransformFunc GenEOTF(float gamma)
{
if (gamma == 1.0f) {
return PassThrough;
}
return std::bind(SafePow, std::placeholders::_1, gamma);
}
struct TransferParameters {
float g = 0.0f;
float a = 0.0f;
float b = 0.0f;
float c = 0.0f;
float d = 0.0f;
float e = 0.0f;
float f = 0.0f;
};
static constexpr float RcpResponse(float x, const TransferParameters& p)
{
return x >= p.d * p.c ? (std::pow(x, 1.0f / p.g) - p.b) / p.a : x / p.c;
}
inline constexpr float Response(float x, const TransferParameters& p)
{
return x >= p.d ? std::pow(p.a * x + p.b, p.g) : p.c * x;
}
inline constexpr float RcpFullResponse(float x, const TransferParameters& p)
{
return x >= p.d * p.c ? (std::pow(x - p.e, 1.0f / p.g) - p.b) / p.a : (x - p.f) / p.c;
}
inline constexpr float FullResponse(float x, const TransferParameters& p)
{
return x >= p.d ? std::pow(p.a * x + p.b, p.g) + p.e : p.c * x + p.f;
}
inline PixelTransformFunc GenOETF(const TransferParameters& params)
{
if (params.e == 0.0f && params.f == 0.0f) {
return std::bind(RcpResponse, std::placeholders::_1, params);
}
return std::bind(RcpFullResponse, std::placeholders::_1, params);
}
inline PixelTransformFunc GenEOTF(const TransferParameters& params)
{
if (params.e == 0.0f && params.f == 0.0f) {
return std::bind(Response, std::placeholders::_1, params);
}
return std::bind(FullResponse, std::placeholders::_1, params);
}
Matrix3f GenRGBToXYZMatrix(const std::array<Vector2f, 3>& basePoints, const Vector2f& whitePoint)
{
const Vector2f& R = basePoints[0];
const Vector2f& G = basePoints[1];
const Vector2f& B = basePoints[2];
float RxRy = R.x_ / R.y_;
float GxGy = G.x_ / G.y_;
float BxBy = B.x_ / B.y_;
float WxWy = whitePoint.x_ / whitePoint.y_;
float oneRxRy = (1 - R.x_) / R.y_;
float oneGxGy = (1 - G.x_) / G.y_;
float oneBxBy = (1 - B.x_) / B.y_;
float oneWxWy = (1 - whitePoint.x_) / whitePoint.y_;
float BY =
((oneWxWy - oneRxRy) * (GxGy - RxRy) - (WxWy - RxRy) * (oneGxGy - oneRxRy)) /
((oneBxBy - oneRxRy) * (GxGy - RxRy) - (BxBy - RxRy) * (oneGxGy - oneRxRy));
float GY = (WxWy - RxRy - BY * (BxBy - RxRy)) / (GxGy - RxRy);
float RY = 1 - GY - BY;
float RYRy = RY / R.y_;
float GYGy = GY / G.y_;
float BYBy = BY / B.y_;
return Matrix3f {
RYRy * R.x_, RY, RYRy * (1 - R.x_ - R.y_),
GYGy * G.x_, GY, GYGy * (1 - G.x_ - G.y_),
BYBy * B.x_, BY, BYBy * (1 - B.x_ - B.y_)
};
}
class SimpleColorSpace {
public:
// 3 RGB basePoints and 1 whitePoint.
SimpleColorSpace(
const std::array<Vector2f, 3>& basePoints,
const Vector2f& whitePoint,
float gamma,
PixelTransformFunc clamper = Saturate<float>
) noexcept
: rgbToXyz_(GenRGBToXYZMatrix(basePoints, whitePoint)),
xyzToRgb_(rgbToXyz_.Inverse()),
transEOTF_(GenEOTF(gamma)),
transOETF_(GenOETF(gamma)),
clamper_(std::move(clamper)),
transferParams_({ gamma, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f })
{
}
SimpleColorSpace(
const std::array<Vector2f, 3>& basePoints,
const Vector2f& whitePoint,
const TransferParameters& parameters,
PixelTransformFunc clamper = Saturate<float>
) noexcept
: rgbToXyz_(GenRGBToXYZMatrix(basePoints, whitePoint)),
xyzToRgb_(rgbToXyz_.Inverse()),
transEOTF_(GenEOTF(parameters)),
transOETF_(GenOETF(parameters)),
clamper_(std::move(clamper)),
transferParams_(parameters)
{
}
~SimpleColorSpace() noexcept = default;
Vector3f ToLinear(const Vector3f& val) const
{
return ApplyTransForm(val, transEOTF_);
}
Vector3f FromLinear(const Vector3f& val) const
{
return ApplyTransForm(val, transOETF_);
}
Vector3f RGBToXYZ(const Vector3f& rgb) const
{
return rgbToXyz_ * ToLinear(rgb);
}
Vector3f XYZToRGB(const Vector3f& xyz) const
{
return ApplyTransForm(FromLinear(xyzToRgb_ * xyz), clamper_);
}
private:
Matrix3f rgbToXyz_;
Matrix3f xyzToRgb_;
PixelTransformFunc transEOTF_;
PixelTransformFunc transOETF_;
PixelTransformFunc clamper_;
TransferParameters transferParams_;
};
SimpleColorSpace &GetSRGBColorSpace()
{
static SimpleColorSpace sRGB {
{{Vector2f{0.640f, 0.330f}, {0.300f, 0.600f}, {0.150f, 0.060f}}}, // rgb base points.
{0.3127f, 0.3290f}, // white points.
{2.4f, 1 / 1.055f, 0.055f / 1.055f, 1 / 12.92f, 0.04045f, 0.0f, 0.0f}}; // TransferParameters
return sRGB;
}
SimpleColorSpace &GetAdobeRGBColorSpace()
{
static SimpleColorSpace adobeRGB {
{{Vector2f{0.64f, 0.33f}, {0.21f, 0.71f}, {0.15f, 0.06f}}}, // rgb base points.
{0.3127f, 0.3290f}, // white points.
2.2f}; // gamma 2.2
return adobeRGB;
}
SimpleColorSpace &GetDisplayP3ColorSpace()
{
static SimpleColorSpace displayP3 {
{{Vector2f{0.680f, 0.320f}, {0.265f, 0.690f}, {0.150f, 0.060f}}}, // rgb base points.
{0.3127f, 0.3290f}, // white points.
{2.4f, 1 / 1.055f, 0.055f / 1.055f, 1 / 12.92f, 0.039f, 0.0f, 0.0f}}; // TransferParameters
return displayP3;
}
SimpleColorSpace &GetDCIP3ColorSpace()
{
static SimpleColorSpace dciP3 {
{{Vector2f{0.680f, 0.320f}, {0.265f, 0.690f}, {0.150f, 0.060f}}}, // rgb base points.
{0.314f, 0.351f}, // white points.
2.6f}; // gamma 2.6
return dciP3;
}
bool IsSupportedFormatForGamutConvertion(int32_t pixelFormat)
{
static std::unordered_set<PixelFormat> supportedFormats = {
PixelFormat::PIXEL_FMT_RGBX_8888,
PixelFormat::PIXEL_FMT_RGBA_8888,
PixelFormat::PIXEL_FMT_RGB_888,
PixelFormat::PIXEL_FMT_BGRX_8888,
PixelFormat::PIXEL_FMT_BGRA_8888
};
return supportedFormats.count(static_cast<PixelFormat>(pixelFormat)) > 0;
}
bool IsSupportedColorGamut(ColorGamut colorGamut)
{
static std::unordered_set<ColorGamut> supportedColorGamuts = {
ColorGamut::COLOR_GAMUT_SRGB,
ColorGamut::COLOR_GAMUT_ADOBE_RGB,
ColorGamut::COLOR_GAMUT_DISPLAY_P3,
ColorGamut::COLOR_GAMUT_DCI_P3
};
return supportedColorGamuts.count(colorGamut) > 0;
}
SimpleColorSpace& GetColorSpaceOfCertainGamut(ColorGamut colorGamut)
{
switch (colorGamut) {
case ColorGamut::COLOR_GAMUT_SRGB: {
return GetSRGBColorSpace();
}
case ColorGamut::COLOR_GAMUT_ADOBE_RGB: {
return GetAdobeRGBColorSpace();
}
case ColorGamut::COLOR_GAMUT_DISPLAY_P3: {
return GetDisplayP3ColorSpace();
}
case ColorGamut::COLOR_GAMUT_DCI_P3: {
return GetDCIP3ColorSpace();
}
default: {
return GetSRGBColorSpace();
}
}
}
float RGBUint8ToFloat(uint8_t val)
{
return val * 1.0f / 255.0f; // 255.0f is the max value.
}
uint8_t RGBFloatToUint8(float val)
{
return static_cast<uint8_t>(Saturate(val) * 255 + 0.5f); // 255.0 is the max value, + 0.5f to avoid negetive.
}
uint8_t ConvertColorGamut(uint8_t *dst, uint8_t* src, int32_t pixelFormat, ColorGamut srcGamut, ColorGamut dstGamut)
{
uint8_t len = 0;
Vector3f srcColor;
std::array<uint8_t *, 3> colorDst; // color dst, 3 bytes (R G B).
switch (static_cast<PixelFormat>(pixelFormat)) {
case PixelFormat::PIXEL_FMT_RGBX_8888:
case PixelFormat::PIXEL_FMT_RGBA_8888: {
// R: src[0], G: src[1], B: src[2]
srcColor = {RGBUint8ToFloat(src[0]), RGBUint8ToFloat(src[1]), RGBUint8ToFloat(src[2])};
// R: dst + 0, G: dst + 1, B: dst + 2
colorDst = {dst + 0, dst + 1, dst + 2};
len = 4; // 4 bytes per pixel.
break;
}
case PixelFormat::PIXEL_FMT_RGB_888: {
// R: src[0], G: src[1], B: src[2]
srcColor = {RGBUint8ToFloat(src[0]), RGBUint8ToFloat(src[1]), RGBUint8ToFloat(src[2])};
// R: dst + 0, G: dst + 1, B: dst + 2
colorDst = {dst + 0, dst + 1, dst + 2};
len = 3; // 3 bytes per pixel.
break;
}
case PixelFormat::PIXEL_FMT_BGRX_8888:
case PixelFormat::PIXEL_FMT_BGRA_8888: {
// R: src[2], G: src[1], B: src[0]
srcColor = {RGBUint8ToFloat(src[2]), RGBUint8ToFloat(src[1]), RGBUint8ToFloat(src[0])};
// R: dst + 2, G: dst + 1, B: dst + 0
colorDst = {dst + 2, dst + 1, dst + 0};
len = 4; // 4 bytes per pixel.
break;
}
default: {
ROSEN_LOGE("ConvertColorGamut: unexpected pixelFormat(%d).", pixelFormat);
return 0;
}
}
auto& srcColorSpace = GetColorSpaceOfCertainGamut(srcGamut);
auto& dstColorSpace = GetColorSpaceOfCertainGamut(dstGamut);
Vector3f outColor = dstColorSpace.XYZToRGB(srcColorSpace.RGBToXYZ(srcColor));
*(colorDst[0]) = RGBFloatToUint8(outColor[0]); // outColor 0 to colorDst[0]
*(colorDst[1]) = RGBFloatToUint8(outColor[1]); // outColor 1 to colorDst[1]
*(colorDst[2]) = RGBFloatToUint8(outColor[2]); // outColor 2 to colorDst[2]
return len;
}
bool ConvertBufferColorGamut(std::vector<uint8_t>& dstBuf, const sptr<OHOS::SurfaceBuffer>& srcBuf,
ColorGamut srcGamut, ColorGamut dstGamut)
{
RS_TRACE_NAME("ConvertBufferColorGamut");
int32_t pixelFormat = srcBuf->GetFormat();
if (!IsSupportedFormatForGamutConvertion(pixelFormat)) {
ROSEN_LOGE("ConvertBufferColorGamut: the buffer's format is not supported.");
return false;
}
if (!IsSupportedColorGamut(srcGamut) || !IsSupportedColorGamut(dstGamut)) {
return false;
}
uint32_t bufferSize = srcBuf->GetSize();
dstBuf.resize(bufferSize);
auto bufferAddr = srcBuf->GetVirAddr();
uint8_t* srcStart = static_cast<uint8_t*>(bufferAddr);
uint32_t offset = 0;
while (offset < bufferSize) {
uint8_t* dst = &dstBuf[offset];
uint8_t* src = srcStart + offset;
uint8_t len = ConvertColorGamut(dst, src, pixelFormat, srcGamut, dstGamut);
offset += len;
}
return true;
}
SkImageInfo GenerateSkImageInfo(const sptr<OHOS::SurfaceBuffer>& buffer)
{
SkColorType colorType = (buffer->GetFormat() == PIXEL_FMT_BGRA_8888) ?
kBGRA_8888_SkColorType : kRGBA_8888_SkColorType;
return SkImageInfo::Make(buffer->GetWidth(), buffer->GetHeight(),
colorType, kPremul_SkAlphaType);
}
void FillDrawParameters(BufferDrawParameters& params, const sptr<OHOS::SurfaceBuffer>& buffer,
const RSSurfaceRenderNode& node)
{
params.bitmap = SkBitmap();
params.antiAlias = true;
const RSProperties& property = node.GetRenderProperties();
params.alpha = node.GetAlpha() * property.GetAlpha();
params.dstRect = SkRect::MakeXYWH(0, 0, buffer->GetWidth(), buffer->GetHeight());
auto geoPtr = std::static_pointer_cast<RSObjAbsGeometry>(property.GetBoundsGeometry());
if (geoPtr) {
params.transform = geoPtr->GetAbsMatrix();
params.widthScale = static_cast<double>(geoPtr->GetAbsRect().width_ * 1.0 / buffer->GetWidth());
params.heightScale = static_cast<double>(geoPtr->GetAbsRect().height_ * 1.0 / buffer->GetHeight());
}
}
} // namespace Detail
void RsRenderServiceUtil::ComposeSurface(std::shared_ptr<HdiLayerInfo> layer, sptr<Surface> consumerSurface,
std::vector<LayerInfoPtr>& layers, ComposeInfo info, RSSurfaceRenderNode* node)
{
@ -64,24 +444,56 @@ bool RsRenderServiceUtil::IsNeedClient(RSSurfaceRenderNode* node)
return rAngle > 0;
}
void RsRenderServiceUtil::DealAnimation(SkCanvas* canvas, SkPaint& paint, const RSProperties& property,
const std::unique_ptr<RSTransitionProperties>& transitionProperties)
// inner interface
void RsRenderServiceUtil::DealAnimation(SkCanvas& canvas, SkPaint& paint, RSSurfaceRenderNode& node)
{
if (!canvas || !transitionProperties) {
ROSEN_LOGD("RsRenderServiceUtil::dealAnimation canvas or properties is nullptr");
auto transitionProperties = node.GetAnimationManager().GetTransitionProperties();
if (transitionProperties == nullptr) {
ROSEN_LOGD("RsRenderServiceUtil::dealAnimation: node's transitionProperties is nullptr.");
return;
}
const RSProperties& property = node.GetRenderProperties();
paint.setAlphaf(paint.getAlphaf() * transitionProperties->GetAlpha());
auto translate = transitionProperties->GetTranslate();
canvas->translate(translate.x_, translate.y_);
canvas.translate(translate.x_, translate.y_);
// scale and rotate about the center of node, currently scaleZ is not used
auto center = property.GetBoundsSize() * 0.5f;
auto scale = transitionProperties->GetScale();
canvas->translate(center.x_, center.y_);
canvas->scale(scale.x_, scale.y_);
canvas->concat(transitionProperties->GetRotate());
canvas->translate(-center.x_, -center.y_);
canvas.translate(center.x_, center.y_);
canvas.scale(scale.x_, scale.y_);
canvas.concat(transitionProperties->GetRotate());
canvas.translate(-center.x_, -center.y_);
}
// inner interface
void RsRenderServiceUtil::Draw(SkCanvas& canvas, BufferDrawParameters& params, RSSurfaceRenderNode& node)
{
SkPaint paint;
paint.setAntiAlias(params.antiAlias);
paint.setAlphaf(params.alpha);
SkBitmap& bitmap = params.bitmap;
const SkPixmap& pixmap = params.pixmap;
if (bitmap.installPixels(pixmap)) {
canvas.save();
if (params.onDisplay) {
canvas.setMatrix(params.transform);
canvas.scale(params.widthScale, params.heightScale);
DealAnimation(canvas, paint, node);
const RSProperties& property = node.GetRenderProperties();
auto filter = std::static_pointer_cast<RSSkiaFilter>(property.GetBackgroundFilter());
if (filter != nullptr) {
auto skRectPtr = std::make_unique<SkRect>();
skRectPtr->setXYWH(0, 0, params.dstRect.width(), params.dstRect.height());
RSPropertiesPainter::SaveLayerForFilter(property, canvas, filter, skRectPtr);
RSPropertiesPainter::RestoreForFilter(canvas);
}
}
canvas.drawBitmapRect(bitmap, params.dstRect, &paint);
canvas.restore();
}
}
void RsRenderServiceUtil::DrawBuffer(SkCanvas* canvas, sptr<OHOS::SurfaceBuffer> buffer,
@ -95,42 +507,47 @@ void RsRenderServiceUtil::DrawBuffer(SkCanvas* canvas, sptr<OHOS::SurfaceBuffer>
ROSEN_LOGE("RsRenderServiceUtil::DrawBuffer buffer is nullptr");
return;
}
auto addr = static_cast<uint32_t*>(buffer->GetVirAddr());
auto addr = buffer->GetVirAddr();
if (addr == nullptr || buffer->GetWidth() <= 0 || buffer->GetHeight() <= 0) {
ROSEN_LOGE("RsRenderServiceUtil::DrawBuffer this buffer have no vir add or width or height is negative");
return;
}
SkColorType colorType = (buffer->GetFormat() == PIXEL_FMT_BGRA_8888) ?
kBGRA_8888_SkColorType : kRGBA_8888_SkColorType;
SkImageInfo layerInfo = SkImageInfo::Make(buffer->GetWidth(), buffer->GetHeight(),
colorType, kPremul_SkAlphaType);
SkPixmap pixmap(layerInfo, addr, buffer->GetStride());
SkBitmap bitmap;
SkPaint paint;
paint.setAntiAlias(true);
paint.setAlphaf(node.GetAlpha() * node.GetRenderProperties().GetAlpha());
if (bitmap.installPixels(pixmap)) {
canvas->save();
std::unique_ptr<SkRect> rect =
std::make_unique<SkRect>(SkRect::MakeXYWH(0, 0, buffer->GetWidth(), buffer->GetHeight()));
if (isDrawnOnDisplay) {
const RSProperties& property = node.GetRenderProperties();
auto geoptr = std::static_pointer_cast<RSObjAbsGeometry>(property.GetBoundsGeometry());
if (geoptr) {
canvas->setMatrix(geoptr->GetAbsMatrix());
canvas->scale(static_cast<double>(geoptr->GetAbsRect().width_)/static_cast<double>(buffer->GetWidth()),
static_cast<double>(geoptr->GetAbsRect().height_)/static_cast<double>(buffer->GetHeight()));
}
DealAnimation(canvas, paint, property, node.GetAnimationManager().GetTransitionProperties());
auto filter = std::static_pointer_cast<RSSkiaFilter>(property.GetBackgroundFilter());
if (filter != nullptr) {
RSPropertiesPainter::SaveLayerForFilter(property, (*canvas), filter, rect);
RSPropertiesPainter::RestoreForFilter(*canvas);
}
}
canvas->drawBitmapRect(bitmap, (*rect), &paint);
canvas->restore();
BufferDrawParameters params;
SkImageInfo imageInfo = Detail::GenerateSkImageInfo(buffer);
params.pixmap = SkPixmap(imageInfo, buffer->GetVirAddr(), buffer->GetStride());
Detail::FillDrawParameters(params, buffer, node);
params.onDisplay = isDrawnOnDisplay;
Draw(*canvas, params, node);
}
void RsRenderServiceUtil::DrawBuffer(SkCanvas& canvas, const sptr<OHOS::SurfaceBuffer>& buffer,
RSSurfaceRenderNode& node, ColorGamut dstGamut, bool isDrawnOnDisplay)
{
if (buffer == nullptr || buffer->GetHeight() < 0 || buffer->GetWidth() < 0 ||
buffer->GetStride() < 0 || buffer->GetSize() == 0 || buffer->GetVirAddr() == nullptr) {
ROSEN_LOGE("RsRenderServiceUtil::DrawBuffer: buffer is not valid!");
return;
}
ColorGamut srcGamut = static_cast<ColorGamut>(buffer->GetSurfaceBufferColorGamut());
if (srcGamut != dstGamut) {
std::vector<uint8_t> newBuffer;
if (Detail::ConvertBufferColorGamut(newBuffer, buffer, srcGamut, dstGamut)) {
// use newBuffer to draw.
BufferDrawParameters params;
SkImageInfo imageInfo = Detail::GenerateSkImageInfo(buffer);
params.pixmap = SkPixmap(imageInfo, newBuffer.data(), buffer->GetStride());
Detail::FillDrawParameters(params, buffer, node);
params.onDisplay = isDrawnOnDisplay;
Draw(canvas, params, node);
return;
}
}
DrawBuffer(&canvas, buffer, node, isDrawnOnDisplay);
}
} // namespace Rosen
} // namespace OHOS
} // namespace OHOS

View File

@ -23,6 +23,7 @@
#include "common/rs_obj_abs_geometry.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkRect.h"
#include "pipeline/rs_surface_render_node.h"
#include "property/rs_transition_properties.h"
@ -30,6 +31,18 @@ namespace OHOS {
namespace Rosen {
struct BufferDrawParameters {
bool antiAlias = true;
bool onDisplay = true;
float alpha = 1.0f;
double widthScale = 1.0f;
double heightScale = 1.0f;
SkPixmap pixmap;
SkBitmap bitmap;
SkMatrix transform;
SkRect dstRect;
};
struct ComposeInfo {
IRect srcRect;
IRect dstRect;
@ -49,11 +62,13 @@ public:
std::vector<LayerInfoPtr>& layers, ComposeInfo info, RSSurfaceRenderNode* node = nullptr);
static void DrawBuffer(SkCanvas* canvas, sptr<OHOS::SurfaceBuffer> buffer, RSSurfaceRenderNode& node,
bool isDrawnOnDisplay = true);
static void DrawBuffer(SkCanvas& canvas, const sptr<OHOS::SurfaceBuffer>& buffer,
RSSurfaceRenderNode& node, ColorGamut dstGamut, bool isDrawnOnDisplay = true);
private:
static void DealAnimation(SkCanvas* canvas, SkPaint& paint, const RSProperties& property,
const std::unique_ptr<RSTransitionProperties>& transitionProperties);
static void Draw(SkCanvas& canvas, BufferDrawParameters& params, RSSurfaceRenderNode& node);
static void DealAnimation(SkCanvas& canvas, SkPaint& paint, RSSurfaceRenderNode& node);
static bool IsNeedClient(RSSurfaceRenderNode* node);
};
} // Rosen
} // OHOS
#endif
#endif

View File

@ -15,10 +15,8 @@
#include "rs_screen.h"
#include <algorithm>
#include <cinttypes>
#include "screen_manager/screen_types.h"
#include "string_utils.h"
namespace OHOS {

View File

@ -16,8 +16,6 @@
#include "rs_screen_manager.h"
#include "pipeline/rs_main_thread.h"
#include <cinttypes>
namespace OHOS {
namespace Rosen {
using namespace HiviewDFX;
@ -514,6 +512,7 @@ ScreenInfo RSScreenManager::QueryScreenInfo(ScreenId id) const
info.width = screen->Width();
info.height = screen->Height();
(void)screen->GetScreenColorGamut(info.colorGamut);
if (!screen->IsEnable()) {
info.state = ScreenState::DISABLED;

View File

@ -48,6 +48,7 @@ enum class ScreenState : uint8_t {
struct ScreenInfo {
uint32_t width = 0;
uint32_t height = 0;
ScreenColorGamut colorGamut = ScreenColorGamut::COLOR_GAMUT_SRGB;
ScreenState state = ScreenState::UNKNOWN;
};