blob: cd2c8c2738d6ddc41ec674e498a716e672e92cc6 [file] [log] [blame]
/*
* 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