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 #include <HwcTrace.h>
17 #include <Hwcomposer.h>
18 #include <Drm.h>
19 #include <DisplayPlane.h>
20 #include <IDisplayDevice.h>
21 #include <HwcLayerList.h>
22 #include <tangier/TngDisplayContext.h>
23
24
25 namespace android {
26 namespace intel {
27
TngDisplayContext()28 TngDisplayContext::TngDisplayContext()
29 : mIMGDisplayDevice(0),
30 mInitialized(false),
31 mCount(0)
32 {
33 CTRACE();
34 }
35
~TngDisplayContext()36 TngDisplayContext::~TngDisplayContext()
37 {
38 WARN_IF_NOT_DEINIT();
39 }
40
initialize()41 bool TngDisplayContext::initialize()
42 {
43 CTRACE();
44
45 // open frame buffer device
46 gralloc_module_t const* module;
47 int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
48 if (err) {
49 ETRACE("failed to load gralloc module, error = %d", err);
50 return false;
51 }
52
53 // init IMG display device
54 err = module->perform(module, GRALLOC_MODULE_GET_DISPLAY_DEVICE_IMG, (void **)&mIMGDisplayDevice);
55 if (err) {
56 ETRACE("failed to get display device, error = %d", err);
57 return false;
58 }
59
60 mCount = 0;
61 mInitialized = true;
62 return true;
63 }
64
commitBegin(size_t numDisplays,hwc_display_contents_1_t ** displays)65 bool TngDisplayContext::commitBegin(size_t numDisplays, hwc_display_contents_1_t **displays)
66 {
67 RETURN_FALSE_IF_NOT_INIT();
68 mCount = 0;
69 return true;
70 }
71
commitContents(hwc_display_contents_1_t * display,HwcLayerList * layerList)72 bool TngDisplayContext::commitContents(hwc_display_contents_1_t *display, HwcLayerList *layerList)
73 {
74 bool ret;
75
76 RETURN_FALSE_IF_NOT_INIT();
77
78 if (!display || !layerList) {
79 ETRACE("invalid parameters");
80 return false;
81 }
82
83 IMG_hwc_layer_t *imgLayerList = (IMG_hwc_layer_t*)mImgLayers;
84
85 for (size_t i = 0; i < display->numHwLayers; i++) {
86 if (mCount >= MAXIMUM_LAYER_NUMBER) {
87 ETRACE("layer count exceeds the limit");
88 return false;
89 }
90
91 // check layer parameters
92 if (!display->hwLayers[i].handle) {
93 continue;
94 }
95
96 DisplayPlane* plane = layerList->getPlane(i);
97 if (!plane) {
98 continue;
99 }
100
101 ret = plane->flip(NULL);
102 if (ret == false) {
103 VTRACE("failed to flip plane %d", i);
104 continue;
105 }
106
107 IMG_hwc_layer_t *imgLayer = &imgLayerList[mCount++];
108 // update IMG layer
109 imgLayer->psLayer = &display->hwLayers[i];
110 imgLayer->custom = (unsigned long)plane->getContext();
111 struct intel_dc_plane_ctx *ctx =
112 (struct intel_dc_plane_ctx *)imgLayer->custom;
113 // update z order
114 Hwcomposer& hwc = Hwcomposer::getInstance();
115 DisplayPlaneManager *pm = hwc.getPlaneManager();
116 void *config = pm->getZOrderConfig();
117 if (config) {
118 memcpy(&ctx->zorder, config, sizeof(ctx->zorder));
119 } else {
120 memset(&ctx->zorder, 0, sizeof(ctx->zorder));
121 }
122
123 VTRACE("count %p, handle %#x, trans %#x, blending %#x"
124 " sourceCrop %f,%f - %fx%f, dst %d,%d - %dx%d, custom %#x",
125 mCount,
126 imgLayer->psLayer->handle,
127 imgLayer->psLayer->transform,
128 imgLayer->psLayer->blending,
129 imgLayer->psLayer->sourceCropf.left,
130 imgLayer->psLayer->sourceCropf.top,
131 imgLayer->psLayer->sourceCropf.right - imgLayer->psLayer->sourceCropf.left,
132 imgLayer->psLayer->sourceCropf.bottom - imgLayer->psLayer->sourceCropf.top,
133 imgLayer->psLayer->displayFrame.left,
134 imgLayer->psLayer->displayFrame.top,
135 imgLayer->psLayer->displayFrame.right - imgLayer->psLayer->displayFrame.left,
136 imgLayer->psLayer->displayFrame.bottom - imgLayer->psLayer->displayFrame.top,
137 imgLayer->custom);
138 }
139
140 layerList->postFlip();
141 return true;
142 }
143
commitEnd(size_t numDisplays,hwc_display_contents_1_t ** displays)144 bool TngDisplayContext::commitEnd(size_t numDisplays, hwc_display_contents_1_t **displays)
145 {
146 int releaseFenceFd = -1;
147
148 VTRACE("count = %d", mCount);
149
150 if (mIMGDisplayDevice && mCount) {
151 int err = mIMGDisplayDevice->post(mIMGDisplayDevice,
152 mImgLayers,
153 mCount,
154 &releaseFenceFd);
155 if (err) {
156 ETRACE("post failed, err = %d", err);
157 return false;
158 }
159 }
160
161 // close acquire fence
162 for (size_t i = 0; i < numDisplays; i++) {
163 // Wait and close HWC_OVERLAY typed layer's acquire fence
164 hwc_display_contents_1_t* display = displays[i];
165 if (!display) {
166 continue;
167 }
168
169 for (size_t j = 0; j < display->numHwLayers-1; j++) {
170 hwc_layer_1_t& layer = display->hwLayers[j];
171 if (layer.compositionType == HWC_OVERLAY) {
172 if (layer.acquireFenceFd != -1) {
173 // sync_wait(layer.acquireFenceFd, 16ms);
174 close(layer.acquireFenceFd);
175 layer.acquireFenceFd = -1;
176 }
177 }
178 }
179
180 // Wait and close framebuffer target layer's acquire fence
181 hwc_layer_1_t& fbt = display->hwLayers[display->numHwLayers-1];
182 if (fbt.acquireFenceFd != -1) {
183 // sync_wait(fbt.acquireFencdFd, 16ms);
184 close(fbt.acquireFenceFd);
185 fbt.acquireFenceFd = -1;
186 }
187
188 // Wait and close outbuf's acquire fence
189 if (display->outbufAcquireFenceFd != -1) {
190 // sync_wait(display->outbufAcquireFenceFd, 16ms);
191 close(display->outbufAcquireFenceFd);
192 display->outbufAcquireFenceFd = -1;
193 }
194 }
195
196 // update release fence and retire fence
197 if (mCount > 0) {
198 // For physical displays, dup the releaseFenceFd only for
199 // HWC layers which successfully flipped to display planes
200 IMG_hwc_layer_t *imgLayerList = (IMG_hwc_layer_t*)mImgLayers;
201
202 for (unsigned int i = 0; i < mCount; i++) {
203 IMG_hwc_layer_t *imgLayer = &imgLayerList[i];
204 imgLayer->psLayer->releaseFenceFd =
205 (releaseFenceFd != -1) ? dup(releaseFenceFd) : -1;
206 }
207 }
208
209 for (size_t i = 0; i < numDisplays; i++) {
210 if (!displays[i]) {
211 continue;
212 }
213
214 // log for layer fence status
215 for (size_t j = 0; j < displays[i]->numHwLayers; j++) {
216 VTRACE("handle %#p, acquiredFD %d, releaseFD %d",
217 displays[i]->hwLayers[j].handle,
218 displays[i]->hwLayers[j].acquireFenceFd,
219 displays[i]->hwLayers[j].releaseFenceFd);
220 }
221
222 // retireFence is used for SurfaceFlinger to do DispSync;
223 // dup releaseFenceFd for physical displays and ignore virtual
224 // display; we don't distinguish between release and retire, and all
225 // physical displays are using a single releaseFence; for virtual
226 // display, fencing is handled by the VirtualDisplay class
227 if (i < IDisplayDevice::DEVICE_VIRTUAL) {
228 displays[i]->retireFenceFd =
229 (releaseFenceFd != -1) ? dup(releaseFenceFd) : -1;
230 }
231 }
232
233 // close original release fence fd
234 if (releaseFenceFd != -1) {
235 close(releaseFenceFd);
236 }
237 return true;
238 }
239
compositionComplete()240 bool TngDisplayContext::compositionComplete()
241 {
242 return true;
243 }
244
setCursorPosition(int disp,int x,int y)245 bool TngDisplayContext::setCursorPosition(int disp, int x, int y)
246 {
247 DTRACE("setCursorPosition");
248 struct intel_dc_cursor_ctx ctx;
249 memset(&ctx, 0, sizeof(ctx));
250 ctx.pipe = disp;
251 if (x < 0) {
252 ctx.pos |= 1 << 15;
253 x = -x;
254 }
255 if (y < 0) {
256 ctx.pos |= 1 << 31;
257 y = -y;
258 }
259 ctx.pos |= (y & 0xfff) << 16 | (x & 0xfff);
260 Drm *drm = Hwcomposer::getInstance().getDrm();
261 return drm->writeIoctl(DRM_PSB_UPDATE_CURSOR_POS, &ctx, sizeof(ctx));
262 }
263
deinitialize()264 void TngDisplayContext::deinitialize()
265 {
266 mIMGDisplayDevice = 0;
267
268 mCount = 0;
269 mInitialized = false;
270 }
271
272
273 } // namespace intel
274 } // namespace android
275