blob: f8e33cdaff4ffab438f3a0aab7795ab8a171aaee [file] [log] [blame]
/*
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "gl_layer_stitch_impl.h"
#define __CLASS__ "GLLayerStitchImpl"
namespace sdm {
const float kFullScreenVertices[] = {
-1.0f, 3.0f,
-1.0f, -1.0f,
3.0f, -1.0f
};
const float kFullScreenTexCoords[] = {
0.0f, 2.0f,
0.0f, 0.0f,
2.0f, 0.0f
};
const char *kVertexShader1 = ""
"#version 300 es \n"
"precision highp float; \n"
"layout(location = 0) in vec2 in_pos; \n"
"layout(location = 1) in vec2 in_uv; \n"
" \n"
"out vec2 uv; \n"
" \n"
"void main() \n"
"{ \n"
" gl_Position = vec4(in_pos, 0.0, 1.0); \n"
" uv = in_uv; \n"
"} \n";
const char *kConvertRenderRGBShader = ""
"precision highp float; \n"
" \n"
"layout(binding = 0) uniform sampler2D u_sTexture; \n"
" \n"
"in vec2 uv; \n"
"out vec4 color; \n"
" \n"
"void main() \n"
"{ \n"
" color = texture(u_sTexture, uv); \n"
"} \n";
int GLLayerStitchImpl::CreateContext(bool secure) {
ctx_.egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
EGL(eglBindAPI(EGL_OPENGL_ES_API));
// Initialize current display.
EGL(eglInitialize(ctx_.egl_display, nullptr, nullptr));
// Get attributes corresponing to render target.
// Describes Framebuffer attributes like buffer depth, color space etc;
EGLConfig eglConfig;
int numConfig = 0;
EGLint eglConfigAttribList[] = {EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_NONE};
EGL(eglChooseConfig(ctx_.egl_display, eglConfigAttribList, &eglConfig, 1, &numConfig));
// When GPU runs in protected context it can read from
// - Protected sources
// - UnProtected source
// and writes into Protected buffer.
// VS in UnProtected context it can read/write happen from/to Unprotected sources.
EGLint egl_contextAttribList[] = {EGL_CONTEXT_CLIENT_VERSION, 3,
secure ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
secure ? EGL_TRUE : EGL_NONE,
EGL_NONE};
ctx_.egl_context = eglCreateContext(ctx_.egl_display, eglConfig, NULL, egl_contextAttribList);
// eglCreatePbufferSurface creates an off-screen pixel buffer surface and returns its handle
EGLint egl_surfaceAttribList[] = {EGL_WIDTH, 1,
EGL_HEIGHT, 1,
secure ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
secure ? EGL_TRUE : EGL_NONE,
EGL_NONE};
ctx_.egl_surface = eglCreatePbufferSurface(ctx_.egl_display, eglConfig, egl_surfaceAttribList);
// eglMakeCurrent attaches rendering context to rendering surface.
MakeCurrent(&ctx_);
DLOGI("Created context = %p", (void *)(&ctx_.egl_context));
// Load Vertex and Fragment shaders.
const char *fragment_shaders[2] = { };
int count = 0;
const char *version = "#version 300 es\n";
fragment_shaders[count++] = version;
// ToDo: Add support to yuv_to_rgb shader.
fragment_shaders[count++] = kConvertRenderRGBShader;
ctx_.program_id = LoadProgram(1, &kVertexShader1, count, fragment_shaders);
return 0;
}
int GLLayerStitchImpl::Blit(const private_handle_t *src_hnd, const private_handle_t *dst_hnd,
const GLRect &src_rect, const GLRect &dst_rect,
int src_acquire_fence_fd, int dst_acquire_fence_fd,
int *release_fence_fd) {
DTRACE_SCOPED();
// eglMakeCurrent attaches rendering context to rendering surface.
MakeCurrent(&ctx_);
SetProgram(ctx_.program_id);
SetSourceBuffer(src_hnd);
SetDestinationBuffer(dst_hnd, dst_rect);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, kFullScreenVertices);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, kFullScreenTexCoords);
glDrawArrays(GL_TRIANGLES, 0, 3);
int in_fence_fd = sync_merge(__CLASS__, src_acquire_fence_fd, dst_acquire_fence_fd);
if (in_fence_fd >= 0) {
WaitOnInputFence(in_fence_fd);
}
// Create output fence for client to wait on.
*release_fence_fd = CreateOutputFence();
return 0;
}
int GLLayerStitchImpl::Init() {
return CreateContext(secure_);
}
int GLLayerStitchImpl::Deinit() {
MakeCurrent(&ctx_);
DestroyContext(&ctx_);
return 0;
}
GLLayerStitchImpl::~GLLayerStitchImpl() {}
GLLayerStitchImpl::GLLayerStitchImpl(bool secure) {
secure_ = secure;
}
} // namespace sdm