Module: Mesa
Branch: main
Commit: bc9b176aef9cd4b8551a513806d34decf853f9a0
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=bc9b176aef9cd4b8551a513806d34decf853f9a0

Author: Dave Airlie <[email protected]>
Date:   Thu Dec 16 08:40:56 2021 +1000

mesa/st: move perfmon code from st into mesa

This merges the perfmon code after the objects have been merged.

Acked-by: Marek Olšák <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14327>

---

 src/mesa/main/performance_monitor.c    | 294 +++++++++++++++++++++++++++++++--
 src/mesa/state_tracker/st_cb_perfmon.c | 273 ------------------------------
 src/mesa/state_tracker/st_cb_perfmon.h |  11 --
 3 files changed, 284 insertions(+), 294 deletions(-)

diff --git a/src/mesa/main/performance_monitor.c 
b/src/mesa/main/performance_monitor.c
index 73893005b2d..5228b1eec88 100644
--- a/src/mesa/main/performance_monitor.c
+++ b/src/mesa/main/performance_monitor.c
@@ -47,7 +47,9 @@
 #include "util/u_memory.h"
 #include "api_exec_decl.h"
 
-#include "state_tracker/st_cb_perfmon.h"
+#include "state_tracker/st_cb_bitmap.h"
+#include "state_tracker/st_context.h"
+#include "state_tracker/st_debug.h"
 
 #include "pipe/p_context.h"
 #include "pipe/p_screen.h"
@@ -60,6 +62,278 @@ _mesa_init_performance_monitors(struct gl_context *ctx)
    ctx->PerfMonitor.Groups = NULL;
 }
 
+
+static bool
+init_perf_monitor(struct gl_context *ctx, struct gl_perf_monitor_object *m)
+{
+   struct pipe_context *pipe = ctx->pipe;
+   unsigned *batch = NULL;
+   unsigned num_active_counters = 0;
+   unsigned max_batch_counters = 0;
+   unsigned num_batch_counters = 0;
+   int gid, cid;
+
+   st_flush_bitmap_cache(st_context(ctx));
+
+   /* 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];
+
+      if (m->ActiveGroups[gid] > g->MaxActiveCounters) {
+         /* Maximum number of counters reached. Cannot start the session. */
+         if (ST_DEBUG & DEBUG_MESA) {
+            debug_printf("Maximum number of counters reached. "
+                         "Cannot start the session!\n");
+         }
+         return false;
+      }
+
+      num_active_counters += m->ActiveGroups[gid];
+      if (g->has_batch)
+         max_batch_counters += m->ActiveGroups[gid];
+   }
+
+   if (!num_active_counters)
+      return true;
+
+   m->active_counters = CALLOC(num_active_counters,
+                                 sizeof(*m->active_counters));
+   if (!m->active_counters)
+      return false;
+
+   if (max_batch_counters) {
+      batch = CALLOC(max_batch_counters, sizeof(*batch));
+      if (!batch)
+         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];
+
+      BITSET_FOREACH_SET(cid, m->ActiveCounters[gid], g->NumCounters) {
+         const struct gl_perf_monitor_counter *c = &g->Counters[cid];
+         struct gl_perf_counter_object *cntr =
+            &m->active_counters[m->num_active_counters];
+
+         cntr->id       = cid;
+         cntr->group_id = gid;
+         if (c->flags & PIPE_DRIVER_QUERY_FLAG_BATCH) {
+            cntr->batch_index = num_batch_counters;
+            batch[num_batch_counters++] = c->query_type;
+         } else {
+            cntr->query = pipe->create_query(pipe, c->query_type, 0);
+            if (!cntr->query)
+               goto fail;
+         }
+         ++m->num_active_counters;
+      }
+   }
+
+   /* Create the batch query. */
+   if (num_batch_counters) {
+      m->batch_query = pipe->create_batch_query(pipe, num_batch_counters,
+                                                  batch);
+      m->batch_result = CALLOC(num_batch_counters, 
sizeof(m->batch_result->batch[0]));
+      if (!m->batch_query || !m->batch_result)
+         goto fail;
+   }
+
+   FREE(batch);
+   return true;
+
+fail:
+   FREE(batch);
+   return false;
+}
+
+static void
+do_reset_perf_monitor(struct gl_perf_monitor_object *m,
+                   struct pipe_context *pipe)
+{
+   unsigned i;
+
+   for (i = 0; i < m->num_active_counters; ++i) {
+      struct pipe_query *query = m->active_counters[i].query;
+      if (query)
+         pipe->destroy_query(pipe, query);
+   }
+   FREE(m->active_counters);
+   m->active_counters = NULL;
+   m->num_active_counters = 0;
+
+   if (m->batch_query) {
+      pipe->destroy_query(pipe, m->batch_query);
+      m->batch_query = NULL;
+   }
+   FREE(m->batch_result);
+   m->batch_result = NULL;
+}
+
+static void
+delete_perf_monitor(struct gl_context *ctx, struct gl_perf_monitor_object *m)
+{
+   struct pipe_context *pipe = st_context(ctx)->pipe;
+
+   do_reset_perf_monitor(m, pipe);
+   FREE(m);
+}
+
+static GLboolean
+begin_perf_monitor(struct gl_context *ctx, struct gl_perf_monitor_object *m)
+{
+   struct pipe_context *pipe = st_context(ctx)->pipe;
+   unsigned i;
+
+   if (!m->num_active_counters) {
+      /* Create a query for each active counter before starting
+       * a new monitoring session. */
+      if (!init_perf_monitor(ctx, m))
+         goto fail;
+   }
+
+   /* Start the query for each active counter. */
+   for (i = 0; i < m->num_active_counters; ++i) {
+      struct pipe_query *query = m->active_counters[i].query;
+      if (query && !pipe->begin_query(pipe, query))
+          goto fail;
+   }
+
+   if (m->batch_query && !pipe->begin_query(pipe, m->batch_query))
+      goto fail;
+
+   return true;
+
+fail:
+   /* Failed to start the monitoring session. */
+   do_reset_perf_monitor(m, pipe);
+   return false;
+}
+
+static void
+end_perf_monitor(struct gl_context *ctx, struct gl_perf_monitor_object *m)
+{
+   struct pipe_context *pipe = st_context(ctx)->pipe;
+   unsigned i;
+
+   /* Stop the query for each active counter. */
+   for (i = 0; i < m->num_active_counters; ++i) {
+      struct pipe_query *query = m->active_counters[i].query;
+      if (query)
+         pipe->end_query(pipe, query);
+   }
+
+   if (m->batch_query)
+      pipe->end_query(pipe, m->batch_query);
+}
+
+static void
+reset_perf_monitor(struct gl_context *ctx, struct gl_perf_monitor_object *m)
+{
+   struct pipe_context *pipe = st_context(ctx)->pipe;
+
+   if (!m->Ended)
+      end_perf_monitor(ctx, m);
+
+   do_reset_perf_monitor(m, pipe);
+
+   if (m->Active)
+      begin_perf_monitor(ctx, m);
+}
+
+static GLboolean
+is_perf_monitor_result_available(struct gl_context *ctx,
+                                 struct gl_perf_monitor_object *m)
+{
+   struct pipe_context *pipe = st_context(ctx)->pipe;
+   unsigned i;
+
+   if (!m->num_active_counters)
+      return false;
+
+   /* The result of a monitoring session is only available if the query of
+    * each active counter is idle. */
+   for (i = 0; i < m->num_active_counters; ++i) {
+      struct pipe_query *query = m->active_counters[i].query;
+      union pipe_query_result result;
+      if (query && !pipe->get_query_result(pipe, query, FALSE, &result)) {
+         /* The query is busy. */
+         return false;
+      }
+   }
+
+   if (m->batch_query &&
+       !pipe->get_query_result(pipe, m->batch_query, FALSE, m->batch_result))
+      return false;
+
+   return true;
+}
+
+static void
+get_perf_monitor_result(struct gl_context *ctx,
+                        struct gl_perf_monitor_object *m,
+                        GLsizei dataSize,
+                        GLuint *data,
+                        GLint *bytesWritten)
+{
+   struct pipe_context *pipe = st_context(ctx)->pipe;
+   unsigned i;
+
+   /* Copy data to the supplied array (data).
+    *
+    * The output data format is: <group ID, counter ID, value> for each
+    * active counter. The API allows counters to appear in any order.
+    */
+   GLsizei offset = 0;
+   bool have_batch_query = false;
+
+   if (m->batch_query)
+      have_batch_query = pipe->get_query_result(pipe, m->batch_query, TRUE,
+                                                m->batch_result);
+
+   /* Read query results for each active counter. */
+   for (i = 0; i < m->num_active_counters; ++i) {
+      struct gl_perf_counter_object *cntr = &m->active_counters[i];
+      union pipe_query_result result = { 0 };
+      int gid, cid;
+      GLenum type;
+
+      cid  = cntr->id;
+      gid  = cntr->group_id;
+      type = ctx->PerfMonitor.Groups[gid].Counters[cid].Type;
+
+      if (cntr->query) {
+         if (!pipe->get_query_result(pipe, cntr->query, TRUE, &result))
+            continue;
+      } else {
+         if (!have_batch_query)
+            continue;
+         result.batch[0] = m->batch_result->batch[cntr->batch_index];
+      }
+
+      data[offset++] = gid;
+      data[offset++] = cid;
+      switch (type) {
+      case GL_UNSIGNED_INT64_AMD:
+         memcpy(&data[offset], &result.u64, sizeof(uint64_t));
+         offset += sizeof(uint64_t) / sizeof(GLuint);
+         break;
+      case GL_UNSIGNED_INT:
+         memcpy(&data[offset], &result.u32, sizeof(uint32_t));
+         offset += sizeof(uint32_t) / sizeof(GLuint);
+         break;
+      case GL_FLOAT:
+      case GL_PERCENTAGE_AMD:
+         memcpy(&data[offset], &result.f, sizeof(GLfloat));
+         offset += sizeof(GLfloat) / sizeof(GLuint);
+         break;
+      }
+   }
+
+   if (bytesWritten)
+      *bytesWritten = offset * sizeof(GLuint);
+}
+
 void
 _mesa_free_perfomance_monitor_groups(struct gl_context *ctx)
 {
@@ -204,7 +478,7 @@ new_performance_monitor(struct gl_context *ctx, GLuint 
index)
 fail:
    ralloc_free(m->ActiveGroups);
    ralloc_free(m->ActiveCounters);
-   st_DeletePerfMonitor(ctx, m);
+   delete_perf_monitor(ctx, m);
    return NULL;
 }
 
@@ -216,7 +490,7 @@ free_performance_monitor(void *data, void *user)
 
    ralloc_free(m->ActiveGroups);
    ralloc_free(m->ActiveCounters);
-   st_DeletePerfMonitor(ctx, m);
+   delete_perf_monitor(ctx, m);
 }
 
 void
@@ -501,14 +775,14 @@ _mesa_DeletePerfMonitorsAMD(GLsizei n, GLuint *monitors)
       if (m) {
          /* Give the driver a chance to stop the monitor if it's active. */
          if (m->Active) {
-            st_ResetPerfMonitor(ctx, m);
+            reset_perf_monitor(ctx, m);
             m->Ended = false;
          }
 
          _mesa_HashRemove(ctx->PerfMonitor.Monitors, monitors[i]);
          ralloc_free(m->ActiveGroups);
          ralloc_free(m->ActiveCounters);
-         st_DeletePerfMonitor(ctx, m);
+         delete_perf_monitor(ctx, m);
       } else {
          /* "INVALID_VALUE error will be generated if any of the monitor IDs
           *  in the <monitors> parameter to DeletePerfMonitorsAMD do not
@@ -568,7 +842,7 @@ _mesa_SelectPerfMonitorCountersAMD(GLuint monitor, 
GLboolean enable,
     *  results for that monitor become invalidated and the result queries
     *  PERFMON_RESULT_SIZE_AMD and PERFMON_RESULT_AVAILABLE_AMD are reset to 
0."
     */
-   st_ResetPerfMonitor(ctx, m);
+   reset_perf_monitor(ctx, m);
 
    /* Sanity check the counter ID list. */
    for (i = 0; i < numCounters; i++) {
@@ -623,7 +897,7 @@ _mesa_BeginPerfMonitorAMD(GLuint monitor)
    /* The driver is free to return false if it can't begin monitoring for
     * any reason.  This translates into an INVALID_OPERATION error.
     */
-   if (st_BeginPerfMonitor(ctx, m)) {
+   if (begin_perf_monitor(ctx, m)) {
       m->Active = true;
       m->Ended = false;
    } else {
@@ -652,7 +926,7 @@ _mesa_EndPerfMonitorAMD(GLuint monitor)
       return;
    }
 
-   st_EndPerfMonitor(ctx, m);
+   end_perf_monitor(ctx, m);
 
    m->Active = false;
    m->Ended = true;
@@ -714,7 +988,7 @@ _mesa_GetPerfMonitorCounterDataAMD(GLuint monitor, GLenum 
pname,
 
    /* If the monitor has never ended, there is no result. */
    result_available = m->Ended &&
-      st_IsPerfMonitorResultAvailable(ctx, m);
+      is_perf_monitor_result_available(ctx, m);
 
    /* AMD appears to return 0 for all queries unless a result is available. */
    if (!result_available) {
@@ -736,7 +1010,7 @@ _mesa_GetPerfMonitorCounterDataAMD(GLuint monitor, GLenum 
pname,
          *bytesWritten = sizeof(GLuint);
       break;
    case GL_PERFMON_RESULT_AMD:
-      st_GetPerfMonitorResult(ctx, m, dataSize, data, bytesWritten);
+      get_perf_monitor_result(ctx, m, dataSize, data, bytesWritten);
       break;
    default:
       _mesa_error(ctx, GL_INVALID_ENUM,
diff --git a/src/mesa/state_tracker/st_cb_perfmon.c 
b/src/mesa/state_tracker/st_cb_perfmon.c
index 7c18c319f40..64c5ef9b911 100644
--- a/src/mesa/state_tracker/st_cb_perfmon.c
+++ b/src/mesa/state_tracker/st_cb_perfmon.c
@@ -39,279 +39,6 @@
 
 #include "main/performance_monitor.h"
 
-static bool
-init_perf_monitor(struct gl_context *ctx, struct gl_perf_monitor_object *m)
-{
-   struct st_context *st = st_context(ctx);
-   struct pipe_context *pipe = st->pipe;
-   unsigned *batch = NULL;
-   unsigned num_active_counters = 0;
-   unsigned max_batch_counters = 0;
-   unsigned num_batch_counters = 0;
-   int gid, cid;
-
-   st_flush_bitmap_cache(st);
-
-   /* 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];
-
-      if (m->ActiveGroups[gid] > g->MaxActiveCounters) {
-         /* Maximum number of counters reached. Cannot start the session. */
-         if (ST_DEBUG & DEBUG_MESA) {
-            debug_printf("Maximum number of counters reached. "
-                         "Cannot start the session!\n");
-         }
-         return false;
-      }
-
-      num_active_counters += m->ActiveGroups[gid];
-      if (g->has_batch)
-         max_batch_counters += m->ActiveGroups[gid];
-   }
-
-   if (!num_active_counters)
-      return true;
-
-   m->active_counters = CALLOC(num_active_counters,
-                                 sizeof(*m->active_counters));
-   if (!m->active_counters)
-      return false;
-
-   if (max_batch_counters) {
-      batch = CALLOC(max_batch_counters, sizeof(*batch));
-      if (!batch)
-         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];
-
-      BITSET_FOREACH_SET(cid, m->ActiveCounters[gid], g->NumCounters) {
-         const struct gl_perf_monitor_counter *c = &g->Counters[cid];
-         struct gl_perf_counter_object *cntr =
-            &m->active_counters[m->num_active_counters];
-
-         cntr->id       = cid;
-         cntr->group_id = gid;
-         if (c->flags & PIPE_DRIVER_QUERY_FLAG_BATCH) {
-            cntr->batch_index = num_batch_counters;
-            batch[num_batch_counters++] = c->query_type;
-         } else {
-            cntr->query = pipe->create_query(pipe, c->query_type, 0);
-            if (!cntr->query)
-               goto fail;
-         }
-         ++m->num_active_counters;
-      }
-   }
-
-   /* Create the batch query. */
-   if (num_batch_counters) {
-      m->batch_query = pipe->create_batch_query(pipe, num_batch_counters,
-                                                  batch);
-      m->batch_result = CALLOC(num_batch_counters, 
sizeof(m->batch_result->batch[0]));
-      if (!m->batch_query || !m->batch_result)
-         goto fail;
-   }
-
-   FREE(batch);
-   return true;
-
-fail:
-   FREE(batch);
-   return false;
-}
-
-static void
-reset_perf_monitor(struct gl_perf_monitor_object *m,
-                   struct pipe_context *pipe)
-{
-   unsigned i;
-
-   for (i = 0; i < m->num_active_counters; ++i) {
-      struct pipe_query *query = m->active_counters[i].query;
-      if (query)
-         pipe->destroy_query(pipe, query);
-   }
-   FREE(m->active_counters);
-   m->active_counters = NULL;
-   m->num_active_counters = 0;
-
-   if (m->batch_query) {
-      pipe->destroy_query(pipe, m->batch_query);
-      m->batch_query = NULL;
-   }
-   FREE(m->batch_result);
-   m->batch_result = NULL;
-}
-
-void
-st_DeletePerfMonitor(struct gl_context *ctx, struct gl_perf_monitor_object *m)
-{
-   struct pipe_context *pipe = st_context(ctx)->pipe;
-
-   reset_perf_monitor(m, pipe);
-   FREE(m);
-}
-
-GLboolean
-st_BeginPerfMonitor(struct gl_context *ctx, struct gl_perf_monitor_object *m)
-{
-   struct pipe_context *pipe = st_context(ctx)->pipe;
-   unsigned i;
-
-   if (!m->num_active_counters) {
-      /* Create a query for each active counter before starting
-       * a new monitoring session. */
-      if (!init_perf_monitor(ctx, m))
-         goto fail;
-   }
-
-   /* Start the query for each active counter. */
-   for (i = 0; i < m->num_active_counters; ++i) {
-      struct pipe_query *query = m->active_counters[i].query;
-      if (query && !pipe->begin_query(pipe, query))
-          goto fail;
-   }
-
-   if (m->batch_query && !pipe->begin_query(pipe, m->batch_query))
-      goto fail;
-
-   return true;
-
-fail:
-   /* Failed to start the monitoring session. */
-   reset_perf_monitor(m, pipe);
-   return false;
-}
-
-void
-st_EndPerfMonitor(struct gl_context *ctx, struct gl_perf_monitor_object *m)
-{
-   struct pipe_context *pipe = st_context(ctx)->pipe;
-   unsigned i;
-
-   /* Stop the query for each active counter. */
-   for (i = 0; i < m->num_active_counters; ++i) {
-      struct pipe_query *query = m->active_counters[i].query;
-      if (query)
-         pipe->end_query(pipe, query);
-   }
-
-   if (m->batch_query)
-      pipe->end_query(pipe, m->batch_query);
-}
-
-void
-st_ResetPerfMonitor(struct gl_context *ctx, struct gl_perf_monitor_object *m)
-{
-   struct pipe_context *pipe = st_context(ctx)->pipe;
-
-   if (!m->Ended)
-      st_EndPerfMonitor(ctx, m);
-
-   reset_perf_monitor(m, pipe);
-
-   if (m->Active)
-      st_BeginPerfMonitor(ctx, m);
-}
-
-GLboolean
-st_IsPerfMonitorResultAvailable(struct gl_context *ctx,
-                                struct gl_perf_monitor_object *m)
-{
-   struct pipe_context *pipe = st_context(ctx)->pipe;
-   unsigned i;
-
-   if (!m->num_active_counters)
-      return false;
-
-   /* The result of a monitoring session is only available if the query of
-    * each active counter is idle. */
-   for (i = 0; i < m->num_active_counters; ++i) {
-      struct pipe_query *query = m->active_counters[i].query;
-      union pipe_query_result result;
-      if (query && !pipe->get_query_result(pipe, query, FALSE, &result)) {
-         /* The query is busy. */
-         return false;
-      }
-   }
-
-   if (m->batch_query &&
-       !pipe->get_query_result(pipe, m->batch_query, FALSE, m->batch_result))
-      return false;
-
-   return true;
-}
-
-void
-st_GetPerfMonitorResult(struct gl_context *ctx,
-                        struct gl_perf_monitor_object *m,
-                        GLsizei dataSize,
-                        GLuint *data,
-                        GLint *bytesWritten)
-{
-   struct pipe_context *pipe = st_context(ctx)->pipe;
-   unsigned i;
-
-   /* Copy data to the supplied array (data).
-    *
-    * The output data format is: <group ID, counter ID, value> for each
-    * active counter. The API allows counters to appear in any order.
-    */
-   GLsizei offset = 0;
-   bool have_batch_query = false;
-
-   if (m->batch_query)
-      have_batch_query = pipe->get_query_result(pipe, m->batch_query, TRUE,
-                                                m->batch_result);
-
-   /* Read query results for each active counter. */
-   for (i = 0; i < m->num_active_counters; ++i) {
-      struct gl_perf_counter_object *cntr = &m->active_counters[i];
-      union pipe_query_result result = { 0 };
-      int gid, cid;
-      GLenum type;
-
-      cid  = cntr->id;
-      gid  = cntr->group_id;
-      type = ctx->PerfMonitor.Groups[gid].Counters[cid].Type;
-
-      if (cntr->query) {
-         if (!pipe->get_query_result(pipe, cntr->query, TRUE, &result))
-            continue;
-      } else {
-         if (!have_batch_query)
-            continue;
-         result.batch[0] = m->batch_result->batch[cntr->batch_index];
-      }
-
-      data[offset++] = gid;
-      data[offset++] = cid;
-      switch (type) {
-      case GL_UNSIGNED_INT64_AMD:
-         memcpy(&data[offset], &result.u64, sizeof(uint64_t));
-         offset += sizeof(uint64_t) / sizeof(GLuint);
-         break;
-      case GL_UNSIGNED_INT:
-         memcpy(&data[offset], &result.u32, sizeof(uint32_t));
-         offset += sizeof(uint32_t) / sizeof(GLuint);
-         break;
-      case GL_FLOAT:
-      case GL_PERCENTAGE_AMD:
-         memcpy(&data[offset], &result.f, sizeof(GLfloat));
-         offset += sizeof(GLfloat) / sizeof(GLuint);
-         break;
-      }
-   }
-
-   if (bytesWritten)
-      *bytesWritten = offset * sizeof(GLuint);
-}
-
-
 bool
 st_have_perfmon(struct st_context *st)
 {
diff --git a/src/mesa/state_tracker/st_cb_perfmon.h 
b/src/mesa/state_tracker/st_cb_perfmon.h
index 84daa7b0335..69480d3c4a9 100644
--- a/src/mesa/state_tracker/st_cb_perfmon.h
+++ b/src/mesa/state_tracker/st_cb_perfmon.h
@@ -32,15 +32,4 @@ st_have_perfmon(struct st_context *st);
 void
 st_destroy_perfmon(struct st_context *st);
 
-void st_DeletePerfMonitor(struct gl_context *ctx, struct 
gl_perf_monitor_object *m);
-GLboolean st_BeginPerfMonitor(struct gl_context *ctx, struct 
gl_perf_monitor_object *m);
-void st_EndPerfMonitor(struct gl_context *ctx, struct gl_perf_monitor_object 
*m);
-void st_ResetPerfMonitor(struct gl_context *ctx, struct gl_perf_monitor_object 
*m);
-GLboolean st_IsPerfMonitorResultAvailable(struct gl_context *ctx,
-                                          struct gl_perf_monitor_object *m);
-void st_GetPerfMonitorResult(struct gl_context *ctx,
-                             struct gl_perf_monitor_object *m,
-                             GLsizei dataSize,
-                             GLuint *data,
-                             GLint *bytesWritten);
 #endif

Reply via email to