OSDN Git Service

Revert "Modify gralloc0 implementation"
[android-x86/external-minigbm.git] / cros_gralloc / cros_gralloc_buffer.cc
1 /*
2  * Copyright 2017 The Chromium OS Authors. All rights reserved.
3  * Use of this source code is governed by a BSD-style license that can be
4  * found in the LICENSE file.
5  */
6
7 #include "cros_gralloc_buffer.h"
8
9 #include <assert.h>
10 #include <sys/mman.h>
11
12 cros_gralloc_buffer::cros_gralloc_buffer(uint32_t id, struct bo *acquire_bo,
13                                          struct cros_gralloc_handle *acquire_handle,
14                                          int32_t reserved_region_fd, uint64_t reserved_region_size)
15     : id_(id), bo_(acquire_bo), hnd_(acquire_handle), refcount_(1), lockcount_(0),
16       reserved_region_fd_(reserved_region_fd), reserved_region_size_(reserved_region_size),
17       reserved_region_addr_(nullptr)
18 {
19         assert(bo_);
20         num_planes_ = drv_bo_get_num_planes(bo_);
21         for (uint32_t plane = 0; plane < num_planes_; plane++)
22                 lock_data_[plane] = nullptr;
23 }
24
25 cros_gralloc_buffer::~cros_gralloc_buffer()
26 {
27         drv_bo_destroy(bo_);
28         if (hnd_) {
29                 native_handle_close(&hnd_->base);
30                 delete hnd_;
31         }
32         if (reserved_region_addr_) {
33                 munmap(reserved_region_addr_, reserved_region_size_);
34         }
35 }
36
37 uint32_t cros_gralloc_buffer::get_id() const
38 {
39         return id_;
40 }
41
42 int32_t cros_gralloc_buffer::increase_refcount()
43 {
44         return ++refcount_;
45 }
46
47 int32_t cros_gralloc_buffer::decrease_refcount()
48 {
49         assert(refcount_ > 0);
50         return --refcount_;
51 }
52
53 int32_t cros_gralloc_buffer::lock(const struct rectangle *rect, uint32_t map_flags,
54                                   uint8_t *addr[DRV_MAX_PLANES])
55 {
56         void *vaddr = nullptr;
57
58         memset(addr, 0, DRV_MAX_PLANES * sizeof(*addr));
59
60         /*
61          * Gralloc consumers don't support more than one kernel buffer per buffer object yet, so
62          * just use the first kernel buffer.
63          */
64         if (drv_num_buffers_per_bo(bo_) != 1) {
65                 drv_log("Can only support one buffer per bo.\n");
66                 return -EINVAL;
67         }
68
69         if (map_flags) {
70                 if (lock_data_[0]) {
71                         drv_bo_invalidate(bo_, lock_data_[0]);
72                         vaddr = lock_data_[0]->vma->addr;
73                 } else {
74                         struct rectangle r = *rect;
75
76                         if (!r.width && !r.height && !r.x && !r.y) {
77                                 /*
78                                  * Android IMapper.hal: An accessRegion of all-zeros means the
79                                  * entire buffer.
80                                  */
81                                 r.width = drv_bo_get_width(bo_);
82                                 r.height = drv_bo_get_height(bo_);
83                         }
84
85                         vaddr = drv_bo_map(bo_, &r, map_flags, &lock_data_[0], 0);
86                 }
87
88                 if (vaddr == MAP_FAILED) {
89                         drv_log("Mapping failed.\n");
90                         return -EFAULT;
91                 }
92         }
93
94         for (uint32_t plane = 0; plane < num_planes_; plane++)
95                 addr[plane] = static_cast<uint8_t *>(vaddr) + drv_bo_get_plane_offset(bo_, plane);
96
97         lockcount_++;
98         return 0;
99 }
100
101 int32_t cros_gralloc_buffer::unlock()
102 {
103         if (lockcount_ <= 0) {
104                 drv_log("Buffer was not locked.\n");
105                 return -EINVAL;
106         }
107
108         if (!--lockcount_) {
109                 if (lock_data_[0]) {
110                         drv_bo_flush_or_unmap(bo_, lock_data_[0]);
111                         lock_data_[0] = nullptr;
112                 }
113         }
114
115         return 0;
116 }
117
118 int32_t cros_gralloc_buffer::resource_info(uint32_t strides[DRV_MAX_PLANES],
119                                            uint32_t offsets[DRV_MAX_PLANES])
120 {
121         return drv_resource_info(bo_, strides, offsets);
122 }
123
124 int32_t cros_gralloc_buffer::invalidate()
125 {
126         if (lockcount_ <= 0) {
127                 drv_log("Buffer was not locked.\n");
128                 return -EINVAL;
129         }
130
131         if (lock_data_[0]) {
132                 return drv_bo_invalidate(bo_, lock_data_[0]);
133         }
134
135         return 0;
136 }
137
138 int32_t cros_gralloc_buffer::flush()
139 {
140         if (lockcount_ <= 0) {
141                 drv_log("Buffer was not locked.\n");
142                 return -EINVAL;
143         }
144
145         if (lock_data_[0]) {
146                 return drv_bo_flush(bo_, lock_data_[0]);
147         }
148
149         return 0;
150 }
151
152 int32_t cros_gralloc_buffer::get_reserved_region(void **addr, uint64_t *size)
153 {
154         if (reserved_region_fd_ <= 0) {
155                 drv_log("Buffer does not have reserved region.\n");
156                 return -EINVAL;
157         }
158
159         if (!reserved_region_addr_) {
160                 reserved_region_addr_ = mmap(nullptr, reserved_region_size_, PROT_WRITE | PROT_READ,
161                                              MAP_SHARED, reserved_region_fd_, 0);
162                 if (reserved_region_addr_ == MAP_FAILED) {
163                         drv_log("Failed to mmap reserved region: %s.\n", strerror(errno));
164                         return -errno;
165                 }
166         }
167
168         *addr = reserved_region_addr_;
169         *size = reserved_region_size_;
170         return 0;
171 }