st/dri: add drisw
authorGeorge Sapountzis <gsapountzis@gmail.com>
Thu, 25 Mar 2010 15:01:53 +0000 (17:01 +0200)
committerGeorge Sapountzis <gsapountzis@gmail.com>
Thu, 25 Mar 2010 15:01:53 +0000 (17:01 +0200)
src/gallium/include/state_tracker/drm_api.h
src/gallium/state_trackers/dri/dri_screen.c
src/gallium/state_trackers/dri/dri_screen.h
src/gallium/state_trackers/dri/dri_st_api.c
src/gallium/state_trackers/dri/drisw.c [new file with mode: 0644]
src/gallium/state_trackers/dri/drisw.h [new file with mode: 0644]

index fe7ef253ef0e86305be04068338295d018453c2d..9780cf250b84681c14633360df6db9d0360101b3 100644 (file)
@@ -13,6 +13,7 @@ struct pipe_texture;
 enum drm_create_screen_mode {
        DRM_CREATE_NORMAL = 0,
        DRM_CREATE_DRI1,
+       DRM_CREATE_DRISW,
        DRM_CREATE_DRIVER = 1024,
        DRM_CREATE_MAX
 };
index 1d808f0f7f9a7830c0d8bac4b0dbd5f50a0c6991..ae311641042bdc884ed369d88c0992512a25a58b 100644 (file)
@@ -30,7 +30,9 @@
  */
 
 #include "utils.h"
+#ifndef __NOT_HAVE_DRM_H
 #include "vblank.h"
+#endif
 #include "xmlpool.h"
 
 #include "dri_screen.h"
@@ -40,6 +42,7 @@
 #include "dri1_helper.h"
 #include "dri1.h"
 #include "dri2.h"
+#include "drisw.h"
 
 #include "util/u_inlines.h"
 #include "pipe/p_screen.h"
@@ -262,6 +265,8 @@ dri_fill_st_visual(struct st_visual *stvis, struct dri_screen *screen,
    /* let the state tracker allocate the accum buffer */
 }
 
+#ifndef __NOT_HAVE_DRM_H
+
 /**
  * Get information about previous buffer swaps.
  */
@@ -274,6 +279,8 @@ dri_get_swap_info(__DRIdrawable * dPriv, __DRIswapInfo * sInfo)
       return 0;
 }
 
+#endif
+
 static void
 dri_destroy_option_cache(struct dri_screen * screen)
 {
@@ -308,6 +315,8 @@ dri_destroy_screen(__DRIscreen * sPriv)
    sPriv->extensions = NULL;
 }
 
+#ifndef __NOT_HAVE_DRM_H
+
 const struct __DriverAPIRec driDriverAPI = {
    .DestroyScreen = dri_destroy_screen,
    .CreateContext = dri_create_context,
@@ -334,4 +343,28 @@ PUBLIC const __DRIextension *__driDriverExtensions[] = {
     NULL
 };
 
+#else
+
+const struct __DriverAPIRec driDriverAPI = {
+   .DestroyScreen = dri_destroy_screen,
+   .CreateContext = dri_create_context,
+   .DestroyContext = dri_destroy_context,
+   .CreateBuffer = dri_create_buffer,
+   .DestroyBuffer = dri_destroy_buffer,
+   .MakeCurrent = dri_make_current,
+   .UnbindContext = dri_unbind_context,
+
+   .InitScreen = drisw_init_screen,
+   .SwapBuffers = drisw_swap_buffers,
+};
+
+/* This is the table of extensions that the loader will dlsym() for. */
+PUBLIC const __DRIextension *__driDriverExtensions[] = {
+    &driCoreExtension.base,
+    &driSWRastExtension.base,
+    NULL
+};
+
+#endif
+
 /* vim: set sw=3 ts=8 sts=3 expandtab: */
index 639d48661e2f4ada3dced61d1d5f5d1916c34efc..4f59db37cfa35655d59ddc7ef748e7b55f4d1a37 100644 (file)
@@ -75,6 +75,8 @@ dri_screen(__DRIscreen * sPriv)
    return (struct dri_screen *)sPriv->private;
 }
 
+#ifndef __NOT_HAVE_DRM_H
+
 static INLINE boolean
 dri_with_format(__DRIscreen * sPriv)
 {
@@ -85,6 +87,16 @@ dri_with_format(__DRIscreen * sPriv)
        && (loader->getBuffersWithFormat != NULL);
 }
 
+#else
+
+static INLINE boolean
+dri_with_format(__DRIscreen * sPriv)
+{
+   return TRUE;
+}
+
+#endif
+
 extern const uint __driNConfigOptions;
 
 const __DRIconfig **
index 3592a782229bdf2554d70d4b162702a7597ec84c..2b98c487c84a549999fea634d7d0ca0b082758ef 100644 (file)
@@ -38,6 +38,7 @@
 #include "dri1_helper.h"
 #include "dri1.h"
 #include "dri2.h"
+#include "drisw.h"
 
 static boolean
 dri_st_framebuffer_validate(struct st_framebuffer_iface *stfbi,
@@ -67,12 +68,19 @@ dri_st_framebuffer_validate(struct st_framebuffer_iface *stfbi,
 
    if (new_stamp || new_mask) {
 
+#ifndef __NOT_HAVE_DRM_H
       if (__dri1_api_hooks) {
          dri1_allocate_textures(drawable, statt_mask);
       }
       else {
          dri_allocate_textures(drawable, statts, count);
       }
+#else
+      if (new_stamp)
+         drisw_update_drawable_info(drawable->dPriv);
+
+      drisw_allocate_textures(drawable, statt_mask);
+#endif
 
       /* add existing textures */
       for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
@@ -102,12 +110,16 @@ dri_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi,
    struct dri_drawable *drawable =
       (struct dri_drawable *) stfbi->st_manager_private;
 
+#ifndef __NOT_HAVE_DRM_H
    if (__dri1_api_hooks) {
       dri1_flush_frontbuffer(drawable, statt);
    }
    else {
       dri_flush_frontbuffer(drawable, statt);
    }
+#else
+   drisw_flush_frontbuffer(drawable, statt);
+#endif
 
    return TRUE;
 }
diff --git a/src/gallium/state_trackers/dri/drisw.c b/src/gallium/state_trackers/dri/drisw.c
new file mode 100644 (file)
index 0000000..b3d65df
--- /dev/null
@@ -0,0 +1,288 @@
+/**************************************************************************
+ *
+ * Copyright 2009, VMware, Inc.
+ * All Rights Reserved.
+ * Copyright 2010 George Sapountzis <gsapountzis@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "util/u_memory.h"
+#include "util/u_inlines.h"
+#include "pipe/p_context.h"
+#include "state_tracker/drm_api.h"
+
+#include "dri_screen.h"
+#include "dri_context.h"
+#include "dri_drawable.h"
+#include "dri_st_api.h"
+#include "dri1_helper.h"
+#include "drisw.h"
+
+
+static INLINE void
+get_drawable_info(__DRIdrawable *dPriv, int *w, int *h)
+{
+   __DRIscreen *sPriv = dPriv->driScreenPriv;
+   const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader;
+   int x, y;
+
+   loader->getDrawableInfo(dPriv,
+                           &x, &y, w, h,
+                           dPriv->loaderPrivate);
+}
+
+static INLINE void
+put_image(__DRIdrawable *dPriv, void *data)
+{
+   __DRIscreen *sPriv = dPriv->driScreenPriv;
+   const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader;
+
+   loader->putImage(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP,
+                    0, 0, dPriv->w, dPriv->h,
+                    data, dPriv->loaderPrivate);
+}
+
+void
+drisw_update_drawable_info(__DRIdrawable *dPriv)
+{
+   get_drawable_info(dPriv, &dPriv->w, &dPriv->h);
+}
+
+static INLINE void
+drisw_present_texture(__DRIdrawable *dPriv,
+                      struct pipe_texture *ptex)
+{
+   struct dri_drawable *drawable = dri_drawable(dPriv);
+   struct dri_screen *screen = dri_screen(drawable->sPriv);
+   struct pipe_context *pipe;
+   struct pipe_surface *psurf;
+   struct pipe_transfer *ptrans;
+   void *pmap;
+
+   pipe = dri1_get_pipe_context(screen);
+   psurf = dri1_get_pipe_surface(drawable, ptex);
+   if (!pipe || !psurf)
+      return;
+
+   ptrans = pipe->get_tex_transfer(pipe, ptex, 0, 0, 0,
+                                   PIPE_TRANSFER_READ,
+                                   0, 0, dPriv->w, dPriv->h);
+
+   pmap = pipe->transfer_map(pipe, ptrans);
+
+   assert(pmap);
+
+   put_image(dPriv, pmap);
+
+   pipe->transfer_unmap(pipe, ptrans);
+
+   pipe->tex_transfer_destroy(pipe, ptrans);
+}
+
+static INLINE void
+drisw_invalidate_drawable(__DRIdrawable *dPriv)
+{
+   struct dri_context *ctx = dri_get_current();
+   struct dri_drawable *drawable = dri_drawable(dPriv);
+
+   drawable->texture_stamp = dPriv->lastStamp - 1;
+
+   /* check if swapping currently bound buffer */
+   if (ctx && ctx->dPriv == dPriv)
+      ctx->st->notify_invalid_framebuffer(ctx->st, drawable->stfb);
+}
+
+static INLINE void
+drisw_copy_to_front(__DRIdrawable * dPriv,
+                    struct pipe_texture *ptex)
+{
+   drisw_present_texture(dPriv, ptex);
+
+   drisw_invalidate_drawable(dPriv);
+}
+
+/*
+ * Backend functions for st_framebuffer interface and swap_buffers.
+ */
+
+void
+drisw_flush_frontbuffer(struct dri_drawable *drawable,
+                        enum st_attachment_type statt)
+{
+   struct dri_context *ctx = dri_get_current();
+   struct pipe_texture *ptex;
+
+   if (!ctx)
+      return;
+
+   ptex = drawable->textures[statt];
+
+   if (ptex) {
+      drisw_copy_to_front(ctx->dPriv, ptex);
+   }
+}
+
+void
+drisw_swap_buffers(__DRIdrawable *dPriv)
+{
+   struct dri_context *ctx = dri_get_current();
+   struct dri_drawable *drawable = dri_drawable(dPriv);
+   struct pipe_texture *ptex;
+
+   if (!ctx)
+      return;
+
+   ptex = drawable->textures[ST_ATTACHMENT_BACK_LEFT];
+
+   if (ptex) {
+      ctx->st->flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+      drisw_copy_to_front(dPriv, ptex);
+   }
+}
+
+/**
+ * Allocate framebuffer attachments.
+ *
+ * During fixed-size operation, the function keeps allocating new attachments
+ * as they are requested. Unused attachments are not removed, not until the
+ * framebuffer is resized or destroyed.
+ *
+ * It should be possible for DRI1 and DRISW to share this function, but it
+ * seems a better seperation and safer for each DRI version to provide its own
+ * function.
+ */
+void
+drisw_allocate_textures(struct dri_drawable *drawable,
+                        unsigned mask)
+{
+   struct dri_screen *screen = dri_screen(drawable->sPriv);
+   struct pipe_texture templ;
+   unsigned width, height;
+   boolean resized;
+   int i;
+
+   width  = drawable->dPriv->w;
+   height = drawable->dPriv->h;
+
+   resized = (drawable->old_w != width ||
+              drawable->old_h != height);
+
+   /* remove outdated textures */
+   if (resized) {
+      for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
+         pipe_texture_reference(&drawable->textures[i], NULL);
+   }
+
+   memset(&templ, 0, sizeof(templ));
+   templ.target = PIPE_TEXTURE_2D;
+   templ.width0 = width;
+   templ.height0 = height;
+   templ.depth0 = 1;
+   templ.last_level = 0;
+
+   for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
+      enum pipe_format format;
+      unsigned tex_usage;
+
+      /* the texture already exists or not requested */
+      if (drawable->textures[i] || !(mask & (1 << i))) {
+         continue;
+      }
+
+      switch (i) {
+      case ST_ATTACHMENT_FRONT_LEFT:
+      case ST_ATTACHMENT_BACK_LEFT:
+      case ST_ATTACHMENT_FRONT_RIGHT:
+      case ST_ATTACHMENT_BACK_RIGHT:
+         format = drawable->stvis.color_format;
+         tex_usage = PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
+                     PIPE_TEXTURE_USAGE_RENDER_TARGET;
+         break;
+      case ST_ATTACHMENT_DEPTH_STENCIL:
+         format = drawable->stvis.depth_stencil_format;
+         tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL;
+         break;
+      default:
+         format = PIPE_FORMAT_NONE;
+         break;
+      }
+
+      if (format != PIPE_FORMAT_NONE) {
+         templ.format = format;
+         templ.tex_usage = tex_usage;
+
+         drawable->textures[i] =
+            screen->pipe_screen->texture_create(screen->pipe_screen, &templ);
+      }
+   }
+
+   drawable->old_w = width;
+   drawable->old_h = height;
+}
+
+/*
+ * Backend function for init_screen.
+ */
+
+static const __DRIextension *drisw_screen_extensions[] = {
+   NULL
+};
+
+const __DRIconfig **
+drisw_init_screen(__DRIscreen * sPriv)
+{
+   struct dri_screen *screen;
+   struct drm_create_screen_arg arg;
+
+   screen = CALLOC_STRUCT(dri_screen);
+   if (!screen)
+      return NULL;
+
+   screen->api = drm_api_create();
+   screen->sPriv = sPriv;
+   screen->fd = -1;
+   sPriv->private = (void *)screen;
+   sPriv->extensions = drisw_screen_extensions;
+   arg.mode = DRM_CREATE_DRISW;
+
+   screen->pipe_screen = screen->api->create_screen(screen->api, -1, &arg);
+   if (!screen->pipe_screen) {
+      debug_printf("%s: failed to create pipe_screen\n", __FUNCTION__);
+      goto fail;
+   }
+
+   screen->smapi = dri_create_st_manager(screen);
+   if (!screen->smapi)
+      goto fail;
+
+   driParseOptionInfo(&screen->optionCache,
+                      __driConfigOptions, __driNConfigOptions);
+
+   return dri_fill_in_modes(screen, 32);
+fail:
+   dri_destroy_screen(sPriv);
+   return NULL;
+}
+
+/* vim: set sw=3 ts=8 sts=3 expandtab: */
diff --git a/src/gallium/state_trackers/dri/drisw.h b/src/gallium/state_trackers/dri/drisw.h
new file mode 100644 (file)
index 0000000..2c0d561
--- /dev/null
@@ -0,0 +1,54 @@
+/**************************************************************************
+ *
+ * Copyright 2009, VMware, Inc.
+ * All Rights Reserved.
+ * Copyright 2010 George Sapountzis <gsapountzis@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef DRISW_H
+#define DRISW_H
+
+#include "dri_context.h"
+#include "dri_drawable.h"
+
+#include "state_tracker/st_api.h"
+#include "dri_wrapper.h"
+
+const __DRIconfig **
+drisw_init_screen(__DRIscreen * sPriv);
+
+void
+drisw_update_drawable_info(__DRIdrawable *dPriv);
+
+void
+drisw_flush_frontbuffer(struct dri_drawable *drawable,
+                        enum st_attachment_type statt);
+
+void
+drisw_allocate_textures(struct dri_drawable *drawable,
+                        unsigned mask);
+
+void drisw_swap_buffers(__DRIdrawable * dPriv);
+
+#endif /* DRISW_H */