SurfaceFlingerから各レイヤーの画像を取得する実験により、GraphicBufferとLayerの理解を深めることができます。
dumpsys SurfaceFlingerに出力されるスロット情報にGraphicBufferポインターがあり、これはQueueBufferCoreを理解するのに役立ちます。
この実験の最初の出発点は、画像のストレージメモリに基づいてこのデータを取得し、画像として保存された直感的な形式で表示することです。
実際、システムのスクリーンショットコマンドscreencapも原理と実装が似ています(もちろん、ここで写真を保存する方法はscreencapからコピーすることです)
フレームワーク/ベース/ CMDS / SCREENCAP / screencap.cpp
内部では、合成されたGraphicBufferは、スクリーンショット画面であるsurfaceflingerから取得されます。
201 sp < GraphicBuffer >outBuffer ; 202 status_t 結果= ScreenshotClient :: Capture(display、Rect()、0 / * reqWidth * /、 203 0 / * reqHeight * /、INT32_MIN、INT32_MAX、/ *すべてのレイヤー* / false、captureOrientation、 204 &outBuffer); 205 if(result!= NO_ERROR){ 206 close(fd); 207 _exit(1); 208 }
次に、ロック方式でストレージアドレスベースを取得します
結果= outBuffer- >ロック(GraphicBuffer :: USAGE_SW_READ_OFTEN、&base);
私たちの実験では、GraphicBufferのバインダー転送プロセスが示されています。
lockAsyncメソッドを介してアドレスベースを取得します
status_t res = buf-> lockAsync(0x00000003U | 0x00000030U、
newDirtyRegion.bounds()、&vaddr、fenceFd);
アドレスベースを使用すると、screencapのメソッドを使用して画像として保存できます
217 w = outBuffer- > getWidth(); 218 h = outBuffer- > getHeight(); 219 s = outBuffer- > getStride(); 220 f = outBuffer- > getPixelFormat(); 221 d = HAL_DATASPACE_UNKNOWN ; 222 サイズ= s * h * bytesPerPixel(f); 223 224 if(png){ 225 const SkImageInfo info = 226 SkImageInfo :: Make(w、h、flinger2skia(f)、kPremul_SkAlphaType、dataSpaceToColorSpace(d)); 227 SkPixmap pixmap(info、base、s * bytesPerPixel(f)); 228 struct FDWStream 最終:public SkWStream { 229 size_t fBytesWritten = 0; 230 int fFd ; 231 FDWStream(int f):fFd(f){} 232 size_t bytesWritten()const override { return fBytesWritten ; } 233 bool write(const void * buffer、size_t size)override { 234 fBytesWritten + = size ; 235 リターン サイズ== 0 || ::書き込み(fFd、バッファ、サイズ)> 0; 236 } 237 } fdStream(fd); 238 (void)SkEncodeImage(&fdStream、pixmap、SkEncodedImageFormat :: kPNG、100); 239 if(fn!= NULL){ 240 notifyMediaScanner(fn); 241 } 242 } else { 243 uint32_t c = dataSpaceToInt(d); 244 書き込み(fd、&w、4); 245 書き込み(fd、&h、4); 246 書き込み(fd、&f、4); 247 書き込み(fd、&c、4); 248 size_t Bpp = bytesPerPixel(f); 249 for(size_t y = 0; y <h; y ++){ 250 write(fd、base、w * Bpp); 251 base =(void *)((char *)base + s * Bpp); 252 } 253 } 254 close(fd);