st/xorg/dri: Pass texture formats via the DRI2 protocol flags.
[mesa.git] / src / gallium / state_trackers / dri / dri_drawable.c
index 1d91fbb89fbb05daac3baed5db043816cf64ee2e..e27d5c12a82e051600d1677ed2830c330af1800a 100644 (file)
 
 #include "util/u_memory.h"
 
-static void
-dri_copy_to_front(__DRIdrawablePrivate * dPriv,
-                 struct pipe_surface *from,
-                 int x, int y, unsigned w, unsigned h)
-{
-   /* TODO send a message to the Xserver to copy to the real front buffer */
-}
-
 static struct pipe_surface *
 dri_surface_from_handle(struct drm_api *api,
                        struct pipe_screen *screen,
@@ -65,8 +57,10 @@ dri_surface_from_handle(struct drm_api *api,
    struct pipe_buffer *buf = NULL;
 
    buf = api->buffer_from_handle(api, screen, "dri2 buffer", handle);
-   if (!buf)
+   if (!buf) {
+      debug_printf("%s: Failed to get buffer from handle\n", __func__);
       return NULL;
+   }
 
    memset(&templat, 0, sizeof(templat));
    templat.tex_usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET;
@@ -83,8 +77,10 @@ dri_surface_from_handle(struct drm_api *api,
    /* we don't need the buffer from this point on */
    pipe_buffer_reference(&buf, NULL);
 
-   if (!texture)
+   if (!texture) {
+      debug_printf("%s: Failed to blanket the buffer with a texture\n", __func__);
       return NULL;
+   }
 
    surface = screen->get_tex_surface(screen, texture, 0, 0, 0,
                                     PIPE_BUFFER_USAGE_GPU_READ |
@@ -95,6 +91,35 @@ dri_surface_from_handle(struct drm_api *api,
    return surface;
 }
 
+/**
+ * Pixmaps have will have the same name of fake front and front.
+ */
+static boolean
+dri2_check_if_pixmap(__DRIbuffer *buffers, int count)
+{
+   boolean found = FALSE;
+   boolean is_pixmap = FALSE;
+   unsigned name;
+   int i;
+
+   for (i = 0; i < count; i++) {
+      switch (buffers[i].attachment) {
+      case __DRI_BUFFER_FRONT_LEFT:
+      case __DRI_BUFFER_FAKE_FRONT_LEFT:
+         if (found) {
+            is_pixmap = buffers[i].name == name;
+         } else {
+            name = buffers[i].name;
+            found = TRUE;
+         }
+      default:
+        continue;
+      }
+   }
+
+   return is_pixmap;
+}
+
 /**
  * This will be called a drawable is known to have been resized.
  */
@@ -153,30 +178,28 @@ dri_get_buffers(__DRIdrawablePrivate * dPriv)
       memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * count);
    }
 
+   drawable->is_pixmap = dri2_check_if_pixmap(buffers, count);
+
    for (i = 0; i < count; i++) {
-      enum pipe_format format = 0;
       int index = 0;
 
       switch (buffers[i].attachment) {
       case __DRI_BUFFER_FRONT_LEFT:
-        index = ST_SURFACE_FRONT_LEFT;
-        format = drawable->color_format;
-        break;
       case __DRI_BUFFER_FAKE_FRONT_LEFT:
         index = ST_SURFACE_FRONT_LEFT;
-        format = drawable->color_format;
+        drawable->color_format = buffers[i].flags;
         break;
       case __DRI_BUFFER_BACK_LEFT:
         index = ST_SURFACE_BACK_LEFT;
-        format = drawable->color_format;
+        drawable->color_format = buffers[i].flags;
         break;
       case __DRI_BUFFER_DEPTH:
         index = ST_SURFACE_DEPTH;
-        format = drawable->depth_format;
+        drawable->depth_format = buffers[i].flags;
         break;
       case __DRI_BUFFER_STENCIL:
         index = ST_SURFACE_DEPTH;
-        format = drawable->stencil_format;
+        drawable->stencil_format = buffers[i].flags;
         break;
       case __DRI_BUFFER_ACCUM:
       default:
@@ -193,7 +216,7 @@ dri_get_buffers(__DRIdrawablePrivate * dPriv)
       surface = dri_surface_from_handle(api,
                                        screen,
                                        buffers[i].name,
-                                       format,
+                                       buffers[i].flags,
                                        dri_drawable->w,
                                        dri_drawable->h, buffers[i].pitch);
 
@@ -204,13 +227,52 @@ dri_get_buffers(__DRIdrawablePrivate * dPriv)
    st_resize_framebuffer(drawable->stfb, dri_drawable->w, dri_drawable->h);
 }
 
+/**
+ * These are used for GLX_EXT_texture_from_pixmap
+ */
+void dri2_set_tex_buffer2(__DRIcontext *pDRICtx, GLint target,
+                          GLint format, __DRIdrawable *dPriv)
+{
+   struct dri_drawable *drawable = dri_drawable(dPriv);
+   struct pipe_surface *ps;
+
+   dri_get_buffers(drawable->dPriv);
+   st_get_framebuffer_surface(drawable->stfb, ST_SURFACE_FRONT_LEFT, &ps);
+
+   st_bind_texture_surface(ps, target == GL_TEXTURE_2D ? ST_TEXTURE_2D :
+                           ST_TEXTURE_RECT, 0, drawable->color_format);
+}
+
+void dri2_set_tex_buffer(__DRIcontext *pDRICtx, GLint target,
+                         __DRIdrawable *dPriv)
+{
+   dri2_set_tex_buffer2(pDRICtx, target, GLX_TEXTURE_FORMAT_RGBA_EXT, dPriv);
+}
+
 void
 dri_flush_frontbuffer(struct pipe_screen *screen,
                      struct pipe_surface *surf, void *context_private)
 {
    struct dri_context *ctx = (struct dri_context *)context_private;
+   struct dri_drawable *drawable = dri_drawable(ctx->dPriv);
+   __DRIdrawable *dri_drawable = ctx->dPriv;
+   __DRIscreen *dri_screen = ctx->sPriv;
+
+   /* XXX Does this function get called with DRI1? */
+
+   if (ctx->dPriv == NULL) {
+      debug_printf("%s: no drawable bound to context\n", __func__);
+      return;
+   }
+
+#if 0
+   /* TODO if rendering to pixmaps is slow enable this code. */
+   if (drawable->is_pixmap)
+      return;
+#endif
 
-   dri_copy_to_front(ctx->dPriv, surf, 0, 0, surf->width, surf->height);
+   (*dri_screen->dri2.loader->flushFrontBuffer)(dri_drawable,
+                                               dri_drawable->loaderPrivate);
 }
 
 /**
@@ -232,34 +294,37 @@ dri_create_buffer(__DRIscreenPrivate * sPriv,
    if (drawable == NULL)
       goto fail;
 
-   drawable->color_format = (visual->redBits == 8) ?
-      PIPE_FORMAT_A8R8G8B8_UNORM : PIPE_FORMAT_R5G6B5_UNORM;
-
-   debug_printf("Red bits is %d\n", visual->redBits);
+   if (visual->redBits == 8) {
+      if (visual->alphaBits == 8)
+         drawable->color_format = PIPE_FORMAT_A8R8G8B8_UNORM;
+      else
+         drawable->color_format = PIPE_FORMAT_X8R8G8B8_UNORM;
+   } else {
+      drawable->color_format = PIPE_FORMAT_R5G6B5_UNORM;
+   }
 
    switch(visual->depthBits) {
    default:
    case 0:
-      debug_printf("Depth buffer 0.\n");
       drawable->depth_format = PIPE_FORMAT_NONE;
       break;
    case 16:
-      debug_printf("Depth buffer 16.\n");
       drawable->depth_format = PIPE_FORMAT_Z16_UNORM;
       break;
    case 24:
       if (visual->stencilBits == 0) {
-         debug_printf("Depth buffer 24. Stencil 0.\n");
         drawable->depth_format = (screen->d_depth_bits_last) ?
            PIPE_FORMAT_X8Z24_UNORM:
            PIPE_FORMAT_Z24X8_UNORM;
       } else {
-         debug_printf("Combined depth stencil 24 / 8.\n");
         drawable->depth_format = (screen->sd_depth_bits_last) ?
            PIPE_FORMAT_S8Z24_UNORM:
            PIPE_FORMAT_Z24S8_UNORM;
       }
       break;
+   case 32:
+      drawable->depth_format = PIPE_FORMAT_Z32_UNORM;
+      break;
    }
 
    switch(visual->stencilBits) {
@@ -288,12 +353,11 @@ dri_create_buffer(__DRIscreenPrivate * sPriv,
    dPriv->driverPrivate = (void *)drawable;
 
    /* setup dri2 buffers information */
+   /* TODO incase of double buffer visual, delay fake creation */
    i = 0;
    drawable->attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
-#if 0
-   /* TODO incase of double buffer visual, delay fake creation */
    drawable->attachments[i++] = __DRI_BUFFER_FAKE_FRONT_LEFT;
-#endif
+
    if (visual->doubleBufferMode)
       drawable->attachments[i++] = __DRI_BUFFER_BACK_LEFT;
    if (visual->depthBits)