1 /*
2 * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above
10 copyright notice, this list of conditions and the following
11 disclaimer in the documentation and/or other materials provided
12 with the distribution.
13 * Neither the name of The Linux Foundation nor the names of its
14 contributors may be used to endorse or promote products derived
15 from this software without specific prior written permission.
16
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #include "gl_color_convert_impl.h"
31
32 #define __CLASS__ "GLColorConvertImpl"
33
34 namespace sdm {
35
36 const float kFullScreenVertices[] = {
37 -1.0f, 3.0f,
38 -1.0f, -1.0f,
39 3.0f, -1.0f
40 };
41
42 const float kFullScreenTexCoords[] = {
43 0.0f, 2.0f,
44 0.0f, 0.0f,
45 2.0f, 0.0f
46 };
47
48 const char* kVertexShader = ""
49 "#version 300 es \n"
50 "precision highp float; \n"
51 "layout(location = 0) in vec2 in_pos; \n"
52 "layout(location = 1) in vec2 in_uv; \n"
53 " \n"
54 "out vec2 uv; \n"
55 " \n"
56 "void main() \n"
57 "{ \n"
58 " gl_Position = vec4(in_pos, 0.0, 1.0); \n"
59 " uv = in_uv; \n"
60 "} \n";
61
62 const char* kConvertRgbToYuvShader = ""
63 "#extension GL_EXT_YUV_target : require \n"
64 "precision highp float; \n"
65 " \n"
66 "layout(binding = 0) uniform sampler2D u_sTexture; \n"
67 " \n"
68 "in vec2 uv; \n"
69 "layout (yuv) out vec4 color; \n"
70 " \n"
71 "void main() \n"
72 "{ \n"
73 " vec3 rgbColor = texture(u_sTexture, uv).rgb; \n"
74 " color = vec4(rgb_2_yuv(rgbColor, itu_601_full_range), 1.0); \n"
75 "} \n";
76
CreateContext(GLRenderTarget target,bool secure)77 int GLColorConvertImpl::CreateContext(GLRenderTarget target, bool secure) {
78 if (target != kTargetRGBA && target != kTargetYUV) {
79 DLOGE("Invalid GLRenderTarget: %d", target);
80 return -1;
81 }
82
83 ctx_.egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
84 EGL(eglBindAPI(EGL_OPENGL_ES_API));
85
86 // Initialize current display.
87 EGL(eglInitialize(ctx_.egl_display, nullptr, nullptr));
88
89 // Get attributes corresponing to render target.
90 // Describes Framebuffer attributes like buffer depth, color space etc;
91 EGLConfig eglConfig;
92 int numConfig = 0;
93 if (target == kTargetRGBA) {
94 EGLint eglConfigAttribList[] = {EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
95 EGL_RED_SIZE, 8,
96 EGL_GREEN_SIZE, 8,
97 EGL_BLUE_SIZE, 8,
98 EGL_ALPHA_SIZE, 8,
99 EGL_NONE};
100 EGL(eglChooseConfig(ctx_.egl_display, eglConfigAttribList, &eglConfig, 1, &numConfig));
101 } else {
102 EGLint eglConfigAttribList[] = {EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
103 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
104 EGL_COLOR_BUFFER_TYPE, EGL_YUV_BUFFER_EXT,
105 EGL_YUV_ORDER_EXT, EGL_YUV_ORDER_YUV_EXT,
106 EGL_YUV_NUMBER_OF_PLANES_EXT, 2,
107 EGL_YUV_SUBSAMPLE_EXT, EGL_YUV_SUBSAMPLE_4_2_0_EXT,
108 EGL_YUV_DEPTH_RANGE_EXT, EGL_YUV_DEPTH_RANGE_LIMITED_EXT,
109 EGL_YUV_CSC_STANDARD_EXT, EGL_YUV_CSC_STANDARD_601_EXT,
110 EGL_YUV_PLANE_BPP_EXT, EGL_YUV_PLANE_BPP_8_EXT,
111 EGL_NONE};
112 EGL(eglChooseConfig(ctx_.egl_display, eglConfigAttribList, &eglConfig, 1, &numConfig));
113 }
114
115 // When GPU runs in protected context it can read from
116 // - Protected sources
117 // - UnProtected source
118 // and writes into Protected buffer.
119 // VS in UnProtected context it can read/write happen from/to Unprotected sources.
120 EGLint egl_contextAttribList[] = {EGL_CONTEXT_CLIENT_VERSION, 3,
121 secure ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
122 secure ? EGL_TRUE : EGL_NONE,
123 EGL_NONE};
124 ctx_.egl_context = eglCreateContext(ctx_.egl_display, eglConfig, NULL, egl_contextAttribList);
125
126 // eglCreatePbufferSurface creates an off-screen pixel buffer surface and returns its handle
127 EGLint egl_surfaceAttribList[] = {EGL_WIDTH, 1,
128 EGL_HEIGHT, 1,
129 secure ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
130 secure ? EGL_TRUE : EGL_NONE,
131 EGL_NONE};
132 ctx_.egl_surface = eglCreatePbufferSurface(ctx_.egl_display, eglConfig, egl_surfaceAttribList);
133
134 // eglMakeCurrent attaches rendering context to rendering surface.
135 MakeCurrent(&ctx_);
136
137 DLOGI("Created context = %p", (void *)(&ctx_.egl_context));
138
139 // Load Vertex and Fragment shaders.
140 const char *fragment_shaders[2] = { };
141 int count = 0;
142 const char *version = "#version 300 es\n";
143
144 fragment_shaders[count++] = version;
145
146 // ToDo: Add support to yuv_to_rgb shader.
147 fragment_shaders[count++] = kConvertRgbToYuvShader;
148
149 ctx_.program_id = LoadProgram(1, &kVertexShader, count, fragment_shaders);
150
151 SetRealTimePriority();
152
153 return 0;
154 }
155
Blit(const private_handle_t * src_hnd,const private_handle_t * dst_hnd,const GLRect & src_rect,const GLRect & dst_rect,const shared_ptr<Fence> & src_acquire_fence,const shared_ptr<Fence> & dst_acquire_fence,shared_ptr<Fence> * release_fence)156 int GLColorConvertImpl::Blit(const private_handle_t *src_hnd, const private_handle_t *dst_hnd,
157 const GLRect &src_rect, const GLRect &dst_rect,
158 const shared_ptr<Fence> &src_acquire_fence,
159 const shared_ptr<Fence> &dst_acquire_fence,
160 shared_ptr<Fence> *release_fence) {
161 DTRACE_SCOPED();
162 // eglMakeCurrent attaches rendering context to rendering surface.
163 MakeCurrent(&ctx_);
164
165 SetProgram(ctx_.program_id);
166
167 SetSourceBuffer(src_hnd);
168 SetDestinationBuffer(dst_hnd, dst_rect);
169
170 glEnableVertexAttribArray(0);
171 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, kFullScreenVertices);
172 glEnableVertexAttribArray(1);
173 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, kFullScreenTexCoords);
174 glDrawArrays(GL_TRIANGLES, 0, 3);
175
176 shared_ptr<Fence> in_fence = Fence::Merge(src_acquire_fence, dst_acquire_fence);
177 if (in_fence) {
178 WaitOnInputFence(in_fence);
179 }
180
181 // Create output fence for client to wait on.
182 CreateOutputFence(release_fence);
183
184 return 0;
185 }
186
Init()187 int GLColorConvertImpl::Init() {
188 return CreateContext(target_, secure_);
189 }
190
Deinit()191 int GLColorConvertImpl::Deinit() {
192 MakeCurrent(&ctx_);
193 DestroyContext(&ctx_);
194
195 return 0;
196 }
197
~GLColorConvertImpl()198 GLColorConvertImpl::~GLColorConvertImpl() {}
199
GLColorConvertImpl(GLRenderTarget target,bool secure)200 GLColorConvertImpl::GLColorConvertImpl(GLRenderTarget target, bool secure) {
201 target_ = target;
202 secure_ = secure;
203 }
204
Reset()205 void GLColorConvertImpl::Reset() {
206 ClearCache();
207 }
208
209 } // namespace sdm
210
211