4 * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
7 * Stanislav Vorobiov <s.vorobiov@samsung.com>
8 * Jinhyung Jo <jinhyung.jo@samsung.com>
9 * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
30 #include "vigs_gl_backend.h"
31 #include "vigs_gl_pool.h"
32 #include "vigs_surface.h"
33 #include "vigs_plane.h"
35 #include "vigs_utils.h"
38 #include "winsys_gl.h"
42 #include "drm/drm_fourcc.h"
44 #define MAKE_FOURCC(a, b, c, d) (((unsigned int)(a)) | \
45 (((unsigned int)(b)) << 8) | \
46 (((unsigned int)(c)) << 16) | \
47 (((unsigned int)(d)) << 24))
48 #define DRM_FORMAT_ARGB8888 MAKE_FOURCC('A', 'R', '2', '4')
49 #define DRM_FORMAT_YUV420 MAKE_FOURCC('Y', 'U', '1', '2')
50 #define DRM_FORMAT_XBGR8888 MAKE_FOURCC('X', 'B', '2', '4')
53 struct vigs_gl_surface;
55 struct vigs_winsys_gl_surface
57 struct winsys_gl_surface base;
61 struct vigs_gl_backend *backend;
64 * Will be set to NULL when orphaned.
66 struct vigs_gl_surface *parent;
73 GLint tex_internalformat;
82 * Texture that represent this surface.
83 * Used as color attachment in 'fb'.
85 * Allocated on first access.
90 struct vigs_gl_surface
92 struct vigs_surface base;
95 * Framebuffer that is used for rendering
98 * Allocated on first access.
103 * Texture for temporary storage.
105 * Allocated on first access.
110 * Ortho matrix for this surface.
116 * YUV conversion shader
118 GLuint yuv_textures[3];
121 static __inline struct vigs_winsys_gl_surface
122 *get_ws_sfc(struct vigs_gl_surface *sfc)
124 return (struct vigs_winsys_gl_surface*)sfc->base.ws_sfc;
132 static const char *g_vs_tex_source_gl2 =
134 "attribute vec4 vertCoord;\n"
135 "uniform mat4 proj;\n"
136 "attribute vec2 texCoord;\n"
137 "varying vec2 v_texCoord;\n"
140 " v_texCoord = texCoord;\n"
141 " gl_Position = proj * vertCoord;\n"
144 static const char *g_vs_tex_source_gl3 =
146 "in vec4 vertCoord;\n"
147 "uniform mat4 proj;\n"
148 "in vec2 texCoord;\n"
149 "out vec2 v_texCoord;\n"
152 " v_texCoord = texCoord;\n"
153 " gl_Position = proj * vertCoord;\n"
156 static const char *g_fs_tex_source_gl2 =
158 "uniform sampler2D tex;\n"
159 "varying vec2 v_texCoord;\n"
162 " gl_FragColor = texture2D(tex, v_texCoord);\n"
165 static const char *g_fs_tex_source_gl3 =
167 "uniform sampler2D tex;\n"
168 "in vec2 v_texCoord;\n"
169 "out vec4 FragColor;\n"
172 " FragColor = texture(tex, v_texCoord);\n"
175 static const char *g_vs_color_source_gl2 =
177 "attribute vec4 vertCoord;\n"
178 "uniform mat4 proj;\n"
181 " gl_Position = proj * vertCoord;\n"
184 static const char *g_vs_color_source_gl3 =
186 "in vec4 vertCoord;\n"
187 "uniform mat4 proj;\n"
190 " gl_Position = proj * vertCoord;\n"
193 static const char *g_fs_color_source_gl2 =
195 "uniform vec4 color;\n"
198 " gl_FragColor = color;\n"
201 static const char *g_fs_color_source_gl3 =
203 "uniform vec4 color;\n"
204 "out vec4 FragColor;\n"
207 " FragColor = color;\n"
210 static const char *g_vs_nv21_source_gl2 =
212 "attribute vec4 vertCoord;\n"
213 "uniform mat4 proj;\n"
214 "attribute vec2 texCoord;\n"
215 "varying vec2 v_texCoord;\n"
218 " v_texCoord = texCoord;\n"
219 " gl_Position = proj * vertCoord;\n"
222 static const char *g_vs_nv21_source_gl3 =
224 "in vec4 vertCoord;\n"
225 "uniform mat4 proj;\n"
226 "in vec2 texCoord;\n"
227 "out vec2 v_texCoord;\n"
230 " v_texCoord = texCoord;\n"
231 " gl_Position = proj * vertCoord;\n"
234 static const char *g_fs_nv21_source_gl2 =
236 "uniform sampler2D ytex;\n"
237 "uniform sampler2D ctex;\n"
238 "uniform vec2 size;\n"
239 "uniform vec2 ytexSize;\n"
240 "uniform vec2 ctexSize;\n"
241 "varying vec2 v_texCoord;\n"
244 " float ypos = floor((1.0 - v_texCoord.y) * size.y) * size.x + floor(v_texCoord.x * size.x);\n"
245 " float ytexPos = floor(ypos / 4);\n"
246 " vec4 ytexColor = texture2D(ytex, vec2((mod(ytexPos, ytexSize.x) + 0.5) / ytexSize.x, 1.0 - (floor(ytexPos / ytexSize.x) + 0.5) / ytexSize.y));\n"
247 " float y = ytexColor[3 - int(mod(ypos + 1, 4))];\n"
248 " float cpos = floor(floor((1.0 - v_texCoord.y) * size.y) / 2) * size.x + floor(v_texCoord.x * size.x);\n"
249 " float ctexPos = floor(cpos / 4);\n"
250 " vec4 ctexColor = texture2D(ctex, vec2((mod(ctexPos, ctexSize.x) + 0.5) / ctexSize.x, 1.0 - (floor(ctexPos / ctexSize.x) + 0.5) / ctexSize.y));\n"
251 " int index = 2 * int(mod(floor(cpos / 2) + 1, 2));"
252 " float u = ctexColor[index];\n"
253 " float v = ctexColor[3 - index];\n"
256 " gl_FragColor = vec4(y + 1.59765625 * v, y - 0.390625 * u - 0.8125 * v, y + 2.015625 * u, 1.0);\n"
259 static const char *g_fs_nv21_source_gl3 =
261 "uniform sampler2D ytex;\n"
262 "uniform sampler2D ctex;\n"
263 "uniform vec2 size;\n"
264 "uniform vec2 ytexSize;\n"
265 "uniform vec2 ctexSize;\n"
266 "in vec2 v_texCoord;\n"
267 "out vec4 FragColor;\n"
270 " float ypos = floor((1.0 - v_texCoord.y) * size.y) * size.x + floor(v_texCoord.x * size.x);\n"
271 " float ytexPos = floor(ypos / 4);\n"
272 " vec4 ytexColor = texture(ytex, vec2((mod(ytexPos, ytexSize.x) + 0.5) / ytexSize.x, 1.0 - (floor(ytexPos / ytexSize.x) + 0.5) / ytexSize.y));\n"
273 " float y = ytexColor[3 - int(mod(ypos + 1, 4))];\n"
274 " float cpos = floor(floor((1.0 - v_texCoord.y) * size.y) / 2) * size.x + floor(v_texCoord.x * size.x);\n"
275 " float ctexPos = floor(cpos / 4);\n"
276 " vec4 ctexColor = texture(ctex, vec2((mod(ctexPos, ctexSize.x) + 0.5) / ctexSize.x, 1.0 - (floor(ctexPos / ctexSize.x) + 0.5) / ctexSize.y));\n"
277 " int index = 2 * int(mod(floor(cpos / 2) + 1, 2));"
278 " float u = ctexColor[index];\n"
279 " float v = ctexColor[3 - index];\n"
282 " FragColor = vec4(y + 1.59765625 * v, y - 0.390625 * u - 0.8125 * v, y + 2.015625 * u, 1.0);\n"
285 static const char *g_vs_yuv420_source_gl2 =
287 "attribute vec4 vertCoord;\n"
288 "uniform mat4 proj;\n"
289 "attribute vec2 texCoord;\n"
290 "varying vec2 v_texCoord;\n"
293 " v_texCoord = texCoord;\n"
294 " gl_Position = proj * vertCoord;\n"
297 static const char *g_vs_yuv420_source_gl3 =
299 "in vec4 vertCoord;\n"
300 "uniform mat4 proj;\n"
301 "in vec2 texCoord;\n"
302 "out vec2 v_texCoord;\n"
305 " v_texCoord = texCoord;\n"
306 " gl_Position = proj * vertCoord;\n"
309 static const char *g_fs_yuv420_source_gl2 =
311 "uniform sampler2D ytex;\n"
312 "uniform sampler2D utex;\n"
313 "uniform sampler2D vtex;\n"
314 "uniform vec2 size;\n"
315 "uniform vec2 ytexSize;\n"
316 "uniform vec2 utexSize;\n"
317 "uniform vec2 vtexSize;\n"
318 "varying vec2 v_texCoord;\n"
321 " float ypos = floor((1.0 - v_texCoord.y) * size.y) * size.x + floor(v_texCoord.x * size.x);\n"
322 " float ytexPos = floor(ypos / 4);\n"
323 " vec4 ytexColor = texture2D(ytex, vec2((mod(ytexPos, ytexSize.x) + 0.5) / ytexSize.x, 1.0 - (floor(ytexPos / ytexSize.x) + 0.5) / ytexSize.y));\n"
324 " float y = ytexColor[3 - int(mod(ypos + 1, 4))];\n"
325 " float uvpos = floor(floor((1.0 - v_texCoord.y) * size.y) / 2) * size.x + floor(v_texCoord.x * size.x);\n"
326 " float uvtexPos = floor(uvpos / 8);\n"
327 " vec4 utexColor = texture2D(utex, vec2((mod(uvtexPos, utexSize.x) + 0.5) / utexSize.x, 1.0 - (floor(uvtexPos / utexSize.x) + 0.5) / utexSize.y));\n"
328 " vec4 vtexColor = texture2D(vtex, vec2((mod(uvtexPos, vtexSize.x) + 0.5) / vtexSize.x, 1.0 - (floor(uvtexPos / vtexSize.x) + 0.5) / vtexSize.y));\n"
329 " int index = 3 - int(mod((uvpos / 2) + 1, 4));\n"
330 " float u = utexColor[index];\n"
331 " float v = vtexColor[index];\n"
334 " gl_FragColor = vec4(y + 1.59765625 * v, y - 0.390625 * u - 0.8125 * v, y + 2.015625 * u, 1.0);\n"
337 static const char *g_fs_yuv420_source_gl3 =
339 "uniform sampler2D ytex;\n"
340 "uniform sampler2D utex;\n"
341 "uniform sampler2D vtex;\n"
342 "uniform vec2 size;\n"
343 "uniform vec2 ytexSize;\n"
344 "uniform vec2 utexSize;\n"
345 "uniform vec2 vtexSize;\n"
346 "in vec2 v_texCoord;\n"
347 "out vec4 FragColor;\n"
350 " float ypos = floor((1.0 - v_texCoord.y) * size.y) * size.x + floor(v_texCoord.x * size.x);\n"
351 " float ytexPos = floor(ypos / 4);\n"
352 " vec4 ytexColor = texture(ytex, vec2((mod(ytexPos, ytexSize.x) + 0.5) / ytexSize.x, 1.0 - (floor(ytexPos / ytexSize.x) + 0.5) / ytexSize.y));\n"
353 " float y = ytexColor[3 - int(mod(ypos + 1, 4))];\n"
354 " float uvpos = floor(floor((1.0 - v_texCoord.y) * size.y) / 2) * size.x + floor(v_texCoord.x * size.x);\n"
355 " float uvtexPos = floor(uvpos / 8);\n"
356 " vec4 utexColor = texture(utex, vec2((mod(uvtexPos, utexSize.x) + 0.5) / utexSize.x, 1.0 - (floor(uvtexPos / utexSize.x) + 0.5) / utexSize.y));\n"
357 " vec4 vtexColor = texture(vtex, vec2((mod(uvtexPos, vtexSize.x) + 0.5) / vtexSize.x, 1.0 - (floor(uvtexPos / vtexSize.x) + 0.5) / vtexSize.y));\n"
358 " int index = 3 - int(mod((uvpos / 2) + 1, 4));\n"
359 " float u = utexColor[index];\n"
360 " float v = vtexColor[index];\n"
363 " FragColor = vec4(y + 1.59765625 * v, y - 0.390625 * u - 0.8125 * v, y + 2.015625 * u, 1.0);\n"
366 static const char *g_fs_xbgr_source_gl2 =
368 "uniform sampler2D tex;\n"
369 "varying vec2 v_texCoord;\n"
372 " gl_FragColor = vec4(texture2D(tex, v_texCoord).bgr, 1.0);\n"
375 static const char *g_fs_xbgr_source_gl3 =
377 "uniform sampler2D tex;\n"
378 "in vec2 v_texCoord;\n"
379 "out vec4 FragColor;\n"
382 " FragColor = vec4(texture(tex, v_texCoord).bgr, 1.0);\n"
385 static GLuint vigs_gl_backend_alloc_tmp_texture(void *user_data,
388 vigsp_surface_format format)
390 struct vigs_gl_backend *backend = (struct vigs_gl_backend*)user_data;
391 GLint tex_internalformat;
394 GLuint tex = 0, cur_tex = 0;
396 backend->GenTextures(1, &tex);
403 case vigsp_surface_bgrx8888:
404 case vigsp_surface_bgra8888:
405 tex_internalformat = GL_RGBA8;
406 tex_format = GL_BGRA;
407 tex_type = GL_UNSIGNED_INT_8_8_8_8_REV;
414 backend->GetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*)&cur_tex);
415 backend->BindTexture(GL_TEXTURE_2D, tex);
418 * Workaround for problem in "Mesa DRI Intel(R) Ivybridge Desktop x86/MMX/SSE2, version 9.0.3":
419 * These lines used to be in 'vigs_gl_backend_init', but it turned out that they must
420 * be called after 'glBindTexture'.
422 backend->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
423 backend->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
425 backend->TexImage2D(GL_TEXTURE_2D, 0, tex_internalformat,
427 tex_format, tex_type,
429 backend->BindTexture(GL_TEXTURE_2D, cur_tex);
434 static void vigs_gl_backend_release_tmp_texture(void *user_data, GLuint id)
436 struct vigs_gl_backend *backend = (struct vigs_gl_backend*)user_data;
438 backend->DeleteTextures(1, &id);
441 static GLuint vigs_gl_backend_alloc_framebuffer(void *user_data,
444 vigsp_surface_format format)
446 struct vigs_gl_backend *backend = (struct vigs_gl_backend*)user_data;
449 backend->GenFramebuffers(1, &fb);
454 static void vigs_gl_backend_release_framebuffer(void *user_data, GLuint id)
456 struct vigs_gl_backend *backend = (struct vigs_gl_backend*)user_data;
458 backend->DeleteFramebuffers(1, &id);
461 static GLuint vigs_gl_create_shader(struct vigs_gl_backend *backend,
465 GLuint shader = backend->CreateShader(type);
469 VIGS_LOG_CRITICAL("Unable to create shader type %d", type);
473 backend->ShaderSource(shader, 1, &source, NULL);
474 backend->CompileShader(shader);
475 backend->GetShaderiv(shader, GL_COMPILE_STATUS, &tmp);
482 backend->GetShaderiv(shader, GL_INFO_LOG_LENGTH, &tmp);
484 buff = g_malloc0(tmp);
486 backend->GetShaderInfoLog(shader, tmp, NULL, buff);
488 VIGS_LOG_CRITICAL("Unable to compile shader (type = %d) - %s",
491 backend->DeleteShader(shader);
501 static GLuint vigs_gl_create_program(struct vigs_gl_backend *backend,
505 GLuint program = backend->CreateProgram();
509 VIGS_LOG_CRITICAL("Unable to create program");
513 backend->AttachShader(program, vs_id);
514 backend->AttachShader(program, fs_id);
515 backend->LinkProgram(program);
516 backend->GetProgramiv(program, GL_LINK_STATUS, &tmp);
523 backend->GetProgramiv(program, GL_INFO_LOG_LENGTH, &tmp);
525 buff = g_malloc0(tmp);
527 backend->GetProgramInfoLog(program, tmp, NULL, buff);
529 VIGS_LOG_CRITICAL("Unable to link program - %s", buff);
531 backend->DeleteProgram(program);
541 static void vigs_gl_draw_update_vert_tex_buffer(struct vigs_gl_backend *backend,
546 if (size > backend->vbo_size) {
547 backend->vbo_size = size;
548 backend->BufferData(GL_ARRAY_BUFFER,
554 if (backend->MapBufferRange) {
555 ptr = backend->MapBufferRange(GL_ARRAY_BUFFER, 0, size,
556 GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT);
559 memcpy(ptr, vigs_vector_data(&backend->v1), size / 2);
560 memcpy(ptr + (size / 2), vigs_vector_data(&backend->v2), size / 2);
562 backend->UnmapBuffer(GL_ARRAY_BUFFER);
564 VIGS_LOG_ERROR("glMapBufferRange failed");
567 ptr = backend->MapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
569 memcpy(ptr, vigs_vector_data(&backend->v1), size / 2);
570 memcpy(ptr + (size / 2), vigs_vector_data(&backend->v2), size / 2);
572 backend->UnmapBuffer(GL_ARRAY_BUFFER);
575 backend->BufferSubData(GL_ARRAY_BUFFER, 0,
576 (size / 2), vigs_vector_data(&backend->v1));
577 backend->BufferSubData(GL_ARRAY_BUFFER, (size / 2),
578 (size / 2), vigs_vector_data(&backend->v2));
583 static void vigs_gl_draw_tex_prog(struct vigs_gl_backend *backend,
586 uint32_t size = count * 16;
588 vigs_gl_draw_update_vert_tex_buffer(backend, size);
590 backend->EnableVertexAttribArray(backend->tex_prog_vertCoord_loc);
591 backend->EnableVertexAttribArray(backend->tex_prog_texCoord_loc);
593 backend->VertexAttribPointer(backend->tex_prog_vertCoord_loc,
594 2, GL_FLOAT, GL_FALSE, 0, NULL);
595 backend->VertexAttribPointer(backend->tex_prog_texCoord_loc,
596 2, GL_FLOAT, GL_FALSE, 0, NULL + (size / 2));
598 backend->DrawArrays(GL_TRIANGLES, 0, count);
600 backend->DisableVertexAttribArray(backend->tex_prog_texCoord_loc);
601 backend->DisableVertexAttribArray(backend->tex_prog_vertCoord_loc);
604 static void vigs_gl_draw_color_prog(struct vigs_gl_backend *backend,
605 const GLfloat color[4],
608 uint32_t size = count * 8;
611 if (size > backend->vbo_size) {
612 backend->vbo_size = size;
613 backend->BufferData(GL_ARRAY_BUFFER,
619 if (backend->MapBufferRange) {
620 ptr = backend->MapBufferRange(GL_ARRAY_BUFFER, 0, size,
621 GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT);
624 memcpy(ptr, vigs_vector_data(&backend->v1), size);
626 backend->UnmapBuffer(GL_ARRAY_BUFFER);
628 VIGS_LOG_ERROR("glMapBufferRange failed");
631 ptr = backend->MapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
633 memcpy(ptr, vigs_vector_data(&backend->v1), size);
635 backend->UnmapBuffer(GL_ARRAY_BUFFER);
638 backend->BufferSubData(GL_ARRAY_BUFFER, 0, size,
639 vigs_vector_data(&backend->v1));
643 backend->Uniform4fv(backend->color_prog_color_loc, 1, color);
645 backend->EnableVertexAttribArray(backend->color_prog_vertCoord_loc);
647 backend->VertexAttribPointer(backend->color_prog_vertCoord_loc,
648 2, GL_FLOAT, GL_FALSE, 0, NULL);
650 backend->DrawArrays(GL_TRIANGLES, 0, count);
652 backend->DisableVertexAttribArray(backend->color_prog_vertCoord_loc);
655 static void vigs_gl_draw_nv21_prog(struct vigs_gl_backend *backend,
658 uint32_t size = count * 16;
660 vigs_gl_draw_update_vert_tex_buffer(backend, size);
662 backend->EnableVertexAttribArray(backend->nv21_prog_vertCoord_loc);
663 backend->EnableVertexAttribArray(backend->nv21_prog_texCoord_loc);
665 backend->VertexAttribPointer(backend->nv21_prog_vertCoord_loc,
666 2, GL_FLOAT, GL_FALSE, 0, NULL);
667 backend->VertexAttribPointer(backend->nv21_prog_texCoord_loc,
668 2, GL_FLOAT, GL_FALSE, 0, NULL + (size / 2));
670 backend->DrawArrays(GL_TRIANGLES, 0, count);
672 backend->DisableVertexAttribArray(backend->nv21_prog_texCoord_loc);
673 backend->DisableVertexAttribArray(backend->nv21_prog_vertCoord_loc);
676 static void vigs_gl_draw_yuv420_prog(struct vigs_gl_backend *backend,
679 uint32_t size = count * 16;
681 vigs_gl_draw_update_vert_tex_buffer(backend, size);
683 backend->EnableVertexAttribArray(backend->yuv420_prog_vertCoord_loc);
684 backend->EnableVertexAttribArray(backend->yuv420_prog_texCoord_loc);
686 backend->VertexAttribPointer(backend->yuv420_prog_vertCoord_loc,
687 2, GL_FLOAT, GL_FALSE, 0, NULL);
688 backend->VertexAttribPointer(backend->yuv420_prog_texCoord_loc,
689 2, GL_FLOAT, GL_FALSE, 0, NULL + (size / 2));
691 backend->DrawArrays(GL_TRIANGLES, 0, count);
693 backend->DisableVertexAttribArray(backend->yuv420_prog_texCoord_loc);
694 backend->DisableVertexAttribArray(backend->yuv420_prog_vertCoord_loc);
697 static void vigs_gl_draw_xbgr_prog(struct vigs_gl_backend *backend,
700 uint32_t size = count * 16;
702 vigs_gl_draw_update_vert_tex_buffer(backend, size);
704 backend->EnableVertexAttribArray(backend->xbgr_prog_vertCoord_loc);
705 backend->EnableVertexAttribArray(backend->xbgr_prog_texCoord_loc);
707 backend->VertexAttribPointer(backend->xbgr_prog_vertCoord_loc,
708 2, GL_FLOAT, GL_FALSE, 0, NULL);
709 backend->VertexAttribPointer(backend->xbgr_prog_texCoord_loc,
710 2, GL_FLOAT, GL_FALSE, 0, NULL + (size / 2));
712 backend->DrawArrays(GL_TRIANGLES, 0, count);
714 backend->DisableVertexAttribArray(backend->xbgr_prog_texCoord_loc);
715 backend->DisableVertexAttribArray(backend->xbgr_prog_vertCoord_loc);
718 static void vigs_gl_create_ortho(GLfloat left, GLfloat right,
719 GLfloat bottom, GLfloat top,
720 GLfloat nearf, GLfloat farf,
723 ortho[0] = 2.0f / (right - left);
724 ortho[5] = 2.0f / (top - bottom);
725 ortho[10] = -2.0f / (farf - nearf);
726 ortho[12] = -(right + left) / (right - left);
727 ortho[13] = -(top + bottom) / (top - bottom);
728 ortho[14] = -(farf + nearf) / (farf - nearf);
732 static void vigs_gl_translate_color(vigsp_color color,
733 vigsp_surface_format format,
738 case vigsp_surface_bgra8888:
739 res[3] = (GLfloat)((color >> 24) & 0xFF) / 255.0f;
741 case vigsp_surface_bgrx8888:
742 res[0] = (GLfloat)((color >> 16) & 0xFF) / 255.0f;
743 res[1] = (GLfloat)((color >> 8) & 0xFF) / 255.0f;
744 res[2] = (GLfloat)(color & 0xFF) / 255.0f;
754 static bool vigs_winsys_gl_surface_create_texture(struct vigs_winsys_gl_surface *ws_sfc)
756 GLuint cur_tex = 0, tmp_tex = 0;
762 ws_sfc->backend->GenTextures(1, &tmp_tex);
768 ws_sfc->backend->GetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*)&cur_tex);
769 ws_sfc->backend->BindTexture(GL_TEXTURE_2D, tmp_tex);
772 * Workaround for problem in "Mesa DRI Intel(R) Ivybridge Desktop x86/MMX/SSE2, version 9.0.3":
773 * These lines used to be in 'vigs_gl_backend_init', but it turned out that they must
774 * be called after 'glBindTexture'.
776 ws_sfc->backend->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
777 ws_sfc->backend->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
779 ws_sfc->backend->TexImage2D(GL_TEXTURE_2D, 0, ws_sfc->tex_internalformat,
780 ws_sfc->base.base.width, ws_sfc->base.base.height, 0,
781 ws_sfc->tex_format, ws_sfc->tex_type,
783 ws_sfc->backend->BindTexture(GL_TEXTURE_2D, cur_tex);
785 ws_sfc->tex = tmp_tex;
790 static bool vigs_gl_surface_create_tmp_texture(struct vigs_gl_surface *gl_sfc)
792 struct vigs_gl_backend *gl_backend = (struct vigs_gl_backend*)gl_sfc->base.backend;
794 if (gl_sfc->tmp_tex) {
798 gl_sfc->tmp_tex = vigs_gl_pool_alloc(gl_backend->tex_pool,
799 gl_sfc->base.ws_sfc->width,
800 gl_sfc->base.ws_sfc->height,
801 gl_sfc->base.format);
803 return gl_sfc->tmp_tex != 0;
806 static bool vigs_gl_surface_setup_framebuffer(struct vigs_gl_surface *gl_sfc,
810 struct vigs_gl_backend *gl_backend = (struct vigs_gl_backend*)gl_sfc->base.backend;
813 gl_sfc->fb = vigs_gl_pool_alloc(gl_backend->fb_pool,
814 gl_sfc->base.ws_sfc->width,
815 gl_sfc->base.ws_sfc->height,
816 gl_sfc->base.format);
823 if (gl_backend->cur_prog_id != prog_id) {
824 gl_backend->UseProgram(prog_id);
825 gl_backend->cur_prog_id = prog_id;
828 gl_backend->Viewport(0, 0,
829 gl_sfc->base.ws_sfc->width,
830 gl_sfc->base.ws_sfc->height);
832 gl_backend->UniformMatrix4fv(proj_loc, 1, GL_FALSE, gl_sfc->ortho);
834 gl_backend->BindFramebuffer(GL_FRAMEBUFFER, gl_sfc->fb);
836 gl_backend->Disable(GL_BLEND);
841 static bool vigs_gl_update_dpy_texture(struct vigs_gl_backend *gl_backend,
842 uint32_t width, uint32_t height)
846 if (vigs_qt5_onscreen_enabled()) {
847 // find available texture by iteration.
848 // it is OK, since we have only very few textures.
849 gl_backend->current_dpy = NULL;
851 for (i = 0; i < TEXTURE_NUM; ++i) {
852 struct dpy_item *item = &(gl_backend->dpy_items[i]);
853 if(likely(!qemu_mutex_trylock(&item->mutex))) {
854 if (item->available) {
855 item->available = false;
856 gl_backend->current_dpy = item;
857 qemu_mutex_unlock(&item->mutex);
860 qemu_mutex_unlock(&item->mutex);
863 if (unlikely(!gl_backend->current_dpy)) {
864 // can not enter here.
865 // simply we drop this frame.
869 gl_backend->current_dpy = &gl_backend->dpy_items[0];
872 gl_backend->GetIntegerv(GL_TEXTURE_BINDING_2D, (GLint *)&cur_tex);
874 if (gl_backend->current_dpy->tex) {
875 if ((gl_backend->current_dpy->width == width) &&
876 (gl_backend->current_dpy->height == height)) {
879 gl_backend->BindTexture(GL_TEXTURE_2D, gl_backend->current_dpy->tex);
883 gl_backend->GenTextures(1, &tmp_tex);
889 gl_backend->current_dpy->tex = tmp_tex;
891 gl_backend->BindTexture(GL_TEXTURE_2D, tmp_tex);
893 gl_backend->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
894 gl_backend->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
895 gl_backend->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
896 gl_backend->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
899 gl_backend->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8,
901 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
904 gl_backend->BindTexture(GL_TEXTURE_2D, cur_tex);
906 gl_backend->current_dpy->width = width;
907 gl_backend->current_dpy->height = height;
917 * vigs_winsys_gl_surface.
921 static void vigs_winsys_gl_surface_acquire(struct winsys_surface *sfc)
923 struct vigs_winsys_gl_surface *vigs_sfc = (struct vigs_winsys_gl_surface*)sfc;
924 vigs_ref_acquire(&vigs_sfc->ref);
927 static void vigs_winsys_gl_surface_release(struct winsys_surface *sfc)
929 struct vigs_winsys_gl_surface *vigs_sfc = (struct vigs_winsys_gl_surface*)sfc;
930 vigs_ref_release(&vigs_sfc->ref);
933 static void vigs_winsys_gl_surface_set_dirty(struct winsys_surface *sfc)
935 struct vigs_winsys_gl_surface *vigs_sfc = (struct vigs_winsys_gl_surface*)sfc;
936 if (vigs_sfc->parent) {
937 vigs_sfc->parent->base.is_dirty = true;
941 static void vigs_winsys_gl_surface_draw_pixels(struct winsys_surface *sfc,
944 struct vigs_winsys_gl_surface *vigs_sfc = (struct vigs_winsys_gl_surface*)sfc;
945 bool has_current = vigs_sfc->backend->has_current(vigs_sfc->backend);
946 if (!vigs_sfc->parent) {
951 vigs_sfc->backend->make_current(vigs_sfc->backend, true)) {
952 struct vigsp_rect rect;
956 rect.size.w = sfc->width;
957 rect.size.h = sfc->height;
959 vigs_sfc->parent->base.draw_pixels(&vigs_sfc->parent->base,
964 vigs_sfc->parent->base.is_dirty = true;
966 vigs_sfc->backend->Finish();
969 vigs_sfc->backend->make_current(vigs_sfc->backend, false);
972 VIGS_LOG_CRITICAL("make_current failed");
976 static void vigs_winsys_gl_surface_draw_pixels_scaled(struct winsys_surface *sfc,
981 struct vigs_winsys_gl_surface *vigs_sfc = (struct vigs_winsys_gl_surface*)sfc;
982 bool has_current = vigs_sfc->backend->has_current(vigs_sfc->backend);
983 if (!vigs_sfc->parent) {
988 vigs_sfc->backend->make_current(vigs_sfc->backend, true)) {
990 vigs_sfc->parent->base.draw_pixels_scaled(&vigs_sfc->parent->base,
995 vigs_sfc->parent->base.is_dirty = true;
997 vigs_sfc->backend->Finish();
1000 vigs_sfc->backend->make_current(vigs_sfc->backend, false);
1003 VIGS_LOG_CRITICAL("make_current failed");
1007 static GLuint vigs_winsys_gl_surface_get_texture(struct winsys_gl_surface *sfc)
1009 struct vigs_winsys_gl_surface *vigs_sfc = (struct vigs_winsys_gl_surface*)sfc;
1010 bool has_current = vigs_sfc->backend->has_current(vigs_sfc->backend);
1012 if (!vigs_sfc->tex &&
1014 vigs_sfc->backend->make_current(vigs_sfc->backend, true))) {
1016 vigs_winsys_gl_surface_create_texture(vigs_sfc);
1019 vigs_sfc->backend->make_current(vigs_sfc->backend, false);
1023 return vigs_sfc->tex;
1026 static void vigs_winsys_gl_surface_destroy(struct vigs_ref *ref)
1028 struct vigs_winsys_gl_surface *vigs_sfc =
1029 container_of(ref, struct vigs_winsys_gl_surface, ref);
1030 bool has_current = vigs_sfc->backend->has_current(vigs_sfc->backend);
1033 vigs_sfc->backend->make_current(vigs_sfc->backend, true)) {
1034 if (vigs_sfc->tex) {
1035 vigs_sfc->backend->DeleteTextures(1, &vigs_sfc->tex);
1039 vigs_sfc->backend->make_current(vigs_sfc->backend, false);
1043 vigs_ref_cleanup(&vigs_sfc->ref);
1048 static struct vigs_winsys_gl_surface
1049 *vigs_winsys_gl_surface_create(struct vigs_gl_backend *backend,
1050 struct vigs_gl_surface *parent,
1053 GLint tex_internalformat,
1057 struct vigs_winsys_gl_surface *ws_sfc;
1059 ws_sfc = g_malloc0(sizeof(*ws_sfc));
1061 ws_sfc->base.base.width = width;
1062 ws_sfc->base.base.height = height;
1063 ws_sfc->base.base.acquire = &vigs_winsys_gl_surface_acquire;
1064 ws_sfc->base.base.release = &vigs_winsys_gl_surface_release;
1065 ws_sfc->base.base.set_dirty = &vigs_winsys_gl_surface_set_dirty;
1066 ws_sfc->base.base.draw_pixels = &vigs_winsys_gl_surface_draw_pixels;
1067 ws_sfc->base.base.draw_pixels_scaled = &vigs_winsys_gl_surface_draw_pixels_scaled;
1068 ws_sfc->base.get_texture = &vigs_winsys_gl_surface_get_texture;
1069 ws_sfc->tex_internalformat = tex_internalformat;
1070 ws_sfc->tex_format = tex_format;
1071 ws_sfc->tex_type = tex_type;
1072 ws_sfc->backend = backend;
1073 ws_sfc->parent = parent;
1075 vigs_ref_init(&ws_sfc->ref, &vigs_winsys_gl_surface_destroy);
1080 static void vigs_winsys_gl_surface_orphan(struct vigs_winsys_gl_surface *sfc)
1089 static void vigs_gl_backend_batch_start(struct vigs_backend *backend)
1091 struct vigs_gl_backend *gl_backend = (struct vigs_gl_backend*)backend;
1093 if (!gl_backend->make_current(gl_backend, true)) {
1094 VIGS_LOG_CRITICAL("make_current failed");
1103 static void vigs_gl_surface_read_pixels(struct vigs_surface *sfc,
1106 struct vigs_gl_backend *gl_backend = (struct vigs_gl_backend*)sfc->backend;
1107 struct vigs_gl_surface *gl_sfc = (struct vigs_gl_surface*)sfc;
1108 struct vigs_winsys_gl_surface *ws_sfc = get_ws_sfc(gl_sfc);
1109 GLfloat sfc_w, sfc_h;
1110 GLfloat *vert_coords;
1111 GLfloat *tex_coords;
1114 VIGS_LOG_TRACE("skipping blank read");
1118 if (!vigs_winsys_gl_surface_create_texture(ws_sfc)) {
1122 if (!vigs_gl_surface_create_tmp_texture(gl_sfc)) {
1126 if (!vigs_gl_surface_setup_framebuffer(gl_sfc,
1127 gl_backend->tex_prog_id,
1128 gl_backend->tex_prog_proj_loc)) {
1132 vigs_vector_resize(&gl_backend->v1, 0);
1133 vigs_vector_resize(&gl_backend->v2, 0);
1135 sfc_w = ws_sfc->base.base.width;
1136 sfc_h = ws_sfc->base.base.height;
1138 gl_backend->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1139 GL_TEXTURE_2D, gl_sfc->tmp_tex, 0);
1141 vert_coords = vigs_vector_append(&gl_backend->v1,
1142 (12 * sizeof(GLfloat)));
1143 tex_coords = vigs_vector_append(&gl_backend->v2,
1144 (12 * sizeof(GLfloat)));
1146 vert_coords[6] = vert_coords[0] = 0;
1147 vert_coords[7] = vert_coords[1] = sfc_h;
1148 vert_coords[2] = sfc_w;
1149 vert_coords[3] = sfc_h;
1150 vert_coords[8] = vert_coords[4] = sfc_w;
1151 vert_coords[9] = vert_coords[5] = 0;
1152 vert_coords[10] = 0;
1153 vert_coords[11] = 0;
1155 tex_coords[6] = tex_coords[0] = 0;
1156 tex_coords[7] = tex_coords[1] = 0;
1159 tex_coords[8] = tex_coords[4] = 1;
1160 tex_coords[9] = tex_coords[5] = 1;
1164 gl_backend->BindTexture(GL_TEXTURE_2D, ws_sfc->tex);
1166 vigs_gl_draw_tex_prog(gl_backend, 6);
1168 gl_backend->PixelStorei(GL_PACK_ALIGNMENT, 1);
1169 gl_backend->ReadPixels(0, 0, sfc_w, sfc_h,
1170 ws_sfc->tex_format, ws_sfc->tex_type,
1174 gl_backend->BindFramebuffer(GL_FRAMEBUFFER, 0);
1177 static void vigs_gl_surface_draw_pixels(struct vigs_surface *sfc,
1179 const struct vigsp_rect *entries,
1180 uint32_t num_entries)
1182 struct vigs_gl_backend *gl_backend = (struct vigs_gl_backend*)sfc->backend;
1183 struct vigs_gl_surface *gl_sfc = (struct vigs_gl_surface*)sfc;
1184 struct vigs_winsys_gl_surface *ws_sfc = get_ws_sfc(gl_sfc);
1185 GLfloat sfc_w, sfc_h;
1186 GLfloat *vert_coords;
1187 GLfloat *tex_coords;
1190 if (!vigs_winsys_gl_surface_create_texture(ws_sfc)) {
1194 if (!vigs_gl_surface_create_tmp_texture(gl_sfc)) {
1198 if (!vigs_gl_surface_setup_framebuffer(gl_sfc,
1199 gl_backend->tex_prog_id,
1200 gl_backend->tex_prog_proj_loc)) {
1204 sfc_w = ws_sfc->base.base.width;
1205 sfc_h = ws_sfc->base.base.height;
1207 gl_backend->BindTexture(GL_TEXTURE_2D, gl_sfc->tmp_tex);
1209 gl_backend->PixelStorei(GL_UNPACK_ALIGNMENT, 1);
1210 gl_backend->PixelStorei(GL_UNPACK_ROW_LENGTH, sfc_w);
1212 for (i = 0; i < num_entries; ++i) {
1213 uint32_t x = entries[i].pos.x;
1214 uint32_t y = entries[i].pos.y;
1215 uint32_t width = entries[i].size.w;
1216 uint32_t height = entries[i].size.h;
1217 VIGS_LOG_TRACE("x = %u, y = %u, width = %u, height = %u",
1220 gl_backend->PixelStorei(GL_UNPACK_SKIP_PIXELS, x);
1221 gl_backend->PixelStorei(GL_UNPACK_SKIP_ROWS, y);
1222 gl_backend->TexSubImage2D(GL_TEXTURE_2D, 0, x, y,
1229 vigs_vector_resize(&gl_backend->v1, 0);
1230 vigs_vector_resize(&gl_backend->v2, 0);
1232 gl_backend->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1233 GL_TEXTURE_2D, ws_sfc->tex, 0);
1235 for (i = 0; i < num_entries; ++i) {
1236 vert_coords = vigs_vector_append(&gl_backend->v1,
1237 (12 * sizeof(GLfloat)));
1238 tex_coords = vigs_vector_append(&gl_backend->v2,
1239 (12 * sizeof(GLfloat)));
1241 vert_coords[6] = vert_coords[0] = entries[i].pos.x;
1242 vert_coords[7] = vert_coords[1] = sfc_h - entries[i].pos.y;
1243 vert_coords[2] = entries[i].pos.x + entries[i].size.w;
1244 vert_coords[3] = sfc_h - entries[i].pos.y;
1245 vert_coords[8] = vert_coords[4] = entries[i].pos.x + entries[i].size.w;
1246 vert_coords[9] = vert_coords[5] = sfc_h - (entries[i].pos.y + entries[i].size.h);
1247 vert_coords[10] = entries[i].pos.x;
1248 vert_coords[11] = sfc_h - (entries[i].pos.y + entries[i].size.h);
1250 tex_coords[6] = tex_coords[0] = (GLfloat)entries[i].pos.x / sfc_w;
1251 tex_coords[7] = tex_coords[1] = (GLfloat)entries[i].pos.y / sfc_h;
1252 tex_coords[2] = (GLfloat)(entries[i].pos.x + entries[i].size.w) / sfc_w;
1253 tex_coords[3] = (GLfloat)entries[i].pos.y / sfc_h;
1254 tex_coords[8] = tex_coords[4] = (GLfloat)(entries[i].pos.x + entries[i].size.w) / sfc_w;
1255 tex_coords[9] = tex_coords[5] = (GLfloat)(entries[i].pos.y + entries[i].size.h) / sfc_h;
1256 tex_coords[10] = (GLfloat)entries[i].pos.x / sfc_w;
1257 tex_coords[11] = (GLfloat)(entries[i].pos.y + entries[i].size.h) / sfc_h;
1260 vigs_gl_draw_tex_prog(gl_backend, num_entries * 6);
1263 gl_backend->BindFramebuffer(GL_FRAMEBUFFER, 0);
1266 static void vigs_gl_surface_draw_pixels_scaled(struct vigs_surface *sfc,
1271 struct vigs_gl_backend *gl_backend = (struct vigs_gl_backend*)sfc->backend;
1272 struct vigs_gl_surface *gl_sfc = (struct vigs_gl_surface*)sfc;
1273 struct vigs_winsys_gl_surface *ws_sfc = get_ws_sfc(gl_sfc);
1274 GLfloat sfc_w, sfc_h;
1275 GLfloat *vert_coords;
1276 GLfloat *tex_coords;
1278 sfc_w = ws_sfc->base.base.width;
1279 sfc_h = ws_sfc->base.base.height;
1281 if (!vigs_winsys_gl_surface_create_texture(ws_sfc)) {
1285 if (!vigs_gl_surface_create_tmp_texture(gl_sfc)) {
1289 if (!vigs_gl_surface_setup_framebuffer(gl_sfc,
1290 gl_backend->tex_prog_id,
1291 gl_backend->tex_prog_proj_loc)) {
1295 gl_backend->BindTexture(GL_TEXTURE_2D, gl_sfc->tmp_tex);
1297 gl_backend->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1298 gl_backend->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1299 gl_backend->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1300 gl_backend->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1302 gl_backend->PixelStorei(GL_UNPACK_ALIGNMENT, 1);
1303 gl_backend->PixelStorei(GL_UNPACK_ROW_LENGTH, width);
1304 gl_backend->PixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
1305 gl_backend->PixelStorei(GL_UNPACK_SKIP_ROWS, 0);
1307 if (width > sfc_w || height > sfc_h) {
1308 gl_backend->TexImage2D(GL_TEXTURE_2D, 0, ws_sfc->tex_internalformat,
1314 gl_backend->TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
1321 vigs_vector_resize(&gl_backend->v1, 0);
1322 vigs_vector_resize(&gl_backend->v2, 0);
1324 gl_backend->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1325 GL_TEXTURE_2D, ws_sfc->tex, 0);
1327 vert_coords = vigs_vector_append(&gl_backend->v1,
1328 (12 * sizeof(GLfloat)));
1329 tex_coords = vigs_vector_append(&gl_backend->v2,
1330 (12 * sizeof(GLfloat)));
1332 vert_coords[6] = vert_coords[0] = 0;
1333 vert_coords[7] = vert_coords[1] = sfc_h;
1334 vert_coords[2] = sfc_w;
1335 vert_coords[3] = sfc_h;
1336 vert_coords[8] = vert_coords[4] = sfc_w;
1337 vert_coords[9] = vert_coords[5] = 0;
1338 vert_coords[10] = 0;
1339 vert_coords[11] = 0;
1341 tex_coords[6] = tex_coords[0] = 0;
1342 tex_coords[7] = tex_coords[1] = 0;
1343 tex_coords[2] = (GLfloat)width / sfc_w;
1345 tex_coords[8] = tex_coords[4] = (GLfloat)width / sfc_w;
1346 tex_coords[9] = tex_coords[5] = (GLfloat)height / sfc_h;
1348 tex_coords[11] = (GLfloat)height / sfc_h;
1350 vigs_gl_draw_tex_prog(gl_backend, 6);
1353 gl_backend->BindFramebuffer(GL_FRAMEBUFFER, 0);
1356 static void vigs_gl_surface_copy(struct vigs_surface *dst,
1357 struct vigs_surface *src,
1358 const struct vigsp_copy *entries,
1359 uint32_t num_entries)
1361 struct vigs_gl_backend *gl_backend = (struct vigs_gl_backend*)dst->backend;
1362 struct vigs_gl_surface *gl_dst = (struct vigs_gl_surface*)dst;
1363 struct vigs_gl_surface *gl_src = (struct vigs_gl_surface*)src;
1364 struct vigs_winsys_gl_surface *ws_dst = get_ws_sfc(gl_dst);
1365 struct vigs_winsys_gl_surface *ws_src = get_ws_sfc(gl_src);
1366 uint32_t total_entries = num_entries, i;
1367 GLfloat src_w, src_h;
1369 GLfloat *vert_coords;
1370 GLfloat *tex_coords;
1372 if (!vigs_winsys_gl_surface_create_texture(ws_dst)) {
1377 VIGS_LOG_WARN("copying garbage ???");
1380 if (!vigs_winsys_gl_surface_create_texture(ws_src)) {
1384 if (!vigs_gl_surface_setup_framebuffer(gl_dst,
1385 gl_backend->tex_prog_id,
1386 gl_backend->tex_prog_proj_loc)) {
1390 vigs_vector_resize(&gl_backend->v1, 0);
1391 vigs_vector_resize(&gl_backend->v2, 0);
1393 src_w = ws_src->base.base.width;
1394 src_h = ws_src->base.base.height;
1395 dst_h = ws_dst->base.base.height;
1399 * Feedback loop is possible, use 'tmp_tex' instead.
1402 if (!vigs_gl_surface_create_tmp_texture(gl_dst)) {
1406 gl_backend->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1407 GL_TEXTURE_2D, gl_dst->tmp_tex, 0);
1411 vert_coords = vigs_vector_append(&gl_backend->v1,
1412 (12 * sizeof(GLfloat)));
1413 tex_coords = vigs_vector_append(&gl_backend->v2,
1414 (12 * sizeof(GLfloat)));
1416 vert_coords[6] = vert_coords[0] = 0;
1417 vert_coords[7] = vert_coords[1] = src_h;
1418 vert_coords[2] = src_w;
1419 vert_coords[3] = src_h;
1420 vert_coords[8] = vert_coords[4] = src_w;
1421 vert_coords[9] = vert_coords[5] = 0;
1422 vert_coords[10] = 0;
1423 vert_coords[11] = 0;
1425 tex_coords[6] = tex_coords[0] = 0;
1426 tex_coords[7] = tex_coords[1] = 1;
1429 tex_coords[8] = tex_coords[4] = 1;
1430 tex_coords[9] = tex_coords[5] = 0;
1435 * No feedback loop possible, render to 'front_tex'.
1438 gl_backend->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1439 GL_TEXTURE_2D, ws_dst->tex, 0);
1442 for (i = 0; i < num_entries; ++i) {
1443 vert_coords = vigs_vector_append(&gl_backend->v1,
1444 (12 * sizeof(GLfloat)));
1445 tex_coords = vigs_vector_append(&gl_backend->v2,
1446 (12 * sizeof(GLfloat)));
1448 vert_coords[6] = vert_coords[0] = entries[i].to.x;
1449 vert_coords[7] = vert_coords[1] = dst_h - entries[i].to.y;
1450 vert_coords[2] = entries[i].to.x + entries[i].size.w;
1451 vert_coords[3] = dst_h - entries[i].to.y;
1452 vert_coords[8] = vert_coords[4] = entries[i].to.x + entries[i].size.w;
1453 vert_coords[9] = vert_coords[5] = dst_h - (entries[i].to.y + entries[i].size.h);
1454 vert_coords[10] = entries[i].to.x;
1455 vert_coords[11] = dst_h - (entries[i].to.y + entries[i].size.h);
1457 tex_coords[6] = tex_coords[0] = (GLfloat)entries[i].from.x / src_w;
1458 tex_coords[7] = tex_coords[1] = (GLfloat)(src_h - entries[i].from.y) / src_h;
1459 tex_coords[2] = (GLfloat)(entries[i].from.x + entries[i].size.w) / src_w;
1460 tex_coords[3] = (GLfloat)(src_h - entries[i].from.y) / src_h;
1461 tex_coords[8] = tex_coords[4] = (GLfloat)(entries[i].from.x + entries[i].size.w) / src_w;
1462 tex_coords[9] = tex_coords[5] = (GLfloat)(src_h - (entries[i].from.y + entries[i].size.h)) / src_h;
1463 tex_coords[10] = (GLfloat)entries[i].from.x / src_w;
1464 tex_coords[11] = (GLfloat)(src_h - (entries[i].from.y + entries[i].size.h)) / src_h;
1467 gl_backend->BindTexture(GL_TEXTURE_2D, ws_src->tex);
1469 vigs_gl_draw_tex_prog(gl_backend, total_entries * 6);
1472 vigs_vector_resize(&gl_backend->v1, 0);
1473 vigs_vector_resize(&gl_backend->v2, 0);
1475 vert_coords = vigs_vector_append(&gl_backend->v1,
1476 (12 * sizeof(GLfloat)));
1477 tex_coords = vigs_vector_append(&gl_backend->v2,
1478 (12 * sizeof(GLfloat)));
1480 vert_coords[6] = vert_coords[0] = 0;
1481 vert_coords[7] = vert_coords[1] = src_h;
1482 vert_coords[2] = src_w;
1483 vert_coords[3] = src_h;
1484 vert_coords[8] = vert_coords[4] = src_w;
1485 vert_coords[9] = vert_coords[5] = 0;
1486 vert_coords[10] = 0;
1487 vert_coords[11] = 0;
1489 tex_coords[6] = tex_coords[0] = 0;
1490 tex_coords[7] = tex_coords[1] = 1;
1493 tex_coords[8] = tex_coords[4] = 1;
1494 tex_coords[9] = tex_coords[5] = 0;
1498 gl_backend->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1499 GL_TEXTURE_2D, ws_dst->tex, 0);
1501 gl_backend->BindTexture(GL_TEXTURE_2D, gl_dst->tmp_tex);
1503 vigs_gl_draw_tex_prog(gl_backend, 6);
1507 gl_backend->BindFramebuffer(GL_FRAMEBUFFER, 0);
1510 static void vigs_gl_surface_solid_fill(struct vigs_surface *sfc,
1512 const struct vigsp_rect *entries,
1513 uint32_t num_entries)
1515 struct vigs_gl_backend *gl_backend = (struct vigs_gl_backend*)sfc->backend;
1516 struct vigs_gl_surface *gl_sfc = (struct vigs_gl_surface*)sfc;
1517 struct vigs_winsys_gl_surface *ws_sfc = get_ws_sfc(gl_sfc);
1522 if (!vigs_winsys_gl_surface_create_texture(ws_sfc)) {
1526 if (!vigs_gl_surface_setup_framebuffer(gl_sfc,
1527 gl_backend->color_prog_id,
1528 gl_backend->color_prog_proj_loc)) {
1532 sfc_h = ws_sfc->base.base.height;
1534 gl_backend->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1535 GL_TEXTURE_2D, ws_sfc->tex, 0);
1537 vigs_vector_resize(&gl_backend->v1, 0);
1539 for (i = 0; i < num_entries; ++i) {
1540 GLfloat *vert_coords = vigs_vector_append(&gl_backend->v1,
1541 (12 * sizeof(GLfloat)));
1543 vert_coords[6] = vert_coords[0] = entries[i].pos.x;
1544 vert_coords[7] = vert_coords[1] = sfc_h - entries[i].pos.y;
1545 vert_coords[2] = entries[i].pos.x + entries[i].size.w;
1546 vert_coords[3] = sfc_h - entries[i].pos.y;
1547 vert_coords[8] = vert_coords[4] = entries[i].pos.x + entries[i].size.w;
1548 vert_coords[9] = vert_coords[5] = sfc_h - (entries[i].pos.y + entries[i].size.h);
1549 vert_coords[10] = entries[i].pos.x;
1550 vert_coords[11] = sfc_h - (entries[i].pos.y + entries[i].size.h);
1553 vigs_gl_translate_color(color, sfc->format, colorf);
1555 vigs_gl_draw_color_prog(gl_backend, colorf, num_entries * 6);
1558 gl_backend->BindFramebuffer(GL_FRAMEBUFFER, 0);
1561 static void vigs_gl_surface_ga_copy(struct vigs_surface *dst,
1562 uint32_t dst_stride,
1563 struct vigs_surface *src,
1564 uint8_t *src_pixels,
1565 uint32_t src_stride,
1566 const struct vigsp_copy *entry)
1568 struct vigs_gl_backend *gl_backend = (struct vigs_gl_backend*)dst->backend;
1569 struct vigs_gl_surface *gl_dst = (struct vigs_gl_surface*)dst;
1570 struct vigs_winsys_gl_surface *ws_dst = get_ws_sfc(gl_dst);
1571 GLfloat dst_w, dst_h, height;
1572 GLfloat *vert_coords;
1573 GLfloat *tex_coords;
1575 if ((entry->from.x != 0) ||
1576 (entry->to.x != 0) ||
1577 (entry->to.y != 0)) {
1578 VIGS_LOG_ERROR("not supported");
1581 if (entry->from.y * src_stride + entry->size.w * entry->size.h >
1582 src->stride * src->ws_sfc->height) {
1583 VIGS_LOG_ERROR("out of bounds");
1589 * Contents were flushed to GPU, so read them back,
1590 * not very pretty, but this path should be triggered
1593 vigs_vector_resize(&gl_backend->v1, src->stride * src->ws_sfc->height);
1595 src_pixels = vigs_vector_data(&gl_backend->v1);
1597 vigs_gl_surface_read_pixels(src, src_pixels);
1600 if (!vigs_winsys_gl_surface_create_texture(ws_dst)) {
1604 if (!vigs_gl_surface_create_tmp_texture(gl_dst)) {
1608 if (!vigs_gl_surface_setup_framebuffer(gl_dst,
1609 gl_backend->tex_prog_id,
1610 gl_backend->tex_prog_proj_loc)) {
1614 height = (entry->size.w * entry->size.h + dst->stride - 1) / dst->stride;
1616 dst_w = ws_dst->base.base.width;
1617 dst_h = ws_dst->base.base.height;
1619 gl_backend->BindTexture(GL_TEXTURE_2D, gl_dst->tmp_tex);
1621 gl_backend->PixelStorei(GL_UNPACK_ALIGNMENT, 1);
1622 gl_backend->PixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1623 gl_backend->PixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
1624 gl_backend->PixelStorei(GL_UNPACK_SKIP_ROWS, 0);
1625 gl_backend->TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
1629 src_pixels + entry->from.y * src_stride);
1631 vigs_vector_resize(&gl_backend->v1, 0);
1632 vigs_vector_resize(&gl_backend->v2, 0);
1634 gl_backend->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1635 GL_TEXTURE_2D, ws_dst->tex, 0);
1637 vert_coords = vigs_vector_append(&gl_backend->v1,
1638 (12 * sizeof(GLfloat)));
1639 tex_coords = vigs_vector_append(&gl_backend->v2,
1640 (12 * sizeof(GLfloat)));
1642 vert_coords[6] = vert_coords[0] = entry->to.x;
1643 vert_coords[7] = vert_coords[1] = dst_h - entry->to.y;
1644 vert_coords[2] = entry->to.x + dst_w;
1645 vert_coords[3] = dst_h - entry->to.y;
1646 vert_coords[8] = vert_coords[4] = entry->to.x + dst_w;
1647 vert_coords[9] = vert_coords[5] = dst_h - (entry->to.y + height);
1648 vert_coords[10] = entry->to.x;
1649 vert_coords[11] = dst_h - (entry->to.y + height);
1651 tex_coords[6] = tex_coords[0] = (GLfloat)entry->to.x / dst_w;
1652 tex_coords[7] = tex_coords[1] = (GLfloat)entry->to.y / dst_h;
1653 tex_coords[2] = (GLfloat)(entry->to.x + dst_w) / dst_w;
1654 tex_coords[3] = (GLfloat)entry->to.y / dst_h;
1655 tex_coords[8] = tex_coords[4] = (GLfloat)(entry->to.x + dst_w) / dst_w;
1656 tex_coords[9] = tex_coords[5] = (GLfloat)(entry->to.y + height) / dst_h;
1657 tex_coords[10] = (GLfloat)entry->to.x / dst_w;
1658 tex_coords[11] = (GLfloat)(entry->to.y + height) / dst_h;
1660 vigs_gl_draw_tex_prog(gl_backend, 6);
1663 gl_backend->BindFramebuffer(GL_FRAMEBUFFER, 0);
1666 static GLuint vigs_gl_surface_create_pixel_buf(struct vigs_surface *sfc)
1668 struct vigs_gl_backend *gl_backend = (struct vigs_gl_backend*)sfc->backend;
1669 struct vigs_gl_surface *gl_sfc = (struct vigs_gl_surface*)sfc;
1670 struct vigs_winsys_gl_surface *ws_sfc = get_ws_sfc(gl_sfc);
1671 GLsizei sfc_stride = sfc->stride;
1672 GLsizei sfc_h = ws_sfc->base.base.height;
1676 VIGS_LOG_ERROR("source surface must be not empty");
1680 gl_backend->GenBuffers(1, &pbuf);
1682 gl_backend->BindBuffer(GL_PIXEL_PACK_BUFFER, pbuf);
1684 gl_backend->BufferData(GL_PIXEL_PACK_BUFFER,
1689 vigs_gl_surface_read_pixels(sfc, 0);
1691 gl_backend->BindBuffer(GL_PIXEL_PACK_BUFFER, 0);
1696 static bool vigs_gl_surface_setup_yuv_textures(struct vigs_surface *dst,
1697 struct vigs_surface *src)
1699 struct vigs_gl_backend *gl_backend = (struct vigs_gl_backend*)dst->backend;
1700 struct vigs_gl_surface *gl_dst = (struct vigs_gl_surface*)dst;
1701 struct vigs_winsys_gl_surface *ws_dst = get_ws_sfc(gl_dst);
1702 GLsizei dst_w = ws_dst->base.base.width;
1703 GLsizei dst_h = ws_dst->base.base.height;
1704 GLsizei tex_widths[3] = {dst_w / 4, dst_w / 8, dst_w / 8};
1705 GLsizei tex_heights[3] = {dst_h, dst_h / 2, dst_h / 2};
1706 GLsizei pbuf_offsets[3] = {0, dst_w * dst_h, 5 * dst_w * dst_h / 4};
1708 bool need_alloc = false;
1712 * We have to create and destroy pixel buffer at every yuv conversion,
1713 * because we can't check restoring of source texture.
1715 pbuf = vigs_gl_surface_create_pixel_buf(src);
1721 if (gl_dst->yuv_textures[0] == 0) {
1722 gl_backend->GenTextures(3, &gl_dst->yuv_textures[0]);
1726 gl_backend->BindBuffer(GL_PIXEL_UNPACK_BUFFER, pbuf);
1728 for (i = 0; i < 3; i++) {
1729 gl_backend->ActiveTexture(GL_TEXTURE0 + i);
1730 gl_backend->BindTexture(GL_TEXTURE_2D, gl_dst->yuv_textures[i]);
1732 gl_backend->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1733 gl_backend->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1735 gl_backend->PixelStorei(GL_UNPACK_ALIGNMENT, 1);
1736 gl_backend->PixelStorei(GL_UNPACK_ROW_LENGTH, tex_widths[i]);
1739 gl_backend->TexImage2D(GL_TEXTURE_2D,
1741 ws_dst->tex_internalformat,
1742 tex_widths[i], tex_heights[i],
1746 (GLvoid *)(intptr_t)pbuf_offsets[i]);
1748 gl_backend->TexSubImage2D(GL_TEXTURE_2D,
1751 tex_widths[i], tex_heights[i],
1754 (GLvoid *)(intptr_t)pbuf_offsets[i]);
1758 gl_backend->ActiveTexture(GL_TEXTURE0);
1760 gl_backend->BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
1762 gl_backend->DeleteBuffers(1, &pbuf);
1767 static void vigs_gl_surface_convert_yuv2argb(struct vigs_surface *dst,
1768 struct vigs_surface *src)
1770 struct vigs_gl_backend *gl_backend = (struct vigs_gl_backend*)dst->backend;
1771 struct vigs_gl_surface *gl_dst = (struct vigs_gl_surface*)dst;
1772 struct vigs_winsys_gl_surface *ws_dst = get_ws_sfc(gl_dst);
1773 GLsizei dst_w = ws_dst->base.base.width;
1774 GLsizei dst_h = ws_dst->base.base.height;
1775 GLfloat *vert_coords;
1776 GLfloat *tex_coords;
1778 if (!vigs_winsys_gl_surface_create_texture(ws_dst)) {
1782 if (!vigs_gl_surface_setup_yuv_textures(dst, src)) {
1786 if (!vigs_gl_surface_setup_framebuffer(gl_dst,
1787 gl_backend->yuv420_prog_id,
1788 gl_backend->yuv420_prog_proj_loc)) {
1792 vigs_vector_resize(&gl_backend->v1, 12 * sizeof(GLfloat));
1793 vigs_vector_resize(&gl_backend->v2, 12 * sizeof(GLfloat));
1795 vert_coords = vigs_vector_data(&gl_backend->v1);
1796 tex_coords = vigs_vector_data(&gl_backend->v2);
1798 vert_coords[6] = vert_coords[0] = 0;
1799 vert_coords[7] = vert_coords[1] = dst_h;
1800 vert_coords[2] = dst_w;
1801 vert_coords[3] = dst_h;
1802 vert_coords[8] = vert_coords[4] = dst_w;
1803 vert_coords[9] = vert_coords[5] = 0.0;
1804 vert_coords[10] = 0.0;
1805 vert_coords[11] = 0.0;
1807 tex_coords[6] = tex_coords[0] = 0.0;
1808 tex_coords[7] = tex_coords[1] = 1.0;
1809 tex_coords[2] = 1.0;
1810 tex_coords[3] = 1.0;
1811 tex_coords[8] = tex_coords[4] = 1.0;
1812 tex_coords[9] = tex_coords[5] = 0.0;
1813 tex_coords[10] = 0.0;
1814 tex_coords[11] = 0.0;
1816 gl_backend->FramebufferTexture2D(GL_FRAMEBUFFER,
1817 GL_COLOR_ATTACHMENT0,
1822 gl_backend->UseProgram(gl_backend->yuv420_prog_id);
1824 gl_backend->Uniform2f(gl_backend->yuv420_prog_ytexSize_loc,
1826 gl_backend->Uniform2f(gl_backend->yuv420_prog_utexSize_loc,
1827 dst_w / 8, dst_h / 2);
1828 gl_backend->Uniform2f(gl_backend->yuv420_prog_vtexSize_loc,
1829 dst_w / 8, dst_h / 2);
1830 gl_backend->Uniform2f(gl_backend->yuv420_prog_size_loc,
1833 vigs_gl_draw_yuv420_prog(gl_backend, 6);
1836 gl_backend->BindFramebuffer(GL_FRAMEBUFFER, 0);
1839 static void vigs_gl_surface_convert_argb2xbgr(struct vigs_surface *dst,
1840 struct vigs_surface *src)
1842 struct vigs_gl_backend *gl_backend = (struct vigs_gl_backend*)dst->backend;
1843 struct vigs_gl_surface *gl_dst = (struct vigs_gl_surface*)dst;
1844 struct vigs_gl_surface *gl_src = (struct vigs_gl_surface*)src;
1845 struct vigs_winsys_gl_surface *ws_dst = get_ws_sfc(gl_dst);
1846 struct vigs_winsys_gl_surface *ws_src = get_ws_sfc(gl_src);
1847 GLsizei dst_w = ws_dst->base.base.width;
1848 GLsizei dst_h = ws_dst->base.base.height;
1849 GLfloat *vert_coords;
1850 GLfloat *tex_coords;
1852 if (!vigs_winsys_gl_surface_create_texture(ws_dst)) {
1857 VIGS_LOG_WARN("copying garbage ???");
1860 if (!vigs_winsys_gl_surface_create_texture(ws_src)) {
1864 if (!vigs_gl_surface_setup_framebuffer(gl_dst,
1865 gl_backend->xbgr_prog_id,
1866 gl_backend->xbgr_prog_proj_loc)) {
1870 vigs_vector_resize(&gl_backend->v1, 12 * sizeof(GLfloat));
1871 vigs_vector_resize(&gl_backend->v2, 12 * sizeof(GLfloat));
1873 vert_coords = vigs_vector_data(&gl_backend->v1);
1874 tex_coords = vigs_vector_data(&gl_backend->v2);
1876 vert_coords[6] = vert_coords[0] = 0;
1877 vert_coords[7] = vert_coords[1] = dst_h;
1878 vert_coords[2] = dst_w;
1879 vert_coords[3] = dst_h;
1880 vert_coords[8] = vert_coords[4] = dst_w;
1881 vert_coords[9] = vert_coords[5] = 0.0;
1882 vert_coords[10] = 0.0;
1883 vert_coords[11] = 0.0;
1885 tex_coords[6] = tex_coords[0] = 0.0;
1886 tex_coords[7] = tex_coords[1] = 1.0;
1887 tex_coords[2] = 1.0;
1888 tex_coords[3] = 1.0;
1889 tex_coords[8] = tex_coords[4] = 1.0;
1890 tex_coords[9] = tex_coords[5] = 0.0;
1891 tex_coords[10] = 0.0;
1892 tex_coords[11] = 0.0;
1894 gl_backend->FramebufferTexture2D(GL_FRAMEBUFFER,
1895 GL_COLOR_ATTACHMENT0,
1900 gl_backend->BindTexture(GL_TEXTURE_2D, ws_src->tex);
1902 gl_backend->UseProgram(gl_backend->xbgr_prog_id);
1904 vigs_gl_draw_xbgr_prog(gl_backend, 6);
1906 gl_backend->UseProgram(gl_backend->tex_prog_id);
1909 gl_backend->BindFramebuffer(GL_FRAMEBUFFER, 0);
1912 static void vigs_gl_surface_convert(struct vigs_surface *dst,
1913 uint32_t dst_format,
1914 struct vigs_surface *src,
1915 uint32_t src_format,
1918 uint32_t width = dst->ws_sfc->width;
1919 uint32_t height = dst->ws_sfc->height;
1920 bool conversion_supported = true;
1922 struct vigsp_copy entry = {
1925 .size = { width, height }
1928 struct vigs_gl_surface *gl_dst = (struct vigs_gl_surface *)dst;
1931 vigs_gl_create_ortho(0.0f, width, height, 0.0f,
1932 -1.0f, 1.0f, gl_dst->ortho);
1935 switch (dst_format) {
1936 case DRM_FORMAT_ARGB8888:
1937 switch (src_format) {
1938 case DRM_FORMAT_YUV420:
1939 vigs_gl_surface_convert_yuv2argb(dst, src);
1941 case DRM_FORMAT_ARGB8888:
1942 vigs_gl_surface_copy(dst, src, &entry, 1);
1945 conversion_supported = false;
1949 case DRM_FORMAT_XBGR8888:
1950 switch (src_format) {
1951 case DRM_FORMAT_ARGB8888:
1952 vigs_gl_surface_convert_argb2xbgr(dst, src);
1955 conversion_supported = false;
1960 conversion_supported = false;
1965 vigs_gl_create_ortho(0.0f, width, 0.0f, height,
1966 -1.0f, 1.0f, gl_dst->ortho);
1969 if (!conversion_supported) {
1970 VIGS_LOG_ERROR("format conversion from 0x%x to 0x%x is not supported",
1976 static void vigs_gl_surface_destroy(struct vigs_surface *sfc)
1978 struct vigs_gl_backend *gl_backend = (struct vigs_gl_backend*)sfc->backend;
1979 struct vigs_gl_surface *gl_sfc = (struct vigs_gl_surface*)sfc;
1980 struct vigs_winsys_gl_surface *ws_sfc = get_ws_sfc(gl_sfc);
1982 vigs_winsys_gl_surface_orphan(ws_sfc);
1985 vigs_gl_pool_release(gl_backend->fb_pool,
1987 sfc->ws_sfc->height,
1990 if (gl_sfc->tmp_tex) {
1991 vigs_gl_pool_release(gl_backend->tex_pool,
1993 sfc->ws_sfc->height,
1997 gl_backend->DeleteTextures(3, &gl_sfc->yuv_textures[0]);
1999 vigs_surface_cleanup(&gl_sfc->base);
2008 static struct vigs_surface *vigs_gl_backend_create_surface(struct vigs_backend *backend,
2012 vigsp_surface_format format,
2013 vigsp_surface_id id)
2015 struct vigs_gl_surface *gl_sfc = NULL;
2016 struct vigs_winsys_gl_surface *ws_sfc = NULL;
2017 GLint tex_internalformat;
2023 case vigsp_surface_bgrx8888:
2024 case vigsp_surface_bgra8888:
2025 tex_internalformat = GL_RGBA8;
2026 tex_format = GL_BGRA;
2027 tex_type = GL_UNSIGNED_INT_8_8_8_8_REV;
2034 tex_bpp = vigs_format_bpp(format);
2036 if ((width * tex_bpp) != stride) {
2037 VIGS_LOG_ERROR("Custom strides not supported yet");
2041 gl_sfc = g_malloc0(sizeof(*gl_sfc));
2043 ws_sfc = vigs_winsys_gl_surface_create((struct vigs_gl_backend*)backend,
2051 vigs_surface_init(&gl_sfc->base,
2058 vigs_gl_create_ortho(0.0f, width, 0.0f, height,
2059 -1.0f, 1.0f, gl_sfc->ortho);
2061 ws_sfc->base.base.release(&ws_sfc->base.base);
2063 gl_sfc->base.read_pixels = &vigs_gl_surface_read_pixels;
2064 gl_sfc->base.draw_pixels = &vigs_gl_surface_draw_pixels;
2065 gl_sfc->base.draw_pixels_scaled = &vigs_gl_surface_draw_pixels_scaled;
2066 gl_sfc->base.copy = &vigs_gl_surface_copy;
2067 gl_sfc->base.solid_fill = &vigs_gl_surface_solid_fill;
2068 gl_sfc->base.ga_copy = &vigs_gl_surface_ga_copy;
2069 gl_sfc->base.convert = &vigs_gl_surface_convert;
2070 gl_sfc->base.destroy = &vigs_gl_surface_destroy;
2072 return &gl_sfc->base;
2076 vigs_gl_backend_sort_planes(const struct vigs_plane *planes,
2077 const struct vigs_plane **sorted_planes)
2080 * Sort planes, only 2 of them now, don't bother...
2081 * The 3rd plane is for HW cursor (should always be on top).
2084 assert(VIGS_MAX_PLANES == 3);
2086 if (planes[0].z_pos <= planes[1].z_pos) {
2087 sorted_planes[0] = &planes[0];
2088 sorted_planes[1] = &planes[1];
2090 sorted_planes[0] = &planes[1];
2091 sorted_planes[1] = &planes[0];
2094 sorted_planes[2] = &planes[2];
2098 * 'above_root' means we want to render only planes that are above root surface.
2099 * 'bottom' means that if at least one plane is going to be rendered it'll be
2100 * bottom plane, i.e. the first one in surface stack.
2102 static bool vigs_gl_backend_composite_planes(struct vigs_gl_backend *gl_backend,
2103 const struct vigs_plane **planes,
2109 GLfloat *vert_coords = vigs_vector_data(&gl_backend->v1);
2110 GLfloat *tex_coords = vigs_vector_data(&gl_backend->v2);
2112 for (i = 0; i < VIGS_MAX_PLANES; ++i) {
2113 const struct vigs_plane *plane = planes[i];
2114 GLfloat src_w, src_h;
2115 GLfloat tmp_x, tmp_y;
2117 if (!vigs_plane_enabled(plane) || ((plane->z_pos >= 0) ^ above_root)) {
2121 VIGS_LOG_DEBUG("plane[%u]: %ux%u format = %d, z_pos = %d, hflip = %d,"
2122 " vflip = %d, rotation = %d ",
2132 src_w = plane->width;
2133 src_h = plane->height;
2135 vert_coords[6] = vert_coords[0] = plane->dst_x;
2136 vert_coords[7] = vert_coords[1] = plane->dst_y;
2137 vert_coords[2] = plane->dst_x + (int)plane->dst_size.w;
2138 vert_coords[3] = plane->dst_y;
2139 vert_coords[8] = vert_coords[4] = plane->dst_x + (int)plane->dst_size.w;
2140 vert_coords[9] = vert_coords[5] = plane->dst_y + (int)plane->dst_size.h;
2141 vert_coords[10] = plane->dst_x;
2142 vert_coords[11] = plane->dst_y + (int)plane->dst_size.h;
2144 tex_coords[6] = tex_coords[0] = (GLfloat)plane->src_rect.pos.x / src_w;
2145 tex_coords[7] = tex_coords[1] = (GLfloat)(src_h - plane->src_rect.pos.y) / src_h;
2146 tex_coords[2] = (GLfloat)(plane->src_rect.pos.x + plane->src_rect.size.w) / src_w;
2147 tex_coords[3] = (GLfloat)(src_h - plane->src_rect.pos.y) / src_h;
2148 tex_coords[8] = tex_coords[4] = (GLfloat)(plane->src_rect.pos.x + plane->src_rect.size.w) / src_w;
2149 tex_coords[9] = tex_coords[5] = (GLfloat)(src_h - (plane->src_rect.pos.y + plane->src_rect.size.h)) / src_h;
2150 tex_coords[10] = (GLfloat)plane->src_rect.pos.x / src_w;
2151 tex_coords[11] = (GLfloat)(src_h - (plane->src_rect.pos.y + plane->src_rect.size.h)) / src_h;
2154 tmp_x = tex_coords[0];
2155 tmp_y = tex_coords[1];
2157 tex_coords[6] = tex_coords[0] = tex_coords[2];
2158 tex_coords[7] = tex_coords[1] = tex_coords[3];
2160 tex_coords[2] = tmp_x;
2161 tex_coords[3] = tmp_y;
2163 tmp_x = tex_coords[4];
2164 tmp_y = tex_coords[5];
2166 tex_coords[8] = tex_coords[4] = tex_coords[10];
2167 tex_coords[9] = tex_coords[5] = tex_coords[11];
2169 tex_coords[10] = tmp_x;
2170 tex_coords[11] = tmp_y;
2174 tmp_x = tex_coords[0];
2175 tmp_y = tex_coords[1];
2177 tex_coords[6] = tex_coords[0] = tex_coords[10];
2178 tex_coords[7] = tex_coords[1] = tex_coords[11];
2180 tex_coords[10] = tmp_x;
2181 tex_coords[11] = tmp_y;
2183 tmp_x = tex_coords[4];
2184 tmp_y = tex_coords[5];
2186 tex_coords[8] = tex_coords[4] = tex_coords[2];
2187 tex_coords[9] = tex_coords[5] = tex_coords[3];
2189 tex_coords[2] = tmp_x;
2190 tex_coords[3] = tmp_y;
2193 switch (plane->rotation) {
2194 case vigsp_rotation90:
2195 tmp_x = tex_coords[0];
2196 tmp_y = tex_coords[1];
2198 tex_coords[6] = tex_coords[0] = tex_coords[10];
2199 tex_coords[7] = tex_coords[1] = tex_coords[11];
2200 tex_coords[10] = tex_coords[4];
2201 tex_coords[11] = tex_coords[5];
2202 tex_coords[8] = tex_coords[4] = tex_coords[2];
2203 tex_coords[9] = tex_coords[5] = tex_coords[3];
2204 tex_coords[2] = tmp_x;
2205 tex_coords[3] = tmp_y;
2208 case vigsp_rotation180:
2209 tmp_x = tex_coords[0];
2210 tmp_y = tex_coords[1];
2212 tex_coords[6] = tex_coords[0] = tex_coords[4];
2213 tex_coords[7] = tex_coords[1] = tex_coords[5];
2214 tex_coords[8] = tex_coords[4] = tmp_x;
2215 tex_coords[9] = tex_coords[5] = tmp_y;
2217 tmp_x = tex_coords[2];
2218 tmp_y = tex_coords[3];
2220 tex_coords[2] = tex_coords[10];
2221 tex_coords[3] = tex_coords[11];
2223 tex_coords[10] = tmp_x;
2224 tex_coords[11] = tmp_y;
2227 case vigsp_rotation270:
2228 tmp_x = tex_coords[0];
2229 tmp_y = tex_coords[1];
2231 tex_coords[6] = tex_coords[0] = tex_coords[2];
2232 tex_coords[7] = tex_coords[1] = tex_coords[3];
2233 tex_coords[2] = tex_coords[4];
2234 tex_coords[3] = tex_coords[5];
2235 tex_coords[8] = tex_coords[4] = tex_coords[10];
2236 tex_coords[9] = tex_coords[5] = tex_coords[11];
2237 tex_coords[10] = tmp_x;
2238 tex_coords[11] = tmp_y;
2241 case vigsp_rotation0:
2246 if (!bottom && (plane->format == vigsp_plane_bgra8888)) {
2248 * This is not bottom plane and it has alpha, turn on blending.
2250 gl_backend->Enable(GL_BLEND);
2251 gl_backend->BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2253 gl_backend->Disable(GL_BLEND);
2256 if (plane->format == vigsp_plane_nv21) {
2257 struct vigs_gl_surface *gl_sfc;
2258 struct vigs_winsys_gl_surface *ws_sfc;
2260 gl_backend->UseProgram(gl_backend->nv21_prog_id);
2262 gl_backend->UniformMatrix4fv(gl_backend->nv21_prog_proj_loc,
2263 1, GL_FALSE, ortho);
2265 gl_sfc = (struct vigs_gl_surface*)plane->surfaces[1];
2266 ws_sfc = get_ws_sfc(gl_sfc);
2268 gl_backend->ActiveTexture(GL_TEXTURE1);
2269 gl_backend->BindTexture(GL_TEXTURE_2D, ws_sfc->tex);
2271 gl_backend->Uniform2f(gl_backend->nv21_prog_ctexSize_loc,
2272 ws_sfc->base.base.width,
2273 ws_sfc->base.base.height);
2275 gl_sfc = (struct vigs_gl_surface*)plane->surfaces[0];
2276 ws_sfc = get_ws_sfc(gl_sfc);
2278 gl_backend->ActiveTexture(GL_TEXTURE0);
2279 gl_backend->BindTexture(GL_TEXTURE_2D, ws_sfc->tex);
2281 gl_backend->Uniform2f(gl_backend->nv21_prog_ytexSize_loc,
2282 ws_sfc->base.base.width,
2283 ws_sfc->base.base.height);
2285 gl_backend->Uniform2f(gl_backend->nv21_prog_size_loc, src_w, src_h);
2287 vigs_gl_draw_nv21_prog(gl_backend, 6);
2289 gl_backend->UseProgram(gl_backend->tex_prog_id);
2290 } else if (plane->format == vigsp_plane_yuv420) {
2291 struct vigs_gl_surface *gl_sfc;
2292 struct vigs_winsys_gl_surface *ws_sfc;
2294 gl_backend->UseProgram(gl_backend->yuv420_prog_id);
2296 gl_backend->UniformMatrix4fv(gl_backend->yuv420_prog_proj_loc,
2297 1, GL_FALSE, ortho);
2299 gl_sfc = (struct vigs_gl_surface*)plane->surfaces[2];
2300 ws_sfc = get_ws_sfc(gl_sfc);
2302 gl_backend->ActiveTexture(GL_TEXTURE2);
2303 gl_backend->BindTexture(GL_TEXTURE_2D, ws_sfc->tex);
2305 gl_backend->Uniform2f(gl_backend->yuv420_prog_vtexSize_loc,
2306 ws_sfc->base.base.width,
2307 ws_sfc->base.base.height);
2309 gl_sfc = (struct vigs_gl_surface*)plane->surfaces[1];
2310 ws_sfc = get_ws_sfc(gl_sfc);
2312 gl_backend->ActiveTexture(GL_TEXTURE1);
2313 gl_backend->BindTexture(GL_TEXTURE_2D, ws_sfc->tex);
2315 gl_backend->Uniform2f(gl_backend->yuv420_prog_utexSize_loc,
2316 ws_sfc->base.base.width,
2317 ws_sfc->base.base.height);
2319 gl_sfc = (struct vigs_gl_surface*)plane->surfaces[0];
2320 ws_sfc = get_ws_sfc(gl_sfc);
2322 gl_backend->ActiveTexture(GL_TEXTURE0);
2323 gl_backend->BindTexture(GL_TEXTURE_2D, ws_sfc->tex);
2325 gl_backend->Uniform2f(gl_backend->yuv420_prog_ytexSize_loc,
2326 ws_sfc->base.base.width,
2327 ws_sfc->base.base.height);
2329 gl_backend->Uniform2f(gl_backend->yuv420_prog_size_loc, src_w, src_h);
2331 vigs_gl_draw_yuv420_prog(gl_backend, 6);
2333 gl_backend->UseProgram(gl_backend->tex_prog_id);
2335 struct vigs_gl_surface *gl_sfc;
2336 struct vigs_winsys_gl_surface *ws_sfc;
2338 gl_sfc = (struct vigs_gl_surface*)plane->surfaces[0];
2339 ws_sfc = get_ws_sfc(gl_sfc);
2341 gl_backend->BindTexture(GL_TEXTURE_2D, ws_sfc->tex);
2343 vigs_gl_draw_tex_prog(gl_backend, 6);
2352 static bool vigs_gl_backend_composite(struct vigs_surface *surface,
2353 const struct vigs_plane *planes,
2355 uint8_t *display_data)
2357 struct vigs_gl_backend *gl_backend = (struct vigs_gl_backend*)surface->backend;
2358 struct vigs_gl_surface *gl_root_sfc = (struct vigs_gl_surface*)surface;
2359 struct vigs_winsys_gl_surface *ws_root_sfc = get_ws_sfc(gl_root_sfc);
2362 GLfloat *vert_coords;
2363 GLfloat *tex_coords;
2364 const struct vigs_plane *sorted_planes[VIGS_MAX_PLANES];
2367 VIGS_LOG_TRACE("enter");
2370 if (!vigs_qt5_onscreen_enabled() && !planes_dirty) {
2371 memcpy(display_data,
2373 surface->stride * surface->ws_sfc->height);
2376 } else if (!ws_root_sfc->tex) {
2377 VIGS_LOG_WARN("compositing garbage (root surface) ???");
2380 if (!vigs_winsys_gl_surface_create_texture(ws_root_sfc)) {
2384 if (!vigs_gl_update_dpy_texture(gl_backend,
2385 surface->ws_sfc->width,
2386 surface->ws_sfc->height)) {
2390 for (i = 0; i < VIGS_MAX_PLANES; ++i) {
2391 struct vigs_gl_surface *gl_sfc;
2392 struct vigs_winsys_gl_surface *ws_sfc;
2394 if (!vigs_plane_enabled(&planes[i])) {
2398 for (j = 0; j < 4; ++j) {
2399 gl_sfc = (struct vigs_gl_surface*)planes[i].surfaces[j];
2405 ws_sfc = get_ws_sfc(gl_sfc);
2408 VIGS_LOG_WARN("compositing garbage (plane %u, sfc %d) ???", i, j);
2411 if (!vigs_winsys_gl_surface_create_texture(ws_sfc)) {
2417 if (!vigs_gl_surface_setup_framebuffer(gl_root_sfc,
2418 gl_backend->tex_prog_id,
2419 gl_backend->tex_prog_proj_loc)) {
2423 vigs_gl_backend_sort_planes(planes, sorted_planes);
2425 vigs_vector_resize(&gl_backend->v1, 0);
2426 vigs_vector_resize(&gl_backend->v2, 0);
2428 vert_coords = vigs_vector_append(&gl_backend->v1,
2429 (12 * sizeof(GLfloat)));
2430 tex_coords = vigs_vector_append(&gl_backend->v2,
2431 (12 * sizeof(GLfloat)));
2435 * Root surface is scanout, upload it to texture.
2439 gl_backend->PixelStorei(GL_UNPACK_ALIGNMENT, 1);
2440 gl_backend->PixelStorei(GL_UNPACK_ROW_LENGTH, 0);
2441 gl_backend->PixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
2442 gl_backend->PixelStorei(GL_UNPACK_SKIP_ROWS, 0);
2444 gl_backend->BindTexture(GL_TEXTURE_2D, ws_root_sfc->tex);
2446 gl_backend->TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
2447 ws_root_sfc->base.base.width,
2448 ws_root_sfc->base.base.height,
2449 ws_root_sfc->tex_format,
2450 ws_root_sfc->tex_type,
2454 gl_backend->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
2455 GL_TEXTURE_2D, gl_backend->current_dpy->tex, 0);
2457 gl_backend->Clear(GL_COLOR_BUFFER_BIT);
2459 bottom = vigs_gl_backend_composite_planes(gl_backend,
2463 gl_root_sfc->ortho);
2466 * Render root surface.
2469 vert_coords[6] = vert_coords[0] = 0;
2470 vert_coords[7] = vert_coords[1] = ws_root_sfc->base.base.height;
2471 vert_coords[2] = ws_root_sfc->base.base.width;
2472 vert_coords[3] = ws_root_sfc->base.base.height;
2473 vert_coords[8] = vert_coords[4] = ws_root_sfc->base.base.width;
2474 vert_coords[9] = vert_coords[5] = 0;
2475 vert_coords[10] = 0;
2476 vert_coords[11] = 0;
2478 if (!surface->ptr) {
2479 tex_coords[6] = tex_coords[0] = 0;
2480 tex_coords[7] = tex_coords[1] = 0;
2483 tex_coords[8] = tex_coords[4] = 1;
2484 tex_coords[9] = tex_coords[5] = 1;
2488 tex_coords[6] = tex_coords[0] = 0;
2489 tex_coords[7] = tex_coords[1] = 1;
2492 tex_coords[8] = tex_coords[4] = 1;
2493 tex_coords[9] = tex_coords[5] = 0;
2500 * Root surface has planes beneath it, turn on blending.
2502 * Note that we DON'T check for alpha on root surface, i.e.:
2503 * (surface->format == vigsp_surface_bgra8888)
2505 * + X.Org doesn't allow having 32 depths, i.e. only bpp can
2506 * be 32, depth must be <= 24, i.e. X.Org is not underlay-aware,
2507 * but that doesn't mean we can't have them with X.Org
2508 * + Since we DO have something beneath the root surface that means
2509 * root surface just got to have alpha, otherwise user won't be
2510 * able to see that "something", i.e. specifying alpha in root
2511 * surface format is not that necessary in this case
2513 gl_backend->Enable(GL_BLEND);
2514 gl_backend->BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2516 gl_backend->Disable(GL_BLEND);
2519 gl_backend->BindTexture(GL_TEXTURE_2D, ws_root_sfc->tex);
2521 vigs_gl_draw_tex_prog(gl_backend, 6);
2525 vigs_gl_backend_composite_planes(gl_backend,
2529 gl_root_sfc->ortho);
2532 gl_backend->BindFramebuffer(GL_FRAMEBUFFER, 0);
2537 static bool vigs_gl_backend_capture(struct vigs_surface *surface,
2540 struct vigs_gl_backend *gl_backend = (struct vigs_gl_backend*)surface->backend;
2542 if (gl_backend->read_pixels_make_current(gl_backend, true)) {
2544 if (!gl_backend->dpy_fb) {
2545 gl_backend->GenFramebuffers(1, &gl_backend->dpy_fb);
2547 if (!gl_backend->dpy_fb) {
2548 VIGS_LOG_ERROR("cannot create capture FB");
2550 gl_backend->read_pixels_make_current(gl_backend, false);
2557 gl_backend->BindFramebuffer(GL_FRAMEBUFFER, gl_backend->dpy_fb);
2558 gl_backend->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
2559 GL_TEXTURE_2D, gl_backend->current_dpy->tex, 0);
2561 gl_backend->ReadPixels(0, 0, gl_backend->current_dpy->width,
2562 gl_backend->current_dpy->height,
2563 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
2565 gl_backend->BindFramebuffer(GL_FRAMEBUFFER, 0);
2567 gl_backend->read_pixels_make_current(gl_backend, false);
2575 static void vigs_gl_backend_batch_end(struct vigs_backend *backend)
2577 struct vigs_gl_backend *gl_backend = (struct vigs_gl_backend*)backend;
2579 gl_backend->Finish();
2580 gl_backend->make_current(gl_backend, false);
2583 static bool vigs_gl_backend_display(struct vigs_backend *backend,
2584 uint8_t *display_data)
2586 struct vigs_gl_backend *gl_backend = (struct vigs_gl_backend*)backend;
2588 VIGS_LOG_TRACE("enter");
2590 if (vigs_qt5_onscreen_enabled()) {
2591 if (gl_backend->current_dpy && gl_backend->current_dpy->tex) {
2592 vigs_qt5_dpy_render_texture(gl_backend->current_dpy);
2597 if (gl_backend->read_pixels_make_current(gl_backend, true)) {
2598 if (!gl_backend->dpy_fb) {
2599 gl_backend->GenFramebuffers(1, &gl_backend->dpy_fb);
2600 if (!gl_backend->dpy_fb) {
2601 VIGS_LOG_CRITICAL("cannot create FB");
2605 gl_backend->BindFramebuffer(GL_FRAMEBUFFER, gl_backend->dpy_fb);
2608 gl_backend->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
2609 GL_TEXTURE_2D, gl_backend->current_dpy->tex, 0);
2611 gl_backend->ReadPixels(0, 0, gl_backend->current_dpy->width,
2612 gl_backend->current_dpy->height,
2613 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
2616 gl_backend->read_pixels_make_current(gl_backend, false);
2624 bool vigs_gl_backend_init(struct vigs_gl_backend *gl_backend)
2626 if (!gl_backend->make_current(gl_backend, true)) {
2630 gl_backend->tex_pool = vigs_gl_pool_create("tmp_tex",
2631 &vigs_gl_backend_alloc_tmp_texture,
2632 &vigs_gl_backend_release_tmp_texture,
2634 gl_backend->fb_pool = vigs_gl_pool_create("fb",
2635 &vigs_gl_backend_alloc_framebuffer,
2636 &vigs_gl_backend_release_framebuffer,
2639 if (gl_backend->is_gl_2) {
2640 const char *tmp = (const char*)gl_backend->GetString(GL_EXTENSIONS);
2642 if (!tmp || (strstr(tmp, "GL_ARB_map_buffer_range ") == NULL)) {
2643 VIGS_LOG_WARN("glMapBufferRange not supported, using glBufferSubData");
2646 gl_backend->MapBufferRange = NULL;
2648 gl_backend->GenVertexArrays(1, &gl_backend->vao);
2650 if (!gl_backend->vao) {
2651 VIGS_LOG_CRITICAL("cannot create VAO");
2655 gl_backend->BindVertexArray(gl_backend->vao);
2658 VIGS_LOG_INFO("Current GL_VENDOR = %s",
2659 (const char *)gl_backend->GetString(GL_VENDOR));
2660 VIGS_LOG_INFO("Current GL_RENDERER = %s",
2661 (const char *)gl_backend->GetString(GL_RENDERER));
2662 VIGS_LOG_INFO("Current GL_VERSION = %s",
2663 (const char *)gl_backend->GetString(GL_VERSION));
2665 gl_backend->tex_prog_vs_id = vigs_gl_create_shader(gl_backend,
2666 (gl_backend->is_gl_2 ? g_vs_tex_source_gl2 : g_vs_tex_source_gl3),
2669 if (!gl_backend->tex_prog_vs_id) {
2673 gl_backend->tex_prog_fs_id = vigs_gl_create_shader(gl_backend,
2674 (gl_backend->is_gl_2 ? g_fs_tex_source_gl2 : g_fs_tex_source_gl3),
2675 GL_FRAGMENT_SHADER);
2677 if (!gl_backend->tex_prog_fs_id) {
2681 gl_backend->tex_prog_id = vigs_gl_create_program(gl_backend,
2682 gl_backend->tex_prog_vs_id,
2683 gl_backend->tex_prog_fs_id);
2685 if (!gl_backend->tex_prog_id) {
2689 gl_backend->tex_prog_proj_loc = gl_backend->GetUniformLocation(gl_backend->tex_prog_id, "proj");
2690 gl_backend->tex_prog_vertCoord_loc = gl_backend->GetAttribLocation(gl_backend->tex_prog_id, "vertCoord");
2691 gl_backend->tex_prog_texCoord_loc = gl_backend->GetAttribLocation(gl_backend->tex_prog_id, "texCoord");
2693 gl_backend->color_prog_vs_id = vigs_gl_create_shader(gl_backend,
2694 (gl_backend->is_gl_2 ? g_vs_color_source_gl2 : g_vs_color_source_gl3),
2697 if (!gl_backend->color_prog_vs_id) {
2701 gl_backend->color_prog_fs_id = vigs_gl_create_shader(gl_backend,
2702 (gl_backend->is_gl_2 ? g_fs_color_source_gl2 : g_fs_color_source_gl3),
2703 GL_FRAGMENT_SHADER);
2705 if (!gl_backend->color_prog_fs_id) {
2709 gl_backend->color_prog_id = vigs_gl_create_program(gl_backend,
2710 gl_backend->color_prog_vs_id,
2711 gl_backend->color_prog_fs_id);
2713 if (!gl_backend->color_prog_id) {
2717 gl_backend->color_prog_proj_loc = gl_backend->GetUniformLocation(gl_backend->color_prog_id, "proj");
2718 gl_backend->color_prog_vertCoord_loc = gl_backend->GetAttribLocation(gl_backend->color_prog_id, "vertCoord");
2719 gl_backend->color_prog_color_loc = gl_backend->GetUniformLocation(gl_backend->color_prog_id, "color");
2721 gl_backend->nv21_prog_vs_id = vigs_gl_create_shader(gl_backend,
2722 (gl_backend->is_gl_2 ? g_vs_nv21_source_gl2 : g_vs_nv21_source_gl3),
2725 if (!gl_backend->nv21_prog_vs_id) {
2729 gl_backend->nv21_prog_fs_id = vigs_gl_create_shader(gl_backend,
2730 (gl_backend->is_gl_2 ? g_fs_nv21_source_gl2 : g_fs_nv21_source_gl3),
2731 GL_FRAGMENT_SHADER);
2733 if (!gl_backend->nv21_prog_fs_id) {
2737 gl_backend->nv21_prog_id = vigs_gl_create_program(gl_backend,
2738 gl_backend->nv21_prog_vs_id,
2739 gl_backend->nv21_prog_fs_id);
2741 if (!gl_backend->nv21_prog_id) {
2745 gl_backend->nv21_prog_proj_loc = gl_backend->GetUniformLocation(gl_backend->nv21_prog_id, "proj");
2746 gl_backend->nv21_prog_vertCoord_loc = gl_backend->GetAttribLocation(gl_backend->nv21_prog_id, "vertCoord");
2747 gl_backend->nv21_prog_texCoord_loc = gl_backend->GetAttribLocation(gl_backend->nv21_prog_id, "texCoord");
2748 gl_backend->nv21_prog_size_loc = gl_backend->GetUniformLocation(gl_backend->nv21_prog_id, "size");
2749 gl_backend->nv21_prog_ytexSize_loc = gl_backend->GetUniformLocation(gl_backend->nv21_prog_id, "ytexSize");
2750 gl_backend->nv21_prog_ctexSize_loc = gl_backend->GetUniformLocation(gl_backend->nv21_prog_id, "ctexSize");
2751 gl_backend->nv21_prog_ytex_loc = gl_backend->GetUniformLocation(gl_backend->nv21_prog_id, "ytex");
2752 gl_backend->nv21_prog_ctex_loc = gl_backend->GetUniformLocation(gl_backend->nv21_prog_id, "ctex");
2754 gl_backend->yuv420_prog_vs_id = vigs_gl_create_shader(gl_backend,
2755 (gl_backend->is_gl_2 ? g_vs_yuv420_source_gl2 : g_vs_yuv420_source_gl3),
2758 if (!gl_backend->yuv420_prog_vs_id) {
2762 gl_backend->yuv420_prog_fs_id = vigs_gl_create_shader(gl_backend,
2763 (gl_backend->is_gl_2 ? g_fs_yuv420_source_gl2 : g_fs_yuv420_source_gl3),
2764 GL_FRAGMENT_SHADER);
2766 if (!gl_backend->yuv420_prog_fs_id) {
2770 gl_backend->yuv420_prog_id = vigs_gl_create_program(gl_backend,
2771 gl_backend->yuv420_prog_vs_id,
2772 gl_backend->yuv420_prog_fs_id);
2774 if (!gl_backend->yuv420_prog_id) {
2778 gl_backend->yuv420_prog_proj_loc = gl_backend->GetUniformLocation(gl_backend->yuv420_prog_id, "proj");
2779 gl_backend->yuv420_prog_vertCoord_loc = gl_backend->GetAttribLocation(gl_backend->yuv420_prog_id, "vertCoord");
2780 gl_backend->yuv420_prog_texCoord_loc = gl_backend->GetAttribLocation(gl_backend->yuv420_prog_id, "texCoord");
2781 gl_backend->yuv420_prog_size_loc = gl_backend->GetUniformLocation(gl_backend->yuv420_prog_id, "size");
2782 gl_backend->yuv420_prog_ytexSize_loc = gl_backend->GetUniformLocation(gl_backend->yuv420_prog_id, "ytexSize");
2783 gl_backend->yuv420_prog_utexSize_loc = gl_backend->GetUniformLocation(gl_backend->yuv420_prog_id, "utexSize");
2784 gl_backend->yuv420_prog_vtexSize_loc = gl_backend->GetUniformLocation(gl_backend->yuv420_prog_id, "vtexSize");
2785 gl_backend->yuv420_prog_ytex_loc = gl_backend->GetUniformLocation(gl_backend->yuv420_prog_id, "ytex");
2786 gl_backend->yuv420_prog_utex_loc = gl_backend->GetUniformLocation(gl_backend->yuv420_prog_id, "utex");
2787 gl_backend->yuv420_prog_vtex_loc = gl_backend->GetUniformLocation(gl_backend->yuv420_prog_id, "vtex");
2789 gl_backend->xbgr_prog_fs_id = vigs_gl_create_shader(gl_backend,
2790 (gl_backend->is_gl_2 ? g_fs_xbgr_source_gl2 : g_fs_xbgr_source_gl3),
2791 GL_FRAGMENT_SHADER);
2793 if (!gl_backend->xbgr_prog_fs_id) {
2798 * Let's borrow compiled vertex shader from tex program
2801 gl_backend->xbgr_prog_id = vigs_gl_create_program(gl_backend,
2802 gl_backend->tex_prog_vs_id,
2803 gl_backend->xbgr_prog_fs_id);
2805 if (!gl_backend->xbgr_prog_id) {
2809 gl_backend->xbgr_prog_proj_loc = gl_backend->GetUniformLocation(gl_backend->xbgr_prog_id, "proj");
2810 gl_backend->xbgr_prog_vertCoord_loc = gl_backend->GetAttribLocation(gl_backend->xbgr_prog_id, "vertCoord");
2811 gl_backend->xbgr_prog_texCoord_loc = gl_backend->GetAttribLocation(gl_backend->xbgr_prog_id, "texCoord");
2813 gl_backend->GenBuffers(1, &gl_backend->vbo);
2814 if (!gl_backend->vbo) {
2815 VIGS_LOG_CRITICAL("cannot create VBOs");
2819 gl_backend->BindBuffer(GL_ARRAY_BUFFER, gl_backend->vbo);
2821 gl_backend->UseProgram(gl_backend->nv21_prog_id);
2822 gl_backend->Uniform1i(gl_backend->nv21_prog_ytex_loc, 0);
2823 gl_backend->Uniform1i(gl_backend->nv21_prog_ctex_loc, 1);
2825 gl_backend->UseProgram(gl_backend->yuv420_prog_id);
2826 gl_backend->Uniform1i(gl_backend->yuv420_prog_ytex_loc, 0);
2827 gl_backend->Uniform1i(gl_backend->yuv420_prog_utex_loc, 1);
2828 gl_backend->Uniform1i(gl_backend->yuv420_prog_vtex_loc, 2);
2830 gl_backend->UseProgram(gl_backend->tex_prog_id);
2831 gl_backend->cur_prog_id = gl_backend->tex_prog_id;
2833 gl_backend->ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
2834 gl_backend->Disable(GL_DEPTH_TEST);
2835 gl_backend->Disable(GL_BLEND);
2837 gl_backend->base.batch_start = &vigs_gl_backend_batch_start;
2838 gl_backend->base.create_surface = &vigs_gl_backend_create_surface;
2839 gl_backend->base.composite = &vigs_gl_backend_composite;
2840 gl_backend->base.capture = &vigs_gl_backend_capture;
2841 gl_backend->base.batch_end = &vigs_gl_backend_batch_end;
2842 gl_backend->base.display = &vigs_gl_backend_display;
2844 gl_backend->make_current(gl_backend, false);
2846 vigs_vector_init(&gl_backend->v1, 0);
2847 vigs_vector_init(&gl_backend->v2, 0);
2850 for (i = 0; i < TEXTURE_NUM; ++i) {
2851 gl_backend->dpy_items[i].available = true;
2852 qemu_mutex_init(&gl_backend->dpy_items[i].mutex);
2858 gl_backend->make_current(gl_backend, false);
2863 void vigs_gl_backend_cleanup(struct vigs_gl_backend *gl_backend)
2865 if (gl_backend->make_current(gl_backend, true)) {
2867 for (i = 0; i < TEXTURE_NUM; i++) {
2868 if (gl_backend->dpy_items[i].tex) {
2869 gl_backend->DeleteTextures(1, &gl_backend->dpy_items[i].tex);
2871 qemu_mutex_destroy(&gl_backend->dpy_items[i].mutex);
2873 if (gl_backend->dpy_fb) {
2874 gl_backend->DeleteFramebuffers(1, &gl_backend->dpy_fb);
2876 gl_backend->DeleteBuffers(1, &gl_backend->vbo);
2877 gl_backend->DetachShader(gl_backend->yuv420_prog_id,
2878 gl_backend->yuv420_prog_vs_id);
2879 gl_backend->DetachShader(gl_backend->yuv420_prog_id,
2880 gl_backend->yuv420_prog_fs_id);
2881 gl_backend->DeleteShader(gl_backend->yuv420_prog_vs_id);
2882 gl_backend->DeleteShader(gl_backend->yuv420_prog_fs_id);
2883 gl_backend->DeleteProgram(gl_backend->yuv420_prog_id);
2884 gl_backend->DetachShader(gl_backend->nv21_prog_id,
2885 gl_backend->nv21_prog_vs_id);
2886 gl_backend->DetachShader(gl_backend->nv21_prog_id,
2887 gl_backend->nv21_prog_fs_id);
2888 gl_backend->DeleteShader(gl_backend->nv21_prog_vs_id);
2889 gl_backend->DeleteShader(gl_backend->nv21_prog_fs_id);
2890 gl_backend->DeleteProgram(gl_backend->nv21_prog_id);
2891 gl_backend->DetachShader(gl_backend->color_prog_id,
2892 gl_backend->color_prog_vs_id);
2893 gl_backend->DetachShader(gl_backend->color_prog_id,
2894 gl_backend->color_prog_fs_id);
2895 gl_backend->DeleteShader(gl_backend->color_prog_vs_id);
2896 gl_backend->DeleteShader(gl_backend->color_prog_fs_id);
2897 gl_backend->DeleteProgram(gl_backend->color_prog_id);
2898 gl_backend->DetachShader(gl_backend->tex_prog_id,
2899 gl_backend->tex_prog_vs_id);
2900 gl_backend->DetachShader(gl_backend->tex_prog_id,
2901 gl_backend->tex_prog_fs_id);
2902 gl_backend->DeleteShader(gl_backend->tex_prog_vs_id);
2903 gl_backend->DeleteShader(gl_backend->tex_prog_fs_id);
2904 gl_backend->DeleteProgram(gl_backend->tex_prog_id);
2906 if (!gl_backend->is_gl_2) {
2907 gl_backend->DeleteVertexArrays(1, &gl_backend->vao);
2910 vigs_gl_pool_destroy(gl_backend->fb_pool);
2911 vigs_gl_pool_destroy(gl_backend->tex_pool);
2913 gl_backend->make_current(gl_backend, false);
2916 vigs_vector_cleanup(&gl_backend->v2);
2917 vigs_vector_cleanup(&gl_backend->v1);