• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7     * Redistributions of source code must retain the above copyright
8       notice, this list of conditions and the following disclaimer.
9     * Redistributions in binary form must reproduce the above
10       copyright notice, this list of conditions and the following
11       disclaimer in the documentation and/or other materials provided
12       with the distribution.
13     * Neither the name of The Linux Foundation nor the names of its
14       contributors may be used to endorse or promote products derived
15       from this software without specific prior written permission.
16 
17  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include "hwc_display_virtual_gpu.h"
31 #include "hwc_session.h"
32 
33 #include <qdMetaData.h>
34 
35 #define __CLASS__ "HWCDisplayVirtualGPU"
36 
37 namespace sdm {
38 
Init()39 int HWCDisplayVirtualGPU::Init() {
40   // Create client target.
41   client_target_ = new HWCLayer(id_, buffer_allocator_);
42 
43   // Calls into SDM need to be dropped. Create Null Display interface.
44   display_intf_ = new DisplayNull();
45 
46   return HWCDisplayVirtual::Init();
47 }
48 
Deinit()49 int HWCDisplayVirtualGPU::Deinit() {
50   // Destory color convert instance. This destroys thread and underlying GL resources.
51   if (gl_color_convert_) {
52     color_convert_task_.PerformTask(ColorConvertTaskCode::kCodeDestroyInstance, nullptr);
53   }
54 
55   delete static_cast<DisplayNull *>(display_intf_);
56   delete client_target_;
57 
58   for (auto hwc_layer : layer_set_) {
59     delete hwc_layer;
60   }
61 
62   return 0;
63 }
64 
HWCDisplayVirtualGPU(CoreInterface * core_intf,HWCBufferAllocator * buffer_allocator,HWCCallbacks * callbacks,hwc2_display_t id,int32_t sdm_id,uint32_t width,uint32_t height,float min_lum,float max_lum)65 HWCDisplayVirtualGPU::HWCDisplayVirtualGPU(CoreInterface *core_intf, HWCBufferAllocator
66                                            *buffer_allocator, HWCCallbacks *callbacks,
67                                            hwc2_display_t id, int32_t sdm_id, uint32_t width,
68                                            uint32_t height, float min_lum, float max_lum) :
69   HWCDisplayVirtual(core_intf, buffer_allocator, callbacks, id, sdm_id, width, height),
70   color_convert_task_(*this) {
71 }
72 
Validate(uint32_t * out_num_types,uint32_t * out_num_requests)73 HWC2::Error HWCDisplayVirtualGPU::Validate(uint32_t *out_num_types, uint32_t *out_num_requests) {
74   DTRACE_SCOPED();
75 
76   // Reset previous changes.
77   layer_changes_.clear();
78   layer_requests_.clear();
79 
80   // Mark all layers to GPU if there is no need to bypass.
81   bool needs_gpu_bypass = NeedsGPUBypass();
82   for (auto hwc_layer : layer_set_) {
83     auto layer = hwc_layer->GetSDMLayer();
84     layer->composition = needs_gpu_bypass ? kCompositionSDE : kCompositionGPU;
85 
86     if (needs_gpu_bypass) {
87       if (hwc_layer->GetClientRequestedCompositionType() == HWC2::Composition::Client) {
88        layer_changes_[hwc_layer->GetId()] = HWC2::Composition::Device;
89        layer_requests_[hwc_layer->GetId()] = HWC2::LayerRequest::ClearClientTarget;
90       }
91     } else {
92       if (hwc_layer->GetClientRequestedCompositionType() != HWC2::Composition::Client) {
93        layer_changes_[hwc_layer->GetId()] = HWC2::Composition::Client;
94       }
95     }
96   }
97 
98   // Derive client target dataspace based on the color mode - bug/115482728
99   int32_t client_target_dataspace = GetDataspaceFromColorMode(GetCurrentColorMode());
100   SetClientTargetDataSpace(client_target_dataspace);
101 
102   *out_num_types = UINT32(layer_changes_.size());
103   *out_num_requests = UINT32(layer_requests_.size());;
104   has_client_composition_ = !needs_gpu_bypass;
105   client_target_->ResetValidation();
106 
107   validated_ = true;
108 
109   return ((*out_num_types > 0) ? HWC2::Error::HasChanges : HWC2::Error::None);
110 }
111 
SetOutputBuffer(buffer_handle_t buf,shared_ptr<Fence> release_fence)112 HWC2::Error HWCDisplayVirtualGPU::SetOutputBuffer(buffer_handle_t buf,
113                                                   shared_ptr<Fence> release_fence) {
114   HWC2::Error error = HWCDisplayVirtual::SetOutputBuffer(buf, release_fence);
115   if (error != HWC2::Error::None) {
116     return error;
117   }
118 
119   const private_handle_t *hnd = static_cast<const private_handle_t *>(buf);
120   output_buffer_.width = hnd->width;
121   output_buffer_.height = hnd->height;
122   output_buffer_.unaligned_width = width_;
123   output_buffer_.unaligned_height = height_;
124 
125   // Update active dimensions.
126   BufferDim_t buffer_dim;
127   if (getMetaData(const_cast<private_handle_t *>(hnd), GET_BUFFER_GEOMETRY, &buffer_dim) == 0) {
128     output_buffer_.unaligned_width = buffer_dim.sliceWidth;
129     output_buffer_.unaligned_height = buffer_dim.sliceHeight;
130     color_convert_task_.PerformTask(ColorConvertTaskCode::kCodeReset, nullptr);
131   }
132 
133   return HWC2::Error::None;
134 }
135 
Present(shared_ptr<Fence> * out_retire_fence)136 HWC2::Error HWCDisplayVirtualGPU::Present(shared_ptr<Fence> *out_retire_fence) {
137   DTRACE_SCOPED();
138 
139   auto status = HWC2::Error::None;
140 
141   if (!validated_) {
142     return HWC2::Error::NotValidated;
143   }
144 
145   if (!output_buffer_.buffer_id) {
146     return HWC2::Error::NoResources;
147   }
148 
149   if (active_secure_sessions_.any() || layer_set_.empty()) {
150     return status;
151   }
152 
153   layer_stack_.output_buffer = &output_buffer_;
154   if (display_paused_) {
155     validated_ = false;
156   }
157 
158   // Ensure that blit is initialized.
159   // GPU context gets in secure or non-secure mode depending on output buffer provided.
160   if (!gl_color_convert_) {
161     // Get instance.
162     color_convert_task_.PerformTask(ColorConvertTaskCode::kCodeGetInstance, nullptr);
163     if (gl_color_convert_ == nullptr) {
164       DLOGE("Failed to get Color Convert Instance");
165       return HWC2::Error::NoResources;
166     } else {
167       DLOGI("Created ColorConvert instance: %p", gl_color_convert_);
168     }
169   }
170 
171   ColorConvertBlitContext ctx = {};
172 
173   Layer *sdm_layer = client_target_->GetSDMLayer();
174   LayerBuffer &input_buffer = sdm_layer->input_buffer;
175   ctx.src_hnd = reinterpret_cast<const private_handle_t *>(input_buffer.buffer_id);
176   ctx.dst_hnd = reinterpret_cast<const private_handle_t *>(output_handle_);
177   ctx.dst_rect = {0, 0, FLOAT(output_buffer_.unaligned_width),
178                   FLOAT(output_buffer_.unaligned_height)};
179   ctx.src_acquire_fence = input_buffer.acquire_fence;
180   ctx.dst_acquire_fence = output_buffer_.acquire_fence;
181 
182   color_convert_task_.PerformTask(ColorConvertTaskCode::kCodeBlit, &ctx);
183 
184   // todo blit
185   DumpVDSBuffer();
186 
187   *out_retire_fence = ctx.release_fence;
188 
189   return status;
190 }
191 
OnTask(const ColorConvertTaskCode & task_code,SyncTask<ColorConvertTaskCode>::TaskContext * task_context)192 void HWCDisplayVirtualGPU::OnTask(const ColorConvertTaskCode &task_code,
193                                   SyncTask<ColorConvertTaskCode>::TaskContext *task_context) {
194   switch (task_code) {
195     case ColorConvertTaskCode::kCodeGetInstance: {
196         gl_color_convert_ = GLColorConvert::GetInstance(kTargetYUV, output_buffer_.flags.secure);
197       }
198       break;
199     case ColorConvertTaskCode::kCodeBlit: {
200         DTRACE_SCOPED();
201         ColorConvertBlitContext* ctx = reinterpret_cast<ColorConvertBlitContext*>(task_context);
202         gl_color_convert_->Blit(ctx->src_hnd, ctx->dst_hnd, ctx->src_rect, ctx->dst_rect,
203                                 ctx->src_acquire_fence, ctx->dst_acquire_fence,
204                                 &(ctx->release_fence));
205       }
206       break;
207     case ColorConvertTaskCode::kCodeReset: {
208         DTRACE_SCOPED();
209         if (gl_color_convert_) {
210           gl_color_convert_->Reset();
211         }
212       }
213       break;
214     case ColorConvertTaskCode::kCodeDestroyInstance: {
215         if (gl_color_convert_) {
216           GLColorConvert::Destroy(gl_color_convert_);
217         }
218       }
219       break;
220   }
221 }
222 
223 }  // namespace sdm
224 
225