blob: 008458bf94edba4b8bad31b619622d82c50a0287 [file] [log] [blame]
Gerd Hoffmann985e1c92015-04-24 07:48:45 +02001/*
2 * QEMU opengl shader helper functions
3 *
4 * Copyright (c) 2014 Red Hat
5 *
6 * Authors:
7 * Gerd Hoffmann <kraxel@redhat.com>
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 * THE SOFTWARE.
26 */
Peter Maydelle16f4c82016-01-29 17:49:51 +000027#include "qemu/osdep.h"
Gerd Hoffmann985e1c92015-04-24 07:48:45 +020028#include "qemu-common.h"
29#include "ui/shader.h"
30
Gerd Hoffmann46e19e12017-10-10 15:54:49 +020031#include "shader/texture-blit-vert.h"
Gerd Hoffmann2e1d70b2017-10-10 15:54:50 +020032#include "shader/texture-blit-flip-vert.h"
Gerd Hoffmann46e19e12017-10-10 15:54:49 +020033#include "shader/texture-blit-frag.h"
34
35struct QemuGLShader {
36 GLint texture_blit_prog;
Gerd Hoffmann2e1d70b2017-10-10 15:54:50 +020037 GLint texture_blit_flip_prog;
Gerd Hoffmann46e19e12017-10-10 15:54:49 +020038 GLint texture_blit_vao;
39};
40
Gerd Hoffmann985e1c92015-04-24 07:48:45 +020041/* ---------------------------------------------------------------------- */
42
Gerd Hoffmann46e19e12017-10-10 15:54:49 +020043static GLuint qemu_gl_init_texture_blit(GLint texture_blit_prog)
Gerd Hoffmanncd2bc882015-01-09 11:40:23 +010044{
Gerd Hoffmannc046d822015-07-10 14:40:01 +020045 static const GLfloat in_position[] = {
Gerd Hoffmanncd2bc882015-01-09 11:40:23 +010046 -1, -1,
47 1, -1,
48 -1, 1,
49 1, 1,
50 };
51 GLint l_position;
Gerd Hoffmannc046d822015-07-10 14:40:01 +020052 GLuint vao, buffer;
Gerd Hoffmanncd2bc882015-01-09 11:40:23 +010053
Gerd Hoffmannc046d822015-07-10 14:40:01 +020054 glGenVertexArrays(1, &vao);
55 glBindVertexArray(vao);
56
57 /* this is the VBO that holds the vertex data */
58 glGenBuffers(1, &buffer);
59 glBindBuffer(GL_ARRAY_BUFFER, buffer);
60 glBufferData(GL_ARRAY_BUFFER, sizeof(in_position), in_position,
61 GL_STATIC_DRAW);
62
Gerd Hoffmanncd2bc882015-01-09 11:40:23 +010063 l_position = glGetAttribLocation(texture_blit_prog, "in_position");
Gerd Hoffmannc046d822015-07-10 14:40:01 +020064 glVertexAttribPointer(l_position, 2, GL_FLOAT, GL_FALSE, 0, 0);
Gerd Hoffmanncd2bc882015-01-09 11:40:23 +010065 glEnableVertexAttribArray(l_position);
Gerd Hoffmannc046d822015-07-10 14:40:01 +020066
67 glBindBuffer(GL_ARRAY_BUFFER, 0);
68 glBindVertexArray(0);
69
70 return vao;
71}
72
Gerd Hoffmann2e1d70b2017-10-10 15:54:50 +020073void qemu_gl_run_texture_blit(QemuGLShader *gls, bool flip)
Gerd Hoffmannc046d822015-07-10 14:40:01 +020074{
Gerd Hoffmann2e1d70b2017-10-10 15:54:50 +020075 glUseProgram(flip
76 ? gls->texture_blit_flip_prog
77 : gls->texture_blit_prog);
Gerd Hoffmann46e19e12017-10-10 15:54:49 +020078 glBindVertexArray(gls->texture_blit_vao);
Gerd Hoffmannc046d822015-07-10 14:40:01 +020079 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
Gerd Hoffmanncd2bc882015-01-09 11:40:23 +010080}
81
82/* ---------------------------------------------------------------------- */
83
Gerd Hoffmann46e19e12017-10-10 15:54:49 +020084static GLuint qemu_gl_create_compile_shader(GLenum type, const GLchar *src)
Gerd Hoffmann985e1c92015-04-24 07:48:45 +020085{
86 GLuint shader;
87 GLint status, length;
88 char *errmsg;
89
90 shader = glCreateShader(type);
91 glShaderSource(shader, 1, &src, 0);
92 glCompileShader(shader);
93
94 glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
95 if (!status) {
96 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
Md Haris Iqbal42ddb8a2016-04-05 18:51:39 +053097 errmsg = g_malloc(length);
Gerd Hoffmann985e1c92015-04-24 07:48:45 +020098 glGetShaderInfoLog(shader, length, &length, errmsg);
99 fprintf(stderr, "%s: compile %s error\n%s\n", __func__,
100 (type == GL_VERTEX_SHADER) ? "vertex" : "fragment",
101 errmsg);
Md Haris Iqbal42ddb8a2016-04-05 18:51:39 +0530102 g_free(errmsg);
Gerd Hoffmann985e1c92015-04-24 07:48:45 +0200103 return 0;
104 }
105 return shader;
106}
107
Gerd Hoffmann46e19e12017-10-10 15:54:49 +0200108static GLuint qemu_gl_create_link_program(GLuint vert, GLuint frag)
Gerd Hoffmann985e1c92015-04-24 07:48:45 +0200109{
110 GLuint program;
111 GLint status, length;
112 char *errmsg;
113
114 program = glCreateProgram();
115 glAttachShader(program, vert);
116 glAttachShader(program, frag);
117 glLinkProgram(program);
118
119 glGetProgramiv(program, GL_LINK_STATUS, &status);
120 if (!status) {
121 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
Md Haris Iqbal42ddb8a2016-04-05 18:51:39 +0530122 errmsg = g_malloc(length);
Gerd Hoffmann985e1c92015-04-24 07:48:45 +0200123 glGetProgramInfoLog(program, length, &length, errmsg);
124 fprintf(stderr, "%s: link program: %s\n", __func__, errmsg);
Md Haris Iqbal42ddb8a2016-04-05 18:51:39 +0530125 g_free(errmsg);
Gerd Hoffmann985e1c92015-04-24 07:48:45 +0200126 return 0;
127 }
128 return program;
129}
130
Gerd Hoffmann46e19e12017-10-10 15:54:49 +0200131static GLuint qemu_gl_create_compile_link_program(const GLchar *vert_src,
132 const GLchar *frag_src)
Gerd Hoffmann985e1c92015-04-24 07:48:45 +0200133{
134 GLuint vert_shader, frag_shader, program;
135
136 vert_shader = qemu_gl_create_compile_shader(GL_VERTEX_SHADER, vert_src);
137 frag_shader = qemu_gl_create_compile_shader(GL_FRAGMENT_SHADER, frag_src);
138 if (!vert_shader || !frag_shader) {
139 return 0;
140 }
141
142 program = qemu_gl_create_link_program(vert_shader, frag_shader);
143 glDeleteShader(vert_shader);
144 glDeleteShader(frag_shader);
145
146 return program;
147}
Gerd Hoffmann46e19e12017-10-10 15:54:49 +0200148
149/* ---------------------------------------------------------------------- */
150
151QemuGLShader *qemu_gl_init_shader(void)
152{
153 QemuGLShader *gls = g_new0(QemuGLShader, 1);
154
155 gls->texture_blit_prog = qemu_gl_create_compile_link_program
156 (texture_blit_vert_src, texture_blit_frag_src);
Gerd Hoffmann2e1d70b2017-10-10 15:54:50 +0200157 gls->texture_blit_flip_prog = qemu_gl_create_compile_link_program
158 (texture_blit_flip_vert_src, texture_blit_frag_src);
159 if (!gls->texture_blit_prog || !gls->texture_blit_flip_prog) {
Gerd Hoffmann46e19e12017-10-10 15:54:49 +0200160 exit(1);
161 }
162
163 gls->texture_blit_vao =
164 qemu_gl_init_texture_blit(gls->texture_blit_prog);
165
166 return gls;
167}
168
169void qemu_gl_fini_shader(QemuGLShader *gls)
170{
171 if (!gls) {
172 return;
173 }
174 g_free(gls);
175}