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