]> git.proxmox.com Git - mirror_qemu.git/blobdiff - ui/shader.c
Merge tag 'pull-maintainer-may24-160524-2' of https://gitlab.com/stsquad/qemu into...
[mirror_qemu.git] / ui / shader.c
index 52a46329307c1ba57e988c30f89b46f7726c2652..ab448c41d4c67b6db48623ba26b5c2994d6900e1 100644 (file)
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "qemu-common.h"
+#include "qemu/osdep.h"
 #include "ui/shader.h"
 
+#include "ui/shader/texture-blit-vert.h"
+#include "ui/shader/texture-blit-flip-vert.h"
+#include "ui/shader/texture-blit-frag.h"
+
+struct QemuGLShader {
+    GLint texture_blit_prog;
+    GLint texture_blit_flip_prog;
+    GLint texture_blit_vao;
+};
+
 /* ---------------------------------------------------------------------- */
 
-void qemu_gl_run_texture_blit(GLint texture_blit_prog)
+static GLuint qemu_gl_init_texture_blit(GLint texture_blit_prog)
 {
-    GLfloat in_position[] = {
+    static const GLfloat in_position[] = {
         -1, -1,
         1,  -1,
         -1,  1,
         1,   1,
     };
     GLint l_position;
+    GLuint vao, buffer;
+
+    glGenVertexArrays(1, &vao);
+    glBindVertexArray(vao);
+
+    /* this is the VBO that holds the vertex data */
+    glGenBuffers(1, &buffer);
+    glBindBuffer(GL_ARRAY_BUFFER, buffer);
+    glBufferData(GL_ARRAY_BUFFER, sizeof(in_position), in_position,
+                 GL_STATIC_DRAW);
 
-    glUseProgram(texture_blit_prog);
     l_position = glGetAttribLocation(texture_blit_prog, "in_position");
-    glVertexAttribPointer(l_position, 2, GL_FLOAT, GL_FALSE, 0, in_position);
+    glVertexAttribPointer(l_position, 2, GL_FLOAT, GL_FALSE, 0, 0);
     glEnableVertexAttribArray(l_position);
-    glDrawArrays(GL_TRIANGLE_STRIP, l_position, 4);
+
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+    glBindVertexArray(0);
+
+    return vao;
+}
+
+void qemu_gl_run_texture_blit(QemuGLShader *gls, bool flip)
+{
+    glUseProgram(flip
+                 ? gls->texture_blit_flip_prog
+                 : gls->texture_blit_prog);
+    glBindVertexArray(gls->texture_blit_vao);
+    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
 }
 
 /* ---------------------------------------------------------------------- */
 
-GLuint qemu_gl_create_compile_shader(GLenum type, const GLchar *src)
+static GLuint qemu_gl_create_compile_shader(GLenum type, const GLchar *src)
 {
     GLuint shader;
     GLint status, length;
@@ -61,18 +93,18 @@ GLuint qemu_gl_create_compile_shader(GLenum type, const GLchar *src)
     glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
     if (!status) {
         glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
-        errmsg = malloc(length);
+        errmsg = g_malloc(length);
         glGetShaderInfoLog(shader, length, &length, errmsg);
         fprintf(stderr, "%s: compile %s error\n%s\n", __func__,
                 (type == GL_VERTEX_SHADER) ? "vertex" : "fragment",
                 errmsg);
-        free(errmsg);
+        g_free(errmsg);
         return 0;
     }
     return shader;
 }
 
-GLuint qemu_gl_create_link_program(GLuint vert, GLuint frag)
+static GLuint qemu_gl_create_link_program(GLuint vert, GLuint frag)
 {
     GLuint program;
     GLint status, length;
@@ -86,29 +118,62 @@ GLuint qemu_gl_create_link_program(GLuint vert, GLuint frag)
     glGetProgramiv(program, GL_LINK_STATUS, &status);
     if (!status) {
         glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
-        errmsg = malloc(length);
+        errmsg = g_malloc(length);
         glGetProgramInfoLog(program, length, &length, errmsg);
         fprintf(stderr, "%s: link program: %s\n", __func__, errmsg);
-        free(errmsg);
+        g_free(errmsg);
         return 0;
     }
     return program;
 }
 
-GLuint qemu_gl_create_compile_link_program(const GLchar *vert_src,
-                                           const GLchar *frag_src)
+static GLuint qemu_gl_create_compile_link_program(const GLchar *vert_src,
+                                                  const GLchar *frag_src)
 {
-    GLuint vert_shader, frag_shader, program;
+    GLuint vert_shader, frag_shader, program = 0;
 
     vert_shader = qemu_gl_create_compile_shader(GL_VERTEX_SHADER, vert_src);
     frag_shader = qemu_gl_create_compile_shader(GL_FRAGMENT_SHADER, frag_src);
     if (!vert_shader || !frag_shader) {
-        return 0;
+        goto end;
     }
 
     program = qemu_gl_create_link_program(vert_shader, frag_shader);
+
+end:
     glDeleteShader(vert_shader);
     glDeleteShader(frag_shader);
 
     return program;
 }
+
+/* ---------------------------------------------------------------------- */
+
+QemuGLShader *qemu_gl_init_shader(void)
+{
+    QemuGLShader *gls = g_new0(QemuGLShader, 1);
+
+    gls->texture_blit_prog = qemu_gl_create_compile_link_program
+        (texture_blit_vert_src, texture_blit_frag_src);
+    gls->texture_blit_flip_prog = qemu_gl_create_compile_link_program
+        (texture_blit_flip_vert_src, texture_blit_frag_src);
+    if (!gls->texture_blit_prog || !gls->texture_blit_flip_prog) {
+        exit(1);
+    }
+
+    gls->texture_blit_vao =
+        qemu_gl_init_texture_blit(gls->texture_blit_prog);
+
+    return gls;
+}
+
+void qemu_gl_fini_shader(QemuGLShader *gls)
+{
+    if (!gls) {
+        return;
+    }
+    glDeleteProgram(gls->texture_blit_prog);
+    glDeleteProgram(gls->texture_blit_flip_prog);
+    glDeleteProgram(gls->texture_blit_vao);
+    g_free(gls);
+}