mesa: add PROGRAM_MEMORY
[mesa.git] / src / mesa / main / attrib.c
index f55433ea65fa49c7e65a4a4559b7ab511694e128..61f703667aa7fa174ffabf75a602561a05af1e61 100644 (file)
@@ -32,7 +32,6 @@
 #include "buffers.h"
 #include "bufferobj.h"
 #include "clear.h"
-#include "colormac.h"
 #include "context.h"
 #include "depth.h"
 #include "enable.h"
@@ -178,6 +177,10 @@ struct texture_state
 };
 
 
+/** An unused GL_*_BIT value */
+#define DUMMY_BIT 0x10000000
+
+
 /**
  * Allocate new attribute node of given type/kind.  Attach payload data.
  * Insert it into the linked list named by 'head'.
@@ -217,7 +220,7 @@ push_attrib(struct gl_context *ctx, struct gl_attrib_node **head,
 {
    void *attribute;
 
-   attribute = MALLOC(attr_size);
+   attribute = malloc(attr_size);
    if (attribute == NULL) {
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushAttrib");
       return false;
@@ -227,7 +230,7 @@ push_attrib(struct gl_context *ctx, struct gl_attrib_node **head,
       memcpy(attribute, attr_data, attr_size);
    }
    else {
-      FREE(attribute);
+      free(attribute);
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushAttrib");
       return false;
    }
@@ -254,6 +257,15 @@ _mesa_PushAttrib(GLbitfield mask)
    /* groups specified by the mask. */
    head = NULL;
 
+   if (mask == 0) {
+      /* if mask is zero we still need to push something so that we
+       * don't get a GL_STACK_UNDERFLOW error in glPopAttrib().
+       */
+      GLuint dummy = 0;
+      if (!push_attrib(ctx, &head, DUMMY_BIT, sizeof(dummy), &dummy))
+         goto end;
+   }
+
    if (mask & GL_ACCUM_BUFFER_BIT) {
       if (!push_attrib(ctx, &head, GL_ACCUM_BUFFER_BIT,
                        sizeof(struct gl_accum_attrib),
@@ -277,7 +289,7 @@ _mesa_PushAttrib(GLbitfield mask)
             attr->DrawBuffer[i] = ctx->DrawBuffer->ColorDrawBuffer[i];
       }
       else {
-         FREE(attr);
+         free(attr);
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushAttrib");
          goto end;
       }
@@ -374,7 +386,7 @@ _mesa_PushAttrib(GLbitfield mask)
       attr->FragmentProgram = ctx->FragmentProgram.Enabled;
 
       if (!save_attrib_data(&head, GL_ENABLE_BIT, attr)) {
-         FREE(attr);
+         free(attr);
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushAttrib");
          goto end;
       }
@@ -440,7 +452,7 @@ _mesa_PushAttrib(GLbitfield mask)
          attr->ReadBuffer = ctx->ReadBuffer->ColorReadBuffer;
       }
       else {
-         FREE(attr);
+         free(attr);
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushAttrib");
          goto end;
       }
@@ -491,7 +503,7 @@ _mesa_PushAttrib(GLbitfield mask)
       }
 
       if (!save_attrib_data(&head, GL_TEXTURE_BIT, texstate)) {
-         FREE(texstate);
+         free(texstate);
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushAttrib(GL_TEXTURE_BIT)");
          goto end;
       }
@@ -754,7 +766,7 @@ pop_texture_group(struct gl_context *ctx, struct texture_state *texstate)
       _mesa_set_enable(ctx, GL_TEXTURE_2D, !!(unit->Enabled & TEXTURE_2D_BIT));
       _mesa_set_enable(ctx, GL_TEXTURE_3D, !!(unit->Enabled & TEXTURE_3D_BIT));
       if (ctx->Extensions.ARB_texture_cube_map) {
-         _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP_ARB,
+         _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP,
                           !!(unit->Enabled & TEXTURE_CUBE_BIT));
       }
       if (ctx->Extensions.NV_texture_rectangle) {
@@ -825,7 +837,7 @@ pop_texture_group(struct gl_context *ctx, struct texture_state *texstate)
          /* don't restore state for unsupported targets to prevent
           * raising GL errors.
           */
-         if (obj->Target == GL_TEXTURE_CUBE_MAP_ARB &&
+         if (obj->Target == GL_TEXTURE_CUBE_MAP &&
              !ctx->Extensions.ARB_texture_cube_map) {
             continue;
          }
@@ -925,10 +937,14 @@ _mesa_PopAttrib(void)
 
       if (MESA_VERBOSE & VERBOSE_API) {
          _mesa_debug(ctx, "glPopAttrib %s\n",
-                     _mesa_lookup_enum_by_nr(attr->kind));
+                     _mesa_enum_to_string(attr->kind));
       }
 
       switch (attr->kind) {
+         case DUMMY_BIT:
+            /* do nothing */
+            break;
+
          case GL_ACCUM_BUFFER_BIT:
             {
                const struct gl_accum_attrib *accum;
@@ -1075,6 +1091,11 @@ _mesa_PopAttrib(void)
                _mesa_ClearDepth(depth->Clear);
                _mesa_set_enable(ctx, GL_DEPTH_TEST, depth->Test);
                _mesa_DepthMask(depth->Mask);
+               if (ctx->Extensions.EXT_depth_bounds_test) {
+                  _mesa_set_enable(ctx, GL_DEPTH_BOUNDS_TEST_EXT,
+                                   depth->BoundsTest);
+                  _mesa_DepthBoundsEXT(depth->BoundsMin, depth->BoundsMax);
+               }
             }
             break;
          case GL_ENABLE_BIT:
@@ -1248,8 +1269,10 @@ _mesa_PopAttrib(void)
                _mesa_FrontFace(polygon->FrontFace);
                _mesa_PolygonMode(GL_FRONT, polygon->FrontMode);
                _mesa_PolygonMode(GL_BACK, polygon->BackMode);
-               _mesa_PolygonOffset(polygon->OffsetFactor,
-                                   polygon->OffsetUnits);
+               _mesa_polygon_offset_clamp(ctx,
+                                          polygon->OffsetFactor,
+                                          polygon->OffsetUnits,
+                                          polygon->OffsetClamp);
                _mesa_set_enable(ctx, GL_POLYGON_SMOOTH, polygon->SmoothFlag);
                _mesa_set_enable(ctx, GL_POLYGON_STIPPLE, polygon->StippleFlag);
                _mesa_set_enable(ctx, GL_CULL_FACE, polygon->CullFlag);
@@ -1269,15 +1292,19 @@ _mesa_PopAttrib(void)
            break;
          case GL_SCISSOR_BIT:
             {
+               unsigned i;
                const struct gl_scissor_attrib *scissor;
                scissor = (const struct gl_scissor_attrib *) attr->data;
-               _mesa_set_scissor(ctx, 0,
-                                 scissor->ScissorArray[0].X,
-                                 scissor->ScissorArray[0].Y,
-                                 scissor->ScissorArray[0].Width,
-                                 scissor->ScissorArray[0].Height);
-               _mesa_set_enable(ctx, GL_SCISSOR_TEST, scissor->EnableFlags & 1);
 
+               for (i = 0; i < ctx->Const.MaxViewports; i++) {
+                  _mesa_set_scissor(ctx, i,
+                                    scissor->ScissorArray[i].X,
+                                    scissor->ScissorArray[i].Y,
+                                    scissor->ScissorArray[i].Width,
+                                    scissor->ScissorArray[i].Height);
+                  _mesa_set_enablei(ctx, GL_SCISSOR_TEST, i,
+                                    (scissor->EnableFlags >> i) & 1);
+               }
             }
             break;
          case GL_STENCIL_BUFFER_BIT:
@@ -1341,6 +1368,8 @@ _mesa_PopAttrib(void)
                if (xform->DepthClamp != ctx->Transform.DepthClamp)
                   _mesa_set_enable(ctx, GL_DEPTH_CLAMP,
                                    ctx->Transform.DepthClamp);
+               if (ctx->Extensions.ARB_clip_control)
+                  _mesa_ClipControl(xform->ClipOrigin, xform->ClipDepthMode);
             }
             break;
          case GL_TEXTURE_BIT:
@@ -1353,10 +1382,15 @@ _mesa_PopAttrib(void)
             break;
          case GL_VIEWPORT_BIT:
             {
+               unsigned i;
                const struct gl_viewport_attrib *vp;
                vp = (const struct gl_viewport_attrib *) attr->data;
-               _mesa_Viewport(vp->X, vp->Y, vp->Width, vp->Height);
-               _mesa_DepthRange(vp->Near, vp->Far);
+
+               for (i = 0; i < ctx->Const.MaxViewports; i++) {
+                  _mesa_set_viewport(ctx, i, vp[i].X, vp[i].Y, vp[i].Width,
+                                     vp[i].Height);
+                  _mesa_set_depth_range(ctx, i, vp[i].Near, vp[i].Far);
+               }
             }
             break;
          case GL_MULTISAMPLE_BIT_ARB:
@@ -1424,13 +1458,13 @@ copy_pixelstore(struct gl_context *ctx,
 #define GL_CLIENT_UNPACK_BIT (1<<21)
 
 /**
- * Copy gl_array_object from src to dest.
+ * Copy gl_vertex_array_object from src to dest.
  * 'dest' must be in an initialized state.
  */
 static void
 copy_array_object(struct gl_context *ctx,
-                  struct gl_array_object *dest,
-                  struct gl_array_object *src)
+                  struct gl_vertex_array_object *dest,
+                  struct gl_vertex_array_object *src)
 {
    GLuint i;
 
@@ -1440,7 +1474,7 @@ copy_array_object(struct gl_context *ctx,
    /* In theory must be the same anyway, but on recreate make sure it matches */
    dest->ARBsemantics = src->ARBsemantics;
 
-   for (i = 0; i < Elements(src->_VertexAttrib); i++) {
+   for (i = 0; i < ARRAY_SIZE(src->VertexAttrib); i++) {
       _mesa_copy_client_array(ctx, &dest->_VertexAttrib[i], &src->_VertexAttrib[i]);
       _mesa_copy_vertex_attrib_array(ctx, &dest->VertexAttrib[i], &src->VertexAttrib[i]);
       _mesa_copy_vertex_buffer_binding(ctx, &dest->VertexBinding[i], &src->VertexBinding[i]);
@@ -1448,7 +1482,7 @@ copy_array_object(struct gl_context *ctx,
 
    /* _Enabled must be the same than on push */
    dest->_Enabled = src->_Enabled;
-   dest->_MaxElement = src->_MaxElement;
+   dest->NewArrays = src->NewArrays;
 }
 
 /**
@@ -1474,10 +1508,14 @@ copy_array_attrib(struct gl_context *ctx,
    /* skip RebindArrays */
 
    if (!vbo_deleted)
-      copy_array_object(ctx, dest->ArrayObj, src->ArrayObj);
+      copy_array_object(ctx, dest->VAO, src->VAO);
 
    /* skip ArrayBufferObj */
-   /* skip ElementArrayBufferObj */
+   /* skip IndexBufferObj */
+
+   /* Invalidate draw state. It will be updated during the next draw. */
+   dest->DrawMethod = DRAW_NONE;
+   dest->_DrawArrays = NULL;
 }
 
 /**
@@ -1490,15 +1528,15 @@ save_array_attrib(struct gl_context *ctx,
 {
    /* Set the Name, needed for restore, but do never overwrite.
     * Needs to match value in the object hash. */
-   dest->ArrayObj->Name = src->ArrayObj->Name;
+   dest->VAO->Name = src->VAO->Name;
    /* And copy all of the rest. */
    copy_array_attrib(ctx, dest, src, false);
 
    /* Just reference them here */
    _mesa_reference_buffer_object(ctx, &dest->ArrayBufferObj,
                                  src->ArrayBufferObj);
-   _mesa_reference_buffer_object(ctx, &dest->ArrayObj->ElementArrayBufferObj,
-                                 src->ArrayObj->ElementArrayBufferObj);
+   _mesa_reference_buffer_object(ctx, &dest->VAO->IndexBufferObj,
+                                 src->VAO->IndexBufferObj);
 }
 
 /**
@@ -1521,13 +1559,13 @@ restore_array_attrib(struct gl_context *ctx,
     * The semantics of objects created using APPLE_vertex_array_objects behave
     * differently.  These objects expect to be recreated by pop.  Alas.
     */
-   const bool arb_vao = (src->ArrayObj->Name != 0
-                        && src->ArrayObj->ARBsemantics);
+   const bool arb_vao = (src->VAO->Name != 0
+                        && src->VAO->ARBsemantics);
 
-   if (arb_vao && !_mesa_IsVertexArray(src->ArrayObj->Name))
+   if (arb_vao && !_mesa_IsVertexArray(src->VAO->Name))
       return;
 
-   _mesa_BindVertexArrayAPPLE(src->ArrayObj->Name);
+   _mesa_BindVertexArrayAPPLE(src->VAO->Name);
 
    /* Restore or recreate the buffer objects by the names ... */
    if (!arb_vao
@@ -1543,10 +1581,10 @@ restore_array_attrib(struct gl_context *ctx,
    }
 
    if (!arb_vao
-       || src->ArrayObj->ElementArrayBufferObj->Name == 0
-       || _mesa_IsBuffer(src->ArrayObj->ElementArrayBufferObj->Name))
+       || src->VAO->IndexBufferObj->Name == 0
+       || _mesa_IsBuffer(src->VAO->IndexBufferObj->Name))
       _mesa_BindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB,
-                         src->ArrayObj->ElementArrayBufferObj->Name);
+                         src->VAO->IndexBufferObj->Name);
 }
 
 /**
@@ -1557,15 +1595,15 @@ static bool
 init_array_attrib_data(struct gl_context *ctx,
                        struct gl_array_attrib *attrib)
 {
-   /* Get a non driver gl_array_object. */
-   attrib->ArrayObj = CALLOC_STRUCT( gl_array_object );
+   /* Get a non driver gl_vertex_array_object. */
+   attrib->VAO = CALLOC_STRUCT( gl_vertex_array_object );
 
-   if (attrib->ArrayObj == NULL) {
+   if (attrib->VAO == NULL) {
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushClientAttrib");
       return false;
    }
 
-   _mesa_initialize_array_object(ctx, attrib->ArrayObj, 0);
+   _mesa_initialize_vao(ctx, attrib->VAO, 0);
    return true;
 }
 
@@ -1580,8 +1618,8 @@ free_array_attrib_data(struct gl_context *ctx,
 {
    /* We use a non driver array object, so don't just unref since we would
     * end up using the drivers DeleteArrayObject function for deletion. */
-   _mesa_delete_array_object(ctx, attrib->ArrayObj);
-   attrib->ArrayObj = 0;
+   _mesa_delete_vao(ctx, attrib->VAO);
+   attrib->VAO = 0;
    _mesa_reference_buffer_object(ctx, &attrib->ArrayBufferObj, NULL);
 }
 
@@ -1616,7 +1654,7 @@ _mesa_PushClientAttrib(GLbitfield mask)
       }
       else {
          _mesa_error( ctx, GL_OUT_OF_MEMORY, "glPushClientAttrib" );
-         FREE(attr);
+         free(attr);
          goto end;
       }
 
@@ -1632,7 +1670,7 @@ _mesa_PushClientAttrib(GLbitfield mask)
       }
       else {
          _mesa_error( ctx, GL_OUT_OF_MEMORY, "glPushClientAttrib" );
-         FREE(attr);
+         free(attr);
          goto end;
        }
    }
@@ -1646,7 +1684,7 @@ _mesa_PushClientAttrib(GLbitfield mask)
       }
 
       if (!init_array_attrib_data(ctx, attr)) {
-         FREE(attr);
+         free(attr);
          goto end;
       }
 
@@ -1656,7 +1694,7 @@ _mesa_PushClientAttrib(GLbitfield mask)
       else {
          free_array_attrib_data(ctx, attr);
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushClientAttrib");
-         FREE(attr);
+         free(attr);
          /* goto to keep safe from possible later changes */
          goto end;
       }