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