* 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.
*/
#include "render_context/new_render_context/render_context_vk.h"
#include "platform/common/rs_log.h"
#include "rs_vulkan_context.h"
#ifdef USE_M133_SKIA
#include "include/gpu/ganesh/vk/GrVkBackendSemaphore.h"
#endif
namespace OHOS {
namespace Rosen {
RenderContextVK::~RenderContextVK()
{
AbandonContext();
}
bool RenderContextVK::Init()
{
return true;
}
bool RenderContextVK::AbandonContext()
{
if (drGPUContext_ == nullptr) {
ROSEN_LOGD("grContext is nullptr.");
return true;
}
drGPUContext_->FlushAndSubmit(true);
drGPUContext_->PurgeUnlockAndSafeCacheGpuResources();
return true;
}
bool RenderContextVK::SetUpGpuContext(std::shared_ptr<Drawing::GPUContext> drawingContext)
{
if (drGPUContext_ != nullptr) {
ROSEN_LOGD("Drawing GPUContext has already created!!");
return true;
}
if (drawingContext == nullptr) {
drawingContext = RsVulkanContext::GetSingleton(cacheDir_).CreateDrawingContext();
if (drawingContext == nullptr) {
ROSEN_LOGE("Fail to create vulkan GPUContext");
return false;
}
}
std::shared_ptr<Drawing::GPUContext> drGPUContext(drawingContext);
drGPUContext_ = std::move(drGPUContext);
return true;
}
std::string RenderContextVK::GetShaderCacheSize() const
{
return std::string();
}
std::string RenderContextVK::CleanAllShaderCache() const
{
return std::string();
}
void RenderContextVK::SetRenderContextType(uint8_t type)
{
RenderContextVKType renderContextType = static_cast<RenderContextVKType>(type);
if (renderContextType == RenderContextVKType::PROTECTED_REDRAW) {
isProtected_.store(true, std::memory_order_release);
RsVulkanContext::GetSingleton().SetIsProtected(true);
} else if (renderContextType == RenderContextVKType::UNPROTECTED_REDRAW) {
isProtected_.store(false, std::memory_order_release);
RsVulkanContext::GetSingleton().SetIsProtected(false);
}
}
void RenderContextVK::ChangeProtectedState(bool isProtected)
{
RsVulkanContext::GetSingleton().SetIsProtected(isProtected);
bool expected = !isProtected;
if (isProtected_.compare_exchange_strong(expected, isProtected, std::memory_order_acq_rel,
std::memory_order_acquire)) {
drGPUContext_ = RsVulkanContext::GetSingleton().GetDrawingContext();
}
isProtected_.store(isProtected, std::memory_order_release);
}
bool RenderContextVK::QueryMaxGpuBufferSize(uint32_t& maxWidth, uint32_t& maxHeight)
{
ROSEN_LOGI("RenderContextVK::QueryMaxGpuBufferSize: using Vulkan backend");
auto& vkContext = RsVulkanContext::GetSingleton();
VkPhysicalDevice physicalDevice = vkContext.GetPhysicalDevice();
if (physicalDevice == VK_NULL_HANDLE) {
ROSEN_LOGE("RenderContextVK::QueryMaxGpuBufferSize: Vulkan physical device is null");
return false;
}
VkPhysicalDeviceProperties deviceProperties;
vkGetPhysicalDeviceProperties(physicalDevice, &deviceProperties);
maxWidth = deviceProperties.limits.maxImageDimension2D;
maxHeight = deviceProperties.limits.maxImageDimension2D;
ROSEN_LOGI("RenderContextVK::QueryMaxGpuBufferSize: Vulkan max image dimension = %u", maxWidth);
return true;
}
void RenderContextVK::AddSurface()
{
int32_t count = surface_count_.fetch_add(1, std::memory_order_relaxed) + 1;
ROSEN_LOGD("RenderContextVK::AddSurface surface_count_=%{public}d", count);
}
void RenderContextVK::DeleteSurface()
{
int32_t count = surface_count_.fetch_sub(1, std::memory_order_acq_rel) - 1;
ROSEN_LOGD("RenderContextVK::DeleteSurface surface_count_=%{public}d", count);
if (cleanUpHelper_ != nullptr && count <= 0) {
ROSEN_LOGD("RenderContextVK::DeleteSurface all surfaces gone, cleanUpHelper_");
cleanUpHelper_();
}
}
void RenderContextVK::SetCleanUpHelper(std::function<void()> func)
{
cleanUpHelper_ = std::move(func);
}
void RenderContextVK::DestroySharedSource()
{
int32_t count = surface_count_.load(std::memory_order_acquire);
ROSEN_LOGD("RenderContextVK::DestroySharedSource surface_count_=%{public}d", count);
if (count > 0) {
return;
}
AbandonContext();
}
}
}