1 /*
2 * Copyright (C) 2007 Google Inc.
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 <unistd.h>
19 #include <fcntl.h>
20 #include <stdio.h>
21 #include <sys/ioctl.h>
22 #include <sys/mman.h>
23 #include <sys/stat.h>
24 #include <sys/types.h>
25
26 #include <linux/fb.h>
27 #include <linux/msm_mdp.h>
28
29 static struct fb_var_screeninfo vi;
30
open_file(char * name,int * fd,int * len,int * fmt)31 static int open_file(char *name, int *fd, int *len, int *fmt)
32 {
33 struct stat stat;
34 char *type, *fn;
35
36 type = name;
37 fn = strchr(name, ':');
38 if (!fn)
39 return -1;
40 *(fn++) = '\0';
41
42 if (!strncmp(type, "yuv420", 6))
43 *fmt = MDP_Y_CBCR_H2V2;
44 else if (!strncmp(type, "rgb565", 6))
45 *fmt = MDP_RGB_565;
46 else {
47 fprintf(stderr, "Unsupported image type: %s\n", type);
48 return -1;
49 }
50
51 *fd = open(fn, O_RDONLY);
52 if (*fd < 0) {
53 perror("cannot open file");
54 return -1;
55 }
56
57 if (fstat(*fd, &stat) < 0) {
58 perror("cannot fstat file");
59 goto err;
60 }
61
62 *len = stat.st_size;
63
64 printf("Successfully opened file %s (fmt=%d len=%d fd=%d)\n", fn, *fmt,
65 *len, *fd);
66 return 0;
67
68 err:
69 close(*fd);
70 return -1;
71 }
72
get_pmem(int * fd,void ** data,int sz)73 static int get_pmem(int *fd, void **data, int sz)
74 {
75 *fd = open("/dev/pmem", O_RDWR | O_NONBLOCK | O_SYNC);
76 if (*fd < 0) {
77 perror("cannot open /dev/pmem");
78 return -1;
79 }
80
81 sz = (sz + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
82 *data = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_SHARED, *fd, 0);
83 if (*data == MAP_FAILED) {
84 perror("pmem mmap");
85 goto err_pmem_mmap;
86 }
87
88 return 0;
89
90 err_pmem_mmap:
91 close(*fd);
92 return -1;
93 }
94
get_framebuffer(int * fd,char ** fb,int * width,int * height)95 static int get_framebuffer(int *fd, char **fb, int *width, int *height)
96 {
97 struct fb_fix_screeninfo fi;
98 void *bits;
99
100 *fd = open("/dev/graphics/fb0", O_RDWR);
101 if(*fd < 0) {
102 perror("cannot open fb0");
103 return -1;
104 }
105
106 if(ioctl(*fd, FBIOGET_FSCREENINFO, &fi) < 0) {
107 perror("failed to get fb0 info");
108 return -1;
109 }
110
111 if(ioctl(*fd, FBIOGET_VSCREENINFO, &vi) < 0) {
112 perror("failed to get fb0 info");
113 return -1;
114 }
115
116 bits = mmap(0, fi.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, *fd, 0);
117 if(bits == MAP_FAILED) {
118 perror("failed to mmap framebuffer");
119 return -1;
120 }
121
122 *width = vi.xres;
123 *height = vi.yres;
124 *fb = bits;
125 return 0;
126 }
127
set_active_framebuffer(int fd,unsigned n)128 static void set_active_framebuffer(int fd, unsigned n)
129 {
130
131 if(n > 1) return;
132 vi.yres_virtual = vi.yres * 2;
133 vi.yoffset = n * vi.yres;
134 if(ioctl(fd, FBIOPUT_VSCREENINFO, &vi) < 0) {
135 fprintf(stderr,"active fb swap failed!\n");
136 }
137 }
138
139 /* geometry: WxH+X+Y */
parse_geometry(char * geom,int * w,int * h,int * x,int * y)140 int parse_geometry(char *geom, int *w, int *h, int *x, int *y)
141 {
142 char *ptr;
143
144 *w = *h = 0;
145
146 if (!(ptr = strchr(geom, 'x')))
147 return -1;
148 *ptr = '\0';
149 *w = atoi(geom);
150 geom = ptr + 1;
151
152 ptr = strchr(geom, '+');
153 if (ptr)
154 *ptr = '\0';
155 *h = atoi(geom);
156 if (!ptr)
157 return 0;
158
159 geom = ptr + 1;
160
161 if (!x || !y || !(ptr = strchr(geom, '+')))
162 return -1;
163 *ptr = '\0';
164 *x = atoi(geom);
165 geom = ptr + 1;
166
167 *y = atoi(geom);
168
169 return 0;
170 }
171
main(int argc,const char * argv[])172 int main(int argc, const char *argv[])
173 {
174 int fb_fd, width, height;
175 char* fb;
176 struct mdp_blit_req_list *req_list;
177 struct mdp_blit_req *req;
178 int opt;
179 int srcw = 0, srch = 0, dstw = 0, dsth = 0;
180 int srcx = 0; int srcy = 0;
181 int dstx = 10; int dsty = 10;
182 int src_imgw = 0, src_imgh = 0, dst_imgw = 0, dst_imgh = 0;
183 int from;
184 int src_fmt;
185 int dst_fmt = MDP_RGB_565;
186 int src_fd = -1;
187 void *src_data;
188
189 req_list = malloc(sizeof(struct mdp_blit_req_list) +
190 sizeof(struct mdp_blit_req));
191 req_list->count = 1;
192 req = req_list->req;
193
194
195 while ((opt = getopt(argc, argv, "s:d:f:t:u:v:")) != -1) {
196 switch (opt) {
197 case 's':
198 if (parse_geometry(optarg, &srcw, &srch, &srcx, &srcy)) {
199 fprintf(stderr, "Can't parse source\n");
200 exit(-1);
201 }
202 printf("Got source: w=%d h=%d x=%d y=%d\n", srcw, srch, srcx, srcy);
203 break;
204
205 case 'd':
206 if (parse_geometry(optarg, &dstw, &dsth, &dstx, &dsty)) {
207 fprintf(stderr, "Can't parse dest\n");
208 exit(-1);
209 }
210 printf("Got dest: w=%d h=%d x=%d y=%d\n", dstw, dsth, dstx, dsty);
211 break;
212
213 case 'u':
214 if (parse_geometry(optarg, &src_imgw, &src_imgh, NULL, NULL)) {
215 fprintf(stderr, "Can't parse src image size\n");
216 exit(-1);
217 }
218 printf("Got src img sz: w=%d h=%d\n", src_imgw, src_imgh);
219 break;
220
221 case 'v':
222 if (parse_geometry(optarg, &dst_imgw, &dst_imgh, NULL, NULL)) {
223 fprintf(stderr, "Can't parse dst image size\n");
224 exit(-1);
225 }
226 printf("Got dst img sz: w=%d h=%d\n", dst_imgw, dst_imgh);
227 break;
228
229 case 'f':
230 {
231 int file_fd;
232 int file_len;
233 int bytes;
234 void *ptr;
235 if (open_file(optarg, &file_fd, &file_len, &src_fmt) < 0) {
236 fprintf(stderr, "Can't open source file\n");
237 exit(-1);
238 }
239
240 if (get_pmem(&src_fd, &src_data, file_len) < 0) {
241 close(file_fd);
242 exit(-1);
243 }
244
245 ptr = src_data;
246 while (file_len) {
247 bytes = read(file_fd, ptr, file_len);
248 if (bytes < 0) {
249 perror("Could not read data from file");
250 exit(-1);
251 }
252 file_len -= bytes;
253 ptr += bytes;
254 }
255 }
256 break;
257
258 case 't':
259 if (!strncmp(optarg, "yuv420", 6))
260 dst_fmt = MDP_Y_CBCR_H2V2;
261 #if 0
262 else if (!strncmp(optarg, "rgb565", 6))
263 dst_fmt = MDP_RGB_565;
264 #endif
265 break;
266
267 default:
268 fprintf(stderr, "Usage: %s -s source -d dest\n", argv[0]);
269 exit(-1);
270 }
271 }
272
273 if (get_framebuffer(&fb_fd, &fb, &width, &height)) {
274 printf("couldnt' get fb\n");
275 return -1;
276 }
277
278 set_active_framebuffer(fb_fd, 0);
279
280 if (!src_imgw || !src_imgh) {
281 src_imgw = width;
282 src_imgh = height;
283 }
284
285 if (!dst_imgw || !dst_imgh) {
286 dst_imgw = width;
287 dst_imgh = height;
288 }
289
290 if (src_fd < 0) {
291 src_fd = fb_fd;
292 src_fmt = MDP_RGB_565;
293 }
294
295 req->src.width = src_imgw;
296 req->src.height = src_imgh;
297 req->src.format = src_fmt;
298 req->src.offset = 0;
299 req->src.memory_id = src_fd;
300 req->src_rect.x = srcx;
301 req->src_rect.y = srcy;
302 req->src_rect.w = srcw;
303 req->src_rect.h = srch;
304
305 req->dst.width = dst_imgw;
306 req->dst.height = dst_imgh;
307 req->dst.format = dst_fmt;
308 req->dst.offset = 0;
309 req->dst.memory_id = fb_fd;
310 req->dst_rect.x = dstx;
311 req->dst_rect.y = dsty;
312 req->dst_rect.w = dstw;
313 req->dst_rect.h = dsth;
314 req->alpha = MDP_ALPHA_NOP;
315 req->transp_mask = MDP_TRANSP_NOP;
316 // req->flags = MDP_ROT_90;
317 req->flags = MDP_ROT_NOP;
318
319 if(ioctl(fb_fd, MSMFB_BLIT, req_list))
320 fprintf(stderr, "crap, failed blit\n");
321
322 printf("Done\n");
323 return 0;
324 }
325