1d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang/*
2d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang * Copyright (C) 2012 The Android Open Source Project
3d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang *
4d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang * Licensed under the Apache License, Version 2.0 (the "License");
5d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang * you may not use this file except in compliance with the License.
6d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang * You may obtain a copy of the License at
7d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang *
8d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang *      http://www.apache.org/licenses/LICENSE-2.0
9d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang *
10d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang * Unless required by applicable law or agreed to in writing, software
11d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang * distributed under the License is distributed on an "AS IS" BASIS,
12d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang * See the License for the specific language governing permissions and
14d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang * limitations under the License.
15d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang */
16d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang#include <pthread.h>
17d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang#include <stdlib.h>
18d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang#include <sys/time.h>
19d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang#include <sys/resource.h>
20d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
21d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang#include <cutils/log.h>
22d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang#include <hardware/hwcomposer.h>
23d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang#include <sync/sync.h>
24d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
25d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Langstruct ranchu_hwc_composer_device_1 {
26d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    hwc_composer_device_1_t base; // constant after init
27d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    const hwc_procs_t *procs;     // constant after init
28d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    pthread_t vsync_thread;       // constant after init
29d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    int32_t vsync_period_ns;      // constant after init
30d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    framebuffer_device_t* fbdev;  // constant after init
31d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
32d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    pthread_mutex_t vsync_lock;
33d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    bool vsync_callback_enabled; // protected by this->vsync_lock
34d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang};
35d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
36d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Langstatic int hwc_prepare(hwc_composer_device_1_t* dev __unused,
37d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang                       size_t numDisplays, hwc_display_contents_1_t** displays) {
38d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
39d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    if (!numDisplays || !displays) return 0;
40d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
41d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    hwc_display_contents_1_t* contents = displays[HWC_DISPLAY_PRIMARY];
42d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
43d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    if (!contents) return 0;
44d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
45d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    for (size_t i = 0; i < contents->numHwLayers; i++) {
46d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    // We do not handle any layers, so set composition type of any non
47d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    // HWC_FRAMEBUFFER_TARGET layer to to HWC_FRAMEBUFFER.
48d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        if (contents->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
49d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            continue;
50d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        }
51d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        contents->hwLayers[i].compositionType = HWC_FRAMEBUFFER;
52d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    }
53d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    return 0;
54d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang}
55d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
56d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Langstatic int hwc_set(struct hwc_composer_device_1* dev,size_t numDisplays,
57d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang                   hwc_display_contents_1_t** displays) {
58d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    struct ranchu_hwc_composer_device_1* pdev = (struct ranchu_hwc_composer_device_1*)dev;
59d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    if (!numDisplays || !displays) {
60d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        return 0;
61d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    }
62d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
63d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    hwc_display_contents_1_t* contents = displays[HWC_DISPLAY_PRIMARY];
64d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
65d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    int retireFenceFd = -1;
66d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    int err = 0;
67d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    for (size_t layer = 0; layer < contents->numHwLayers; layer++) {
68d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            hwc_layer_1_t* fb_layer = &contents->hwLayers[layer];
69d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
70d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        int releaseFenceFd = -1;
71d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        if (fb_layer->acquireFenceFd > 0) {
72d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            const int kAcquireWarningMS= 3000;
73d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            err = sync_wait(fb_layer->acquireFenceFd, kAcquireWarningMS);
74d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            if (err < 0 && errno == ETIME) {
75d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang                ALOGE("hwcomposer waited on fence %d for %d ms",
76d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang                      fb_layer->acquireFenceFd, kAcquireWarningMS);
77d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            }
78d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            close(fb_layer->acquireFenceFd);
79d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
80d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            if (fb_layer->compositionType != HWC_FRAMEBUFFER_TARGET) {
81d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang                ALOGE("hwcomposer found acquire fence on layer %d which is not an"
82d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang                      "HWC_FRAMEBUFFER_TARGET layer", layer);
83d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            }
84d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
85d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            releaseFenceFd = dup(fb_layer->acquireFenceFd);
86d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            fb_layer->acquireFenceFd = -1;
87d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        }
88d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
89d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        if (fb_layer->compositionType != HWC_FRAMEBUFFER_TARGET) {
90d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            continue;
91d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        }
92d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
93d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        pdev->fbdev->post(pdev->fbdev, fb_layer->handle);
94d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        fb_layer->releaseFenceFd = releaseFenceFd;
95d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
96d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        if (releaseFenceFd > 0) {
97d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            if (retireFenceFd == -1) {
98d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang                retireFenceFd = dup(releaseFenceFd);
99d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            } else {
100d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang                int mergedFenceFd = sync_merge("hwc_set retireFence",
101d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang                                               releaseFenceFd, retireFenceFd);
102d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang                close(retireFenceFd);
103d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang                retireFenceFd = mergedFenceFd;
104d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            }
105d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        }
106d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    }
107d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
108d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    contents->retireFenceFd = retireFenceFd;
109d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    return err;
110d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang}
111d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
112d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Langstatic int hwc_query(struct hwc_composer_device_1* dev, int what, int* value) {
113d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    struct ranchu_hwc_composer_device_1* pdev =
114d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            (struct ranchu_hwc_composer_device_1*)dev;
115d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
116d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    switch (what) {
117d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        case HWC_BACKGROUND_LAYER_SUPPORTED:
118d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            // we do not support the background layer
119d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            value[0] = 0;
120d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            break;
121d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        case HWC_VSYNC_PERIOD:
122d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            value[0] = pdev->vsync_period_ns;
123d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            break;
124d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        default:
125d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            // unsupported query
126d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            ALOGE("%s badness unsupported query what=%d", __FUNCTION__, what);
127d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            return -EINVAL;
128d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    }
129d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    return 0;
130d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang}
131d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
132d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Langstatic int hwc_event_control(struct hwc_composer_device_1* dev, int dpy __unused,
133d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang                             int event, int enabled) {
134d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    struct ranchu_hwc_composer_device_1* pdev =
135d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            (struct ranchu_hwc_composer_device_1*)dev;
136d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    int ret = -EINVAL;
137d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
138d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    // enabled can only be 0 or 1
139d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    if (!(enabled & ~1)) {
140d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        if (event == HWC_EVENT_VSYNC) {
141d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            pthread_mutex_lock(&pdev->vsync_lock);
142d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            pdev->vsync_callback_enabled=enabled;
143d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            pthread_mutex_unlock(&pdev->vsync_lock);
144d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            ret = 0;
145d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        }
146d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    }
147d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    return ret;
148d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang}
149d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
150d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Langstatic int hwc_blank(struct hwc_composer_device_1* dev __unused, int disp,
151d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang                     int blank __unused) {
152d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    if (disp != HWC_DISPLAY_PRIMARY) {
153d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        return -EINVAL;
154d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    }
155d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    return 0;
156d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang}
157d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
158d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Langstatic void hwc_dump(hwc_composer_device_1* dev __unused, char* buff __unused,
159d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang                     int buff_len __unused) {
160d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    // This is run when running dumpsys.
161d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    // No-op for now.
162d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang}
163d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
164d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
165d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Langstatic int hwc_get_display_configs(struct hwc_composer_device_1* dev __unused,
166d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang                                   int disp, uint32_t* configs, size_t* numConfigs) {
167d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    if (*numConfigs == 0) {
168d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        return 0;
169d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    }
170d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
171d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    if (disp == HWC_DISPLAY_PRIMARY) {
172d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        configs[0] = 0;
173d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        *numConfigs = 1;
174d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        return 0;
175d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    }
176d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
177d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    return -EINVAL;
178d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang}
179d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
180d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
181d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Langstatic int32_t hwc_attribute(struct ranchu_hwc_composer_device_1* pdev,
182d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang                             const uint32_t attribute) {
183d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    switch(attribute) {
184d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        case HWC_DISPLAY_VSYNC_PERIOD:
185d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            return pdev->vsync_period_ns;
186d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        case HWC_DISPLAY_WIDTH:
187d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            return pdev->fbdev->width;
188d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        case HWC_DISPLAY_HEIGHT:
189d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            return pdev->fbdev->height;
190d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        case HWC_DISPLAY_DPI_X:
191d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            return pdev->fbdev->xdpi*1000;
192d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        case HWC_DISPLAY_DPI_Y:
193d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            return pdev->fbdev->ydpi*1000;
194d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        default:
195d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            ALOGE("unknown display attribute %u", attribute);
196d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            return -EINVAL;
197d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    }
198d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang}
199d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
200d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Langstatic int hwc_get_display_attributes(struct hwc_composer_device_1* dev __unused,
201d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang                                      int disp, uint32_t config __unused,
202d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang                                      const uint32_t* attributes, int32_t* values) {
203d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
204d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    struct ranchu_hwc_composer_device_1* pdev = (struct ranchu_hwc_composer_device_1*)dev;
205d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    for (int i = 0; attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; i++) {
206d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        if (disp == HWC_DISPLAY_PRIMARY) {
207d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            values[i] = hwc_attribute(pdev, attributes[i]);
208d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        } else {
209d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            ALOGE("unknown display type %u", disp);
210d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            return -EINVAL;
211d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        }
212d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    }
213d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
214d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    return 0;
215d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang}
216d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
217d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Langstatic int hwc_close(hw_device_t* dev) {
218d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    struct ranchu_hwc_composer_device_1* pdev = (struct ranchu_hwc_composer_device_1*)dev;
219d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    pthread_kill(pdev->vsync_thread, SIGTERM);
220d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    pthread_join(pdev->vsync_thread, NULL);
221d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    free(dev);
222d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    return 0;
223d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang}
224d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
225d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Langstatic void* hwc_vsync_thread(void* data) {
226d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    struct ranchu_hwc_composer_device_1* pdev = (struct ranchu_hwc_composer_device_1*)data;
227d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
228d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
229d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    struct timespec rt;
230d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    if (clock_gettime(CLOCK_MONOTONIC, &rt) == -1) {
231d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        ALOGE("%s:%d error in vsync thread clock_gettime: %s",
232d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang              __FILE__, __LINE__, strerror(errno));
233d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    }
234d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    const int log_interval = 60;
235d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    int64_t last_logged = rt.tv_sec;
236d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    int sent = 0;
237d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    int last_sent = 0;
238d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    bool vsync_enabled = false;
239d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    struct timespec wait_time;
240d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    wait_time.tv_sec = 0;
241d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    wait_time.tv_nsec = pdev->vsync_period_ns;
242d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
243d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    while (true) {
244d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        int err = nanosleep(&wait_time, NULL);
245d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        if (err == -1) {
246d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            if (errno == EINTR) {
247d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang                break;
248d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            }
249d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            ALOGE("error in vsync thread: %s", strerror(errno));
250d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        }
251d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
252d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        pthread_mutex_lock(&pdev->vsync_lock);
253d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        vsync_enabled = pdev->vsync_callback_enabled;
254d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        pthread_mutex_unlock(&pdev->vsync_lock);
255d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
256d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        if (!vsync_enabled) {
257d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            continue;
258d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        }
259d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
260d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        if (clock_gettime(CLOCK_MONOTONIC, &rt) == -1) {
261d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            ALOGE("%s:%d error in vsync thread clock_gettime: %s",
262d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang                  __FILE__, __LINE__, strerror(errno));
263d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        }
264d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
265d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        int64_t timestamp = int64_t(rt.tv_sec) * 1e9 + rt.tv_nsec;
266d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        pdev->procs->vsync(pdev->procs, 0, timestamp);
267d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        if (rt.tv_sec - last_logged >= log_interval) {
268d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            ALOGD("hw_composer sent %d syncs in %ds", sent - last_sent, rt.tv_sec - last_logged);
269d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            last_logged = rt.tv_sec;
270d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang            last_sent = sent;
271d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        }
272d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        ++sent;
273d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    }
274d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
275d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    return NULL;
276d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang}
277d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
278d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Langstatic void hwc_register_procs(struct hwc_composer_device_1* dev,
279d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang                               hwc_procs_t const* procs) {
280d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    struct ranchu_hwc_composer_device_1* pdev = (struct ranchu_hwc_composer_device_1*)dev;
281d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    pdev->procs = procs;
282d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang}
283d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
284d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Langstatic int hwc_open(const struct hw_module_t* module, const char* name,
285d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang                    struct hw_device_t** device) {
286d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    int ret = 0;
287d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
288d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    if (strcmp(name, HWC_HARDWARE_COMPOSER)) {
289d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        ALOGE("%s called with bad name %s", __FUNCTION__, name);
290d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        return -EINVAL;
291d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    }
292d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
293d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    ranchu_hwc_composer_device_1 *pdev = new ranchu_hwc_composer_device_1();
294d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    if (!pdev) {
295d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        ALOGE("%s failed to allocate dev", __FUNCTION__);
296d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        return -ENOMEM;
297d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    }
298d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
299d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    pdev->base.common.tag = HARDWARE_DEVICE_TAG;
300d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    pdev->base.common.version = HWC_DEVICE_API_VERSION_1_1;
301d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    pdev->base.common.module = const_cast<hw_module_t *>(module);
302d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    pdev->base.common.close = hwc_close;
303d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
304d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    pdev->base.prepare = hwc_prepare;
305d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    pdev->base.set = hwc_set;
306d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    pdev->base.eventControl = hwc_event_control;
307d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    pdev->base.blank = hwc_blank;
308d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    pdev->base.query = hwc_query;
309d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    pdev->base.registerProcs = hwc_register_procs;
310d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    pdev->base.dump = hwc_dump;
311d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    pdev->base.getDisplayConfigs = hwc_get_display_configs;
312d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    pdev->base.getDisplayAttributes = hwc_get_display_attributes;
313d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
314d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    pdev->vsync_period_ns = 1000*1000*1000/60; // vsync is 60 hz
315d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
316d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    hw_module_t const* hw_module;
317d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &hw_module);
318d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    if (ret != 0) {
319d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        ALOGE("ranchu_hw_composer hwc_open %s module not found", GRALLOC_HARDWARE_MODULE_ID);
320d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        return ret;
321d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    }
322d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    ret = framebuffer_open(hw_module, &pdev->fbdev);
323d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    if (ret != 0) {
324d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        ALOGE("ranchu_hw_composer hwc_open could not open framebuffer");
325d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    }
326d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
327d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    pthread_mutex_init(&pdev->vsync_lock, NULL);
328d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    pdev->vsync_callback_enabled = false;
329d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
330d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    ret = pthread_create (&pdev->vsync_thread, NULL, hwc_vsync_thread, pdev);
331d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    if (ret) {
332d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        ALOGE("ranchu_hw_composer could not start vsync_thread\n");
333d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    }
334d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
335d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    *device = &pdev->base.common;
336d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
337d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    return ret;
338d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang}
339d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
340d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
341d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Langstatic struct hw_module_methods_t hwc_module_methods = {
342d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    open: hwc_open,
343d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang};
344d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang
345d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Langhwc_module_t HAL_MODULE_INFO_SYM = {
346d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    common: {
347d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        tag: HARDWARE_MODULE_TAG,
348d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        module_api_version: HWC_MODULE_API_VERSION_0_1,
349d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        hal_api_version: HARDWARE_HAL_API_VERSION,
350d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        id: HWC_HARDWARE_MODULE_ID,
351d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        name: "Android Emulator hwcomposer module",
352d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        author: "The Android Open Source Project",
353d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang        methods: &hwc_module_methods,
354d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang    }
355d4d0af6f3f24fb7e50cf514e486c7c6e953b6a05Joshua Lang};
356