diff options
author | marha <marha@users.sourceforge.net> | 2013-09-30 09:00:43 +0200 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2013-09-30 09:00:43 +0200 |
commit | 3aaead2ee2e0f925b33c1ccbde7fa3c0b119d064 (patch) | |
tree | b5487ebc7c6056e0b248afc471edf40b90a3b0b4 /mesalib/src/mesa/main | |
parent | 1245204b2091d108a8688ff7f749f2c6cc830381 (diff) | |
parent | a12cf779e828ec70da714832e1eaa730119fe10c (diff) | |
download | vcxsrv-3aaead2ee2e0f925b33c1ccbde7fa3c0b119d064.tar.gz vcxsrv-3aaead2ee2e0f925b33c1ccbde7fa3c0b119d064.tar.bz2 vcxsrv-3aaead2ee2e0f925b33c1ccbde7fa3c0b119d064.zip |
Merge remote-tracking branch 'origin/released'
* origin/released:
git update fontconfig mesa libXau pixman xkeyboard-config 30 Sep 2013
Diffstat (limited to 'mesalib/src/mesa/main')
-rw-r--r-- | mesalib/src/mesa/main/context.c | 2 | ||||
-rw-r--r-- | mesalib/src/mesa/main/core.h | 3 | ||||
-rw-r--r-- | mesalib/src/mesa/main/dd.h | 24 | ||||
-rw-r--r-- | mesalib/src/mesa/main/extensions.c | 1 | ||||
-rw-r--r-- | mesalib/src/mesa/main/mtypes.h | 88 | ||||
-rw-r--r-- | mesalib/src/mesa/main/performance_monitor.c | 609 | ||||
-rw-r--r-- | mesalib/src/mesa/main/performance_monitor.h | 85 | ||||
-rw-r--r-- | mesalib/src/mesa/main/teximage.c | 6 | ||||
-rw-r--r-- | mesalib/src/mesa/main/texobj.c | 9 | ||||
-rw-r--r-- | mesalib/src/mesa/main/texobj.h | 3 | ||||
-rw-r--r-- | mesalib/src/mesa/main/texparam.c | 2 |
11 files changed, 818 insertions, 14 deletions
diff --git a/mesalib/src/mesa/main/context.c b/mesalib/src/mesa/main/context.c index 58f42cc5b..310518c92 100644 --- a/mesalib/src/mesa/main/context.c +++ b/mesalib/src/mesa/main/context.c @@ -105,6 +105,7 @@ #include "macros.h" #include "matrix.h" #include "multisample.h" +#include "performance_monitor.h" #include "pixel.h" #include "pixelstore.h" #include "points.h" @@ -764,6 +765,7 @@ init_attrib_groups(struct gl_context *ctx) _mesa_init_lighting( ctx ); _mesa_init_matrix( ctx ); _mesa_init_multisample( ctx ); + _mesa_init_performance_monitors( ctx ); _mesa_init_pixel( ctx ); _mesa_init_pixelstore( ctx ); _mesa_init_point( ctx ); diff --git a/mesalib/src/mesa/main/core.h b/mesalib/src/mesa/main/core.h index 0ba0db8a3..73ed01c25 100644 --- a/mesalib/src/mesa/main/core.h +++ b/mesalib/src/mesa/main/core.h @@ -31,8 +31,7 @@ * The public header of core mesa. * * This file is the (only) public header of core mesa. It is supposed to be - * used by GLX, WGL, and GLSL. It is important that headers directly or - * indirectly included here do not perform feature tests (#if FEATURE_xxx). + * used by GLX, WGL, and GLSL. */ diff --git a/mesalib/src/mesa/main/dd.h b/mesalib/src/mesa/main/dd.h index c1d9b2c95..0806e41a0 100644 --- a/mesalib/src/mesa/main/dd.h +++ b/mesalib/src/mesa/main/dd.h @@ -645,6 +645,30 @@ struct dd_function_table { void (*WaitQuery)(struct gl_context *ctx, struct gl_query_object *q); /*@}*/ + /** + * \name Performance monitors + */ + /*@{*/ + struct gl_perf_monitor_object * (*NewPerfMonitor)(struct gl_context *ctx); + void (*DeletePerfMonitor)(struct gl_context *ctx, + struct gl_perf_monitor_object *m); + GLboolean (*BeginPerfMonitor)(struct gl_context *ctx, + struct gl_perf_monitor_object *m); + + /** Stop an active performance monitor, discarding results. */ + void (*ResetPerfMonitor)(struct gl_context *ctx, + struct gl_perf_monitor_object *m); + void (*EndPerfMonitor)(struct gl_context *ctx, + struct gl_perf_monitor_object *m); + GLboolean (*IsPerfMonitorResultAvailable)(struct gl_context *ctx, + struct gl_perf_monitor_object *m); + void (*GetPerfMonitorResult)(struct gl_context *ctx, + struct gl_perf_monitor_object *m, + GLsizei dataSize, + GLuint *data, + GLint *bytesWritten); + /*@}*/ + /** * \name Vertex Array objects diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c index 34615e3e0..eb9362059 100644 --- a/mesalib/src/mesa/main/extensions.c +++ b/mesalib/src/mesa/main/extensions.c @@ -291,6 +291,7 @@ static const struct extension extension_table[] = { { "GL_3DFX_texture_compression_FXT1", o(TDFX_texture_compression_FXT1), GL, 1999 }, { "GL_AMD_conservative_depth", o(ARB_conservative_depth), GL, 2009 }, { "GL_AMD_draw_buffers_blend", o(ARB_draw_buffers_blend), GL, 2009 }, + { "GL_AMD_performance_monitor", o(AMD_performance_monitor), GL, 2007 }, { "GL_AMD_seamless_cubemap_per_texture", o(AMD_seamless_cubemap_per_texture), GL, 2009 }, { "GL_AMD_shader_stencil_export", o(ARB_shader_stencil_export), GL, 2009 }, { "GL_AMD_vertex_shader_layer", o(AMD_vertex_shader_layer), GL, 2012 }, diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index 448946c03..d82672dc9 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -34,6 +34,8 @@ #define MTYPES_H +#include <stdint.h> /* uint32_t */ + #include "main/glheader.h" #include "main/config.h" #include "glapi/glapi.h" @@ -1778,6 +1780,89 @@ struct gl_transform_feedback_state /** + * A "performance monitor" as described in AMD_performance_monitor. + */ +struct gl_perf_monitor_object +{ + GLboolean Active; + + /** + * A list of groups with currently active counters. + * + * ActiveGroups[g] == n if there are n counters active from group 'g'. + */ + unsigned *ActiveGroups; + + /** + * An array of bitsets, subscripted by group ID, then indexed by counter ID. + * + * Checking whether counter 'c' in group 'g' is active can be done via: + * + * BITSET_TEST(ActiveCounters[g], c) + */ + GLuint **ActiveCounters; +}; + + +union gl_perf_monitor_counter_value +{ + float f; + uint64_t u64; + uint32_t u32; +}; + + +struct gl_perf_monitor_counter +{ + /** Human readable name for the counter. */ + const char *Name; + + /** + * Data type of the counter. Valid values are FLOAT, UNSIGNED_INT, + * UNSIGNED_INT64_AMD, and PERCENTAGE_AMD. + */ + GLenum Type; + + /** Minimum counter value. */ + union gl_perf_monitor_counter_value Minimum; + + /** Maximum counter value. */ + union gl_perf_monitor_counter_value Maximum; +}; + + +struct gl_perf_monitor_group +{ + /** Human readable name for the group. */ + const char *Name; + + /** + * Maximum number of counters in this group which can be active at the + * same time. + */ + GLuint MaxActiveCounters; + + /** Array of counters within this group. */ + const struct gl_perf_monitor_counter *Counters; + GLuint NumCounters; +}; + + +/** + * Context state for AMD_performance_monitor. + */ +struct gl_perf_monitor_state +{ + /** Array of performance monitor groups (indexed by group ID) */ + const struct gl_perf_monitor_group *Groups; + GLuint NumGroups; + + /** The table of all performance monitors. */ + struct _mesa_HashTable *Monitors; +}; + + +/** * Names of the various vertex/fragment program register files, etc. * * NOTE: first four tokens must fit into 2 bits (see t_vb_arbprogram.c) @@ -3176,6 +3261,7 @@ struct gl_extensions GLboolean EXT_vertex_array_bgra; GLboolean OES_standard_derivatives; /* vendor extensions */ + GLboolean AMD_performance_monitor; GLboolean AMD_seamless_cubemap_per_texture; GLboolean AMD_vertex_shader_layer; GLboolean APPLE_object_purgeable; @@ -3639,6 +3725,8 @@ struct gl_context struct gl_transform_feedback_state TransformFeedback; + struct gl_perf_monitor_state PerfMonitor; + struct gl_buffer_object *CopyReadBuffer; /**< GL_ARB_copy_buffer */ struct gl_buffer_object *CopyWriteBuffer; /**< GL_ARB_copy_buffer */ diff --git a/mesalib/src/mesa/main/performance_monitor.c b/mesalib/src/mesa/main/performance_monitor.c new file mode 100644 index 000000000..8dfa8261e --- /dev/null +++ b/mesalib/src/mesa/main/performance_monitor.c @@ -0,0 +1,609 @@ +/* + * Copyright © 2012 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * \file performance_monitor.c + * Core Mesa support for the AMD_performance_monitor extension. + * + * In order to implement this extension, start by defining two enums: + * one for Groups, and one for Counters. These will be used as indexes into + * arrays, so they should start at 0 and increment from there. + * + * Counter IDs need to be globally unique. That is, you can't have counter 7 + * in group A and counter 7 in group B. A global enum of all available + * counters is a convenient way to guarantee this. + */ + +#include <stdbool.h> +#include "glheader.h" +#include "context.h" +#include "enums.h" +#include "hash.h" +#include "macros.h" +#include "mtypes.h" +#include "performance_monitor.h" +#include "bitset.h" +#include "ralloc.h" + +void +_mesa_init_performance_monitors(struct gl_context *ctx) +{ + ctx->PerfMonitor.Monitors = _mesa_NewHashTable(); + ctx->PerfMonitor.NumGroups = 0; + ctx->PerfMonitor.Groups = NULL; +} + +static struct gl_perf_monitor_object * +new_performance_monitor(struct gl_context *ctx, GLuint index) +{ + unsigned i; + struct gl_perf_monitor_object *m = ctx->Driver.NewPerfMonitor(ctx); + + if (m == NULL) + return NULL; + + m->ActiveGroups = + rzalloc_array(NULL, unsigned, ctx->PerfMonitor.NumGroups); + + m->ActiveCounters = + ralloc_array(NULL, BITSET_WORD *, ctx->PerfMonitor.NumGroups); + + if (m->ActiveGroups == NULL || m->ActiveCounters == NULL) + goto fail; + + for (i = 0; i < ctx->PerfMonitor.NumGroups; i++) { + const struct gl_perf_monitor_group *g = &ctx->PerfMonitor.Groups[i]; + + m->ActiveCounters[i] = rzalloc_array(m->ActiveCounters, BITSET_WORD, + BITSET_WORDS(g->NumCounters)); + if (m->ActiveCounters[i] == NULL) + goto fail; + } + + return m; + +fail: + ralloc_free(m->ActiveGroups); + ralloc_free(m->ActiveCounters); + ctx->Driver.DeletePerfMonitor(ctx, m); + return NULL; +} + +static inline struct gl_perf_monitor_object * +lookup_monitor(struct gl_context *ctx, GLuint id) +{ + return (struct gl_perf_monitor_object *) + _mesa_HashLookup(ctx->PerfMonitor.Monitors, id); +} + +static inline const struct gl_perf_monitor_group * +get_group(const struct gl_context *ctx, GLuint id) +{ + if (id >= ctx->PerfMonitor.NumGroups) + return NULL; + + return &ctx->PerfMonitor.Groups[id]; +} + +static inline const struct gl_perf_monitor_counter * +get_counter(const struct gl_perf_monitor_group *group_obj, GLuint id) +{ + if (id >= group_obj->NumCounters) + return NULL; + + return &group_obj->Counters[id]; +} + +/*****************************************************************************/ + +void GLAPIENTRY +_mesa_GetPerfMonitorGroupsAMD(GLint *numGroups, GLsizei groupsSize, + GLuint *groups) +{ + GET_CURRENT_CONTEXT(ctx); + + if (numGroups != NULL) + *numGroups = ctx->PerfMonitor.NumGroups; + + if (groupsSize > 0 && groups != NULL) { + unsigned i; + unsigned n = MIN2(groupsSize, ctx->PerfMonitor.NumGroups); + + /* We just use the index in the Groups array as the ID. */ + for (i = 0; i < n; i++) + groups[i] = i; + } +} + +void GLAPIENTRY +_mesa_GetPerfMonitorCountersAMD(GLuint group, GLint *numCounters, + GLint *maxActiveCounters, + GLsizei countersSize, GLuint *counters) +{ + GET_CURRENT_CONTEXT(ctx); + const struct gl_perf_monitor_group *group_obj = get_group(ctx, group); + if (group_obj == NULL) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glGetPerfMonitorCountersAMD(invalid group)"); + return; + } + + if (maxActiveCounters != NULL) + *maxActiveCounters = group_obj->MaxActiveCounters; + + if (numCounters != NULL) + *numCounters = group_obj->NumCounters; + + if (counters != NULL) { + unsigned i; + unsigned n = MIN2(group_obj->NumCounters, countersSize); + for (i = 0; i < n; i++) { + /* We just use the index in the Counters array as the ID. */ + counters[i] = i; + } + } +} + +void GLAPIENTRY +_mesa_GetPerfMonitorGroupStringAMD(GLuint group, GLsizei bufSize, + GLsizei *length, GLchar *groupString) +{ + GET_CURRENT_CONTEXT(ctx); + + const struct gl_perf_monitor_group *group_obj = get_group(ctx, group); + + if (group_obj == NULL) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetPerfMonitorGroupStringAMD"); + return; + } + + if (bufSize == 0) { + /* Return the number of characters that would be required to hold the + * group string, excluding the null terminator. + */ + if (length != NULL) + *length = strlen(group_obj->Name); + } else { + if (length != NULL) + *length = MIN2(strlen(group_obj->Name), bufSize); + if (groupString != NULL) + strncpy(groupString, group_obj->Name, bufSize); + } +} + +void GLAPIENTRY +_mesa_GetPerfMonitorCounterStringAMD(GLuint group, GLuint counter, + GLsizei bufSize, GLsizei *length, + GLchar *counterString) +{ + GET_CURRENT_CONTEXT(ctx); + + const struct gl_perf_monitor_group *group_obj; + const struct gl_perf_monitor_counter *counter_obj; + + group_obj = get_group(ctx, group); + + if (group_obj == NULL) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glGetPerfMonitorCounterStringAMD(invalid group)"); + return; + } + + counter_obj = get_counter(group_obj, counter); + + if (counter_obj == NULL) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glGetPerfMonitorCounterStringAMD(invalid counter)"); + return; + } + + if (bufSize == 0) { + /* Return the number of characters that would be required to hold the + * counter string, excluding the null terminator. + */ + if (length != NULL) + *length = strlen(counter_obj->Name); + } else { + if (length != NULL) + *length = MIN2(strlen(counter_obj->Name), bufSize); + if (counterString != NULL) + strncpy(counterString, counter_obj->Name, bufSize); + } +} + +void GLAPIENTRY +_mesa_GetPerfMonitorCounterInfoAMD(GLuint group, GLuint counter, GLenum pname, + GLvoid *data) +{ + GET_CURRENT_CONTEXT(ctx); + + const struct gl_perf_monitor_group *group_obj; + const struct gl_perf_monitor_counter *counter_obj; + + group_obj = get_group(ctx, group); + + if (group_obj == NULL) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glGetPerfMonitorCounterInfoAMD(invalid group)"); + return; + } + + counter_obj = get_counter(group_obj, counter); + + if (counter_obj == NULL) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glGetPerfMonitorCounterInfoAMD(invalid counter)"); + return; + } + + switch (pname) { + case GL_COUNTER_TYPE_AMD: + *((GLenum *) data) = counter_obj->Type; + break; + + case GL_COUNTER_RANGE_AMD: + switch (counter_obj->Type) { + case GL_FLOAT: + case GL_PERCENTAGE_AMD: { + float *f_data = data; + f_data[0] = counter_obj->Minimum.f; + f_data[1] = counter_obj->Maximum.f; + break; + } + case GL_UNSIGNED_INT: { + uint32_t *u32_data = data; + u32_data[0] = counter_obj->Minimum.u32; + u32_data[1] = counter_obj->Maximum.u32; + break; + } + case GL_UNSIGNED_INT64_AMD: { + uint64_t *u64_data = data; + u64_data[0] = counter_obj->Minimum.u64; + u64_data[1] = counter_obj->Maximum.u64; + break; + } + default: + assert(!"Should not get here: invalid counter type"); + } + break; + + default: + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetPerfMonitorCounterInfoAMD(pname)"); + return; + } +} + +void GLAPIENTRY +_mesa_GenPerfMonitorsAMD(GLsizei n, GLuint *monitors) +{ + GLuint first; + GET_CURRENT_CONTEXT(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glGenPerfMonitorsAMD(%d)\n", n); + + if (n < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGenPerfMonitorsAMD(n < 0)"); + return; + } + + if (monitors == NULL) + return; + + /* We don't actually need them to be contiguous, but this is what + * the rest of Mesa does, so we may as well. + */ + first = _mesa_HashFindFreeKeyBlock(ctx->PerfMonitor.Monitors, n); + if (first) { + GLsizei i; + for (i = 0; i < n; i++) { + struct gl_perf_monitor_object *m = + new_performance_monitor(ctx, first + i); + if (!m) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenPerfMonitorsAMD"); + return; + } + monitors[i] = first + i; + _mesa_HashInsert(ctx->PerfMonitor.Monitors, first + i, m); + } + } else { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenPerfMonitorsAMD"); + return; + } +} + +void GLAPIENTRY +_mesa_DeletePerfMonitorsAMD(GLsizei n, GLuint *monitors) +{ + GLint i; + GET_CURRENT_CONTEXT(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glDeletePerfMonitorsAMD(%d)\n", n); + + if (n < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glDeletePerfMonitorsAMD(n < 0)"); + return; + } + + if (monitors == NULL) + return; + + for (i = 0; i < n; i++) { + struct gl_perf_monitor_object *m = lookup_monitor(ctx, monitors[i]); + + if (m) { + /* Give the driver a chance to stop the monitor if it's active. */ + if (m->Active) + ctx->Driver.ResetPerfMonitor(ctx, m); + + _mesa_HashRemove(ctx->PerfMonitor.Monitors, monitors[i]); + ralloc_free(m->ActiveGroups); + ralloc_free(m->ActiveCounters); + ctx->Driver.DeletePerfMonitor(ctx, m); + } else { + /* "INVALID_VALUE error will be generated if any of the monitor IDs + * in the <monitors> parameter to DeletePerfMonitorsAMD do not + * reference a valid generated monitor ID." + */ + _mesa_error(ctx, GL_INVALID_VALUE, + "glDeletePerfMonitorsAMD(invalid monitor)"); + } + } +} + +void GLAPIENTRY +_mesa_SelectPerfMonitorCountersAMD(GLuint monitor, GLboolean enable, + GLuint group, GLint numCounters, + GLuint *counterList) +{ + GET_CURRENT_CONTEXT(ctx); + unsigned i; + struct gl_perf_monitor_object *m; + const struct gl_perf_monitor_group *group_obj; + + m = lookup_monitor(ctx, monitor); + + /* "INVALID_VALUE error will be generated if the <monitor> parameter to + * SelectPerfMonitorCountersAMD does not reference a monitor created by + * GenPerfMonitorsAMD." + */ + if (m == NULL) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glSelectPerfMonitorCountersAMD(invalid monitor)"); + return; + } + + group_obj = get_group(ctx, group); + + /* "INVALID_VALUE error will be generated if the <group> parameter to + * GetPerfMonitorCountersAMD, GetPerfMonitorCounterStringAMD, + * GetPerfMonitorCounterStringAMD, GetPerfMonitorCounterInfoAMD, or + * SelectPerfMonitorCountersAMD does not reference a valid group ID." + */ + if (group_obj == NULL) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glSelectPerfMonitorCountersAMD(invalid group)"); + return; + } + + /* "INVALID_VALUE error will be generated if the <numCounters> parameter to + * SelectPerfMonitorCountersAMD is less than 0." + */ + if (numCounters < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glSelectPerfMonitorCountersAMD(numCounters < 0)"); + return; + } + + /* "When SelectPerfMonitorCountersAMD is called on a monitor, any outstanding + * results for that monitor become invalidated and the result queries + * PERFMON_RESULT_SIZE_AMD and PERFMON_RESULT_AVAILABLE_AMD are reset to 0." + */ + ctx->Driver.ResetPerfMonitor(ctx, m); + + /* Sanity check the counter ID list. */ + for (i = 0; i < numCounters; i++) { + if (counterList[i] >= group_obj->NumCounters) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glSelectPerfMonitorCountersAMD(invalid counter ID)"); + return; + } + } + + if (enable) { + /* Enable the counters */ + for (i = 0; i < numCounters; i++) { + ++m->ActiveGroups[group]; + BITSET_SET(m->ActiveCounters[group], counterList[i]); + } + } else { + /* Disable the counters */ + for (i = 0; i < numCounters; i++) { + --m->ActiveGroups[group]; + BITSET_CLEAR(m->ActiveCounters[group], counterList[i]); + } + } +} + +void GLAPIENTRY +_mesa_BeginPerfMonitorAMD(GLuint monitor) +{ + GET_CURRENT_CONTEXT(ctx); + + struct gl_perf_monitor_object *m = lookup_monitor(ctx, monitor); + + if (m == NULL) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glBeginPerfMonitorAMD(invalid monitor)"); + return; + } + + /* "INVALID_OPERATION error will be generated if BeginPerfMonitorAMD is + * called when a performance monitor is already active." + */ + if (m->Active) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBeginPerfMonitor(already active)"); + return; + } + + /* The driver is free to return false if it can't begin monitoring for + * any reason. This translates into an INVALID_OPERATION error. + */ + if (ctx->Driver.BeginPerfMonitor(ctx, m)) { + m->Active = true; + } else { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBeginPerfMonitor(driver unable to begin monitoring)"); + } +} + +void GLAPIENTRY +_mesa_EndPerfMonitorAMD(GLuint monitor) +{ + GET_CURRENT_CONTEXT(ctx); + + struct gl_perf_monitor_object *m = lookup_monitor(ctx, monitor); + + if (m == NULL) { + _mesa_error(ctx, GL_INVALID_VALUE, "glEndPerfMonitorAMD(invalid monitor)"); + return; + } + + /* "INVALID_OPERATION error will be generated if EndPerfMonitorAMD is called + * when a performance monitor is not currently started." + */ + if (!m->Active) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginPerfMonitor(not active)"); + return; + } + + ctx->Driver.EndPerfMonitor(ctx, m); + + m->Active = false; +} + +/** + * Return the number of bytes needed to store a monitor's result. + */ +static unsigned +perf_monitor_result_size(const struct gl_context *ctx, + const struct gl_perf_monitor_object *m) +{ + unsigned group, counter; + unsigned size = 0; + + for (group = 0; group < ctx->PerfMonitor.NumGroups; group++) { + const struct gl_perf_monitor_group *g = &ctx->PerfMonitor.Groups[group]; + for (counter = 0; counter < g->NumCounters; counter++) { + const struct gl_perf_monitor_counter *c = &g->Counters[counter]; + + if (!BITSET_TEST(m->ActiveCounters[group], counter)) + continue; + + size += sizeof(uint32_t); /* Group ID */ + size += sizeof(uint32_t); /* Counter ID */ + size += _mesa_perf_monitor_counter_size(c); + } + } + return size; +} + +void GLAPIENTRY +_mesa_GetPerfMonitorCounterDataAMD(GLuint monitor, GLenum pname, + GLsizei dataSize, GLuint *data, + GLint *bytesWritten) +{ + GET_CURRENT_CONTEXT(ctx); + + struct gl_perf_monitor_object *m = lookup_monitor(ctx, monitor); + + if (m == NULL) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glGetPerfMonitorCounterDataAMD(invalid monitor)"); + return; + } + + /* "It is an INVALID_OPERATION error for <data> to be NULL." */ + if (data == NULL) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetPerfMonitorCounterDataAMD(data == NULL)"); + return; + } + + /* We need at least enough room for a single value. */ + if (dataSize < sizeof(GLuint)) { + if (bytesWritten != NULL) + *bytesWritten = 0; + return; + } + + /* AMD appears to return 0 for all queries unless a result is available. */ + if (!ctx->Driver.IsPerfMonitorResultAvailable(ctx, m)) { + *data = 0; + if (bytesWritten != NULL) + *bytesWritten = sizeof(GLuint); + return; + } + + switch (pname) { + case GL_PERFMON_RESULT_AVAILABLE_AMD: + *data = 1; + if (bytesWritten != NULL) + *bytesWritten = sizeof(GLuint); + break; + case GL_PERFMON_RESULT_SIZE_AMD: + *data = perf_monitor_result_size(ctx, m); + if (bytesWritten != NULL) + *bytesWritten = sizeof(GLuint); + break; + case GL_PERFMON_RESULT_AMD: + ctx->Driver.GetPerfMonitorResult(ctx, m, dataSize, data, bytesWritten); + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetPerfMonitorCounterDataAMD(pname)"); + } +} + +/** + * Returns how many bytes a counter's value takes up. + */ +unsigned +_mesa_perf_monitor_counter_size(const struct gl_perf_monitor_counter *c) +{ + switch (c->Type) { + case GL_FLOAT: + case GL_PERCENTAGE_AMD: + return sizeof(GLfloat); + case GL_UNSIGNED_INT: + return sizeof(GLuint); + case GL_UNSIGNED_INT64_AMD: + return sizeof(uint64_t); + default: + assert(!"Should not get here: invalid counter type"); + return 0; + } +} diff --git a/mesalib/src/mesa/main/performance_monitor.h b/mesalib/src/mesa/main/performance_monitor.h new file mode 100644 index 000000000..a852a4184 --- /dev/null +++ b/mesalib/src/mesa/main/performance_monitor.h @@ -0,0 +1,85 @@ +/* + * Copyright © 2012 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * \file performance_monitor.h + * Core Mesa support for the AMD_performance_monitor extension. + */ + +#pragma once +#ifndef PERFORMANCE_MONITOR_H +#define PERFORMANCE_MONITOR_H + +#include "glheader.h" + +extern void +_mesa_init_performance_monitors(struct gl_context *ctx); + +extern void GLAPIENTRY +_mesa_GetPerfMonitorGroupsAMD(GLint *numGroups, GLsizei groupsSize, + GLuint *groups); + +extern void GLAPIENTRY +_mesa_GetPerfMonitorCountersAMD(GLuint group, GLint *numCounters, + GLint *maxActiveCounters, + GLsizei countersSize, GLuint *counters); + +extern void GLAPIENTRY +_mesa_GetPerfMonitorGroupStringAMD(GLuint group, GLsizei bufSize, + GLsizei *length, GLchar *groupString); + +extern void GLAPIENTRY +_mesa_GetPerfMonitorCounterStringAMD(GLuint group, GLuint counter, + GLsizei bufSize, GLsizei *length, + GLchar *counterString); + +extern void GLAPIENTRY +_mesa_GetPerfMonitorCounterInfoAMD(GLuint group, GLuint counter, GLenum pname, + GLvoid *data); + +extern void GLAPIENTRY +_mesa_GenPerfMonitorsAMD(GLsizei n, GLuint *monitors); + +extern void GLAPIENTRY +_mesa_DeletePerfMonitorsAMD(GLsizei n, GLuint *monitors); + +extern void GLAPIENTRY +_mesa_SelectPerfMonitorCountersAMD(GLuint monitor, GLboolean enable, + GLuint group, GLint numCounters, + GLuint *counterList); + +extern void GLAPIENTRY +_mesa_BeginPerfMonitorAMD(GLuint monitor); + +extern void GLAPIENTRY +_mesa_EndPerfMonitorAMD(GLuint monitor); + +extern void GLAPIENTRY +_mesa_GetPerfMonitorCounterDataAMD(GLuint monitor, GLenum pname, + GLsizei dataSize, GLuint *data, + GLint *bytesWritten); + +unsigned +_mesa_perf_monitor_counter_size(const struct gl_perf_monitor_counter *); + +#endif diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c index c1261138d..e6cae0034 100644 --- a/mesalib/src/mesa/main/teximage.c +++ b/mesalib/src/mesa/main/teximage.c @@ -3179,7 +3179,7 @@ teximage(struct gl_context *ctx, GLboolean compressed, GLuint dims, _mesa_update_fbo_texture(ctx, texObj, face, level); - _mesa_dirty_texobj(ctx, texObj, GL_TRUE); + _mesa_dirty_texobj(ctx, texObj); } } _mesa_unlock_texture(ctx, texObj); @@ -3298,7 +3298,7 @@ _mesa_EGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image) ctx->Driver.EGLImageTargetTexture2D(ctx, target, texObj, texImage, image); - _mesa_dirty_texobj(ctx, texObj, GL_TRUE); + _mesa_dirty_texobj(ctx, texObj); } _mesa_unlock_texture(ctx, texObj); @@ -3569,7 +3569,7 @@ copyteximage(struct gl_context *ctx, GLuint dims, _mesa_update_fbo_texture(ctx, texObj, face, level); - _mesa_dirty_texobj(ctx, texObj, GL_TRUE); + _mesa_dirty_texobj(ctx, texObj); } } _mesa_unlock_texture(ctx, texObj); diff --git a/mesalib/src/mesa/main/texobj.c b/mesalib/src/mesa/main/texobj.c index cc2c786bb..abd30c563 100644 --- a/mesalib/src/mesa/main/texobj.c +++ b/mesalib/src/mesa/main/texobj.c @@ -715,20 +715,17 @@ _mesa_cube_complete(const struct gl_texture_object *texObj) /** * Mark a texture object dirty. It forces the object to be incomplete - * and optionally forces the context to re-validate its state. + * and forces the context to re-validate its state. * * \param ctx GL context. * \param texObj texture object. - * \param invalidate_state also invalidate context state. */ void -_mesa_dirty_texobj(struct gl_context *ctx, struct gl_texture_object *texObj, - GLboolean invalidate_state) +_mesa_dirty_texobj(struct gl_context *ctx, struct gl_texture_object *texObj) { texObj->_BaseComplete = GL_FALSE; texObj->_MipmapComplete = GL_FALSE; - if (invalidate_state) - ctx->NewState |= _NEW_TEXTURE; + ctx->NewState |= _NEW_TEXTURE; } diff --git a/mesalib/src/mesa/main/texobj.h b/mesalib/src/mesa/main/texobj.h index 0df088ce4..55091a642 100644 --- a/mesalib/src/mesa/main/texobj.h +++ b/mesalib/src/mesa/main/texobj.h @@ -126,8 +126,7 @@ extern GLboolean _mesa_cube_complete(const struct gl_texture_object *texObj); extern void -_mesa_dirty_texobj(struct gl_context *ctx, struct gl_texture_object *texObj, - GLboolean invalidate_state); +_mesa_dirty_texobj(struct gl_context *ctx, struct gl_texture_object *texObj); extern struct gl_texture_object * _mesa_get_fallback_texture(struct gl_context *ctx, gl_texture_index tex); diff --git a/mesalib/src/mesa/main/texparam.c b/mesalib/src/mesa/main/texparam.c index 757ae80ec..31723c377 100644 --- a/mesalib/src/mesa/main/texparam.c +++ b/mesalib/src/mesa/main/texparam.c @@ -256,7 +256,7 @@ static inline void incomplete(struct gl_context *ctx, struct gl_texture_object *texObj) { FLUSH_VERTICES(ctx, _NEW_TEXTURE); - _mesa_dirty_texobj(ctx, texObj, GL_TRUE); + _mesa_dirty_texobj(ctx, texObj); } |