| // Copyright 2021 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // This file was automatically generated with: |
| // ../../ui/gfx/x/gen_xproto.py \ |
| // ../../third_party/xcbproto/src \ |
| // gen/ui/gfx/x \ |
| // bigreq \ |
| // composite \ |
| // damage \ |
| // dpms \ |
| // dri2 \ |
| // dri3 \ |
| // ge \ |
| // glx \ |
| // present \ |
| // randr \ |
| // record \ |
| // render \ |
| // res \ |
| // screensaver \ |
| // shape \ |
| // shm \ |
| // sync \ |
| // xc_misc \ |
| // xevie \ |
| // xf86dri \ |
| // xf86vidmode \ |
| // xfixes \ |
| // xinerama \ |
| // xinput \ |
| // xkb \ |
| // xprint \ |
| // xproto \ |
| // xselinux \ |
| // xtest \ |
| // xv \ |
| // xvmc |
| |
| #include "shm.h" |
| |
| #include <xcb/xcb.h> |
| #include <xcb/xcbext.h> |
| |
| #include "base/logging.h" |
| #include "base/posix/eintr_wrapper.h" |
| #include "ui/gfx/x/xproto_internal.h" |
| |
| namespace x11 { |
| |
| Shm::Shm(Connection* connection, const x11::QueryExtensionReply& info) |
| : connection_(connection), info_(info) {} |
| |
| template <> |
| COMPONENT_EXPORT(X11) |
| void ReadEvent<Shm::CompletionEvent>(Shm::CompletionEvent* event_, |
| ReadBuffer* buffer) { |
| auto& buf = *buffer; |
| |
| auto& sequence = (*event_).sequence; |
| auto& drawable = (*event_).drawable; |
| auto& minor_event = (*event_).minor_event; |
| auto& major_event = (*event_).major_event; |
| auto& shmseg = (*event_).shmseg; |
| auto& offset = (*event_).offset; |
| |
| // response_type |
| uint8_t response_type; |
| Read(&response_type, &buf); |
| |
| // pad0 |
| Pad(&buf, 1); |
| |
| // sequence |
| Read(&sequence, &buf); |
| |
| // drawable |
| Read(&drawable, &buf); |
| |
| // minor_event |
| Read(&minor_event, &buf); |
| |
| // major_event |
| Read(&major_event, &buf); |
| |
| // pad1 |
| Pad(&buf, 1); |
| |
| // shmseg |
| Read(&shmseg, &buf); |
| |
| // offset |
| Read(&offset, &buf); |
| |
| DCHECK_LE(buf.offset, 32ul); |
| } |
| |
| std::string Shm::BadSegError::ToString() const { |
| std::stringstream ss_; |
| ss_ << "Shm::BadSegError{"; |
| ss_ << ".sequence = " << static_cast<uint64_t>(sequence) << ", "; |
| ss_ << ".bad_value = " << static_cast<uint64_t>(bad_value) << ", "; |
| ss_ << ".minor_opcode = " << static_cast<uint64_t>(minor_opcode) << ", "; |
| ss_ << ".major_opcode = " << static_cast<uint64_t>(major_opcode); |
| ss_ << "}"; |
| return ss_.str(); |
| } |
| |
| template <> |
| void ReadError<Shm::BadSegError>(Shm::BadSegError* error_, ReadBuffer* buffer) { |
| auto& buf = *buffer; |
| |
| auto& sequence = (*error_).sequence; |
| auto& bad_value = (*error_).bad_value; |
| auto& minor_opcode = (*error_).minor_opcode; |
| auto& major_opcode = (*error_).major_opcode; |
| |
| // response_type |
| uint8_t response_type; |
| Read(&response_type, &buf); |
| |
| // error_code |
| uint8_t error_code; |
| Read(&error_code, &buf); |
| |
| // sequence |
| Read(&sequence, &buf); |
| |
| // bad_value |
| Read(&bad_value, &buf); |
| |
| // minor_opcode |
| Read(&minor_opcode, &buf); |
| |
| // major_opcode |
| Read(&major_opcode, &buf); |
| |
| // pad0 |
| Pad(&buf, 1); |
| |
| DCHECK_LE(buf.offset, 32ul); |
| } |
| Future<Shm::QueryVersionReply> Shm::QueryVersion( |
| const Shm::QueryVersionRequest& request) { |
| if (!connection_->Ready() || !present()) |
| return {}; |
| |
| WriteBuffer buf; |
| |
| // major_opcode |
| uint8_t major_opcode = info_.major_opcode; |
| buf.Write(&major_opcode); |
| |
| // minor_opcode |
| uint8_t minor_opcode = 0; |
| buf.Write(&minor_opcode); |
| |
| // length |
| // Caller fills in length for writes. |
| Pad(&buf, sizeof(uint16_t)); |
| |
| Align(&buf, 4); |
| |
| return connection_->SendRequest<Shm::QueryVersionReply>( |
| &buf, "Shm::QueryVersion", false); |
| } |
| |
| Future<Shm::QueryVersionReply> Shm::QueryVersion() { |
| return Shm::QueryVersion(Shm::QueryVersionRequest{}); |
| } |
| |
| template <> |
| COMPONENT_EXPORT(X11) |
| std::unique_ptr<Shm::QueryVersionReply> detail::ReadReply< |
| Shm::QueryVersionReply>(ReadBuffer* buffer) { |
| auto& buf = *buffer; |
| auto reply = std::make_unique<Shm::QueryVersionReply>(); |
| |
| auto& shared_pixmaps = (*reply).shared_pixmaps; |
| auto& sequence = (*reply).sequence; |
| auto& major_version = (*reply).major_version; |
| auto& minor_version = (*reply).minor_version; |
| auto& uid = (*reply).uid; |
| auto& gid = (*reply).gid; |
| auto& pixmap_format = (*reply).pixmap_format; |
| |
| // response_type |
| uint8_t response_type; |
| Read(&response_type, &buf); |
| |
| // shared_pixmaps |
| Read(&shared_pixmaps, &buf); |
| |
| // sequence |
| Read(&sequence, &buf); |
| |
| // length |
| uint32_t length; |
| Read(&length, &buf); |
| |
| // major_version |
| Read(&major_version, &buf); |
| |
| // minor_version |
| Read(&minor_version, &buf); |
| |
| // uid |
| Read(&uid, &buf); |
| |
| // gid |
| Read(&gid, &buf); |
| |
| // pixmap_format |
| Read(&pixmap_format, &buf); |
| |
| // pad0 |
| Pad(&buf, 15); |
| |
| Align(&buf, 4); |
| DCHECK_EQ(buf.offset < 32 ? 0 : buf.offset - 32, 4 * length); |
| |
| return reply; |
| } |
| |
| Future<void> Shm::Attach(const Shm::AttachRequest& request) { |
| if (!connection_->Ready() || !present()) |
| return {}; |
| |
| WriteBuffer buf; |
| |
| auto& shmseg = request.shmseg; |
| auto& shmid = request.shmid; |
| auto& read_only = request.read_only; |
| |
| // major_opcode |
| uint8_t major_opcode = info_.major_opcode; |
| buf.Write(&major_opcode); |
| |
| // minor_opcode |
| uint8_t minor_opcode = 1; |
| buf.Write(&minor_opcode); |
| |
| // length |
| // Caller fills in length for writes. |
| Pad(&buf, sizeof(uint16_t)); |
| |
| // shmseg |
| buf.Write(&shmseg); |
| |
| // shmid |
| buf.Write(&shmid); |
| |
| // read_only |
| buf.Write(&read_only); |
| |
| // pad0 |
| Pad(&buf, 3); |
| |
| Align(&buf, 4); |
| |
| return connection_->SendRequest<void>(&buf, "Shm::Attach", false); |
| } |
| |
| Future<void> Shm::Attach(const Seg& shmseg, |
| const uint32_t& shmid, |
| const uint8_t& read_only) { |
| return Shm::Attach(Shm::AttachRequest{shmseg, shmid, read_only}); |
| } |
| |
| Future<void> Shm::Detach(const Shm::DetachRequest& request) { |
| if (!connection_->Ready() || !present()) |
| return {}; |
| |
| WriteBuffer buf; |
| |
| auto& shmseg = request.shmseg; |
| |
| // major_opcode |
| uint8_t major_opcode = info_.major_opcode; |
| buf.Write(&major_opcode); |
| |
| // minor_opcode |
| uint8_t minor_opcode = 2; |
| buf.Write(&minor_opcode); |
| |
| // length |
| // Caller fills in length for writes. |
| Pad(&buf, sizeof(uint16_t)); |
| |
| // shmseg |
| buf.Write(&shmseg); |
| |
| Align(&buf, 4); |
| |
| return connection_->SendRequest<void>(&buf, "Shm::Detach", false); |
| } |
| |
| Future<void> Shm::Detach(const Seg& shmseg) { |
| return Shm::Detach(Shm::DetachRequest{shmseg}); |
| } |
| |
| Future<void> Shm::PutImage(const Shm::PutImageRequest& request) { |
| if (!connection_->Ready() || !present()) |
| return {}; |
| |
| WriteBuffer buf; |
| |
| auto& drawable = request.drawable; |
| auto& gc = request.gc; |
| auto& total_width = request.total_width; |
| auto& total_height = request.total_height; |
| auto& src_x = request.src_x; |
| auto& src_y = request.src_y; |
| auto& src_width = request.src_width; |
| auto& src_height = request.src_height; |
| auto& dst_x = request.dst_x; |
| auto& dst_y = request.dst_y; |
| auto& depth = request.depth; |
| auto& format = request.format; |
| auto& send_event = request.send_event; |
| auto& shmseg = request.shmseg; |
| auto& offset = request.offset; |
| |
| // major_opcode |
| uint8_t major_opcode = info_.major_opcode; |
| buf.Write(&major_opcode); |
| |
| // minor_opcode |
| uint8_t minor_opcode = 3; |
| buf.Write(&minor_opcode); |
| |
| // length |
| // Caller fills in length for writes. |
| Pad(&buf, sizeof(uint16_t)); |
| |
| // drawable |
| buf.Write(&drawable); |
| |
| // gc |
| buf.Write(&gc); |
| |
| // total_width |
| buf.Write(&total_width); |
| |
| // total_height |
| buf.Write(&total_height); |
| |
| // src_x |
| buf.Write(&src_x); |
| |
| // src_y |
| buf.Write(&src_y); |
| |
| // src_width |
| buf.Write(&src_width); |
| |
| // src_height |
| buf.Write(&src_height); |
| |
| // dst_x |
| buf.Write(&dst_x); |
| |
| // dst_y |
| buf.Write(&dst_y); |
| |
| // depth |
| buf.Write(&depth); |
| |
| // format |
| uint8_t tmp0; |
| tmp0 = static_cast<uint8_t>(format); |
| buf.Write(&tmp0); |
| |
| // send_event |
| buf.Write(&send_event); |
| |
| // pad0 |
| Pad(&buf, 1); |
| |
| // shmseg |
| buf.Write(&shmseg); |
| |
| // offset |
| buf.Write(&offset); |
| |
| Align(&buf, 4); |
| |
| return connection_->SendRequest<void>(&buf, "Shm::PutImage", false); |
| } |
| |
| Future<void> Shm::PutImage(const Drawable& drawable, |
| const GraphicsContext& gc, |
| const uint16_t& total_width, |
| const uint16_t& total_height, |
| const uint16_t& src_x, |
| const uint16_t& src_y, |
| const uint16_t& src_width, |
| const uint16_t& src_height, |
| const int16_t& dst_x, |
| const int16_t& dst_y, |
| const uint8_t& depth, |
| const ImageFormat& format, |
| const uint8_t& send_event, |
| const Seg& shmseg, |
| const uint32_t& offset) { |
| return Shm::PutImage(Shm::PutImageRequest{ |
| drawable, gc, total_width, total_height, src_x, src_y, src_width, |
| src_height, dst_x, dst_y, depth, format, send_event, shmseg, offset}); |
| } |
| |
| Future<Shm::GetImageReply> Shm::GetImage(const Shm::GetImageRequest& request) { |
| if (!connection_->Ready() || !present()) |
| return {}; |
| |
| WriteBuffer buf; |
| |
| auto& drawable = request.drawable; |
| auto& x = request.x; |
| auto& y = request.y; |
| auto& width = request.width; |
| auto& height = request.height; |
| auto& plane_mask = request.plane_mask; |
| auto& format = request.format; |
| auto& shmseg = request.shmseg; |
| auto& offset = request.offset; |
| |
| // major_opcode |
| uint8_t major_opcode = info_.major_opcode; |
| buf.Write(&major_opcode); |
| |
| // minor_opcode |
| uint8_t minor_opcode = 4; |
| buf.Write(&minor_opcode); |
| |
| // length |
| // Caller fills in length for writes. |
| Pad(&buf, sizeof(uint16_t)); |
| |
| // drawable |
| buf.Write(&drawable); |
| |
| // x |
| buf.Write(&x); |
| |
| // y |
| buf.Write(&y); |
| |
| // width |
| buf.Write(&width); |
| |
| // height |
| buf.Write(&height); |
| |
| // plane_mask |
| buf.Write(&plane_mask); |
| |
| // format |
| buf.Write(&format); |
| |
| // pad0 |
| Pad(&buf, 3); |
| |
| // shmseg |
| buf.Write(&shmseg); |
| |
| // offset |
| buf.Write(&offset); |
| |
| Align(&buf, 4); |
| |
| return connection_->SendRequest<Shm::GetImageReply>(&buf, "Shm::GetImage", |
| false); |
| } |
| |
| Future<Shm::GetImageReply> Shm::GetImage(const Drawable& drawable, |
| const int16_t& x, |
| const int16_t& y, |
| const uint16_t& width, |
| const uint16_t& height, |
| const uint32_t& plane_mask, |
| const uint8_t& format, |
| const Seg& shmseg, |
| const uint32_t& offset) { |
| return Shm::GetImage(Shm::GetImageRequest{ |
| drawable, x, y, width, height, plane_mask, format, shmseg, offset}); |
| } |
| |
| template <> |
| COMPONENT_EXPORT(X11) |
| std::unique_ptr<Shm::GetImageReply> detail::ReadReply<Shm::GetImageReply>( |
| ReadBuffer* buffer) { |
| auto& buf = *buffer; |
| auto reply = std::make_unique<Shm::GetImageReply>(); |
| |
| auto& depth = (*reply).depth; |
| auto& sequence = (*reply).sequence; |
| auto& visual = (*reply).visual; |
| auto& size = (*reply).size; |
| |
| // response_type |
| uint8_t response_type; |
| Read(&response_type, &buf); |
| |
| // depth |
| Read(&depth, &buf); |
| |
| // sequence |
| Read(&sequence, &buf); |
| |
| // length |
| uint32_t length; |
| Read(&length, &buf); |
| |
| // visual |
| Read(&visual, &buf); |
| |
| // size |
| Read(&size, &buf); |
| |
| Align(&buf, 4); |
| DCHECK_EQ(buf.offset < 32 ? 0 : buf.offset - 32, 4 * length); |
| |
| return reply; |
| } |
| |
| Future<void> Shm::CreatePixmap(const Shm::CreatePixmapRequest& request) { |
| if (!connection_->Ready() || !present()) |
| return {}; |
| |
| WriteBuffer buf; |
| |
| auto& pid = request.pid; |
| auto& drawable = request.drawable; |
| auto& width = request.width; |
| auto& height = request.height; |
| auto& depth = request.depth; |
| auto& shmseg = request.shmseg; |
| auto& offset = request.offset; |
| |
| // major_opcode |
| uint8_t major_opcode = info_.major_opcode; |
| buf.Write(&major_opcode); |
| |
| // minor_opcode |
| uint8_t minor_opcode = 5; |
| buf.Write(&minor_opcode); |
| |
| // length |
| // Caller fills in length for writes. |
| Pad(&buf, sizeof(uint16_t)); |
| |
| // pid |
| buf.Write(&pid); |
| |
| // drawable |
| buf.Write(&drawable); |
| |
| // width |
| buf.Write(&width); |
| |
| // height |
| buf.Write(&height); |
| |
| // depth |
| buf.Write(&depth); |
| |
| // pad0 |
| Pad(&buf, 3); |
| |
| // shmseg |
| buf.Write(&shmseg); |
| |
| // offset |
| buf.Write(&offset); |
| |
| Align(&buf, 4); |
| |
| return connection_->SendRequest<void>(&buf, "Shm::CreatePixmap", false); |
| } |
| |
| Future<void> Shm::CreatePixmap(const Pixmap& pid, |
| const Drawable& drawable, |
| const uint16_t& width, |
| const uint16_t& height, |
| const uint8_t& depth, |
| const Seg& shmseg, |
| const uint32_t& offset) { |
| return Shm::CreatePixmap(Shm::CreatePixmapRequest{ |
| pid, drawable, width, height, depth, shmseg, offset}); |
| } |
| |
| Future<void> Shm::AttachFd(const Shm::AttachFdRequest& request) { |
| if (!connection_->Ready() || !present()) |
| return {}; |
| |
| WriteBuffer buf; |
| |
| auto& shmseg = request.shmseg; |
| auto& shm_fd = request.shm_fd; |
| auto& read_only = request.read_only; |
| |
| // major_opcode |
| uint8_t major_opcode = info_.major_opcode; |
| buf.Write(&major_opcode); |
| |
| // minor_opcode |
| uint8_t minor_opcode = 6; |
| buf.Write(&minor_opcode); |
| |
| // length |
| // Caller fills in length for writes. |
| Pad(&buf, sizeof(uint16_t)); |
| |
| // shmseg |
| buf.Write(&shmseg); |
| |
| // shm_fd |
| buf.fds().push_back(HANDLE_EINTR(dup(shm_fd.get()))); |
| |
| // read_only |
| buf.Write(&read_only); |
| |
| // pad0 |
| Pad(&buf, 3); |
| |
| Align(&buf, 4); |
| |
| return connection_->SendRequest<void>(&buf, "Shm::AttachFd", false); |
| } |
| |
| Future<void> Shm::AttachFd(const Seg& shmseg, |
| const RefCountedFD& shm_fd, |
| const uint8_t& read_only) { |
| return Shm::AttachFd(Shm::AttachFdRequest{shmseg, shm_fd, read_only}); |
| } |
| |
| Future<Shm::CreateSegmentReply> Shm::CreateSegment( |
| const Shm::CreateSegmentRequest& request) { |
| if (!connection_->Ready() || !present()) |
| return {}; |
| |
| WriteBuffer buf; |
| |
| auto& shmseg = request.shmseg; |
| auto& size = request.size; |
| auto& read_only = request.read_only; |
| |
| // major_opcode |
| uint8_t major_opcode = info_.major_opcode; |
| buf.Write(&major_opcode); |
| |
| // minor_opcode |
| uint8_t minor_opcode = 7; |
| buf.Write(&minor_opcode); |
| |
| // length |
| // Caller fills in length for writes. |
| Pad(&buf, sizeof(uint16_t)); |
| |
| // shmseg |
| buf.Write(&shmseg); |
| |
| // size |
| buf.Write(&size); |
| |
| // read_only |
| buf.Write(&read_only); |
| |
| // pad0 |
| Pad(&buf, 3); |
| |
| Align(&buf, 4); |
| |
| return connection_->SendRequest<Shm::CreateSegmentReply>( |
| &buf, "Shm::CreateSegment", true); |
| } |
| |
| Future<Shm::CreateSegmentReply> Shm::CreateSegment(const Seg& shmseg, |
| const uint32_t& size, |
| const uint8_t& read_only) { |
| return Shm::CreateSegment(Shm::CreateSegmentRequest{shmseg, size, read_only}); |
| } |
| |
| template <> |
| COMPONENT_EXPORT(X11) |
| std::unique_ptr<Shm::CreateSegmentReply> detail::ReadReply< |
| Shm::CreateSegmentReply>(ReadBuffer* buffer) { |
| auto& buf = *buffer; |
| auto reply = std::make_unique<Shm::CreateSegmentReply>(); |
| |
| auto& nfd = (*reply).nfd; |
| auto& sequence = (*reply).sequence; |
| auto& shm_fd = (*reply).shm_fd; |
| |
| // response_type |
| uint8_t response_type; |
| Read(&response_type, &buf); |
| |
| // nfd |
| Read(&nfd, &buf); |
| |
| // sequence |
| Read(&sequence, &buf); |
| |
| // length |
| uint32_t length; |
| Read(&length, &buf); |
| |
| // shm_fd |
| shm_fd = RefCountedFD(buf.TakeFd()); |
| |
| // pad0 |
| Pad(&buf, 24); |
| |
| Align(&buf, 4); |
| DCHECK_EQ(buf.offset < 32 ? 0 : buf.offset - 32, 4 * length); |
| |
| return reply; |
| } |
| |
| } // namespace x11 |