xref: /qemu/ui/shader.c (revision 532042d5)
1985e1c9bSGerd Hoffmann /*
2985e1c9bSGerd Hoffmann  * QEMU opengl shader helper functions
3985e1c9bSGerd Hoffmann  *
4985e1c9bSGerd Hoffmann  * Copyright (c) 2014 Red Hat
5985e1c9bSGerd Hoffmann  *
6985e1c9bSGerd Hoffmann  * Authors:
7985e1c9bSGerd Hoffmann  *    Gerd Hoffmann <kraxel@redhat.com>
8985e1c9bSGerd Hoffmann  *
9985e1c9bSGerd Hoffmann  * Permission is hereby granted, free of charge, to any person obtaining a copy
10985e1c9bSGerd Hoffmann  * of this software and associated documentation files (the "Software"), to deal
11985e1c9bSGerd Hoffmann  * in the Software without restriction, including without limitation the rights
12985e1c9bSGerd Hoffmann  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13985e1c9bSGerd Hoffmann  * copies of the Software, and to permit persons to whom the Software is
14985e1c9bSGerd Hoffmann  * furnished to do so, subject to the following conditions:
15985e1c9bSGerd Hoffmann  *
16985e1c9bSGerd Hoffmann  * The above copyright notice and this permission notice shall be included in
17985e1c9bSGerd Hoffmann  * all copies or substantial portions of the Software.
18985e1c9bSGerd Hoffmann  *
19985e1c9bSGerd Hoffmann  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20985e1c9bSGerd Hoffmann  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21985e1c9bSGerd Hoffmann  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22985e1c9bSGerd Hoffmann  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23985e1c9bSGerd Hoffmann  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24985e1c9bSGerd Hoffmann  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25985e1c9bSGerd Hoffmann  * THE SOFTWARE.
26985e1c9bSGerd Hoffmann  */
27e16f4c87SPeter Maydell #include "qemu/osdep.h"
28985e1c9bSGerd Hoffmann #include "ui/shader.h"
29985e1c9bSGerd Hoffmann 
302b1ccdf4SMarc-André Lureau #include "ui/shader/texture-blit-vert.h"
312b1ccdf4SMarc-André Lureau #include "ui/shader/texture-blit-flip-vert.h"
322b1ccdf4SMarc-André Lureau #include "ui/shader/texture-blit-frag.h"
3346e19e14SGerd Hoffmann 
3446e19e14SGerd Hoffmann struct QemuGLShader {
3546e19e14SGerd Hoffmann     GLint texture_blit_prog;
362e1d70b9SGerd Hoffmann     GLint texture_blit_flip_prog;
3746e19e14SGerd Hoffmann     GLint texture_blit_vao;
3846e19e14SGerd Hoffmann };
3946e19e14SGerd Hoffmann 
40985e1c9bSGerd Hoffmann /* ---------------------------------------------------------------------- */
41985e1c9bSGerd Hoffmann 
qemu_gl_init_texture_blit(GLint texture_blit_prog)4246e19e14SGerd Hoffmann static GLuint qemu_gl_init_texture_blit(GLint texture_blit_prog)
43cd2bc889SGerd Hoffmann {
44c046d828SGerd Hoffmann     static const GLfloat in_position[] = {
45cd2bc889SGerd Hoffmann         -1, -1,
46cd2bc889SGerd Hoffmann         1,  -1,
47cd2bc889SGerd Hoffmann         -1,  1,
48cd2bc889SGerd Hoffmann         1,   1,
49cd2bc889SGerd Hoffmann     };
50cd2bc889SGerd Hoffmann     GLint l_position;
51c046d828SGerd Hoffmann     GLuint vao, buffer;
52cd2bc889SGerd Hoffmann 
53c046d828SGerd Hoffmann     glGenVertexArrays(1, &vao);
54c046d828SGerd Hoffmann     glBindVertexArray(vao);
55c046d828SGerd Hoffmann 
56c046d828SGerd Hoffmann     /* this is the VBO that holds the vertex data */
57c046d828SGerd Hoffmann     glGenBuffers(1, &buffer);
58c046d828SGerd Hoffmann     glBindBuffer(GL_ARRAY_BUFFER, buffer);
59c046d828SGerd Hoffmann     glBufferData(GL_ARRAY_BUFFER, sizeof(in_position), in_position,
60c046d828SGerd Hoffmann                  GL_STATIC_DRAW);
61c046d828SGerd Hoffmann 
62cd2bc889SGerd Hoffmann     l_position = glGetAttribLocation(texture_blit_prog, "in_position");
63c046d828SGerd Hoffmann     glVertexAttribPointer(l_position, 2, GL_FLOAT, GL_FALSE, 0, 0);
64cd2bc889SGerd Hoffmann     glEnableVertexAttribArray(l_position);
65c046d828SGerd Hoffmann 
66c046d828SGerd Hoffmann     glBindBuffer(GL_ARRAY_BUFFER, 0);
67c046d828SGerd Hoffmann     glBindVertexArray(0);
68c046d828SGerd Hoffmann 
69c046d828SGerd Hoffmann     return vao;
70c046d828SGerd Hoffmann }
71c046d828SGerd Hoffmann 
qemu_gl_run_texture_blit(QemuGLShader * gls,bool flip)722e1d70b9SGerd Hoffmann void qemu_gl_run_texture_blit(QemuGLShader *gls, bool flip)
73c046d828SGerd Hoffmann {
742e1d70b9SGerd Hoffmann     glUseProgram(flip
752e1d70b9SGerd Hoffmann                  ? gls->texture_blit_flip_prog
762e1d70b9SGerd Hoffmann                  : gls->texture_blit_prog);
7746e19e14SGerd Hoffmann     glBindVertexArray(gls->texture_blit_vao);
78c046d828SGerd Hoffmann     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
79cd2bc889SGerd Hoffmann }
80cd2bc889SGerd Hoffmann 
81cd2bc889SGerd Hoffmann /* ---------------------------------------------------------------------- */
82cd2bc889SGerd Hoffmann 
qemu_gl_create_compile_shader(GLenum type,const GLchar * src)8346e19e14SGerd Hoffmann static GLuint qemu_gl_create_compile_shader(GLenum type, const GLchar *src)
84985e1c9bSGerd Hoffmann {
85985e1c9bSGerd Hoffmann     GLuint shader;
86985e1c9bSGerd Hoffmann     GLint status, length;
87985e1c9bSGerd Hoffmann     char *errmsg;
88985e1c9bSGerd Hoffmann 
89985e1c9bSGerd Hoffmann     shader = glCreateShader(type);
90985e1c9bSGerd Hoffmann     glShaderSource(shader, 1, &src, 0);
91985e1c9bSGerd Hoffmann     glCompileShader(shader);
92985e1c9bSGerd Hoffmann 
93985e1c9bSGerd Hoffmann     glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
94985e1c9bSGerd Hoffmann     if (!status) {
95985e1c9bSGerd Hoffmann         glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
9642ddb8aaSMd Haris Iqbal         errmsg = g_malloc(length);
97985e1c9bSGerd Hoffmann         glGetShaderInfoLog(shader, length, &length, errmsg);
98985e1c9bSGerd Hoffmann         fprintf(stderr, "%s: compile %s error\n%s\n", __func__,
99985e1c9bSGerd Hoffmann                 (type == GL_VERTEX_SHADER) ? "vertex" : "fragment",
100985e1c9bSGerd Hoffmann                 errmsg);
10142ddb8aaSMd Haris Iqbal         g_free(errmsg);
102985e1c9bSGerd Hoffmann         return 0;
103985e1c9bSGerd Hoffmann     }
104985e1c9bSGerd Hoffmann     return shader;
105985e1c9bSGerd Hoffmann }
106985e1c9bSGerd Hoffmann 
qemu_gl_create_link_program(GLuint vert,GLuint frag)10746e19e14SGerd Hoffmann static GLuint qemu_gl_create_link_program(GLuint vert, GLuint frag)
108985e1c9bSGerd Hoffmann {
109985e1c9bSGerd Hoffmann     GLuint program;
110985e1c9bSGerd Hoffmann     GLint status, length;
111985e1c9bSGerd Hoffmann     char *errmsg;
112985e1c9bSGerd Hoffmann 
113985e1c9bSGerd Hoffmann     program = glCreateProgram();
114985e1c9bSGerd Hoffmann     glAttachShader(program, vert);
115985e1c9bSGerd Hoffmann     glAttachShader(program, frag);
116985e1c9bSGerd Hoffmann     glLinkProgram(program);
117985e1c9bSGerd Hoffmann 
118985e1c9bSGerd Hoffmann     glGetProgramiv(program, GL_LINK_STATUS, &status);
119985e1c9bSGerd Hoffmann     if (!status) {
120985e1c9bSGerd Hoffmann         glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
12142ddb8aaSMd Haris Iqbal         errmsg = g_malloc(length);
122985e1c9bSGerd Hoffmann         glGetProgramInfoLog(program, length, &length, errmsg);
123985e1c9bSGerd Hoffmann         fprintf(stderr, "%s: link program: %s\n", __func__, errmsg);
12442ddb8aaSMd Haris Iqbal         g_free(errmsg);
125985e1c9bSGerd Hoffmann         return 0;
126985e1c9bSGerd Hoffmann     }
127985e1c9bSGerd Hoffmann     return program;
128985e1c9bSGerd Hoffmann }
129985e1c9bSGerd Hoffmann 
qemu_gl_create_compile_link_program(const GLchar * vert_src,const GLchar * frag_src)13046e19e14SGerd Hoffmann static GLuint qemu_gl_create_compile_link_program(const GLchar *vert_src,
131985e1c9bSGerd Hoffmann                                                   const GLchar *frag_src)
132985e1c9bSGerd Hoffmann {
1338fe496adSMarc-André Lureau     GLuint vert_shader, frag_shader, program = 0;
134985e1c9bSGerd Hoffmann 
135985e1c9bSGerd Hoffmann     vert_shader = qemu_gl_create_compile_shader(GL_VERTEX_SHADER, vert_src);
136985e1c9bSGerd Hoffmann     frag_shader = qemu_gl_create_compile_shader(GL_FRAGMENT_SHADER, frag_src);
137985e1c9bSGerd Hoffmann     if (!vert_shader || !frag_shader) {
1388fe496adSMarc-André Lureau         goto end;
139985e1c9bSGerd Hoffmann     }
140985e1c9bSGerd Hoffmann 
141985e1c9bSGerd Hoffmann     program = qemu_gl_create_link_program(vert_shader, frag_shader);
1428fe496adSMarc-André Lureau 
1438fe496adSMarc-André Lureau end:
144985e1c9bSGerd Hoffmann     glDeleteShader(vert_shader);
145985e1c9bSGerd Hoffmann     glDeleteShader(frag_shader);
146985e1c9bSGerd Hoffmann 
147985e1c9bSGerd Hoffmann     return program;
148985e1c9bSGerd Hoffmann }
14946e19e14SGerd Hoffmann 
15046e19e14SGerd Hoffmann /* ---------------------------------------------------------------------- */
15146e19e14SGerd Hoffmann 
qemu_gl_init_shader(void)15246e19e14SGerd Hoffmann QemuGLShader *qemu_gl_init_shader(void)
15346e19e14SGerd Hoffmann {
15446e19e14SGerd Hoffmann     QemuGLShader *gls = g_new0(QemuGLShader, 1);
15546e19e14SGerd Hoffmann 
15646e19e14SGerd Hoffmann     gls->texture_blit_prog = qemu_gl_create_compile_link_program
15746e19e14SGerd Hoffmann         (texture_blit_vert_src, texture_blit_frag_src);
1582e1d70b9SGerd Hoffmann     gls->texture_blit_flip_prog = qemu_gl_create_compile_link_program
1592e1d70b9SGerd Hoffmann         (texture_blit_flip_vert_src, texture_blit_frag_src);
1602e1d70b9SGerd Hoffmann     if (!gls->texture_blit_prog || !gls->texture_blit_flip_prog) {
16146e19e14SGerd Hoffmann         exit(1);
16246e19e14SGerd Hoffmann     }
16346e19e14SGerd Hoffmann 
16446e19e14SGerd Hoffmann     gls->texture_blit_vao =
16546e19e14SGerd Hoffmann         qemu_gl_init_texture_blit(gls->texture_blit_prog);
16646e19e14SGerd Hoffmann 
16746e19e14SGerd Hoffmann     return gls;
16846e19e14SGerd Hoffmann }
16946e19e14SGerd Hoffmann 
qemu_gl_fini_shader(QemuGLShader * gls)17046e19e14SGerd Hoffmann void qemu_gl_fini_shader(QemuGLShader *gls)
17146e19e14SGerd Hoffmann {
17246e19e14SGerd Hoffmann     if (!gls) {
17346e19e14SGerd Hoffmann         return;
17446e19e14SGerd Hoffmann     }
175*532042d5SMarc-André Lureau     glDeleteProgram(gls->texture_blit_prog);
176*532042d5SMarc-André Lureau     glDeleteProgram(gls->texture_blit_flip_prog);
177*532042d5SMarc-André Lureau     glDeleteProgram(gls->texture_blit_vao);
17846e19e14SGerd Hoffmann     g_free(gls);
17946e19e14SGerd Hoffmann }
180