From d7e45e4fb521ae9b5d71e07f621353ddde0687da Mon Sep 17 00:00:00 2001 From: Nolan Scobie Date: Thu, 5 Jan 2023 16:04:58 -0500 Subject: [PATCH] Remove RecordingCanvas's reliance on Skia's private SkTemplates.h SkAutoTMalloc was previously used through some transitive inclusion of SkTemplates.h. Skia is trying to move these private types into an internal namespace to address leakage, so this usage must be removed first. AutoTMalloc has the same API surface as SkAutoTMalloc, but is not the same due to SkAutoTMalloc delegating most of its work to other private Skia dependencies and had to be rewritten. AutoTMalloc is declared in utils/AutoMalloc.h since there are other "AutoMalloc-like" variants that will be needed in HWUI to replace other Skia types. Changes in include ordering are from required clang reformatting. Bug: 264403827 Test: existing presubmits (should be a drop-in replacement) Change-Id: I1763ce0a643ba3e2f7be58e860dbdf08e3ba07bc --- libs/hwui/RecordingCanvas.h | 20 ++++---- libs/hwui/utils/AutoMalloc.h | 94 ++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 9 deletions(-) create mode 100644 libs/hwui/utils/AutoMalloc.h diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h index 2539694a73eef..b7d4dc90f4293 100644 --- a/libs/hwui/RecordingCanvas.h +++ b/libs/hwui/RecordingCanvas.h @@ -16,11 +16,13 @@ #pragma once -#include "CanvasTransform.h" -#include "hwui/Bitmap.h" -#include "utils/Macros.h" -#include "utils/TypeLogic.h" +#include +#include +#include +#include + +#include "CanvasTransform.h" #include "SkCanvas.h" #include "SkCanvasVirtualEnforcer.h" #include "SkDrawable.h" @@ -28,11 +30,11 @@ #include "SkPaint.h" #include "SkPath.h" #include "SkRect.h" - +#include "hwui/Bitmap.h" #include "pipeline/skia/AnimatedDrawables.h" - -#include -#include +#include "utils/AutoMalloc.h" +#include "utils/Macros.h" +#include "utils/TypeLogic.h" enum class SkBlendMode; class SkRRect; @@ -145,7 +147,7 @@ private: template void map(const Fn[], Args...) const; - SkAutoTMalloc fBytes; + AutoTMalloc fBytes; size_t fUsed = 0; size_t fReserved = 0; diff --git a/libs/hwui/utils/AutoMalloc.h b/libs/hwui/utils/AutoMalloc.h new file mode 100644 index 0000000000000..05f5e9f241336 --- /dev/null +++ b/libs/hwui/utils/AutoMalloc.h @@ -0,0 +1,94 @@ +/** + * Copyright (C) 2023 The Android Open Source Project + * + * 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. + */ + +#pragma once + +#include +#include +#include + +namespace android { +namespace uirenderer { + +/** Manages an array of T elements, freeing the array in the destructor. + * Does NOT call any constructors/destructors on T (T must be POD). + */ +template ::value && + std::is_trivially_destructible::value>> +class AutoTMalloc { +public: + /** Takes ownership of the ptr. The ptr must be a value which can be passed to std::free. */ + explicit AutoTMalloc(T* ptr = nullptr) : fPtr(ptr) {} + + /** Allocates space for 'count' Ts. */ + explicit AutoTMalloc(size_t count) : fPtr(mallocIfCountThrowOnFail(count)) {} + + AutoTMalloc(AutoTMalloc&&) = default; + AutoTMalloc& operator=(AutoTMalloc&&) = default; + + /** Resize the memory area pointed to by the current ptr preserving contents. */ + void realloc(size_t count) { fPtr.reset(reallocIfCountThrowOnFail(count)); } + + /** Resize the memory area pointed to by the current ptr without preserving contents. */ + T* reset(size_t count = 0) { + fPtr.reset(mallocIfCountThrowOnFail(count)); + return this->get(); + } + + T* get() const { return fPtr.get(); } + + operator T*() { return fPtr.get(); } + + operator const T*() const { return fPtr.get(); } + + T& operator[](int index) { return fPtr.get()[index]; } + + const T& operator[](int index) const { return fPtr.get()[index]; } + + /** + * Transfer ownership of the ptr to the caller, setting the internal + * pointer to NULL. Note that this differs from get(), which also returns + * the pointer, but it does not transfer ownership. + */ + T* release() { return fPtr.release(); } + +private: + struct FreeDeleter { + void operator()(uint8_t* p) { std::free(p); } + }; + std::unique_ptr fPtr; + + T* mallocIfCountThrowOnFail(size_t count) { + T* newPtr = nullptr; + if (count) { + newPtr = (T*)std::malloc(count * sizeof(T)); + LOG_ALWAYS_FATAL_IF(!newPtr, "failed to malloc %zu bytes", count * sizeof(T)); + } + return newPtr; + } + T* reallocIfCountThrowOnFail(size_t count) { + T* newPtr = nullptr; + if (count) { + newPtr = (T*)std::realloc(fPtr.release(), count * sizeof(T)); + LOG_ALWAYS_FATAL_IF(!newPtr, "failed to realloc %zu bytes", count * sizeof(T)); + } + return newPtr; + } +}; + +} // namespace uirenderer +} // namespace android