Nolan Scobie | 609e597 | 2024-03-20 14:47:34 -0400 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2024 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | #include "GraphiteBackendTexture.h" |
| 18 | |
| 19 | #undef LOG_TAG |
| 20 | #define LOG_TAG "RenderEngine" |
| 21 | #define ATRACE_TAG ATRACE_TAG_GRAPHICS |
| 22 | |
| 23 | #include <include/core/SkSurfaceProps.h> |
| 24 | #include <include/gpu/graphite/Image.h> |
| 25 | #include <include/gpu/graphite/Surface.h> |
| 26 | #include <include/gpu/graphite/TextureInfo.h> |
| 27 | |
| 28 | #include "skia/ColorSpaces.h" |
| 29 | |
| 30 | #include <android/hardware_buffer.h> |
| 31 | #include <inttypes.h> |
| 32 | #include <log/log_main.h> |
| 33 | #include <utils/Trace.h> |
| 34 | |
| 35 | namespace android::renderengine::skia { |
| 36 | |
| 37 | GraphiteBackendTexture::GraphiteBackendTexture(std::shared_ptr<skgpu::graphite::Recorder> recorder, |
| 38 | AHardwareBuffer* buffer, bool isOutputBuffer) |
| 39 | : SkiaBackendTexture(buffer, isOutputBuffer), mRecorder(std::move(recorder)) { |
| 40 | ATRACE_CALL(); |
| 41 | AHardwareBuffer_Desc desc; |
| 42 | AHardwareBuffer_describe(buffer, &desc); |
| 43 | const bool createProtectedImage = 0 != (desc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT); |
| 44 | |
| 45 | const SkISize dimensions = {static_cast<int32_t>(desc.width), |
| 46 | static_cast<int32_t>(desc.height)}; |
| 47 | LOG_ALWAYS_FATAL_IF(static_cast<uint32_t>(dimensions.width()) != desc.width || |
| 48 | static_cast<uint32_t>(dimensions.height()) != desc.height, |
| 49 | "Failed to create a valid texture, casting unsigned dimensions [%" PRIu32 |
| 50 | ",%" PRIu32 "] to signed [%" PRIo32 ",%" PRIo32 "] " |
| 51 | "is invalid", |
| 52 | desc.width, desc.height, dimensions.width(), dimensions.height()); |
| 53 | |
| 54 | mBackendTexture = mRecorder->createBackendTexture(buffer, isOutputBuffer, createProtectedImage, |
| 55 | dimensions, false); |
| 56 | if (!mBackendTexture.isValid() || !dimensions.width() || !dimensions.height()) { |
| 57 | LOG_ALWAYS_FATAL("Failed to create a valid texture. [%p]:[%d,%d] isProtected:%d " |
| 58 | "isWriteable:%d format:%d", |
| 59 | this, dimensions.width(), dimensions.height(), createProtectedImage, |
| 60 | isOutputBuffer, desc.format); |
| 61 | } |
| 62 | } |
| 63 | |
| 64 | GraphiteBackendTexture::~GraphiteBackendTexture() { |
| 65 | if (mBackendTexture.isValid()) { |
| 66 | mRecorder->deleteBackendTexture(mBackendTexture); |
| 67 | mBackendTexture = {}; |
| 68 | } |
| 69 | } |
| 70 | |
| 71 | sk_sp<SkImage> GraphiteBackendTexture::makeImage(SkAlphaType alphaType, ui::Dataspace dataspace, |
| 72 | TextureReleaseProc releaseImageProc, |
| 73 | ReleaseContext releaseContext) { |
| 74 | const SkColorType colorType = colorTypeForImage(alphaType); |
| 75 | sk_sp<SkImage> image = |
| 76 | SkImages::WrapTexture(mRecorder.get(), mBackendTexture, colorType, alphaType, |
| 77 | toSkColorSpace(dataspace), releaseImageProc, releaseContext); |
| 78 | if (!image) { |
| 79 | logFatalTexture("Unable to generate SkImage.", dataspace, colorType); |
| 80 | } |
| 81 | return image; |
| 82 | } |
| 83 | |
| 84 | sk_sp<SkSurface> GraphiteBackendTexture::makeSurface(ui::Dataspace dataspace, |
| 85 | TextureReleaseProc releaseSurfaceProc, |
| 86 | ReleaseContext releaseContext) { |
| 87 | const SkColorType colorType = internalColorType(); |
| 88 | SkSurfaceProps props; |
| 89 | sk_sp<SkSurface> surface = |
| 90 | SkSurfaces::WrapBackendTexture(mRecorder.get(), mBackendTexture, colorType, |
| 91 | toSkColorSpace(dataspace), &props, releaseSurfaceProc, |
| 92 | releaseContext); |
| 93 | if (!surface) { |
| 94 | logFatalTexture("Unable to generate SkSurface.", dataspace, colorType); |
| 95 | } |
| 96 | return surface; |
| 97 | } |
| 98 | |
| 99 | void GraphiteBackendTexture::logFatalTexture(const char* msg, ui::Dataspace dataspace, |
| 100 | SkColorType colorType) { |
| 101 | // TODO: b/293371537 - Iterate on this logging (validate failure cases, possibly check |
| 102 | // VulkanTextureInfo, etc.) |
| 103 | const skgpu::graphite::TextureInfo& textureInfo = mBackendTexture.info(); |
| 104 | LOG_ALWAYS_FATAL("%s isOutputBuffer:%d, dataspace:%d, colorType:%d" |
| 105 | "\n\tBackendTexture: isValid:%d, dimensions:%dx%d" |
| 106 | "\n\t\tTextureInfo: isValid:%d, numSamples:%d, mipmapped:%d, isProtected: %d", |
| 107 | msg, isOutputBuffer(), static_cast<int32_t>(dataspace), colorType, |
| 108 | mBackendTexture.isValid(), mBackendTexture.dimensions().width(), |
| 109 | mBackendTexture.dimensions().height(), textureInfo.isValid(), |
| 110 | textureInfo.numSamples(), static_cast<int32_t>(textureInfo.mipmapped()), |
| 111 | static_cast<int32_t>(textureInfo.isProtected())); |
| 112 | } |
| 113 | |
| 114 | } // namespace android::renderengine::skia |