tu: Implement fallback linear staging blit for CopyImage
[mesa.git] / src / gallium / state_trackers / glx / xlib / xm_api.c
index 79bf45d7d78b0c6af8d49169e83ca2e8aff373c2..94a787b422aa198c834fc170b11e965eba5ed9d0 100644 (file)
 #include "pipe/p_defines.h"
 #include "pipe/p_screen.h"
 #include "pipe/p_state.h"
+#include "state_tracker/st_api.h"
 
 #include "util/u_atomic.h"
 #include "util/u_inlines.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
 
 #include "hud/hud_context.h"
 
+#include "main/errors.h"
+
 #include "xm_public.h"
 #include <GL/glx.h>
 
@@ -142,8 +147,11 @@ xmesa_close_display(Display *display)
 {
    XMesaExtDisplayInfo *info, *prev;
 
+   /* These assertions are not valid since screen creation can fail and result
+    * in an empty list
    assert(MesaExtInfo.ndisplays > 0);
    assert(MesaExtInfo.head);
+   */
 
    _XLockMutex(_Xglobal_lock);
    /* first find display */
@@ -223,7 +231,30 @@ xmesa_init_display( Display *display )
       return NULL;
    }
    info->display = display;
+
    xmdpy = &info->mesaDisplay; /* to be filled out below */
+   xmdpy->display = display;
+   xmdpy->pipe = NULL;
+
+   xmdpy->smapi = CALLOC_STRUCT(st_manager);
+   if (!xmdpy->smapi) {
+      Xfree(info);
+      mtx_unlock(&init_mutex);
+      return NULL;
+   }
+
+   xmdpy->screen = driver.create_pipe_screen(display);
+   if (!xmdpy->screen) {
+      free(xmdpy->smapi);
+      Xfree(info);
+      mtx_unlock(&init_mutex);
+      return NULL;
+   }
+
+   /* At this point, both smapi and screen are known to be valid */
+   xmdpy->smapi->screen = xmdpy->screen;
+   xmdpy->smapi->get_param = xmesa_get_param;
+   (void) mtx_init(&xmdpy->mutex, mtx_plain);
 
    /* chain to the list of displays */
    _XLockMutex(_Xglobal_lock);
@@ -232,32 +263,6 @@ xmesa_init_display( Display *display )
    MesaExtInfo.ndisplays++;
    _XUnlockMutex(_Xglobal_lock);
 
-   /* now create the new XMesaDisplay info */
-   assert(display);
-
-   xmdpy->display = display;
-   xmdpy->screen = driver.create_pipe_screen(display);
-   xmdpy->smapi = CALLOC_STRUCT(st_manager);
-   xmdpy->pipe = NULL;
-   if (xmdpy->smapi) {
-      xmdpy->smapi->screen = xmdpy->screen;
-      xmdpy->smapi->get_param = xmesa_get_param;
-   }
-
-   if (xmdpy->screen && xmdpy->smapi) {
-      (void) mtx_init(&xmdpy->mutex, mtx_plain);
-   }
-   else {
-      if (xmdpy->screen) {
-         xmdpy->screen->destroy(xmdpy->screen);
-         xmdpy->screen = NULL;
-      }
-      free(xmdpy->smapi);
-      xmdpy->smapi = NULL;
-
-      xmdpy->display = NULL;
-   }
-
    mtx_unlock(&init_mutex);
 
    return xmdpy;
@@ -399,7 +404,7 @@ xmesa_get_window_size(Display *dpy, XMesaBuffer b,
 static GLuint
 choose_pixel_format(XMesaVisual v)
 {
-   boolean native_byte_order = (host_byte_order() == 
+   boolean native_byte_order = (host_byte_order() ==
                                 ImageByteOrder(v->display));
 
    if (   GET_REDMASK(v)   == 0x0000ff
@@ -485,7 +490,7 @@ choose_depth_stencil_format(XMesaDisplay xmdpy, int depth, int stencil,
    for (i = 0; i < count; i++) {
       if (xmdpy->screen->is_format_supported(xmdpy->screen, formats[i],
                                              target, sample_count,
-                                             tex_usage)) {
+                                             sample_count, tex_usage)) {
          fmt = formats[i];
          break;
       }
@@ -631,15 +636,13 @@ xmesa_free_buffer(XMesaBuffer buffer)
  * initializing the context's visual and buffer information.
  * \param v  the XMesaVisual to initialize
  * \param b  the XMesaBuffer to initialize (may be NULL)
- * \param rgb_flag  TRUE = RGBA mode, FALSE = color index mode
  * \param window  the window/pixmap we're rendering into
  * \param cmap  the colormap associated with the window/pixmap
  * \return GL_TRUE=success, GL_FALSE=failure
  */
 static GLboolean
 initialize_visual_and_buffer(XMesaVisual v, XMesaBuffer b,
-                             GLboolean rgb_flag, Drawable window,
-                             Colormap cmap)
+                             Drawable window, Colormap cmap)
 {
    assert(!b || b->xm_visual == v);
 
@@ -647,29 +650,22 @@ initialize_visual_and_buffer(XMesaVisual v, XMesaBuffer b,
    v->BitsPerPixel = bits_per_pixel(v);
    assert(v->BitsPerPixel > 0);
 
-   if (rgb_flag == GL_FALSE) {
-      /* COLOR-INDEXED WINDOW: not supported*/
+   /* RGB WINDOW:
+    * We support RGB rendering into almost any kind of visual.
+    */
+   const int xclass = v->visualType;
+   if (xclass != GLX_TRUE_COLOR && xclass != GLX_DIRECT_COLOR) {
+      _mesa_warning(NULL,
+         "XMesa: RGB mode rendering not supported in given visual.\n");
       return GL_FALSE;
    }
-   else {
-      /* RGB WINDOW:
-       * We support RGB rendering into almost any kind of visual.
-       */
-      const int xclass = v->visualType;
-      if (xclass != GLX_TRUE_COLOR && xclass == !GLX_DIRECT_COLOR) {
-        _mesa_warning(NULL,
-            "XMesa: RGB mode rendering not supported in given visual.\n");
-        return GL_FALSE;
-      }
-      v->mesa_visual.indexBits = 0;
 
-      if (v->BitsPerPixel == 32) {
-         /* We use XImages for all front/back buffers.  If an X Window or
-          * X Pixmap is 32bpp, there's no guarantee that the alpha channel
-          * will be preserved.  For XImages we're in luck.
-          */
-         v->mesa_visual.alphaBits = 8;
-      }
+   if (v->BitsPerPixel == 32) {
+      /* We use XImages for all front/back buffers.  If an X Window or
+       * X Pixmap is 32bpp, there's no guarantee that the alpha channel
+       * will be preserved.  For XImages we're in luck.
+       */
+      v->mesa_visual.alphaBits = 8;
    }
 
    /*
@@ -693,12 +689,12 @@ initialize_visual_and_buffer(XMesaVisual v, XMesaBuffer b,
 
 /**
  * Convert an X visual type to a GLX visual type.
- * 
+ *
  * \param visualType X visual type (i.e., \c TrueColor, \c StaticGray, etc.)
  *        to be converted.
  * \return If \c visualType is a valid X visual type, a GLX visual type will
  *         be returned.  Otherwise \c GLX_NONE will be returned.
- * 
+ *
  * \note
  * This code was lifted directly from lib/GL/glx/glcontextmodes.c in the
  * DRI CVS tree.
@@ -770,6 +766,9 @@ XMesaVisual XMesaCreateVisual( Display *display,
    if (!xmdpy)
       return NULL;
 
+   if (!rgb_flag)
+      return NULL;
+
    /* For debugging only */
    if (getenv("MESA_XSYNC")) {
       /* This makes debugging X easier.
@@ -816,14 +815,14 @@ XMesaVisual XMesaCreateVisual( Display *display,
    if (alpha_flag)
       v->mesa_visual.alphaBits = 8;
 
-   (void) initialize_visual_and_buffer( v, NULL, rgb_flag, 0, 0 );
+   (void) initialize_visual_and_buffer( v, NULL, 0, 0 );
 
    {
       const int xclass = v->visualType;
       if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) {
-         red_bits   = _mesa_bitcount(GET_REDMASK(v));
-         green_bits = _mesa_bitcount(GET_GREENMASK(v));
-         blue_bits  = _mesa_bitcount(GET_BLUEMASK(v));
+         red_bits   = util_bitcount(GET_REDMASK(v));
+         green_bits = util_bitcount(GET_GREENMASK(v));
+         blue_bits  = util_bitcount(GET_BLUEMASK(v));
       }
       else {
          /* this is an approximation */
@@ -844,7 +843,6 @@ XMesaVisual XMesaCreateVisual( Display *display,
    {
       struct gl_config *vis = &v->mesa_visual;
 
-      vis->rgbMode          = GL_TRUE;
       vis->doubleBufferMode = db_flag;
       vis->stereoMode       = stereo_flag;
 
@@ -854,7 +852,6 @@ XMesaVisual XMesaCreateVisual( Display *display,
       vis->alphaBits        = alpha_bits;
       vis->rgbBits          = red_bits + green_bits + blue_bits;
 
-      vis->indexBits      = 0;
       vis->depthBits      = depth_size;
       vis->stencilBits    = stencil_size;
 
@@ -863,10 +860,6 @@ XMesaVisual XMesaCreateVisual( Display *display,
       vis->accumBlueBits  = accum_blue_size;
       vis->accumAlphaBits = accum_alpha_size;
 
-      vis->haveAccumBuffer   = accum_red_size > 0;
-      vis->haveDepthBuffer   = depth_size > 0;
-      vis->haveStencilBuffer = stencil_size > 0;
-
       vis->numAuxBuffers = 0;
       vis->level = 0;
       vis->sampleBuffers = num_samples > 1;
@@ -888,6 +881,7 @@ XMesaVisual XMesaCreateVisual( Display *display,
    if (!xmdpy->screen->is_format_supported(xmdpy->screen,
                                            v->stvis.color_format,
                                            PIPE_TEXTURE_2D, num_samples,
+                                           num_samples,
                                            PIPE_BIND_RENDER_TARGET))
       v->stvis.color_format = PIPE_FORMAT_NONE;
 
@@ -935,10 +929,10 @@ xmesa_get_name(void)
 /**
  * Do per-display initializations.
  */
-void
+int
 xmesa_init( Display *display )
 {
-   xmesa_init_display(display);
+   return xmesa_init_display(display) ? 0 : 1;
 }
 
 
@@ -1035,7 +1029,7 @@ XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list,
 
    c->st->st_manager_private = (void *) c;
 
-   c->hud = hud_create(c->st->cso_context);
+   c->hud = hud_create(c->st->cso_context, NULL);
 
    return c;
 
@@ -1051,14 +1045,14 @@ PUBLIC
 void XMesaDestroyContext( XMesaContext c )
 {
    if (c->hud) {
-      hud_destroy(c->hud);
+      hud_destroy(c->hud, NULL);
    }
 
    c->st->destroy(c->st);
 
-   /* FIXME: We should destroy the screen here, but if we do so, surfaces may 
+   /* FIXME: We should destroy the screen here, but if we do so, surfaces may
     * outlive it, causing segfaults
-   struct pipe_screen *screen = c->st->pipe->screen; 
+   struct pipe_screen *screen = c->st->pipe->screen;
    screen->destroy(screen);
    */
 
@@ -1109,8 +1103,7 @@ XMesaCreateWindowBuffer(XMesaVisual v, Window w)
    if (!b)
       return NULL;
 
-   if (!initialize_visual_and_buffer( v, b, v->mesa_visual.rgbMode,
-                                      (Drawable) w, cmap )) {
+   if (!initialize_visual_and_buffer( v, b, (Drawable) w, cmap )) {
       xmesa_free_buffer(b);
       return NULL;
    }
@@ -1140,8 +1133,7 @@ XMesaCreatePixmapBuffer(XMesaVisual v, Pixmap p, Colormap cmap)
    if (!b)
       return NULL;
 
-   if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode,
-                                    (Drawable) p, cmap)) {
+   if (!initialize_visual_and_buffer(v, b, (Drawable) p, cmap)) {
       xmesa_free_buffer(b);
       return NULL;
    }
@@ -1175,8 +1167,8 @@ XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p,
       if (ctx->Extensions.ARB_texture_non_power_of_two) {
          target = GLX_TEXTURE_2D_EXT;
       }
-      else if (   _mesa_bitcount(b->width)  == 1
-               && _mesa_bitcount(b->height) == 1) {
+      else if (   util_bitcount(b->width)  == 1
+               && util_bitcount(b->height) == 1) {
          /* power of two size */
          if (b->height == 1) {
             target = GLX_TEXTURE_1D_EXT;
@@ -1199,8 +1191,7 @@ XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p,
    b->TextureFormat = format;
    b->TextureMipmap = mipmap;
 
-   if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode,
-                                    (Drawable) p, cmap)) {
+   if (!initialize_visual_and_buffer(v, b, (Drawable) p, cmap)) {
       xmesa_free_buffer(b);
       return NULL;
    }
@@ -1229,8 +1220,7 @@ XMesaCreatePBuffer(XMesaVisual v, Colormap cmap,
    if (!b)
       return NULL;
 
-   if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode,
-                                    drawable, cmap)) {
+   if (!initialize_visual_and_buffer(v, b, drawable, cmap)) {
       xmesa_free_buffer(b);
       return NULL;
    }
@@ -1268,6 +1258,9 @@ xmesa_check_buffer_size(XMesaBuffer b)
 {
    GLuint old_width, old_height;
 
+   if (!b)
+      return;
+
    if (b->type == PBUFFER)
       return;
 
@@ -1297,8 +1290,9 @@ GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer,
    }
 
    if (c) {
-      if (!drawBuffer || !readBuffer)
-         return GL_FALSE;  /* must specify buffers! */
+      if (!drawBuffer != !readBuffer) {
+         return GL_FALSE;  /* must specify zero or two buffers! */
+      }
 
       if (c == old_ctx &&
          c->xm_buffer == drawBuffer &&
@@ -1312,10 +1306,13 @@ GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer,
       c->xm_buffer = drawBuffer;
       c->xm_read_buffer = readBuffer;
 
-      stapi->make_current(stapi, c->st, drawBuffer->stfb, readBuffer->stfb);
+      stapi->make_current(stapi, c->st,
+                          drawBuffer ? drawBuffer->stfb : NULL,
+                          readBuffer ? readBuffer->stfb : NULL);
 
       /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */
-      drawBuffer->wasCurrent = GL_TRUE;
+      if (drawBuffer)
+         drawBuffer->wasCurrent = GL_TRUE;
    }
    else {
       /* Detach */
@@ -1357,11 +1354,11 @@ void XMesaSwapBuffers( XMesaBuffer b )
    if (xmctx && xmctx->hud) {
       struct pipe_resource *back =
          xmesa_get_framebuffer_resource(b->stfb, ST_ATTACHMENT_BACK_LEFT);
-      hud_run(xmctx->hud, back);
+      hud_run(xmctx->hud, NULL, back);
    }
 
    if (xmctx && xmctx->xm_buffer == b) {
-      xmctx->st->flush( xmctx->st, ST_FLUSH_FRONT, NULL);
+      xmctx->st->flush( xmctx->st, ST_FLUSH_FRONT, NULL, NULL, NULL);
    }
 
    xmesa_swap_st_framebuffer(b->stfb);
@@ -1376,7 +1373,7 @@ void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height )
 {
    XMesaContext xmctx = XMesaGetCurrentContext();
 
-   xmctx->st->flush( xmctx->st, ST_FLUSH_FRONT, NULL);
+   xmctx->st->flush( xmctx->st, ST_FLUSH_FRONT, NULL, NULL, NULL);
 
    xmesa_copy_st_framebuffer(b->stfb,
          ST_ATTACHMENT_BACK_LEFT, ST_ATTACHMENT_FRONT_LEFT,
@@ -1391,7 +1388,7 @@ void XMesaFlush( XMesaContext c )
       XMesaDisplay xmdpy = xmesa_init_display(c->xm_visual->display);
       struct pipe_fence_handle *fence = NULL;
 
-      c->st->flush(c->st, ST_FLUSH_FRONT, &fence);
+      c->st->flush(c->st, ST_FLUSH_FRONT, &fence, NULL, NULL);
       if (fence) {
          xmdpy->screen->fence_finish(xmdpy->screen, NULL, fence,
                                      PIPE_TIMEOUT_INFINITE);