【Android】从SurfaceFlinger中获取各layer图片(4)再回顾

从SurfaceFlinger中获取各layer图片的试验可以加深对GraphicBuffer和Layer的理解。

dumpsys SurfaceFlinger中打印的Slot信息中有GraphicBuffer的指针,可以帮助我们了解QueueBufferCore.

这个试验最初的出发点是根据图像的存储内存,再获取到这个数据,通过保存为图片的直观形式展现出来。

其实系统截图命令screencap也是类似的原理和实现(当然,我这里的保存图片就是从screencap里copy出来的方法)

frameworks/base/cmds/screencap/screencap.cpp

里面从surfaceflinger里面获取到了合成完成的GraphicBuffer,即屏幕截图画面

201    sp<GraphicBuffer> outBuffer;
202    status_t result = ScreenshotClient::capture(display, Rect(), 0 /* reqWidth */,
203            0 /* reqHeight */, INT32_MIN, INT32_MAX, /* all layers */ false, captureOrientation,
204            &outBuffer);
205    if (result != NO_ERROR) {
206        close(fd);
207        _exit(1);
208    }

再通过lock方法获取到存储地址base

  result = outBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, &base);

我们的试验中,显示出了GraphicBuffer的binder传送过程,

通过lockAsync方法获取到地址base

        status_t res = buf->lockAsync(0x00000003U | 0x00000030U,

                newDirtyRegion.bounds(), &vaddr, fenceFd);

               

有了地址base,就可以使用screencap里面的方法来保存为图片了

217    w = outBuffer->getWidth();
218    h = outBuffer->getHeight();
219    s = outBuffer->getStride();
220    f = outBuffer->getPixelFormat();
221    d = HAL_DATASPACE_UNKNOWN;
222    size = 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 final : 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            return size == 0 || ::write(fFd, buffer, size) > 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        write(fd, &w, 4);
245        write(fd, &h, 4);
246        write(fd, &f, 4);
247        write(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);

猜你喜欢

转载自blog.csdn.net/aaajj/article/details/105474888