1 /*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "GraphicBufferMapper"
18
19 #include <stdint.h>
20 #ifdef HAVE_ANDROID_OS // just want PAGE_SIZE define
21 # include <asm/page.h>
22 #else
23 # include <sys/user.h>
24 #endif
25 #include <errno.h>
26 #include <sys/mman.h>
27
28 #include <cutils/ashmem.h>
29
30 #include <utils/Errors.h>
31 #include <utils/Log.h>
32
33 #include <ui/GraphicBufferMapper.h>
34 #include <ui/Rect.h>
35
36 #include <hardware/gralloc.h>
37
38 #include <private/ui/sw_gralloc_handle.h>
39
40
41 namespace android {
42 // ---------------------------------------------------------------------------
43
ANDROID_SINGLETON_STATIC_INSTANCE(GraphicBufferMapper)44 ANDROID_SINGLETON_STATIC_INSTANCE( GraphicBufferMapper )
45
46 GraphicBufferMapper::GraphicBufferMapper()
47 : mAllocMod(0)
48 {
49 hw_module_t const* module;
50 int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
51 LOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
52 if (err == 0) {
53 mAllocMod = (gralloc_module_t const *)module;
54 }
55 }
56
registerBuffer(buffer_handle_t handle)57 status_t GraphicBufferMapper::registerBuffer(buffer_handle_t handle)
58 {
59 status_t err;
60 if (sw_gralloc_handle_t::validate(handle) < 0) {
61 err = mAllocMod->registerBuffer(mAllocMod, handle);
62 } else {
63 err = sw_gralloc_handle_t::registerBuffer((sw_gralloc_handle_t*)handle);
64 }
65 LOGW_IF(err, "registerBuffer(%p) failed %d (%s)",
66 handle, err, strerror(-err));
67 return err;
68 }
69
unregisterBuffer(buffer_handle_t handle)70 status_t GraphicBufferMapper::unregisterBuffer(buffer_handle_t handle)
71 {
72 status_t err;
73 if (sw_gralloc_handle_t::validate(handle) < 0) {
74 err = mAllocMod->unregisterBuffer(mAllocMod, handle);
75 } else {
76 err = sw_gralloc_handle_t::unregisterBuffer((sw_gralloc_handle_t*)handle);
77 }
78 LOGW_IF(err, "unregisterBuffer(%p) failed %d (%s)",
79 handle, err, strerror(-err));
80 return err;
81 }
82
lock(buffer_handle_t handle,int usage,const Rect & bounds,void ** vaddr)83 status_t GraphicBufferMapper::lock(buffer_handle_t handle,
84 int usage, const Rect& bounds, void** vaddr)
85 {
86 status_t err;
87 if (sw_gralloc_handle_t::validate(handle) < 0) {
88 err = mAllocMod->lock(mAllocMod, handle, usage,
89 bounds.left, bounds.top, bounds.width(), bounds.height(),
90 vaddr);
91 } else {
92 err = sw_gralloc_handle_t::lock((sw_gralloc_handle_t*)handle, usage,
93 bounds.left, bounds.top, bounds.width(), bounds.height(),
94 vaddr);
95 }
96 LOGW_IF(err, "lock(...) failed %d (%s)", err, strerror(-err));
97 return err;
98 }
99
unlock(buffer_handle_t handle)100 status_t GraphicBufferMapper::unlock(buffer_handle_t handle)
101 {
102 status_t err;
103 if (sw_gralloc_handle_t::validate(handle) < 0) {
104 err = mAllocMod->unlock(mAllocMod, handle);
105 } else {
106 err = sw_gralloc_handle_t::unlock((sw_gralloc_handle_t*)handle);
107 }
108 LOGW_IF(err, "unlock(...) failed %d (%s)", err, strerror(-err));
109 return err;
110 }
111
112 // ---------------------------------------------------------------------------
113
alloc(uint32_t w,uint32_t h,int format,int usage,buffer_handle_t * pHandle,int32_t * pStride)114 status_t sw_gralloc_handle_t::alloc(uint32_t w, uint32_t h, int format,
115 int usage, buffer_handle_t* pHandle, int32_t* pStride)
116 {
117 int align = 4;
118 int bpp = 0;
119 switch (format) {
120 case HAL_PIXEL_FORMAT_RGBA_8888:
121 case HAL_PIXEL_FORMAT_RGBX_8888:
122 case HAL_PIXEL_FORMAT_BGRA_8888:
123 bpp = 4;
124 break;
125 case HAL_PIXEL_FORMAT_RGB_888:
126 bpp = 3;
127 break;
128 case HAL_PIXEL_FORMAT_RGB_565:
129 case HAL_PIXEL_FORMAT_RGBA_5551:
130 case HAL_PIXEL_FORMAT_RGBA_4444:
131 bpp = 2;
132 break;
133 default:
134 return -EINVAL;
135 }
136 size_t bpr = (w*bpp + (align-1)) & ~(align-1);
137 size_t size = bpr * h;
138 size_t stride = bpr / bpp;
139 size = (size + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
140
141 int fd = ashmem_create_region("sw-gralloc-buffer", size);
142 if (fd < 0) {
143 LOGE("ashmem_create_region(size=%d) failed (%s)",
144 size, strerror(-errno));
145 return -errno;
146 }
147
148 int prot = PROT_READ;
149 if (usage & GRALLOC_USAGE_SW_WRITE_MASK)
150 prot |= PROT_WRITE;
151
152 if (ashmem_set_prot_region(fd, prot) < 0) {
153 LOGE("ashmem_set_prot_region(fd=%d, prot=%x) failed (%s)",
154 fd, prot, strerror(-errno));
155 close(fd);
156 return -errno;
157 }
158
159 void* base = mmap(0, size, prot, MAP_SHARED, fd, 0);
160 if (base == MAP_FAILED) {
161 LOGE("alloc mmap(fd=%d, size=%d, prot=%x) failed (%s)",
162 fd, size, prot, strerror(-errno));
163 close(fd);
164 return -errno;
165 }
166
167 sw_gralloc_handle_t* hnd = new sw_gralloc_handle_t();
168 hnd->fd = fd;
169 hnd->size = size;
170 hnd->base = intptr_t(base);
171 hnd->prot = prot;
172 *pStride = stride;
173 *pHandle = hnd;
174
175 return NO_ERROR;
176 }
177
free(sw_gralloc_handle_t * hnd)178 status_t sw_gralloc_handle_t::free(sw_gralloc_handle_t* hnd)
179 {
180 if (hnd->base) {
181 munmap((void*)hnd->base, hnd->size);
182 }
183 if (hnd->fd >= 0) {
184 close(hnd->fd);
185 }
186 delete hnd;
187 return NO_ERROR;
188 }
189
registerBuffer(sw_gralloc_handle_t * hnd)190 status_t sw_gralloc_handle_t::registerBuffer(sw_gralloc_handle_t* hnd)
191 {
192 if (hnd->pid != getpid()) {
193 void* base = mmap(0, hnd->size, hnd->prot, MAP_SHARED, hnd->fd, 0);
194 if (base == MAP_FAILED) {
195 LOGE("registerBuffer mmap(fd=%d, size=%d, prot=%x) failed (%s)",
196 hnd->fd, hnd->size, hnd->prot, strerror(-errno));
197 return -errno;
198 }
199 hnd->base = intptr_t(base);
200 }
201 return NO_ERROR;
202 }
203
unregisterBuffer(sw_gralloc_handle_t * hnd)204 status_t sw_gralloc_handle_t::unregisterBuffer(sw_gralloc_handle_t* hnd)
205 {
206 if (hnd->pid != getpid()) {
207 if (hnd->base) {
208 munmap((void*)hnd->base, hnd->size);
209 }
210 hnd->base = 0;
211 }
212 return NO_ERROR;
213 }
214
lock(sw_gralloc_handle_t * hnd,int usage,int l,int t,int w,int h,void ** vaddr)215 status_t sw_gralloc_handle_t::lock(sw_gralloc_handle_t* hnd, int usage,
216 int l, int t, int w, int h, void** vaddr)
217 {
218 *vaddr = (void*)hnd->base;
219 return NO_ERROR;
220 }
221
unlock(sw_gralloc_handle_t * hnd)222 status_t sw_gralloc_handle_t::unlock(sw_gralloc_handle_t* hnd)
223 {
224 return NO_ERROR;
225 }
226
227 // ---------------------------------------------------------------------------
228 }; // namespace android
229