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