blob: 9f17eaa2dad274779f07836e3134ef2a94e2f6fc [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "garnet/lib/machina/framebuffer_scanout.h"
#include <fcntl.h>
#include <unistd.h>
#include <zircon/device/display.h>
#include <zircon/process.h>
#include <zircon/syscalls.h>
#include "garnet/lib/machina/gpu_bitmap.h"
namespace machina {
// Create a scanout that owns a zircon framebuffer device.
zx_status_t FramebufferScanout::Create(const char* path,
fbl::unique_ptr<GpuScanout>* out) {
// Open framebuffer and get display info.
fbl::unique_fd fd(open(path, O_RDWR));
if (!fd) {
return ZX_ERR_NOT_FOUND;
}
ioctl_display_get_fb_t fb;
ssize_t ret = ioctl_display_get_fb(fd.get(), &fb);
if (ret != sizeof(fb)) {
return ret;
}
// Map framebuffer VMO.
uintptr_t fbo;
size_t size = fb.info.stride * fb.info.pixelsize * fb.info.height;
zx_status_t status =
zx_vmar_map(zx_vmar_root_self(), 0, fb.vmo, 0, size,
ZX_VM_FLAG_PERM_READ | ZX_VM_FLAG_PERM_WRITE, &fbo);
if (status != ZX_OK) {
return status;
}
GpuBitmap bitmap(fb.info.width, fb.info.height, fb.info.stride,
fb.info.format, reinterpret_cast<uint8_t*>(fbo));
fbl::unique_ptr<FramebufferScanout> scanout(
new FramebufferScanout(fbl::move(bitmap), fbl::move(fd)));
*out = fbl::move(scanout);
return ZX_OK;
}
FramebufferScanout::FramebufferScanout(GpuBitmap surface, fbl::unique_fd fd)
: GpuScanout(fbl::move(surface)), fd_(fbl::move(fd)) {}
void FramebufferScanout::InvalidateRegion(const GpuRect& rect) {
ioctl_display_region_t fb_region = {
.x = rect.x,
.y = rect.y,
.width = rect.width,
.height = rect.height,
};
ioctl_display_flush_fb_region(fd_.get(), &fb_region);
}
} // namespace machina