r600g: pad the DMA CS to a multiple of 8 dwords
[mesa.git] / src / mesa / main / context.c
index a4dedeea2e509da7065d33137d2871b3a7fc6a7f..02acfc2aa5b99a9f0289fbe45c5034bb5f36ad0e 100644 (file)
@@ -81,6 +81,7 @@
 #include "imports.h"
 #include "accum.h"
 #include "api_exec.h"
+#include "api_loopback.h"
 #include "arrayobj.h"
 #include "attrib.h"
 #include "blend.h"
@@ -563,6 +564,7 @@ _mesa_init_constants(struct gl_context *ctx)
    ctx->Const.MaxTextureMaxAnisotropy = MAX_TEXTURE_MAX_ANISOTROPY;
    ctx->Const.MaxTextureLodBias = MAX_TEXTURE_LOD_BIAS;
    ctx->Const.MaxTextureBufferSize = 65536;
+   ctx->Const.TextureBufferOffsetAlignment = 1;
    ctx->Const.MaxArrayLockSize = MAX_ARRAY_LOCK_SIZE;
    ctx->Const.SubPixelBits = SUB_PIXEL_BITS;
    ctx->Const.MinPointSize = MIN_POINT_SIZE;
@@ -656,6 +658,9 @@ _mesa_init_constants(struct gl_context *ctx)
 
    /* PrimitiveRestart */
    ctx->Const.PrimitiveRestartInSoftware = GL_FALSE;
+
+   /* ES 3.0 or ARB_ES3_compatibility */
+   ctx->Const.MaxElementIndex = 0xffffffffu;
 }
 
 
@@ -706,9 +711,9 @@ check_context_limits(struct gl_context *ctx)
    assert(MAX_TEXTURE_LEVELS >= MAX_CUBE_TEXTURE_LEVELS);
 
    /* Max texture size should be <= max viewport size (render to texture) */
-   assert((1 << (ctx->Const.MaxTextureLevels - 1))
+   assert((1U << (ctx->Const.MaxTextureLevels - 1))
           <= ctx->Const.MaxViewportWidth);
-   assert((1 << (ctx->Const.MaxTextureLevels - 1))
+   assert((1U << (ctx->Const.MaxTextureLevels - 1))
           <= ctx->Const.MaxViewportHeight);
 
    assert(ctx->Const.MaxDrawBuffers <= MAX_DRAW_BUFFERS);
@@ -832,7 +837,7 @@ _mesa_generic_nop(void)
  * Allocate and initialize a new dispatch table.
  */
 struct _glapi_table *
-_mesa_alloc_dispatch_table(int size)
+_mesa_alloc_dispatch_table()
 {
    /* Find the larger of Mesa's dispatch table and libGL's dispatch table.
     * In practice, this'll be the same for stand-alone Mesa.  But for DRI
@@ -842,9 +847,6 @@ _mesa_alloc_dispatch_table(int size)
    GLint numEntries = MAX2(_glapi_get_dispatch_table_size(), _gloffset_COUNT);
    struct _glapi_table *table;
 
-   /* should never happen, but just in case */
-   numEntries = MAX2(numEntries, size);
-
    table = malloc(numEntries * sizeof(_glapi_proc));
    if (table) {
       _glapi_proc *entry = (_glapi_proc *) table;
@@ -856,6 +858,91 @@ _mesa_alloc_dispatch_table(int size)
    return table;
 }
 
+/**
+ * Creates a minimal dispatch table for use within glBegin()/glEnd().
+ *
+ * This ensures that we generate GL_INVALID_OPERATION errors from most
+ * functions, since the set of functions that are valid within Begin/End is
+ * very small.
+ *
+ * From the GL 1.0 specification section 2.6.3, "GL Commands within
+ * Begin/End"
+ *
+ *     "The only GL commands that are allowed within any Begin/End pairs are
+ *      the commands for specifying vertex coordinates, vertex color, normal
+ *      coordinates, and texture coordinates (Vertex, Color, Index, Normal,
+ *      TexCoord), EvalCoord and EvalPoint commands (see section 5.1),
+ *      commands for specifying lighting material parameters (Material
+ *      commands see section 2.12.2), display list invocation commands
+ *      (CallList and CallLists see section 5.4), and the EdgeFlag
+ *      command. Executing Begin after Begin has already been executed but
+ *      before an End is issued generates the INVALID OPERATION error, as does
+ *      executing End without a previous corresponding Begin. Executing any
+ *      other GL command within Begin/End results in the error INVALID
+ *      OPERATION."
+ *
+ * The table entries for specifying vertex attributes are set up by
+ * install_vtxfmt() and _mesa_loopback_init_api_table(), and End() and dlists
+ * are set by install_vtxfmt() as well.
+ */
+static struct _glapi_table *
+create_beginend_table(const struct gl_context *ctx)
+{
+   struct _glapi_table *table;
+
+   table = _mesa_alloc_dispatch_table();
+   if (!table)
+      return NULL;
+
+   /* Fill in functions which return a value, since they should return some
+    * specific value even if they emit a GL_INVALID_OPERATION error from them
+    * being called within glBegin()/glEnd().
+    */
+#define COPY_DISPATCH(func) SET_##func(table, GET_##func(ctx->Exec))
+
+   COPY_DISPATCH(GenLists);
+   COPY_DISPATCH(IsProgram);
+   COPY_DISPATCH(IsVertexArray);
+   COPY_DISPATCH(IsBuffer);
+   COPY_DISPATCH(IsEnabled);
+   COPY_DISPATCH(IsEnabledi);
+   COPY_DISPATCH(IsRenderbuffer);
+   COPY_DISPATCH(IsFramebuffer);
+   COPY_DISPATCH(CheckFramebufferStatus);
+   COPY_DISPATCH(RenderMode);
+   COPY_DISPATCH(GetString);
+   COPY_DISPATCH(GetStringi);
+   COPY_DISPATCH(GetPointerv);
+   COPY_DISPATCH(IsQuery);
+   COPY_DISPATCH(IsSampler);
+   COPY_DISPATCH(IsSync);
+   COPY_DISPATCH(IsTexture);
+   COPY_DISPATCH(IsTransformFeedback);
+   COPY_DISPATCH(DeleteQueries);
+   COPY_DISPATCH(AreTexturesResident);
+   COPY_DISPATCH(FenceSync);
+   COPY_DISPATCH(ClientWaitSync);
+   COPY_DISPATCH(MapBuffer);
+   COPY_DISPATCH(UnmapBuffer);
+   COPY_DISPATCH(MapBufferRange);
+   COPY_DISPATCH(MapBufferRange);
+   COPY_DISPATCH(ObjectPurgeableAPPLE);
+   COPY_DISPATCH(ObjectUnpurgeableAPPLE);
+
+   _mesa_loopback_init_api_table(ctx, table);
+
+   return table;
+}
+
+void
+_mesa_initialize_dispatch_tables(struct gl_context *ctx)
+{
+   /* Do the code-generated setup of the exec table in api_exec.c. */
+   _mesa_initialize_exec_table(ctx);
+
+   if (ctx->Save)
+      _mesa_initialize_save_table(ctx);
+}
 
 /**
  * Initialize a struct gl_context struct (rendering context).
@@ -930,19 +1017,15 @@ _mesa_initialize_context(struct gl_context *ctx,
 
    _mesa_reference_shared_state(ctx, &ctx->Shared, shared);
 
-   if (!init_attrib_groups( ctx )) {
-      _mesa_reference_shared_state(ctx, &ctx->Shared, NULL);
-      return GL_FALSE;
-   }
+   if (!init_attrib_groups( ctx ))
+      goto fail;
 
-   /* setup the API dispatch tables */
-   ctx->Exec = _mesa_create_exec_table(ctx);
-
-   if (!ctx->Exec) {
-      _mesa_reference_shared_state(ctx, &ctx->Shared, NULL);
-      return GL_FALSE;
-   }
-   ctx->CurrentDispatch = ctx->Exec;
+   /* setup the API dispatch tables with all nop functions */
+   ctx->OutsideBeginEnd = _mesa_alloc_dispatch_table();
+   if (!ctx->OutsideBeginEnd)
+      goto fail;
+   ctx->Exec = ctx->OutsideBeginEnd;
+   ctx->CurrentDispatch = ctx->OutsideBeginEnd;
 
    ctx->FragmentProgram._MaintainTexEnvProgram
       = (_mesa_getenv("MESA_TEX_PROG") != NULL);
@@ -963,15 +1046,12 @@ _mesa_initialize_context(struct gl_context *ctx,
          sizeof(ctx->TextureFormatSupported));
 
    switch (ctx->API) {
-   case API_OPENGL:
-      ctx->Save = _mesa_create_save_table(ctx);
-      if (!ctx->Save) {
-         _mesa_reference_shared_state(ctx, &ctx->Shared, NULL);
-        free(ctx->Exec);
-        return GL_FALSE;
-      }
+   case API_OPENGL_COMPAT:
+      ctx->BeginEnd = create_beginend_table(ctx);
+      ctx->Save = _mesa_alloc_dispatch_table();
+      if (!ctx->BeginEnd || !ctx->Save)
+         goto fail;
 
-      _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt );
       /* fall-through */
    case API_OPENGL_CORE:
       break;
@@ -993,13 +1073,18 @@ _mesa_initialize_context(struct gl_context *ctx,
    case API_OPENGLES2:
       ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE;
       ctx->VertexProgram._MaintainTnlProgram = GL_TRUE;
-      ctx->Point.PointSprite = GL_TRUE;  /* always on for ES 2.x */
       break;
    }
 
    ctx->FirstTimeCurrent = GL_TRUE;
 
    return GL_TRUE;
+
+fail:
+   free(ctx->BeginEnd);
+   free(ctx->Exec);
+   free(ctx->Save);
+   return GL_FALSE;
 }
 
 
@@ -1462,7 +1547,7 @@ _mesa_make_current( struct gl_context *newCtx,
       }
 
       if (newCtx->FirstTimeCurrent) {
-         _mesa_compute_version(newCtx);
+         assert(newCtx->Version > 0);
 
          newCtx->Extensions.String = _mesa_make_extension_string(newCtx);
 
@@ -1578,11 +1663,6 @@ _mesa_record_error(struct gl_context *ctx, GLenum error)
    if (ctx->ErrorValue == GL_NO_ERROR) {
       ctx->ErrorValue = error;
    }
-
-   /* Call device driver's error handler, if any.  This is used on the Mac. */
-   if (ctx->Driver.Error) {
-      ctx->Driver.Error(ctx);
-   }
 }