+ dst = data;
+ src = bo->map + x_bytes + (y * internal_stride);
+
+ for (int i = 0; i < height; i++) {
+ memcpy(dst, src, width_bytes);
+ dst += stride;
+ src += internal_stride;
+ }
+
+ gbm_dri_bo_unmap_dumb(bo);
+}
+
+static EGLBoolean
+drm_add_configs_for_visuals(_EGLDriver *drv, _EGLDisplay *disp)
+{
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+ const struct gbm_dri_visual *visuals = dri2_dpy->gbm_dri->visual_table;
+ int num_visuals = dri2_dpy->gbm_dri->num_visuals;
+ unsigned int format_count[num_visuals];
+ unsigned int config_count = 0;
+
+ memset(format_count, 0, num_visuals * sizeof(unsigned int));
+
+ for (unsigned i = 0; dri2_dpy->driver_configs[i]; i++) {
+ const __DRIconfig *config = dri2_dpy->driver_configs[i];
+ int shifts[4];
+ unsigned int sizes[4];
+ bool is_float;
+
+ dri2_get_shifts_and_sizes(dri2_dpy->core, config, shifts, sizes);
+
+ dri2_get_render_type_float(dri2_dpy->core, config, &is_float);
+
+ for (unsigned j = 0; j < num_visuals; j++) {
+ struct dri2_egl_config *dri2_conf;
+
+ if (visuals[j].rgba_shifts.red != shifts[0] ||
+ visuals[j].rgba_shifts.green != shifts[1] ||
+ visuals[j].rgba_shifts.blue != shifts[2] ||
+ visuals[j].rgba_shifts.alpha != shifts[3] ||
+ visuals[j].rgba_sizes.red != sizes[0] ||
+ visuals[j].rgba_sizes.green != sizes[1] ||
+ visuals[j].rgba_sizes.blue != sizes[2] ||
+ visuals[j].rgba_sizes.alpha != sizes[3] ||
+ visuals[j].is_float != is_float)
+ continue;
+
+ const EGLint attr_list[] = {
+ EGL_NATIVE_VISUAL_ID, visuals[j].gbm_format,
+ EGL_NONE,
+ };
+
+ dri2_conf = dri2_add_config(disp, dri2_dpy->driver_configs[i],
+ config_count + 1, EGL_WINDOW_BIT, attr_list, NULL, NULL);
+ if (dri2_conf) {
+ if (dri2_conf->base.ConfigID == config_count + 1)
+ config_count++;
+ format_count[j]++;
+ }
+ }
+ }