【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);

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章