blob: ce2acd01dfe3c232f50878342b9d9ec7b738d730 [file] [log] [blame]
Mathias Agopian1473f462009-04-10 14:24:30 -07001/*
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
Mathias Agopian6950e422009-10-05 17:07:12 -070017#define LOG_TAG "GraphicBufferMapper"
Mathias Agopian1473f462009-04-10 14:24:30 -070018
19#include <stdint.h>
Mathias Agopian6f5f5a02009-10-05 18:19:57 -070020#ifdef HAVE_ANDROID_OS // just want PAGE_SIZE define
21# include <asm/page.h>
22#else
23# include <sys/user.h>
24#endif
Mathias Agopian1473f462009-04-10 14:24:30 -070025#include <errno.h>
Mathias Agopian6f5f5a02009-10-05 18:19:57 -070026#include <sys/mman.h>
27
28#include <cutils/ashmem.h>
Mathias Agopian1473f462009-04-10 14:24:30 -070029
30#include <utils/Errors.h>
Mathias Agopian1473f462009-04-10 14:24:30 -070031#include <utils/Log.h>
32
Mathias Agopian6950e422009-10-05 17:07:12 -070033#include <ui/GraphicBufferMapper.h>
Mathias Agopian1473f462009-04-10 14:24:30 -070034#include <ui/Rect.h>
35
Mathias Agopian1473f462009-04-10 14:24:30 -070036#include <hardware/gralloc.h>
37
Mathias Agopian6f5f5a02009-10-05 18:19:57 -070038#include <private/ui/sw_gralloc_handle.h>
39
Mathias Agopianaf9a5152009-04-10 20:34:46 -070040
Mathias Agopian1473f462009-04-10 14:24:30 -070041namespace android {
42// ---------------------------------------------------------------------------
43
Mathias Agopian6950e422009-10-05 17:07:12 -070044ANDROID_SINGLETON_STATIC_INSTANCE( GraphicBufferMapper )
Mathias Agopiana6b40ba2009-04-15 18:34:24 -070045
Mathias Agopian6950e422009-10-05 17:07:12 -070046GraphicBufferMapper::GraphicBufferMapper()
Mathias Agopian1473f462009-04-10 14:24:30 -070047 : 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
Mathias Agopian6950e422009-10-05 17:07:12 -070057status_t GraphicBufferMapper::registerBuffer(buffer_handle_t handle)
Mathias Agopian1473f462009-04-10 14:24:30 -070058{
Mathias Agopian6f5f5a02009-10-05 18:19:57 -070059 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 }
Mathias Agopiandff8e582009-05-04 14:17:04 -070065 LOGW_IF(err, "registerBuffer(%p) failed %d (%s)",
66 handle, err, strerror(-err));
Mathias Agopian1473f462009-04-10 14:24:30 -070067 return err;
68}
69
Mathias Agopian6950e422009-10-05 17:07:12 -070070status_t GraphicBufferMapper::unregisterBuffer(buffer_handle_t handle)
Mathias Agopian1473f462009-04-10 14:24:30 -070071{
Mathias Agopian6f5f5a02009-10-05 18:19:57 -070072 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 }
Mathias Agopiandff8e582009-05-04 14:17:04 -070078 LOGW_IF(err, "unregisterBuffer(%p) failed %d (%s)",
79 handle, err, strerror(-err));
Mathias Agopian1473f462009-04-10 14:24:30 -070080 return err;
81}
82
Mathias Agopian6950e422009-10-05 17:07:12 -070083status_t GraphicBufferMapper::lock(buffer_handle_t handle,
Mathias Agopiandff8e582009-05-04 14:17:04 -070084 int usage, const Rect& bounds, void** vaddr)
Mathias Agopian1473f462009-04-10 14:24:30 -070085{
Mathias Agopian6f5f5a02009-10-05 18:19:57 -070086 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 }
Mathias Agopian5e631892009-07-30 12:24:41 -070096 LOGW_IF(err, "lock(...) failed %d (%s)", err, strerror(-err));
Mathias Agopian1473f462009-04-10 14:24:30 -070097 return err;
98}
99
Mathias Agopian6950e422009-10-05 17:07:12 -0700100status_t GraphicBufferMapper::unlock(buffer_handle_t handle)
Mathias Agopian1473f462009-04-10 14:24:30 -0700101{
Mathias Agopian6f5f5a02009-10-05 18:19:57 -0700102 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 }
Mathias Agopian1473f462009-04-10 14:24:30 -0700108 LOGW_IF(err, "unlock(...) failed %d (%s)", err, strerror(-err));
109 return err;
110}
111
Mathias Agopian1473f462009-04-10 14:24:30 -0700112// ---------------------------------------------------------------------------
Mathias Agopian6f5f5a02009-10-05 18:19:57 -0700113
114status_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
178status_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
190status_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
204status_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
215status_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
222status_t sw_gralloc_handle_t::unlock(sw_gralloc_handle_t* hnd)
223{
224 return NO_ERROR;
225}
226
227// ---------------------------------------------------------------------------
Mathias Agopian1473f462009-04-10 14:24:30 -0700228}; // namespace android