1 /* 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 */ 27 #include "qemu/osdep.h" 28 #include "qemu-common.h" 29 #include "ui/shader.h" 30 31 #include "shader/texture-blit-vert.h" 32 #include "shader/texture-blit-flip-vert.h" 33 #include "shader/texture-blit-frag.h" 34 35 struct QemuGLShader { 36 GLint texture_blit_prog; 37 GLint texture_blit_flip_prog; 38 GLint texture_blit_vao; 39 }; 40 41 /* ---------------------------------------------------------------------- */ 42 43 static GLuint qemu_gl_init_texture_blit(GLint texture_blit_prog) 44 { 45 static const GLfloat in_position[] = { 46 -1, -1, 47 1, -1, 48 -1, 1, 49 1, 1, 50 }; 51 GLint l_position; 52 GLuint vao, buffer; 53 54 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 63 l_position = glGetAttribLocation(texture_blit_prog, "in_position"); 64 glVertexAttribPointer(l_position, 2, GL_FLOAT, GL_FALSE, 0, 0); 65 glEnableVertexAttribArray(l_position); 66 67 glBindBuffer(GL_ARRAY_BUFFER, 0); 68 glBindVertexArray(0); 69 70 return vao; 71 } 72 73 void qemu_gl_run_texture_blit(QemuGLShader *gls, bool flip) 74 { 75 glUseProgram(flip 76 ? gls->texture_blit_flip_prog 77 : gls->texture_blit_prog); 78 glBindVertexArray(gls->texture_blit_vao); 79 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 80 } 81 82 /* ---------------------------------------------------------------------- */ 83 84 static GLuint qemu_gl_create_compile_shader(GLenum type, const GLchar *src) 85 { 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); 97 errmsg = g_malloc(length); 98 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); 102 g_free(errmsg); 103 return 0; 104 } 105 return shader; 106 } 107 108 static GLuint qemu_gl_create_link_program(GLuint vert, GLuint frag) 109 { 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); 122 errmsg = g_malloc(length); 123 glGetProgramInfoLog(program, length, &length, errmsg); 124 fprintf(stderr, "%s: link program: %s\n", __func__, errmsg); 125 g_free(errmsg); 126 return 0; 127 } 128 return program; 129 } 130 131 static GLuint qemu_gl_create_compile_link_program(const GLchar *vert_src, 132 const GLchar *frag_src) 133 { 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 } 148 149 /* ---------------------------------------------------------------------- */ 150 151 QemuGLShader *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); 157 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) { 160 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 169 void qemu_gl_fini_shader(QemuGLShader *gls) 170 { 171 if (!gls) { 172 return; 173 } 174 g_free(gls); 175 } 176