blob: 1ad2b556fb548276fc9a85606f7048d5f5d2e4ab [file] [log] [blame]
// Copyright 2018 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.
#include "ui/ozone/platform/wayland/wayland_util.h"
#include "base/memory/shared_memory.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "ui/gfx/skia_util.h"
namespace wl {
namespace {
const uint32_t kShmFormat = WL_SHM_FORMAT_ARGB8888;
const SkColorType kColorType = kBGRA_8888_SkColorType;
} // namespace
wl_buffer* CreateSHMBuffer(const gfx::Size& size,
base::SharedMemory* shared_memory,
wl_shm* shm) {
SkImageInfo info = SkImageInfo::MakeN32Premul(size.width(), size.height());
int stride = info.minRowBytes();
size_t image_buffer_size = info.computeByteSize(stride);
if (image_buffer_size == SIZE_MAX)
return nullptr;
if (shared_memory->handle().GetHandle()) {
shared_memory->Unmap();
shared_memory->Close();
}
if (!shared_memory->CreateAndMapAnonymous(image_buffer_size)) {
LOG(ERROR) << "Create and mmap failed.";
return nullptr;
}
// TODO(tonikitoo): Use SharedMemory::requested_size instead of
// 'image_buffer_size'?
wl::Object<wl_shm_pool> pool;
pool.reset(wl_shm_create_pool(shm, shared_memory->handle().GetHandle(),
image_buffer_size));
wl_buffer* buffer = wl_shm_pool_create_buffer(
pool.get(), 0, size.width(), size.height(), stride, kShmFormat);
return buffer;
}
void DrawBitmapToSHMB(const gfx::Size& size,
const base::SharedMemory& shared_memory,
const SkBitmap& bitmap) {
SkImageInfo info = SkImageInfo::MakeN32Premul(size.width(), size.height());
int stride = info.minRowBytes();
sk_sp<SkSurface> sk_surface = SkSurface::MakeRasterDirect(
SkImageInfo::Make(size.width(), size.height(), kColorType,
kOpaque_SkAlphaType),
static_cast<uint8_t*>(shared_memory.memory()), stride);
// The |bitmap| contains ARGB image, so update our wl_buffer, which is
// backed by a SkSurface.
SkRect damage;
bitmap.getBounds(&damage);
// Clear to transparent in case |bitmap| is smaller than the canvas.
SkCanvas* canvas = sk_surface->getCanvas();
canvas->clear(SK_ColorTRANSPARENT);
canvas->drawBitmapRect(bitmap, damage, nullptr);
}
} // namespace wl