| /* |
| * Copyright 2023 Google LLC |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "include/core/SkTypes.h" |
| |
| #if __ANDROID_API__ >= 26 |
| |
| #include "include/android/AHardwareBufferUtils.h" |
| #include "include/android/graphite/SurfaceAndroid.h" |
| #include "include/core/SkColorSpace.h" |
| #include "include/gpu/graphite/BackendTexture.h" |
| #include "include/gpu/graphite/Recorder.h" |
| #include "include/gpu/graphite/Surface.h" |
| #include "src/gpu/graphite/Caps.h" |
| #include "src/gpu/graphite/RecorderPriv.h" |
| #include "src/gpu/graphite/TextureFormat.h" |
| #include "src/gpu/graphite/TextureInfoPriv.h" |
| |
| #include <android/hardware_buffer.h> |
| |
| using namespace skgpu::graphite; |
| |
| namespace SkSurfaces { |
| |
| sk_sp<SkSurface> WrapAndroidHardwareBuffer(Recorder* recorder, |
| AHardwareBuffer* hardwareBuffer, |
| sk_sp<SkColorSpace> colorSpace, |
| const SkSurfaceProps* surfaceProps, |
| BufferReleaseProc releaseP, |
| ReleaseContext releaseC, |
| bool fromWindow) { |
| if (!recorder || !hardwareBuffer) { |
| return nullptr; |
| } |
| |
| AHardwareBuffer_Desc bufferDesc; |
| AHardwareBuffer_describe(hardwareBuffer, &bufferDesc); |
| |
| if (!SkToBool(bufferDesc.usage & AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT) || |
| !SkToBool(bufferDesc.usage & AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE)) { |
| if (releaseP) { |
| releaseP(releaseC); |
| } |
| return nullptr; |
| } |
| |
| bool isProtectedContent = SkToBool(bufferDesc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT); |
| |
| bool fromWindowLocal = false; |
| #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK |
| fromWindowLocal = fromWindow; |
| #endif |
| |
| SkISize dims = SkISize::Make(bufferDesc.width, bufferDesc.height); |
| |
| BackendTexture backendTexture = recorder->createBackendTexture(hardwareBuffer, |
| /* isRenderable= */ true, |
| isProtectedContent, |
| dims, |
| fromWindowLocal); |
| if (!backendTexture.isValid()) { |
| if (releaseP) { |
| releaseP(releaseC); |
| } |
| return nullptr; |
| } |
| |
| // Skia determines that the AHwBuf should be imported using an external format. |
| // In this case - even though we can never write to a texture using an external format - Skia |
| // validity checks will expect the usage of kExternalFormatColorType (see VulkanCaps's |
| // fExternalFormatColorTypeInfo), so enforce that here. |
| const bool textureUsesExternalFormat = |
| TextureInfoPriv::ViewFormat(backendTexture.info()) == TextureFormat::kExternal; |
| SkColorType colorType = textureUsesExternalFormat |
| ? AHardwareBufferUtils::kExternalFormatColorType |
| : AHardwareBufferUtils::GetSkColorTypeFromBufferFormat(bufferDesc.format); |
| |
| // Ensure that we have not somehow ended up in a situation where the determined color type is |
| // incompatible with the texture's format. |
| SkASSERT(textureUsesExternalFormat || |
| recorder->priv().caps()->areColorTypeAndTextureInfoCompatible(colorType, |
| backendTexture.info())); |
| |
| // Will call 'releaseP' if SkSurface creation fails. |
| return SkSurfaces::WrapBackendTexture(recorder, |
| backendTexture, |
| colorType, |
| std::move(colorSpace), |
| surfaceProps, |
| releaseP, |
| releaseC); |
| } |
| |
| } // namespace SkSurfaces |
| |
| #endif // __ANDROID_API__ >= 26 |