mesa: tidy up renderbuffer RefCount initialisation
[mesa.git] / src / mesa / main / attrib.c
index 30c815d67f0261a27e29b3aa5bb6f9f624f33c2f..8e738c91c8fae074e4ef8c3a3cea3d3f5f98e342 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"
@@ -112,7 +111,7 @@ struct gl_enable_attrib
    GLboolean PolygonSmooth;
    GLboolean PolygonStipple;
    GLboolean RescaleNormals;
-   GLboolean Scissor;
+   GLbitfield Scissor;
    GLboolean Stencil;
    GLboolean StencilTwoSide;          /* GL_EXT_stencil_two_side */
    GLboolean MultisampleEnabled;      /* GL_ARB_multisample */
@@ -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;
       }
@@ -354,7 +366,7 @@ _mesa_PushAttrib(GLbitfield mask)
       attr->PolygonSmooth = ctx->Polygon.SmoothFlag;
       attr->PolygonStipple = ctx->Polygon.StippleFlag;
       attr->RescaleNormals = ctx->Transform.RescaleNormals;
-      attr->Scissor = ctx->Scissor.Enabled;
+      attr->Scissor = ctx->Scissor.EnableFlags;
       attr->Stencil = ctx->Stencil.Enabled;
       attr->StencilTwoSide = ctx->Stencil.TestTwoSide;
       attr->MultisampleEnabled = ctx->Multisample.Enabled;
@@ -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;
       }
@@ -533,8 +545,9 @@ _mesa_PushAttrib(GLbitfield mask)
 
    if (mask & GL_VIEWPORT_BIT) {
       if (!push_attrib(ctx, &head, GL_VIEWPORT_BIT,
-                       sizeof(struct gl_viewport_attrib),
-                       (void*)&ctx->Viewport))
+                       sizeof(struct gl_viewport_attrib)
+                       * ctx->Const.MaxViewports,
+                       (void*)&ctx->ViewportArray))
          goto end;
    }
 
@@ -658,7 +671,13 @@ pop_enable_group(struct gl_context *ctx, const struct gl_enable_attrib *enable)
                    GL_POLYGON_SMOOTH);
    TEST_AND_UPDATE(ctx->Polygon.StippleFlag, enable->PolygonStipple,
                    GL_POLYGON_STIPPLE);
-   TEST_AND_UPDATE(ctx->Scissor.Enabled, enable->Scissor, GL_SCISSOR_TEST);
+   if (ctx->Scissor.EnableFlags != enable->Scissor) {
+      unsigned i;
+
+      for (i = 0; i < ctx->Const.MaxViewports; i++) {
+         _mesa_set_enablei(ctx, GL_SCISSOR_TEST, i, (enable->Scissor >> i) & 1);
+      }
+   }
    TEST_AND_UPDATE(ctx->Stencil.Enabled, enable->Stencil, GL_STENCIL_TEST);
    if (ctx->Extensions.EXT_stencil_two_side) {
       TEST_AND_UPDATE(ctx->Stencil.TestTwoSide, enable->StencilTwoSide, GL_STENCIL_TEST_TWO_SIDE_EXT);
@@ -747,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) {
@@ -818,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;
          }
@@ -918,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;
@@ -1048,7 +1071,8 @@ _mesa_PopAttrib(void)
                if (ctx->Extensions.ARB_color_buffer_float)
                   _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR_ARB,
                                    color->ClampFragmentColor);
-               _mesa_ClampColor(GL_CLAMP_READ_COLOR_ARB, color->ClampReadColor);
+               if (ctx->Extensions.ARB_color_buffer_float || ctx->Version >= 30)
+                  _mesa_ClampColor(GL_CLAMP_READ_COLOR_ARB, color->ClampReadColor);
 
                /* GL_ARB_framebuffer_sRGB / GL_EXT_framebuffer_sRGB */
                if (ctx->Extensions.EXT_framebuffer_sRGB)
@@ -1068,6 +1092,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:
@@ -1219,7 +1248,7 @@ _mesa_PopAttrib(void)
                   GLuint u;
                   for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
                      _mesa_TexEnvi(GL_POINT_SPRITE_NV, GL_COORD_REPLACE_NV,
-                                   (GLint) point->CoordReplace[u]);
+                                   !!(point->CoordReplace & (1u << u)));
                   }
                   _mesa_set_enable(ctx, GL_POINT_SPRITE_NV,point->PointSprite);
                   if (ctx->Extensions.NV_point_sprite)
@@ -1241,8 +1270,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);
@@ -1262,11 +1293,26 @@ _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_Scissor(scissor->X, scissor->Y,
-                             scissor->Width, scissor->Height);
-               _mesa_set_enable(ctx, GL_SCISSOR_TEST, scissor->Enabled);
+
+               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);
+               }
+               if (ctx->Extensions.EXT_window_rectangles) {
+                  STATIC_ASSERT(sizeof(struct gl_scissor_rect) ==
+                                4 * sizeof(GLint));
+                  _mesa_WindowRectanglesEXT(
+                        scissor->WindowRectMode, scissor->NumWindowRects,
+                        (const GLint *)scissor->WindowRects);
+               }
             }
             break;
          case GL_STENCIL_BUFFER_BIT:
@@ -1330,6 +1376,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:
@@ -1337,15 +1385,20 @@ _mesa_PopAttrib(void)
                struct texture_state *texstate
                   = (struct texture_state *) attr->data;
                pop_texture_group(ctx, texstate);
-              ctx->NewState |= _NEW_TEXTURE;
+              ctx->NewState |= _NEW_TEXTURE_OBJECT | _NEW_TEXTURE_STATE;
             }
             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:
@@ -1413,13 +1466,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;
 
@@ -1429,15 +1482,17 @@ 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]);
+      _mesa_copy_vertex_buffer_binding(ctx, &dest->BufferBinding[i], &src->BufferBinding[i]);
    }
 
    /* _Enabled must be the same than on push */
    dest->_Enabled = src->_Enabled;
-   dest->_MaxElement = src->_MaxElement;
+   /* The bitmask of bound VBOs needs to match the VertexBinding array */
+   dest->VertexAttribBufferMask = src->VertexAttribBufferMask;
+   dest->NewArrays = src->NewArrays;
 }
 
 /**
@@ -1463,10 +1518,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;
 }
 
 /**
@@ -1479,15 +1538,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);
 }
 
 /**
@@ -1510,13 +1569,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
@@ -1532,10 +1591,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);
 }
 
 /**
@@ -1546,15 +1605,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;
 }
 
@@ -1569,8 +1628,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);
 }
 
@@ -1605,7 +1664,7 @@ _mesa_PushClientAttrib(GLbitfield mask)
       }
       else {
          _mesa_error( ctx, GL_OUT_OF_MEMORY, "glPushClientAttrib" );
-         FREE(attr);
+         free(attr);
          goto end;
       }
 
@@ -1621,7 +1680,7 @@ _mesa_PushClientAttrib(GLbitfield mask)
       }
       else {
          _mesa_error( ctx, GL_OUT_OF_MEMORY, "glPushClientAttrib" );
-         FREE(attr);
+         free(attr);
          goto end;
        }
    }
@@ -1635,7 +1694,7 @@ _mesa_PushClientAttrib(GLbitfield mask)
       }
 
       if (!init_array_attrib_data(ctx, attr)) {
-         FREE(attr);
+         free(attr);
          goto end;
       }
 
@@ -1645,7 +1704,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;
       }