/*
* Copyright 2017 The Chromium OS 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 "cros_gralloc_buffer.h"
#include <assert.h>
#include <sys/mman.h>
cros_gralloc_buffer::cros_gralloc_buffer(uint32_t id, struct bo *acquire_bo,
struct cros_gralloc_handle *acquire_handle)
: id_(id), bo_(acquire_bo), hnd_(acquire_handle), refcount_(1), lockcount_(0)
{
assert(bo_);
num_planes_ = drv_bo_get_num_planes(bo_);
for (uint32_t plane = 0; plane < num_planes_; plane++)
lock_data_[plane] = nullptr;
}
cros_gralloc_buffer::~cros_gralloc_buffer()
{
drv_bo_destroy(bo_);
if (hnd_) {
native_handle_close(&hnd_->base);
delete hnd_;
}
}
uint32_t cros_gralloc_buffer::get_id() const
{
return id_;
}
int32_t cros_gralloc_buffer::increase_refcount()
{
return ++refcount_;
}
int32_t cros_gralloc_buffer::decrease_refcount()
{
assert(refcount_ > 0);
return --refcount_;
}
int32_t cros_gralloc_buffer::lock(const struct rectangle *rect, uint32_t map_flags,
uint8_t *addr[DRV_MAX_PLANES])
{
void *vaddr = nullptr;
memset(addr, 0, DRV_MAX_PLANES * sizeof(*addr));
/*
* Gralloc consumers don't support more than one kernel buffer per buffer object yet, so
* just use the first kernel buffer.
*/
if (drv_num_buffers_per_bo(bo_) != 1) {
drv_log("Can only support one buffer per bo.\n");
return -EINVAL;
}
if (map_flags) {
if (lock_data_[0]) {
drv_bo_invalidate(bo_, lock_data_[0]);
vaddr = lock_data_[0]->vma->addr;
} else {
vaddr = drv_bo_map(bo_, rect, map_flags, &lock_data_[0], 0);
}
if (vaddr == MAP_FAILED) {
drv_log("Mapping failed.\n");
return -EFAULT;
}
}
for (uint32_t plane = 0; plane < num_planes_; plane++)
addr[plane] = static_cast<uint8_t *>(vaddr) + drv_bo_get_plane_offset(bo_, plane);
lockcount_++;
return 0;
}
int32_t cros_gralloc_buffer::unlock()
{
if (lockcount_ <= 0) {
drv_log("Buffer was not locked.\n");
return -EINVAL;
}
if (!--lockcount_) {
if (lock_data_[0]) {
drv_bo_flush_or_unmap(bo_, lock_data_[0]);
lock_data_[0] = nullptr;
}
}
return 0;
}