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