• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 #include <vector>
17 #include <stdio.h>
18 #include <fcntl.h>
19 #include <alloca.h>
20 #include <unistd.h>
21 #include <sys/ioctl.h>
22 #include <malloc.h>
23 #include <png.h>
24 
25 #include "VideoTex.h"
26 #include "glError.h"
27 
28 #include <ui/GraphicBuffer.h>
29 #include <ui/GraphicBufferAllocator.h>
30 #include <ui/GraphicBufferMapper.h>
31 
32 namespace android {
33 namespace automotive {
34 namespace evs {
35 namespace support {
36 
37 // Eventually we shouldn't need this dependency, but for now the
38 // graphics allocator interface isn't fully supported on all platforms
39 // and this is our work around.
40 using ::android::GraphicBuffer;
41 
42 
VideoTex(EGLDisplay glDisplay)43 VideoTex::VideoTex(EGLDisplay glDisplay)
44     : TexWrapper()
45     , mDisplay(glDisplay) {
46     // Nothing but initialization here...
47 }
48 
~VideoTex()49 VideoTex::~VideoTex() {
50     // Drop our device texture image
51     if (mKHRimage != EGL_NO_IMAGE_KHR) {
52         eglDestroyImageKHR(mDisplay, mKHRimage);
53         mKHRimage = EGL_NO_IMAGE_KHR;
54     }
55 }
56 
57 
58 // Return true if the texture contents are changed
refresh(const BufferDesc & imageBuffer)59 bool VideoTex::refresh(const BufferDesc& imageBuffer) {
60     // No new image has been delivered, so there's nothing to do here
61     if (imageBuffer.memHandle.getNativeHandle() == nullptr) {
62         return false;
63     }
64 
65     // Drop our device texture image
66     if (mKHRimage != EGL_NO_IMAGE_KHR) {
67         eglDestroyImageKHR(mDisplay, mKHRimage);
68         mKHRimage = EGL_NO_IMAGE_KHR;
69     }
70 
71     // create a GraphicBuffer from the existing handle
72     sp<GraphicBuffer> imageGraphicBuffer = new GraphicBuffer(
73         imageBuffer.memHandle, GraphicBuffer::CLONE_HANDLE, imageBuffer.width,
74         imageBuffer.height, imageBuffer.format, 1, // layer count
75         GRALLOC_USAGE_HW_TEXTURE, imageBuffer.stride);
76 
77     if (imageGraphicBuffer.get() == nullptr) {
78         ALOGE("Failed to allocate GraphicBuffer to wrap image handle");
79         // Returning "true" in this error condition because we already released the
80         // previous image (if any) and so the texture may change in unpredictable ways now!
81         return true;
82     }
83 
84 
85     // Get a GL compatible reference to the graphics buffer we've been given
86     EGLint eglImageAttributes[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
87     EGLClientBuffer clientBuf = static_cast<EGLClientBuffer>(imageGraphicBuffer->getNativeBuffer());
88     mKHRimage = eglCreateImageKHR(mDisplay, EGL_NO_CONTEXT,
89                                   EGL_NATIVE_BUFFER_ANDROID, clientBuf,
90                                   eglImageAttributes);
91     if (mKHRimage == EGL_NO_IMAGE_KHR) {
92         const char *msg = getEGLError();
93         ALOGE("error creating EGLImage: %s", msg);
94         return false;
95     } else {
96         // Update the texture handle we already created to refer to this gralloc buffer
97         glActiveTexture(GL_TEXTURE0);
98         glBindTexture(GL_TEXTURE_2D, glId());
99         glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, static_cast<GLeglImageOES>(mKHRimage));
100 
101         // Initialize the sampling properties (it seems the sample may not work if this isn't done)
102         // The user of this texture may very well want to set their own filtering, but we're going
103         // to pay the (minor) price of setting this up for them to avoid the dreaded "black image"
104         // if they forget.
105         // TODO:  Can we do this once for the texture ID rather than ever refresh?
106         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
107         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
108         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
109         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
110     }
111 
112     return true;
113 }
114 }  // namespace support
115 }  // namespace evs
116 }  // namespace automotive
117 }  // namespace android
118