1 // Copyright 2024 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either expresso or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "gfxstream/guest/RenderControl.h"
16 
17 #include <vector>
18 
19 #include "HostConnection.h"
20 
21 namespace {
22 
23 typedef struct compose_layer {
24     uint32_t cbHandle;
25     hwc2_composition_t composeMode;
26     hwc_rect_t displayFrame;
27     hwc_frect_t crop;
28     int32_t blendMode;
29     float alpha;
30     hwc_color_t color;
31     hwc_transform_t transform;
32 } ComposeLayer;
33 
34 typedef struct compose_device {
35     uint32_t version;
36     uint32_t targetHandle;
37     uint32_t numLayers;
38     struct compose_layer layer[0];
39 } ComposeDevice;
40 
41 typedef struct compose_device_v2 {
42     uint32_t version;
43     uint32_t displayId;
44     uint32_t targetHandle;
45     uint32_t numLayers;
46     struct compose_layer layer[0];
47 } ComposeDevice_v2;
48 
49 class RenderControlDeviceImpl {
50    public:
RenderControlDeviceImpl()51     RenderControlDeviceImpl() : mHostConnection(HostConnection::createUnique(kCapsetNone)) {}
52 
53     RenderControlDeviceImpl(const RenderControlDeviceImpl& rhs) = delete;
54     RenderControlDeviceImpl& operator=(const RenderControlDeviceImpl& rhs) = delete;
55 
56     RenderControlDeviceImpl(RenderControlDeviceImpl&& rhs) = delete;
57     RenderControlDeviceImpl& operator=(RenderControlDeviceImpl&& rhs) = delete;
58 
DoCompose(std::vector<uint8_t> & bytes)59     int DoCompose(std::vector<uint8_t>& bytes) {
60         if (!mHostConnection) {
61             ALOGE("RenderControlDevice missing HostConnection.");
62             return -1;
63         }
64 
65         auto* rc = mHostConnection->rcEncoder();
66         if (!rc) {
67             ALOGE("RenderControlDevice missing rcEncoder.");
68             return -1;
69         }
70 
71         mHostConnection->lock();
72         rc->rcCompose(rc, bytes.size(), bytes.data());
73         mHostConnection->unlock();
74         return 0;
75     }
76 
77    private:
78     std::unique_ptr<HostConnection> mHostConnection;
79 };
80 
ToHandle(RenderControlDeviceImpl * device)81 RenderControlDevice* ToHandle(RenderControlDeviceImpl* device) {
82     return reinterpret_cast<RenderControlDevice*>(device);
83 }
84 
ToImpl(RenderControlDevice * device)85 RenderControlDeviceImpl* ToImpl(RenderControlDevice* device) {
86     return reinterpret_cast<RenderControlDeviceImpl*>(device);
87 }
88 
89 }  // namespace
90 
rcCreateDevice()91 extern "C" __attribute__((visibility("default"))) RenderControlDevice* rcCreateDevice() {
92     return ToHandle(new RenderControlDeviceImpl());
93 }
94 
rcDestroyDevice(RenderControlDevice * pDevice)95 extern "C" __attribute__((visibility("default"))) void rcDestroyDevice(
96     RenderControlDevice* pDevice) {
97     if (pDevice != nullptr) {
98         delete ToImpl(pDevice);
99     }
100 }
101 
rcCompose(RenderControlDevice * deviceHandle,const RenderControlComposition * pComposition,uint32_t compositionLayerCount,const RenderControlCompositionLayer * pCompositionLayers)102 extern "C" __attribute__((visibility("default"))) int rcCompose(
103     RenderControlDevice* deviceHandle, const RenderControlComposition* pComposition,
104     uint32_t compositionLayerCount, const RenderControlCompositionLayer* pCompositionLayers) {
105     const size_t bytesNeeded =
106         sizeof(ComposeDevice_v2) + (sizeof(ComposeLayer) * compositionLayerCount);
107     std::vector<uint8_t> bytes(bytesNeeded);
108 
109     auto* composeDevice = reinterpret_cast<ComposeDevice_v2*>(bytes.data());
110     auto* composeLayers = composeDevice->layer;
111 
112     composeDevice->version = 2;
113     composeDevice->displayId = 0;
114     composeDevice->targetHandle = pComposition->compositionResultColorBufferHandle;
115     composeDevice->numLayers = compositionLayerCount;
116 
117     for (uint32_t i = 0; i < compositionLayerCount; i++) {
118         auto& requestLayer = pCompositionLayers[i];
119         auto& composeLayer = composeLayers[i];
120         composeLayer.cbHandle = requestLayer.colorBufferHandle;
121         composeLayer.composeMode = requestLayer.composeMode;
122         composeLayer.displayFrame = requestLayer.displayFrame;
123         composeLayer.crop = requestLayer.crop;
124         composeLayer.blendMode = requestLayer.blendMode;
125         composeLayer.alpha = requestLayer.alpha;
126         composeLayer.color = requestLayer.color;
127         composeLayer.transform = requestLayer.transform;
128     }
129 
130     RenderControlDeviceImpl* device = ToImpl(deviceHandle);
131     return device->DoCompose(bytes);
132 }
133