/*
* 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;
}