Reviewed-by: Samuel Pitoiset <samuel.pitoi...@gmail.com>

On 11/13/2015 08:17 PM, Nicolai Hähnle wrote:
It is easy enough to pre-determine the required size, and arrays are
generally better behaved especially when they get large.

v2: make sure init_perf_monitor returns true when no counters are active
(spotted by Samuel Pitoiset)
---
  src/mesa/state_tracker/st_cb_perfmon.c | 81 ++++++++++++++++++++--------------
  src/mesa/state_tracker/st_cb_perfmon.h | 18 ++++----
  2 files changed, 58 insertions(+), 41 deletions(-)

diff --git a/src/mesa/state_tracker/st_cb_perfmon.c 
b/src/mesa/state_tracker/st_cb_perfmon.c
index ec12eb2..8628e23 100644
--- a/src/mesa/state_tracker/st_cb_perfmon.c
+++ b/src/mesa/state_tracker/st_cb_perfmon.c
@@ -42,15 +42,14 @@ init_perf_monitor(struct gl_context *ctx, struct 
gl_perf_monitor_object *m)
     struct st_context *st = st_context(ctx);
     struct st_perf_monitor_object *stm = st_perf_monitor_object(m);
     struct pipe_context *pipe = st->pipe;
+   unsigned num_active_counters = 0;
     int gid, cid;

     st_flush_bitmap_cache(st);

-   /* Create a query for each active counter. */
+   /* Determine the number of active counters. */
     for (gid = 0; gid < ctx->PerfMonitor.NumGroups; gid++) {
        const struct gl_perf_monitor_group *g = &ctx->PerfMonitor.Groups[gid];
-      const struct st_perf_monitor_group *stg = &st->perfmon[gid];
-      BITSET_WORD tmp;

        if (m->ActiveGroups[gid] > g->MaxActiveCounters) {
           /* Maximum number of counters reached. Cannot start the session. */
@@ -61,19 +60,32 @@ init_perf_monitor(struct gl_context *ctx, struct 
gl_perf_monitor_object *m)
           return false;
        }

+      num_active_counters += m->ActiveGroups[gid];
+   }
+
+   if (!num_active_counters)
+      return true;
+
+   stm->active_counters = CALLOC(num_active_counters,
+                                 sizeof(*stm->active_counters));
+   if (!stm->active_counters)
+      return false;
+
+   /* Create a query for each active counter. */
+   for (gid = 0; gid < ctx->PerfMonitor.NumGroups; gid++) {
+      const struct gl_perf_monitor_group *g = &ctx->PerfMonitor.Groups[gid];
+      const struct st_perf_monitor_group *stg = &st->perfmon[gid];
+      BITSET_WORD tmp;
+
        BITSET_FOREACH_SET(cid, tmp, m->ActiveCounters[gid], g->NumCounters) {
           const struct st_perf_monitor_counter *stc = &stg->counters[cid];
-         struct st_perf_counter_object *cntr;
-
-         cntr = CALLOC_STRUCT(st_perf_counter_object);
-         if (!cntr)
-            return false;
+         struct st_perf_counter_object *cntr =
+            &stm->active_counters[stm->num_active_counters];

           cntr->query    = pipe->create_query(pipe, stc->query_type, 0);
           cntr->id       = cid;
           cntr->group_id = gid;
-
-         list_addtail(&cntr->list, &stm->active_counters);
+         ++stm->num_active_counters;
        }
     }
     return true;
@@ -83,24 +95,24 @@ static void
  reset_perf_monitor(struct st_perf_monitor_object *stm,
                     struct pipe_context *pipe)
  {
-   struct st_perf_counter_object *cntr, *tmp;
+   unsigned i;

-   LIST_FOR_EACH_ENTRY_SAFE(cntr, tmp, &stm->active_counters, list) {
-      if (cntr->query)
-         pipe->destroy_query(pipe, cntr->query);
-      list_del(&cntr->list);
-      free(cntr);
+   for (i = 0; i < stm->num_active_counters; ++i) {
+      struct pipe_query *query = stm->active_counters[i].query;
+      if (query)
+         pipe->destroy_query(pipe, query);
     }
+   FREE(stm->active_counters);
+   stm->active_counters = NULL;
+   stm->num_active_counters = 0;
  }

  static struct gl_perf_monitor_object *
  st_NewPerfMonitor(struct gl_context *ctx)
  {
     struct st_perf_monitor_object *stq = 
ST_CALLOC_STRUCT(st_perf_monitor_object);
-   if (stq) {
-      list_inithead(&stq->active_counters);
+   if (stq)
        return &stq->base;
-   }
     return NULL;
  }

@@ -119,9 +131,9 @@ st_BeginPerfMonitor(struct gl_context *ctx, struct 
gl_perf_monitor_object *m)
  {
     struct st_perf_monitor_object *stm = st_perf_monitor_object(m);
     struct pipe_context *pipe = st_context(ctx)->pipe;
-   struct st_perf_counter_object *cntr;
+   unsigned i;

-   if (LIST_IS_EMPTY(&stm->active_counters)) {
+   if (!stm->num_active_counters) {
        /* Create a query for each active counter before starting
         * a new monitoring session. */
        if (!init_perf_monitor(ctx, m))
@@ -129,8 +141,9 @@ st_BeginPerfMonitor(struct gl_context *ctx, struct 
gl_perf_monitor_object *m)
     }

     /* Start the query for each active counter. */
-   LIST_FOR_EACH_ENTRY(cntr, &stm->active_counters, list) {
-      if (!pipe->begin_query(pipe, cntr->query))
+   for (i = 0; i < stm->num_active_counters; ++i) {
+      struct pipe_query *query = stm->active_counters[i].query;
+      if (!pipe->begin_query(pipe, query))
            goto fail;
     }
     return true;
@@ -146,11 +159,13 @@ st_EndPerfMonitor(struct gl_context *ctx, struct 
gl_perf_monitor_object *m)
  {
     struct st_perf_monitor_object *stm = st_perf_monitor_object(m);
     struct pipe_context *pipe = st_context(ctx)->pipe;
-   struct st_perf_counter_object *cntr;
+   unsigned i;

     /* Stop the query for each active counter. */
-   LIST_FOR_EACH_ENTRY(cntr, &stm->active_counters, list)
-      pipe->end_query(pipe, cntr->query);
+   for (i = 0; i < stm->num_active_counters; ++i) {
+      struct pipe_query *query = stm->active_counters[i].query;
+      pipe->end_query(pipe, query);
+   }
  }

  static void
@@ -174,16 +189,17 @@ st_IsPerfMonitorResultAvailable(struct gl_context *ctx,
  {
     struct st_perf_monitor_object *stm = st_perf_monitor_object(m);
     struct pipe_context *pipe = st_context(ctx)->pipe;
-   struct st_perf_counter_object *cntr;
+   unsigned i;

-   if (LIST_IS_EMPTY(&stm->active_counters))
+   if (!stm->num_active_counters)
        return false;

     /* The result of a monitoring session is only available if the query of
      * each active counter is idle. */
-   LIST_FOR_EACH_ENTRY(cntr, &stm->active_counters, list) {
+   for (i = 0; i < stm->num_active_counters; ++i) {
+      struct pipe_query *query = stm->active_counters[i].query;
        union pipe_query_result result;
-      if (!pipe->get_query_result(pipe, cntr->query, FALSE, &result)) {
+      if (!pipe->get_query_result(pipe, query, FALSE, &result)) {
           /* The query is busy. */
           return false;
        }
@@ -200,7 +216,7 @@ st_GetPerfMonitorResult(struct gl_context *ctx,
  {
     struct st_perf_monitor_object *stm = st_perf_monitor_object(m);
     struct pipe_context *pipe = st_context(ctx)->pipe;
-   struct st_perf_counter_object *cntr;
+   unsigned i;

     /* Copy data to the supplied array (data).
      *
@@ -210,7 +226,8 @@ st_GetPerfMonitorResult(struct gl_context *ctx,
     GLsizei offset = 0;

     /* Read query results for each active counter. */
-   LIST_FOR_EACH_ENTRY(cntr, &stm->active_counters, list) {
+   for (i = 0; i < stm->num_active_counters; ++i) {
+      struct st_perf_counter_object *cntr = &stm->active_counters[i];
        union pipe_query_result result = { 0 };
        int gid, cid;
        GLenum type;
diff --git a/src/mesa/state_tracker/st_cb_perfmon.h 
b/src/mesa/state_tracker/st_cb_perfmon.h
index 9864b0a..79e0421 100644
--- a/src/mesa/state_tracker/st_cb_perfmon.h
+++ b/src/mesa/state_tracker/st_cb_perfmon.h
@@ -26,21 +26,21 @@

  #include "util/list.h"

+struct st_perf_counter_object
+{
+   struct pipe_query *query;
+   int id;
+   int group_id;
+};
+
  /**
   * Subclass of gl_perf_monitor_object
   */
  struct st_perf_monitor_object
  {
     struct gl_perf_monitor_object base;
-   struct list_head active_counters;
-};
-
-struct st_perf_counter_object
-{
-   struct list_head list;
-   struct pipe_query *query;
-   int id;
-   int group_id;
+   unsigned num_active_counters;
+   struct st_perf_counter_object *active_counters;
  };

  /**

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to