1c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood/* 2c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood * Copyright (C) 2010 The Android Open Source Project 3c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood * 4c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood * Licensed under the Apache License, Version 2.0 (the "License"); 5c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood * you may not use this file except in compliance with the License. 6c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood * You may obtain a copy of the License at 7c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood * 8c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood * http://www.apache.org/licenses/LICENSE-2.0 9c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood * 10c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood * Unless required by applicable law or agreed to in writing, software 11c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood * distributed under the License is distributed on an "AS IS" BASIS, 12c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood * See the License for the specific language governing permissions and 14c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood * limitations under the License. 15c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood */ 16c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 17c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood#include <errno.h> 18c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood#include <unistd.h> 19c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood#include <stdio.h> 20c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood#include <fcntl.h> 21c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 22c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood#include <linux/fb.h> 23c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood#include <sys/ioctl.h> 24c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood#include <sys/mman.h> 25c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 260678a8c250832a5549703f533f6afea9d8729e43Mathias Agopian#include <binder/ProcessState.h> 270678a8c250832a5549703f533f6afea9d8729e43Mathias Agopian 28c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood#include <gui/SurfaceComposerClient.h> 29c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood#include <gui/ISurfaceComposer.h> 30c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 310137fb8937e69ed41cff3bf8cb0c1fea43daa3b5Mathias Agopian#include <ui/PixelFormat.h> 320137fb8937e69ed41cff3bf8cb0c1fea43daa3b5Mathias Agopian 33c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood#include <SkImageEncoder.h> 34c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood#include <SkBitmap.h> 35c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood#include <SkData.h> 36c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood#include <SkStream.h> 37c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 38c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwoodusing namespace android; 39c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 40c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwoodstatic uint32_t DEFAULT_DISPLAY_ID = ISurfaceComposer::eDisplayIdMain; 41c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 42c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwoodstatic void usage(const char* pname) 43c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood{ 44c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood fprintf(stderr, 45c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood "usage: %s [-hp] [-d display-id] [FILENAME]\n" 46c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood " -h: this message\n" 47c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood " -p: save the file as a png.\n" 48c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood " -d: specify the display id to capture, default %d.\n" 49c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood "If FILENAME ends with .png it will be saved as a png.\n" 50c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood "If FILENAME is not given, the results will be printed to stdout.\n", 51c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood pname, DEFAULT_DISPLAY_ID 52c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood ); 53c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood} 54c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 55b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reedstatic SkColorType flinger2skia(PixelFormat f) 56c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood{ 57c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood switch (f) { 58c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood case PIXEL_FORMAT_RGB_565: 59b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed return kRGB_565_SkColorType; 60c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood default: 61b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed return kN32_SkColorType; 62c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } 63c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood} 64c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 65c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwoodstatic status_t vinfoToPixelFormat(const fb_var_screeninfo& vinfo, 66c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood uint32_t* bytespp, uint32_t* f) 67c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood{ 68c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 69c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood switch (vinfo.bits_per_pixel) { 70c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood case 16: 71c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood *f = PIXEL_FORMAT_RGB_565; 72c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood *bytespp = 2; 73c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood break; 74c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood case 24: 75c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood *f = PIXEL_FORMAT_RGB_888; 76c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood *bytespp = 3; 77c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood break; 78c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood case 32: 79c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood // TODO: do better decoding of vinfo here 80c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood *f = PIXEL_FORMAT_RGBX_8888; 81c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood *bytespp = 4; 82c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood break; 83c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood default: 84c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood return BAD_VALUE; 85c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } 86c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood return NO_ERROR; 87c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood} 88c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 89c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwoodint main(int argc, char** argv) 90c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood{ 910678a8c250832a5549703f533f6afea9d8729e43Mathias Agopian ProcessState::self()->startThreadPool(); 920678a8c250832a5549703f533f6afea9d8729e43Mathias Agopian 93c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood const char* pname = argv[0]; 94c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood bool png = false; 95c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood int32_t displayId = DEFAULT_DISPLAY_ID; 96c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood int c; 97c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood while ((c = getopt(argc, argv, "phd:")) != -1) { 98c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood switch (c) { 99c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood case 'p': 100c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood png = true; 101c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood break; 102c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood case 'd': 103c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood displayId = atoi(optarg); 104c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood break; 105c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood case '?': 106c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood case 'h': 107c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood usage(pname); 108c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood return 1; 109c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } 110c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } 111c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood argc -= optind; 112c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood argv += optind; 113c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 114c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood int fd = -1; 115c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood if (argc == 0) { 116c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood fd = dup(STDOUT_FILENO); 117c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } else if (argc == 1) { 118c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood const char* fn = argv[0]; 119c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0664); 120c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood if (fd == -1) { 121c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood fprintf(stderr, "Error opening file: %s (%s)\n", fn, strerror(errno)); 122c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood return 1; 123c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } 124c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood const int len = strlen(fn); 125c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood if (len >= 4 && 0 == strcmp(fn+len-4, ".png")) { 126c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood png = true; 127c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } 128c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } 129c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 130c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood if (fd == -1) { 131c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood usage(pname); 132c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood return 1; 133c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } 134c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 135c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood void const* mapbase = MAP_FAILED; 136c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood ssize_t mapsize = -1; 137c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 138c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood void const* base = 0; 1390137fb8937e69ed41cff3bf8cb0c1fea43daa3b5Mathias Agopian uint32_t w, s, h, f; 140c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood size_t size = 0; 141c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 142c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood ScreenshotClient screenshot; 143c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood sp<IBinder> display = SurfaceComposerClient::getBuiltInDisplay(displayId); 1449890e341bf9d565309cd7db5e6c4194c66c0a1d8Dan Stoza if (display != NULL && screenshot.update(display, Rect(), false) == NO_ERROR) { 145c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood base = screenshot.getPixels(); 146c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood w = screenshot.getWidth(); 147c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood h = screenshot.getHeight(); 1480137fb8937e69ed41cff3bf8cb0c1fea43daa3b5Mathias Agopian s = screenshot.getStride(); 149c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood f = screenshot.getFormat(); 150c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood size = screenshot.getSize(); 151c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } else { 152c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood const char* fbpath = "/dev/graphics/fb0"; 153c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood int fb = open(fbpath, O_RDONLY); 154c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood if (fb >= 0) { 155c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood struct fb_var_screeninfo vinfo; 156c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood if (ioctl(fb, FBIOGET_VSCREENINFO, &vinfo) == 0) { 157c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood uint32_t bytespp; 158c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood if (vinfoToPixelFormat(vinfo, &bytespp, &f) == NO_ERROR) { 159c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood size_t offset = (vinfo.xoffset + vinfo.yoffset*vinfo.xres) * bytespp; 160c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood w = vinfo.xres; 161c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood h = vinfo.yres; 1620137fb8937e69ed41cff3bf8cb0c1fea43daa3b5Mathias Agopian s = vinfo.xres; 163c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood size = w*h*bytespp; 164c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood mapsize = offset + size; 165c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood mapbase = mmap(0, mapsize, PROT_READ, MAP_PRIVATE, fb, 0); 166c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood if (mapbase != MAP_FAILED) { 167c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood base = (void const *)((char const *)mapbase + offset); 168c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } 169c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } 170c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } 171c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood close(fb); 172c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } 173c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } 174c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 175c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood if (base) { 176c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood if (png) { 177b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed const SkImageInfo info = SkImageInfo::Make(w, h, flinger2skia(f), 178b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed kPremul_SkAlphaType); 179c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood SkBitmap b; 180b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed b.installPixels(info, const_cast<void*>(base), s*bytesPerPixel(f)); 181c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood SkDynamicMemoryWStream stream; 182c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood SkImageEncoder::EncodeStream(&stream, b, 183c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood SkImageEncoder::kPNG_Type, SkImageEncoder::kDefaultQuality); 184c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood SkData* streamData = stream.copyToData(); 185c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood write(fd, streamData->data(), streamData->size()); 186c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood streamData->unref(); 187c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } else { 188c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood write(fd, &w, 4); 189c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood write(fd, &h, 4); 190c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood write(fd, &f, 4); 1910137fb8937e69ed41cff3bf8cb0c1fea43daa3b5Mathias Agopian size_t Bpp = bytesPerPixel(f); 1920137fb8937e69ed41cff3bf8cb0c1fea43daa3b5Mathias Agopian for (size_t y=0 ; y<h ; y++) { 1930137fb8937e69ed41cff3bf8cb0c1fea43daa3b5Mathias Agopian write(fd, base, w*Bpp); 1940137fb8937e69ed41cff3bf8cb0c1fea43daa3b5Mathias Agopian base = (void *)((char *)base + s*Bpp); 1950137fb8937e69ed41cff3bf8cb0c1fea43daa3b5Mathias Agopian } 196c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } 197c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } 198c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood close(fd); 199c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood if (mapbase != MAP_FAILED) { 200c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood munmap((void *)mapbase, mapsize); 201c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } 202c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood return 0; 203c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood} 204