diff options
Diffstat (limited to 'src/egl/drivers')
-rw-r--r-- | src/egl/drivers/dri2/platform_drm.c | 153 |
1 files changed, 152 insertions, 1 deletions
diff --git a/src/egl/drivers/dri2/platform_drm.c b/src/egl/drivers/dri2/platform_drm.c index 6ec63c1555..bafaa22b3c 100644 --- a/src/egl/drivers/dri2/platform_drm.c +++ b/src/egl/drivers/dri2/platform_drm.c @@ -71,6 +71,8 @@ dri2_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type, dri2_surf->base.Width = surf->base.width; dri2_surf->base.Height = surf->base.height; + surf->dri_private = dri2_surf; + break; default: goto cleanup_surf; @@ -125,10 +127,155 @@ dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf) return EGL_TRUE; } +static void +dri2_process_back_buffer(struct dri2_egl_surface *dri2_surf, unsigned format) +{ + struct dri2_egl_display *dri2_dpy = + dri2_egl_display(dri2_surf->base.Resource.Display); + + (void) format; + + switch (dri2_surf->base.Type) { + case EGL_WINDOW_BIT: + /* allocate a front buffer for our double-buffered window*/ + if (dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT] != NULL) + break; + dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT] = + dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen, + __DRI_BUFFER_FRONT_LEFT, format, + dri2_surf->base.Width, dri2_surf->base.Height); + break; + default: + break; + } +} + +static inline void +pointer_swap(const void **p1, const void **p2) +{ + const void *tmp = *p1; + *p1 = *p2; + *p2 = tmp; +} + +static __DRIbuffer * +dri2_get_buffers_with_format(__DRIdrawable * driDrawable, + int *width, int *height, + unsigned int *attachments, int count, + int *out_count, void *loaderPrivate) +{ + struct dri2_egl_surface *dri2_surf = loaderPrivate; + struct dri2_egl_display *dri2_dpy = + dri2_egl_display(dri2_surf->base.Resource.Display); + int i; + + dri2_surf->buffer_count = 0; + for (i = 0; i < 2*count; i+=2) { + assert(attachments[i] < __DRI_BUFFER_COUNT); + assert(dri2_surf->buffer_count < 5); + + if (dri2_surf->dri_buffers[attachments[i]] == NULL) { + + dri2_surf->dri_buffers[attachments[i]] = + dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen, + attachments[i], attachments[i+1], + dri2_surf->base.Width, dri2_surf->base.Height); + + if (!dri2_surf->dri_buffers[attachments[i]]) + continue; + + if (attachments[i] == __DRI_BUFFER_BACK_LEFT) + dri2_process_back_buffer(dri2_surf, attachments[i+1]); + } + + memcpy(&dri2_surf->buffers[dri2_surf->buffer_count], + dri2_surf->dri_buffers[attachments[i]], + sizeof(__DRIbuffer)); + + dri2_surf->buffer_count++; + } + + assert(dri2_surf->dri_buffers[__DRI_BUFFER_BACK_LEFT]); + + *out_count = dri2_surf->buffer_count; + if (dri2_surf->buffer_count == 0) + return NULL; + + *width = dri2_surf->base.Width; + *height = dri2_surf->base.Height; + + return dri2_surf->buffers; +} + +static __DRIbuffer * +dri2_get_buffers(__DRIdrawable * driDrawable, + int *width, int *height, + unsigned int *attachments, int count, + int *out_count, void *loaderPrivate) +{ + unsigned int *attachments_with_format; + __DRIbuffer *buffer; + const unsigned int format = 32; + int i; + + attachments_with_format = calloc(count * 2, sizeof(unsigned int)); + if (!attachments_with_format) { + *out_count = 0; + return NULL; + } + + for (i = 0; i < count; ++i) { + attachments_with_format[2*i] = attachments[i]; + attachments_with_format[2*i + 1] = format; + } + + buffer = + dri2_get_buffers_with_format(driDrawable, + width, height, + attachments_with_format, count, + out_count, loaderPrivate); + + free(attachments_with_format); + + return buffer; +} + +static void +dri2_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate) +{ + (void) driDrawable; + (void) loaderPrivate; +} + static EGLBoolean dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw) { - return EGL_FALSE; + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); + struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); + + if (dri2_surf->base.Type == EGL_WINDOW_BIT) { + pointer_swap( + (const void **) &dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT], + (const void **) &dri2_surf->dri_buffers[__DRI_BUFFER_BACK_LEFT]); + + dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT]->attachment = + __DRI_BUFFER_FRONT_LEFT; + dri2_surf->dri_buffers[__DRI_BUFFER_BACK_LEFT]->attachment = + __DRI_BUFFER_BACK_LEFT; + } + + _EGLContext *ctx; + if (dri2_drv->glFlush) { + ctx = _eglGetCurrentContext(); + if (ctx && ctx->DrawSurface == &dri2_surf->base) + dri2_drv->glFlush(); + } + + (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable); + (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable); + + return EGL_TRUE; } @@ -242,6 +389,10 @@ dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp) dri2_dpy->gbm_dri->lookup_image = dri2_lookup_egl_image; dri2_dpy->gbm_dri->lookup_user_data = disp; + dri2_dpy->gbm_dri->get_buffers = dri2_get_buffers; + dri2_dpy->gbm_dri->flush_front_buffer = dri2_flush_front_buffer; + dri2_dpy->gbm_dri->get_buffers_with_format = dri2_get_buffers_with_format; + dri2_setup_screen(disp); for (i = 0; dri2_dpy->driver_configs[i]; i++) |