static void gdk_x11_gl_context_dispose (GObject *gobject) { GdkWaylandGLContext *context_wayland = GDK_WAYLAND_GL_CONTEXT (gobject); if (context_wayland->egl_context != NULL) { GdkGLContext *context = GDK_GL_CONTEXT (gobject); GdkWindow *window = gdk_gl_context_get_window (context); GdkDisplay *display = gdk_window_get_display (window); GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display); if (eglGetCurrentContext () == context_wayland->egl_context) eglMakeCurrent(display_wayland->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); GDK_NOTE (OPENGL, g_print ("Destroying EGL context\n")); eglDestroyContext (display_wayland->egl_display, context_wayland->egl_context); context_wayland->egl_context = NULL; } G_OBJECT_CLASS (gdk_wayland_gl_context_parent_class)->dispose (gobject); }
static gboolean gdk_mir_display_make_gl_context_current (GdkDisplay *display, GdkGLContext *context) { EGLDisplay egl_display = _gdk_mir_display_get_egl_display (display); GdkMirGLContext *mir_context; GdkWindow *window; EGLSurface egl_surface; if (context == NULL) { eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); return TRUE; } mir_context = GDK_MIR_GL_CONTEXT (context); window = gdk_gl_context_get_window (context); if (mir_context->is_attached) { egl_surface = _gdk_mir_window_get_egl_surface (window, mir_context->egl_config); } else { if (_gdk_mir_display_have_egl_surfaceless_context (display)) egl_surface = EGL_NO_SURFACE; else egl_surface = _gdk_mir_window_get_dummy_egl_surface (window, mir_context->egl_config); } if (!eglMakeCurrent (egl_display, egl_surface, egl_surface, mir_context->egl_context)) { g_warning ("eglMakeCurrent failed"); return FALSE; } return TRUE; }
gboolean gdk_wayland_display_make_gl_context_current (GdkDisplay *display, GdkGLContext *context) { GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display); GdkWaylandGLContext *context_wayland; GdkWindow *window; EGLSurface egl_surface; if (context == NULL) { eglMakeCurrent(display_wayland->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); return TRUE; } context_wayland = GDK_WAYLAND_GL_CONTEXT (context); window = gdk_gl_context_get_window (context); if (context_wayland->is_attached) egl_surface = gdk_wayland_window_get_egl_surface (window->impl_window, context_wayland->egl_config); else { if (display_wayland->have_egl_surfaceless_context) egl_surface = EGL_NO_SURFACE; else egl_surface = gdk_wayland_window_get_dummy_egl_surface (window->impl_window, context_wayland->egl_config); } if (!eglMakeCurrent (display_wayland->egl_display, egl_surface, egl_surface, context_wayland->egl_context)) { g_warning ("eglMakeCurrent failed"); return FALSE; } return TRUE; }
static void gdk_wayland_gl_context_end_frame (GdkGLContext *context, cairo_region_t *painted, cairo_region_t *damage) { GdkWindow *window = gdk_gl_context_get_window (context); GdkDisplay *display = gdk_window_get_display (window); GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display); GdkWaylandGLContext *context_wayland = GDK_WAYLAND_GL_CONTEXT (context); EGLSurface egl_surface; gdk_gl_context_make_current (context); egl_surface = gdk_wayland_window_get_egl_surface (window->impl_window, context_wayland->egl_config); /* TODO: Use eglSwapBuffersWithDamageEXT if available */ if (display_wayland->have_egl_swap_buffers_with_damage) { int i, j, n_rects = cairo_region_num_rectangles (damage); EGLint *rects = g_new (EGLint, n_rects * 4); cairo_rectangle_int_t rect; int window_height = gdk_window_get_height (window); for (i = 0, j = 0; i < n_rects; i++) { cairo_region_get_rectangle (damage, i, &rect); rects[j++] = rect.x; rects[j++] = window_height - rect.height - rect.y; rects[j++] = rect.width; rects[j++] = rect.height; } eglSwapBuffersWithDamageEXT (display_wayland->egl_display, egl_surface, rects, n_rects); g_free (rects); } else eglSwapBuffers (display_wayland->egl_display, egl_surface); }
/* This is always called with the paint context current */ void gdk_gl_texture_from_surface (cairo_surface_t *surface, cairo_region_t *region) { GdkGLContext *paint_context; cairo_surface_t *image; double device_x_offset, device_y_offset; cairo_rectangle_int_t rect, e; int n_rects, i; GdkWindow *window; int unscaled_window_height; unsigned int texture_id; int window_scale; double sx, sy; float umax, vmax; gboolean use_texture_rectangle; guint target; paint_context = gdk_gl_context_get_current (); if ((_gdk_gl_flags & GDK_GL_SOFTWARE_DRAW_SURFACE) == 0 && paint_context && GDK_GL_CONTEXT_GET_CLASS (paint_context)->texture_from_surface && GDK_GL_CONTEXT_GET_CLASS (paint_context)->texture_from_surface (paint_context, surface, region)) return; /* Software fallback */ use_texture_rectangle = gdk_gl_context_use_texture_rectangle (paint_context); window = gdk_gl_context_get_window (paint_context); window_scale = gdk_window_get_scale_factor (window); gdk_window_get_unscaled_size (window, NULL, &unscaled_window_height); sx = sy = 1; cairo_surface_get_device_scale (window->current_paint.surface, &sx, &sy); cairo_surface_get_device_offset (surface, &device_x_offset, &device_y_offset); glGenTextures (1, &texture_id); if (use_texture_rectangle) target = GL_TEXTURE_RECTANGLE_ARB; else target = GL_TEXTURE_2D; glBindTexture (target, texture_id); glEnable (GL_SCISSOR_TEST); glTexParameteri (target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri (target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri (target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri (target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); n_rects = cairo_region_num_rectangles (region); #define FLIP_Y(_y) (unscaled_window_height - (_y)) for (i = 0; i < n_rects; i++) { cairo_region_get_rectangle (region, i, &rect); glScissor (rect.x * window_scale, FLIP_Y ((rect.y + rect.height) * window_scale), rect.width * window_scale, rect.height * window_scale); e = rect; e.x *= sx; e.y *= sy; e.x += (int)device_x_offset; e.y += (int)device_y_offset; e.width *= sx; e.height *= sy; image = cairo_surface_map_to_image (surface, &e); gdk_gl_context_upload_texture (paint_context, image, e.width, e.height, target); cairo_surface_unmap_image (surface, image); if (use_texture_rectangle) { umax = rect.width * sx; vmax = rect.height * sy; } else { umax = 1.0; vmax = 1.0; } { GdkTexturedQuad quad = { rect.x * window_scale, FLIP_Y(rect.y * window_scale), (rect.x + rect.width) * window_scale, FLIP_Y((rect.y + rect.height) * window_scale), 0, 0, umax, vmax, }; /* We don't want to combine the quads here, because they have different textures. * And we don't want to upload the unused source areas to make it one texture. */ gdk_gl_texture_quads (paint_context, target, 1, &quad); } } #undef FLIP_Y glDisable (GL_SCISSOR_TEST); glDeleteTextures (1, &texture_id); }
void gdk_gl_texture_quads (GdkGLContext *paint_context, guint texture_target, int n_quads, GdkTexturedQuad *quads) { GdkGLContextPaintData *paint_data = gdk_gl_context_get_paint_data (paint_context); GdkGLContextProgram *program; GdkWindow *window = gdk_gl_context_get_window (paint_context); int window_scale = gdk_window_get_scale_factor (window); float w = gdk_window_get_width (window) * window_scale; float h = gdk_window_get_height (window) * window_scale; int i; float *vertex_buffer_data; bind_vao (paint_data); if (paint_data->tmp_vertex_buffer == 0) glGenBuffers(1, &paint_data->tmp_vertex_buffer); if (texture_target == GL_TEXTURE_RECTANGLE_ARB) use_texture_rect_program (paint_data); else use_texture_2d_program (paint_data); program = paint_data->current_program; glActiveTexture (GL_TEXTURE0); glUniform1i(program->map_location, 0); /* Use texture unit 0 */ glEnableVertexAttribArray (program->position_location); glEnableVertexAttribArray (program->uv_location); glBindBuffer (GL_ARRAY_BUFFER, paint_data->tmp_vertex_buffer); glVertexAttribPointer (program->position_location, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, NULL); glVertexAttribPointer (program->uv_location, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, (void *) (sizeof(float) * 2)); #define VERTEX_SIZE 4 #define QUAD_N_VERTICES 6 #define QUAD_SIZE (VERTEX_SIZE * QUAD_N_VERTICES) vertex_buffer_data = g_new (float, n_quads * QUAD_SIZE); for (i = 0; i < n_quads; i++) { GdkTexturedQuad *quad = &quads[i]; float vertex_data[] = { (quad->x1 * 2) / w - 1, (quad->y1 * 2) / h - 1, quad->u1, quad->v1, (quad->x1 * 2) / w - 1, (quad->y2 * 2) / h - 1, quad->u1, quad->v2, (quad->x2 * 2) / w - 1, (quad->y1 * 2) / h - 1, quad->u2, quad->v1, (quad->x2 * 2) / w - 1, (quad->y2 * 2) / h - 1, quad->u2, quad->v2, (quad->x1 * 2) / w - 1, (quad->y2 * 2) / h - 1, quad->u1, quad->v2, (quad->x2 * 2) / w - 1, (quad->y1 * 2) / h - 1, quad->u2, quad->v1, }; float *vertex = &vertex_buffer_data[i * QUAD_SIZE]; memcpy (vertex, vertex_data, sizeof(vertex_data)); } glBufferData (GL_ARRAY_BUFFER, sizeof(float) * n_quads * QUAD_SIZE, vertex_buffer_data, GL_STREAM_DRAW); glDrawArrays (GL_TRIANGLES, 0, n_quads * QUAD_N_VERTICES); g_free (vertex_buffer_data); glDisableVertexAttribArray (program->position_location); glDisableVertexAttribArray (program->uv_location); }