summaryrefslogtreecommitdiff
path: root/cros_gralloc/cros_gralloc_buffer.cc
blob: 710b78f78ed4d2c6b8f2fac8bdcf9408dcd0b122 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
/*
 * 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(uint64_t 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) {
		cros_gralloc_error("Can only support one buffer per bo.");
		return -EINVAL;
	}

	if (flags) {
		if (lock_data_[0]) {
			vaddr = lock_data_[0]->addr;
		} else {
			vaddr = drv_bo_map(bo_, 0, 0, drv_bo_get_width(bo_), drv_bo_get_height(bo_),
					   BO_TRANSFER_READ_WRITE, &lock_data_[0], 0);
		}

		if (vaddr == MAP_FAILED) {
			cros_gralloc_error("Mapping failed.");
			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) {
		cros_gralloc_error("Buffer was not locked.");
		return -EINVAL;
	}

	--lockcount_;
	if (lock_data_[0])
		return drv_bo_flush(bo_, lock_data_[0]);

	return 0;
}