blob: afb0ebe24017297f5994072f68c3d052312f59a3 [file] [log] [blame]
Sean Paule0c4c3d2015-01-20 16:56:04 -05001/*
2 * Copyright (C) 2015 The Android Open Source Project
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
17#define LOG_TAG "hwcomposer-drm"
18
Sean Paulef8f1f92015-04-29 16:05:23 -040019#include "drm_hwcomposer.h"
Sean Paul6a55e9f2015-04-30 15:31:06 -040020#include "drmresources.h"
Sean Paulda6270d2015-06-01 14:11:52 -040021#include "importer.h"
Sean Paul4057be32015-05-13 06:23:09 -070022#include "vsyncworker.h"
Sean Paulef8f1f92015-04-29 16:05:23 -040023
Sean Paule0c4c3d2015-01-20 16:56:04 -050024#include <errno.h>
Sean Paulef8f1f92015-04-29 16:05:23 -040025#include <fcntl.h>
Sean Paul5ad302c2015-05-11 10:43:31 -070026#include <list>
Sean Paule42febf2015-05-07 11:35:29 -070027#include <map>
Sean Paulef8f1f92015-04-29 16:05:23 -040028#include <pthread.h>
Dan Albertc5255b32015-05-07 23:42:54 -070029#include <stdlib.h>
Sean Paule0c4c3d2015-01-20 16:56:04 -050030#include <sys/param.h>
Sean Paul9aa5ad32015-01-22 15:47:54 -050031#include <sys/resource.h>
Sean Paule0c4c3d2015-01-20 16:56:04 -050032#include <xf86drm.h>
33#include <xf86drmMode.h>
Sean Paule0c4c3d2015-01-20 16:56:04 -050034
Sean Paulef8f1f92015-04-29 16:05:23 -040035#include <cutils/log.h>
36#include <cutils/properties.h>
Sean Paule0c4c3d2015-01-20 16:56:04 -050037#include <hardware/hardware.h>
38#include <hardware/hwcomposer.h>
Sean Paulf1dc1912015-01-24 01:34:31 -050039#include <sw_sync.h>
Sean Paulef8f1f92015-04-29 16:05:23 -040040#include <sync/sync.h>
Sean Paule0c4c3d2015-01-20 16:56:04 -050041
Sean Paule0c4c3d2015-01-20 16:56:04 -050042#define UM_PER_INCH 25400
43
Sean Paul6a55e9f2015-04-30 15:31:06 -040044namespace android {
Sean Paule0c4c3d2015-01-20 16:56:04 -050045
Sean Paule42febf2015-05-07 11:35:29 -070046typedef struct hwc_drm_display {
Sean Paulef8f1f92015-04-29 16:05:23 -040047 struct hwc_context_t *ctx;
48 int display;
Sean Paul9aa5ad32015-01-22 15:47:54 -050049
Sean Paul6a55e9f2015-04-30 15:31:06 -040050 std::vector<uint32_t> config_ids;
Sean Paul9aa5ad32015-01-22 15:47:54 -050051
Sean Paul4057be32015-05-13 06:23:09 -070052 VSyncWorker vsync_worker;
Sean Paule42febf2015-05-07 11:35:29 -070053} hwc_drm_display_t;
Sean Paule0c4c3d2015-01-20 16:56:04 -050054
55struct hwc_context_t {
Sean Paule42febf2015-05-07 11:35:29 -070056 // map of display:hwc_drm_display_t
57 typedef std::map<int, hwc_drm_display_t> DisplayMap;
58 typedef DisplayMap::iterator DisplayMapIter;
Sean Paule0c4c3d2015-01-20 16:56:04 -050059
Sean Paulda6270d2015-06-01 14:11:52 -040060 hwc_context_t() : procs(NULL), importer(NULL) {
61 }
62
63 ~hwc_context_t() {
64 delete importer;
65 }
66
Sean Paule42febf2015-05-07 11:35:29 -070067 hwc_composer_device_1_t device;
Sean Paulef8f1f92015-04-29 16:05:23 -040068 hwc_procs_t const *procs;
Sean Paule0c4c3d2015-01-20 16:56:04 -050069
Sean Paule42febf2015-05-07 11:35:29 -070070 DisplayMap displays;
Sean Paul6a55e9f2015-04-30 15:31:06 -040071 DrmResources drm;
Sean Paulda6270d2015-06-01 14:11:52 -040072 Importer *importer;
Sean Paule0c4c3d2015-01-20 16:56:04 -050073};
74
Sean Paulb386f1b2015-05-13 06:33:23 -070075static int hwc_prepare(hwc_composer_device_1_t *dev, size_t num_displays,
Sean Paulef8f1f92015-04-29 16:05:23 -040076 hwc_display_contents_1_t **display_contents) {
Sean Paulb386f1b2015-05-13 06:33:23 -070077 // XXX: Once we have a GL compositor, just make everything HWC_OVERLAY
78 struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
79 Composition *composition =
80 ctx->drm.compositor()->CreateComposition(ctx->importer);
81 if (!composition) {
82 ALOGE("Drm composition init failed");
83 return -EINVAL;
84 }
Sean Paule0c4c3d2015-01-20 16:56:04 -050085
Sean Paule42febf2015-05-07 11:35:29 -070086 for (int i = 0; i < (int)num_displays; ++i) {
Sean Paulef8f1f92015-04-29 16:05:23 -040087 if (!display_contents[i])
88 continue;
Sean Paule0c4c3d2015-01-20 16:56:04 -050089
Sean Paulb386f1b2015-05-13 06:33:23 -070090 int num_layers = display_contents[i]->numHwLayers;
91 int num_planes = composition->GetRemainingLayers(i, num_layers);
92
93 // XXX: Should go away with atomic modeset
94 DrmCrtc *crtc = ctx->drm.GetCrtcForDisplay(i);
95 if (!crtc) {
96 ALOGE("No crtc for display %d", i);
97 delete composition;
98 return -ENODEV;
99 }
100 if (crtc->requires_modeset())
101 num_planes = 0;
102
103 for (int j = std::max(0, num_layers - num_planes); j < num_layers; j++) {
104 if (j >= num_planes)
105 break;
106
107 hwc_layer_1_t *layer = &display_contents[i]->hwLayers[j];
108 if (layer->compositionType == HWC_FRAMEBUFFER)
109 layer->compositionType = HWC_OVERLAY;
Sean Paulef8f1f92015-04-29 16:05:23 -0400110 }
111 }
Sean Pauldffca952015-02-04 10:19:55 -0800112
Sean Paulb386f1b2015-05-13 06:33:23 -0700113 delete composition;
Sean Paulef8f1f92015-04-29 16:05:23 -0400114 return 0;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500115}
116
Sean Paulb386f1b2015-05-13 06:33:23 -0700117static void hwc_set_cleanup(size_t num_displays,
118 hwc_display_contents_1_t **display_contents,
119 Composition *composition) {
120 for (int i = 0; i < (int)num_displays; ++i) {
121 if (!display_contents[i])
122 continue;
123
124 hwc_display_contents_1_t *dc = display_contents[i];
125 for (size_t j = 0; j < dc->numHwLayers; ++j) {
126 hwc_layer_1_t *layer = &dc->hwLayers[j];
127 if (layer->acquireFenceFd >= 0) {
128 close(layer->acquireFenceFd);
129 layer->acquireFenceFd = -1;
130 }
131 }
132 if (dc->outbufAcquireFenceFd >= 0) {
133 close(dc->outbufAcquireFenceFd);
134 dc->outbufAcquireFenceFd = -1;
135 }
136 }
137
138 delete composition;
139}
140
Sean Paulb386f1b2015-05-13 06:33:23 -0700141static int hwc_add_layer(int display, hwc_context_t *ctx, hwc_layer_1_t *layer,
142 Composition *composition) {
143 hwc_drm_bo_t bo;
144 int ret = ctx->importer->ImportBuffer(layer->handle, &bo);
145 if (ret) {
146 ALOGE("Failed to import handle to bo %d", ret);
147 return ret;
Sean Paulef8f1f92015-04-29 16:05:23 -0400148 }
Sean Paulefb20cb2015-02-04 09:29:15 -0800149
Sean Paulb386f1b2015-05-13 06:33:23 -0700150 ret = composition->AddLayer(display, layer, &bo);
151 if (!ret)
Sean Paulef8f1f92015-04-29 16:05:23 -0400152 return 0;
Sean Paul9aa5ad32015-01-22 15:47:54 -0500153
Sean Paulb386f1b2015-05-13 06:33:23 -0700154 int destroy_ret = ctx->importer->ReleaseBuffer(&bo);
155 if (destroy_ret)
156 ALOGE("Failed to destroy buffer %d", destroy_ret);
Sean Paul9aa5ad32015-01-22 15:47:54 -0500157
Sean Paulef8f1f92015-04-29 16:05:23 -0400158 return ret;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500159}
160
161static int hwc_set(hwc_composer_device_1_t *dev, size_t num_displays,
Sean Paulef8f1f92015-04-29 16:05:23 -0400162 hwc_display_contents_1_t **display_contents) {
163 struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
Sean Paulb386f1b2015-05-13 06:33:23 -0700164 Composition *composition =
165 ctx->drm.compositor()->CreateComposition(ctx->importer);
166 if (!composition) {
167 ALOGE("Drm composition init failed");
168 hwc_set_cleanup(num_displays, display_contents, NULL);
169 return -EINVAL;
Sean Paulef8f1f92015-04-29 16:05:23 -0400170 }
Sean Paule0c4c3d2015-01-20 16:56:04 -0500171
Sean Paulb386f1b2015-05-13 06:33:23 -0700172 int ret;
173 for (int i = 0; i < (int)num_displays; ++i) {
174 if (!display_contents[i])
175 continue;
176
177 DrmCrtc *crtc = ctx->drm.GetCrtcForDisplay(i);
178 if (!crtc) {
179 ALOGE("No crtc for display %d", i);
180 hwc_set_cleanup(num_displays, display_contents, composition);
181 return -ENODEV;
182 }
183
184 hwc_display_contents_1_t *dc = display_contents[i];
185 unsigned num_layers = dc->numHwLayers;
186 unsigned num_planes = composition->GetRemainingLayers(i, num_layers);
187 bool use_target = false;
188 // XXX: We don't need to check for modeset required with atomic modeset
189 if (crtc->requires_modeset() || num_layers > num_planes)
190 use_target = true;
191
192 // XXX: Won't need to worry about FB_TARGET with GL Compositor
193 for (int j = 0; use_target && j < (int)num_layers; ++j) {
194 hwc_layer_1_t *layer = &dc->hwLayers[j];
195 if (layer->compositionType != HWC_FRAMEBUFFER_TARGET)
196 continue;
197
198 ret = hwc_add_layer(i, ctx, layer, composition);
199 if (ret) {
200 ALOGE("Add layer failed %d", ret);
201 hwc_set_cleanup(num_displays, display_contents, composition);
202 return ret;
203 }
204 --num_planes;
205 break;
206 }
207
208 for (int j = 0; num_planes && j < (int)num_layers; ++j) {
209 hwc_layer_1_t *layer = &dc->hwLayers[j];
210 if (layer->compositionType != HWC_OVERLAY)
211 continue;
212
213 ret = hwc_add_layer(i, ctx, layer, composition);
214 if (ret) {
215 ALOGE("Add layer failed %d", ret);
216 hwc_set_cleanup(num_displays, display_contents, composition);
217 return ret;
218 }
219 --num_planes;
220 }
221 }
222
223 ret = ctx->drm.compositor()->QueueComposition(composition);
224 if (ret) {
225 ALOGE("Failed to queue the composition");
226 hwc_set_cleanup(num_displays, display_contents, composition);
227 return ret;
228 }
229 hwc_set_cleanup(num_displays, display_contents, NULL);
Sean Paulef8f1f92015-04-29 16:05:23 -0400230 return ret;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500231}
232
Sean Paulef8f1f92015-04-29 16:05:23 -0400233static int hwc_event_control(struct hwc_composer_device_1 *dev, int display,
234 int event, int enabled) {
Sean Paulef8f1f92015-04-29 16:05:23 -0400235 if (event != HWC_EVENT_VSYNC || (enabled != 0 && enabled != 1))
236 return -EINVAL;
Sean Pauleb9e75c2015-01-25 23:31:30 -0500237
Sean Paul4057be32015-05-13 06:23:09 -0700238 struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
239 hwc_drm_display_t *hd = &ctx->displays[display];
240 return hd->vsync_worker.VSyncControl(enabled);
Sean Paule0c4c3d2015-01-20 16:56:04 -0500241}
242
Sean Paulef8f1f92015-04-29 16:05:23 -0400243static int hwc_set_power_mode(struct hwc_composer_device_1 *dev, int display,
244 int mode) {
245 struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500246
Sean Paul6a55e9f2015-04-30 15:31:06 -0400247 uint64_t dpmsValue = 0;
Sean Paulef8f1f92015-04-29 16:05:23 -0400248 switch (mode) {
249 case HWC_POWER_MODE_OFF:
Sean Paul6a55e9f2015-04-30 15:31:06 -0400250 dpmsValue = DRM_MODE_DPMS_OFF;
Sean Paulef8f1f92015-04-29 16:05:23 -0400251 break;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500252
Sean Paulef8f1f92015-04-29 16:05:23 -0400253 /* We can't support dozing right now, so go full on */
254 case HWC_POWER_MODE_DOZE:
255 case HWC_POWER_MODE_DOZE_SUSPEND:
256 case HWC_POWER_MODE_NORMAL:
Sean Paul6a55e9f2015-04-30 15:31:06 -0400257 dpmsValue = DRM_MODE_DPMS_ON;
Sean Paulef8f1f92015-04-29 16:05:23 -0400258 break;
259 };
Sean Paul6a55e9f2015-04-30 15:31:06 -0400260 return ctx->drm.SetDpmsMode(display, dpmsValue);
Sean Paule0c4c3d2015-01-20 16:56:04 -0500261}
262
Sean Paulef8f1f92015-04-29 16:05:23 -0400263static int hwc_query(struct hwc_composer_device_1 * /* dev */, int what,
264 int *value) {
265 switch (what) {
266 case HWC_BACKGROUND_LAYER_SUPPORTED:
267 *value = 0; /* TODO: We should do this */
268 break;
269 case HWC_VSYNC_PERIOD:
270 ALOGW("Query for deprecated vsync value, returning 60Hz");
271 *value = 1000 * 1000 * 1000 / 60;
272 break;
273 case HWC_DISPLAY_TYPES_SUPPORTED:
274 *value = HWC_DISPLAY_PRIMARY | HWC_DISPLAY_EXTERNAL;
275 break;
276 }
277 return 0;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500278}
279
Sean Paulef8f1f92015-04-29 16:05:23 -0400280static void hwc_register_procs(struct hwc_composer_device_1 *dev,
281 hwc_procs_t const *procs) {
282 struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500283
Sean Paulef8f1f92015-04-29 16:05:23 -0400284 ctx->procs = procs;
Sean Paul4057be32015-05-13 06:23:09 -0700285
286 for (hwc_context_t::DisplayMapIter iter = ctx->displays.begin();
287 iter != ctx->displays.end(); ++iter) {
288 iter->second.vsync_worker.SetProcs(procs);
289 }
Sean Paule0c4c3d2015-01-20 16:56:04 -0500290}
291
Sean Paulef8f1f92015-04-29 16:05:23 -0400292static int hwc_get_display_configs(struct hwc_composer_device_1 *dev,
293 int display, uint32_t *configs,
Sean Paul6a55e9f2015-04-30 15:31:06 -0400294 size_t *num_configs) {
295 if (!*num_configs)
Sean Paulef8f1f92015-04-29 16:05:23 -0400296 return 0;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500297
Sean Paulef8f1f92015-04-29 16:05:23 -0400298 struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
Sean Paule42febf2015-05-07 11:35:29 -0700299 hwc_drm_display_t *hd = &ctx->displays[display];
Sean Paul6a55e9f2015-04-30 15:31:06 -0400300 hd->config_ids.clear();
301
302 DrmConnector *connector = ctx->drm.GetConnectorForDisplay(display);
303 if (!connector) {
304 ALOGE("Failed to get connector for display %d", display);
Sean Paulef8f1f92015-04-29 16:05:23 -0400305 return -ENODEV;
306 }
Sean Paule0c4c3d2015-01-20 16:56:04 -0500307
Sean Paule42febf2015-05-07 11:35:29 -0700308 int ret = connector->UpdateModes();
Sean Paul6a55e9f2015-04-30 15:31:06 -0400309 if (ret) {
310 ALOGE("Failed to update display modes %d", ret);
Sean Paulef8f1f92015-04-29 16:05:23 -0400311 return ret;
Sean Paulef8f1f92015-04-29 16:05:23 -0400312 }
Sean Paule0c4c3d2015-01-20 16:56:04 -0500313
Sean Paul6a55e9f2015-04-30 15:31:06 -0400314 for (DrmConnector::ModeIter iter = connector->begin_modes();
315 iter != connector->end_modes(); ++iter) {
316 size_t idx = hd->config_ids.size();
317 if (idx == *num_configs)
318 break;
319 hd->config_ids.push_back(iter->id());
320 configs[idx] = iter->id();
321 }
322 *num_configs = hd->config_ids.size();
323 return *num_configs == 0 ? -1 : 0;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500324}
325
Sean Paulef8f1f92015-04-29 16:05:23 -0400326static int hwc_get_display_attributes(struct hwc_composer_device_1 *dev,
327 int display, uint32_t config,
328 const uint32_t *attributes,
329 int32_t *values) {
330 struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
Sean Paul6a55e9f2015-04-30 15:31:06 -0400331 DrmConnector *c = ctx->drm.GetConnectorForDisplay(display);
Sean Paulef8f1f92015-04-29 16:05:23 -0400332 if (!c) {
Sean Paul6a55e9f2015-04-30 15:31:06 -0400333 ALOGE("Failed to get DrmConnector for display %d", display);
Sean Paulef8f1f92015-04-29 16:05:23 -0400334 return -ENODEV;
335 }
Sean Paul6a55e9f2015-04-30 15:31:06 -0400336 DrmMode mode;
337 for (DrmConnector::ModeIter iter = c->begin_modes(); iter != c->end_modes();
338 ++iter) {
339 if (iter->id() == config) {
340 mode = *iter;
341 break;
342 }
343 }
344 if (mode.id() == 0) {
345 ALOGE("Failed to find active mode for display %d", display);
346 return -ENOENT;
Sean Paulef8f1f92015-04-29 16:05:23 -0400347 }
Sean Paule0c4c3d2015-01-20 16:56:04 -0500348
Sean Paul6a55e9f2015-04-30 15:31:06 -0400349 uint32_t mm_width = c->mm_width();
350 uint32_t mm_height = c->mm_height();
Sean Paulef8f1f92015-04-29 16:05:23 -0400351 for (int i = 0; attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; ++i) {
352 switch (attributes[i]) {
353 case HWC_DISPLAY_VSYNC_PERIOD:
Sean Paul6a55e9f2015-04-30 15:31:06 -0400354 values[i] = 1000 * 1000 * 1000 / mode.v_refresh();
Sean Paulef8f1f92015-04-29 16:05:23 -0400355 break;
356 case HWC_DISPLAY_WIDTH:
Sean Paul6a55e9f2015-04-30 15:31:06 -0400357 values[i] = mode.h_display();
Sean Paulef8f1f92015-04-29 16:05:23 -0400358 break;
359 case HWC_DISPLAY_HEIGHT:
Sean Paul6a55e9f2015-04-30 15:31:06 -0400360 values[i] = mode.v_display();
Sean Paulef8f1f92015-04-29 16:05:23 -0400361 break;
362 case HWC_DISPLAY_DPI_X:
363 /* Dots per 1000 inches */
Sean Paul6a55e9f2015-04-30 15:31:06 -0400364 values[i] = mm_width ? (mode.h_display() * UM_PER_INCH) / mm_width : 0;
Sean Paulef8f1f92015-04-29 16:05:23 -0400365 break;
366 case HWC_DISPLAY_DPI_Y:
367 /* Dots per 1000 inches */
Sean Paul6a55e9f2015-04-30 15:31:06 -0400368 values[i] =
369 mm_height ? (mode.v_display() * UM_PER_INCH) / mm_height : 0;
Sean Paulef8f1f92015-04-29 16:05:23 -0400370 break;
371 }
372 }
Sean Paulef8f1f92015-04-29 16:05:23 -0400373 return 0;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500374}
375
Sean Paulef8f1f92015-04-29 16:05:23 -0400376static int hwc_get_active_config(struct hwc_composer_device_1 *dev,
377 int display) {
378 struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
Sean Paul6a55e9f2015-04-30 15:31:06 -0400379 DrmConnector *c = ctx->drm.GetConnectorForDisplay(display);
380 if (!c) {
381 ALOGE("Failed to get DrmConnector for display %d", display);
Sean Paulef8f1f92015-04-29 16:05:23 -0400382 return -ENODEV;
383 }
Sean Paule0c4c3d2015-01-20 16:56:04 -0500384
Sean Paul6a55e9f2015-04-30 15:31:06 -0400385 DrmMode mode = c->active_mode();
Sean Paule42febf2015-05-07 11:35:29 -0700386 hwc_drm_display_t *hd = &ctx->displays[display];
Sean Paul6a55e9f2015-04-30 15:31:06 -0400387 for (size_t i = 0; i < hd->config_ids.size(); ++i) {
388 if (hd->config_ids[i] == mode.id())
389 return i;
Sean Paulef8f1f92015-04-29 16:05:23 -0400390 }
Sean Paul6a55e9f2015-04-30 15:31:06 -0400391 return -1;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500392}
393
Sean Paulef8f1f92015-04-29 16:05:23 -0400394static int hwc_set_active_config(struct hwc_composer_device_1 *dev, int display,
395 int index) {
396 struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
Sean Paule42febf2015-05-07 11:35:29 -0700397 hwc_drm_display_t *hd = &ctx->displays[display];
Sean Paul6a55e9f2015-04-30 15:31:06 -0400398 if (index >= (int)hd->config_ids.size()) {
399 ALOGE("Invalid config index %d passed in", index);
400 return -EINVAL;
Sean Paulef8f1f92015-04-29 16:05:23 -0400401 }
Sean Paule0c4c3d2015-01-20 16:56:04 -0500402
Sean Paule42febf2015-05-07 11:35:29 -0700403 int ret =
Sean Paul6a55e9f2015-04-30 15:31:06 -0400404 ctx->drm.SetDisplayActiveMode(display, hd->config_ids[index]);
405 if (ret) {
406 ALOGE("Failed to set config for display %d", display);
407 return ret;
Sean Paulef8f1f92015-04-29 16:05:23 -0400408 }
Sean Paule0c4c3d2015-01-20 16:56:04 -0500409
Sean Paul6a55e9f2015-04-30 15:31:06 -0400410 return ret;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500411}
412
Sean Paulef8f1f92015-04-29 16:05:23 -0400413static int hwc_device_close(struct hw_device_t *dev) {
414 struct hwc_context_t *ctx = (struct hwc_context_t *)dev;
Sean Paulef8f1f92015-04-29 16:05:23 -0400415 delete ctx;
Sean Paulef8f1f92015-04-29 16:05:23 -0400416 return 0;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500417}
418
Sean Paul24a26e32015-02-04 10:34:47 -0800419/*
420 * TODO: This function sets the active config to the first one in the list. This
421 * should be fixed such that it selects the preferred mode for the display, or
422 * some other, saner, method of choosing the config.
423 */
Sean Paule42febf2015-05-07 11:35:29 -0700424static int hwc_set_initial_config(hwc_drm_display_t *hd) {
Sean Paulef8f1f92015-04-29 16:05:23 -0400425 uint32_t config;
426 size_t num_configs = 1;
427 int ret = hwc_get_display_configs(&hd->ctx->device, hd->display, &config,
428 &num_configs);
429 if (ret || !num_configs)
430 return 0;
Sean Paul24a26e32015-02-04 10:34:47 -0800431
Sean Paulef8f1f92015-04-29 16:05:23 -0400432 ret = hwc_set_active_config(&hd->ctx->device, hd->display, 0);
433 if (ret) {
434 ALOGE("Failed to set active config d=%d ret=%d", hd->display, ret);
435 return ret;
436 }
Sean Paul24a26e32015-02-04 10:34:47 -0800437
Sean Paulef8f1f92015-04-29 16:05:23 -0400438 return ret;
Sean Paul24a26e32015-02-04 10:34:47 -0800439}
440
Sean Paul6a55e9f2015-04-30 15:31:06 -0400441static int hwc_initialize_display(struct hwc_context_t *ctx, int display) {
Sean Paule42febf2015-05-07 11:35:29 -0700442 hwc_drm_display_t *hd = &ctx->displays[display];
Sean Paulef8f1f92015-04-29 16:05:23 -0400443 hd->ctx = ctx;
444 hd->display = display;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500445
Sean Paulb386f1b2015-05-13 06:33:23 -0700446 int ret = hwc_set_initial_config(hd);
Sean Paulef8f1f92015-04-29 16:05:23 -0400447 if (ret) {
448 ALOGE("Failed to set initial config for d=%d ret=%d", display, ret);
Sean Paulef8f1f92015-04-29 16:05:23 -0400449 return ret;
450 }
Sean Paul24a26e32015-02-04 10:34:47 -0800451
Sean Paul4057be32015-05-13 06:23:09 -0700452 ret = hd->vsync_worker.Init(&ctx->drm, display);
453 if (ret) {
454 ALOGE("Failed to create event worker for display %d %d\n", display, ret);
455 return ret;
456 }
457
Sean Paulef8f1f92015-04-29 16:05:23 -0400458 return 0;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500459}
460
Sean Paulef8f1f92015-04-29 16:05:23 -0400461static int hwc_enumerate_displays(struct hwc_context_t *ctx) {
Sean Paul6a55e9f2015-04-30 15:31:06 -0400462 int ret;
463 for (DrmResources::ConnectorIter c = ctx->drm.begin_connectors();
464 c != ctx->drm.end_connectors(); ++c) {
465 ret = hwc_initialize_display(ctx, (*c)->display());
466 if (ret) {
467 ALOGE("Failed to initialize display %d", (*c)->display());
468 return ret;
Sean Paulef8f1f92015-04-29 16:05:23 -0400469 }
470 }
Sean Paulef8f1f92015-04-29 16:05:23 -0400471
472 return 0;
Sean Paule0c4c3d2015-01-20 16:56:04 -0500473}
474
Sean Paulef8f1f92015-04-29 16:05:23 -0400475static int hwc_device_open(const struct hw_module_t *module, const char *name,
476 struct hw_device_t **dev) {
477 if (strcmp(name, HWC_HARDWARE_COMPOSER)) {
478 ALOGE("Invalid module name- %s", name);
479 return -EINVAL;
480 }
481
482 struct hwc_context_t *ctx = new hwc_context_t();
483 if (!ctx) {
484 ALOGE("Failed to allocate hwc context");
485 return -ENOMEM;
486 }
487
Sean Paul6a55e9f2015-04-30 15:31:06 -0400488 int ret = ctx->drm.Init();
489 if (ret) {
490 ALOGE("Can't initialize Drm object %d", ret);
491 delete ctx;
492 return ret;
493 }
494
Sean Paulda6270d2015-06-01 14:11:52 -0400495 ctx->importer = Importer::CreateInstance(&ctx->drm);
496 if (!ctx->importer) {
497 ALOGE("Failed to create importer instance");
Sean Paulef8f1f92015-04-29 16:05:23 -0400498 delete ctx;
499 return ret;
500 }
501
Sean Paulef8f1f92015-04-29 16:05:23 -0400502 ret = hwc_enumerate_displays(ctx);
503 if (ret) {
504 ALOGE("Failed to enumerate displays: %s", strerror(ret));
Sean Paul6a55e9f2015-04-30 15:31:06 -0400505 delete ctx;
506 return ret;
507 }
508
Sean Paulef8f1f92015-04-29 16:05:23 -0400509 ctx->device.common.tag = HARDWARE_DEVICE_TAG;
510 ctx->device.common.version = HWC_DEVICE_API_VERSION_1_4;
511 ctx->device.common.module = const_cast<hw_module_t *>(module);
512 ctx->device.common.close = hwc_device_close;
513
514 ctx->device.prepare = hwc_prepare;
515 ctx->device.set = hwc_set;
516 ctx->device.eventControl = hwc_event_control;
517 ctx->device.setPowerMode = hwc_set_power_mode;
518 ctx->device.query = hwc_query;
519 ctx->device.registerProcs = hwc_register_procs;
520 ctx->device.getDisplayConfigs = hwc_get_display_configs;
521 ctx->device.getDisplayAttributes = hwc_get_display_attributes;
522 ctx->device.getActiveConfig = hwc_get_active_config;
523 ctx->device.setActiveConfig = hwc_set_active_config;
524 ctx->device.setCursorPositionAsync = NULL; /* TODO: Add cursor */
525
526 *dev = &ctx->device.common;
527
528 return 0;
529}
Sean Paul6a55e9f2015-04-30 15:31:06 -0400530}
Sean Paulef8f1f92015-04-29 16:05:23 -0400531
Sean Paul6a55e9f2015-04-30 15:31:06 -0400532static struct hw_module_methods_t hwc_module_methods = {
533 open : android::hwc_device_open
534};
Sean Paule0c4c3d2015-01-20 16:56:04 -0500535
536hwc_module_t HAL_MODULE_INFO_SYM = {
Sean Paulef8f1f92015-04-29 16:05:23 -0400537 common : {
538 tag : HARDWARE_MODULE_TAG,
539 version_major : 1,
540 version_minor : 0,
541 id : HWC_HARDWARE_MODULE_ID,
542 name : "DRM hwcomposer module",
543 author : "The Android Open Source Project",
544 methods : &hwc_module_methods,
545 dso : NULL,
546 reserved : {0},
547 }
Sean Paule0c4c3d2015-01-20 16:56:04 -0500548};