Created
April 1, 2023 18:39
-
-
Save fredldotme/066d8c7b42c5d6e825c0c3cd9740fff4 to your computer and use it in GitHub Desktop.
color correction WIP
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
static GLint | |
xwl_eglstream_compile_glsl_prog(GLenum type, const char *source) | |
{ | |
GLint ok; | |
GLint prog; | |
prog = glCreateShader(type); | |
glShaderSource(prog, 1, (const GLchar **) &source, NULL); | |
glCompileShader(prog); | |
glGetShaderiv(prog, GL_COMPILE_STATUS, &ok); | |
if (!ok) { | |
GLchar *info; | |
GLint size; | |
glGetShaderiv(prog, GL_INFO_LOG_LENGTH, &size); | |
info = malloc(size); | |
if (info) { | |
glGetShaderInfoLog(prog, size, NULL, info); | |
ErrorF("Failed to compile %s: %s\n", | |
type == GL_FRAGMENT_SHADER ? "FS" : "VS", info); | |
ErrorF("Program source:\n%s", source); | |
free(info); | |
} | |
else | |
ErrorF("Failed to get shader compilation info.\n"); | |
FatalError("GLSL compile failure\n"); | |
} | |
return prog; | |
} | |
static GLuint | |
xwl_eglstream_build_glsl_prog(GLuint vs, GLuint fs) | |
{ | |
GLint ok; | |
GLuint prog; | |
prog = glCreateProgram(); | |
glAttachShader(prog, vs); | |
glAttachShader(prog, fs); | |
glLinkProgram(prog); | |
glGetProgramiv(prog, GL_LINK_STATUS, &ok); | |
if (!ok) { | |
GLchar *info; | |
GLint size; | |
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &size); | |
info = malloc(size); | |
glGetProgramInfoLog(prog, size, NULL, info); | |
ErrorF("Failed to link: %s\n", info); | |
FatalError("GLSL link failure\n"); | |
} | |
return prog; | |
} | |
static inline void | |
xwl_eglstream_init_shaders(struct glamor_egl_screen_private *xwl_screen) | |
{ | |
GLint fs, vs, attrib; | |
const char *blit_vs_src = | |
"#version 100\n" | |
"attribute highp vec2 vertexCoord;\n" | |
"attribute highp vec2 textureCoord;\n" | |
"varying highp vec2 uv;\n" | |
"\n" | |
"void main() {\n" | |
" uv = textureCoord.xy;\n" | |
" gl_Position = vec4(vertexCoord, 0, 1);\n" | |
"}\n"; | |
const char *blit_fs_src = | |
"#version 100\n" | |
"\n" | |
"uniform sampler2D tex;\n" | |
"uniform bool is_rgba;\n" | |
"varying highp vec2 uv;\n" | |
"void main() {\n" | |
" if (is_rgba)\n" | |
" gl_FragColor = texture2D(tex, uv);\n" | |
" else\n" | |
" gl_FragColor = vec4(texture2D(tex, uv).rgb, 1.0);\n" | |
"}"; | |
static const GLfloat vertex_buffer_data[] = { | |
-1,-1, 0, | |
-1, 1, 0, | |
1,-1, 0, | |
-1, 1, 0, | |
1,-1, 0, | |
1, 1, 0 | |
}; | |
static const GLfloat texture_buffer_data[] = { | |
0, 0, | |
0, 1, | |
1, 0, | |
0, 1, | |
1, 0, | |
1, 1 | |
}; | |
vs = xwl_eglstream_compile_glsl_prog(GL_VERTEX_SHADER, blit_vs_src); | |
fs = xwl_eglstream_compile_glsl_prog(GL_FRAGMENT_SHADER, blit_fs_src); | |
xwl_screen->blit_prog = xwl_eglstream_build_glsl_prog(vs, fs); | |
glDeleteShader(vs); | |
glDeleteShader(fs); | |
/* Create the blitter's vao */ | |
glGenVertexArrays(1, &xwl_screen->blit_vao); | |
glBindVertexArray(xwl_screen->blit_vao); | |
/* Set the data for both position and texcoord in the vbo */ | |
glGenBuffers(2, xwl_screen->blit_vbos); | |
/* Vertex buffer data */ | |
glBindBuffer(GL_ARRAY_BUFFER, xwl_screen->blit_vbos[0]); | |
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_buffer_data), vertex_buffer_data, GL_STATIC_DRAW); | |
attrib = glGetAttribLocation(xwl_screen->blit_prog, "vertexCoord"); | |
glVertexAttribPointer(attrib, 3, GL_FLOAT, GL_TRUE, 0, 0); | |
glEnableVertexAttribArray(attrib); | |
/* Texture buffer data */ | |
glBindBuffer(GL_ARRAY_BUFFER, xwl_screen->blit_vbos[1]); | |
glBufferData(GL_ARRAY_BUFFER, sizeof(texture_buffer_data), texture_buffer_data, GL_STATIC_DRAW); | |
attrib = glGetAttribLocation(xwl_screen->blit_prog, "textureCoord"); | |
glVertexAttribPointer(attrib, 2, GL_FLOAT, GL_TRUE, 0, 0); | |
glEnableVertexAttribArray(attrib); | |
/* Save the location of uniforms we'll set later */ | |
xwl_screen->blit_is_rgba_pos = | |
glGetUniformLocation(xwl_screen->blit_prog, "is_rgba"); | |
xwl_screen->texture_pos = | |
glGetUniformLocation(xwl_screen->blit_prog, "tex"); | |
} | |
static PixmapPtr | |
xwl_glamor_hybris_create_pixmap_for_native_buffer(ScreenPtr screen, EGLClientBuffer buf, int width, int height, | |
int depth, int format, int stride) | |
{ | |
PixmapPtr pixmap; | |
struct xwl_pixmap *xwl_pixmap; | |
struct xwl_screen *xwl_screen = xwl_screen_get(screen); | |
GLuint tmp_fbo = 0, tmp_texture = 0; | |
GLint prev_fbo = 0; | |
GLenum draw_buffers[1] = {GL_COLOR_ATTACHMENT0}; | |
int status; | |
/* TODO: make use of this */ | |
const EGLint attrs[] = { | |
EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, | |
EGL_NONE | |
}; | |
xwl_pixmap = malloc(sizeof *xwl_pixmap); | |
if (xwl_pixmap == NULL) | |
return NULL; | |
pixmap = glamor_create_pixmap(screen, | |
width, | |
height, | |
depth, | |
GLAMOR_CREATE_PIXMAP_NO_TEXTURE); | |
if (!pixmap) { | |
free(xwl_pixmap); | |
return NULL; | |
} | |
xwl_glamor_egl_make_current(xwl_screen); | |
xwl_pixmap->buf = buf; | |
xwl_pixmap->buffer = NULL; | |
xwl_pixmap->stride = stride; | |
xwl_pixmap->format = format; | |
xwl_pixmap->image = eglCreateImageKHR(xwl_screen->egl_display, | |
EGL_NO_CONTEXT, | |
EGL_NATIVE_BUFFER_HYBRIS, | |
xwl_pixmap->buf, NULL); | |
if (xwl_pixmap->image == EGL_NO_IMAGE_KHR) | |
goto error; | |
/* Save current GL state */ | |
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prev_fbo); | |
/* Set up receiving texture and temporaries */ | |
glGenTextures(1, &xwl_pixmap->texture); | |
glGenTextures(1, &tmp_texture); | |
glGenFramebuffers(1, &tmp_fbo); | |
/* Use the xwl_pixmap's texture as the receiving end of the render pipeline */ | |
glBindTexture(GL_TEXTURE_2D, xwl_pixmap->texture); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | |
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); | |
glBindTexture(GL_TEXTURE_2D, 0); | |
/* Bind receiving texture as the FBO's color attachment */ | |
glBindFramebuffer(GL_FRAMEBUFFER, tmp_fbo); | |
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, xwl_pixmap->texture, 0); | |
glDrawBuffers(1, draw_buffers); | |
status = glCheckFramebufferStatus(GL_FRAMEBUFFER); | |
if (status != GL_FRAMEBUFFER_COMPLETE) { | |
ErrorF("hybris: Framebuffer incomplete 0x%X, not color-converting native buffer\n", status); | |
goto error; | |
} | |
/* Take the opportunity to set up the shader and temporary texture */ | |
glUseProgram(glamor_egl->blit_prog); | |
glActiveTexture(GL_TEXTURE0); | |
glBindTexture(GL_TEXTURE_2D, tmp_texture); | |
glBindVertexArray(glamor_egl->blit_vao); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | |
glUniform1i(glamor_egl->texture_pos, 0); | |
glUniform1i(glamor_egl->blit_is_rgba_pos, depth >= 32); | |
/* Dump the EGLImage onto texture */ | |
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, xwl_pixmap->image); | |
if ((status = eglGetError()) != EGL_SUCCESS) { | |
ErrorF("hybris: Failed to dump EGLImage onto texture, 0x%X\n", status); | |
goto error; | |
} | |
/* And draw */ | |
glDrawArrays(GL_TRIANGLES, 0, 6); | |
glViewport(0, 0, width, height); | |
/* Rendering complete, reset state */ | |
glBindFramebuffer(GL_FRAMEBUFFER, 0); | |
glBindTexture(GL_TEXTURE_2D, 0); | |
glBindVertexArray(0); | |
glUseProgram(0); | |
glDeleteFramebuffers(1, &tmp_fbo); | |
glDeleteTextures(1, &tmp_texture); | |
glamor_set_pixmap_texture(pixmap, xwl_pixmap->texture); | |
/* `set_pixmap_texture()` may fail silently if the FBO creation failed, | |
* so we check again the texture to be sure it worked. | |
*/ | |
if (!glamor_get_pixmap_texture(pixmap)) { | |
ErrorF("hybris: Setting pixmap texture failed\n"); | |
goto error; | |
} | |
glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_ONLY); | |
xwl_pixmap_set_private(pixmap, xwl_pixmap); | |
return pixmap; | |
error: | |
glBindFramebuffer(GL_FRAMEBUFFER, prev_fbo); | |
if (tmp_fbo != 0) | |
glDeleteFramebuffers(1, &tmp_fbo); | |
if (tmp_texture != 0) | |
glDeleteTextures(1, &tmp_texture); | |
if (xwl_pixmap->image != EGL_NO_IMAGE_KHR) | |
eglDestroyImageKHR(xwl_screen->egl_display, xwl_pixmap->image); | |
if (pixmap) | |
glamor_destroy_pixmap(pixmap); | |
free(xwl_pixmap); | |
return NULL; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment