Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 35 additions & 2 deletions base/cvd/cuttlefish/host/libs/wayland/wayland_dmabuf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
#include <wayland-server-core.h>
#include <wayland-server-protocol.h>

#include "cuttlefish/host/libs/wayland/wayland_utils.h"

namespace wayland {
namespace {

Expand Down Expand Up @@ -63,6 +65,19 @@ void linux_buffer_params_add(wl_client*,
<< " stride=" << stride
<< " mod_hi=" << modifier_hi
<< " mod_lo=" << modifier_lo;

DmabufParams* dmabuf_params = GetUserData<DmabufParams>(params);

DmabufPlane dma_plane = {
.fd = android::base::unique_fd(fd),
.plane = plane,
.offset = offset,
.stride = stride,
.modifier_hi = modifier_hi,
.modifier_lo = modifier_lo,
};

dmabuf_params->planes[plane] = std::move(dma_plane);
}

void linux_buffer_params_create(wl_client* client,
Expand All @@ -81,8 +96,19 @@ void linux_buffer_params_create(wl_client* client,
wl_resource* buffer_resource =
wl_resource_create(client, &wl_buffer_interface, 1, 0);

DmabufParams* dmabuf_params = GetUserData<DmabufParams>(params);

Dmabuf* dmabuf = new Dmabuf();
dmabuf->width = w;
dmabuf->height = h;
dmabuf->format = format;
dmabuf->flags = flags;
dmabuf->params = dmabuf_params;

wl_resource_set_implementation(buffer_resource, &buffer_implementation,
nullptr, params_destroy_resource_callback);
dmabuf, params_destroy_resource_callback);

zwp_linux_buffer_params_v1_send_created(params, buffer_resource);
}

void linux_buffer_params_create_immed(wl_client* client,
Expand Down Expand Up @@ -128,12 +154,14 @@ void linux_dmabuf_create_params(wl_client* client,
<< " display=" << display
<< " id=" << id;

DmabufParams* dmabuf_params = new DmabufParams();

wl_resource* buffer_params_resource =
wl_resource_create(client, &zwp_linux_buffer_params_v1_interface, 1, id);

wl_resource_set_implementation(buffer_params_resource,
&zwp_linux_buffer_params_implementation,
nullptr, params_destroy_resource_callback);
dmabuf_params, params_destroy_resource_callback);
}

const struct zwp_linux_dmabuf_v1_interface
Expand Down Expand Up @@ -164,4 +192,9 @@ void BindDmabufInterface(wl_display* display) {
kLinuxDmabufVersion, nullptr, bind_linux_dmabuf);
}

bool IsDmabufResource(struct wl_resource* resource) {
return wl_resource_instance_of(resource, &wl_buffer_interface,
&zwp_linux_dmabuf_v1_interface);
}

} // namespace wayland
31 changes: 31 additions & 0 deletions base/cvd/cuttlefish/host/libs/wayland/wayland_dmabuf.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,43 @@
#pragma once

#include <stdint.h>
#include <map>

#include <android-base/unique_fd.h>

#include <wayland-server-core.h>

namespace wayland {

struct DmabufPlane {
android::base::unique_fd fd;
uint32_t plane = 0;
uint32_t offset = 0;
uint32_t stride = 0;
uint32_t modifier_hi = 0;
uint32_t modifier_lo = 0;
};

struct DmabufParams {
DmabufParams() = default;

DmabufParams(const DmabufParams& rhs) = delete;
DmabufParams& operator=(const DmabufParams& rhs) = delete;

std::map<int32_t, DmabufPlane> planes;
};

struct Dmabuf {
uint32_t width = 0;
uint32_t height = 0;
uint32_t format = 0;
uint32_t flags = 0;
DmabufParams* params;
};

// Binds the dmabuf interface to the given wayland server.
void BindDmabufInterface(wl_display* display);

bool IsDmabufResource(struct wl_resource* resource);

} // namespace wayland
74 changes: 57 additions & 17 deletions base/cvd/cuttlefish/host/libs/wayland/wayland_surface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,13 @@

#include <android-base/logging.h>
#include <drm/drm_fourcc.h>
#include <sys/mman.h>
#include <wayland-server-protocol.h>

#include "cuttlefish/host/libs/wayland/wayland_surfaces.h"
#include "cuttlefish/host/libs/wayland/wayland_dmabuf.h"
#include "cuttlefish/host/libs/wayland/wayland_surfaces.h"
#include "cuttlefish/host/libs/wayland/wayland_utils.h"

namespace wayland {
namespace {
Expand Down Expand Up @@ -70,31 +74,67 @@ void Surface::Commit() {
const uint32_t display_number = *state_.virtio_gpu_metadata_.scanout_id;

struct wl_shm_buffer* shm_buffer = wl_shm_buffer_get(state_.current_buffer);
CHECK(shm_buffer != nullptr);

wl_shm_buffer_begin_access(shm_buffer);

const int32_t buffer_w = wl_shm_buffer_get_width(shm_buffer);
CHECK(buffer_w == state_.region.w);
const int32_t buffer_h = wl_shm_buffer_get_height(shm_buffer);
CHECK(buffer_h == state_.region.h);
const int32_t buffer_stride_bytes = wl_shm_buffer_get_stride(shm_buffer);
const std::uint32_t buffer_drm_format =
GetDrmFormat(wl_shm_buffer_get_format(shm_buffer));
uint32_t buffer_w = 0;
uint32_t buffer_h = 0;
uint32_t buffer_drm_format = 0;
uint32_t buffer_stride_bytes = 0;
uint8_t* buffer_pixels = nullptr;
uint32_t buffer_size = 0;

if (shm_buffer != nullptr) {
wl_shm_buffer_begin_access(shm_buffer);
buffer_w = wl_shm_buffer_get_width(shm_buffer);
CHECK(buffer_w == state_.region.w);
buffer_h = wl_shm_buffer_get_height(shm_buffer);
CHECK(buffer_h == state_.region.h);
buffer_drm_format = GetDrmFormat(wl_shm_buffer_get_format(shm_buffer));
buffer_stride_bytes = wl_shm_buffer_get_stride(shm_buffer);
buffer_pixels =
reinterpret_cast<uint8_t*>(wl_shm_buffer_get_data(shm_buffer));
} else {
CHECK(IsDmabufResource(state_.current_buffer));
Dmabuf* dmabuf = GetUserData<Dmabuf>(state_.current_buffer);
buffer_w = dmabuf->width;
buffer_h = dmabuf->height;

if (dmabuf->params != nullptr) {
const DmabufParams& dmabuf_params = *dmabuf->params;

CHECK(dmabuf_params.planes.size() == 1);
const DmabufPlane& dmabuf_plane = dmabuf_params.planes.begin()->second;

if (dmabuf_plane.fd.ok()) {
buffer_drm_format = dmabuf->format;
buffer_stride_bytes = dmabuf_plane.stride;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here

buffer_size = buffer_h * buffer_stride_bytes;
auto mapped = mmap(nullptr, buffer_size, PROT_READ | PROT_WRITE,
MAP_SHARED, dmabuf_plane.fd, 0);
if (mapped != MAP_FAILED) {
buffer_pixels = reinterpret_cast<uint8_t*>(mapped);
}
}
}
}

if (!state_.has_notified_surface_create) {
surfaces_.HandleSurfaceCreated(display_number, buffer_w, buffer_h);
state_.has_notified_surface_create = true;
}

uint8_t* buffer_pixels =
reinterpret_cast<uint8_t*>(wl_shm_buffer_get_data(shm_buffer));

surfaces_.HandleSurfaceFrame(display_number, buffer_w, buffer_h,
buffer_drm_format, buffer_stride_bytes,
buffer_pixels);
if (buffer_pixels != nullptr) {
surfaces_.HandleSurfaceFrame(display_number, buffer_w, buffer_h,
buffer_drm_format, buffer_stride_bytes,
buffer_pixels);
}

wl_shm_buffer_end_access(shm_buffer);
if (shm_buffer != nullptr) {
wl_shm_buffer_end_access(shm_buffer);
} else {
if (buffer_pixels != nullptr) {
munmap(buffer_pixels, buffer_size);
}
}
}

wl_buffer_send_release(state_.current_buffer);
Expand Down
Loading