Merge branch 'mesa_7_7_branch'
[mesa.git] / src / gallium / state_trackers / egl / egl_surface.c
index 69e2d6b7081eb28f8b0a338ca72f654a2ff3291f..d55aa51b82d98b5d776e698d0376e9862bc49fcc 100644 (file)
@@ -12,6 +12,9 @@
 
 #include "state_tracker/drm_api.h"
 
+#include "util/u_format.h"
+#include "util/u_rect.h"
+
 /*
  * Util functions
  */
@@ -33,34 +36,62 @@ drm_find_mode(drmModeConnectorPtr connector, _EGLMode *mode)
 }
 
 static struct st_framebuffer *
-drm_create_framebuffer(const __GLcontextModes *visual,
+drm_create_framebuffer(struct pipe_screen *screen,
+                       const __GLcontextModes *visual,
                        unsigned width,
                        unsigned height,
                        void *priv)
 {
-       enum pipe_format colorFormat, depthFormat, stencilFormat;
-
-       if (visual->redBits == 5)
-               colorFormat = PIPE_FORMAT_R5G6B5_UNORM;
-       else
-               colorFormat = PIPE_FORMAT_A8R8G8B8_UNORM;
-
-       if (visual->depthBits == 16)
-               depthFormat = PIPE_FORMAT_Z16_UNORM;
-       else if (visual->depthBits == 24)
-               depthFormat = PIPE_FORMAT_S8Z24_UNORM;
-       else
-               depthFormat = PIPE_FORMAT_NONE;
+       enum pipe_format color_format, depth_stencil_format;
+       boolean d_depth_bits_last;
+       boolean ds_depth_bits_last;
+
+       d_depth_bits_last =
+               screen->is_format_supported(screen, PIPE_FORMAT_X8Z24_UNORM,
+                                           PIPE_TEXTURE_2D,
+                                           PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0);
+       ds_depth_bits_last =
+               screen->is_format_supported(screen, PIPE_FORMAT_S8Z24_UNORM,
+                                           PIPE_TEXTURE_2D,
+                                           PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0);
+
+       if (visual->redBits == 8) {
+               if (visual->alphaBits == 8)
+                       color_format = PIPE_FORMAT_A8R8G8B8_UNORM;
+               else
+                       color_format = PIPE_FORMAT_X8R8G8B8_UNORM;
+       } else {
+               color_format = PIPE_FORMAT_R5G6B5_UNORM;
+       }
 
-       if (visual->stencilBits == 8)
-               stencilFormat = PIPE_FORMAT_S8Z24_UNORM;
-       else
-               stencilFormat = PIPE_FORMAT_NONE;
+       switch(visual->depthBits) {
+               default:
+               case 0:
+                       depth_stencil_format = PIPE_FORMAT_NONE;
+                       break;
+               case 16:
+                       depth_stencil_format = PIPE_FORMAT_Z16_UNORM;
+                       break;
+               case 24:
+                       if (visual->stencilBits == 0) {
+                               depth_stencil_format = (d_depth_bits_last) ?
+                                       PIPE_FORMAT_X8Z24_UNORM:
+                                       PIPE_FORMAT_Z24X8_UNORM;
+                       } else {
+                               depth_stencil_format = (ds_depth_bits_last) ?
+                                       PIPE_FORMAT_S8Z24_UNORM:
+                                       PIPE_FORMAT_Z24S8_UNORM;
+                       }
+                       break;
+               case 32:
+                       depth_stencil_format = PIPE_FORMAT_Z32_UNORM;
+                       break;
+       }
 
        return st_create_framebuffer(visual,
-                                    colorFormat,
-                                    depthFormat,
-                                    stencilFormat,
+                                    color_format,
+                                    depth_stencil_format,
+                                    depth_stencil_format,
                                     width,
                                     height,
                                     priv);
@@ -84,11 +115,10 @@ drm_create_texture(_EGLDisplay *dpy,
        templat.tex_usage |= PIPE_TEXTURE_USAGE_PRIMARY;
        templat.target = PIPE_TEXTURE_2D;
        templat.last_level = 0;
-       templat.depth[0] = 1;
+       templat.depth0 = 1;
        templat.format = PIPE_FORMAT_A8R8G8B8_UNORM;
-       templat.width[0] = w;
-       templat.height[0] = h;
-       pf_get_block(templat.format, &templat.block);
+       templat.width0 = w;
+       templat.height0 = h;
 
        texture = screen->texture_create(dev->screen,
                                         &templat);
@@ -141,9 +171,9 @@ drm_takedown_shown_screen(_EGLDisplay *dpy, struct drm_screen *screen)
        drmModeSetCrtc(
                dev->drmFD,
                screen->crtcID,
-               0, // FD
+               0, /* FD */
                0, 0,
-               NULL, 0, // List of output ids
+               NULL, 0, /* List of output ids */
                NULL);
 
        drmModeRmFB(dev->drmFD, screen->fbID);
@@ -152,11 +182,13 @@ drm_takedown_shown_screen(_EGLDisplay *dpy, struct drm_screen *screen)
 
        pipe_surface_reference(&screen->surface, NULL);
        pipe_texture_reference(&screen->tex, NULL);
-       pipe_buffer_reference(&screen->buffer, NULL);
 
        screen->shown = 0;
 }
 
+/**
+ * Called by libEGL's eglCreateWindowSurface().
+ */
 _EGLSurface *
 drm_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, NativeWindowType window, const EGLint *attrib_list)
 {
@@ -164,6 +196,9 @@ drm_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, N
 }
 
 
+/**
+ * Called by libEGL's eglCreatePixmapSurface().
+ */
 _EGLSurface *
 drm_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, NativePixmapType pixmap, const EGLint *attrib_list)
 {
@@ -171,10 +206,14 @@ drm_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, N
 }
 
 
+/**
+ * Called by libEGL's eglCreatePbufferSurface().
+ */
 _EGLSurface *
 drm_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
                            const EGLint *attrib_list)
 {
+       struct drm_device *dev = lookup_drm_device(dpy);
        int i;
        int width = -1;
        int height = -1;
@@ -211,9 +250,8 @@ drm_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
        surf->h = height;
 
        visual = drm_visual_from_config(conf);
-       surf->stfb = drm_create_framebuffer(visual,
-                                           width,
-                                           height,
+       surf->stfb = drm_create_framebuffer(dev->screen, visual,
+                                           width, height,
                                            (void*)surf);
        drm_visual_modes_destroy(visual);
 
@@ -225,6 +263,9 @@ err:
        return NULL;
 }
 
+/**
+ * Called by libEGL's eglCreateScreenSurfaceMESA().
+ */
 _EGLSurface *
 drm_create_screen_surface_mesa(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *cfg,
                                const EGLint *attrib_list)
@@ -234,6 +275,9 @@ drm_create_screen_surface_mesa(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *cf
        return surf;
 }
 
+/**
+ * Called by libEGL's eglShowScreenSurfaceMESA().
+ */
 EGLBoolean
 drm_show_screen_surface_mesa(_EGLDriver *drv, _EGLDisplay *dpy,
                              _EGLScreen *screen,
@@ -250,8 +294,8 @@ drm_show_screen_surface_mesa(_EGLDriver *drv, _EGLDisplay *dpy,
 
 
        drm_create_texture(dpy, scrn, mode->Width, mode->Height);
-       if (!scrn->buffer)
-               return EGL_FALSE;
+       if (!scrn->tex)
+               goto err_tex;
 
        ret = drmModeAddFB(dev->drmFD,
                           scrn->front.width, scrn->front.height,
@@ -325,11 +369,14 @@ err_fb:
 err_bo:
        pipe_surface_reference(&scrn->surface, NULL);
        pipe_texture_reference(&scrn->tex, NULL);
-       pipe_buffer_reference(&scrn->buffer, NULL);
 
+err_tex:
        return EGL_FALSE;
 }
 
+/**
+ * Called by libEGL's eglDestroySurface().
+ */
 EGLBoolean
 drm_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface)
 {
@@ -343,6 +390,9 @@ drm_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface)
        return EGL_TRUE;
 }
 
+/**
+ * Called by libEGL's eglSwapBuffers().
+ */
 EGLBoolean
 drm_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw)
 {
@@ -353,24 +403,30 @@ drm_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw)
        if (!surf)
                return EGL_FALSE;
 
-       /* error checking */
-       if (!_eglSwapBuffers(drv, dpy, draw))
-               return EGL_FALSE;
-
        st_get_framebuffer_surface(surf->stfb, ST_SURFACE_BACK_LEFT, &back_surf);
 
        if (back_surf) {
+               struct drm_context *ctx = lookup_drm_context(draw->Binding);
 
                st_notify_swapbuffers(surf->stfb);
 
-               if (surf->screen) {
-                       surf->user->pipe->surface_copy(surf->user->pipe,
-                               surf->screen->surface,
-                               0, 0,
-                               back_surf,
-                               0, 0,
-                               surf->w, surf->h);
-                       surf->user->pipe->flush(surf->user->pipe, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_TEXTURE_CACHE, NULL);
+               if (ctx && surf->screen) {
+            if (ctx->pipe->surface_copy) {
+                ctx->pipe->surface_copy(ctx->pipe,
+                    surf->screen->surface,
+                    0, 0,
+                    back_surf,
+                    0, 0,
+                    surf->w, surf->h);
+            } else {
+                util_surface_copy(ctx->pipe, FALSE,
+                    surf->screen->surface,
+                    0, 0,
+                    back_surf,
+                    0, 0,
+                    surf->w, surf->h);
+            }
+                       ctx->pipe->flush(ctx->pipe, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_TEXTURE_CACHE, NULL);
 
 #ifdef DRM_MODE_FEATURE_DIRTYFB
                        /* TODO query connector property to see if this is needed */