blob: d36e7af232518962597bb54db859a6a3640639f2 [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"
32#include "shader/texture-blit-frag.h"
33
34struct QemuGLShader {
35 GLint texture_blit_prog;
36 GLint texture_blit_vao;
37};
38
Gerd Hoffmann985e1c92015-04-24 07:48:45 +020039/* ---------------------------------------------------------------------- */
40
Gerd Hoffmann46e19e12017-10-10 15:54:49 +020041static GLuint qemu_gl_init_texture_blit(GLint texture_blit_prog)
Gerd Hoffmanncd2bc882015-01-09 11:40:23 +010042{
Gerd Hoffmannc046d822015-07-10 14:40:01 +020043 static const GLfloat in_position[] = {
Gerd Hoffmanncd2bc882015-01-09 11:40:23 +010044 -1, -1,
45 1, -1,
46 -1, 1,
47 1, 1,
48 };
49 GLint l_position;
Gerd Hoffmannc046d822015-07-10 14:40:01 +020050 GLuint vao, buffer;
Gerd Hoffmanncd2bc882015-01-09 11:40:23 +010051
Gerd Hoffmannc046d822015-07-10 14:40:01 +020052 glGenVertexArrays(1, &vao);
53 glBindVertexArray(vao);
54
55 /* this is the VBO that holds the vertex data */
56 glGenBuffers(1, &buffer);
57 glBindBuffer(GL_ARRAY_BUFFER, buffer);
58 glBufferData(GL_ARRAY_BUFFER, sizeof(in_position), in_position,
59 GL_STATIC_DRAW);
60
Gerd Hoffmanncd2bc882015-01-09 11:40:23 +010061 l_position = glGetAttribLocation(texture_blit_prog, "in_position");
Gerd Hoffmannc046d822015-07-10 14:40:01 +020062 glVertexAttribPointer(l_position, 2, GL_FLOAT, GL_FALSE, 0, 0);
Gerd Hoffmanncd2bc882015-01-09 11:40:23 +010063 glEnableVertexAttribArray(l_position);
Gerd Hoffmannc046d822015-07-10 14:40:01 +020064
65 glBindBuffer(GL_ARRAY_BUFFER, 0);
66 glBindVertexArray(0);
67
68 return vao;
69}
70
Gerd Hoffmann46e19e12017-10-10 15:54:49 +020071void qemu_gl_run_texture_blit(QemuGLShader *gls)
Gerd Hoffmannc046d822015-07-10 14:40:01 +020072{
Gerd Hoffmann46e19e12017-10-10 15:54:49 +020073 glUseProgram(gls->texture_blit_prog);
74 glBindVertexArray(gls->texture_blit_vao);
Gerd Hoffmannc046d822015-07-10 14:40:01 +020075 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
Gerd Hoffmanncd2bc882015-01-09 11:40:23 +010076}
77
78/* ---------------------------------------------------------------------- */
79
Gerd Hoffmann46e19e12017-10-10 15:54:49 +020080static GLuint qemu_gl_create_compile_shader(GLenum type, const GLchar *src)
Gerd Hoffmann985e1c92015-04-24 07:48:45 +020081{
82 GLuint shader;
83 GLint status, length;
84 char *errmsg;
85
86 shader = glCreateShader(type);
87 glShaderSource(shader, 1, &src, 0);
88 glCompileShader(shader);
89
90 glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
91 if (!status) {
92 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
Md Haris Iqbal42ddb8a2016-04-05 18:51:39 +053093 errmsg = g_malloc(length);
Gerd Hoffmann985e1c92015-04-24 07:48:45 +020094 glGetShaderInfoLog(shader, length, &length, errmsg);
95 fprintf(stderr, "%s: compile %s error\n%s\n", __func__,
96 (type == GL_VERTEX_SHADER) ? "vertex" : "fragment",
97 errmsg);
Md Haris Iqbal42ddb8a2016-04-05 18:51:39 +053098 g_free(errmsg);
Gerd Hoffmann985e1c92015-04-24 07:48:45 +020099 return 0;
100 }
101 return shader;
102}
103
Gerd Hoffmann46e19e12017-10-10 15:54:49 +0200104static GLuint qemu_gl_create_link_program(GLuint vert, GLuint frag)
Gerd Hoffmann985e1c92015-04-24 07:48:45 +0200105{
106 GLuint program;
107 GLint status, length;
108 char *errmsg;
109
110 program = glCreateProgram();
111 glAttachShader(program, vert);
112 glAttachShader(program, frag);
113 glLinkProgram(program);
114
115 glGetProgramiv(program, GL_LINK_STATUS, &status);
116 if (!status) {
117 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
Md Haris Iqbal42ddb8a2016-04-05 18:51:39 +0530118 errmsg = g_malloc(length);
Gerd Hoffmann985e1c92015-04-24 07:48:45 +0200119 glGetProgramInfoLog(program, length, &length, errmsg);
120 fprintf(stderr, "%s: link program: %s\n", __func__, errmsg);
Md Haris Iqbal42ddb8a2016-04-05 18:51:39 +0530121 g_free(errmsg);
Gerd Hoffmann985e1c92015-04-24 07:48:45 +0200122 return 0;
123 }
124 return program;
125}
126
Gerd Hoffmann46e19e12017-10-10 15:54:49 +0200127static GLuint qemu_gl_create_compile_link_program(const GLchar *vert_src,
128 const GLchar *frag_src)
Gerd Hoffmann985e1c92015-04-24 07:48:45 +0200129{
130 GLuint vert_shader, frag_shader, program;
131
132 vert_shader = qemu_gl_create_compile_shader(GL_VERTEX_SHADER, vert_src);
133 frag_shader = qemu_gl_create_compile_shader(GL_FRAGMENT_SHADER, frag_src);
134 if (!vert_shader || !frag_shader) {
135 return 0;
136 }
137
138 program = qemu_gl_create_link_program(vert_shader, frag_shader);
139 glDeleteShader(vert_shader);
140 glDeleteShader(frag_shader);
141
142 return program;
143}
Gerd Hoffmann46e19e12017-10-10 15:54:49 +0200144
145/* ---------------------------------------------------------------------- */
146
147QemuGLShader *qemu_gl_init_shader(void)
148{
149 QemuGLShader *gls = g_new0(QemuGLShader, 1);
150
151 gls->texture_blit_prog = qemu_gl_create_compile_link_program
152 (texture_blit_vert_src, texture_blit_frag_src);
153 if (!gls->texture_blit_prog) {
154 exit(1);
155 }
156
157 gls->texture_blit_vao =
158 qemu_gl_init_texture_blit(gls->texture_blit_prog);
159
160 return gls;
161}
162
163void qemu_gl_fini_shader(QemuGLShader *gls)
164{
165 if (!gls) {
166 return;
167 }
168 g_free(gls);
169}