blob: 24db6aa7a7d5ae95ed15d1dac107745be8b5b459
1 | /* |
2 | // Copyright (c) 2014 Intel Corporation |
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 | // This file is modified by Amlogic, Inc. 2017.01.17. |
17 | */ |
18 | |
19 | #include <HwcTrace.h> |
20 | #include <Hwcomposer.h> |
21 | #include <VirtualDevice.h> |
22 | #include <Utils.h> |
23 | #include <sync/sync.h> |
24 | |
25 | namespace android { |
26 | namespace amlogic { |
27 | |
28 | VirtualDevice::VirtualDevice(Hwcomposer& hwc) |
29 | : mHwc(hwc), |
30 | mId(HWC_DISPLAY_VIRTUAL), |
31 | mIsConnected(false), |
32 | mInitialized(false), |
33 | mWidth(0), |
34 | mHeight(0), |
35 | mFormat(0), |
36 | mRetireFence(-1) |
37 | { |
38 | CTRACE(); |
39 | mName = "Virtual"; |
40 | |
41 | // set capacity of layers, layer's changed type, layer's changed request. |
42 | mHwcLayersChangeType.setCapacity(LAYER_MAX_NUM_CHANGE_TYPE); |
43 | mHwcLayers.setCapacity(LAYER_MAX_NUM_SUPPORT); |
44 | } |
45 | |
46 | VirtualDevice::~VirtualDevice() |
47 | { |
48 | CTRACE(); |
49 | } |
50 | |
51 | bool VirtualDevice::initialize() { |
52 | CTRACE(); |
53 | |
54 | mInitialized = true; |
55 | return true; |
56 | } |
57 | |
58 | void VirtualDevice::deinitialize() { |
59 | CTRACE(); |
60 | mInitialized = false; |
61 | } |
62 | |
63 | HwcLayer* VirtualDevice::getLayerById(hwc2_layer_t layerId) { |
64 | HwcLayer* layer = NULL; |
65 | |
66 | layer = mHwcLayers.valueFor(layerId); |
67 | if (!layer) ETRACE("getLayerById %lld error!", layerId); |
68 | |
69 | return layer; |
70 | } |
71 | |
72 | int32_t VirtualDevice::acceptDisplayChanges() { |
73 | HwcLayer* layer = NULL; |
74 | |
75 | for (uint32_t i=0; i<mHwcLayersChangeType.size(); i++) { |
76 | hwc2_layer_t layerId = mHwcLayersChangeType.keyAt(i); |
77 | layer = mHwcLayersChangeType.valueAt(i); |
78 | if (layer) { |
79 | if (layer->getCompositionType() != HWC2_COMPOSITION_CLIENT) { |
80 | layer->setCompositionType(HWC2_COMPOSITION_CLIENT); |
81 | } |
82 | } |
83 | } |
84 | // reset layer changed or requested to zero. |
85 | mHwcLayersChangeType.clear(); |
86 | |
87 | return HWC2_ERROR_NONE; |
88 | } |
89 | |
90 | bool VirtualDevice::createLayer(hwc2_layer_t* outLayer) { |
91 | HwcLayer* layer = new HwcLayer(mId); |
92 | |
93 | if (layer == NULL || !layer->initialize()) { |
94 | ETRACE("createLayer: failed !"); |
95 | return false; |
96 | } |
97 | |
98 | hwc2_layer_t layerId = reinterpret_cast<hwc2_layer_t>(layer); |
99 | mHwcLayers.add(layerId, layer); |
100 | *outLayer = layerId; |
101 | return true; |
102 | } |
103 | |
104 | bool VirtualDevice::destroyLayer(hwc2_layer_t layerId) { |
105 | //HwcLayer* layer = reinterpret_cast<HwcLayer*>(layerId); |
106 | HwcLayer* layer = mHwcLayers.valueFor(layerId); |
107 | |
108 | if (layer == NULL) { |
109 | ETRACE("destroyLayer: no Hwclayer found (%d)", layerId); |
110 | return false; |
111 | } |
112 | |
113 | mHwcLayers.removeItem(layerId); |
114 | DEINIT_AND_DELETE_OBJ(layer); |
115 | return true; |
116 | } |
117 | |
118 | int32_t VirtualDevice::getActiveConfig( |
119 | hwc2_config_t* outConfig) { |
120 | |
121 | return HWC2_ERROR_NONE; |
122 | } |
123 | |
124 | int32_t VirtualDevice::getChangedCompositionTypes( |
125 | uint32_t* outNumElements, |
126 | hwc2_layer_t* outLayers, |
127 | int32_t* /*hwc2_composition_t*/ outTypes) { |
128 | HwcLayer* layer = NULL; |
129 | |
130 | // if outLayers or outTypes were NULL, the number of layers and types which would have been returned. |
131 | if (NULL == outLayers || NULL == outTypes) { |
132 | *outNumElements = mHwcLayersChangeType.size(); |
133 | } else { |
134 | for (uint32_t i=0; i<mHwcLayersChangeType.size(); i++) { |
135 | hwc2_layer_t layerId = mHwcLayersChangeType.keyAt(i); |
136 | layer = mHwcLayersChangeType.valueAt(i); |
137 | if (layer) { |
138 | if (layer->getCompositionType() != HWC2_COMPOSITION_CLIENT) { |
139 | // change all other device type to client. |
140 | outLayers[i] = layerId; |
141 | outTypes[i] = HWC2_COMPOSITION_CLIENT; |
142 | continue; |
143 | } |
144 | } |
145 | } |
146 | |
147 | if (mHwcLayersChangeType.size() > 0) { |
148 | DTRACE("There are %d layers type has changed.", mHwcLayersChangeType.size()); |
149 | *outNumElements = mHwcLayersChangeType.size(); |
150 | } else { |
151 | DTRACE("No layers compositon type changed."); |
152 | } |
153 | } |
154 | |
155 | return HWC2_ERROR_NONE; |
156 | } |
157 | |
158 | int32_t VirtualDevice::getClientTargetSupport( |
159 | uint32_t width, |
160 | uint32_t height, |
161 | int32_t /*android_pixel_format_t*/ format, |
162 | int32_t /*android_dataspace_t*/ dataspace) { |
163 | |
164 | // TODO: ? |
165 | return HWC2_ERROR_NONE; |
166 | } |
167 | |
168 | int32_t VirtualDevice::getColorModes( |
169 | uint32_t* outNumModes, |
170 | int32_t* /*android_color_mode_t*/ outModes) { |
171 | return HWC2_ERROR_NONE; |
172 | } |
173 | |
174 | int32_t VirtualDevice::getDisplayAttribute( |
175 | hwc2_config_t config, |
176 | int32_t /*hwc2_attribute_t*/ attribute, |
177 | int32_t* outValue) { |
178 | Mutex::Autolock _l(mLock); |
179 | |
180 | if (!mIsConnected) { |
181 | ETRACE("display %d is not connected.", mId); |
182 | } |
183 | |
184 | // TODO: HWC2_ERROR_BAD_CONFIG? |
185 | switch (attribute) { |
186 | case HWC2_ATTRIBUTE_VSYNC_PERIOD: |
187 | *outValue = 1e9 / 60; |
188 | ETRACE("refresh period: %d", *outValue); |
189 | break; |
190 | case HWC2_ATTRIBUTE_WIDTH: |
191 | *outValue = mWidth; |
192 | break; |
193 | case HWC2_ATTRIBUTE_HEIGHT: |
194 | *outValue = mHeight; |
195 | break; |
196 | case HWC2_ATTRIBUTE_DPI_X: |
197 | *outValue = 160; |
198 | break; |
199 | case HWC2_ATTRIBUTE_DPI_Y: |
200 | *outValue = 160; |
201 | break; |
202 | default: |
203 | ETRACE("unknown display attribute %u", attribute); |
204 | *outValue = -1; |
205 | break; |
206 | } |
207 | |
208 | return HWC2_ERROR_NONE; |
209 | } |
210 | |
211 | int32_t VirtualDevice::getDisplayConfigs( |
212 | uint32_t* outNumConfigs, |
213 | hwc2_config_t* outConfigs) { |
214 | Mutex::Autolock _l(mLock); |
215 | |
216 | if (!mIsConnected) { |
217 | ETRACE("display %d is not connected.", mId); |
218 | } |
219 | |
220 | if (NULL != outConfigs) outConfigs[0] = 0; |
221 | *outNumConfigs = 1; |
222 | |
223 | return HWC2_ERROR_NONE; |
224 | } |
225 | |
226 | int32_t VirtualDevice::getDisplayName( |
227 | uint32_t* outSize, |
228 | char* outName) { |
229 | return HWC2_ERROR_NONE; |
230 | } |
231 | |
232 | int32_t VirtualDevice::getDisplayRequests( |
233 | int32_t* /*hwc2_display_request_t*/ outDisplayRequests, |
234 | uint32_t* outNumElements, |
235 | hwc2_layer_t* outLayers, |
236 | int32_t* /*hwc2_layer_request_t*/ outLayerRequests) { |
237 | *outNumElements = 0; |
238 | |
239 | return HWC2_ERROR_NONE; |
240 | } |
241 | |
242 | int32_t VirtualDevice::getDisplayType( |
243 | int32_t* /*hwc2_display_type_t*/ outType) { |
244 | if (!mIsConnected) { |
245 | ETRACE("display %d is not connected.", mId); |
246 | } |
247 | |
248 | *outType = HWC2_DISPLAY_TYPE_VIRTUAL; |
249 | return HWC2_ERROR_NONE; |
250 | } |
251 | |
252 | int32_t VirtualDevice::getDozeSupport( |
253 | int32_t* outSupport) { |
254 | return HWC2_ERROR_NONE; |
255 | } |
256 | |
257 | int32_t VirtualDevice::getHdrCapabilities( |
258 | uint32_t* outNumTypes, |
259 | int32_t* /*android_hdr_t*/ outTypes, |
260 | float* outMaxLuminance, |
261 | float* outMaxAverageLuminance, |
262 | float* outMinLuminance) { |
263 | return HWC2_ERROR_NONE; |
264 | } |
265 | |
266 | int32_t VirtualDevice::getReleaseFences( |
267 | uint32_t* outNumElements, |
268 | hwc2_layer_t* outLayers, |
269 | int32_t* outFences) { |
270 | |
271 | //No hw compose for virtual display. |
272 | *outNumElements= 0; |
273 | return HWC2_ERROR_NONE; |
274 | } |
275 | |
276 | int32_t VirtualDevice::presentDisplay( |
277 | int32_t* outRetireFence) { |
278 | if (!mIsConnected) |
279 | return HWC2_ERROR_BAD_DISPLAY; |
280 | |
281 | if (!mVirtualHnd) { |
282 | ETRACE("virtual display handle is null."); |
283 | return HWC2_ERROR_NO_RESOURCES; |
284 | } |
285 | |
286 | if (private_handle_t::validate(mVirtualHnd) < 0) |
287 | return HWC2_ERROR_NO_RESOURCES; |
288 | |
289 | if (mTargetAcquireFence > -1 && mVirtualReleaseFence > -1) { |
290 | mRetireFence = sync_merge("VirtualDevice-2", mTargetAcquireFence, mVirtualReleaseFence); |
291 | } else if (mTargetAcquireFence > -1) { |
292 | mRetireFence = sync_merge("VirtualDevice-0", mTargetAcquireFence, mTargetAcquireFence); |
293 | } else if (mVirtualReleaseFence > -1) { |
294 | mRetireFence = sync_merge("VirtualDevice-1", mVirtualReleaseFence, mVirtualReleaseFence); |
295 | } else { |
296 | mRetireFence = -1; |
297 | } |
298 | |
299 | *outRetireFence = mRetireFence; |
300 | |
301 | DTRACE("VirtualDevice::presentDisplay retire fence %d", mRetireFence); |
302 | |
303 | if (mTargetAcquireFence > -1) { |
304 | close(mTargetAcquireFence); |
305 | mTargetAcquireFence = -1; |
306 | } |
307 | if (mVirtualReleaseFence > -1) { |
308 | close(mVirtualReleaseFence); |
309 | mVirtualReleaseFence = -1; |
310 | } |
311 | |
312 | //reset layers' acquire fence. |
313 | HwcLayer * layer = NULL; |
314 | for (uint32_t i=0; i<mHwcLayers.size(); i++) { |
315 | hwc2_layer_t layerId = mHwcLayers.keyAt(i); |
316 | layer = mHwcLayers.valueAt(i); |
317 | if (layer != NULL) { |
318 | close(layer->getAcquireFence()); |
319 | layer->resetAcquireFence(); |
320 | } |
321 | } |
322 | |
323 | return HWC2_ERROR_NONE; |
324 | } |
325 | |
326 | int32_t VirtualDevice::setActiveConfig( |
327 | hwc2_config_t config) { |
328 | return HWC2_ERROR_NONE; |
329 | } |
330 | |
331 | int32_t VirtualDevice::setClientTarget( |
332 | buffer_handle_t target, |
333 | int32_t acquireFence, |
334 | int32_t /*android_dataspace_t*/ dataspace, |
335 | hwc_region_t damage) { |
336 | |
337 | DTRACE("VirtualDevice::setClientTarget %p, %d", target, acquireFence); |
338 | |
339 | if (mTargetAcquireFence > -1) { |
340 | close(mTargetAcquireFence); |
341 | mTargetAcquireFence = -1; |
342 | } |
343 | |
344 | if (!mIsConnected) |
345 | return HWC2_ERROR_BAD_DISPLAY; |
346 | |
347 | if (target && private_handle_t::validate(target) < 0) { |
348 | return HWC2_ERROR_BAD_PARAMETER; |
349 | } |
350 | |
351 | if (NULL != target) { |
352 | mClientTargetHnd = target; |
353 | mClientTargetDamageRegion = damage; |
354 | mTargetAcquireFence = acquireFence; |
355 | } else { |
356 | DTRACE("client target is null!, no need to update this frame."); |
357 | } |
358 | |
359 | return HWC2_ERROR_NONE; |
360 | } |
361 | |
362 | int32_t VirtualDevice::setColorMode( |
363 | int32_t /*android_color_mode_t*/ mode) { |
364 | return HWC2_ERROR_NONE; |
365 | } |
366 | |
367 | int32_t VirtualDevice::setColorTransform( |
368 | const float* matrix, |
369 | int32_t /*android_color_transform_t*/ hint) { |
370 | return HWC2_ERROR_NONE; |
371 | } |
372 | |
373 | int32_t VirtualDevice::setPowerMode( |
374 | int32_t /*hwc2_power_mode_t*/ mode){ |
375 | return HWC2_ERROR_NONE; |
376 | } |
377 | |
378 | bool VirtualDevice::vsyncControl(bool enabled) { |
379 | RETURN_FALSE_IF_NOT_INIT(); |
380 | |
381 | return true; |
382 | } |
383 | |
384 | int32_t VirtualDevice::validateDisplay(uint32_t* outNumTypes, |
385 | uint32_t* outNumRequests) { |
386 | HwcLayer* layer = NULL; |
387 | |
388 | for (uint32_t i=0; i<mHwcLayers.size(); i++) { |
389 | hwc2_layer_t layerId = mHwcLayers.keyAt(i); |
390 | layer = mHwcLayers.valueAt(i); |
391 | if (layer) { |
392 | // Virtual Display. |
393 | if (layer->getCompositionType() != HWC2_COMPOSITION_CLIENT) { |
394 | // change all other device type to client. |
395 | mHwcLayersChangeType.add(layerId, layer); |
396 | continue; |
397 | } |
398 | } |
399 | } |
400 | |
401 | // No requests. |
402 | *outNumRequests = 0; |
403 | |
404 | if (mHwcLayersChangeType.size() > 0) { |
405 | DTRACE("there are %d layer types has changed.", mHwcLayersChangeType.size()); |
406 | *outNumTypes = mHwcLayersChangeType.size(); |
407 | return HWC2_ERROR_HAS_CHANGES; |
408 | } |
409 | |
410 | return HWC2_ERROR_NONE; |
411 | } |
412 | |
413 | int32_t VirtualDevice::setCursorPosition( |
414 | hwc2_layer_t layerId, |
415 | int32_t x, |
416 | int32_t y) { |
417 | Mutex::Autolock _l(mLock); |
418 | return HWC2_ERROR_NONE; |
419 | } |
420 | |
421 | bool VirtualDevice::updateDisplayConfigs() |
422 | { |
423 | Mutex::Autolock _l(mLock); |
424 | return true; |
425 | } |
426 | |
427 | void VirtualDevice::onVsync(int64_t timestamp) { |
428 | // dont need implement now. |
429 | } |
430 | |
431 | int32_t VirtualDevice::createVirtualDisplay( |
432 | uint32_t width, |
433 | uint32_t height, |
434 | int32_t* /*android_pixel_format_t*/ format, |
435 | hwc2_display_t* outDisplay) { |
436 | mIsConnected = true; |
437 | mWidth = width; |
438 | mHeight = height; |
439 | mFormat = *format; |
440 | mVirtualReleaseFence= -1; |
441 | mRetireFence = -1; |
442 | mTargetAcquireFence = -1; |
443 | *outDisplay = HWC_DISPLAY_VIRTUAL; |
444 | |
445 | return HWC2_ERROR_NONE; |
446 | } |
447 | |
448 | int32_t VirtualDevice::destroyVirtualDisplay( |
449 | hwc2_display_t display) { |
450 | if (display != HWC_DISPLAY_VIRTUAL) { |
451 | return HWC2_ERROR_BAD_PARAMETER; |
452 | } |
453 | mIsConnected = false; |
454 | mWidth = 0; |
455 | mHeight = 0; |
456 | mFormat = 0; |
457 | |
458 | //release fence. |
459 | if (mRetireFence > -1) { |
460 | close(mRetireFence); |
461 | mRetireFence = -1; |
462 | } |
463 | if (mVirtualReleaseFence > -1) { |
464 | close(mVirtualReleaseFence); |
465 | mVirtualReleaseFence = -1; |
466 | } |
467 | if (mTargetAcquireFence > -1) { |
468 | close(mTargetAcquireFence); |
469 | mTargetAcquireFence = -1; |
470 | } |
471 | |
472 | //release layers. |
473 | if (!mHwcLayers.isEmpty()) { |
474 | int i = 0; |
475 | HwcLayer* layer = NULL; |
476 | for (i = 0; i < mHwcLayers.size(); i++) { |
477 | layer = mHwcLayers[i]; |
478 | DEINIT_AND_DELETE_OBJ(layer); |
479 | } |
480 | mHwcLayers.clear(); |
481 | } |
482 | |
483 | return HWC2_ERROR_NONE; |
484 | } |
485 | |
486 | int32_t VirtualDevice::setOutputBuffer( |
487 | buffer_handle_t buffer, int32_t releaseFence) { |
488 | DTRACE("VirtualDevice::setOutputBuffer"); |
489 | |
490 | if (mVirtualReleaseFence > -1) { |
491 | close(mVirtualReleaseFence); |
492 | mVirtualReleaseFence = -1; |
493 | } |
494 | |
495 | if (!mIsConnected) |
496 | return HWC2_ERROR_BAD_DISPLAY; |
497 | |
498 | if (NULL == buffer) { |
499 | ETRACE("Virtual Display output buffer target is null!, no need to update this frame."); |
500 | return HWC2_ERROR_BAD_PARAMETER; |
501 | } |
502 | |
503 | if (buffer && private_handle_t::validate(buffer) < 0) { |
504 | ETRACE("buffer handle is invalid"); |
505 | return HWC2_ERROR_BAD_PARAMETER; |
506 | } |
507 | |
508 | mVirtualHnd = buffer; |
509 | mVirtualReleaseFence = releaseFence; |
510 | DTRACE("VirtualDevice setOutputBuffer %d, %p ", releaseFence, buffer); |
511 | return HWC2_ERROR_NONE; |
512 | } |
513 | |
514 | void VirtualDevice::dump(Dump& d) { |
515 | Mutex::Autolock _l(mLock); |
516 | d.append("----------------------------------------------------------" |
517 | "-------------------------------------------------------------------\n"); |
518 | d.append("Device Name: %s (%s)\n", mName, |
519 | mIsConnected ? "connected" : "disconnected"); |
520 | |
521 | if (mIsConnected) { |
522 | d.append(" Layers state:\n"); |
523 | d.append(" numLayers=%zu\n", mHwcLayers.size()); |
524 | d.append(" numChangedTypeLayers=%zu\n", mHwcLayersChangeType.size()); |
525 | if (mHwcLayers.size() > 0) { |
526 | d.append( |
527 | " type | handle | zorder | ds | alpa | tr | blnd |" |
528 | " source crop (l,t,r,b) | frame \n" |
529 | " -------------+--------------+------------+----+------+----+------+" |
530 | "--------------------------------+------------------------\n"); |
531 | for (uint32_t i=0; i<mHwcLayers.size(); i++) { |
532 | hwc2_layer_t layerId = mHwcLayers.keyAt(i); |
533 | HwcLayer *layer = mHwcLayers.valueAt(i); |
534 | if (layer) layer->dump(d); |
535 | } |
536 | } |
537 | } |
538 | } |
539 | |
540 | } // namespace amlogic |
541 | } // namespace android |
542 |