diff options
Diffstat (limited to 'gpu.c')
-rw-r--r-- | gpu.c | 165 |
1 files changed, 41 insertions, 124 deletions
@@ -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; |