1/*
2 * Copyright (C) 2008 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#include <limits.h>
18#include <errno.h>
19#include <pthread.h>
20#include <unistd.h>
21#include <string.h>
22#include <stdarg.h>
23
24#include <sys/mman.h>
25#include <sys/stat.h>
26#include <sys/types.h>
27#include <sys/ioctl.h>
28
29#include <cutils/log.h>
30#include <cutils/atomic.h>
31
32#include <hardware/hardware.h>
33#include <hardware/gralloc.h>
34
35#include <linux/android_pmem.h>
36
37#include "gralloc_priv.h"
38
39
40// we need this for now because pmem cannot mmap at an offset
41#define PMEM_HACK   1
42
43/* desktop Linux needs a little help with gettid() */
44#if defined(ARCH_X86) && !defined(HAVE_ANDROID_OS)
45#define __KERNEL__
46# include <linux/unistd.h>
47pid_t gettid() { return syscall(__NR_gettid);}
48#undef __KERNEL__
49#endif
50
51/*****************************************************************************/
52
53static int gralloc_map(gralloc_module_t const* module,
54        buffer_handle_t handle,
55        void** vaddr)
56{
57    private_handle_t* hnd = (private_handle_t*)handle;
58    if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
59        size_t size = hnd->size;
60#if PMEM_HACK
61        size += hnd->offset;
62#endif
63        void* mappedAddress = mmap(0, size,
64                PROT_READ|PROT_WRITE, MAP_SHARED, hnd->fd, 0);
65        if (mappedAddress == MAP_FAILED) {
66            ALOGE("Could not mmap handle %p, fd=%d (%s)",
67                    handle, hnd->fd, strerror(errno));
68            hnd->base = 0;
69            return -errno;
70        }
71        hnd->base = intptr_t(mappedAddress) + hnd->offset;
72        //ALOGD("gralloc_map() succeeded fd=%d, off=%d, size=%d, vaddr=%p",
73        //        hnd->fd, hnd->offset, hnd->size, mappedAddress);
74    }
75    *vaddr = (void*)hnd->base;
76    return 0;
77}
78
79static int gralloc_unmap(gralloc_module_t const* module,
80        buffer_handle_t handle)
81{
82    private_handle_t* hnd = (private_handle_t*)handle;
83    if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
84        void* base = (void*)hnd->base;
85        size_t size = hnd->size;
86#if PMEM_HACK
87        base = (void*)(intptr_t(base) - hnd->offset);
88        size += hnd->offset;
89#endif
90        //ALOGD("unmapping from %p, size=%d, flags=%08x", base, size, hnd->flags);
91        if (munmap(base, size) < 0) {
92            ALOGE("Could not unmap %s", strerror(errno));
93        }
94    }
95    hnd->base = 0;
96    return 0;
97}
98
99/*****************************************************************************/
100
101static pthread_mutex_t sMapLock = PTHREAD_MUTEX_INITIALIZER;
102
103/*****************************************************************************/
104
105int gralloc_register_buffer(gralloc_module_t const* module,
106        buffer_handle_t handle)
107{
108    if (private_handle_t::validate(handle) < 0)
109        return -EINVAL;
110
111    // if this handle was created in this process, then we keep it as is.
112    int err = 0;
113    private_handle_t* hnd = (private_handle_t*)handle;
114    if (hnd->pid != getpid()) {
115        hnd->base = NULL;
116        if (!(hnd->flags & private_handle_t::PRIV_FLAGS_USES_GPU)) {
117            void *vaddr;
118            err = gralloc_map(module, handle, &vaddr);
119        }
120    }
121    return err;
122}
123
124int gralloc_unregister_buffer(gralloc_module_t const* module,
125        buffer_handle_t handle)
126{
127    if (private_handle_t::validate(handle) < 0)
128        return -EINVAL;
129
130    // never unmap buffers that were created in this process
131    private_handle_t* hnd = (private_handle_t*)handle;
132    if (hnd->pid != getpid()) {
133        if (hnd->base) {
134            gralloc_unmap(module, handle);
135        }
136    }
137    return 0;
138}
139
140int mapBuffer(gralloc_module_t const* module,
141        private_handle_t* hnd)
142{
143    void* vaddr;
144    return gralloc_map(module, hnd, &vaddr);
145}
146
147int terminateBuffer(gralloc_module_t const* module,
148        private_handle_t* hnd)
149{
150    if (hnd->base) {
151        // this buffer was mapped, unmap it now
152        if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_PMEM) {
153            if (hnd->pid != getpid()) {
154                // ... unless it's a "master" pmem buffer, that is a buffer
155                // mapped in the process it's been allocated.
156                // (see gralloc_alloc_buffer())
157                gralloc_unmap(module, hnd);
158            }
159        } else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_GPU) {
160            // XXX: for now do nothing here
161        } else {
162            gralloc_unmap(module, hnd);
163        }
164    }
165
166    return 0;
167}
168
169int gralloc_lock(gralloc_module_t const* module,
170        buffer_handle_t handle, int usage,
171        int l, int t, int w, int h,
172        void** vaddr)
173{
174    // this is called when a buffer is being locked for software
175    // access. in thin implementation we have nothing to do since
176    // not synchronization with the h/w is needed.
177    // typically this is used to wait for the h/w to finish with
178    // this buffer if relevant. the data cache may need to be
179    // flushed or invalidated depending on the usage bits and the
180    // hardware.
181
182    if (private_handle_t::validate(handle) < 0)
183        return -EINVAL;
184
185    private_handle_t* hnd = (private_handle_t*)handle;
186    *vaddr = (void*)hnd->base;
187    return 0;
188}
189
190int gralloc_unlock(gralloc_module_t const* module,
191        buffer_handle_t handle)
192{
193    // we're done with a software buffer. nothing to do in this
194    // implementation. typically this is used to flush the data cache.
195
196    if (private_handle_t::validate(handle) < 0)
197        return -EINVAL;
198    return 0;
199}
200
201
202/*****************************************************************************/
203
204int gralloc_perform(struct gralloc_module_t const* module,
205        int operation, ... )
206{
207    int res = -EINVAL;
208    return res;
209}
210