framebuffer_service.c revision 5a536efa5b5f5d973232846d5fe6818df84ab5dc
1/*
2 * Copyright (C) 2007 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#include <stdlib.h>
18#include <stdio.h>
19#include <unistd.h>
20#include <string.h>
21#include <fcntl.h>
22#include <errno.h>
23#include <sys/types.h>
24#include <sys/wait.h>
25
26#include "fdevent.h"
27#include "adb.h"
28
29#include <linux/fb.h>
30#include <sys/ioctl.h>
31#include <sys/mman.h>
32
33/* TODO:
34** - sync with vsync to avoid tearing
35*/
36/* This version number defines the format of the fbinfo struct.
37   It must match versioning in ddms where this data is consumed. */
38#define DDMS_RAWIMAGE_VERSION 1
39struct fbinfo {
40    unsigned int version;
41    unsigned int bpp;
42    unsigned int size;
43    unsigned int width;
44    unsigned int height;
45    unsigned int red_offset;
46    unsigned int red_length;
47    unsigned int blue_offset;
48    unsigned int blue_length;
49    unsigned int green_offset;
50    unsigned int green_length;
51    unsigned int alpha_offset;
52    unsigned int alpha_length;
53} __attribute__((packed));
54
55void framebuffer_service(int fd, void *cookie)
56{
57    struct fbinfo fbinfo;
58    unsigned int i;
59    char buf[640];
60    int fd_screencap;
61    int w, h, f;
62    int fds[2];
63
64    if (pipe(fds) < 0) goto done;
65
66    pid_t pid = fork();
67    if (pid < 0) goto done;
68
69    if (pid == 0) {
70        dup2(fds[1], STDOUT_FILENO);
71        close(fds[0]);
72        close(fds[1]);
73        const char* command = "screencap";
74        const char *args[2] = {command, NULL};
75        execvp(command, (char**)args);
76        exit(1);
77    }
78
79    fd_screencap = fds[0];
80
81    /* read w, h & format */
82    if(readx(fd_screencap, &w, 4)) goto done;
83    if(readx(fd_screencap, &h, 4)) goto done;
84    if(readx(fd_screencap, &f, 4)) goto done;
85
86    fbinfo.version = DDMS_RAWIMAGE_VERSION;
87    /* see hardware/hardware.h */
88    switch (f) {
89        case 1: /* RGBA_8888 */
90            fbinfo.bpp = 32;
91            fbinfo.size = w * h * 4;
92            fbinfo.width = w;
93            fbinfo.height = h;
94            fbinfo.red_offset = 0;
95            fbinfo.red_length = 8;
96            fbinfo.green_offset = 8;
97            fbinfo.green_length = 8;
98            fbinfo.blue_offset = 16;
99            fbinfo.blue_length = 8;
100            fbinfo.alpha_offset = 24;
101            fbinfo.alpha_length = 8;
102            break;
103        case 2: /* RGBX_8888 */
104            fbinfo.bpp = 32;
105            fbinfo.size = w * h * 4;
106            fbinfo.width = w;
107            fbinfo.height = h;
108            fbinfo.red_offset = 0;
109            fbinfo.red_length = 8;
110            fbinfo.green_offset = 8;
111            fbinfo.green_length = 8;
112            fbinfo.blue_offset = 16;
113            fbinfo.blue_length = 8;
114            fbinfo.alpha_offset = 24;
115            fbinfo.alpha_length = 0;
116            break;
117        case 3: /* RGB_888 */
118            fbinfo.bpp = 24;
119            fbinfo.size = w * h * 3;
120            fbinfo.width = w;
121            fbinfo.height = h;
122            fbinfo.red_offset = 0;
123            fbinfo.red_length = 8;
124            fbinfo.green_offset = 8;
125            fbinfo.green_length = 8;
126            fbinfo.blue_offset = 16;
127            fbinfo.blue_length = 8;
128            fbinfo.alpha_offset = 24;
129            fbinfo.alpha_length = 0;
130            break;
131        case 4: /* RGB_565 */
132            fbinfo.bpp = 16;
133            fbinfo.size = w * h * 2;
134            fbinfo.width = w;
135            fbinfo.height = h;
136            fbinfo.red_offset = 11;
137            fbinfo.red_length = 5;
138            fbinfo.green_offset = 5;
139            fbinfo.green_length = 6;
140            fbinfo.blue_offset = 0;
141            fbinfo.blue_length = 5;
142            fbinfo.alpha_offset = 0;
143            fbinfo.alpha_length = 0;
144            break;
145        case 5: /* BGRA_8888 */
146            fbinfo.bpp = 32;
147            fbinfo.size = w * h * 4;
148            fbinfo.width = w;
149            fbinfo.height = h;
150            fbinfo.red_offset = 16;
151            fbinfo.red_length = 8;
152            fbinfo.green_offset = 8;
153            fbinfo.green_length = 8;
154            fbinfo.blue_offset = 0;
155            fbinfo.blue_length = 8;
156            fbinfo.alpha_offset = 24;
157            fbinfo.alpha_length = 8;
158           break;
159        default:
160            goto done;
161    }
162
163    /* write header */
164    if(writex(fd, &fbinfo, sizeof(fbinfo))) goto done;
165
166    /* write data */
167    for(i = 0; i < fbinfo.size; i += sizeof(buf)) {
168      if(readx(fd_screencap, buf, sizeof(buf))) goto done;
169      if(writex(fd, buf, sizeof(buf))) goto done;
170    }
171    if(readx(fd_screencap, buf, fbinfo.size % sizeof(buf))) goto done;
172    if(writex(fd, buf, fbinfo.size % sizeof(buf))) goto done;
173
174done:
175    TEMP_FAILURE_RETRY(waitpid(pid, NULL, 0));
176
177    close(fds[0]);
178    close(fds[1]);
179    close(fd);
180}
181