hwc_utils.cpp revision e79c41329f1cc15bef9cb3a06eda7791e8cd4abe
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 * Copyright (C) 2012-2013, The Linux Foundation All rights reserved.
4 *
5 * Not a Contribution, Apache license notifications and license are retained
6 * for attribution purposes only.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 *      http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20#define HWC_UTILS_DEBUG 0
21#include <sys/ioctl.h>
22#include <EGL/egl.h>
23#include <cutils/properties.h>
24#include <gralloc_priv.h>
25#include <fb_priv.h>
26#include <overlay.h>
27#include "hwc_utils.h"
28#include "hwc_mdpcomp.h"
29#include "hwc_fbupdate.h"
30#include "mdp_version.h"
31#include "hwc_copybit.h"
32#include "external.h"
33#include "QService.h"
34#include "comptype.h"
35namespace qhwc {
36
37// Opens Framebuffer device
38static void openFramebufferDevice(hwc_context_t *ctx)
39{
40    hw_module_t const *module;
41    if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
42        framebuffer_open(module, &(ctx->mFbDev));
43        private_module_t* m = reinterpret_cast<private_module_t*>(
44                ctx->mFbDev->common.module);
45        //xres, yres may not be 32 aligned
46        ctx->dpyAttr[HWC_DISPLAY_PRIMARY].stride = m->finfo.line_length /
47                                                (m->info.xres/8);
48        ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres = m->info.xres;
49        ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres = m->info.yres;
50        ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xdpi = ctx->mFbDev->xdpi;
51        ctx->dpyAttr[HWC_DISPLAY_PRIMARY].ydpi = ctx->mFbDev->ydpi;
52        ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period =
53                1000000000l / ctx->mFbDev->fps;
54        ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd = openFb(HWC_DISPLAY_PRIMARY);
55    }
56}
57
58void initContext(hwc_context_t *ctx)
59{
60    openFramebufferDevice(ctx);
61    overlay::Overlay::initOverlay();
62    ctx->mOverlay = overlay::Overlay::getInstance();
63    ctx->mQService = qService::QService::getInstance(ctx);
64    ctx->mMDP.version = qdutils::MDPVersion::getInstance().getMDPVersion();
65    ctx->mMDP.hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay();
66    ctx->mMDP.panel = qdutils::MDPVersion::getInstance().getPanelType();
67    //Is created and destroyed only once for primary
68    //For external it could get created and destroyed multiple times depending
69    //on what external we connect to.
70    ctx->mFBUpdate[HWC_DISPLAY_PRIMARY] =
71        IFBUpdate::getObject(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres,
72        HWC_DISPLAY_PRIMARY);
73
74    char value[PROPERTY_VALUE_MAX];
75    // Check if the target supports copybit compostion (dyn/mdp/c2d) to
76    // decide if we need to open the copybit module.
77    int compositionType =
78        qdutils::QCCompositionType::getInstance().getCompositionType();
79
80    if (compositionType & (qdutils::COMPOSITION_TYPE_DYN |
81                           qdutils::COMPOSITION_TYPE_MDP |
82                           qdutils::COMPOSITION_TYPE_C2D)) {
83            ctx->mCopyBit[HWC_DISPLAY_PRIMARY] = new CopyBit();
84    }
85
86    ctx->mExtDisplay = new ExternalDisplay(ctx);
87    for (uint32_t i = 0; i < HWC_NUM_DISPLAY_TYPES; i++)
88        ctx->mLayerCache[i] = new LayerCache();
89    ctx->mMDPComp = MDPComp::getObject(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres);
90    MDPComp::init(ctx);
91
92    pthread_mutex_init(&(ctx->vstate.lock), NULL);
93    pthread_cond_init(&(ctx->vstate.cond), NULL);
94    ctx->vstate.enable = false;
95    ctx->mExtDispConfiguring = false;
96    ALOGI("Initializing Qualcomm Hardware Composer");
97    ALOGI("MDP version: %d", ctx->mMDP.version);
98}
99
100void closeContext(hwc_context_t *ctx)
101{
102    if(ctx->mOverlay) {
103        delete ctx->mOverlay;
104        ctx->mOverlay = NULL;
105    }
106
107    for(int i = 0; i< HWC_NUM_DISPLAY_TYPES; i++) {
108        if(ctx->mCopyBit[i]) {
109            delete ctx->mCopyBit[i];
110            ctx->mCopyBit[i] = NULL;
111        }
112    }
113
114    if(ctx->mFbDev) {
115        framebuffer_close(ctx->mFbDev);
116        ctx->mFbDev = NULL;
117        close(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd);
118        ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd = -1;
119    }
120
121    if(ctx->mExtDisplay) {
122        delete ctx->mExtDisplay;
123        ctx->mExtDisplay = NULL;
124    }
125
126    for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
127        if(ctx->mFBUpdate[i]) {
128            delete ctx->mFBUpdate[i];
129            ctx->mFBUpdate[i] = NULL;
130        }
131    }
132
133    if(ctx->mMDPComp) {
134        delete ctx->mMDPComp;
135        ctx->mMDPComp = NULL;
136    }
137
138    pthread_mutex_destroy(&(ctx->vstate.lock));
139    pthread_cond_destroy(&(ctx->vstate.cond));
140}
141
142
143void dumpsys_log(android::String8& buf, const char* fmt, ...)
144{
145    va_list varargs;
146    va_start(varargs, fmt);
147    buf.appendFormatV(fmt, varargs);
148    va_end(varargs);
149}
150
151/* Calculates the destination position based on the action safe rectangle */
152void getActionSafePosition(hwc_context_t *ctx, int dpy, uint32_t& x,
153                           uint32_t& y, uint32_t& w, uint32_t& h) {
154
155    // if external supports underscan, do nothing
156    // it will be taken care in the driver
157    if(ctx->mExtDisplay->isCEUnderscanSupported())
158        return;
159
160    float wRatio = 1.0;
161    float hRatio = 1.0;
162    float xRatio = 1.0;
163    float yRatio = 1.0;
164
165    float fbWidth = ctx->dpyAttr[dpy].xres;
166    float fbHeight = ctx->dpyAttr[dpy].yres;
167
168    float asX = 0;
169    float asY = 0;
170    float asW = fbWidth;
171    float asH= fbHeight;
172    char value[PROPERTY_VALUE_MAX];
173
174    // Apply action safe parameters
175    property_get("hw.actionsafe.width", value, "0");
176    int asWidthRatio = atoi(value);
177    property_get("hw.actionsafe.height", value, "0");
178    int asHeightRatio = atoi(value);
179    // based on the action safe ratio, get the Action safe rectangle
180    asW = fbWidth * (1.0f -  asWidthRatio / 100.0f);
181    asH = fbHeight * (1.0f -  asHeightRatio / 100.0f);
182    asX = (fbWidth - asW) / 2;
183    asY = (fbHeight - asH) / 2;
184
185    // calculate the position ratio
186    xRatio = (float)x/fbWidth;
187    yRatio = (float)y/fbHeight;
188    wRatio = (float)w/fbWidth;
189    hRatio = (float)h/fbHeight;
190
191    //Calculate the position...
192    x = (xRatio * asW) + asX;
193    y = (yRatio * asH) + asY;
194    w = (wRatio * asW);
195    h = (hRatio * asH);
196
197    return;
198}
199
200static inline bool isAlphaScaled(hwc_layer_1_t const* layer) {
201    int dst_w, dst_h, src_w, src_h;
202
203    hwc_rect_t displayFrame  = layer->displayFrame;
204    hwc_rect_t sourceCrop = layer->sourceCrop;
205
206    dst_w = displayFrame.right - displayFrame.left;
207    dst_h = displayFrame.bottom - displayFrame.top;
208
209    src_w = sourceCrop.right - sourceCrop.left;
210    src_h = sourceCrop.bottom - sourceCrop.top;
211
212    if(((src_w != dst_w) || (src_h != dst_h))) {
213        if(layer->blending != HWC_BLENDING_NONE)
214            return true;
215    }
216    return false;
217}
218
219void setListStats(hwc_context_t *ctx,
220        const hwc_display_contents_1_t *list, int dpy) {
221
222    ctx->listStats[dpy].numAppLayers = list->numHwLayers - 1;
223    ctx->listStats[dpy].fbLayerIndex = list->numHwLayers - 1;
224    ctx->listStats[dpy].skipCount = 0;
225    ctx->listStats[dpy].needsAlphaScale = false;
226    ctx->listStats[dpy].yuvCount = 0;
227
228    for (size_t i = 0; i < list->numHwLayers; i++) {
229        hwc_layer_1_t const* layer = &list->hwLayers[i];
230        private_handle_t *hnd = (private_handle_t *)layer->handle;
231
232        //reset stored yuv index
233        ctx->listStats[dpy].yuvIndices[i] = -1;
234
235        if(list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
236            continue;
237        //We disregard FB being skip for now! so the else if
238        } else if (isSkipLayer(&list->hwLayers[i])) {
239            ctx->listStats[dpy].skipCount++;
240        } else if (UNLIKELY(isYuvBuffer(hnd))) {
241            int& yuvCount = ctx->listStats[dpy].yuvCount;
242            ctx->listStats[dpy].yuvIndices[yuvCount] = i;
243            yuvCount++;
244        }
245
246        if(!ctx->listStats[dpy].needsAlphaScale)
247            ctx->listStats[dpy].needsAlphaScale = isAlphaScaled(layer);
248    }
249}
250
251
252static inline void calc_cut(float& leftCutRatio, float& topCutRatio,
253        float& rightCutRatio, float& bottomCutRatio, int orient) {
254    if(orient & HAL_TRANSFORM_FLIP_H) {
255        swap(leftCutRatio, rightCutRatio);
256    }
257    if(orient & HAL_TRANSFORM_FLIP_V) {
258        swap(topCutRatio, bottomCutRatio);
259    }
260    if(orient & HAL_TRANSFORM_ROT_90) {
261        //Anti clock swapping
262        float tmpCutRatio = leftCutRatio;
263        leftCutRatio = topCutRatio;
264        topCutRatio = rightCutRatio;
265        rightCutRatio = bottomCutRatio;
266        bottomCutRatio = tmpCutRatio;
267    }
268}
269
270bool isSecuring(hwc_context_t* ctx) {
271    if((ctx->mMDP.version < qdutils::MDSS_V5) &&
272       (ctx->mMDP.version > qdutils::MDP_V3_0) &&
273        ctx->mSecuring) {
274        return true;
275    }
276    return false;
277}
278
279bool isSecureModePolicy(int mdpVersion) {
280    if (mdpVersion < qdutils::MDSS_V5)
281        return true;
282    else
283        return false;
284}
285
286//Crops source buffer against destination and FB boundaries
287void calculate_crop_rects(hwc_rect_t& crop, hwc_rect_t& dst,
288        const int fbWidth, const int fbHeight, int orient) {
289    int& crop_l = crop.left;
290    int& crop_t = crop.top;
291    int& crop_r = crop.right;
292    int& crop_b = crop.bottom;
293    int crop_w = crop.right - crop.left;
294    int crop_h = crop.bottom - crop.top;
295
296    int& dst_l = dst.left;
297    int& dst_t = dst.top;
298    int& dst_r = dst.right;
299    int& dst_b = dst.bottom;
300    int dst_w = abs(dst.right - dst.left);
301    int dst_h = abs(dst.bottom - dst.top);
302
303    float leftCutRatio = 0.0f, rightCutRatio = 0.0f, topCutRatio = 0.0f,
304            bottomCutRatio = 0.0f;
305
306    if(dst_l < 0) {
307        leftCutRatio = (float)(0.0f - dst_l) / (float)dst_w;
308        dst_l = 0;
309    }
310    if(dst_r > fbWidth) {
311        rightCutRatio = (float)(dst_r - fbWidth) / (float)dst_w;
312        dst_r = fbWidth;
313    }
314    if(dst_t < 0) {
315        topCutRatio = (float)(0 - dst_t) / (float)dst_h;
316        dst_t = 0;
317    }
318    if(dst_b > fbHeight) {
319        bottomCutRatio = (float)(dst_b - fbHeight) / (float)dst_h;
320        dst_b = fbHeight;
321    }
322
323    calc_cut(leftCutRatio, topCutRatio, rightCutRatio, bottomCutRatio, orient);
324    crop_l += crop_w * leftCutRatio;
325    crop_t += crop_h * topCutRatio;
326    crop_r -= crop_w * rightCutRatio;
327    crop_b -= crop_h * bottomCutRatio;
328}
329
330bool isExternalActive(hwc_context_t* ctx) {
331    return ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive;
332}
333
334int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy,
335                                                        int fd) {
336    int ret = 0;
337    struct mdp_buf_sync data;
338    int acquireFd[MAX_NUM_LAYERS];
339    int count = 0;
340    int releaseFd = -1;
341    int fbFd = -1;
342    memset(&data, 0, sizeof(data));
343    bool swapzero = false;
344    data.flags = MDP_BUF_SYNC_FLAG_WAIT;
345    data.acq_fen_fd = acquireFd;
346    data.rel_fen_fd = &releaseFd;
347    char property[PROPERTY_VALUE_MAX];
348    if(property_get("debug.egl.swapinterval", property, "1") > 0) {
349        if(atoi(property) == 0)
350            swapzero = true;
351    }
352
353    //Accumulate acquireFenceFds
354    for(uint32_t i = 0; i < list->numHwLayers; i++) {
355        if(list->hwLayers[i].compositionType == HWC_OVERLAY &&
356                        list->hwLayers[i].acquireFenceFd != -1) {
357            if(UNLIKELY(swapzero))
358                acquireFd[count++] = -1;
359            else
360                acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
361        }
362        if(list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
363            if(UNLIKELY(swapzero))
364                acquireFd[count++] = -1;
365            else if(fd != -1) {
366                //set the acquireFD from fd - which is coming from c2d
367                acquireFd[count++] = fd;
368                // Buffer sync IOCTL should be async when using c2d fence is
369                // used
370                data.flags &= ~MDP_BUF_SYNC_FLAG_WAIT;
371            } else if(list->hwLayers[i].acquireFenceFd != -1)
372                acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
373        }
374    }
375
376    data.acq_fen_fd_cnt = count;
377    fbFd = ctx->dpyAttr[dpy].fd;
378    //Waits for acquire fences, returns a release fence
379    if(LIKELY(!swapzero)) {
380        uint64_t start = systemTime();
381        ret = ioctl(fbFd, MSMFB_BUFFER_SYNC, &data);
382        ALOGD_IF(HWC_UTILS_DEBUG, "%s: time taken for MSMFB_BUFFER_SYNC IOCTL = %d",
383                            __FUNCTION__, (size_t) ns2ms(systemTime() - start));
384    }
385    if(ret < 0) {
386        ALOGE("ioctl MSMFB_BUFFER_SYNC failed, err=%s",
387                strerror(errno));
388    }
389    for(uint32_t i = 0; i < list->numHwLayers; i++) {
390        if(list->hwLayers[i].compositionType == HWC_OVERLAY ||
391           list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
392            //Close the acquireFenceFds
393            if(list->hwLayers[i].acquireFenceFd > 0) {
394                close(list->hwLayers[i].acquireFenceFd);
395                list->hwLayers[i].acquireFenceFd = -1;
396            }
397            if(fd > 0) {
398                close(fd);
399                fd = -1;
400            }
401            //Populate releaseFenceFds.
402            if(UNLIKELY(swapzero))
403                list->hwLayers[i].releaseFenceFd = -1;
404            else
405                list->hwLayers[i].releaseFenceFd = dup(releaseFd);
406        }
407    }
408    if(UNLIKELY(swapzero)){
409        list->retireFenceFd = -1;
410        close(releaseFd);
411    } else {
412        list->retireFenceFd = releaseFd;
413    }
414    return ret;
415}
416
417void LayerCache::resetLayerCache(int num) {
418    for(uint32_t i = 0; i < MAX_NUM_LAYERS; i++) {
419        hnd[i] = NULL;
420    }
421    numHwLayers = num;
422}
423
424void LayerCache::updateLayerCache(hwc_display_contents_1_t* list) {
425
426    int numFbLayers = 0;
427    int numCacheableLayers = 0;
428
429    canUseLayerCache = false;
430    //Bail if geometry changed or num of layers changed
431    if(list->flags & HWC_GEOMETRY_CHANGED ||
432       list->numHwLayers != numHwLayers ) {
433        resetLayerCache(list->numHwLayers);
434        return;
435    }
436
437    for(uint32_t i = 0; i < list->numHwLayers; i++) {
438        //Bail on skip layers
439        if(list->hwLayers[i].flags & HWC_SKIP_LAYER) {
440            resetLayerCache(list->numHwLayers);
441            return;
442        }
443
444        if(list->hwLayers[i].compositionType == HWC_FRAMEBUFFER) {
445            numFbLayers++;
446            if(hnd[i] == NULL) {
447                hnd[i] = list->hwLayers[i].handle;
448            } else if (hnd[i] ==
449                       list->hwLayers[i].handle) {
450                numCacheableLayers++;
451            } else {
452                hnd[i] = NULL;
453                return;
454            }
455        } else {
456            hnd[i] = NULL;
457        }
458    }
459    if(numFbLayers == numCacheableLayers)
460        canUseLayerCache = true;
461
462    //XXX: The marking part is separate, if MDP comp wants
463    // to use it in the future. Right now getting MDP comp
464    // to use this is more trouble than it is worth.
465    markCachedLayersAsOverlay(list);
466}
467
468void LayerCache::markCachedLayersAsOverlay(hwc_display_contents_1_t* list) {
469    //This optimization only works if ALL the layer handles
470    //that were on the framebuffer didn't change.
471    if(canUseLayerCache){
472        for(uint32_t i = 0; i < list->numHwLayers; i++) {
473            if (list->hwLayers[i].handle &&
474                list->hwLayers[i].handle == hnd[i] &&
475                list->hwLayers[i].compositionType != HWC_FRAMEBUFFER_TARGET)
476            {
477                list->hwLayers[i].compositionType = HWC_OVERLAY;
478            }
479        }
480    }
481
482}
483
484};//namespace
485