1d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema/*
2d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
3d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema * Not a Contribution.
4d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema *
5d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema * Copyright 2015 The Android Open Source Project
6d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema *
7d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema * Licensed under the Apache License, Version 2.0 (the "License");
8d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema * you may not use this file except in compliance with the License.
9d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema * You may obtain a copy of the License at
10d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema *
11d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema *      http://www.apache.org/licenses/LICENSE-2.0
12d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema *
13d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema * Unless required by applicable law or agreed to in writing, software
14d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema * distributed under the License is distributed on an "AS IS" BASIS,
15d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema * See the License for the specific language governing permissions and
17d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema * limitations under the License.
18d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema */
19d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema
20d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema#include "EGLImageWrapper.h"
21d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema#include <cutils/native_handle.h>
22d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema#include <gralloc_priv.h>
23d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema#include <ui/GraphicBuffer.h>
24d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema#include <fcntl.h>
25d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema#include <linux/msm_ion.h>
26d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema
27d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema//-----------------------------------------------------------------------------
28d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennemavoid free_ion_cookie(int ion_fd, int cookie)
29d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema//-----------------------------------------------------------------------------
30d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema{
31d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema  if (ion_fd && !ioctl(ion_fd, ION_IOC_FREE, &cookie)) {
32d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema  } else {
33d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema      ALOGE("ION_IOC_FREE failed: ion_fd = %d, cookie = %d", ion_fd, cookie);
34d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema  }
35d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema}
36d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema
37d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema//-----------------------------------------------------------------------------
38d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennemaint get_ion_cookie(int ion_fd, int fd)
39d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema//-----------------------------------------------------------------------------
40d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema{
41d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema   int cookie = fd;
42d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema
43d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema   struct ion_fd_data fdData;
44d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema   memset(&fdData, 0, sizeof(fdData));
45d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema   fdData.fd = fd;
46d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema
47d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema   if (ion_fd && !ioctl(ion_fd, ION_IOC_IMPORT, &fdData)) {
48d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema        cookie = fdData.handle;
49d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema   } else {
50d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema        ALOGE("ION_IOC_IMPORT failed: ion_fd = %d, fd = %d", ion_fd, fd);
51d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema   }
52d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema
53d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema   return cookie;
54d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema}
55d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema
56d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema//-----------------------------------------------------------------------------
57d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben FennemaEGLImageWrapper::DeleteEGLImageCallback::DeleteEGLImageCallback(int fd)
58d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema//-----------------------------------------------------------------------------
59d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema{
60d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema    ion_fd = fd;
61d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema}
62d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema
63d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema//-----------------------------------------------------------------------------
64d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennemavoid EGLImageWrapper::DeleteEGLImageCallback::operator()(int& k, EGLImageBuffer*& eglImage)
65d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema//-----------------------------------------------------------------------------
66d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema{
67d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema    free_ion_cookie(ion_fd,  k);
68d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema    if( eglImage != 0 )
69d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema    {
70d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema        delete eglImage;
71d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema    }
72d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema}
73d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema
74d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema//-----------------------------------------------------------------------------
75d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben FennemaEGLImageWrapper::EGLImageWrapper()
76d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema//-----------------------------------------------------------------------------
77d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema{
78d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema    eglImageBufferMap = new android::LruCache<int, EGLImageBuffer*>(32);
79d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema    ion_fd = open("/dev/ion", O_RDONLY);
80d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema    callback = new DeleteEGLImageCallback(ion_fd);
81d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema    eglImageBufferMap->setOnEntryRemovedListener(callback);
82d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema}
83d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema
84d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema//-----------------------------------------------------------------------------
85d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben FennemaEGLImageWrapper::~EGLImageWrapper()
86d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema//-----------------------------------------------------------------------------
87d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema{
88d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema    if( eglImageBufferMap != 0 )
89d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema    {
90d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema        eglImageBufferMap->clear();
91d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema        delete eglImageBufferMap;
92d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema        eglImageBufferMap = 0;
93d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema    }
94d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema
95d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema    if( callback != 0 )
96d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema    {
97d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema        delete callback;
98d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema        callback = 0;
99d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema    }
100d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema
101d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema    if( ion_fd > 0 )
102d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema    {
103d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema        close(ion_fd);
104d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema    }
105d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema    ion_fd = -1;
106d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema}
107d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema//-----------------------------------------------------------------------------
108d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennemastatic EGLImageBuffer* L_wrap(const private_handle_t *src)
109d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema//-----------------------------------------------------------------------------
110d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema{
111d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema    EGLImageBuffer* result = 0;
112d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema
113d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema    native_handle_t *native_handle = const_cast<private_handle_t *>(src);
114d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema
115d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema    int flags = android::GraphicBuffer::USAGE_HW_TEXTURE |
116d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema                android::GraphicBuffer::USAGE_SW_READ_NEVER |
117d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema                android::GraphicBuffer::USAGE_SW_WRITE_NEVER;
118d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema
119d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema    if (src->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
120d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema      flags |= android::GraphicBuffer::USAGE_PROTECTED;
121d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema    }
122d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema
123d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema    android::sp<android::GraphicBuffer> graphicBuffer =
124d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema        new android::GraphicBuffer(src->unaligned_width, src->unaligned_height, src->format,
125d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema#ifndef __NOUGAT__
126d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema                                   1, // Layer count
127d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema#endif
128d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema                                   flags, src->width /*src->stride*/,
129d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema                                   native_handle, false);
130d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema
131d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema    result = new EGLImageBuffer(graphicBuffer);
132d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema
133d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema    return result;
134d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema}
135d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema
136d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema//-----------------------------------------------------------------------------
137d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben FennemaEGLImageBuffer *EGLImageWrapper::wrap(const void *pvt_handle)
138d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema//-----------------------------------------------------------------------------
139d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema{
140d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema    const private_handle_t *src = static_cast<const private_handle_t *>(pvt_handle);
141d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema
142d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema    int ion_cookie = get_ion_cookie(ion_fd, src->fd);
143d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema    EGLImageBuffer* eglImage = eglImageBufferMap->get(ion_cookie);
144d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema    if( eglImage == 0 )
145d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema    {
146d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema        eglImage = L_wrap(src);
147d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema        eglImageBufferMap->put(ion_cookie, eglImage);
148d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema    }
149d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema    else {
150d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema        free_ion_cookie(ion_fd, ion_cookie);
151d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema    }
152d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema
153d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema    return eglImage;
154d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema}
155