* nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
* and Linux systems.
*
* Copyright (C) 2004 NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses>.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "NvCtrlAttributes.h"
#include "query-assign.h"
#include "msg.h"
#include "glxinfo.h"
#include <GL/glx.h>
#include <EGL/egl.h>
* print_extension_list() - Formats OpenGL/GLX extension strings
* to contain commas and returns a pointer to the formatted string.
* The user is responsible for freeing this buffer.
*
* If there is an error or there is not enough memory to create
* the buffer, NULL is returned.
*
*/
static char *
format_extension_list(const char *ext)
{
int i;
char * extTmp = NULL;
const char *extCountTmp;
if ( !ext || !ext[0] )
return NULL;
i = 0;
extCountTmp = ext;
while ( *extCountTmp != '\0' ) {
if ( *extCountTmp == ' ' ) {
i++;
}
extCountTmp++;
}
* Allocate buffer that will hold the extension string with
* commas in it
*/
extTmp = nvalloc( (strlen(ext) +i +1) *sizeof(char) );
i = 0;
while ( *ext != '\0' && *ext != '\n' ) {
if ( *ext == ' ' ) {
extTmp[i++] = ',';
}
extTmp[i++] = *ext;
ext++;
}
extTmp[i] = '\0';
while ( extTmp[ strlen(extTmp)-1 ] == ' ' ||
extTmp[ strlen(extTmp)-1 ] == ',' ) {
extTmp[ strlen(extTmp)-1 ] = '\0';
}
return extTmp;
}
* print_fbconfig_attribs() & helper functions -
* Prints a table of fbconfig attributes
*
* NOTE: Only support FBconfig for GLX v1.3+
*
*/
#ifdef GLX_VERSION_1_3
const char *
render_type_abbrev(int rend_type)
{
switch (rend_type) {
case GLX_RGBA_BIT:
return "rgb";
case GLX_COLOR_INDEX_BIT:
return "ci";
case (GLX_RGBA_BIT | GLX_COLOR_INDEX_BIT):
return "any";
default:
return ".";
}
}
const char *
transparent_type_abbrev(int trans_type)
{
switch (trans_type) {
case GLX_NONE:
return ".";
case GLX_TRANSPARENT_RGB:
return "rg";
case GLX_TRANSPARENT_INDEX:
return "ci";
default:
return ".";
}
}
const char *
x_visual_type_abbrev(int x_visual_type)
{
switch (x_visual_type) {
case GLX_TRUE_COLOR:
return "tc";
case GLX_DIRECT_COLOR:
return "dc";
case GLX_PSEUDO_COLOR:
return "pc";
case GLX_STATIC_COLOR:
return "sc";
case GLX_GRAY_SCALE:
return "gs";
case GLX_STATIC_GRAY:
return "sg";
default:
return ".";
}
}
const char *
caveat_abbrev(int caveat)
{
if (caveat == GLX_NONE_EXT || caveat == 0)
return(".");
else if (caveat == GLX_SLOW_VISUAL_EXT)
return("slo");
else if (caveat == GLX_NON_CONFORMANT_VISUAL_EXT)
return("NoC");
else
return(".");
}
static void
print_fbconfig_attribs(const GLXFBConfigAttr *fbca)
{
int i;
if ( fbca == NULL ) {
return;
}
printf("--fc- --vi- vt buf lv rgb d s colorbuffer ax dp st "
"accumbuffer ---ms---- cav -----pbuffer----- ---transparent----\n");
printf(" id id siz l ci b t r g b a bf th en "
" r g b a mvs mcs b eat widt hght max-pxs typ r g b a i\n");
printf("---------------------------------------------------"
"--------------------------------------------------------------\n");
i = 0;
while ( fbca[i].fbconfig_id != 0 ) {
printf("0x%03x ", fbca[i].fbconfig_id);
if ( fbca[i].visual_id ) {
printf("0x%03x ", fbca[i].visual_id);
} else {
printf(" . ");
}
printf("%2.2s %3d %2d %3.3s %1c %1c ",
x_visual_type_abbrev(fbca[i].x_visual_type),
fbca[i].buffer_size,
fbca[i].level,
render_type_abbrev(fbca[i].render_type),
fbca[i].doublebuffer ? 'y' : '.',
fbca[i].stereo ? 'y' : '.'
);
printf("%2d %2d %2d %2d %2d %2d %2d ",
fbca[i].red_size,
fbca[i].green_size,
fbca[i].blue_size,
fbca[i].alpha_size,
fbca[i].aux_buffers,
fbca[i].depth_size,
fbca[i].stencil_size
);
printf("%2d %2d %2d %2d ",
fbca[i].accum_red_size,
fbca[i].accum_green_size,
fbca[i].accum_blue_size,
fbca[i].accum_alpha_size
);
if ( fbca[i].multi_sample_valid == 1 ) {
printf("%3d ",
fbca[i].multi_samples
);
if ( fbca[i].multi_sample_coverage_valid == 1 ) {
printf("%3d ",
fbca[i].multi_samples_color
);
} else {
printf("%3d ",
fbca[i].multi_samples
);
}
printf("%1d ",
fbca[i].multi_sample_buffers
);
} else {
printf(" . . . ");
}
printf("%3.3s %4x %4x %7x %3.3s %2d %2d %2d %2d %2d\n",
caveat_abbrev(fbca[i].config_caveat),
fbca[i].pbuffer_width,
fbca[i].pbuffer_height,
fbca[i].pbuffer_max,
transparent_type_abbrev(fbca[i].transparent_type),
fbca[i].transparent_red_value,
fbca[i].transparent_green_value,
fbca[i].transparent_blue_value,
fbca[i].transparent_alpha_value,
fbca[i].transparent_index_value
);
i++;
}
}
#endif
* print_glxinfo() - prints information about glx
*
*/
#define TAB " "
#define SAFE_FREE(m) \
if ( (m) != NULL ) { \
free( m ); \
m = NULL; \
}
#define NULL_TO_EMPTY(s) \
((s)!=NULL)?(s):""
void print_glxinfo(const char *display_name, CtrlSystemList *systems)
{
CtrlSystem *system;
CtrlTargetNode *node;
ReturnStatus status = NvCtrlSuccess;
char *direct_rendering = NULL;
char *glx_extensions = NULL;
char *server_vendor = NULL;
char *server_version = NULL;
char *server_extensions = NULL;
char *client_vendor = NULL;
char *client_version = NULL;
char *client_extensions = NULL;
char *opengl_vendor = NULL;
char *opengl_renderer = NULL;
char *opengl_version = NULL;
char *opengl_extensions = NULL;
GLXFBConfigAttr *fbconfig_attribs = NULL;
char *formatted_ext_str = NULL;
system = NvCtrlConnectToSystem(display_name, systems);
if (system == NULL) {
return;
}
for (node = system->targets[X_SCREEN_TARGET]; node; node = node->next) {
CtrlTarget *t = node->t;
if ( !t->h ) continue;
nv_msg(NULL, "GLX Information for %s:", t->name);
status = NvCtrlGetStringAttribute(t,
NV_CTRL_STRING_GLX_DIRECT_RENDERING,
&direct_rendering);
if ( status != NvCtrlSuccess &&
status != NvCtrlNoAttribute ) { goto finish; }
status = NvCtrlGetStringAttribute(t,
NV_CTRL_STRING_GLX_GLX_EXTENSIONS,
&glx_extensions);
if ( status != NvCtrlSuccess &&
status != NvCtrlNoAttribute ) { goto finish; }
if ( glx_extensions != NULL ) {
formatted_ext_str = format_extension_list(glx_extensions);
if ( formatted_ext_str != NULL ) {
free(glx_extensions);
glx_extensions = formatted_ext_str;
}
}
status = NvCtrlGetStringAttribute(t,
NV_CTRL_STRING_GLX_SERVER_VENDOR,
&server_vendor);
if ( status != NvCtrlSuccess &&
status != NvCtrlNoAttribute ) { goto finish; }
status = NvCtrlGetStringAttribute(t,
NV_CTRL_STRING_GLX_SERVER_VERSION,
&server_version);
if ( status != NvCtrlSuccess &&
status != NvCtrlNoAttribute ) { goto finish; }
status = NvCtrlGetStringAttribute(t,
NV_CTRL_STRING_GLX_SERVER_EXTENSIONS,
&server_extensions);
if ( status != NvCtrlSuccess &&
status != NvCtrlNoAttribute ) { goto finish; }
if ( server_extensions != NULL ) {
formatted_ext_str = format_extension_list(server_extensions);
if ( formatted_ext_str != NULL ) {
free(server_extensions);
server_extensions = formatted_ext_str;
}
}
status = NvCtrlGetStringAttribute(t,
NV_CTRL_STRING_GLX_CLIENT_VENDOR,
&client_vendor);
if ( status != NvCtrlSuccess &&
status != NvCtrlNoAttribute ) { goto finish; }
status = NvCtrlGetStringAttribute(t,
NV_CTRL_STRING_GLX_CLIENT_VERSION,
&client_version);
if ( status != NvCtrlSuccess &&
status != NvCtrlNoAttribute ) { goto finish; }
status = NvCtrlGetStringAttribute(t,
NV_CTRL_STRING_GLX_CLIENT_EXTENSIONS,
&client_extensions);
if ( status != NvCtrlSuccess &&
status != NvCtrlNoAttribute ) { goto finish; }
if ( client_extensions != NULL ) {
formatted_ext_str = format_extension_list(client_extensions);
if ( formatted_ext_str != NULL ) {
free(client_extensions);
client_extensions = formatted_ext_str;
}
}
status = NvCtrlGetStringAttribute(t,
NV_CTRL_STRING_GLX_OPENGL_VENDOR,
&opengl_vendor);
if ( status != NvCtrlSuccess &&
status != NvCtrlNoAttribute ) { goto finish; }
status = NvCtrlGetStringAttribute(t,
NV_CTRL_STRING_GLX_OPENGL_RENDERER,
&opengl_renderer);
if ( status != NvCtrlSuccess &&
status != NvCtrlNoAttribute ) { goto finish; }
status = NvCtrlGetStringAttribute(t,
NV_CTRL_STRING_GLX_OPENGL_VERSION,
&opengl_version);
if ( status != NvCtrlSuccess &&
status != NvCtrlNoAttribute ) { goto finish; }
status = NvCtrlGetStringAttribute(t,
NV_CTRL_STRING_GLX_OPENGL_EXTENSIONS,
&opengl_extensions);
if ( status != NvCtrlSuccess &&
status != NvCtrlNoAttribute ) { goto finish; }
if ( opengl_extensions != NULL ) {
formatted_ext_str = format_extension_list(opengl_extensions);
if ( formatted_ext_str != NULL ) {
free(opengl_extensions);
opengl_extensions = formatted_ext_str;
}
}
status = NvCtrlGetVoidAttribute(t,
NV_CTRL_ATTR_GLX_FBCONFIG_ATTRIBS,
(void *)(&fbconfig_attribs));
if ( status != NvCtrlSuccess &&
status != NvCtrlNoAttribute ) { goto finish; }
nv_msg(TAB, "direct rendering: %s", NULL_TO_EMPTY(direct_rendering));
nv_msg(TAB, "GLX extensions:");
nv_msg(" ", "%s", NULL_TO_EMPTY(glx_extensions));
nv_msg(" ", "\n");
nv_msg(TAB, "server glx vendor string: %s",
NULL_TO_EMPTY(server_vendor));
nv_msg(TAB, "server glx version string: %s",
NULL_TO_EMPTY(server_version));
nv_msg(TAB, "server glx extensions:");
nv_msg(" ", "%s", NULL_TO_EMPTY(server_extensions));
nv_msg(" ", "\n");
nv_msg(TAB, "client glx vendor string: %s",
NULL_TO_EMPTY(client_vendor));
nv_msg(TAB, "client glx version string: %s",
NULL_TO_EMPTY(client_version));
nv_msg(TAB, "client glx extensions:");
nv_msg(" ", "%s", NULL_TO_EMPTY(client_extensions));
nv_msg(" ", "\n");
nv_msg(TAB, "OpenGL vendor string: %s",
NULL_TO_EMPTY(opengl_vendor));
nv_msg(TAB, "OpenGL renderer string: %s",
NULL_TO_EMPTY(opengl_renderer));
nv_msg(TAB, "OpenGL version string: %s",
NULL_TO_EMPTY(opengl_version));
nv_msg(TAB, "OpenGL extensions:");
nv_msg(" ", "%s", NULL_TO_EMPTY(opengl_extensions));
#ifdef GLX_VERSION_1_3
if ( fbconfig_attribs != NULL ) {
nv_msg(" ", "\n");
print_fbconfig_attribs(fbconfig_attribs);
}
#endif
fflush(stdout);
SAFE_FREE(server_vendor);
SAFE_FREE(server_version);
SAFE_FREE(server_extensions);
SAFE_FREE(client_vendor);
SAFE_FREE(client_version);
SAFE_FREE(client_extensions);
SAFE_FREE(direct_rendering);
SAFE_FREE(glx_extensions);
SAFE_FREE(opengl_vendor);
SAFE_FREE(opengl_renderer);
SAFE_FREE(opengl_version);
SAFE_FREE(opengl_extensions);
SAFE_FREE(fbconfig_attribs);
}
finish:
if ( status == NvCtrlError ) {
nv_error_msg("Error fetching GLX Information: %s",
NvCtrlAttributesStrError(status) );
}
SAFE_FREE(server_vendor);
SAFE_FREE(server_version);
SAFE_FREE(server_extensions);
SAFE_FREE(client_vendor);
SAFE_FREE(client_version);
SAFE_FREE(client_extensions);
SAFE_FREE(direct_rendering);
SAFE_FREE(glx_extensions);
SAFE_FREE(opengl_vendor);
SAFE_FREE(opengl_renderer);
SAFE_FREE(opengl_version);
SAFE_FREE(opengl_extensions);
SAFE_FREE(fbconfig_attribs);
NvCtrlFreeAllSystems(systems);
}
* EGL information
*
*/
const char *egl_color_buffer_type_abbrev(int type)
{
switch (type) {
case EGL_RGB_BUFFER:
return "rgb";
case EGL_LUMINANCE_BUFFER:
return "lum";
default:
return ".";
}
}
const char *egl_config_caveat_abbrev(int type)
{
switch (type) {
case EGL_SLOW_CONFIG:
return "slo";
case EGL_NON_CONFORMANT_CONFIG:
return "NoC";
case EGL_NONE:
default:
return ".";
}
}
const char *egl_transparent_type_abbrev(int type)
{
switch (type) {
case EGL_TRANSPARENT_RGB:
return "rgb";
case EGL_NONE:
default:
return ".";
}
}
static void print_egl_config_attribs(const EGLConfigAttr *fbca)
{
int i;
if (fbca == NULL) {
return;
}
printf("--fc- --vi- --vt-- buf lv rgb colorbuffer am lm dp st "
"-bind cfrm sb sm cav -----pbuffer----- swapin nv rn su "
"-transparent--\n");
printf(" id id siz l lum r g b a sz sz th en "
" - a eat widt hght max-pxs mx mn rd ty ty "
"typ r g b \n");
printf("------------------------------------------------------"
"-----------------------------------------------------------"
"--------------\n");
for (i = 0; fbca[i].config_id != 0; i++) {
printf("0x%03x ", fbca[i].config_id);
if (fbca[i].native_visual_id) {
printf("0x%03x ", fbca[i].native_visual_id);
} else {
printf(" . ");
}
printf("0x%X %3d %2d %3s ",
fbca[i].native_visual_type,
fbca[i].buffer_size,
fbca[i].level,
egl_color_buffer_type_abbrev(fbca[i].color_buffer_type));
printf("%2d %2d %2d %2d %2d %2d %2d %2d ",
fbca[i].red_size,
fbca[i].green_size,
fbca[i].blue_size,
fbca[i].alpha_size,
fbca[i].alpha_mask_size,
fbca[i].luminance_size,
fbca[i].depth_size,
fbca[i].stencil_size);
printf("%2c %2c ",
fbca[i].bind_to_texture_rgb ? 'y' : '.',
fbca[i].bind_to_texture_rgba ? 'y' : '.');
printf("0x%02X %2d %2d ",
fbca[i].conformant,
fbca[i].sample_buffers,
fbca[i].samples);
printf("%3.3s %4x %4x %7x %2d %2d ",
egl_config_caveat_abbrev(fbca[i].config_caveat),
fbca[i].max_pbuffer_width,
fbca[i].max_pbuffer_height,
fbca[i].max_pbuffer_pixels,
fbca[i].max_swap_interval,
fbca[i].min_swap_interval);
printf("%2c %4x %4x ",
fbca[i].native_renderable ? 'y' : '.',
fbca[i].renderable_type,
fbca[i].surface_type);
printf("%3s %2d %2d %2d\n",
egl_transparent_type_abbrev(fbca[i].transparent_type),
fbca[i].transparent_red_value,
fbca[i].transparent_green_value,
fbca[i].transparent_blue_value);
}
}
* print_eglinfo() - prints information about egl
*
*/
void print_eglinfo(const char *display_name, CtrlSystemList *systems)
{
CtrlSystem *system;
CtrlTargetNode *node;
CtrlTargetType target;
ReturnStatus status = NvCtrlSuccess;
char *egl_vendor = NULL;
char *egl_version = NULL;
char *egl_extensions = NULL;
char *formatted_ext_str = NULL;
EGLConfigAttr *egl_config_attribs = NULL;
system = NvCtrlConnectToSystem(display_name, systems);
if (system == NULL) {
return;
}
if (system->has_nv_control) {
target = X_SCREEN_TARGET;
} else {
target = GPU_TARGET;
}
for (node = system->targets[target]; node; node = node->next) {
CtrlTarget *t = node->t;
if (!t->h) continue;
nv_msg(NULL, "EGL Information for %s:", t->name);
status = NvCtrlGetStringAttribute(t,
NV_CTRL_STRING_EGL_VENDOR,
&egl_vendor);
if (status != NvCtrlSuccess && status != NvCtrlNoAttribute) {
goto finish;
}
status = NvCtrlGetStringAttribute(t,
NV_CTRL_STRING_EGL_VERSION,
&egl_version);
if (status != NvCtrlSuccess && status != NvCtrlNoAttribute) {
goto finish;
}
status = NvCtrlGetStringAttribute(t,
NV_CTRL_STRING_EGL_EXTENSIONS,
&egl_extensions);
if (status != NvCtrlSuccess && status != NvCtrlNoAttribute) {
goto finish;
}
if (egl_extensions != NULL) {
formatted_ext_str = format_extension_list(egl_extensions);
if (formatted_ext_str != NULL) {
free(egl_extensions);
egl_extensions = formatted_ext_str;
}
}
status = NvCtrlGetVoidAttribute(t,
NV_CTRL_ATTR_EGL_CONFIG_ATTRIBS,
(void *)(&egl_config_attribs));
if (status != NvCtrlSuccess && status != NvCtrlNoAttribute) {
goto finish;
}
nv_msg(TAB, "EGL vendor string: %s", NULL_TO_EMPTY(egl_vendor));
nv_msg(TAB, "EGL version string: %s", NULL_TO_EMPTY(egl_version));
nv_msg(TAB, "EGL extensions:");
nv_msg(" ", "%s", NULL_TO_EMPTY(egl_extensions));
nv_msg(" ", "\n");
if (egl_config_attribs != NULL) {
nv_msg(" ", "\n");
print_egl_config_attribs(egl_config_attribs);
}
fflush(stdout);
SAFE_FREE(egl_vendor);
SAFE_FREE(egl_version);
SAFE_FREE(egl_extensions);
SAFE_FREE(egl_config_attribs);
if (target == GPU_TARGET) {
break;
}
}
finish:
if (status == NvCtrlError) {
nv_error_msg("Error fetching EGL Information: %s",
NvCtrlAttributesStrError(status) );
}
SAFE_FREE(egl_vendor);
SAFE_FREE(egl_version);
SAFE_FREE(egl_extensions);
SAFE_FREE(egl_config_attribs);
NvCtrlFreeAllSystems(systems);
}