From bf81c247ee68c8660c4f092e7366d1260d463116 Mon Sep 17 00:00:00 2001
From: Jakob Bornecrantz <jakob@vmware.com>
Date: Sat, 14 Nov 2009 19:54:44 -0800
Subject: [PATCH] egl_xlib: WIP Rework

---
 src/gallium/winsys/egl_xlib/egl_xlib.c |  220 ++++++++++++++++++-------------
 1 files changed, 128 insertions(+), 92 deletions(-)

diff --git a/src/gallium/winsys/egl_xlib/egl_xlib.c b/src/gallium/winsys/egl_xlib/egl_xlib.c
index d02f825..99cc959 100644
--- a/src/gallium/winsys/egl_xlib/egl_xlib.c
+++ b/src/gallium/winsys/egl_xlib/egl_xlib.c
@@ -31,6 +31,7 @@
  * Authors: Brian Paul
  */
 
+#include "state_tracker/st_api.h"
 
 #include <dlfcn.h>
 #include <X11/Xlib.h>
@@ -53,11 +54,19 @@
 #include "egllog.h"
 #include "eglsurface.h"
 
-#include "state_tracker/st_public.h"
+//#include "state_tracker/st_public.h"
+
 
 #include "sw_winsys.h"
 
 
+/* TODO some smarter checking here */
+#ifndef container_of
+#define container_of(__item, __type, __field) \
+	((__type *)(((char *) (__item)) - offsetof(__type, __field)))
+#endif
+
+
 /** subclass of _EGLDriver */
 struct xlib_egl_driver
 {
@@ -71,12 +80,15 @@ struct xlib_egl_display
 {
    Display *Dpy;
 
+   struct st_api *api; /**< current API */
+
    struct pipe_winsys *winsys;
    struct pipe_screen *screen;
 };
 
 
 /** subclass of _EGLContext */
+
 struct xlib_egl_context
 {
    _EGLContext Base;   /**< base class */
@@ -91,24 +103,19 @@ struct xlib_egl_surface
 {
    _EGLSurface Base;   /**< base class */
 
+   struct st_framebuffer framebuffer;
+   struct pipe_texture *tex_back;
+   struct pipe_texture *tex_front;
+   struct pipe_texture *tex_ds;
+
    /* These are set for window surface */
    Display *Dpy;  /**< The X Display of the window */
    Window Win;    /**< The user-created window ID */
    GC Gc;
    XVisualInfo VisInfo;
-
-   struct pipe_winsys *winsys;
-
-   struct st_framebuffer *Framebuffer;
 };
 
 
-static void
-flush_frontbuffer(struct pipe_winsys *pws,
-                  struct pipe_surface *psurf,
-                  void *context_private);
-
-
 /** cast wrapper */
 static INLINE struct xlib_egl_driver *
 xlib_egl_driver(_EGLDriver *drv)
@@ -125,6 +132,13 @@ xlib_egl_display(_EGLDisplay *dpy)
 
 
 static INLINE struct xlib_egl_surface *
+surface_from_st_framebuffer(struct st_framebuffer *fb)
+{
+    return container_of(fb, struct xlib_egl_surface, framebuffer);
+}
+
+
+static INLINE struct xlib_egl_surface *
 lookup_surface(_EGLSurface *surf)
 {
    return (struct xlib_egl_surface *) surf;
@@ -240,7 +254,7 @@ xlib_eglInitialize(_EGLDriver *drv, _EGLDisplay *dpy,
       free(xdpy);
       return _eglError(EGL_BAD_ALLOC, "eglInitialize");
    }
-   xdpy->winsys->flush_frontbuffer = flush_frontbuffer;
+   //xdpy->winsys->flush_frontbuffer = flush_frontbuffer;
    xdpy->screen = softpipe_create_screen(xdpy->winsys);
    if (!xdpy->screen) {
       free(xdpy->winsys);
@@ -286,7 +300,7 @@ xlib_eglTerminate(_EGLDriver *drv, _EGLDisplay *dpy)
 static _EGLProc
 xlib_eglGetProcAddress(const char *procname)
 {
-   return (_EGLProc) st_get_proc_address(procname);
+   return NULL;//(_EGLProc) st_get_proc_address(procname);
 }
 
 
@@ -330,6 +344,8 @@ get_drawable_size(Display *dpy, Drawable d, uint *width, uint *height)
 static void
 check_and_update_buffer_size(struct xlib_egl_surface *surface)
 {
+   struct st_context *ctx = NULL;
+
    uint width, height;
    if (surface->Base.Type == EGL_PBUFFER_BIT) {
       width = surface->Base.Width;
@@ -338,21 +354,27 @@ check_and_update_buffer_size(struct xlib_egl_surface *surface)
    else {
       get_drawable_size(surface->Dpy, surface->Win, &width, &height);
    }
-   st_resize_framebuffer(surface->Framebuffer, width, height);
-   surface->Base.Width = width;
-   surface->Base.Height = height;
+
+   if (surface->Base.Width != width || surface->Base.Height != height) {
+      /* XXX find the bound context to this surface */
+      surface->Base.Width = width;
+      surface->Base.Height = height;
+
+      ctx->notify_invalid_framebuffer(ctx, &surface->framebuffer);
+   }
 }
 
 
 
 static void
-display_surface(struct pipe_winsys *pws,
-                struct pipe_surface *psurf,
-                struct xlib_egl_surface *xsurf)
+display_surface(struct xlib_egl_surface *xsurf,
+                struct pipe_texture *texture)
 {
+   /* XXX Fix this */
+#if 0
    struct softpipe_texture *spt = softpipe_texture(psurf->texture);
    XImage *ximage;
-   void *data;
+   void *data = NULL;
 
    if (xsurf->Base.Type == EGL_PBUFFER_BIT)
       return;
@@ -387,21 +409,45 @@ display_surface(struct pipe_winsys *pws,
    XDestroyImage(ximage);
 
    pws->buffer_unmap(pws, spt->buffer);
+#endif
 }
 
-
-
-/** Display gallium surface in X window */
-static void
-flush_frontbuffer(struct pipe_winsys *pws,
-                  struct pipe_surface *psurf,
-                  void *context_private)
+static boolean
+flush_frontbuffer(struct st_framebuffer *fb,
+                  const enum st_framebuffer_attachment att)
 {
-   struct xlib_egl_surface *xsurf = (struct xlib_egl_surface *) context_private;
-   display_surface(pws, psurf, xsurf);
+   /* XXX get the surface from the framebuffer */
+   struct xlib_egl_surface *xsurf = NULL;
+   display_surface(xsurf, xsurf->tex_front);
+
+   return TRUE;
 }
 
+static boolean
+validate(struct st_framebuffer *fb,
+         const enum st_framebuffer_attachment *att,
+         const unsigned count,
+         struct pipe_texture **out)
+{
+   /* XXX get the surface from the framebuffer */
+   struct xlib_egl_surface *xsurf = NULL;
+   int i;
+
+   for (i = 0; i < count; i++) {
+      switch (att[i]) {
+      case ST_SURFACE_FRONT_LEFT:
+         pipe_texture_reference(&out[i], xsurf->tex_front);
+      case ST_SURFACE_BACK_LEFT:
+         pipe_texture_reference(&out[i], xsurf->tex_back);
+      case ST_SURFACE_DEPTH_STENCIL:
+         pipe_texture_reference(&out[i], xsurf->tex_ds);
+      default:
+         assert(!"unsupported surface attachment");
+      }
+   }
 
+   return TRUE;
+}
 
 /**
  * Called via eglCreateContext(), drv->API.CreateContext().
@@ -437,7 +483,9 @@ xlib_eglCreateContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
       ctx->pipe = softpipe_create(xdpy->screen);
       /* Now do xlib / state tracker inits here */
       _eglConfigToContextModesRec(conf, &visual);
-      ctx->Context = st_create_context(ctx->pipe, &visual, share_ctx);
+      ctx->Context = xdpy->api->create_context(xdpy->api, ctx->pipe,
+                                               (struct st_visual*)&visual,
+                                               share_ctx);
       break;
    default:
       _eglError(EGL_BAD_MATCH, "eglCreateContext(unsupported API)");
@@ -455,17 +503,7 @@ xlib_eglDestroyContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
    struct xlib_egl_context *context = lookup_context(ctx);
 
    if (!_eglIsContextBound(&context->Base)) {
-      /* API-dependent clean-up */
-      switch (context->Base.ClientAPI) {
-      case EGL_OPENGL_ES_API:
-      case EGL_OPENVG_API:
-         /* fall-through */
-      case EGL_OPENGL_API:
-         st_destroy_context(context->Context);
-         break;
-      default:
-         assert(0);
-      }
+      context->Context->destroy(context->Context);
       free(context);
    }
    return EGL_TRUE;
@@ -479,6 +517,7 @@ static EGLBoolean
 xlib_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy,
                     _EGLSurface *draw, _EGLSurface *read, _EGLContext *ctx)
 {
+   struct xlib_egl_display *display = xlib_egl_display(dpy);
    struct xlib_egl_context *context = lookup_context(ctx);
    struct xlib_egl_surface *draw_surf = lookup_surface(draw);
    struct xlib_egl_surface *read_surf = lookup_surface(read);
@@ -487,17 +526,19 @@ xlib_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy,
 
    oldctx = _eglGetCurrentContext();
    if (oldctx && _eglIsContextLinked(oldctx))
-      oldcontext = st_get_current();
+      oldcontext = lookup_context(oldctx)->Context;
 
    if (!_eglMakeCurrent(drv, dpy, draw, read, ctx))
       return EGL_FALSE;
 
    /* Flush before switching context.  Check client API? */
    if (oldcontext)
-      st_flush(oldcontext, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
-   st_make_current((context ? context->Context : NULL),
-                   (draw_surf ? draw_surf->Framebuffer : NULL),
-                   (read_surf ? read_surf->Framebuffer : NULL));
+      oldcontext->flush(oldcontext, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
+
+   display->api->make_current(display->api,
+                              (context ? context->Context : NULL),
+                              (draw_surf ? &draw_surf->framebuffer : NULL),
+                              (read_surf ? &read_surf->framebuffer : NULL));
 
    if (draw_surf)
       check_and_update_buffer_size(draw_surf);
@@ -575,8 +616,6 @@ xlib_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf
    surf->Dpy = xdpy->Dpy;  /* The X display */
    surf->Gc = XCreateGC(surf->Dpy, surf->Win, 0, NULL);
 
-   surf->winsys = xdpy->winsys;
-
    _eglConfigToContextModesRec(conf, &visual);
    get_drawable_size(surf->Dpy, surf->Win, &width, &height);
    get_drawable_visual_info(surf->Dpy, surf->Win, &surf->VisInfo);
@@ -584,15 +623,9 @@ xlib_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf
    surf->Base.Width = width;
    surf->Base.Height = height;
 
-   /* Create GL statetracker framebuffer */
-   surf->Framebuffer = st_create_framebuffer(&visual,
-                                             choose_color_format(&visual),
-                                             choose_depth_format(&visual),
-                                             choose_stencil_format(&visual),
-                                             width, height,
-                                             (void *) surf);
-
-   st_resize_framebuffer(surf->Framebuffer, width, height);
+   surf->framebuffer.flush_front = flush_frontbuffer;
+   surf->framebuffer.validate = validate;
+   /* XXX we delay the creation of textures */
 
    return &surf->Base;
 }
@@ -602,7 +635,6 @@ static _EGLSurface *
 xlib_eglCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
                              const EGLint *attrib_list)
 {
-   struct xlib_egl_display *xdpy = xlib_egl_display(disp);
    struct xlib_egl_surface *surf;
    __GLcontextModes visual;
    uint width, height;
@@ -647,18 +679,9 @@ xlib_eglCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *con
       return NULL;
    }
 
-   surf->winsys = xdpy->winsys;
-
    _eglConfigToContextModesRec(conf, &visual);
 
-   /* Create GL statetracker framebuffer */
-   surf->Framebuffer = st_create_framebuffer(&visual,
-                                             choose_color_format(&visual),
-                                             choose_depth_format(&visual),
-                                             choose_stencil_format(&visual),
-                                             width, height,
-                                             (void *) surf);
-   st_resize_framebuffer(surf->Framebuffer, width, height);
+   /* XXX we delay the creation of textures */
 
    return &surf->Base;
 }
@@ -671,7 +694,7 @@ xlib_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface)
    if (!_eglIsSurfaceBound(&surf->Base)) {
       if (surf->Base.Type != EGL_PBUFFER_BIT)
          XFreeGC(surf->Dpy, surf->Gc);
-      st_unreference_framebuffer(surf->Framebuffer);
+      /* Free textures */
       free(surf);
    }
    return EGL_TRUE;
@@ -684,7 +707,7 @@ xlib_eglBindTexImage(_EGLDriver *drv, _EGLDisplay *dpy,
 {
    struct xlib_egl_surface *xsurf = lookup_surface(surface);
    struct xlib_egl_context *xctx;
-   struct pipe_surface *psurf;
+   struct st_context *ctx;
    enum pipe_format format;
    int target;
 
@@ -717,20 +740,24 @@ xlib_eglBindTexImage(_EGLDriver *drv, _EGLDisplay *dpy,
 
    /* flush properly */
    if (eglGetCurrentSurface(EGL_DRAW) == surface) {
-      xctx = lookup_context(_eglGetCurrentContext());
-      st_flush(xctx->Context, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME,
-               NULL);
+      ctx = lookup_context(_eglGetCurrentContext())->Context;
+      ctx->flush(ctx, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME,
+                 NULL);
    }
    else if (_eglIsSurfaceBound(&xsurf->Base)) {
-      xctx = lookup_context(xsurf->Base.Binding);
-      if (xctx)
-         st_finish(xctx->Context);
+      ctx = lookup_context(xsurf->Base.Binding)->Context;
+      if (ctx) {
+         /* ctx->finish(ctx); XXX Fix me */
+      }
    }
 
-   st_get_framebuffer_surface(xsurf->Framebuffer, ST_SURFACE_BACK_LEFT,
-                              &psurf);
-   st_bind_texture_surface(psurf, target, xsurf->Base.MipmapLevel, format);
-   xsurf->Base.BoundToTexture = EGL_TRUE;
+   xctx = lookup_context(_eglGetCurrentContext());
+   if (xctx) {
+      ctx = xctx->Context;
+      ctx->bind_texture(ctx, xsurf->tex_back, target, xsurf->Base.MipmapLevel, format);
+      xsurf->Base.BoundToTexture = EGL_TRUE;
+   } else
+      return EGL_FALSE;
 
    return EGL_TRUE;
 }
@@ -741,7 +768,9 @@ xlib_eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface,
                         EGLint buffer)
 {
    struct xlib_egl_surface *xsurf = lookup_surface(surface);
-   struct pipe_surface *psurf;
+   struct xlib_egl_context *xctx;
+   struct st_context *ctx;
+   int target;
 
    if (!xsurf || xsurf->Base.Type != EGL_PBUFFER_BIT ||
        !xsurf->Base.BoundToTexture)
@@ -749,10 +778,21 @@ xlib_eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface,
    if (buffer != EGL_BACK_BUFFER)
       return _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage");
 
-   st_get_framebuffer_surface(xsurf->Framebuffer, ST_SURFACE_BACK_LEFT,
-                              &psurf);
-   st_unbind_texture_surface(psurf, ST_TEXTURE_2D, xsurf->Base.MipmapLevel);
-   xsurf->Base.BoundToTexture = EGL_FALSE;
+   switch (xsurf->Base.TextureTarget) {
+   case EGL_TEXTURE_2D:
+      target = ST_TEXTURE_2D;
+      break;
+   default:
+      return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
+   }
+
+   xctx = lookup_context(_eglGetCurrentContext());
+   if (xctx) {
+      ctx = xctx->Context;
+      ctx->unbind_texture(ctx, xsurf->tex_back, target, xsurf->Base.MipmapLevel);
+      xsurf->Base.BoundToTexture = EGL_TRUE;
+   } else
+      return EGL_FALSE;
 
    return EGL_TRUE;
 }
@@ -767,15 +807,11 @@ xlib_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw)
 
    {
       struct xlib_egl_surface *xsurf = lookup_surface(draw);
-      struct pipe_winsys *pws = xsurf->winsys;
-      struct pipe_surface *psurf;
-
-      st_get_framebuffer_surface(xsurf->Framebuffer, ST_SURFACE_BACK_LEFT,
-                                 &psurf);
 
-      st_notify_swapbuffers(xsurf->Framebuffer);
+      /* no need to notify as we do not do proper swaps */
+      /* st_notify_swapbuffers(xsurf->Framebuffer); */
 
-      display_surface(pws, psurf, xsurf);
+      display_surface(xsurf, xsurf->tex_back);
 
       check_and_update_buffer_size(xsurf);
    }
-- 
1.6.0.4

