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
GraphiteBackendTexture(std::shared_ptr<skgpu::graphite::Recorder> recorder,AHardwareBuffer * buffer,bool isOutputBuffer)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
~GraphiteBackendTexture()64 GraphiteBackendTexture::~GraphiteBackendTexture() {
65 if (mBackendTexture.isValid()) {
66 mRecorder->deleteBackendTexture(mBackendTexture);
67 mBackendTexture = {};
68 }
69 }
70
makeImage(SkAlphaType alphaType,ui::Dataspace dataspace,TextureReleaseProc releaseImageProc,ReleaseContext releaseContext)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
makeSurface(ui::Dataspace dataspace,TextureReleaseProc releaseSurfaceProc,ReleaseContext releaseContext)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
logFatalTexture(const char * msg,ui::Dataspace dataspace,SkColorType colorType)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
115