| /* |
| * Copyright (C) 2007 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <fcntl.h> |
| #include <stdio.h> |
| #include <sys/ioctl.h> |
| #include <sys/mman.h> |
| #include <sys/stat.h> |
| #include <sys/types.h> |
| |
| #include <linux/fb.h> |
| #include <linux/msm_mdp.h> |
| |
| static struct fb_var_screeninfo vi; |
| |
| static int open_file(char *name, int *fd, int *len, int *fmt) |
| { |
| struct stat stat; |
| char *type, *fn; |
| |
| type = name; |
| fn = strchr(name, ':'); |
| if (!fn) |
| return -1; |
| *(fn++) = '\0'; |
| |
| if (!strncmp(type, "yuv420", 6)) |
| *fmt = MDP_Y_CBCR_H2V2; |
| else if (!strncmp(type, "rgb565", 6)) |
| *fmt = MDP_RGB_565; |
| else { |
| fprintf(stderr, "Unsupported image type: %s\n", type); |
| return -1; |
| } |
| |
| *fd = open(fn, O_RDONLY); |
| if (*fd < 0) { |
| perror("cannot open file"); |
| return -1; |
| } |
| |
| if (fstat(*fd, &stat) < 0) { |
| perror("cannot fstat file"); |
| goto err; |
| } |
| |
| *len = stat.st_size; |
| |
| printf("Successfully opened file %s (fmt=%d len=%d fd=%d)\n", fn, *fmt, |
| *len, *fd); |
| return 0; |
| |
| err: |
| close(*fd); |
| return -1; |
| } |
| |
| static int get_pmem(int *fd, void **data, int sz) |
| { |
| *fd = open("/dev/pmem", O_RDWR | O_NONBLOCK | O_SYNC); |
| if (*fd < 0) { |
| perror("cannot open /dev/pmem"); |
| return -1; |
| } |
| |
| sz = (sz + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); |
| *data = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_SHARED, *fd, 0); |
| if (*data == MAP_FAILED) { |
| perror("pmem mmap"); |
| goto err_pmem_mmap; |
| } |
| |
| return 0; |
| |
| err_pmem_mmap: |
| close(*fd); |
| return -1; |
| } |
| |
| static int get_framebuffer(int *fd, char **fb, int *width, int *height) |
| { |
| struct fb_fix_screeninfo fi; |
| void *bits; |
| |
| *fd = open("/dev/graphics/fb0", O_RDWR); |
| if(*fd < 0) { |
| perror("cannot open fb0"); |
| return -1; |
| } |
| |
| if(ioctl(*fd, FBIOGET_FSCREENINFO, &fi) < 0) { |
| perror("failed to get fb0 info"); |
| return -1; |
| } |
| |
| if(ioctl(*fd, FBIOGET_VSCREENINFO, &vi) < 0) { |
| perror("failed to get fb0 info"); |
| return -1; |
| } |
| |
| bits = mmap(0, fi.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, *fd, 0); |
| if(bits == MAP_FAILED) { |
| perror("failed to mmap framebuffer"); |
| return -1; |
| } |
| |
| *width = vi.xres; |
| *height = vi.yres; |
| *fb = bits; |
| return 0; |
| } |
| |
| static void set_active_framebuffer(int fd, unsigned n) |
| { |
| |
| if(n > 1) return; |
| vi.yres_virtual = vi.yres * 2; |
| vi.yoffset = n * vi.yres; |
| if(ioctl(fd, FBIOPUT_VSCREENINFO, &vi) < 0) { |
| fprintf(stderr,"active fb swap failed!\n"); |
| } |
| } |
| |
| /* geometry: WxH+X+Y */ |
| int parse_geometry(char *geom, int *w, int *h, int *x, int *y) |
| { |
| char *ptr; |
| |
| *w = *h = 0; |
| |
| if (!(ptr = strchr(geom, 'x'))) |
| return -1; |
| *ptr = '\0'; |
| *w = atoi(geom); |
| geom = ptr + 1; |
| |
| ptr = strchr(geom, '+'); |
| if (ptr) |
| *ptr = '\0'; |
| *h = atoi(geom); |
| if (!ptr) |
| return 0; |
| |
| geom = ptr + 1; |
| |
| if (!x || !y || !(ptr = strchr(geom, '+'))) |
| return -1; |
| *ptr = '\0'; |
| *x = atoi(geom); |
| geom = ptr + 1; |
| |
| *y = atoi(geom); |
| |
| return 0; |
| } |
| |
| int main(int argc, const char *argv[]) |
| { |
| int fb_fd, width, height; |
| char* fb; |
| struct mdp_blit_req_list *req_list; |
| struct mdp_blit_req *req; |
| int opt; |
| int srcw = 0, srch = 0, dstw = 0, dsth = 0; |
| int srcx = 0; int srcy = 0; |
| int dstx = 10; int dsty = 10; |
| int src_imgw = 0, src_imgh = 0, dst_imgw = 0, dst_imgh = 0; |
| int from; |
| int src_fmt; |
| int dst_fmt = MDP_RGB_565; |
| int src_fd = -1; |
| void *src_data; |
| |
| req_list = malloc(sizeof(struct mdp_blit_req_list) + |
| sizeof(struct mdp_blit_req)); |
| req_list->count = 1; |
| req = req_list->req; |
| |
| |
| while ((opt = getopt(argc, argv, "s:d:f:t:u:v:")) != -1) { |
| switch (opt) { |
| case 's': |
| if (parse_geometry(optarg, &srcw, &srch, &srcx, &srcy)) { |
| fprintf(stderr, "Can't parse source\n"); |
| exit(-1); |
| } |
| printf("Got source: w=%d h=%d x=%d y=%d\n", srcw, srch, srcx, srcy); |
| break; |
| |
| case 'd': |
| if (parse_geometry(optarg, &dstw, &dsth, &dstx, &dsty)) { |
| fprintf(stderr, "Can't parse dest\n"); |
| exit(-1); |
| } |
| printf("Got dest: w=%d h=%d x=%d y=%d\n", dstw, dsth, dstx, dsty); |
| break; |
| |
| case 'u': |
| if (parse_geometry(optarg, &src_imgw, &src_imgh, NULL, NULL)) { |
| fprintf(stderr, "Can't parse src image size\n"); |
| exit(-1); |
| } |
| printf("Got src img sz: w=%d h=%d\n", src_imgw, src_imgh); |
| break; |
| |
| case 'v': |
| if (parse_geometry(optarg, &dst_imgw, &dst_imgh, NULL, NULL)) { |
| fprintf(stderr, "Can't parse dst image size\n"); |
| exit(-1); |
| } |
| printf("Got dst img sz: w=%d h=%d\n", dst_imgw, dst_imgh); |
| break; |
| |
| case 'f': |
| { |
| int file_fd; |
| int file_len; |
| int bytes; |
| void *ptr; |
| if (open_file(optarg, &file_fd, &file_len, &src_fmt) < 0) { |
| fprintf(stderr, "Can't open source file\n"); |
| exit(-1); |
| } |
| |
| if (get_pmem(&src_fd, &src_data, file_len) < 0) { |
| close(file_fd); |
| exit(-1); |
| } |
| |
| ptr = src_data; |
| while (file_len) { |
| bytes = read(file_fd, ptr, file_len); |
| if (bytes < 0) { |
| perror("Could not read data from file"); |
| exit(-1); |
| } |
| file_len -= bytes; |
| ptr += bytes; |
| } |
| } |
| break; |
| |
| case 't': |
| if (!strncmp(optarg, "yuv420", 6)) |
| dst_fmt = MDP_Y_CBCR_H2V2; |
| #if 0 |
| else if (!strncmp(optarg, "rgb565", 6)) |
| dst_fmt = MDP_RGB_565; |
| #endif |
| break; |
| |
| default: |
| fprintf(stderr, "Usage: %s -s source -d dest\n", argv[0]); |
| exit(-1); |
| } |
| } |
| |
| if (get_framebuffer(&fb_fd, &fb, &width, &height)) { |
| printf("couldnt' get fb\n"); |
| return -1; |
| } |
| |
| set_active_framebuffer(fb_fd, 0); |
| |
| if (!src_imgw || !src_imgh) { |
| src_imgw = width; |
| src_imgh = height; |
| } |
| |
| if (!dst_imgw || !dst_imgh) { |
| dst_imgw = width; |
| dst_imgh = height; |
| } |
| |
| if (src_fd < 0) { |
| src_fd = fb_fd; |
| src_fmt = MDP_RGB_565; |
| } |
| |
| req->src.width = src_imgw; |
| req->src.height = src_imgh; |
| req->src.format = src_fmt; |
| req->src.offset = 0; |
| req->src.memory_id = src_fd; |
| req->src_rect.x = srcx; |
| req->src_rect.y = srcy; |
| req->src_rect.w = srcw; |
| req->src_rect.h = srch; |
| |
| req->dst.width = dst_imgw; |
| req->dst.height = dst_imgh; |
| req->dst.format = dst_fmt; |
| req->dst.offset = 0; |
| req->dst.memory_id = fb_fd; |
| req->dst_rect.x = dstx; |
| req->dst_rect.y = dsty; |
| req->dst_rect.w = dstw; |
| req->dst_rect.h = dsth; |
| req->alpha = MDP_ALPHA_NOP; |
| req->transp_mask = MDP_TRANSP_NOP; |
| // req->flags = MDP_ROT_90; |
| req->flags = MDP_ROT_NOP; |
| |
| if(ioctl(fb_fd, MSMFB_BLIT, req_list)) |
| fprintf(stderr, "crap, failed blit\n"); |
| |
| printf("Done\n"); |
| return 0; |
| } |