summaryrefslogtreecommitdiff
path: root/gpu.c
diff options
context:
space:
mode:
Diffstat (limited to 'gpu.c')
-rw-r--r--gpu.c165
1 files changed, 41 insertions, 124 deletions
diff --git a/gpu.c b/gpu.c
index 71ef625..da746c6 100644
--- a/gpu.c
+++ b/gpu.c
@@ -45,19 +45,8 @@
return NULL; \
}
-// TODO(mburakov): It should be theoretically possible to do everything in a
-// single pass using a compute shader and GLES3. Unfortunately my test machine
-// reports the primary framebuffer as multiplane. This is probably the reason
-// why texture created from it can not be sampled using imageLoad in a compute
-// shader even though it's still RGB. Fallback to GLES2 and per-plane textures
-// for now, and figure out details later.
-
-extern const char _binary_vertex_glsl_start[];
-extern const char _binary_vertex_glsl_end[];
-extern const char _binary_luma_glsl_start[];
-extern const char _binary_luma_glsl_end[];
-extern const char _binary_chroma_glsl_start[];
-extern const char _binary_chroma_glsl_end[];
+extern const char _binary_compute_glsl_start[];
+extern const char _binary_compute_glsl_end[];
struct GpuContext {
#ifndef USE_EGL_MESA_PLATFORM_SURFACELESS
@@ -69,11 +58,8 @@ struct GpuContext {
PFNEGLQUERYDMABUFFORMATSEXTPROC eglQueryDmaBufFormatsEXT;
PFNEGLQUERYDMABUFMODIFIERSEXTPROC eglQueryDmaBufModifiersEXT;
PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES;
- GLuint program_luma;
- GLuint program_chroma;
+ GLuint compute_program;
GLint sample_offsets;
- GLuint framebuffer;
- GLuint vertices;
};
struct GpuFrame {
@@ -149,47 +135,33 @@ static bool HasExtension(const char* haystack, const char* needle) {
return result;
}
-static GLuint CreateGlProgram(const char* vs_begin, const char* vs_end,
- const char* fs_begin, const char* fs_end) {
+static GLuint CreateGlProgram(const char* begin, const char* end) {
GLuint program = 0;
- GLuint vertex = glCreateShader(GL_VERTEX_SHADER);
- if (!vertex) {
- LOG("Failed to create vertex shader (%s)", GlErrorString(glGetError()));
+ GLuint shader = glCreateShader(GL_COMPUTE_SHADER);
+ if (!shader) {
+ LOG("Failed to create compute shader (%s)", GlErrorString(glGetError()));
goto bail_out;
}
- GLsizei size = (GLsizei)(vs_end - vs_begin);
- glShaderSource(vertex, 1, &vs_begin, &size);
- glCompileShader(vertex);
- if (!CheckBuildableShader(vertex)) goto delete_vs;
-
- GLuint fragment = glCreateShader(GL_FRAGMENT_SHADER);
- if (!fragment) {
- LOG("Failed to create fragment shader (%s)", GlErrorString(glGetError()));
- goto delete_vs;
- }
- size = (GLsizei)(fs_end - fs_begin);
- glShaderSource(fragment, 1, &fs_begin, &size);
- glCompileShader(fragment);
- if (!CheckBuildableShader(fragment)) goto delete_fs;
+ GLsizei size = (GLsizei)(end - begin);
+ glShaderSource(shader, 1, &begin, &size);
+ glCompileShader(shader);
+ if (!CheckBuildableShader(shader)) goto delete_shader;
program = glCreateProgram();
if (!program) {
LOG("Failed to create shader program (%s)", GlErrorString(glGetError()));
- goto delete_fs;
+ goto delete_shader;
}
- glAttachShader(program, vertex);
- glAttachShader(program, fragment);
+ glAttachShader(program, shader);
glLinkProgram(program);
if (!CheckBuildableProgram(program)) {
glDeleteProgram(program);
program = 0;
- goto delete_fs;
+ goto delete_shader;
}
-delete_fs:
- glDeleteShader(fragment);
-delete_vs:
- glDeleteShader(vertex);
+delete_shader:
+ glDeleteShader(shader);
bail_out:
return program;
}
@@ -234,13 +206,12 @@ static const GLfloat* GetRangeVectors(enum YuvRange range) {
}
}
-static bool SetupCommonUniforms(GLuint program, enum YuvColorspace colorspace,
- enum YuvRange range) {
+static bool SetupUniforms(GLuint program, enum YuvColorspace colorspace,
+ enum YuvRange range) {
struct {
const char* name;
GLint location;
} uniforms[] = {
- {.name = "img_input"},
{.name = "colorspace"},
{.name = "ranges"},
};
@@ -255,10 +226,9 @@ static bool SetupCommonUniforms(GLuint program, enum YuvColorspace colorspace,
}
glUseProgram(program);
- glUniform1i(uniforms[0].location, 0);
- glUniformMatrix3fv(uniforms[1].location, 1, GL_TRUE,
+ glUniformMatrix3fv(uniforms[0].location, 1, GL_TRUE,
GetColorspaceMatrix(colorspace));
- glUniform3fv(uniforms[2].location, 2, GetRangeVectors(range));
+ glUniform3fv(uniforms[1].location, 2, GetRangeVectors(range));
GLenum error = glGetError();
if (error != GL_NO_ERROR) {
LOG("Failed to set img_input uniform (%s)", GlErrorString(glGetError()));
@@ -377,42 +347,20 @@ struct GpuContext* GpuContextCreate(enum YuvColorspace colorspace,
LOOKUP_FUNCTION(PFNGLEGLIMAGETARGETTEXTURE2DOESPROC,
glEGLImageTargetTexture2DOES)
- gpu_context->program_luma =
- CreateGlProgram(_binary_vertex_glsl_start, _binary_vertex_glsl_end,
- _binary_luma_glsl_start, _binary_luma_glsl_end);
- if (!gpu_context->program_luma ||
- !SetupCommonUniforms(gpu_context->program_luma, colorspace, range)) {
- LOG("Failed to create luma program");
- return NULL;
- }
-
- gpu_context->program_chroma =
- CreateGlProgram(_binary_vertex_glsl_start, _binary_vertex_glsl_end,
- _binary_chroma_glsl_start, _binary_chroma_glsl_end);
- if (!gpu_context->program_chroma ||
- !SetupCommonUniforms(gpu_context->program_chroma, colorspace, range)) {
- LOG("Failed to create chroma program");
- return NULL;
- }
- gpu_context->sample_offsets =
- glGetUniformLocation(gpu_context->program_chroma, "sample_offsets");
- if (gpu_context->sample_offsets == -1) {
- LOG("Failed to find sample_offsets uniform (%s)",
- GlErrorString(glGetError()));
+ gpu_context->compute_program =
+ CreateGlProgram(_binary_compute_glsl_start, _binary_compute_glsl_end);
+ if (!gpu_context->compute_program) {
+ LOG("Failed to create compute program");
return NULL;
}
- glGenFramebuffers(1, &gpu_context->framebuffer);
- glBindFramebuffer(GL_FRAMEBUFFER, gpu_context->framebuffer);
- glGenBuffers(1, &gpu_context->vertices);
- glBindBuffer(GL_ARRAY_BUFFER, gpu_context->vertices);
- static const GLfloat vertices[] = {0, 0, 1, 0, 1, 1, 0, 1};
- glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
- glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
- glEnableVertexAttribArray(0);
+ glUseProgram(gpu_context->compute_program);
+ glUniformMatrix3fv(0, 1, GL_TRUE, GetColorspaceMatrix(colorspace));
+ glUniform3fv(1, 2, GetRangeVectors(range));
GLenum error = glGetError();
if (error != GL_NO_ERROR) {
- LOG("Failed to create gl objects (%s)", GlErrorString(glGetError()));
+ LOG("Failed to configure program uniforms (%s)",
+ GlErrorString(glGetError()));
return NULL;
}
return RELEASE(gpu_context);
@@ -431,13 +379,8 @@ bool GpuContextSync(struct GpuContext* gpu_context) {
void GpuContextDestroy(struct GpuContext** gpu_context) {
if (!gpu_context || !*gpu_context) return;
- if ((*gpu_context)->vertices) glDeleteBuffers(1, &(*gpu_context)->vertices);
- if ((*gpu_context)->framebuffer)
- glDeleteFramebuffers(1, &(*gpu_context)->framebuffer);
- if ((*gpu_context)->program_chroma)
- glDeleteProgram((*gpu_context)->program_chroma);
- if ((*gpu_context)->program_luma)
- glDeleteProgram((*gpu_context)->program_luma);
+ if ((*gpu_context)->compute_program)
+ glDeleteProgram((*gpu_context)->compute_program);
if ((*gpu_context)->context != EGL_NO_CONTEXT) {
eglMakeCurrent((*gpu_context)->display, EGL_NO_SURFACE, EGL_NO_SURFACE,
EGL_NO_CONTEXT);
@@ -718,45 +661,19 @@ void GpuFrameGetSize(const struct GpuFrame* gpu_frame, uint32_t* width,
*height = gpu_frame->height;
}
-static bool GpuFrameConvertImpl(GLuint from, GLuint to) {
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
- to, 0);
- GLenum framebuffer_status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- if (framebuffer_status != GL_FRAMEBUFFER_COMPLETE) {
- LOG("Framebuffer is incomplete (0x%x)", framebuffer_status);
- return false;
- }
+bool GpuFrameConvert(const struct GpuFrame* from, const struct GpuFrame* to) {
+ glBindImageTexture(0, from->textures[0], 0, GL_FALSE, 0, GL_READ_ONLY,
+ GL_RGBA8);
+ glBindImageTexture(1, to->textures[0], 0, GL_FALSE, 0, GL_READ_ONLY,
+ GL_RGBA8);
+ glBindImageTexture(2, to->textures[1], 0, GL_FALSE, 0, GL_READ_ONLY,
+ GL_RGBA8);
+ glDispatchCompute(from->width / 2, from->height / 2, 1);
+ glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
- glBindTexture(GL_TEXTURE_2D, from);
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
GLenum error = glGetError();
if (error != GL_NO_ERROR) {
- LOG("Failed to convert plane (%s)", GlErrorString(error));
- return false;
- }
- return true;
-}
-
-bool GpuFrameConvert(const struct GpuFrame* from, const struct GpuFrame* to) {
- glUseProgram(from->gpu_context->program_luma);
- glViewport(0, 0, (GLsizei)to->width, (GLsizei)to->height);
- if (!GpuFrameConvertImpl(from->textures[0], to->textures[0])) {
- LOG("Failed to convert luma plane");
- return false;
- }
-
- const GLfloat sample_offsets[] = {
- _(0.f, 0.f),
- _(1.f / (GLfloat)from->width, 0.f),
- _(0.f, 1.f / (GLfloat)from->height),
- _(1.f / (GLfloat)from->width, 1.f / (GLfloat)from->height),
- };
-
- glUseProgram(from->gpu_context->program_chroma);
- glUniform2fv(from->gpu_context->sample_offsets, 4, sample_offsets);
- glViewport(0, 0, (GLsizei)to->width / 2, (GLsizei)to->height / 2);
- if (!GpuFrameConvertImpl(from->textures[0], to->textures[1])) {
- LOG("Failed to convert chroma plane");
+ LOG("Failed to dispatch compute (%s)", GlErrorString(glGetError()));
return false;
}
return true;