mirror of
https://gitee.com/openharmony/graphic_graphic_2d
synced 2024-11-27 01:00:50 +00:00
!17232 HRP: Refactor pixelmap
Merge pull request !17232 from Podlesny Viktor/hrp_pixelmap
This commit is contained in:
commit
e88442f47d
@ -330,6 +330,12 @@ private:
|
||||
static uint64_t NowNano();
|
||||
static double Now();
|
||||
|
||||
static bool IsNoneMode();
|
||||
static bool IsReadMode();
|
||||
static bool IsReadEmulationMode();
|
||||
static bool IsWriteMode();
|
||||
static bool IsWriteEmulationMode();
|
||||
|
||||
static bool IsRecording();
|
||||
static bool IsPlaying();
|
||||
|
||||
|
@ -109,6 +109,31 @@ bool RSProfiler::IsBetaRecordEnabled()
|
||||
#endif
|
||||
}
|
||||
|
||||
bool RSProfiler::IsNoneMode()
|
||||
{
|
||||
return g_mode == Mode::NONE;
|
||||
}
|
||||
|
||||
bool RSProfiler::IsReadMode()
|
||||
{
|
||||
return g_mode == Mode::READ;
|
||||
}
|
||||
|
||||
bool RSProfiler::IsReadEmulationMode()
|
||||
{
|
||||
return g_mode == Mode::READ_EMUL;
|
||||
}
|
||||
|
||||
bool RSProfiler::IsWriteMode()
|
||||
{
|
||||
return g_mode == Mode::WRITE;
|
||||
}
|
||||
|
||||
bool RSProfiler::IsWriteEmulationMode()
|
||||
{
|
||||
return g_mode == Mode::WRITE_EMUL;
|
||||
}
|
||||
|
||||
uint32_t RSProfiler::GetCommandCount()
|
||||
{
|
||||
const uint32_t count = g_commandCount;
|
||||
|
@ -20,53 +20,293 @@
|
||||
|
||||
#include "media_errors.h"
|
||||
#include "pixel_map.h"
|
||||
#ifdef RS_PROFILER_SUPPORTS_PIXELMAP_YUV_EXT
|
||||
#include "pixel_yuv_ext.h"
|
||||
#else
|
||||
#include "pixel_yuv.h"
|
||||
#endif
|
||||
#include "rs_profiler.h"
|
||||
#include "rs_profiler_cache.h"
|
||||
#include "rs_profiler_log.h"
|
||||
#include "rs_profiler_utils.h"
|
||||
#include "rs_profiler_log.h"
|
||||
#include "rs_profiler_pixelmap.h"
|
||||
|
||||
#include "transaction/rs_marshalling_helper.h"
|
||||
#include "platform/common/rs_system_properties.h"
|
||||
|
||||
namespace OHOS::Media {
|
||||
namespace OHOS::Rosen {
|
||||
|
||||
static SurfaceBuffer* IncrementSurfaceBufferReference(sptr<SurfaceBuffer>& buffer)
|
||||
bool PixelMapStorage::IsSharedMemory(const PixelMap& map)
|
||||
{
|
||||
return IsSharedMemory(const_cast<PixelMap&>(map).GetAllocatorType());
|
||||
}
|
||||
|
||||
bool PixelMapStorage::IsSharedMemory(const PixelMemInfo& info)
|
||||
{
|
||||
return IsSharedMemory(info.allocatorType);
|
||||
}
|
||||
|
||||
bool PixelMapStorage::IsSharedMemory(AllocatorType type)
|
||||
{
|
||||
return type == AllocatorType::SHARE_MEM_ALLOC;
|
||||
}
|
||||
|
||||
bool PixelMapStorage::IsDmaMemory(const PixelMap& map)
|
||||
{
|
||||
return IsDmaMemory(const_cast<PixelMap&>(map).GetAllocatorType());
|
||||
}
|
||||
|
||||
bool PixelMapStorage::IsDmaMemory(const PixelMemInfo& info)
|
||||
{
|
||||
return IsDmaMemory(info.allocatorType);
|
||||
}
|
||||
|
||||
bool PixelMapStorage::IsDmaMemory(AllocatorType type)
|
||||
{
|
||||
return type == AllocatorType::DMA_ALLOC;
|
||||
}
|
||||
|
||||
void PixelMapStorage::Push(uint64_t id, const PixelMap& map)
|
||||
{
|
||||
if (IsDmaMemory(map)) {
|
||||
PushDmaMemory(id, map);
|
||||
} else if (IsSharedMemory(map)) {
|
||||
PushSharedMemory(id, map);
|
||||
}
|
||||
}
|
||||
|
||||
bool PixelMapStorage::Pull(uint64_t id, const ImageInfo& info, PixelMemInfo& memory, size_t& skipBytes)
|
||||
{
|
||||
skipBytes = 0u;
|
||||
if (IsSharedMemory(memory)) {
|
||||
return PullSharedMemory(id, info, memory, skipBytes);
|
||||
} else if (IsDmaMemory(memory)) {
|
||||
return PullDmaMemory(id, info, memory, skipBytes);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void PixelMapStorage::Push(uint64_t id, const ImageInfo& info, const PixelMemInfo& memory, size_t skipBytes)
|
||||
{
|
||||
if (IsSharedMemory(memory)) {
|
||||
PushSharedMemory(id, info, memory, skipBytes);
|
||||
} else if (IsDmaMemory(memory)) {
|
||||
PushDmaMemory(id, info, memory, skipBytes);
|
||||
}
|
||||
}
|
||||
|
||||
bool PixelMapStorage::PullSharedMemory(uint64_t id, const ImageInfo& info, PixelMemInfo& memory, size_t& skipBytes)
|
||||
{
|
||||
skipBytes = 0u;
|
||||
if (!ValidateBufferSize(memory)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto image = ImageCache::Get(id);
|
||||
if (!image) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memory.base = new uint8_t[memory.bufferSize];
|
||||
if (!memory.base) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CopyImageData(image, memory.base, memory.bufferSize)) {
|
||||
delete[] memory.base;
|
||||
memory.base = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
memory.context = nullptr;
|
||||
skipBytes = image->parcelSkipBytes;
|
||||
return true;
|
||||
}
|
||||
|
||||
void PixelMapStorage::PushSharedMemory(uint64_t id, const ImageInfo& info, const PixelMemInfo& memory, size_t skipBytes)
|
||||
{
|
||||
PushImage(id, GenerateImageData(info, memory), skipBytes);
|
||||
}
|
||||
|
||||
void PixelMapStorage::PushSharedMemory(uint64_t id, const PixelMap& map)
|
||||
{
|
||||
if (!map.GetFd()) {
|
||||
return;
|
||||
}
|
||||
|
||||
constexpr size_t skipBytes = 24u;
|
||||
const size_t size = const_cast<PixelMap&>(map).GetByteCount();
|
||||
if (auto image = MapImage(*reinterpret_cast<const int32_t*>(map.GetFd()), size, PROT_READ)) {
|
||||
PushImage(id, GenerateImageData(image, size, map), skipBytes);
|
||||
UnmapImage(image, size);
|
||||
}
|
||||
}
|
||||
|
||||
bool PixelMapStorage::PullDmaMemory(uint64_t id, const ImageInfo& info, PixelMemInfo& memory, size_t& skipBytes)
|
||||
{
|
||||
skipBytes = 0u;
|
||||
if (!ValidateBufferSize(memory)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto image = ImageCache::Get(id);
|
||||
if (!image) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto surfaceBuffer = SurfaceBuffer::Create();
|
||||
if (!surfaceBuffer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const BufferRequestConfig config = { .width = image->dmaWidth,
|
||||
.height = image->dmaHeight,
|
||||
.strideAlignment = image->dmaStride,
|
||||
.format = image->dmaFormat,
|
||||
.usage = image->dmaUsage };
|
||||
surfaceBuffer->Alloc(config);
|
||||
|
||||
memory.base = static_cast<uint8_t*>(surfaceBuffer->GetVirAddr());
|
||||
if (!CopyImageData(image, memory.base, image->dmaSize)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memory.context = IncrementSurfaceBufferReference(surfaceBuffer);
|
||||
skipBytes = image->parcelSkipBytes;
|
||||
return true;
|
||||
}
|
||||
|
||||
void PixelMapStorage::PushDmaMemory(uint64_t id, const ImageInfo& info, const PixelMemInfo& memory, size_t skipBytes)
|
||||
{
|
||||
auto surfaceBuffer = reinterpret_cast<SurfaceBuffer*>(memory.context);
|
||||
auto buffer = surfaceBuffer ? surfaceBuffer->GetBufferHandle() : nullptr;
|
||||
if (buffer) {
|
||||
const auto pixels = GenerateImageData(memory.base, buffer->size, memory.isAstc, GetBytesPerPixel(info));
|
||||
PushImage(id, pixels, skipBytes, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void PixelMapStorage::PushDmaMemory(uint64_t id, const PixelMap& map)
|
||||
{
|
||||
const auto surfaceBuffer = reinterpret_cast<SurfaceBuffer*>(map.GetFd());
|
||||
const auto buffer = surfaceBuffer ? surfaceBuffer->GetBufferHandle() : nullptr;
|
||||
if (!buffer) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto pixels =
|
||||
GenerateImageData(reinterpret_cast<const uint8_t*>(surfaceBuffer->GetVirAddr()), buffer->size, map);
|
||||
MessageParcel parcel;
|
||||
surfaceBuffer->WriteToMessageParcel(parcel);
|
||||
PushImage(id, pixels, parcel.GetReadableBytes(), buffer);
|
||||
}
|
||||
|
||||
void PixelMapStorage::PushImage(uint64_t id, const ImageData& data, size_t skipBytes, BufferHandle* buffer)
|
||||
{
|
||||
if (data.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (buffer && ((buffer->width == 0) || (buffer->height == 0))) {
|
||||
return;
|
||||
}
|
||||
|
||||
Image image;
|
||||
image.parcelSkipBytes = skipBytes;
|
||||
image.data = data;
|
||||
|
||||
if (buffer) {
|
||||
image.dmaSize = static_cast<size_t>(buffer->size);
|
||||
image.dmaWidth = buffer->width;
|
||||
image.dmaHeight = buffer->height;
|
||||
image.dmaStride = buffer->stride;
|
||||
image.dmaFormat = buffer->format;
|
||||
image.dmaUsage = buffer->usage;
|
||||
}
|
||||
|
||||
ImageCache::Add(id, std::move(image));
|
||||
}
|
||||
|
||||
bool PixelMapStorage::ValidateBufferSize(const PixelMemInfo& memory)
|
||||
{
|
||||
return (memory.bufferSize > 0) && (static_cast<size_t>(memory.bufferSize) <= Image::maxSize);
|
||||
}
|
||||
|
||||
uint32_t PixelMapStorage::GetBytesPerPixel(const ImageInfo& info)
|
||||
{
|
||||
const auto rowPitch = PixelMap::GetRGBxRowDataSize(info);
|
||||
return (rowPitch > 0) ? static_cast<uint32_t>(rowPitch / info.size.width) : 0u;
|
||||
}
|
||||
|
||||
uint8_t* PixelMapStorage::MapImage(int32_t file, size_t size, int32_t flags)
|
||||
{
|
||||
auto image = ::mmap(nullptr, size, flags, MAP_SHARED, file, 0);
|
||||
return (image != MAP_FAILED) ? reinterpret_cast<uint8_t*>(image) : nullptr; // NOLINT
|
||||
}
|
||||
|
||||
void PixelMapStorage::UnmapImage(void* image, size_t size)
|
||||
{
|
||||
if (IsDataValid(image, size)) {
|
||||
::munmap(image, size);
|
||||
}
|
||||
}
|
||||
|
||||
SurfaceBuffer* PixelMapStorage::IncrementSurfaceBufferReference(sptr<SurfaceBuffer>& buffer)
|
||||
{
|
||||
if (auto object = buffer.GetRefPtr()) {
|
||||
auto ref = reinterpret_cast<OHOS::RefBase*>(object);
|
||||
ref->IncStrongRef(ref);
|
||||
object->IncStrongRef(object);
|
||||
return object;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static bool IsDataValid(const void* data, size_t size)
|
||||
bool PixelMapStorage::IsDataValid(const void* data, size_t size)
|
||||
{
|
||||
return data && (size > 0);
|
||||
}
|
||||
|
||||
static std::vector<uint8_t> GenerateRawCopy(const uint8_t* data, size_t size)
|
||||
bool PixelMapStorage::CopyImageData(const uint8_t* srcImage, size_t srcSize, uint8_t* dstImage, size_t dstSize)
|
||||
{
|
||||
std::vector<uint8_t> out;
|
||||
if (!srcImage || !dstImage || (srcSize == 0) || (dstSize == 0) || (srcSize > dstSize)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dstSize == srcSize) {
|
||||
return Utils::Move(dstImage, dstSize, srcImage, srcSize);
|
||||
}
|
||||
|
||||
for (size_t offset = 0; offset < dstSize;) {
|
||||
const size_t size = std::min(dstSize - offset, srcSize);
|
||||
if (!Utils::Move(dstImage + offset, size, srcImage, size)) {
|
||||
return false;
|
||||
}
|
||||
offset += size;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PixelMapStorage::CopyImageData(const ImageData& data, uint8_t* dstImage, size_t dstSize)
|
||||
{
|
||||
return CopyImageData(data.data(), data.size(), dstImage, dstSize);
|
||||
}
|
||||
|
||||
bool PixelMapStorage::CopyImageData(const Image* image, uint8_t* dstImage, size_t dstSize)
|
||||
{
|
||||
return image ? CopyImageData(image->data, dstImage, dstSize) : false;
|
||||
}
|
||||
|
||||
ImageData PixelMapStorage::GenerateRawCopy(const uint8_t* data, size_t size)
|
||||
{
|
||||
ImageData out;
|
||||
if (IsDataValid(data, size)) {
|
||||
out.insert(out.end(), data, data + size);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
static std::vector<uint8_t> GenerateMiniatureAstc(const uint8_t* data, size_t size)
|
||||
ImageData PixelMapStorage::GenerateMiniatureAstc(const uint8_t* data, size_t size)
|
||||
{
|
||||
constexpr uint32_t astcBytesPerPixel = 16u;
|
||||
return GenerateRawCopy(data, astcBytesPerPixel);
|
||||
}
|
||||
|
||||
static std::vector<uint8_t> GenerateMiniature(const uint8_t* data, size_t size, uint32_t pixelBytes)
|
||||
ImageData PixelMapStorage::GenerateMiniature(const uint8_t* data, size_t size, uint32_t pixelBytes)
|
||||
{
|
||||
if (!IsDataValid(data, size)) {
|
||||
return {};
|
||||
@ -88,516 +328,36 @@ static std::vector<uint8_t> GenerateMiniature(const uint8_t* data, size_t size,
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<uint8_t> out(bytesPerPixel, 0);
|
||||
ImageData out(bytesPerPixel, 0);
|
||||
for (uint32_t i = 0; i < bytesPerPixel; i++) {
|
||||
out[i] = static_cast<uint8_t>(averageValue[i] / sampleCount);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
static std::vector<uint8_t> GenerateImageData(const uint8_t* data, size_t size, bool isAstc, uint32_t pixelBytes)
|
||||
ImageData PixelMapStorage::GenerateImageData(const uint8_t* data, size_t size, const PixelMap& map)
|
||||
{
|
||||
if (!Rosen::RSProfiler::IsBetaRecordEnabled()) {
|
||||
return GenerateImageData(
|
||||
data, size, const_cast<PixelMap&>(map).IsAstc(), const_cast<PixelMap&>(map).GetPixelBytes());
|
||||
}
|
||||
|
||||
ImageData PixelMapStorage::GenerateImageData(const ImageInfo& info, const PixelMemInfo& memory)
|
||||
{
|
||||
return GenerateImageData(memory.base, memory.bufferSize, memory.isAstc, GetBytesPerPixel(info));
|
||||
}
|
||||
|
||||
ImageData PixelMapStorage::GenerateImageData(const uint8_t* data, size_t size, bool isAstc, uint32_t pixelBytes)
|
||||
{
|
||||
if (!RSProfiler::IsBetaRecordEnabled()) {
|
||||
return GenerateRawCopy(data, size);
|
||||
}
|
||||
|
||||
return isAstc ? GenerateMiniatureAstc(data, size) : GenerateMiniature(data, size, pixelBytes);
|
||||
}
|
||||
|
||||
static std::vector<uint8_t> GenerateImageData(const uint8_t* data, size_t size, PixelMap& map)
|
||||
{
|
||||
return GenerateImageData(data, size, map.IsAstc(), map.GetPixelBytes());
|
||||
}
|
||||
|
||||
static bool CopyImageData(const uint8_t* srcImage, size_t srcSize, uint8_t* dstImage, size_t dstSize)
|
||||
{
|
||||
if (!srcImage || !dstImage || (srcSize == 0) || (dstSize == 0) || (srcSize > dstSize)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dstSize == srcSize) {
|
||||
return Rosen::Utils::Move(dstImage, dstSize, srcImage, srcSize);
|
||||
}
|
||||
|
||||
for (size_t offset = 0; offset < dstSize;) {
|
||||
const size_t size = std::min(dstSize - offset, srcSize);
|
||||
if (!Rosen::Utils::Move(dstImage + offset, size, srcImage, size)) {
|
||||
return false;
|
||||
}
|
||||
offset += size;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool CopyImageData(const std::vector<uint8_t>& data, uint8_t* dstImage, size_t dstSize)
|
||||
{
|
||||
return CopyImageData(data.data(), data.size(), dstImage, dstSize);
|
||||
}
|
||||
|
||||
static bool CopyImageData(const Rosen::Image* image, uint8_t* dstImage, size_t dstSize)
|
||||
{
|
||||
return image ? CopyImageData(image->data, dstImage, dstSize) : false;
|
||||
}
|
||||
|
||||
struct UnmarshallingContext {
|
||||
public:
|
||||
static constexpr int headerLength = 24; // NOLINT
|
||||
|
||||
public:
|
||||
explicit UnmarshallingContext(Parcel& parcel) : parcel(parcel) {}
|
||||
|
||||
bool GatherImageFromFile(const Rosen::Image* image)
|
||||
{
|
||||
if ((size <= 0) || (size > Rosen::Image::maxSize)) {
|
||||
return false;
|
||||
}
|
||||
if (!image) {
|
||||
return false;
|
||||
}
|
||||
|
||||
allocType = AllocatorType::HEAP_ALLOC;
|
||||
|
||||
base = new (std::nothrow) uint8_t[size];
|
||||
if (!base) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CopyImageData(image, base, size)) {
|
||||
delete[] base;
|
||||
base = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
context = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GatherDmaImageFromFile(const Rosen::Image* image)
|
||||
{
|
||||
if ((size <= 0) || (size > Rosen::Image::maxSize)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
sptr<SurfaceBuffer> surfaceBuffer = SurfaceBuffer::Create();
|
||||
if (!surfaceBuffer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const BufferRequestConfig config = { .width = image->dmaWidth,
|
||||
.height = image->dmaHeight,
|
||||
.strideAlignment = image->dmaStride,
|
||||
.format = image->dmaFormat,
|
||||
.usage = image->dmaUsage };
|
||||
surfaceBuffer->Alloc(config);
|
||||
|
||||
base = static_cast<uint8_t*>(surfaceBuffer->GetVirAddr());
|
||||
if (base && CopyImageData(image, base, image->dmaSize)) {
|
||||
context = IncrementSurfaceBufferReference(surfaceBuffer);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsAshmemSizeValid(int32_t file) const
|
||||
{
|
||||
return astc || (static_cast<int32_t>(size) == AshmemGetSize(file));
|
||||
}
|
||||
|
||||
bool IsYUV() const
|
||||
{
|
||||
return (info.pixelFormat == PixelFormat::NV12) || (info.pixelFormat == PixelFormat::NV21) ||
|
||||
(info.pixelFormat == PixelFormat::YCBCR_P010) || (info.pixelFormat == PixelFormat::YCRCB_P010);
|
||||
}
|
||||
|
||||
bool IsASTC() const
|
||||
{
|
||||
return (info.pixelFormat == PixelFormat::ASTC_4x4) || (info.pixelFormat == PixelFormat::ASTC_6x6) ||
|
||||
(info.pixelFormat == PixelFormat::ASTC_8x8);
|
||||
}
|
||||
|
||||
bool IsRGBA() const
|
||||
{
|
||||
return (info.pixelFormat == PixelFormat::ARGB_8888) || (info.pixelFormat == PixelFormat::BGRA_8888) ||
|
||||
(info.pixelFormat == PixelFormat::RGBA_8888) || (info.pixelFormat == PixelFormat::RGBA_1010102) ||
|
||||
(info.pixelFormat == PixelFormat::CMYK) || (info.pixelFormat == PixelFormat::RGBA_F16) ||
|
||||
(info.pixelFormat == PixelFormat::RGBA_U16);
|
||||
}
|
||||
|
||||
bool IsRGB() const
|
||||
{
|
||||
return (info.pixelFormat == PixelFormat::RGB_888) || (info.pixelFormat == PixelFormat::RGB_565);
|
||||
}
|
||||
|
||||
bool IsR8() const
|
||||
{
|
||||
return (info.pixelFormat == PixelFormat::ALPHA_8);
|
||||
}
|
||||
|
||||
bool IsFormatValid() const
|
||||
{
|
||||
return IsR8() || IsRGB() || IsRGBA() || IsASTC() || IsYUV();
|
||||
}
|
||||
|
||||
bool IsSizeValid() const
|
||||
{
|
||||
const auto rawSize = static_cast<size_t>(rowPitch * info.size.height);
|
||||
return (astc || IsYUV() || (size == rawSize) || (info.pixelFormat == PixelFormat::RGBA_F16));
|
||||
}
|
||||
|
||||
public:
|
||||
Parcel& parcel;
|
||||
std::unique_ptr<PixelMap> map;
|
||||
ImageInfo info;
|
||||
bool editable = false;
|
||||
bool astc = false;
|
||||
int32_t csm = 0;
|
||||
uint32_t versionId = 0u;
|
||||
AllocatorType allocType = AllocatorType::DEFAULT;
|
||||
size_t rowPitch = 0;
|
||||
size_t size = 0;
|
||||
uint8_t* base = nullptr;
|
||||
void* context = nullptr;
|
||||
};
|
||||
|
||||
// This class has to be 'reimplemented' here to get access to the PixelMap's private functions.
|
||||
// It works ONLY thanks to the 'friend class ImageSource' in PixelMap.
|
||||
class ImageSource {
|
||||
public:
|
||||
static PixelMap* Unmarshal(Parcel& parcel);
|
||||
static bool Marshal(Parcel& parcel, PixelMap& map);
|
||||
|
||||
private:
|
||||
static void CacheImage(
|
||||
uint64_t id, const std::vector<uint8_t>& data, size_t skipBytes, BufferHandle* bufferHandle = nullptr);
|
||||
static Rosen::Image* GetCachedImage(uint64_t id);
|
||||
|
||||
static uint8_t* MapImage(int32_t file, size_t size, int32_t flags);
|
||||
static void UnmapImage(void* image, size_t size);
|
||||
|
||||
static void OnClientMarshalling(PixelMap& map, uint64_t id);
|
||||
|
||||
static bool InitUnmarshalling(UnmarshallingContext& context);
|
||||
static bool UnmarshalFromSharedMemory(UnmarshallingContext& context, uint64_t id);
|
||||
static bool UnmarshalFromDMA(UnmarshallingContext& context, uint64_t id);
|
||||
static bool UnmarshalFromData(UnmarshallingContext& context);
|
||||
static PixelMap* FinalizeUnmarshalling(UnmarshallingContext& context);
|
||||
};
|
||||
|
||||
void ImageSource::CacheImage(
|
||||
uint64_t id, const std::vector<uint8_t>& data, size_t skipBytes, BufferHandle* bufferHandle)
|
||||
{
|
||||
if (data.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (bufferHandle && ((bufferHandle->width == 0) || (bufferHandle->height == 0))) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Rosen::RSProfiler::GetMode() != Rosen::Mode::WRITE && Rosen::RSProfiler::GetMode() != Rosen::Mode::WRITE_EMUL) {
|
||||
return;
|
||||
}
|
||||
|
||||
Rosen::Image image;
|
||||
image.data = data;
|
||||
|
||||
if (bufferHandle) {
|
||||
image.dmaSize = static_cast<size_t>(bufferHandle->size);
|
||||
image.dmaWidth = bufferHandle->width;
|
||||
image.dmaHeight = bufferHandle->height;
|
||||
image.dmaStride = bufferHandle->stride;
|
||||
image.dmaFormat = bufferHandle->format;
|
||||
image.dmaUsage = bufferHandle->usage;
|
||||
}
|
||||
|
||||
image.parcelSkipBytes = skipBytes;
|
||||
Rosen::ImageCache::Add(id, std::move(image));
|
||||
}
|
||||
|
||||
Rosen::Image* ImageSource::GetCachedImage(uint64_t id)
|
||||
{
|
||||
return Rosen::ImageCache::Get(id);
|
||||
}
|
||||
|
||||
uint8_t* ImageSource::MapImage(int32_t file, size_t size, int32_t flags)
|
||||
{
|
||||
auto image = ::mmap(nullptr, size, flags, MAP_SHARED, file, 0);
|
||||
return (image != MAP_FAILED) ? reinterpret_cast<uint8_t*>(image) : nullptr; // NOLINT
|
||||
}
|
||||
|
||||
void ImageSource::UnmapImage(void* image, size_t size)
|
||||
{
|
||||
if (IsDataValid(image, size)) {
|
||||
::munmap(image, size);
|
||||
}
|
||||
}
|
||||
|
||||
bool ImageSource::InitUnmarshalling(UnmarshallingContext& context)
|
||||
{
|
||||
if (!PixelMap::ReadImageInfo(context.parcel, context.info)) {
|
||||
HRPE("Unmarshal: PixelMap::ReadImageInfo failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (context.IsYUV()) {
|
||||
#ifdef RS_PROFILER_SUPPORTS_PIXELMAP_YUV_EXT
|
||||
context.map = std::make_unique<PixelYuvExt>();
|
||||
HRPI("Unmarshal: PixelYuvExt creation in progress...");
|
||||
#else
|
||||
context.map = std::make_unique<PixelYuv>();
|
||||
HRPI("Unmarshal: PixelYuv creation in progress...");
|
||||
#endif
|
||||
} else {
|
||||
context.map = std::make_unique<PixelMap>();
|
||||
HRPI("Unmarshal: PixelMap creation in progress...");
|
||||
}
|
||||
|
||||
if (!context.map) {
|
||||
HRPE("Unmarshal: Pixel map creation failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
context.editable = context.parcel.ReadBool();
|
||||
context.astc = context.parcel.ReadBool();
|
||||
context.allocType = static_cast<AllocatorType>(context.parcel.ReadInt32());
|
||||
context.csm = context.parcel.ReadInt32();
|
||||
context.rowPitch = static_cast<size_t>(context.parcel.ReadInt32());
|
||||
context.versionId = context.parcel.ReadUint32();
|
||||
context.size = static_cast<size_t>(context.parcel.ReadInt32());
|
||||
|
||||
if (!context.IsFormatValid()) {
|
||||
HRPE("Unmarshal: Invalid pixel format");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!context.IsSizeValid()) {
|
||||
HRPE("Unmarshal: Invalid size");
|
||||
return false;
|
||||
}
|
||||
|
||||
context.map->SetEditable(context.editable);
|
||||
context.map->SetAstc(context.astc);
|
||||
context.map->SetVersionId(context.versionId);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ImageSource::UnmarshalFromSharedMemory(UnmarshallingContext& context, uint64_t id)
|
||||
{
|
||||
constexpr int32_t invalidFile = -1;
|
||||
const auto file =
|
||||
Rosen::RSProfiler::IsParcelMock(context.parcel) ? invalidFile : PixelMap::ReadFileDescriptor(context.parcel);
|
||||
if (file < 0) {
|
||||
if (auto image = GetCachedImage(id)) {
|
||||
if (context.GatherImageFromFile(image)) {
|
||||
context.parcel.SkipBytes(UnmarshallingContext::headerLength);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
HRPE("Unmarshal: SharedMemory: Cached image fetch failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!context.IsAshmemSizeValid(file)) {
|
||||
::close(file);
|
||||
HRPE("Unmarshal: SharedMemory: Invalid file size");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto image = MapImage(file, context.size, PROT_READ | PROT_WRITE);
|
||||
if (!image) {
|
||||
image = MapImage(file, context.size, PROT_READ);
|
||||
}
|
||||
|
||||
if (!image) {
|
||||
::close(file);
|
||||
HRPE("Unmarshal: SharedMemory: Cannot map an image from a file");
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto imageData = GenerateImageData(image, context.size, *context.map);
|
||||
CacheImage(id, imageData, UnmarshallingContext::headerLength);
|
||||
|
||||
context.context = new int32_t();
|
||||
if (!context.context) {
|
||||
UnmapImage(image, context.size);
|
||||
::close(file);
|
||||
HRPE("Unmarshal: SharedMemory: Cannot allocate memory for a file handle");
|
||||
return false;
|
||||
}
|
||||
*static_cast<int32_t*>(context.context) = file;
|
||||
context.base = image;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ImageSource::UnmarshalFromDMA(UnmarshallingContext& context, uint64_t id)
|
||||
{
|
||||
auto image = Rosen::RSProfiler::IsParcelMock(context.parcel) ? GetCachedImage(id) : nullptr;
|
||||
if (image) {
|
||||
// REPLAY IMAGE
|
||||
context.parcel.SkipBytes(image->parcelSkipBytes);
|
||||
return context.GatherDmaImageFromFile(image);
|
||||
}
|
||||
|
||||
const size_t readPosition = context.parcel.GetReadPosition();
|
||||
|
||||
sptr<SurfaceBuffer> surfaceBuffer = SurfaceBuffer::Create();
|
||||
surfaceBuffer->ReadFromMessageParcel(static_cast<MessageParcel&>(context.parcel));
|
||||
context.base = static_cast<uint8_t*>(surfaceBuffer->GetVirAddr());
|
||||
context.context = IncrementSurfaceBufferReference(surfaceBuffer);
|
||||
|
||||
if (auto bufferHandle = surfaceBuffer->GetBufferHandle()) {
|
||||
// RECORD IMAGE
|
||||
const auto imageData = GenerateImageData(context.base, bufferHandle->size, *context.map);
|
||||
CacheImage(id, imageData, context.parcel.GetReadPosition() - readPosition, bufferHandle);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ImageSource::UnmarshalFromData(UnmarshallingContext& context)
|
||||
{
|
||||
context.base = PixelMap::ReadImageData(context.parcel, static_cast<int32_t>(context.size));
|
||||
if (!context.base) {
|
||||
HRPE("Unmarshal: PixelMap::ReadImageData failed");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
PixelMap* ImageSource::FinalizeUnmarshalling(UnmarshallingContext& context)
|
||||
{
|
||||
if (context.map->SetImageInfo(context.info) != SUCCESS) {
|
||||
if (context.map->freePixelMapProc_) {
|
||||
context.map->freePixelMapProc_(context.base, context.context, context.size);
|
||||
}
|
||||
PixelMap::ReleaseMemory(context.allocType, context.base, context.context, context.size);
|
||||
if (context.context && (context.allocType == AllocatorType::SHARE_MEM_ALLOC)) {
|
||||
delete static_cast<int32_t*>(context.context);
|
||||
}
|
||||
|
||||
HRPE("Unmarshal: PixelMap::SetImageInfo failed");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
context.map->SetPixelsAddr(context.base, context.context, context.size, context.allocType, nullptr);
|
||||
|
||||
if (!context.map->ReadTransformData(context.parcel, context.map.get())) {
|
||||
HRPE("Unmarshal: PixelMap::ReadTransformData failed");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!context.map->ReadAstcRealSize(context.parcel, context.map.get())) {
|
||||
HRPE("Unmarshal: PixelMap::ReadAstcRealSize failed");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!context.map->ReadYuvDataInfoFromParcel(context.parcel, context.map.get())) {
|
||||
HRPE("Unmarshal: PixelMap::ReadYuvDataInfoFromParcel failed");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
HRPI("Unmarshal: Done");
|
||||
return context.map.release();
|
||||
}
|
||||
|
||||
PixelMap* ImageSource::Unmarshal(Parcel& parcel)
|
||||
{
|
||||
const uint64_t id = parcel.ReadUint64();
|
||||
UnmarshallingContext context { parcel };
|
||||
|
||||
if (!InitUnmarshalling(context)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(A_PLATFORM)
|
||||
if (context.allocType == AllocatorType::SHARE_MEM_ALLOC) {
|
||||
if (!UnmarshalFromSharedMemory(context, id)) {
|
||||
return nullptr;
|
||||
}
|
||||
} else if (context.allocType == AllocatorType::DMA_ALLOC) {
|
||||
if (!UnmarshalFromDMA(context, id)) {
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
if (!UnmarshalFromData(context)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (!UnmarshalFromData(context)) {
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
return FinalizeUnmarshalling(context);
|
||||
}
|
||||
|
||||
void ImageSource::OnClientMarshalling(Media::PixelMap& map, uint64_t id)
|
||||
{
|
||||
if (Rosen::RSProfiler::IsSharedMemoryEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto descriptor = map.GetFd();
|
||||
if (!descriptor) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (map.GetAllocatorType() == AllocatorType::DMA_ALLOC) {
|
||||
auto surfaceBuffer = reinterpret_cast<SurfaceBuffer*>(descriptor);
|
||||
if (auto bufferHandle = surfaceBuffer->GetBufferHandle()) {
|
||||
const auto imageData = GenerateImageData(
|
||||
reinterpret_cast<const uint8_t*>(surfaceBuffer->GetVirAddr()), bufferHandle->size, map);
|
||||
MessageParcel parcel2;
|
||||
surfaceBuffer->WriteToMessageParcel(parcel2);
|
||||
size_t bufferHandleSize = parcel2.GetReadableBytes();
|
||||
CacheImage(id, imageData, bufferHandleSize, bufferHandle);
|
||||
}
|
||||
} else {
|
||||
const size_t size = map.isAstc_ ? map.pixelsSize_ :
|
||||
static_cast<size_t>(map.rowDataSize_ * map.imageInfo_.size.height);
|
||||
if (auto image = MapImage(*reinterpret_cast<const int32_t*>(map.GetFd()), size, PROT_READ)) {
|
||||
const auto imageData = GenerateImageData(image, size, map);
|
||||
CacheImage(id, imageData, UnmarshallingContext::headerLength);
|
||||
UnmapImage(image, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ImageSource::Marshal(Parcel& parcel, Media::PixelMap& map)
|
||||
{
|
||||
const uint64_t id = Rosen::ImageCache::New();
|
||||
if (!parcel.WriteUint64(id) || !map.Marshalling(parcel)) {
|
||||
return false;
|
||||
}
|
||||
OnClientMarshalling(map, id);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace OHOS::Media
|
||||
|
||||
namespace OHOS::Rosen {
|
||||
|
||||
using PixelMapHelper = Media::ImageSource;
|
||||
|
||||
Media::PixelMap* RSProfiler::UnmarshalPixelMap(Parcel& parcel)
|
||||
{
|
||||
bool isClientEnabled = false;
|
||||
if (!parcel.ReadBool(isClientEnabled)) {
|
||||
HRPE("Unable to read is_client_enabled for image");
|
||||
return nullptr;
|
||||
}
|
||||
if (!isClientEnabled) {
|
||||
return Media::PixelMap::Unmarshalling(parcel);
|
||||
}
|
||||
|
||||
return PixelMapHelper::Unmarshal(parcel);
|
||||
}
|
||||
|
||||
bool RSProfiler::SkipPixelMap(Parcel& parcel)
|
||||
{
|
||||
if (RSProfiler::IsEnabled() && RSProfiler::GetMode() == Mode::WRITE) {
|
||||
if (IsEnabled() && IsWriteMode()) {
|
||||
std::shared_ptr<Media::PixelMap> pixelMap;
|
||||
RSMarshallingHelper::Unmarshalling(parcel, pixelMap);
|
||||
return true;
|
||||
@ -611,17 +371,62 @@ bool RSProfiler::MarshalPixelMap(Parcel& parcel, const std::shared_ptr<Media::Pi
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isClientEnabled = RSSystemProperties::GetProfilerEnabled();
|
||||
if (!parcel.WriteBool(isClientEnabled)) {
|
||||
HRPE("Unable to write is_client_enabled for image");
|
||||
const bool profilerEnabled = RSSystemProperties::GetProfilerEnabled();
|
||||
if (!parcel.WriteBool(profilerEnabled)) {
|
||||
HRPE("MarshalPixelMap: Unable to write profilerEnabled");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isClientEnabled) {
|
||||
if (!profilerEnabled) {
|
||||
return map->Marshalling(parcel);
|
||||
}
|
||||
|
||||
return PixelMapHelper::Marshal(parcel, *map);
|
||||
const uint64_t id = ImageCache::New();
|
||||
if (!parcel.WriteUint64(id) || !map->Marshalling(parcel)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsSharedMemoryEnabled() && (IsWriteMode() || IsWriteEmulationMode())) {
|
||||
PixelMapStorage::Push(id, *map);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Media::PixelMap* RSProfiler::UnmarshalPixelMap(Parcel& parcel)
|
||||
{
|
||||
bool profilerEnabled = false;
|
||||
if (!parcel.ReadBool(profilerEnabled)) {
|
||||
HRPE("UnmarshalPixelMap: Unable to read profilerEnabled");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!profilerEnabled) {
|
||||
return PixelMap::Unmarshalling(parcel);
|
||||
}
|
||||
|
||||
const uint64_t id = parcel.ReadUint64();
|
||||
|
||||
ImageInfo info;
|
||||
PixelMemInfo memory;
|
||||
PIXEL_MAP_ERR error;
|
||||
auto map = PixelMap::StartUnmarshalling(parcel, info, memory, error);
|
||||
|
||||
size_t skipBytes = 0u;
|
||||
if (PixelMapStorage::Pull(id, info, memory, skipBytes)) {
|
||||
parcel.SkipBytes(skipBytes);
|
||||
return PixelMap::FinishUnmarshalling(map, parcel, info, memory, error);
|
||||
}
|
||||
|
||||
const auto parcelPosition = parcel.GetReadPosition();
|
||||
if (map && !PixelMap::ReadMemInfoFromParcel(parcel, memory, error)) {
|
||||
delete map;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (IsWriteMode() || IsWriteEmulationMode()) {
|
||||
PixelMapStorage::Push(id, info, memory, parcel.GetReadPosition() - parcelPosition);
|
||||
}
|
||||
return PixelMap::FinishUnmarshalling(map, parcel, info, memory, error);
|
||||
}
|
||||
|
||||
} // namespace OHOS::Rosen
|
80
rosen/modules/render_service_profiler/rs_profiler_pixelmap.h
Normal file
80
rosen/modules/render_service_profiler/rs_profiler_pixelmap.h
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (C) 2025 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef HRP_PIXELMAP_H
|
||||
#define HRP_PIXELMAP_H
|
||||
|
||||
namespace OHOS::Rosen {
|
||||
|
||||
using OHOS::sptr;
|
||||
using OHOS::SurfaceBuffer;
|
||||
using OHOS::Media::ImageInfo;
|
||||
using OHOS::Media::PIXEL_MAP_ERR;
|
||||
using OHOS::Media::PixelMap;
|
||||
using OHOS::Media::PixelMemInfo;
|
||||
using OHOS::Media::AllocatorType;
|
||||
|
||||
using ImageData = std::vector<uint8_t>;
|
||||
|
||||
class PixelMapStorage final {
|
||||
public:
|
||||
static bool Pull(uint64_t id, const ImageInfo& info, PixelMemInfo& memory, size_t& skipBytes);
|
||||
static void Push(uint64_t id, const ImageInfo& info, const PixelMemInfo& memory, size_t skipBytes);
|
||||
|
||||
static void Push(uint64_t id, const PixelMap& map);
|
||||
|
||||
private:
|
||||
static bool PullSharedMemory(uint64_t id, const ImageInfo& info, PixelMemInfo& memory, size_t& skipBytes);
|
||||
static void PushSharedMemory(uint64_t id, const ImageInfo& info, const PixelMemInfo& memory, size_t skipBytes);
|
||||
static void PushSharedMemory(uint64_t id, const PixelMap& map);
|
||||
|
||||
static bool PullDmaMemory(uint64_t id, const ImageInfo& info, PixelMemInfo& memory, size_t& skipBytes);
|
||||
static void PushDmaMemory(uint64_t id, const ImageInfo& info, const PixelMemInfo& memory, size_t skipBytes);
|
||||
static void PushDmaMemory(uint64_t id, const PixelMap& map);
|
||||
|
||||
static void PushImage(uint64_t id, const ImageData& data, size_t skipBytes, BufferHandle* buffer = nullptr);
|
||||
|
||||
static bool IsSharedMemory(const PixelMap& map);
|
||||
static bool IsSharedMemory(const PixelMemInfo& memory);
|
||||
static bool IsSharedMemory(AllocatorType type);
|
||||
static bool IsDmaMemory(const PixelMap& map);
|
||||
static bool IsDmaMemory(const PixelMemInfo& memory);
|
||||
static bool IsDmaMemory(AllocatorType type);
|
||||
|
||||
static bool ValidateBufferSize(const PixelMemInfo& memory);
|
||||
static uint32_t GetBytesPerPixel(const ImageInfo& info);
|
||||
|
||||
static uint8_t* MapImage(int32_t file, size_t size, int32_t flags);
|
||||
static void UnmapImage(void* image, size_t size);
|
||||
|
||||
static SurfaceBuffer* IncrementSurfaceBufferReference(sptr<SurfaceBuffer>& buffer);
|
||||
|
||||
static bool IsDataValid(const void* data, size_t size);
|
||||
|
||||
static bool CopyImageData(const uint8_t* srcImage, size_t srcSize, uint8_t* dstImage, size_t dstSize);
|
||||
static bool CopyImageData(const ImageData& data, uint8_t* dstImage, size_t dstSize);
|
||||
static bool CopyImageData(const Image* image, uint8_t* dstImage, size_t dstSize);
|
||||
|
||||
static ImageData GenerateRawCopy(const uint8_t* data, size_t size);
|
||||
static ImageData GenerateMiniatureAstc(const uint8_t* data, size_t size);
|
||||
static ImageData GenerateMiniature(const uint8_t* data, size_t size, uint32_t pixelBytes);
|
||||
static ImageData GenerateImageData(const uint8_t* data, size_t size, const PixelMap& map);
|
||||
static ImageData GenerateImageData(const ImageInfo& info, const PixelMemInfo& memory);
|
||||
static ImageData GenerateImageData(const uint8_t* data, size_t size, bool isAstc, uint32_t pixelBytes);
|
||||
};
|
||||
|
||||
} // OHOS::Rosen
|
||||
|
||||
#endif // HRP_PIXELMAP_H
|
Loading…
Reference in New Issue
Block a user