最近在做一个android的新平台,涉及到了SurfaceFlinger的使用。又要在另外一个平台上实现一个抓屏的功能,被折磨的囧啊。最近终于能够闲下来整理一下这块的东西了。网上有很多讲解SurfaceFlinger的文章,但大部分都是原理分析,看的头大。下面是一个测试小例子,测试SurfaceFlinger的使用,并结合skia测试了软合成shotsceen的性能。
点击(此处)折叠或打开
- /**
- * =====================================================================================
- * Filename: surface.cpp
- * Created: 2012年03月24日 13时39分28秒
- * Author: louie
(),
- * Company: sunniwell.net
- * Description: surface test
- * =====================================================================================
- */
- #define LOG_TAG "SurfaceTest"
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/mman.h>
- #include <fcntl.h>
- #include <dirent.h>
- #include <unistd.h>
- #include <string.h>
- #include <linux/fb.h>
- #include <binder/IPCThreadState.h>
- #include <binder/ProcessState.h>
- #include <binder/IMemory.h>
- #include <binder/IPCThreadState.h>
- #include <binder/IServiceManager.h>
- #include <binder/MemoryHeapBase.h>
- #include <binder/MemoryBase.h>
- #include <binder/Binder.h>
- #include <utils/Log.h>
- #include <cutils/atomic.h>
- #include <cutils/properties.h>
- #include <utils/threads.h>
- #include <utils/Atomic.h>
- #include <utils/String16.h>
- #include <android_runtime/AndroidRuntime.h>
- #include <android_runtime/ActivityManager.h>
- #include <media/AudioTrack.h>
- #include <media/RobotWrapper.h>
- #include <surfaceflinger/Surface.h>
- #include <surfaceflinger/ISurface.h>
- #include <surfaceflinger/ISurfaceComposer.h>
- #include <surfaceflinger/SurfaceComposerClient.h>
- #include <ui/DisplayInfo.h>
- #include <SkTypeface.h>
- #include <SkTemplates.h>
- #include <SkRegion.h>
- #include <SkDevice.h>
- #include <SkRect.h>
- #include <SkCanvas.h>
- #include <SkBitmap.h>
- #include <SkStream.h>
- #include <SkImageDecoder.h>
- #include <SkImageEncoder.h>
- #include "hi_unf_disp.h"
- using namespace android;
- bool SkFileDecoder( SkBitmap* bitmap,
const char srcPath[],
int bits_per_pixel)
- {
- SkFILEStream stream(srcPath);
- if (!stream.isValid())
{
- LOGE("ERROR: bad filename <%s>\n", srcPath);
- return false;
- }
- stream.rewind();
- SkImageDecoder* codec
= SkImageDecoder::Factory(&stream);
- if (NULL
== codec)
{
- LOGE("ERROR: no codec found for <%s>\n", srcPath);
- return false;
- }
- SkBitmap::Config config;
- switch (bits_per_pixel)
- {
- case 32:
- config = SkBitmap::kARGB_8888_Config;
- break;
- case 16:
- config = SkBitmap::kRGB_565_Config;
- break;
- default:
- LOGE ("Warning: drawRect() not implemented for color depth %i\n",bits_per_pixel);
- break;
- }
- SkAutoTDelete<SkImageDecoder> ad(codec);
- stream.rewind();
- if (!codec->decode(&stream,
bitmap, config,
- SkImageDecoder::kDecodePixels_Mode))
{
- LOGE("ERROR: codec failed for <%s>\n", srcPath);
- return false;
- }
- return true;
- }
- int main(
)
- {
- sp<SurfaceComposerClient> surfaceclient;
- sp<SurfaceControl> surfaceControl;
- sp<Surface> surface;
- SkBitmap bitmap;
- Surface::SurfaceInfo info;
- DisplayInfo display;
- //surface 的名字以pid开头
- LOGE("[%s %s %d] <pid :%d>\n", __FUNCTION__, __FILE__, __LINE__,
getpid());
- surfaceclient = new SurfaceComposerClient();
- surfaceclient->getDisplayInfo(0,
&display);
- LOGE("display < %d %d>", display.w, display.h);
- surfaceControl = surfaceclient->createSurface(getpid(),
0, display.w, display.h, PIXEL_FORMAT_RGBA_8888);
- //composer parameters必须在一对open/close transaction之间当close调用时,
- //参数被提交给服务端参数值的改变都存放在/frameworks/base/include/private/surfaceflinger/LayerState.h:layer_state_t中,
- //当调用closeTransaction时,结构体才会被传送到服务端。这样可以明显简化C/S接口、加快C/S通信速度。
- surfaceclient->openTransaction();
- surfaceControl->setLayer(1000);
- surfaceControl->setSize(display.w, display.h);
- surfaceControl->setPosition(1, 1);
- surfaceControl->show(
);
- surfaceclient->closeTransaction();
- surface = surfaceControl->getSurface();
- surface->lock(&info);
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, fb_w,
fb_h);
- bitmap.setIsOpaque(true);
- bitmap.setPixels(info.bits);
- SkCanvas* canvas
= new SkCanvas(bitmap);
- surface->unlockAndPost();
- int A = 150, R
= 128, G
= 128, B = 128
;
- while( A
< 256)
- {
- LOGE("Surface <%d %d %d %d>\n", A, R, G,
B);
- surface->lock(&info);
- /*bitmap 的buffer 被重置,surface 为双缓冲,前后buffer被替换 因此每次都要重新设置bitmap的内存*/
- bitmap.setPixels(info.bits);
- bitmap.eraseARGB(A, R, G, B);
- surface->unlockAndPost();
- A += 20;
- sleep(3);
- }
- SkPaint paint;
- int color
= 0xff00ff77;
- paint.setARGB(color>>24
& 0xff, color>>16
& 0xff, color>>8
& 0xff, color
& 0xff);
- surface->lock(&info);
- bitmap.setPixels(info.bits);
- bitmap.eraseARGB(0, 0, 0, 0);
- canvas->setBitmapDevice(bitmap);
- canvas->drawLine(100, 100, 500, 500,
paint);
- surface->unlockAndPost();
- sleep(3);
- surface->lock(&info);
- bitmap.setPixels(info.bits);
- bitmap.eraseARGB(0, 0, 0, 0);
- SkRect rect;
- rect.fLeft
= 200;
- rect.fTop
= 200;
- rect.fRight
= 400;
- rect.fBottom
= 400;
- color = 0xffff0077;
- paint.setARGB(color>>24
& 0xff, color>>16
& 0xff, color>>8
& 0xff, color
& 0xff);
- canvas->setBitmapDevice(bitmap);
- canvas->drawRect(rect, paint);
- surface->unlockAndPost();
- sleep(3);
- surface->lock(&info);
- bitmap.setPixels(info.bits);
- bitmap.eraseARGB(0, 0, 0, 0);
- color = 0xff0f00ff;
- paint.setARGB(color>>24
& 0xff, color>>16
& 0xff, color>>8
& 0xff, color
& 0xff);
- canvas->setBitmapDevice(bitmap);
- canvas->drawCircle(640, 260, 100, paint);
- surface->unlockAndPost();
- sleep(3);
- surface->lock(&info);
- bitmap.setIsOpaque(false);
- bitmap.setPixels(info.bits);
- bitmap.eraseColor(0);
- canvas->setBitmapDevice(bitmap);
- /* 在这里原来使用的是bitmap,但是没有显示出来,仔细分析了一下,觉得原因在图片解码的时候,
- * bitmap内存被重新分配。可以看一下skia的源码。在这里画出的2.png的位置有点问题,但是jpg的
- * 图片的位置时正确的,没找到原因。
- */
- SkBitmap Ibitmap;
- SkFileDecoder(&Ibitmap,
"/swcommon/1.png", 32);
- SkRect dst{0, 0, bitmap.width(),
bitmap.height()};
- SkIRect src{0, 0, Ibitmap.width(),
Ibitmap.height()};
- canvas->drawBitmapRect(Ibitmap,
&src, dst);
- Ibitmap.eraseColor(0);
- SkFileDecoder(&Ibitmap,
"/swcommon/2.png", 32);
- SkRect dst2{200, 200, 700, 500};
- canvas->drawBitmapRect(Ibitmap,
&src, dst2);
- surface->unlockAndPost();
- sleep(3);
- surface->lock(&info);
- bitmap.setPixels(info.bits);
- bitmap.eraseColor(0);
- canvas->setBitmapDevice(bitmap);
- Ibitmap.eraseColor(0);
- SkFileDecoder(&Ibitmap,
"/swcommon/1.jpg", 32);
- SkIRect srcj{0, 0, Ibitmap.width(),
Ibitmap.height()};
- canvas->drawBitmapRect(Ibitmap,
&srcj, dst);
- Ibitmap.eraseColor(0);
- SkFileDecoder(&Ibitmap,
"/swcommon/2.jpg", 32);
- SkRect dst4{200, 200, 700, 500};
- canvas->drawBitmapRect(Ibitmap,
&src, dst4);
- SkImageEncoder::EncodeFile("/swcommon/screenshot.jpg", bitmap,
SkImageEncoder::kJPEG_Type, 100);
- surface->unlockAndPost();
- sleep(3);
- LOGE("[%s %s %d] END !\n", __FUNCTION__, __FILE__, __LINE__);
- return 0;
- }