188a5df93668cb2079d10fd55de25a333f5f43842Mathias Agopian/* 288a5df93668cb2079d10fd55de25a333f5f43842Mathias Agopian * Copyright (C) 2010 The Android Open Source Project 388a5df93668cb2079d10fd55de25a333f5f43842Mathias Agopian * 488a5df93668cb2079d10fd55de25a333f5f43842Mathias Agopian * Licensed under the Apache License, Version 2.0 (the "License"); 588a5df93668cb2079d10fd55de25a333f5f43842Mathias Agopian * you may not use this file except in compliance with the License. 688a5df93668cb2079d10fd55de25a333f5f43842Mathias Agopian * You may obtain a copy of the License at 788a5df93668cb2079d10fd55de25a333f5f43842Mathias Agopian * 888a5df93668cb2079d10fd55de25a333f5f43842Mathias Agopian * http://www.apache.org/licenses/LICENSE-2.0 988a5df93668cb2079d10fd55de25a333f5f43842Mathias Agopian * 1088a5df93668cb2079d10fd55de25a333f5f43842Mathias Agopian * Unless required by applicable law or agreed to in writing, software 1188a5df93668cb2079d10fd55de25a333f5f43842Mathias Agopian * distributed under the License is distributed on an "AS IS" BASIS, 1288a5df93668cb2079d10fd55de25a333f5f43842Mathias Agopian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1388a5df93668cb2079d10fd55de25a333f5f43842Mathias Agopian * See the License for the specific language governing permissions and 1488a5df93668cb2079d10fd55de25a333f5f43842Mathias Agopian * limitations under the License. 1588a5df93668cb2079d10fd55de25a333f5f43842Mathias Agopian */ 1688a5df93668cb2079d10fd55de25a333f5f43842Mathias Agopian 175cff0630eb970faf1682095ca434b204628b4d62Joe Onorato#include <errno.h> 1888a5df93668cb2079d10fd55de25a333f5f43842Mathias Agopian#include <unistd.h> 195cff0630eb970faf1682095ca434b204628b4d62Joe Onorato#include <stdio.h> 2088a5df93668cb2079d10fd55de25a333f5f43842Mathias Agopian#include <fcntl.h> 2188a5df93668cb2079d10fd55de25a333f5f43842Mathias Agopian 229afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian#include <linux/fb.h> 239afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian#include <sys/ioctl.h> 249afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian#include <sys/mman.h> 259afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian 2688a5df93668cb2079d10fd55de25a333f5f43842Mathias Agopian#include <binder/IMemory.h> 278335f1ccccedb6655d96d9d5b697a7f0938235ddMathias Agopian#include <gui/SurfaceComposerClient.h> 280b722fe9ce98d97dbcb6fefd170b85ab7037e528Jeff Brown#include <gui/ISurfaceComposer.h> 2988a5df93668cb2079d10fd55de25a333f5f43842Mathias Agopian 305cff0630eb970faf1682095ca434b204628b4d62Joe Onorato#include <SkImageEncoder.h> 315cff0630eb970faf1682095ca434b204628b4d62Joe Onorato#include <SkBitmap.h> 32889a3fa6ab9710104af60db5f73d69f253ddf254Derek Sollenberger#include <SkData.h> 335cff0630eb970faf1682095ca434b204628b4d62Joe Onorato#include <SkStream.h> 345cff0630eb970faf1682095ca434b204628b4d62Joe Onorato 3588a5df93668cb2079d10fd55de25a333f5f43842Mathias Agopianusing namespace android; 3688a5df93668cb2079d10fd55de25a333f5f43842Mathias Agopian 370b722fe9ce98d97dbcb6fefd170b85ab7037e528Jeff Brownstatic uint32_t DEFAULT_DISPLAY_ID = ISurfaceComposer::eDisplayIdMain; 380b722fe9ce98d97dbcb6fefd170b85ab7037e528Jeff Brown 399afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopianstatic void usage(const char* pname) 405cff0630eb970faf1682095ca434b204628b4d62Joe Onorato{ 415cff0630eb970faf1682095ca434b204628b4d62Joe Onorato fprintf(stderr, 420b722fe9ce98d97dbcb6fefd170b85ab7037e528Jeff Brown "usage: %s [-hp] [-d display-id] [FILENAME]\n" 435cff0630eb970faf1682095ca434b204628b4d62Joe Onorato " -h: this message\n" 445cff0630eb970faf1682095ca434b204628b4d62Joe Onorato " -p: save the file as a png.\n" 450b722fe9ce98d97dbcb6fefd170b85ab7037e528Jeff Brown " -d: specify the display id to capture, default %d.\n" 465cff0630eb970faf1682095ca434b204628b4d62Joe Onorato "If FILENAME ends with .png it will be saved as a png.\n" 479afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian "If FILENAME is not given, the results will be printed to stdout.\n", 480b722fe9ce98d97dbcb6fefd170b85ab7037e528Jeff Brown pname, DEFAULT_DISPLAY_ID 495cff0630eb970faf1682095ca434b204628b4d62Joe Onorato ); 505cff0630eb970faf1682095ca434b204628b4d62Joe Onorato} 515cff0630eb970faf1682095ca434b204628b4d62Joe Onorato 525cff0630eb970faf1682095ca434b204628b4d62Joe Onoratostatic SkBitmap::Config flinger2skia(PixelFormat f) 535cff0630eb970faf1682095ca434b204628b4d62Joe Onorato{ 545cff0630eb970faf1682095ca434b204628b4d62Joe Onorato switch (f) { 555cff0630eb970faf1682095ca434b204628b4d62Joe Onorato case PIXEL_FORMAT_A_8: 565cff0630eb970faf1682095ca434b204628b4d62Joe Onorato return SkBitmap::kA8_Config; 575cff0630eb970faf1682095ca434b204628b4d62Joe Onorato case PIXEL_FORMAT_RGB_565: 585cff0630eb970faf1682095ca434b204628b4d62Joe Onorato return SkBitmap::kRGB_565_Config; 595cff0630eb970faf1682095ca434b204628b4d62Joe Onorato case PIXEL_FORMAT_RGBA_4444: 605cff0630eb970faf1682095ca434b204628b4d62Joe Onorato return SkBitmap::kARGB_4444_Config; 615cff0630eb970faf1682095ca434b204628b4d62Joe Onorato default: 625cff0630eb970faf1682095ca434b204628b4d62Joe Onorato return SkBitmap::kARGB_8888_Config; 635cff0630eb970faf1682095ca434b204628b4d62Joe Onorato } 645cff0630eb970faf1682095ca434b204628b4d62Joe Onorato} 655cff0630eb970faf1682095ca434b204628b4d62Joe Onorato 669afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopianstatic status_t vinfoToPixelFormat(const fb_var_screeninfo& vinfo, 679afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian uint32_t* bytespp, uint32_t* f) 689afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian{ 699afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian 709afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian switch (vinfo.bits_per_pixel) { 719afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian case 16: 729afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian *f = PIXEL_FORMAT_RGB_565; 739afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian *bytespp = 2; 749afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian break; 759afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian case 24: 769afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian *f = PIXEL_FORMAT_RGB_888; 779afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian *bytespp = 3; 789afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian break; 799afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian case 32: 809afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian // TODO: do better decoding of vinfo here 819afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian *f = PIXEL_FORMAT_RGBX_8888; 829afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian *bytespp = 4; 839afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian break; 849afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian default: 859afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian return BAD_VALUE; 869afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian } 879afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian return NO_ERROR; 889afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian} 899afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian 9088a5df93668cb2079d10fd55de25a333f5f43842Mathias Agopianint main(int argc, char** argv) 9188a5df93668cb2079d10fd55de25a333f5f43842Mathias Agopian{ 929afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian const char* pname = argv[0]; 935cff0630eb970faf1682095ca434b204628b4d62Joe Onorato bool png = false; 940b722fe9ce98d97dbcb6fefd170b85ab7037e528Jeff Brown int32_t displayId = DEFAULT_DISPLAY_ID; 955cff0630eb970faf1682095ca434b204628b4d62Joe Onorato int c; 960b722fe9ce98d97dbcb6fefd170b85ab7037e528Jeff Brown while ((c = getopt(argc, argv, "phd:")) != -1) { 975cff0630eb970faf1682095ca434b204628b4d62Joe Onorato switch (c) { 985cff0630eb970faf1682095ca434b204628b4d62Joe Onorato case 'p': 995cff0630eb970faf1682095ca434b204628b4d62Joe Onorato png = true; 1005cff0630eb970faf1682095ca434b204628b4d62Joe Onorato break; 1010b722fe9ce98d97dbcb6fefd170b85ab7037e528Jeff Brown case 'd': 1020b722fe9ce98d97dbcb6fefd170b85ab7037e528Jeff Brown displayId = atoi(optarg); 1030b722fe9ce98d97dbcb6fefd170b85ab7037e528Jeff Brown break; 1045cff0630eb970faf1682095ca434b204628b4d62Joe Onorato case '?': 1055cff0630eb970faf1682095ca434b204628b4d62Joe Onorato case 'h': 1069afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian usage(pname); 1075cff0630eb970faf1682095ca434b204628b4d62Joe Onorato return 1; 1085cff0630eb970faf1682095ca434b204628b4d62Joe Onorato } 1095cff0630eb970faf1682095ca434b204628b4d62Joe Onorato } 1105cff0630eb970faf1682095ca434b204628b4d62Joe Onorato argc -= optind; 1115cff0630eb970faf1682095ca434b204628b4d62Joe Onorato argv += optind; 1125cff0630eb970faf1682095ca434b204628b4d62Joe Onorato 1135cff0630eb970faf1682095ca434b204628b4d62Joe Onorato int fd = -1; 1145cff0630eb970faf1682095ca434b204628b4d62Joe Onorato if (argc == 0) { 1155cff0630eb970faf1682095ca434b204628b4d62Joe Onorato fd = dup(STDOUT_FILENO); 1165cff0630eb970faf1682095ca434b204628b4d62Joe Onorato } else if (argc == 1) { 1175cff0630eb970faf1682095ca434b204628b4d62Joe Onorato const char* fn = argv[0]; 1185cff0630eb970faf1682095ca434b204628b4d62Joe Onorato fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0664); 1195cff0630eb970faf1682095ca434b204628b4d62Joe Onorato if (fd == -1) { 1209afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian fprintf(stderr, "Error opening file: %s (%s)\n", fn, strerror(errno)); 1215cff0630eb970faf1682095ca434b204628b4d62Joe Onorato return 1; 1225cff0630eb970faf1682095ca434b204628b4d62Joe Onorato } 1235cff0630eb970faf1682095ca434b204628b4d62Joe Onorato const int len = strlen(fn); 1245cff0630eb970faf1682095ca434b204628b4d62Joe Onorato if (len >= 4 && 0 == strcmp(fn+len-4, ".png")) { 1255cff0630eb970faf1682095ca434b204628b4d62Joe Onorato png = true; 1265cff0630eb970faf1682095ca434b204628b4d62Joe Onorato } 1275cff0630eb970faf1682095ca434b204628b4d62Joe Onorato } 1285cff0630eb970faf1682095ca434b204628b4d62Joe Onorato 1295cff0630eb970faf1682095ca434b204628b4d62Joe Onorato if (fd == -1) { 1309afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian usage(pname); 1315cff0630eb970faf1682095ca434b204628b4d62Joe Onorato return 1; 1325cff0630eb970faf1682095ca434b204628b4d62Joe Onorato } 1335cff0630eb970faf1682095ca434b204628b4d62Joe Onorato 1349afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian void const* mapbase = MAP_FAILED; 1359afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian ssize_t mapsize = -1; 13688a5df93668cb2079d10fd55de25a333f5f43842Mathias Agopian 1379afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian void const* base = 0; 1389afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian uint32_t w, h, f; 1399afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian size_t size = 0; 1405cff0630eb970faf1682095ca434b204628b4d62Joe Onorato 1419afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian ScreenshotClient screenshot; 1420b722fe9ce98d97dbcb6fefd170b85ab7037e528Jeff Brown sp<IBinder> display = SurfaceComposerClient::getBuiltInDisplay(displayId); 1430b722fe9ce98d97dbcb6fefd170b85ab7037e528Jeff Brown if (display != NULL && screenshot.update(display) == NO_ERROR) { 1449afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian base = screenshot.getPixels(); 1459afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian w = screenshot.getWidth(); 1469afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian h = screenshot.getHeight(); 1479afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian f = screenshot.getFormat(); 1489afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian size = screenshot.getSize(); 1495cff0630eb970faf1682095ca434b204628b4d62Joe Onorato } else { 1509afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian const char* fbpath = "/dev/graphics/fb0"; 1519afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian int fb = open(fbpath, O_RDONLY); 1529afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian if (fb >= 0) { 1539afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian struct fb_var_screeninfo vinfo; 1549afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian if (ioctl(fb, FBIOGET_VSCREENINFO, &vinfo) == 0) { 1559afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian uint32_t bytespp; 1569afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian if (vinfoToPixelFormat(vinfo, &bytespp, &f) == NO_ERROR) { 1579afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian size_t offset = (vinfo.xoffset + vinfo.yoffset*vinfo.xres) * bytespp; 1589afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian w = vinfo.xres; 1599afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian h = vinfo.yres; 1609afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian size = w*h*bytespp; 1619afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian mapsize = offset + size; 1629afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian mapbase = mmap(0, mapsize, PROT_READ, MAP_PRIVATE, fb, 0); 1639afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian if (mapbase != MAP_FAILED) { 1649afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian base = (void const *)((char const *)mapbase + offset); 1659afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian } 1669afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian } 1679afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian } 1689afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian close(fb); 1699afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian } 1709afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian } 1719afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian 1729afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian if (base) { 1739afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian if (png) { 1749afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian SkBitmap b; 1759afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian b.setConfig(flinger2skia(f), w, h); 1769afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian b.setPixels((void*)base); 1779afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian SkDynamicMemoryWStream stream; 1789afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian SkImageEncoder::EncodeStream(&stream, b, 1799afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian SkImageEncoder::kPNG_Type, SkImageEncoder::kDefaultQuality); 180889a3fa6ab9710104af60db5f73d69f253ddf254Derek Sollenberger SkData* streamData = stream.copyToData(); 181889a3fa6ab9710104af60db5f73d69f253ddf254Derek Sollenberger write(fd, streamData->data(), streamData->size()); 182889a3fa6ab9710104af60db5f73d69f253ddf254Derek Sollenberger streamData->unref(); 1839afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian } else { 1849afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian write(fd, &w, 4); 1859afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian write(fd, &h, 4); 1869afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian write(fd, &f, 4); 1879afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian write(fd, base, size); 1889afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian } 1895cff0630eb970faf1682095ca434b204628b4d62Joe Onorato } 19088a5df93668cb2079d10fd55de25a333f5f43842Mathias Agopian close(fd); 1919afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian if (mapbase != MAP_FAILED) { 1929afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian munmap((void *)mapbase, mapsize); 1939afc7b02facf4918d3033ebb4548b76a59b1373cMathias Agopian } 19488a5df93668cb2079d10fd55de25a333f5f43842Mathias Agopian return 0; 19588a5df93668cb2079d10fd55de25a333f5f43842Mathias Agopian} 196