1f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis/*
2f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis * Copyright (C) 2010 The Android Open Source Project
3f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis *
4f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis * Licensed under the Apache License, Version 2.0 (the "License");
5f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis * you may not use this file except in compliance with the License.
6f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis * You may obtain a copy of the License at
7f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis *
8f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis *      http://www.apache.org/licenses/LICENSE-2.0
9f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis *
10f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis * Unless required by applicable law or agreed to in writing, software
11f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis * distributed under the License is distributed on an "AS IS" BASIS,
12f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis * See the License for the specific language governing permissions and
14f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis * limitations under the License.
15f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis */
16f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
17f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis#include <limits.h>
18f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis#include <unistd.h>
19f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis#include <fcntl.h>
20f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
21f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis#include <sys/mman.h>
22f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
23f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis#include "gr.h"
24f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis#include "gpu.h"
25f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
26f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennisgpu_context_t::gpu_context_t(Deps& deps, PmemAllocator& pmemAllocator,
27f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        PmemAllocator& pmemAdspAllocator, const private_module_t* module) :
28f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    deps(deps),
29f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    pmemAllocator(pmemAllocator),
30f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    pmemAdspAllocator(pmemAdspAllocator)
31f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis{
32f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    // Zero out the alloc_device_t
33f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    memset(static_cast<alloc_device_t*>(this), 0, sizeof(alloc_device_t));
34f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
35f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    // Initialize the procs
36f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    common.tag     = HARDWARE_DEVICE_TAG;
37f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    common.version = 0;
38f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    common.module  = const_cast<hw_module_t*>(&module->base.common);
39f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    common.close   = gralloc_close;
40f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    alloc          = gralloc_alloc;
41f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    free           = gralloc_free;
42f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis}
43f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
44f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennisint gpu_context_t::gralloc_alloc_framebuffer_locked(size_t size, int usage,
45f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        buffer_handle_t* pHandle)
46f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis{
47f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    private_module_t* m = reinterpret_cast<private_module_t*>(common.module);
48f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
49f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    // we don't support allocations with both the FB and PMEM_ADSP flags
50f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    if (usage & GRALLOC_USAGE_PRIVATE_PMEM_ADSP) {
51f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        return -EINVAL;
52f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    }
53f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
54f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    // allocate the framebuffer
55f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    if (m->framebuffer == NULL) {
56f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        // initialize the framebuffer, the framebuffer is mapped once
57f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        // and forever.
58f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        int err = deps.mapFrameBufferLocked(m);
59f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        if (err < 0) {
60f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis            return err;
61f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        }
62f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    }
63f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
64f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    const uint32_t bufferMask = m->bufferMask;
65f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    const uint32_t numBuffers = m->numBuffers;
66f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    const size_t bufferSize = m->finfo.line_length * m->info.yres;
67f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    if (numBuffers == 1) {
68f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        // If we have only one buffer, we never use page-flipping. Instead,
69f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        // we return a regular buffer which will be memcpy'ed to the main
70f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        // screen when post is called.
71f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        int newUsage = (usage & ~GRALLOC_USAGE_HW_FB) | GRALLOC_USAGE_HW_2D;
72f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        return gralloc_alloc_buffer(bufferSize, newUsage, pHandle);
73f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    }
74f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
75f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    if (bufferMask >= ((1LU<<numBuffers)-1)) {
76f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        // We ran out of buffers.
77f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        return -ENOMEM;
78f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    }
79f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
80f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    // create a "fake" handles for it
81f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    intptr_t vaddr = intptr_t(m->framebuffer->base);
82f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    private_handle_t* hnd = new private_handle_t(dup(m->framebuffer->fd), size,
83f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis                                                 private_handle_t::PRIV_FLAGS_USES_PMEM |
84f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis                                                 private_handle_t::PRIV_FLAGS_FRAMEBUFFER);
85f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
86f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    // find a free slot
87f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    for (uint32_t i=0 ; i<numBuffers ; i++) {
88f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        if ((bufferMask & (1LU<<i)) == 0) {
89f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis            m->bufferMask |= (1LU<<i);
90f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis            break;
91f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        }
92f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        vaddr += bufferSize;
93f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    }
94f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
95f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    hnd->base = vaddr;
96f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    hnd->offset = vaddr - intptr_t(m->framebuffer->base);
97f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    *pHandle = hnd;
98f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
99f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    return 0;
100f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis}
101f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
102f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
103f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennisint gpu_context_t::gralloc_alloc_framebuffer(size_t size, int usage,
104f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        buffer_handle_t* pHandle)
105f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis{
106f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    private_module_t* m = reinterpret_cast<private_module_t*>(common.module);
107f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    pthread_mutex_lock(&m->lock);
108f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    int err = gralloc_alloc_framebuffer_locked(size, usage, pHandle);
109f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    pthread_mutex_unlock(&m->lock);
110f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    return err;
111f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis}
112f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
113f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
114f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennisint gpu_context_t::gralloc_alloc_buffer(size_t size, int usage, buffer_handle_t* pHandle)
115f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis{
116f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    int err = 0;
117f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    int flags = 0;
118f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
119f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    int fd = -1;
120f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    void* base = 0; // XXX JMG: This should change to just get an address from
121f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis                    // the PmemAllocator rather than getting the base & offset separately
122f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    int offset = 0;
123f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    int lockState = 0;
124f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
125f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    size = roundUpToPageSize(size);
126f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
127f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    if (usage & GRALLOC_USAGE_HW_TEXTURE) {
128f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        // enable pmem in that case, so our software GL can fallback to
129f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        // the copybit module.
130f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        flags |= private_handle_t::PRIV_FLAGS_USES_PMEM;
131f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    }
132f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
133f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    if (usage & GRALLOC_USAGE_HW_2D) {
134f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        flags |= private_handle_t::PRIV_FLAGS_USES_PMEM;
135f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    }
136f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
137f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    if (usage & GRALLOC_USAGE_PRIVATE_PMEM_ADSP) {
138f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        flags |= private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP;
139f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        flags &= ~private_handle_t::PRIV_FLAGS_USES_PMEM;
140f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    }
141f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
142f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    private_module_t* m = reinterpret_cast<private_module_t*>(common.module);
143f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
144f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    if ((flags & private_handle_t::PRIV_FLAGS_USES_PMEM) != 0 ||
145f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        (flags & private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP) != 0) {
146f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
147f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        PmemAllocator* pma = 0;
148f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
149f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        if ((flags & private_handle_t::PRIV_FLAGS_USES_PMEM) != 0) {
150f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis          if ((flags & private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP) != 0) {
151f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis              LOGE("attempting to allocate a gralloc buffer with both the "
152f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis                   "USES_PMEM and USES_PMEM_ADSP flags.  Unsetting the "
153f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis                   "USES_PMEM_ADSP flag.");
154f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis              flags &= ~private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP;
155f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis          }
156f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis          pma = &pmemAllocator;
157f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        } else { // (flags & private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP) != 0
158f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis          pma = &pmemAdspAllocator;
159f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        }
160f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
161f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        // PMEM buffers are always mmapped
162f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        lockState |= private_handle_t::LOCK_STATE_MAPPED;
163f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
164f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        // Allocate the buffer from pmem
165f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        err = pma->alloc_pmem_buffer(size, usage, &base, &offset, &fd);
166f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        if (err < 0) {
167ad20ef6be061091a95353fbf71712a3a97618304Mathias Agopian            if (((usage & GRALLOC_USAGE_HW_MASK) == 0) &&
168f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis                ((usage & GRALLOC_USAGE_PRIVATE_PMEM_ADSP) == 0)) {
169f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis                // the caller didn't request PMEM, so we can try something else
170f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis                flags &= ~private_handle_t::PRIV_FLAGS_USES_PMEM;
171f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis                err = 0;
172f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis                goto try_ashmem;
173f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis            } else {
174f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis                LOGE("couldn't open pmem (%s)", strerror(errno));
175f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis            }
176f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        }
177f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    } else {
178f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennistry_ashmem:
179f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        fd = deps.ashmem_create_region("gralloc-buffer", size);
180f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        if (fd < 0) {
181f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis            LOGE("couldn't create ashmem (%s)", strerror(errno));
182f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis            err = -errno;
183f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        }
184f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    }
185f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
186f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    if (err == 0) {
187f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        private_handle_t* hnd = new private_handle_t(fd, size, flags);
188f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        hnd->offset = offset;
189f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        hnd->base = int(base)+offset;
190f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        hnd->lockState = lockState;
191f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        *pHandle = hnd;
192f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    }
193f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
194f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    LOGE_IF(err, "gralloc failed err=%s", strerror(-err));
195f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
196f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    return err;
197f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis}
198f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
199f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennisstatic inline size_t ALIGN(size_t x, size_t align) {
200f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    return (x + align-1) & ~(align-1);
201f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis}
202f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
203f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennisint gpu_context_t::alloc_impl(int w, int h, int format, int usage,
204f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        buffer_handle_t* pHandle, int* pStride) {
205f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    if (!pHandle || !pStride)
206f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        return -EINVAL;
207f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
208f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    size_t size, alignedw, alignedh;
209f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
210f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    alignedw = ALIGN(w, 32);
211f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    alignedh = ALIGN(h, 32);
212f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    switch (format) {
213f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        case HAL_PIXEL_FORMAT_RGBA_8888:
214f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        case HAL_PIXEL_FORMAT_RGBX_8888:
215f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        case HAL_PIXEL_FORMAT_BGRA_8888:
216f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis            size = alignedw * alignedh * 4;
217f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis            break;
218f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        case HAL_PIXEL_FORMAT_RGB_888:
219f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis            size = alignedw * alignedh * 3;
220f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis            break;
221f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        case HAL_PIXEL_FORMAT_RGB_565:
222f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        case HAL_PIXEL_FORMAT_RGBA_5551:
223f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        case HAL_PIXEL_FORMAT_RGBA_4444:
224f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis            size = alignedw * alignedh * 2;
225f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis            break;
226f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
227f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        // adreno formats
228498d56e2df6b4dcaf3d5dc578c073eca93ec8b7bJamie Gennis        case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:  // NV21
229f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis            size  = ALIGN(alignedw*alignedh, 4096);
230f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis            size += ALIGN(2 * ALIGN(w/2, 32) * ALIGN(h/2, 32), 4096);
231f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis            break;
232f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:   // NV12
233f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis            // The chroma plane is subsampled,
234f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis            // but the pitch in bytes is unchanged
235f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis            // The GPU needs 4K alignment, but the video decoder needs 8K
236f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis            alignedw = ALIGN(w, 128);
237f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis            size  = ALIGN( alignedw * alignedh, 8192);
238f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis            size += ALIGN( alignedw * ALIGN(h/2, 32), 4096);
239f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis            break;
240f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
241f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        case HAL_PIXEL_FORMAT_YV12:
24215a9e53fbeaf765bfa6ed795d270e5968b30acb8Mathias Agopian            if ((w&1) || (h&1)) {
24315a9e53fbeaf765bfa6ed795d270e5968b30acb8Mathias Agopian                LOGE("w or h is odd for HAL_PIXEL_FORMAT_YV12");
24415a9e53fbeaf765bfa6ed795d270e5968b30acb8Mathias Agopian                return -EINVAL;
24515a9e53fbeaf765bfa6ed795d270e5968b30acb8Mathias Agopian            }
246f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis            alignedw = ALIGN(w, 16);
24715a9e53fbeaf765bfa6ed795d270e5968b30acb8Mathias Agopian            alignedh = h;
2484248ce329aa5164322acb15be20cbf32648a9790Mathias Agopian            size = alignedw*alignedh +
2494248ce329aa5164322acb15be20cbf32648a9790Mathias Agopian                    (ALIGN(alignedw/2, 16) * (alignedh/2))*2;
250f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis            break;
251f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
252f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        default:
253f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis            LOGE("unrecognized pixel format: %d", format);
254f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis            return -EINVAL;
255f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    }
256f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
257f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    if ((ssize_t)size <= 0)
258f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        return -EINVAL;
259f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
260f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    int err;
261f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    if (usage & GRALLOC_USAGE_HW_FB) {
262f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        err = gralloc_alloc_framebuffer(size, usage, pHandle);
263f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    } else {
264f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        err = gralloc_alloc_buffer(size, usage, pHandle);
265f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    }
266f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
267f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    if (err < 0) {
268f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        return err;
269f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    }
270f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
271f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    *pStride = alignedw;
272f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    return 0;
273f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis}
274f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
275f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennisint gpu_context_t::free_impl(private_handle_t const* hnd) {
276f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    private_module_t* m = reinterpret_cast<private_module_t*>(common.module);
277f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
278f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        // free this buffer
279f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        const size_t bufferSize = m->finfo.line_length * m->info.yres;
280f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        int index = (hnd->base - m->framebuffer->base) / bufferSize;
281f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        m->bufferMask &= ~(1<<index);
282f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    } else {
283f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        PmemAllocator* pmem_allocator = 0;
284f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_PMEM) {
285f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis            pmem_allocator = &pmemAllocator;
286f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        } else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP) {
287f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis            pmem_allocator = &pmemAdspAllocator;
288f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        }
28928b31647cda80ee08b3b3d7a402832e132505b2cMathias Agopian        if (pmem_allocator) {
29028b31647cda80ee08b3b3d7a402832e132505b2cMathias Agopian            pmem_allocator->free_pmem_buffer(hnd->size, (void*)hnd->base,
29128b31647cda80ee08b3b3d7a402832e132505b2cMathias Agopian                    hnd->offset, hnd->fd);
29228b31647cda80ee08b3b3d7a402832e132505b2cMathias Agopian        }
293f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        deps.terminateBuffer(&m->base, const_cast<private_handle_t*>(hnd));
294f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    }
295f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
296f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    deps.close(hnd->fd);
297f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    delete hnd; // XXX JMG: move this to the deps
298f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    return 0;
299f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis}
300f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
301f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis/******************************************************************************
302f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis * Static functions
303f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis *****************************************************************************/
304f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
305f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennisint gpu_context_t::gralloc_alloc(alloc_device_t* dev, int w, int h, int format,
306f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        int usage, buffer_handle_t* pHandle, int* pStride)
307f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis{
308f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    if (!dev) {
309f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        return -EINVAL;
310f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    }
311f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    gpu_context_t* gpu = reinterpret_cast<gpu_context_t*>(dev);
312f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    return gpu->alloc_impl(w, h, format, usage, pHandle, pStride);
313f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis}
314f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
315f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennisint gpu_context_t::gralloc_free(alloc_device_t* dev,
316f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis                                    buffer_handle_t handle)
317f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis{
318f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    if (private_handle_t::validate(handle) < 0)
319f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        return -EINVAL;
320f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
321f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(handle);
322f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    gpu_context_t* gpu = reinterpret_cast<gpu_context_t*>(dev);
323f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    return gpu->free_impl(hnd);
324f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis}
325f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
326f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis/*****************************************************************************/
327f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
328f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennisint gpu_context_t::gralloc_close(struct hw_device_t *dev)
329f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis{
330f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    gpu_context_t* ctx = reinterpret_cast<gpu_context_t*>(dev);
331f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    if (ctx) {
332f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        /* TODO: keep a list of all buffer_handle_t created, and free them
333f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis         * all here.
334f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis         */
335f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis        delete ctx;
336f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    }
337f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis    return 0;
338f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis}
339f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
340f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis
341f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennisgpu_context_t::Deps::~Deps() {}
342