blob: ae7bb9546ff5be87ac193b242b4ee827aa889bae [file] [log] [blame]
Naseer Ahmed29a26812012-06-14 00:56:20 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
Arun Kumar K.Rba9eed52013-01-04 00:51:29 -08003 * Copyright (C) 2012-2013, The Linux Foundation. All rights reserved.
Naseer Ahmed29a26812012-06-14 00:56:20 -07004 *
Arun Kumar K.R361da4f2012-11-28 10:42:59 -08005 * Not a Contribution, Apache license notifications and license are retained
6 * for attribution purposes only.
7 *
Naseer Ahmed29a26812012-06-14 00:56:20 -07008 * 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 */
Naseer Ahmed64b81212013-02-14 10:29:47 -050020#define ATRACE_TAG ATRACE_TAG_GRAPHICS
Naseer Ahmed29a26812012-06-14 00:56:20 -070021#include <fcntl.h>
22#include <errno.h>
23
24#include <cutils/log.h>
25#include <cutils/atomic.h>
Naseer Ahmed72cf9762012-07-21 12:17:13 -070026#include <EGL/egl.h>
Naseer Ahmed64b81212013-02-14 10:29:47 -050027#include <utils/Trace.h>
Naseer Ahmed29a26812012-06-14 00:56:20 -070028
Naseer Ahmed72cf9762012-07-21 12:17:13 -070029#include <overlay.h>
30#include <fb_priv.h>
Naseer Ahmed96c4c952012-07-25 18:27:14 -070031#include <mdp_version.h>
Naseer Ahmed29a26812012-06-14 00:56:20 -070032#include "hwc_utils.h"
Naseer Ahmedf48aef62012-07-20 09:05:53 -070033#include "hwc_video.h"
Naseer Ahmed758bfc52012-11-28 17:02:08 -050034#include "hwc_fbupdate.h"
Naseer Ahmed54821fe2012-11-28 18:44:38 -050035#include "hwc_mdpcomp.h"
Saurabh Shah56f610d2012-08-07 15:27:06 -070036#include "external.h"
Arun Kumar K.R361da4f2012-11-28 10:42:59 -080037#include "hwc_copybit.h"
Naseer Ahmed29a26812012-06-14 00:56:20 -070038
39using namespace qhwc;
Naseer Ahmed758bfc52012-11-28 17:02:08 -050040#define VSYNC_DEBUG 0
Naseer Ahmed29a26812012-06-14 00:56:20 -070041
42static int hwc_device_open(const struct hw_module_t* module,
43 const char* name,
44 struct hw_device_t** device);
45
46static struct hw_module_methods_t hwc_module_methods = {
47 open: hwc_device_open
48};
49
50hwc_module_t HAL_MODULE_INFO_SYM = {
51 common: {
52 tag: HARDWARE_MODULE_TAG,
53 version_major: 2,
54 version_minor: 0,
55 id: HWC_HARDWARE_MODULE_ID,
56 name: "Qualcomm Hardware Composer Module",
57 author: "CodeAurora Forum",
58 methods: &hwc_module_methods,
59 dso: 0,
60 reserved: {0},
61 }
62};
63
64/*
65 * Save callback functions registered to HWC
66 */
Naseer Ahmed5b6708a2012-08-02 13:46:08 -070067static void hwc_registerProcs(struct hwc_composer_device_1* dev,
Naseer Ahmed29a26812012-06-14 00:56:20 -070068 hwc_procs_t const* procs)
69{
Iliyan Malchev0f9c3972012-10-11 15:16:15 -070070 ALOGI("%s", __FUNCTION__);
Naseer Ahmed29a26812012-06-14 00:56:20 -070071 hwc_context_t* ctx = (hwc_context_t*)(dev);
72 if(!ctx) {
73 ALOGE("%s: Invalid context", __FUNCTION__);
74 return;
75 }
Jesse Hall3be78d92012-08-21 15:12:23 -070076 ctx->proc = procs;
77
Naseer Ahmedff4f0252012-10-01 13:03:01 -040078 // Now that we have the functions needed, kick off
79 // the uevent & vsync threads
Jesse Hall3be78d92012-08-21 15:12:23 -070080 init_uevent_thread(ctx);
Naseer Ahmedff4f0252012-10-01 13:03:01 -040081 init_vsync_thread(ctx);
Naseer Ahmed29a26812012-06-14 00:56:20 -070082}
83
Saurabh Shah649cda62012-09-16 16:05:58 -070084//Helper
Naseer Ahmedb1c76322012-10-17 00:32:50 -040085static void reset(hwc_context_t *ctx, int numDisplays,
86 hwc_display_contents_1_t** displays) {
Saurabh Shah3e858eb2012-09-17 16:53:21 -070087 memset(ctx->listStats, 0, sizeof(ctx->listStats));
Amara Venkata Mastan Manoj Kumar11a380d2013-01-17 09:30:56 -080088 for(int i = 0; i < MAX_DISPLAYS; i++) {
Naseer Ahmedb1c76322012-10-17 00:32:50 -040089 hwc_display_contents_1_t *list = displays[i];
90 // XXX:SurfaceFlinger no longer guarantees that this
91 // value is reset on every prepare. However, for the layer
92 // cache we need to reset it.
93 // We can probably rethink that later on
94 if (LIKELY(list && list->numHwLayers > 1)) {
95 for(uint32_t j = 0; j < list->numHwLayers; j++) {
96 if(list->hwLayers[j].compositionType != HWC_FRAMEBUFFER_TARGET)
97 list->hwLayers[j].compositionType = HWC_FRAMEBUFFER;
98 }
99 }
Saurabh Shahcf053c62012-12-13 12:32:55 -0800100
101 if(ctx->mFBUpdate[i])
102 ctx->mFBUpdate[i]->reset();
Arun Kumar K.R361da4f2012-11-28 10:42:59 -0800103
104 if(ctx->mCopyBit[i])
105 ctx->mCopyBit[i]->reset();
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700106 }
Naseer Ahmed758bfc52012-11-28 17:02:08 -0500107 VideoOverlay::reset();
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700108}
109
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500110//clear prev layer prop flags and realloc for current frame
111static void reset_layer_prop(hwc_context_t* ctx, int dpy) {
112 int layer_count = ctx->listStats[dpy].numAppLayers;
113
114 if(ctx->layerProp[dpy]) {
115 delete[] ctx->layerProp[dpy];
116 ctx->layerProp[dpy] = NULL;
117 }
118
119 if(layer_count) {
120 ctx->layerProp[dpy] = new LayerProp[layer_count];
121 }
122}
123
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700124static int hwc_prepare_primary(hwc_composer_device_1 *dev,
125 hwc_display_contents_1_t *list) {
126 hwc_context_t* ctx = (hwc_context_t*)(dev);
Saurabh Shahcf053c62012-12-13 12:32:55 -0800127 const int dpy = HWC_DISPLAY_PRIMARY;
Saurabh Shahbf1e02a2013-02-26 13:38:05 -0800128 if (LIKELY(list && list->numHwLayers > 1 &&
129 list->numHwLayers <= MAX_NUM_LAYERS) && ctx->dpyAttr[dpy].isActive) {
Saurabh Shah86623d72012-09-25 19:39:17 -0700130 uint32_t last = list->numHwLayers - 1;
Saurabh Shah1a8cda02012-10-12 17:00:39 -0700131 hwc_layer_1_t *fbLayer = &list->hwLayers[last];
132 if(fbLayer->handle) {
Saurabh Shahcf053c62012-12-13 12:32:55 -0800133 setListStats(ctx, list, dpy);
134 reset_layer_prop(ctx, dpy);
Arun Kumar K.R361da4f2012-11-28 10:42:59 -0800135 int ret = ctx->mMDPComp->prepare(ctx, list);
136 if(!ret) {
137 // IF MDPcomp fails use this route
Saurabh Shahcf053c62012-12-13 12:32:55 -0800138 VideoOverlay::prepare(ctx, list, dpy);
Naseer Ahmed64b81212013-02-14 10:29:47 -0500139 ctx->mFBUpdate[dpy]->prepare(ctx, list);
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500140 }
Saurabh Shahcf053c62012-12-13 12:32:55 -0800141 ctx->mLayerCache[dpy]->updateLayerCache(list);
Arun Kumar K.R361da4f2012-11-28 10:42:59 -0800142 // Use Copybit, when MDP comp fails
143 if(!ret && ctx->mCopyBit[dpy])
144 ctx->mCopyBit[dpy]->prepare(ctx, list, dpy);
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700145 }
146 }
147 return 0;
148}
149
150static int hwc_prepare_external(hwc_composer_device_1 *dev,
Amara Venkata Mastan Manoj Kumar11a380d2013-01-17 09:30:56 -0800151 hwc_display_contents_1_t *list, int dpy) {
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700152 hwc_context_t* ctx = (hwc_context_t*)(dev);
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700153
Saurabh Shahbf1e02a2013-02-26 13:38:05 -0800154 if (LIKELY(list && list->numHwLayers > 1 &&
155 list->numHwLayers <= MAX_NUM_LAYERS) &&
Saurabh Shahcf053c62012-12-13 12:32:55 -0800156 ctx->dpyAttr[dpy].isActive &&
157 ctx->dpyAttr[dpy].connected) {
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700158 uint32_t last = list->numHwLayers - 1;
Amara Venkata Mastan Manoj Kumar11a380d2013-01-17 09:30:56 -0800159 if(!ctx->dpyAttr[dpy].isPause) {
160 hwc_layer_1_t *fbLayer = &list->hwLayers[last];
161 if(fbLayer->handle) {
162 setListStats(ctx, list, dpy);
163 reset_layer_prop(ctx, dpy);
164 VideoOverlay::prepare(ctx, list, dpy);
Naseer Ahmed64b81212013-02-14 10:29:47 -0500165 ctx->mFBUpdate[dpy]->prepare(ctx, list);
Amara Venkata Mastan Manoj Kumar11a380d2013-01-17 09:30:56 -0800166 ctx->mLayerCache[dpy]->updateLayerCache(list);
167 if(ctx->mCopyBit[dpy])
168 ctx->mCopyBit[dpy]->prepare(ctx, list, dpy);
169 ctx->mExtDispConfiguring = false;
170 }
171 } else {
172 // External Display is in Pause state.
173 // ToDo:
174 // Mark all application layers as OVERLAY so that
175 // GPU will not compose. This is done for power
176 // optimization
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700177 }
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700178 }
179 return 0;
Saurabh Shah649cda62012-09-16 16:05:58 -0700180}
181
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700182static int hwc_prepare(hwc_composer_device_1 *dev, size_t numDisplays,
183 hwc_display_contents_1_t** displays)
Naseer Ahmed29a26812012-06-14 00:56:20 -0700184{
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700185 int ret = 0;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700186 hwc_context_t* ctx = (hwc_context_t*)(dev);
Naseer Ahmed758bfc52012-11-28 17:02:08 -0500187 Locker::Autolock _l(ctx->mBlankLock);
Naseer Ahmedb1c76322012-10-17 00:32:50 -0400188 reset(ctx, numDisplays, displays);
Saurabh Shah56f610d2012-08-07 15:27:06 -0700189
Naseer Ahmed758bfc52012-11-28 17:02:08 -0500190 ctx->mOverlay->configBegin();
Saurabh Shah56f610d2012-08-07 15:27:06 -0700191
Amara Venkata Mastan Manoj Kumar11a380d2013-01-17 09:30:56 -0800192 for (int32_t i = numDisplays; i >= 0; i--) {
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500193 hwc_display_contents_1_t *list = displays[i];
194 switch(i) {
195 case HWC_DISPLAY_PRIMARY:
196 ret = hwc_prepare_primary(dev, list);
197 break;
198 case HWC_DISPLAY_EXTERNAL:
Amara Venkata Mastan Manoj Kumar11a380d2013-01-17 09:30:56 -0800199 case HWC_DISPLAY_VIRTUAL:
200 ret = hwc_prepare_external(dev, list, i);
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500201 break;
202 default:
203 ret = -EINVAL;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700204 }
205 }
Naseer Ahmed758bfc52012-11-28 17:02:08 -0500206
Saurabh Shahcf053c62012-12-13 12:32:55 -0800207 ctx->mOverlay->configDone();
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700208 return ret;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700209}
210
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700211static int hwc_eventControl(struct hwc_composer_device_1* dev, int dpy,
Naseer Ahmed56601cd2013-03-05 11:34:14 -0500212 int event, int enable)
Naseer Ahmed72cf9762012-07-21 12:17:13 -0700213{
214 int ret = 0;
215 hwc_context_t* ctx = (hwc_context_t*)(dev);
216 private_module_t* m = reinterpret_cast<private_module_t*>(
217 ctx->mFbDev->common.module);
Iliyan Malcheveac89652012-10-04 10:38:28 -0700218 pthread_mutex_lock(&ctx->vstate.lock);
Naseer Ahmed72cf9762012-07-21 12:17:13 -0700219 switch(event) {
220 case HWC_EVENT_VSYNC:
Naseer Ahmed56601cd2013-03-05 11:34:14 -0500221 if (ctx->vstate.enable == enable)
Omprakash Dhyade1ef881c2012-10-03 02:26:55 -0700222 break;
Naseer Ahmed56601cd2013-03-05 11:34:14 -0500223 ret = hwc_vsync_control(ctx, dpy, enable);
224 if(ret == 0) {
225 ctx->vstate.enable = !!enable;
226 pthread_cond_signal(&ctx->vstate.cond);
227 }
Iliyan Malcheveac89652012-10-04 10:38:28 -0700228 ALOGD_IF (VSYNC_DEBUG, "VSYNC state changed to %s",
Naseer Ahmed56601cd2013-03-05 11:34:14 -0500229 (enable)?"ENABLED":"DISABLED");
Iliyan Malcheveac89652012-10-04 10:38:28 -0700230 break;
Naseer Ahmed72cf9762012-07-21 12:17:13 -0700231 default:
232 ret = -EINVAL;
233 }
Iliyan Malcheveac89652012-10-04 10:38:28 -0700234 pthread_mutex_unlock(&ctx->vstate.lock);
Naseer Ahmed72cf9762012-07-21 12:17:13 -0700235 return ret;
236}
237
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700238static int hwc_blank(struct hwc_composer_device_1* dev, int dpy, int blank)
239{
Naseer Ahmed64b81212013-02-14 10:29:47 -0500240 ATRACE_CALL();
Naseer Ahmed934790c2012-08-16 18:11:09 -0700241 hwc_context_t* ctx = (hwc_context_t*)(dev);
242 private_module_t* m = reinterpret_cast<private_module_t*>(
243 ctx->mFbDev->common.module);
Naseer Ahmed758bfc52012-11-28 17:02:08 -0500244 Locker::Autolock _l(ctx->mBlankLock);
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700245 int ret = 0;
Naseer Ahmed56601cd2013-03-05 11:34:14 -0500246 ALOGD("%s: %s display: %d", __FUNCTION__,
247 blank==1 ? "Blanking":"Unblanking", dpy);
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700248 switch(dpy) {
249 case HWC_DISPLAY_PRIMARY:
250 if(blank) {
Naseer Ahmed758bfc52012-11-28 17:02:08 -0500251 ctx->mOverlay->configBegin();
252 ctx->mOverlay->configDone();
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700253 ret = ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_POWERDOWN);
Ramkumar Radhakrishnan893d6ee2013-02-26 10:48:05 -0800254
255 if(ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected == true) {
256 // Surfaceflinger does not send Blank/unblank event to hwc
257 // for virtual display, handle it explicitly when blank for
258 // primary is invoked, so that any pipes unset get committed
259 if (!ctx->mExtDisplay->post()) {
260 ret = -1;
261 ALOGE("%s:post failed for virtual display !!",
262 __FUNCTION__);
263 } else {
264 ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isActive = !blank;
265 }
266 }
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700267 } else {
268 ret = ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_UNBLANK);
Ramkumar Radhakrishnan893d6ee2013-02-26 10:48:05 -0800269 if(ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected == true) {
270 ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isActive = !blank;
271 }
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700272 }
273 break;
274 case HWC_DISPLAY_EXTERNAL:
275 if(blank) {
Ramkumar Radhakrishnan893d6ee2013-02-26 10:48:05 -0800276 // External post commits the changes to display
Arun Kumar K.Rba9eed52013-01-04 00:51:29 -0800277 // Call this on blank, so that any pipe unsets gets committed
278 if (!ctx->mExtDisplay->post()) {
279 ret = -1;
Ramkumar Radhakrishnan893d6ee2013-02-26 10:48:05 -0800280 ALOGE("%s:post failed for external display !! ",
281 __FUNCTION__);
Arun Kumar K.Rba9eed52013-01-04 00:51:29 -0800282 }
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700283 } else {
284 }
285 break;
286 default:
287 return -EINVAL;
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700288 }
Arun Kumar K.Rf6f49a12012-11-27 11:46:50 -0800289 // Enable HPD here, as during bootup unblank is called
290 // when SF is completely initialized
291 ctx->mExtDisplay->setHPD(1);
Naseer Ahmed56601cd2013-03-05 11:34:14 -0500292 if(ret == 0){
293 ctx->dpyAttr[dpy].isActive = !blank;
294 } else {
295 ALOGE("%s: Failed in %s display: %d error:%s", __FUNCTION__,
296 blank==1 ? "blanking":"unblanking", dpy, strerror(errno));
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700297 return ret;
298 }
Naseer Ahmed56601cd2013-03-05 11:34:14 -0500299
300 ALOGD("%s: Done %s display: %d", __FUNCTION__,
301 blank==1 ? "blanking":"unblanking", dpy);
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700302 return 0;
303}
304
305static int hwc_query(struct hwc_composer_device_1* dev,
Naseer Ahmed72cf9762012-07-21 12:17:13 -0700306 int param, int* value)
307{
308 hwc_context_t* ctx = (hwc_context_t*)(dev);
309 private_module_t* m = reinterpret_cast<private_module_t*>(
310 ctx->mFbDev->common.module);
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700311 int supported = HWC_DISPLAY_PRIMARY_BIT;
Naseer Ahmed72cf9762012-07-21 12:17:13 -0700312
313 switch (param) {
314 case HWC_BACKGROUND_LAYER_SUPPORTED:
315 // Not supported for now
316 value[0] = 0;
317 break;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700318 case HWC_VSYNC_PERIOD: //Not used for hwc > 1.1
Saurabh Shah2e2798c2012-08-30 14:47:10 -0700319 value[0] = m->fps;
Naseer Ahmed72cf9762012-07-21 12:17:13 -0700320 ALOGI("fps: %d", value[0]);
321 break;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700322 case HWC_DISPLAY_TYPES_SUPPORTED:
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700323 if(ctx->mMDP.hasOverlay)
324 supported |= HWC_DISPLAY_EXTERNAL_BIT;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700325 value[0] = supported;
326 break;
Naseer Ahmed72cf9762012-07-21 12:17:13 -0700327 default:
328 return -EINVAL;
329 }
330 return 0;
331
332}
333
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700334static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
Naseer Ahmed64b81212013-02-14 10:29:47 -0500335 ATRACE_CALL();
Saurabh Shaheaf67912012-10-10 17:33:14 -0700336 int ret = 0;
Saurabh Shahcf053c62012-12-13 12:32:55 -0800337 const int dpy = HWC_DISPLAY_PRIMARY;
Amara Venkata Mastan Manoj Kumar57e3c812013-01-11 13:36:33 -0800338 if (LIKELY(list) && ctx->dpyAttr[dpy].isActive) {
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700339 uint32_t last = list->numHwLayers - 1;
340 hwc_layer_1_t *fbLayer = &list->hwLayers[last];
Arun Kumar K.R361da4f2012-11-28 10:42:59 -0800341 int fd = -1; //FenceFD from the Copybit(valid in async mode)
Naseer Ahmed64b81212013-02-14 10:29:47 -0500342 bool copybitDone = false;
Arun Kumar K.R361da4f2012-11-28 10:42:59 -0800343 if(ctx->mCopyBit[dpy])
Naseer Ahmed64b81212013-02-14 10:29:47 -0500344 copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
Amara Venkata Mastan Manoj Kumar57e3c812013-01-11 13:36:33 -0800345 if(list->numHwLayers > 1)
346 hwc_sync(ctx, list, dpy, fd);
Saurabh Shahcf053c62012-12-13 12:32:55 -0800347 if (!VideoOverlay::draw(ctx, list, dpy)) {
Saurabh Shaheaf67912012-10-10 17:33:14 -0700348 ALOGE("%s: VideoOverlay::draw fail!", __FUNCTION__);
349 ret = -1;
350 }
Saurabh Shahcbf7ccc2012-12-19 16:45:51 -0800351 if (!ctx->mMDPComp->draw(ctx, list)) {
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500352 ALOGE("%s: MDPComp::draw fail!", __FUNCTION__);
353 ret = -1;
354 }
355
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700356 //TODO We dont check for SKIP flag on this layer because we need PAN
357 //always. Last layer is always FB
Naseer Ahmed64b81212013-02-14 10:29:47 -0500358 private_handle_t *hnd = NULL;
359 if(copybitDone) {
360 hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
361 } else {
362 hnd = (private_handle_t *)fbLayer->handle;
363 }
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500364 if(fbLayer->compositionType == HWC_FRAMEBUFFER_TARGET && hnd) {
Amara Venkata Mastan Manoj Kumar57e3c812013-01-11 13:36:33 -0800365 if(!(fbLayer->flags & HWC_SKIP_LAYER) &&
366 (list->numHwLayers > 1)) {
Naseer Ahmed64b81212013-02-14 10:29:47 -0500367 if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
Naseer Ahmed54821fe2012-11-28 18:44:38 -0500368 ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
369 ret = -1;
370 }
371 }
Saurabh Shah43333302013-02-06 13:30:27 -0800372 }
373 if (ctx->mFbDev->post(ctx->mFbDev, fbLayer->handle)) {
374 ALOGE("%s: ctx->mFbDev->post fail!", __FUNCTION__);
Saurabh Shah747af1e2013-02-26 10:25:12 -0800375 ret = -1;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700376 }
377 }
Saurabh Shah747af1e2013-02-26 10:25:12 -0800378
379 closeAcquireFds(list);
Saurabh Shaheaf67912012-10-10 17:33:14 -0700380 return ret;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700381}
382
383static int hwc_set_external(hwc_context_t *ctx,
Naseer Ahmed64b81212013-02-14 10:29:47 -0500384 hwc_display_contents_1_t* list, int dpy)
385{
386 ATRACE_CALL();
Saurabh Shaheaf67912012-10-10 17:33:14 -0700387 int ret = 0;
Kinjal Bhavsarf83d4482012-10-10 15:56:21 -0700388 Locker::Autolock _l(ctx->mExtSetLock);
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700389
Amara Venkata Mastan Manoj Kumar57e3c812013-01-11 13:36:33 -0800390 if (LIKELY(list) && ctx->dpyAttr[dpy].isActive &&
Amara Venkata Mastan Manoj Kumar11a380d2013-01-17 09:30:56 -0800391 !ctx->dpyAttr[dpy].isPause &&
Saurabh Shahcf053c62012-12-13 12:32:55 -0800392 ctx->dpyAttr[dpy].connected) {
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700393 uint32_t last = list->numHwLayers - 1;
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700394 hwc_layer_1_t *fbLayer = &list->hwLayers[last];
Arun Kumar K.R361da4f2012-11-28 10:42:59 -0800395 int fd = -1; //FenceFD from the Copybit(valid in async mode)
Naseer Ahmed64b81212013-02-14 10:29:47 -0500396 bool copybitDone = false;
Arun Kumar K.R361da4f2012-11-28 10:42:59 -0800397 if(ctx->mCopyBit[dpy])
Naseer Ahmed64b81212013-02-14 10:29:47 -0500398 copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700399
Amara Venkata Mastan Manoj Kumar57e3c812013-01-11 13:36:33 -0800400 if(list->numHwLayers > 1)
401 hwc_sync(ctx, list, dpy, fd);
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700402
Saurabh Shahcf053c62012-12-13 12:32:55 -0800403 if (!VideoOverlay::draw(ctx, list, dpy)) {
Saurabh Shaheaf67912012-10-10 17:33:14 -0700404 ALOGE("%s: VideoOverlay::draw fail!", __FUNCTION__);
405 ret = -1;
406 }
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700407
Naseer Ahmed64b81212013-02-14 10:29:47 -0500408 private_handle_t *hnd = NULL;
409 if(copybitDone) {
410 hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
411 } else {
412 hnd = (private_handle_t *)fbLayer->handle;
413 }
414
Saurabh Shah150806a2012-10-09 15:38:23 -0700415 if(fbLayer->compositionType == HWC_FRAMEBUFFER_TARGET &&
Amara Venkata Mastan Manoj Kumar57e3c812013-01-11 13:36:33 -0800416 !(fbLayer->flags & HWC_SKIP_LAYER) && hnd &&
417 (list->numHwLayers > 1)) {
Naseer Ahmed64b81212013-02-14 10:29:47 -0500418 if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
Naseer Ahmed758bfc52012-11-28 17:02:08 -0500419 ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
Saurabh Shaheaf67912012-10-10 17:33:14 -0700420 ret = -1;
421 }
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700422 }
Saurabh Shaheaf67912012-10-10 17:33:14 -0700423 if (!ctx->mExtDisplay->post()) {
424 ALOGE("%s: ctx->mExtDisplay->post fail!", __FUNCTION__);
Saurabh Shah747af1e2013-02-26 10:25:12 -0800425 ret = -1;
Saurabh Shaheaf67912012-10-10 17:33:14 -0700426 }
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700427 }
Saurabh Shah747af1e2013-02-26 10:25:12 -0800428
429 closeAcquireFds(list);
Saurabh Shaheaf67912012-10-10 17:33:14 -0700430 return ret;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700431}
432
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700433static int hwc_set(hwc_composer_device_1 *dev,
434 size_t numDisplays,
435 hwc_display_contents_1_t** displays)
Naseer Ahmed29a26812012-06-14 00:56:20 -0700436{
437 int ret = 0;
438 hwc_context_t* ctx = (hwc_context_t*)(dev);
Naseer Ahmed32ff2252012-09-29 01:41:21 -0400439 Locker::Autolock _l(ctx->mBlankLock);
Amara Venkata Mastan Manoj Kumar11a380d2013-01-17 09:30:56 -0800440 for (uint32_t i = 0; i <= numDisplays; i++) {
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700441 hwc_display_contents_1_t* list = displays[i];
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700442 switch(i) {
443 case HWC_DISPLAY_PRIMARY:
444 ret = hwc_set_primary(ctx, list);
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700445 break;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700446 case HWC_DISPLAY_EXTERNAL:
Amara Venkata Mastan Manoj Kumar11a380d2013-01-17 09:30:56 -0800447 case HWC_DISPLAY_VIRTUAL:
448 /* ToDo: We are using hwc_set_external path for both External and
449 Virtual displays on HWC1.1. Eventually, we will have
450 separate functions when we move to HWC1.2
451 */
452 ret = hwc_set_external(ctx, list, i);
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700453 break;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700454 default:
455 ret = -EINVAL;
Naseer Ahmed5b6708a2012-08-02 13:46:08 -0700456 }
Naseer Ahmed29a26812012-06-14 00:56:20 -0700457 }
Naseer Ahmed29a26812012-06-14 00:56:20 -0700458 return ret;
459}
460
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700461int hwc_getDisplayConfigs(struct hwc_composer_device_1* dev, int disp,
462 uint32_t* configs, size_t* numConfigs) {
463 int ret = 0;
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700464 hwc_context_t* ctx = (hwc_context_t*)(dev);
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700465 //in 1.1 there is no way to choose a config, report as config id # 0
466 //This config is passed to getDisplayAttributes. Ignore for now.
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700467 switch(disp) {
468 case HWC_DISPLAY_PRIMARY:
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700469 if(*numConfigs > 0) {
470 configs[0] = 0;
471 *numConfigs = 1;
472 }
473 ret = 0; //NO_ERROR
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700474 break;
475 case HWC_DISPLAY_EXTERNAL:
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700476 ret = -1; //Not connected
477 if(ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected) {
478 ret = 0; //NO_ERROR
479 if(*numConfigs > 0) {
480 configs[0] = 0;
481 *numConfigs = 1;
482 }
483 }
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700484 break;
485 }
486 return ret;
487}
488
489int hwc_getDisplayAttributes(struct hwc_composer_device_1* dev, int disp,
490 uint32_t config, const uint32_t* attributes, int32_t* values) {
491
492 hwc_context_t* ctx = (hwc_context_t*)(dev);
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700493 //If hotpluggable displays are inactive return error
494 if(disp == HWC_DISPLAY_EXTERNAL && !ctx->dpyAttr[disp].connected) {
495 return -1;
496 }
497
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700498 //From HWComposer
499 static const uint32_t DISPLAY_ATTRIBUTES[] = {
500 HWC_DISPLAY_VSYNC_PERIOD,
501 HWC_DISPLAY_WIDTH,
502 HWC_DISPLAY_HEIGHT,
503 HWC_DISPLAY_DPI_X,
504 HWC_DISPLAY_DPI_Y,
505 HWC_DISPLAY_NO_ATTRIBUTE,
506 };
507
508 const int NUM_DISPLAY_ATTRIBUTES = (sizeof(DISPLAY_ATTRIBUTES) /
509 sizeof(DISPLAY_ATTRIBUTES)[0]);
510
511 for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) {
512 switch (attributes[i]) {
513 case HWC_DISPLAY_VSYNC_PERIOD:
514 values[i] = ctx->dpyAttr[disp].vsync_period;
515 break;
516 case HWC_DISPLAY_WIDTH:
517 values[i] = ctx->dpyAttr[disp].xres;
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700518 ALOGD("%s disp = %d, width = %d",__FUNCTION__, disp,
519 ctx->dpyAttr[disp].xres);
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700520 break;
521 case HWC_DISPLAY_HEIGHT:
522 values[i] = ctx->dpyAttr[disp].yres;
Saurabh Shahc4d034f2012-09-27 15:55:15 -0700523 ALOGD("%s disp = %d, height = %d",__FUNCTION__, disp,
524 ctx->dpyAttr[disp].yres);
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700525 break;
526 case HWC_DISPLAY_DPI_X:
Naseer Ahmed7b80d9c2012-09-26 20:14:38 -0400527 values[i] = (int32_t) (ctx->dpyAttr[disp].xdpi*1000.0);
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700528 break;
529 case HWC_DISPLAY_DPI_Y:
Naseer Ahmed7b80d9c2012-09-26 20:14:38 -0400530 values[i] = (int32_t) (ctx->dpyAttr[disp].ydpi*1000.0);
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700531 break;
532 default:
533 ALOGE("Unknown display attribute %d",
534 attributes[i]);
535 return -EINVAL;
536 }
537 }
538 return 0;
539}
540
Naseer Ahmed1d183f52012-11-26 12:35:16 -0500541void hwc_dump(struct hwc_composer_device_1* dev, char *buff, int buff_len)
542{
543 hwc_context_t* ctx = (hwc_context_t*)(dev);
Saurabh Shah0d0a7cb2013-02-12 17:58:19 -0800544 android::String8 aBuf("");
545 dumpsys_log(aBuf, "Qualcomm HWC state:\n");
546 dumpsys_log(aBuf, " MDPVersion=%d\n", ctx->mMDP.version);
547 dumpsys_log(aBuf, " DisplayPanel=%c\n", ctx->mMDP.panel);
548 ctx->mMDPComp->dump(aBuf);
549 char ovDump[2048] = {'\0'};
550 ctx->mOverlay->getDump(ovDump, 2048);
551 dumpsys_log(aBuf, ovDump);
552 strlcpy(buff, aBuf.string(), buff_len);
Naseer Ahmed1d183f52012-11-26 12:35:16 -0500553}
554
Naseer Ahmed29a26812012-06-14 00:56:20 -0700555static int hwc_device_close(struct hw_device_t *dev)
556{
557 if(!dev) {
Naseer Ahmed72cf9762012-07-21 12:17:13 -0700558 ALOGE("%s: NULL device pointer", __FUNCTION__);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700559 return -1;
560 }
561 closeContext((hwc_context_t*)dev);
562 free(dev);
563
564 return 0;
565}
566
567static int hwc_device_open(const struct hw_module_t* module, const char* name,
568 struct hw_device_t** device)
569{
570 int status = -EINVAL;
571
572 if (!strcmp(name, HWC_HARDWARE_COMPOSER)) {
573 struct hwc_context_t *dev;
574 dev = (hwc_context_t*)malloc(sizeof(*dev));
575 memset(dev, 0, sizeof(*dev));
Naseer Ahmed72cf9762012-07-21 12:17:13 -0700576
577 //Initialize hwc context
Naseer Ahmed29a26812012-06-14 00:56:20 -0700578 initContext(dev);
Naseer Ahmed72cf9762012-07-21 12:17:13 -0700579
580 //Setup HWC methods
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700581 dev->device.common.tag = HARDWARE_DEVICE_TAG;
582 dev->device.common.version = HWC_DEVICE_API_VERSION_1_1;
583 dev->device.common.module = const_cast<hw_module_t*>(module);
584 dev->device.common.close = hwc_device_close;
585 dev->device.prepare = hwc_prepare;
586 dev->device.set = hwc_set;
587 dev->device.eventControl = hwc_eventControl;
588 dev->device.blank = hwc_blank;
589 dev->device.query = hwc_query;
590 dev->device.registerProcs = hwc_registerProcs;
Naseer Ahmed1d183f52012-11-26 12:35:16 -0500591 dev->device.dump = hwc_dump;
Saurabh Shah3e858eb2012-09-17 16:53:21 -0700592 dev->device.getDisplayConfigs = hwc_getDisplayConfigs;
593 dev->device.getDisplayAttributes = hwc_getDisplayAttributes;
594 *device = &dev->device.common;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700595 status = 0;
596 }
597 return status;
598}