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 <common/utils/HwcTrace.h>
17#include <common/base/Drm.h>
18#include <Hwcomposer.h>
19#include <DisplayPlane.h>
20#include <IDisplayDevice.h>
21#include <common/base/HwcLayerList.h>
22#include <ips/tangier/TngDisplayContext.h>
23
24namespace android {
25namespace intel {
26
27TngDisplayContext::TngDisplayContext()
28    : mIMGDisplayDevice(0),
29      mInitialized(false),
30      mCount(0)
31{
32    CTRACE();
33}
34
35TngDisplayContext::~TngDisplayContext()
36{
37    WARN_IF_NOT_DEINIT();
38}
39
40bool TngDisplayContext::initialize()
41{
42    CTRACE();
43
44    // open frame buffer device
45    gralloc_module_t const* module;
46    int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
47    if (err) {
48        ELOGTRACE("failed to load gralloc module, error = %d", err);
49        return false;
50    }
51
52    // init IMG display device
53    err = module->perform(module, GRALLOC_MODULE_GET_DISPLAY_DEVICE_IMG, (void **)&mIMGDisplayDevice);
54    if (err) {
55        ELOGTRACE("failed to get display device, error = %d", err);
56        return false;
57    }
58
59    mCount = 0;
60    mInitialized = true;
61    return true;
62}
63
64bool TngDisplayContext::commitBegin(size_t /* numDisplays */,
65        hwc_display_contents_1_t ** /* displays */)
66{
67    RETURN_FALSE_IF_NOT_INIT();
68    mCount = 0;
69    return true;
70}
71
72bool 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        ELOGTRACE("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            ELOGTRACE("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            VLOGTRACE("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 = (uint32_t)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        VLOGTRACE("count %d, handle %#x, trans %#x, blending %#x"
124              " sourceCrop %f,%f - %fx%f, dst %d,%d - %dx%d, custom %#x",
125              mCount,
126              (uint32_t)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
144bool TngDisplayContext::commitEnd(size_t numDisplays, hwc_display_contents_1_t **displays)
145{
146    int releaseFenceFd = -1;
147
148    VLOGTRACE("count = %d", mCount);
149
150    if (mIMGDisplayDevice && mCount) {
151        int err = mIMGDisplayDevice->post(mIMGDisplayDevice,
152                                          mImgLayers,
153                                          mCount,
154                                          &releaseFenceFd);
155        if (err) {
156            ELOGTRACE("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 (size_t 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            VLOGTRACE("handle %#x, acquiredFD %d, releaseFD %d",
217                 (uint32_t)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
240bool TngDisplayContext::compositionComplete()
241{
242    return true;
243}
244
245bool TngDisplayContext::setCursorPosition(int disp, int x, int y)
246{
247    DLOGTRACE("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
264
265void TngDisplayContext::deinitialize()
266{
267    mIMGDisplayDevice = 0;
268
269    mCount = 0;
270    mInitialized = false;
271}
272
273
274} // namespace intel
275} // namespace android
276