137f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian/*
237f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian * Copyright (C) 2012 The Android Open Source Project
337f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian *
437f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian * Licensed under the Apache License, Version 2.0 (the "License");
537f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian * you may not use this file except in compliance with the License.
637f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian * You may obtain a copy of the License at
737f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian *
837f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian *      http://www.apache.org/licenses/LICENSE-2.0
937f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian *
1037f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian * Unless required by applicable law or agreed to in writing, software
1137f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian * distributed under the License is distributed on an "AS IS" BASIS,
1237f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1337f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian * See the License for the specific language governing permissions and
1437f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian * limitations under the License.
1537f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian */
1637f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian
1737f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian#include <stdint.h>
1837f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian#include <sys/types.h>
1937f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian
2037f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian#include <fcntl.h>
2137f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian#include <sys/ioctl.h>
2237f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian#include <linux/fb.h>
2337f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian#include <linux/input.h>
2437f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian#include <errno.h>
2537f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian#include <string.h>
2637f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian#include <stdio.h>
2737f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian#include <cutils/memory.h>
2837f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian#include <asm-generic/mman.h>
2937f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian#include <sys/mman.h>
3037f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian#include <utils/threads.h>
3137f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian#include <unistd.h>
3237f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian#include <math.h>
3337f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian
3437f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopianusing namespace android;
3537f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian
3637f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian#ifndef FBIO_WAITFORVSYNC
3737f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian#define FBIO_WAITFORVSYNC   _IOW('F', 0x20, __u32)
3837f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian#endif
3937f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian
4037f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopianstruct Buffer {
4137f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    size_t w;
4237f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    size_t h;
4337f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    size_t s;
4437f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    union {
4537f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        void* addr;
4637f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        uint32_t* pixels;
4737f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    };
4837f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian};
4937f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian
5037f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopianvoid clearBuffer(Buffer* buf, uint32_t pixel) {
5137f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    android_memset32(buf->pixels, pixel, buf->s * buf->h * 4);
5237f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian}
5337f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian
5437f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopianvoid drawTwoPixels(Buffer* buf, uint32_t pixel, ssize_t x, ssize_t y, size_t w) {
5537f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    if (y>0 && y<ssize_t(buf->h)) {
5637f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        uint32_t* bits = buf->pixels + y * buf->s;
571c8cbb54407b9c1d56626de80a796a395012a92cAurimas Liutikas        if (x>=0 && x<ssize_t(buf->w)) {
5837f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian            bits[x] = pixel;
5937f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        }
6037f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        ssize_t W(w);
611c8cbb54407b9c1d56626de80a796a395012a92cAurimas Liutikas        if ((x+W)>=0 && (x+W)<ssize_t(buf->w)) {
6237f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian            bits[x+W] = pixel;
6337f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        }
6437f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    }
6537f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian}
6637f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian
6737f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopianvoid drawHLine(Buffer* buf, uint32_t pixel, ssize_t x, ssize_t y, size_t w) {
6837f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    if (y>0 && y<ssize_t(buf->h)) {
6937f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        ssize_t W(w);
7037f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        if (x<0) {
7137f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian            W += x;
7237f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian            x = 0;
7337f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        }
7437f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        if (x+w > buf->w) {
7537f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian            W = buf->w - x;
7637f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        }
7737f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        if (W>0) {
7837f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian            uint32_t* bits = buf->pixels + y * buf->s + x;
7937f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian            android_memset32(bits, pixel, W*4);
8037f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        }
8137f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    }
8237f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian}
8337f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian
8437f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopianvoid drawRect(Buffer* buf, uint32_t pixel, ssize_t x, ssize_t y, size_t w, size_t h) {
8537f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    ssize_t W(w), H(h);
8637f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    if (x<0) {
8737f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        w += x;
8837f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        x = 0;
8937f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    }
9037f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    if (y<0) {
9137f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        h += y;
9237f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        y = 0;
9337f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    }
9437f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    if (x+w > buf->w)   W = buf->w - x;
9537f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    if (y+h > buf->h)   H = buf->h - y;
9637f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    if (W>0 && H>0) {
9737f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        uint32_t* bits = buf->pixels + y * buf->s + x;
9837f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        for (ssize_t i=0 ; i<H ; i++) {
9937f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian            android_memset32(bits, pixel, W*4);
10037f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian            bits += buf->s;
10137f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        }
10237f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    }
10337f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian}
10437f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian
10537f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopianvoid drawCircle(Buffer* buf, uint32_t pixel,
10637f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        size_t x0, size_t y0, size_t radius, bool filled = false) {
10737f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    ssize_t f = 1 - radius;
10837f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    ssize_t ddF_x = 1;
10937f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    ssize_t ddF_y = -2 * radius;
11037f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    ssize_t x = 0;
11137f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    ssize_t y = radius;
11237f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    if (filled) {
11337f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        drawHLine(buf, pixel, x0-radius, y0, 2*radius);
11437f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    } else {
11537f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        drawTwoPixels(buf, pixel, x0-radius, y0, 2*radius);
11637f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    }
11737f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    while (x < y) {
11837f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        if (f >= 0) {
11937f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian            y--;
12037f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian            ddF_y += 2;
12137f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian            f += ddF_y;
12237f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        }
12337f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        x++;
12437f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        ddF_x += 2;
12537f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        f += ddF_x;
12637f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        if (filled) {
12737f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian            drawHLine(buf, pixel, x0-x, y0+y, 2*x);
12837f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian            drawHLine(buf, pixel, x0-x, y0-y, 2*x);
12937f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian            drawHLine(buf, pixel, x0-y, y0+x, 2*y);
13037f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian            drawHLine(buf, pixel, x0-y, y0-x, 2*y);
13137f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        } else {
13237f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian            drawTwoPixels(buf, pixel, x0-x, y0+y, 2*x);
13337f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian            drawTwoPixels(buf, pixel, x0-x, y0-y, 2*x);
13437f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian            drawTwoPixels(buf, pixel, x0-y, y0+x, 2*y);
13537f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian            drawTwoPixels(buf, pixel, x0-y, y0-x, 2*y);
13637f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        }
13737f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    }
13837f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian}
13937f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian
14037f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopianclass TouchEvents {
14137f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    class EventThread : public Thread {
14237f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        int fd;
14337f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian
14437f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        virtual bool threadLoop() {
14537f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian            input_event event;
14637f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian            int first_down = 0;
14737f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian            do {
14837f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian                read(fd, &event, sizeof(event));
14937f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian                if (event.type == EV_ABS) {
15037f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian                    if (event.code == ABS_MT_TRACKING_ID) {
15137f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian                        down = event.value == -1 ? 0 : 1;
15237f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian                        first_down = down;
15337f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian                    }
15437f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian                    if (event.code == ABS_MT_POSITION_X) {
15537f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian                        x = event.value;
15637f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian                    }
15737f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian                    if (event.code == ABS_MT_POSITION_Y) {
15837f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian                        y = event.value;
15937f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian                    }
16037f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian                }
16137f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian            } while (event.type == EV_SYN);
16237f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian            return true;
16337f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        }
16437f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian
16537f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    public:
16637f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        int x, y, down;
16737f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        EventThread() : Thread(false),
16837f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian                x(0), y(0), down(0)
16937f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        {
17037f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian            fd = open("/dev/input/event1", O_RDONLY);
17137f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        }
17237f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian};
17337f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    sp<EventThread> thread;
17437f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian
17537f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopianpublic:
17637f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    TouchEvents() {
17737f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        thread = new EventThread();
17837f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        thread->run("EventThread", PRIORITY_URGENT_DISPLAY);
17937f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    }
18037f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian
18137f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    int getMostRecentPosition(int* x, int* y) {
18237f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        *x = thread->x;
18337f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        *y = thread->y;
18437f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        return thread->down;
18537f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    }
18637f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian};
18737f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian
18837f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian
18937f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopianstruct Queue {
19037f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    struct position {
19137f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        int x, y;
19237f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    };
19337f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    int index;
19437f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    position q[16];
19537f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    Queue() : index(0) { }
19637f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    void push(int x, int y) {
19737f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        index++;
19837f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        index &= 0xF;
19937f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        q[index].x = x;
20037f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        q[index].y = y;
20137f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    }
20237f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    void get(int lag, int* x, int* y) {
20337f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        const int i = (index - lag) & 0xF;
20437f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        *x = q[i].x;
20537f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        *y = q[i].y;
20637f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    }
20737f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian};
20837f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian
20937f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopianextern char *optarg;
21037f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopianextern int optind;
21137f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopianextern int optopt;
21237f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopianextern int opterr;
21337f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopianextern int optreset;
21437f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian
21537f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopianvoid usage(const char* name) {
21637f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    printf("\nusage: %s [-h] [-l lag]\n", name);
21737f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian}
21837f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian
21937f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopianint main(int argc, char** argv) {
22037f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    fb_var_screeninfo vi;
22137f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    fb_fix_screeninfo fi;
22237f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian
22337f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    int lag = 0;
22437f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    int fd = open("/dev/graphics/fb0", O_RDWR);
22537f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    ioctl(fd, FBIOGET_VSCREENINFO, &vi);
22637f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    ioctl(fd, FBIOGET_FSCREENINFO, &fi);
22737f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    void* bits = mmap(0, fi.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
22837f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    Buffer framebuffer;
22937f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    framebuffer.w = vi.xres;
23037f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    framebuffer.h = vi.yres;
23137f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    framebuffer.s = fi.line_length / (vi.bits_per_pixel >> 3);
23237f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    framebuffer.addr = bits;
23337f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian
23437f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    int ch;
23537f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    while ((ch = getopt(argc, argv, "hl:")) != -1) {
23637f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        switch (ch) {
23737f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian            case 'l':
23837f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian                lag = atoi(optarg);
23937f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian                break;
24037f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian            case 'h':
24137f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian            default:
24237f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian                usage(argv[0]);
24337f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian                exit(0);
24437f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        }
24537f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    }
24637f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    argc -= optind;
24737f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    argv += optind;
24837f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian
24937f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian
25037f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    TouchEvents touch;
25137f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    Queue queue;
25237f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian
25337f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian
2541c8cbb54407b9c1d56626de80a796a395012a92cAurimas Liutikas    int x=0, y=0;
25537f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    int lag_x=0, lag_y=0;
25637f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian
25737f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    clearBuffer(&framebuffer, 0);
25837f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    while (true) {
25937f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        uint32_t crt = 0;
2601c8cbb54407b9c1d56626de80a796a395012a92cAurimas Liutikas        ioctl(fd, FBIO_WAITFORVSYNC, &crt);
26137f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian
26237f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        // draw beam marker
26337f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        drawRect(&framebuffer, 0x400000, framebuffer.w-2, 0, 2, framebuffer.h);
26437f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        // erase screen
26537f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        if (lag) {
26637f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian            drawCircle(&framebuffer, 0, lag_x, lag_y, 100);
26737f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian            drawHLine(&framebuffer, 0, 0, lag_y, 32);
26837f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        }
26937f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        drawCircle(&framebuffer, 0, x, y, 100, true);
27037f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        drawHLine(&framebuffer, 0, 0, y, 32);
27137f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian
27237f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        // draw a line at y=1000
27337f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        drawHLine(&framebuffer, 0x808080, 0, 1000, framebuffer.w);
27437f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian
27537f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        // get touch events
27637f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        touch.getMostRecentPosition(&x, &y);
27737f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        queue.push(x, y);
27837f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        queue.get(lag, &lag_x, &lag_y);
27937f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian
28037f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        if (lag) {
28137f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian            drawCircle(&framebuffer, 0x00FF00, lag_x, lag_y, 100);
28237f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian            drawHLine(&framebuffer, 0x00FF00, 0, lag_y, 32);
28337f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        }
28437f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian
28537f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        drawCircle(&framebuffer, 0xFFFFFF, x, y, 100, true);
28637f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        drawHLine(&framebuffer, 0xFFFFFF, 0, y, 32);
28737f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian
28837f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        // draw end of frame beam marker
28937f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian        drawRect(&framebuffer, 0x004000, framebuffer.w-2, 0, 2, framebuffer.h);
29037f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    }
29137f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian
29237f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    close(fd);
29337f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian    return 0;
29437f6934e863de13926975ff5c4e60b9ee9fa79ccMathias Agopian}
295