blob: dea82dfff823652d6610beadf886d8d8d22f2c9b [file] [log] [blame]
Naseer Ahmed29a26812012-06-14 00:56:20 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
Saurabh Shah56f610d2012-08-07 15:27:06 -07003 * Copyright (C) 2012, The Linux Foundation All rights reserved.
Naseer Ahmed29a26812012-06-14 00:56:20 -07004 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
Naseer Ahmed758bfc52012-11-28 17:02:08 -050018#include <sys/ioctl.h>
Naseer Ahmed5b6708a2012-08-02 13:46:08 -070019#include <EGL/egl.h>
Saurabh Shahfc2acbe2012-08-17 19:47:52 -070020#include <cutils/properties.h>
21#include <gralloc_priv.h>
22#include <fb_priv.h>
Naseer Ahmed758bfc52012-11-28 17:02:08 -050023#include <overlay.h>
Naseer Ahmed29a26812012-06-14 00:56:20 -070024#include "hwc_utils.h"
Naseer Ahmeda87da602012-07-01 23:54:19 -070025#include "mdp_version.h"
Saurabh Shah56f610d2012-08-07 15:27:06 -070026#include "external.h"
Saurabh Shah56f610d2012-08-07 15:27:06 -070027#include "QService.h"
Naseer Ahmed72cf9762012-07-21 12:17:13 -070028
Naseer Ahmed29a26812012-06-14 00:56:20 -070029namespace qhwc {
Naseer Ahmed72cf9762012-07-21 12:17:13 -070030
31// Opens Framebuffer device
32static void openFramebufferDevice(hwc_context_t *ctx)
33{
34 hw_module_t const *module;
35 if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
36 framebuffer_open(module, &(ctx->mFbDev));
Saurabh Shah3e858eb2012-09-17 16:53:21 -070037 private_module_t* m = reinterpret_cast<private_module_t*>(
38 ctx->mFbDev->common.module);
39 //xres, yres may not be 32 aligned
40 ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres = m->info.xres;
41 ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres = m->info.yres;
42 ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xdpi = ctx->mFbDev->xdpi;
43 ctx->dpyAttr[HWC_DISPLAY_PRIMARY].ydpi = ctx->mFbDev->ydpi;
44 ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period =
45 1000000000l / ctx->mFbDev->fps;
46 ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd = openFb(HWC_DISPLAY_PRIMARY);
Naseer Ahmed72cf9762012-07-21 12:17:13 -070047 }
48}
49
Naseer Ahmed29a26812012-06-14 00:56:20 -070050void initContext(hwc_context_t *ctx)
51{
Naseer Ahmed72cf9762012-07-21 12:17:13 -070052 openFramebufferDevice(ctx);
Saurabh Shahc4d034f2012-09-27 15:55:15 -070053 overlay::Overlay::initOverlay();
Naseer Ahmed758bfc52012-11-28 17:02:08 -050054 ctx->mOverlay = overlay::Overlay::getInstance();
Saurabh Shah56f610d2012-08-07 15:27:06 -070055 ctx->mQService = qService::QService::getInstance(ctx);
Naseer Ahmed96c4c952012-07-25 18:27:14 -070056 ctx->mMDP.version = qdutils::MDPVersion::getInstance().getMDPVersion();
57 ctx->mMDP.hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay();
58 ctx->mMDP.panel = qdutils::MDPVersion::getInstance().getPanelType();
Naseer Ahmed72cf9762012-07-21 12:17:13 -070059 ctx->mExtDisplay = new ExternalDisplay(ctx);
Naseer Ahmedb1c76322012-10-17 00:32:50 -040060 ctx->mLayerCache = new LayerCache();
Naseer Ahmed72cf9762012-07-21 12:17:13 -070061
Naseer Ahmedff4f0252012-10-01 13:03:01 -040062 pthread_mutex_init(&(ctx->vstate.lock), NULL);
63 pthread_cond_init(&(ctx->vstate.cond), NULL);
64 ctx->vstate.enable = false;
65
Naseer Ahmed72cf9762012-07-21 12:17:13 -070066 ALOGI("Initializing Qualcomm Hardware Composer");
Naseer Ahmed96c4c952012-07-25 18:27:14 -070067 ALOGI("MDP version: %d", ctx->mMDP.version);
Naseer Ahmed29a26812012-06-14 00:56:20 -070068}
69
70void closeContext(hwc_context_t *ctx)
71{
Naseer Ahmed758bfc52012-11-28 17:02:08 -050072 if(ctx->mOverlay) {
73 delete ctx->mOverlay;
74 ctx->mOverlay = NULL;
Naseer Ahmed29a26812012-06-14 00:56:20 -070075 }
Naseer Ahmedf48aef62012-07-20 09:05:53 -070076
Naseer Ahmed72cf9762012-07-21 12:17:13 -070077 if(ctx->mFbDev) {
78 framebuffer_close(ctx->mFbDev);
79 ctx->mFbDev = NULL;
Saurabh Shah3e858eb2012-09-17 16:53:21 -070080 close(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd);
81 ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd = -1;
Naseer Ahmed29a26812012-06-14 00:56:20 -070082 }
Naseer Ahmed72cf9762012-07-21 12:17:13 -070083
84 if(ctx->mExtDisplay) {
85 delete ctx->mExtDisplay;
86 ctx->mExtDisplay = NULL;
87 }
Naseer Ahmedff4f0252012-10-01 13:03:01 -040088
89 pthread_mutex_destroy(&(ctx->vstate.lock));
90 pthread_cond_destroy(&(ctx->vstate.cond));
91
Naseer Ahmed29a26812012-06-14 00:56:20 -070092}
93
Naseer Ahmed5b6708a2012-08-02 13:46:08 -070094void dumpLayer(hwc_layer_1_t const* l)
Naseer Ahmed29a26812012-06-14 00:56:20 -070095{
96 ALOGD("\ttype=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, {%d,%d,%d,%d}"
97 ", {%d,%d,%d,%d}",
98 l->compositionType, l->flags, l->handle, l->transform, l->blending,
99 l->sourceCrop.left,
100 l->sourceCrop.top,
101 l->sourceCrop.right,
102 l->sourceCrop.bottom,
103 l->displayFrame.left,
104 l->displayFrame.top,
105 l->displayFrame.right,
106 l->displayFrame.bottom);
107}
108
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700109void setListStats(hwc_context_t *ctx,
110 const hwc_display_contents_1_t *list, int dpy) {
111
112 ctx->listStats[dpy].numAppLayers = list->numHwLayers - 1;
113 ctx->listStats[dpy].fbLayerIndex = list->numHwLayers - 1;
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700114 ctx->listStats[dpy].yuvCount = 0;
115 ctx->listStats[dpy].yuvIndex = -1;
116 ctx->listStats[dpy].skipCount = 0;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700117
118 for (size_t i = 0; i < list->numHwLayers; i++) {
119 private_handle_t *hnd =
120 (private_handle_t *)list->hwLayers[i].handle;
121
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700122 if(list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
123 continue;
124 //We disregard FB being skip for now! so the else if
Saurabh Shah35712cb2012-09-14 10:28:18 -0700125 } else if (isSkipLayer(&list->hwLayers[i])) {
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700126 ctx->listStats[dpy].skipCount++;
127 }
128
129 if (UNLIKELY(isYuvBuffer(hnd))) {
130 ctx->listStats[dpy].yuvCount++;
131 ctx->listStats[dpy].yuvIndex = i;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700132 }
133 }
Naseer Ahmed29a26812012-06-14 00:56:20 -0700134}
135
Saurabh Shah541b59d2012-10-11 11:08:12 -0700136static inline void calc_cut(float& leftCutRatio, float& topCutRatio,
137 float& rightCutRatio, float& bottomCutRatio, int orient) {
Saurabh Shah27c1d652012-08-14 19:30:28 -0700138 if(orient & HAL_TRANSFORM_FLIP_H) {
Saurabh Shah541b59d2012-10-11 11:08:12 -0700139 swap(leftCutRatio, rightCutRatio);
Saurabh Shah27c1d652012-08-14 19:30:28 -0700140 }
141 if(orient & HAL_TRANSFORM_FLIP_V) {
Saurabh Shah541b59d2012-10-11 11:08:12 -0700142 swap(topCutRatio, bottomCutRatio);
Saurabh Shah27c1d652012-08-14 19:30:28 -0700143 }
144 if(orient & HAL_TRANSFORM_ROT_90) {
145 //Anti clock swapping
Saurabh Shah541b59d2012-10-11 11:08:12 -0700146 float tmpCutRatio = leftCutRatio;
147 leftCutRatio = topCutRatio;
148 topCutRatio = rightCutRatio;
149 rightCutRatio = bottomCutRatio;
150 bottomCutRatio = tmpCutRatio;
Saurabh Shah27c1d652012-08-14 19:30:28 -0700151 }
152}
153
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700154//Crops source buffer against destination and FB boundaries
155void calculate_crop_rects(hwc_rect_t& crop, hwc_rect_t& dst,
Saurabh Shah27c1d652012-08-14 19:30:28 -0700156 const int fbWidth, const int fbHeight, int orient) {
157 int& crop_l = crop.left;
158 int& crop_t = crop.top;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700159 int& crop_r = crop.right;
160 int& crop_b = crop.bottom;
161 int crop_w = crop.right - crop.left;
162 int crop_h = crop.bottom - crop.top;
163
Saurabh Shah27c1d652012-08-14 19:30:28 -0700164 int& dst_l = dst.left;
165 int& dst_t = dst.top;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700166 int& dst_r = dst.right;
167 int& dst_b = dst.bottom;
Saurabh Shah27c1d652012-08-14 19:30:28 -0700168 int dst_w = abs(dst.right - dst.left);
169 int dst_h = abs(dst.bottom - dst.top);
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700170
Saurabh Shah541b59d2012-10-11 11:08:12 -0700171 float leftCutRatio = 0.0f, rightCutRatio = 0.0f, topCutRatio = 0.0f,
172 bottomCutRatio = 0.0f;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700173
Saurabh Shah27c1d652012-08-14 19:30:28 -0700174 if(dst_l < 0) {
Saurabh Shah541b59d2012-10-11 11:08:12 -0700175 leftCutRatio = (float)(0.0f - dst_l) / (float)dst_w;
Saurabh Shah27c1d652012-08-14 19:30:28 -0700176 dst_l = 0;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700177 }
178 if(dst_r > fbWidth) {
Saurabh Shah541b59d2012-10-11 11:08:12 -0700179 rightCutRatio = (float)(dst_r - fbWidth) / (float)dst_w;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700180 dst_r = fbWidth;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700181 }
Saurabh Shah27c1d652012-08-14 19:30:28 -0700182 if(dst_t < 0) {
Saurabh Shah541b59d2012-10-11 11:08:12 -0700183 topCutRatio = (float)(0 - dst_t) / (float)dst_h;
Saurabh Shah27c1d652012-08-14 19:30:28 -0700184 dst_t = 0;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700185 }
186 if(dst_b > fbHeight) {
Saurabh Shah541b59d2012-10-11 11:08:12 -0700187 bottomCutRatio = (float)(dst_b - fbHeight) / (float)dst_h;
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700188 dst_b = fbHeight;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700189 }
Saurabh Shah27c1d652012-08-14 19:30:28 -0700190
Saurabh Shah541b59d2012-10-11 11:08:12 -0700191 calc_cut(leftCutRatio, topCutRatio, rightCutRatio, bottomCutRatio, orient);
192 crop_l += crop_w * leftCutRatio;
193 crop_t += crop_h * topCutRatio;
194 crop_r -= crop_w * rightCutRatio;
195 crop_b -= crop_h * bottomCutRatio;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700196}
Naseer Ahmedf48aef62012-07-20 09:05:53 -0700197
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700198bool isExternalActive(hwc_context_t* ctx) {
199 return ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive;
Saurabh Shahfc2acbe2012-08-17 19:47:52 -0700200}
201
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700202int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy) {
Kinjal Bhavsar2dd04a82012-09-18 18:27:59 -0700203 int ret = 0;
204#ifdef USE_FENCE_SYNC
205 struct mdp_buf_sync data;
Naseer Ahmedb1c76322012-10-17 00:32:50 -0400206 int acquireFd[MAX_NUM_LAYERS];
Kinjal Bhavsar2dd04a82012-09-18 18:27:59 -0700207 int count = 0;
208 int releaseFd = -1;
209 int fbFd = -1;
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700210 data.flags = MDP_BUF_SYNC_FLAG_WAIT;
Kinjal Bhavsar2dd04a82012-09-18 18:27:59 -0700211 data.acq_fen_fd = acquireFd;
212 data.rel_fen_fd = &releaseFd;
213 //Accumulate acquireFenceFds
214 for(uint32_t i = 0; i < list->numHwLayers; i++) {
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700215 if((list->hwLayers[i].compositionType == HWC_OVERLAY ||
216 list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) &&
Naseer Ahmedb1c76322012-10-17 00:32:50 -0400217 list->hwLayers[i].acquireFenceFd != -1 &&
218 (list->hwLayers[i].flags & HWC_MDPCOMP)) {
Kinjal Bhavsar2dd04a82012-09-18 18:27:59 -0700219 acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
220 }
221 }
222
Kinjal Bhavsar40a1cc52012-10-10 15:52:03 -0700223 data.acq_fen_fd_cnt = count;
224 fbFd = ctx->dpyAttr[dpy].fd;
Kinjal Bhavsar2dd04a82012-09-18 18:27:59 -0700225
Kinjal Bhavsar40a1cc52012-10-10 15:52:03 -0700226 //Waits for acquire fences, returns a release fence
227 ret = ioctl(fbFd, MSMFB_BUFFER_SYNC, &data);
228 if(ret < 0) {
229 ALOGE("ioctl MSMFB_BUFFER_SYNC failed, err=%s",
230 strerror(errno));
Kinjal Bhavsar2dd04a82012-09-18 18:27:59 -0700231 }
Kinjal Bhavsar40a1cc52012-10-10 15:52:03 -0700232
233 for(uint32_t i = 0; i < list->numHwLayers; i++) {
234 if((list->hwLayers[i].compositionType == HWC_OVERLAY ||
235 list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET)) {
236 //Close the acquireFenceFds
237 if(list->hwLayers[i].acquireFenceFd > 0) {
238 close(list->hwLayers[i].acquireFenceFd);
239 list->hwLayers[i].acquireFenceFd = -1;
240 }
241 //Populate releaseFenceFds.
242 list->hwLayers[i].releaseFenceFd = dup(releaseFd);
243 }
244 }
245 list->retireFenceFd = releaseFd;
Kinjal Bhavsar2dd04a82012-09-18 18:27:59 -0700246#endif
247 return ret;
248}
249
Naseer Ahmedb1c76322012-10-17 00:32:50 -0400250void LayerCache::resetLayerCache(int num) {
251 for(uint32_t i = 0; i < MAX_NUM_LAYERS; i++) {
252 hnd[i] = NULL;
253 }
254 numHwLayers = num;
255}
256
257void LayerCache::updateLayerCache(hwc_display_contents_1_t* list) {
258
259 int numFbLayers = 0;
260 int numCacheableLayers = 0;
261
262 canUseLayerCache = false;
263 //Bail if geometry changed or num of layers changed
264 if(list->flags & HWC_GEOMETRY_CHANGED ||
265 list->numHwLayers != numHwLayers ) {
266 resetLayerCache(list->numHwLayers);
267 return;
268 }
269
270 for(uint32_t i = 0; i < list->numHwLayers; i++) {
271 //Bail on skip layers
272 if(list->hwLayers[i].flags & HWC_SKIP_LAYER) {
273 resetLayerCache(list->numHwLayers);
274 return;
275 }
276
277 if(list->hwLayers[i].compositionType == HWC_FRAMEBUFFER) {
278 numFbLayers++;
279 if(hnd[i] == NULL) {
280 hnd[i] = list->hwLayers[i].handle;
281 } else if (hnd[i] ==
282 list->hwLayers[i].handle) {
283 numCacheableLayers++;
284 } else {
285 hnd[i] = NULL;
286 return;
287 }
288 } else {
289 hnd[i] = NULL;
290 }
291 }
292 if(numFbLayers == numCacheableLayers)
293 canUseLayerCache = true;
294
295 //XXX: The marking part is separate, if MDP comp wants
296 // to use it in the future. Right now getting MDP comp
297 // to use this is more trouble than it is worth.
298 markCachedLayersAsOverlay(list);
299}
300
301void LayerCache::markCachedLayersAsOverlay(hwc_display_contents_1_t* list) {
302 //This optimization only works if ALL the layer handles
303 //that were on the framebuffer didn't change.
304 if(canUseLayerCache){
305 for(uint32_t i = 0; i < list->numHwLayers; i++) {
306 if (list->hwLayers[i].handle &&
307 list->hwLayers[i].handle == hnd[i] &&
308 list->hwLayers[i].compositionType != HWC_FRAMEBUFFER_TARGET)
309 {
310 list->hwLayers[i].compositionType = HWC_OVERLAY;
311 }
312 }
313 }
314
315}
316
Naseer Ahmed29a26812012-06-14 00:56:20 -0700317};//namespace