swrast: Fix GL_ATI_separate_stencil
[mesa.git] / src / mesa / drivers / dri / swrast / swrast.c
index 5c2b346e3e9c1fb6774b747e6ad389ca43cb4bb9..15b57244dcdd9da81d944b38b57dc2a735788489 100644 (file)
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
-/* TODO:
- *   - depth 8 (ci8, r3g3b2 ?)
- *   - XMesaResizeBuffers() ?
- *     add it to __DRIcoreExtension or own extension (GL_MESA_resize_buffers) ?
- *   - GLX_MESA_copy_sub_buffer
- *   - GLX_EXT_texture_from_pixmap
- *
- * BUGS:
- *   - winpos, glxpixmap: draw half width only with xorg at depth 16,
- *     they somehow manage to get a wrong drawable with depth 32,
- *     the "depth 32" visual is the composite overlay visual which is the
- *     only available single-buffer visual with glx_visuals "min" ...
- *
- *   there is clearly something wrong with GLX visual setup, the assumption
- *   that GLX runs before composite no longer holds ...
+/*
+ * DRI software rasterizer
  *
- *   at depth 16:
- *   with glx_visuals "min", the composite overlay visual is added
- *   with glx_visuals "all", segfaults when moving cursor over glx window
+ * This is the mesa swrast module packaged into a DRI driver structure.
  *
- *   - texobj: loses textures at depth 32
- *   - texcyl: crashes mesa with "Linear Filtrered"
+ * The front-buffer is allocated by the loader. The loader provides read/write
+ * callbacks for access to the front-buffer. The driver uses a scratch row for
+ * front-buffer rendering to avoid repeated calls to the loader.
  *
- * DONE:
- *   - round image (i.e. backbuffer) pitch to 32 bits
- *   - depth 16
- *   - front-buffer rendering - depths, wincopy
- *   - GLX_SGI_make_current_read (wincopy with front)
+ * The back-buffer is allocated by the driver and is private.
  */
 
-#include <GL/gl.h>
-#include <GL/internal/dri_interface.h>
-#include "context.h"
-#include "extensions.h"
-#include "framebuffer.h"
-#include "imports.h"
-#include "renderbuffer.h"
+#include "main/context.h"
+#include "main/extensions.h"
+#include "main/framebuffer.h"
+#include "main/imports.h"
+#include "main/renderbuffer.h"
 #include "swrast/swrast.h"
 #include "swrast_setup/swrast_setup.h"
 #include "tnl/tnl.h"
@@ -63,6 +43,7 @@
 #include "tnl/t_pipeline.h"
 #include "vbo/vbo.h"
 #include "drivers/common/driverfuncs.h"
+#include "utils.h"
 
 #include "swrast_priv.h"
 
@@ -71,6 +52,7 @@
 #define need_GL_VERSION_1_4
 #define need_GL_VERSION_1_5
 #define need_GL_VERSION_2_0
+#define need_GL_VERSION_2_1
 
 /* sw extensions for imaging */
 #define need_GL_EXT_blend_color
@@ -84,6 +66,7 @@
 #define need_GL_ARB_vertex_program
 #define need_GL_APPLE_vertex_array_object
 #define need_GL_ATI_fragment_shader
+#define need_GL_ATI_separate_stencil
 #define need_GL_EXT_depth_bounds_test
 #define need_GL_EXT_framebuffer_object
 #define need_GL_EXT_framebuffer_blit
@@ -95,7 +78,6 @@
 #define need_GL_NV_fragment_program
 
 #include "extension_helper.h"
-#include "utils.h"
 
 const struct dri_extension card_extensions[] =
 {
@@ -103,6 +85,7 @@ const struct dri_extension card_extensions[] =
     { "GL_VERSION_1_4",                        GL_VERSION_1_4_functions },
     { "GL_VERSION_1_5",                        GL_VERSION_1_5_functions },
     { "GL_VERSION_2_0",                        GL_VERSION_2_0_functions },
+    { "GL_VERSION_2_1",                        GL_VERSION_2_1_functions },
 
     { "GL_EXT_blend_color",            GL_EXT_blend_color_functions },
     { "GL_EXT_blend_minmax",           GL_EXT_blend_minmax_functions },
@@ -114,6 +97,7 @@ const struct dri_extension card_extensions[] =
     { "GL_ARB_vertex_program",         GL_ARB_vertex_program_functions },
     { "GL_APPLE_vertex_array_object",  GL_APPLE_vertex_array_object_functions },
     { "GL_ATI_fragment_shader",                GL_ATI_fragment_shader_functions },
+    { "GL_ATI_separate_stencil",       GL_ATI_separate_stencil_functions },
     { "GL_EXT_depth_bounds_test",      GL_EXT_depth_bounds_test_functions },
     { "GL_EXT_framebuffer_object",     GL_EXT_framebuffer_object_functions },
     { "GL_EXT_framebuffer_blit",       GL_EXT_framebuffer_blit_functions },
@@ -126,6 +110,11 @@ const struct dri_extension card_extensions[] =
     { NULL,                            NULL }
 };
 
+
+/**
+ * Screen and config-related functions
+ */
+
 static void
 setupLoaderExtensions(__DRIscreen *psp,
                      const __DRIextension **extensions)
@@ -143,53 +132,62 @@ swrastFillInModes(__DRIscreen *psp,
                  unsigned pixel_bits, unsigned depth_bits,
                  unsigned stencil_bits, GLboolean have_back_buffer)
 {
-   __DRIconfig **configs;
-   unsigned depth_buffer_factor;
-   unsigned back_buffer_factor;
-   GLenum fb_format;
-   GLenum fb_type;
-
-   /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
-    * support pageflipping at all.
-    */
-   static const GLenum back_buffer_modes[] = {
-      GLX_NONE, GLX_SWAP_UNDEFINED_OML
-   };
-
-   u_int8_t depth_bits_array[3];
-   u_int8_t stencil_bits_array[3];
-
-   depth_bits_array[0] = 0;
-   depth_bits_array[1] = depth_bits;
-   depth_bits_array[2] = depth_bits;
-
-   stencil_bits_array[0] = 0;
-   stencil_bits_array[1] = 0;
-   stencil_bits_array[2] = stencil_bits;
-
-   depth_buffer_factor = 3;
-   back_buffer_factor = 2;
-
-   if (pixel_bits == 16) {
-      fb_format = GL_RGB;
-      fb_type = GL_UNSIGNED_SHORT_5_6_5;
-   }
-   else {
-      fb_format = GL_BGRA;
-      fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
-   }
-
-   configs = driCreateConfigs(fb_format, fb_type,
-                             depth_bits_array, stencil_bits_array,
-                             depth_buffer_factor, back_buffer_modes,
-                             back_buffer_factor);
-   if (configs == NULL) {
-      fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
-              __LINE__);
-      return NULL;
-   }
+    __DRIconfig **configs;
+    unsigned depth_buffer_factor;
+    unsigned back_buffer_factor;
+    GLenum fb_format;
+    GLenum fb_type;
+
+    /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
+     * support pageflipping at all.
+     */
+    static const GLenum back_buffer_modes[] = {
+       GLX_NONE, GLX_SWAP_UNDEFINED_OML
+    };
+
+    uint8_t depth_bits_array[4];
+    uint8_t stencil_bits_array[4];
+
+    depth_bits_array[0] = 0;
+    depth_bits_array[1] = 0;
+    depth_bits_array[2] = depth_bits;
+    depth_bits_array[3] = depth_bits;
+
+    /* Just like with the accumulation buffer, always provide some modes
+     * with a stencil buffer.
+     */
+    stencil_bits_array[0] = 0;
+    stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
+    stencil_bits_array[2] = 0;
+    stencil_bits_array[3] = (stencil_bits == 0) ? 8 : stencil_bits;
+
+    depth_buffer_factor = 4;
+    back_buffer_factor = 2;
+
+    if (pixel_bits == 8) {
+       fb_format = GL_RGB;
+       fb_type = GL_UNSIGNED_BYTE_2_3_3_REV;
+    }
+    else if (pixel_bits == 16) {
+       fb_format = GL_RGB;
+       fb_type = GL_UNSIGNED_SHORT_5_6_5;
+    }
+    else {
+       fb_format = GL_BGRA;
+       fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
+    }
+
+    configs = driCreateConfigs(fb_format, fb_type,
+                              depth_bits_array, stencil_bits_array,
+                              depth_buffer_factor, back_buffer_modes,
+                              back_buffer_factor);
+    if (configs == NULL) {
+       fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
+               __LINE__);
+       return NULL;
+    }
 
-   return configs;
+    return configs;
 }
 
 static __DRIscreen *
@@ -198,6 +196,7 @@ driCreateNewScreen(int scrn, const __DRIextension **extensions,
 {
     static const __DRIextension *emptyExtensionList[] = { NULL };
     __DRIscreen *psp;
+    __DRIconfig **configs8, **configs16, **configs32;
 
     (void) data;
 
@@ -212,8 +211,13 @@ driCreateNewScreen(int scrn, const __DRIextension **extensions,
     psp->num = scrn;
     psp->extensions = emptyExtensionList;
 
-    *driver_configs = driConcatConfigs(swrastFillInModes(psp, 16, 16, 0, 1),
-                                      swrastFillInModes(psp, 32, 24, 8, 1));
+    configs8  = swrastFillInModes(psp,  8,  8, 0, 1);
+    configs16 = swrastFillInModes(psp, 16, 16, 0, 1);
+    configs32 = swrastFillInModes(psp, 32, 24, 8, 1);
+
+    configs16 = (__DRIconfig **)driConcatConfigs(configs8, configs16);
+
+    *driver_configs = driConcatConfigs(configs16, configs32);
 
     driInitExtensions( NULL, card_extensions, GL_FALSE );
 
@@ -238,17 +242,14 @@ static const __DRIextension **driGetExtensions(__DRIscreen *psp)
 
 
 /**
- * swrast_buffer.c
+ * Framebuffer and renderbuffer-related functions.
  */
 
 static GLuint
 choose_pixel_format(const GLvisual *v)
 {
     if (v->rgbMode) {
-       /* XXX 24bpp packed, 8bpp, xmesa gets bitsPerPixel from xserver */
        int bpp = v->rgbBits;
-       if (bpp == 24)
-           bpp = 32;
 
        if (bpp == 32
            && v->redMask   == 0xff0000
@@ -260,6 +261,11 @@ choose_pixel_format(const GLvisual *v)
            && v->greenMask == 0x07e0
            && v->blueMask  == 0x001f)
            return PF_R5G6B5;
+       else if (bpp == 8
+           && v->redMask   == 0x07
+           && v->greenMask == 0x38
+           && v->blueMask  == 0xc0)
+           return PF_R3G3B2;
     }
     else {
        if (v->indexBits == 8)
@@ -285,6 +291,7 @@ swrast_alloc_front_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
 {
     struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb);
     int bpp;
+    unsigned mask = PITCH_ALIGN_BITS - 1;
 
     TRACE;
 
@@ -307,15 +314,15 @@ swrast_alloc_front_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
        return GL_FALSE;
     }
 
-    /* always pad to 32 bits */
-    xrb->pitch = ((width * bpp + 0x1f) & ~0x1f) / 8;
+    /* always pad to PITCH_ALIGN_BITS */
+    xrb->pitch = ((width * bpp + mask) & ~mask) / 8;
 
     return GL_TRUE;
 }
 
 static GLboolean
 swrast_alloc_back_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
-                       GLenum internalFormat, GLuint width, GLuint height)
+                         GLenum internalFormat, GLuint width, GLuint height)
 {
     struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb);
 
@@ -323,7 +330,7 @@ swrast_alloc_back_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
 
     _mesa_free(rb->Data);
 
-    (void) swrast_alloc_front_storage(ctx, rb, internalFormat, width, height);
+    swrast_alloc_front_storage(ctx, rb, internalFormat, width, height);
 
     rb->Data = _mesa_malloc(height * xrb->pitch);
 
@@ -338,50 +345,61 @@ swrast_new_renderbuffer(const GLvisual *visual, GLboolean front)
 
     TRACE;
 
-    if (xrb) {
-       _mesa_init_renderbuffer(&xrb->Base, 0);
+    if (!xrb)
+       return NULL;
 
-       pixel_format = choose_pixel_format(visual);
+    _mesa_init_renderbuffer(&xrb->Base, 0);
 
-       xrb->Base.Delete = swrast_delete_renderbuffer;
-       if (front) {
-           xrb->Base.AllocStorage = swrast_alloc_front_storage;
-           swrast_set_span_funcs_pixmap(xrb, pixel_format);
-       }
-       else {
-           xrb->Base.AllocStorage = swrast_alloc_back_storage;
-           swrast_set_span_funcs_ximage(xrb, pixel_format);
-       }
+    pixel_format = choose_pixel_format(visual);
 
-       switch (pixel_format) {
-       case PF_A8R8G8B8:
-           xrb->Base.InternalFormat = GL_RGBA;
-           xrb->Base._BaseFormat = GL_RGBA;
-           xrb->Base.DataType = GL_UNSIGNED_BYTE;
-           xrb->Base.RedBits   = 8 * sizeof(GLubyte);
-           xrb->Base.GreenBits = 8 * sizeof(GLubyte);
-           xrb->Base.BlueBits  = 8 * sizeof(GLubyte);
-           xrb->Base.AlphaBits = 8 * sizeof(GLubyte);
-           break;
-       case PF_R5G6B5:
-           xrb->Base.InternalFormat = GL_RGB;
-           xrb->Base._BaseFormat = GL_RGB;
-           xrb->Base.DataType = GL_UNSIGNED_BYTE;
-           xrb->Base.RedBits   = 5 * sizeof(GLubyte);
-           xrb->Base.GreenBits = 6 * sizeof(GLubyte);
-           xrb->Base.BlueBits  = 5 * sizeof(GLubyte);
-           xrb->Base.AlphaBits = 0;
-           break;
-       case PF_CI8:
-           xrb->Base.InternalFormat = GL_COLOR_INDEX8_EXT;
-           xrb->Base._BaseFormat = GL_COLOR_INDEX;
-           xrb->Base.DataType = GL_UNSIGNED_BYTE;
-           xrb->Base.IndexBits = 8 * sizeof(GLubyte);
-           break;
-       default:
-           return NULL;
-       }
+    xrb->Base.Delete = swrast_delete_renderbuffer;
+    if (front) {
+       xrb->Base.AllocStorage = swrast_alloc_front_storage;
+       swrast_set_span_funcs_front(xrb, pixel_format);
     }
+    else {
+       xrb->Base.AllocStorage = swrast_alloc_back_storage;
+       swrast_set_span_funcs_back(xrb, pixel_format);
+    }
+
+    switch (pixel_format) {
+    case PF_A8R8G8B8:
+       xrb->Base.InternalFormat = GL_RGBA;
+       xrb->Base._BaseFormat = GL_RGBA;
+       xrb->Base.DataType = GL_UNSIGNED_BYTE;
+       xrb->Base.RedBits   = 8 * sizeof(GLubyte);
+       xrb->Base.GreenBits = 8 * sizeof(GLubyte);
+       xrb->Base.BlueBits  = 8 * sizeof(GLubyte);
+       xrb->Base.AlphaBits = 8 * sizeof(GLubyte);
+       break;
+    case PF_R5G6B5:
+       xrb->Base.InternalFormat = GL_RGB;
+       xrb->Base._BaseFormat = GL_RGB;
+       xrb->Base.DataType = GL_UNSIGNED_BYTE;
+       xrb->Base.RedBits   = 5 * sizeof(GLubyte);
+       xrb->Base.GreenBits = 6 * sizeof(GLubyte);
+       xrb->Base.BlueBits  = 5 * sizeof(GLubyte);
+       xrb->Base.AlphaBits = 0;
+       break;
+    case PF_R3G3B2:
+       xrb->Base.InternalFormat = GL_RGB;
+       xrb->Base._BaseFormat = GL_RGB;
+       xrb->Base.DataType = GL_UNSIGNED_BYTE;
+       xrb->Base.RedBits   = 3 * sizeof(GLubyte);
+       xrb->Base.GreenBits = 3 * sizeof(GLubyte);
+       xrb->Base.BlueBits  = 2 * sizeof(GLubyte);
+       xrb->Base.AlphaBits = 0;
+       break;
+    case PF_CI8:
+       xrb->Base.InternalFormat = GL_COLOR_INDEX8_EXT;
+       xrb->Base._BaseFormat = GL_COLOR_INDEX;
+       xrb->Base.DataType = GL_UNSIGNED_BYTE;
+       xrb->Base.IndexBits = 8 * sizeof(GLubyte);
+       break;
+    default:
+       return NULL;
+    }
+
     return xrb;
 }
 
@@ -477,7 +495,7 @@ static void driSwapBuffers(__DRIdrawable *buf)
 
 
 /**
- * swrast_dd.c
+ * General device driver functions.
  */
 
 static void
@@ -511,7 +529,7 @@ get_string(GLcontext *ctx, GLenum pname)
        case GL_VENDOR:
            return (const GLubyte *) "Mesa Project";
        case GL_RENDERER:
-           return (const GLubyte *) "X.Org";
+           return (const GLubyte *) "Software Rasterizer";
        default:
            return NULL;
     }
@@ -548,7 +566,7 @@ swrast_init_driver_functions(struct dd_function_table *driver)
 
 
 /**
- * swrast_context.c
+ * Context-related functions.
  */
 
 static __DRIcontext *
@@ -646,10 +664,11 @@ static int driBindContext(__DRIcontext *ctx,
        if (!draw || !read)
            return GL_FALSE;
 
-       /* check for same context and buffer */
        mesaCtx = &ctx->Base;
        mesaDraw = &draw->Base;
        mesaRead = &read->Base;
+
+       /* check for same context and buffer */
        if (mesaCtx == _mesa_get_current_context()
            && mesaCtx->DrawBuffer == mesaDraw
            && mesaCtx->ReadBuffer == mesaRead) {
@@ -678,19 +697,18 @@ static int driUnbindContext(__DRIcontext *ctx)
 {
     TRACE;
     (void) ctx;
-    _mesa_make_current(NULL, NULL, NULL);
     return GL_TRUE;
 }
 
 
 static const __DRIcoreExtension driCoreExtension = {
     { __DRI_CORE, __DRI_CORE_VERSION },
-    NULL,
+    NULL, /* driCreateNewScreen */
     driDestroyScreen,
     driGetExtensions,
     driGetConfigAttrib,
     driIndexConfigAttrib,
-    NULL,
+    NULL, /* driCreateNewDrawable */
     driDestroyDrawable,
     driSwapBuffers,
     driCreateNewContext,
@@ -703,7 +721,7 @@ static const __DRIcoreExtension driCoreExtension = {
 static const __DRIswrastExtension driSWRastExtension = {
     { __DRI_SWRAST, __DRI_SWRAST_VERSION },
     driCreateNewScreen,
-    driCreateNewDrawable,
+    driCreateNewDrawable
 };
 
 /* This is the table of extensions that the loader will dlsym() for. */