diff options
Diffstat (limited to 'mesalib')
90 files changed, 3174 insertions, 270 deletions
diff --git a/mesalib/docs/GL3.txt b/mesalib/docs/GL3.txt index 640dec24c..d150b0874 100644 --- a/mesalib/docs/GL3.txt +++ b/mesalib/docs/GL3.txt @@ -87,7 +87,7 @@ GL_ARB_vertex_type_2_10_10_10_rev DONE (i965, r600) GL 4.0: GLSL 4.0 not started -GL_ARB_texture_query_lod not started +GL_ARB_texture_query_lod DONE (i965) GL_ARB_draw_buffers_blend DONE (i965, r600, softpipe) GL_ARB_draw_indirect not started GL_ARB_gpu_shader5 not started @@ -151,7 +151,7 @@ ARB_shader_storage_buffer_object not started ARB_stencil_texturing not started ARB_texture_buffer_range DONE (nv50, nvc0) ARB_texture_query_levels not started -ARB_texture_storage_multisample not started +ARB_texture_storage_multisample DONE (i965) ARB_texture_view not started ARB_vertex_attrib_binding not started diff --git a/mesalib/docs/application-issues.html b/mesalib/docs/application-issues.html new file mode 100644 index 000000000..6db086585 --- /dev/null +++ b/mesalib/docs/application-issues.html @@ -0,0 +1,83 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<html lang="en"> +<head> + <meta http-equiv="content-type" content="text/html; charset=utf-8"> + <title>Application Issues</title> + <link rel="stylesheet" type="text/css" href="mesa.css"> +</head> +<body> + +<div class="header"> + <h1>The Mesa 3D Graphics Library</h1> +</div> + +<iframe src="contents.html"></iframe> +<div class="content"> + +<h1>Application Issues</h1> + +<p> +This page documents known issues with some OpenGL applications. +</p> + + +<h2>Topogun</h2> + +<p> +<a href="http://www.topogun.com/">Topogun</a> for Linux (version 2, at least) +creates a GLX visual without requesting a depth buffer. +This causes bad rendering if the OpenGL driver happens to choose a visual +without a depth buffer. +</p> + +<p> +Mesa 9.1.2 and later (will) support a DRI configuration option to work around +this issue. +Using the <a href="http://dri.freedesktop.org/wiki/DriConf">driconf</a> tool, +set the "Create all visuals with a depth buffer" option before running Topogun. +Then, all GLX visuals will be created with a depth buffer. +</p> + + +<h2>Old OpenGL games</h2> + +<p> +Some old OpenGL games (approx. ten years or older) may crash during +start-up because of an extension string buffer-overflow problem. +</p> + +<p> +The problem is a modern OpenGL driver will return a very long string +for the glGetString(GL_EXTENSIONS) query and if the application +naively copies the string into a fixed-size buffer it can overflow the +buffer and crash the application. +</p> + +<p> +The work-around is to set the MESA_EXTENSION_MAX_YEAR environment variable +to the approximate release year of the game. +This will cause the glGetString(GL_EXTENSIONS) query to only report extensions +older than the given year. +</p> + +<p> +For example, if the game was released in 2001, do +<pre> +export MESA_EXTENSION_MAX_YEAR=2001 +</pre> +before running the game. +</p> + + + +<h2>Viewperf</h2> + +<p> +See the <a href="viewperf.html">Viewperf issues</a> page for a detailed list +of Viewperf issues. +</p> + + +</div> +</body> +</html> diff --git a/mesalib/docs/contents.html b/mesalib/docs/contents.html index 57522992c..50c0d5913 100644 --- a/mesalib/docs/contents.html +++ b/mesalib/docs/contents.html @@ -71,6 +71,7 @@ <li><a href="llvmpipe.html" target="_parent">Gallium llvmpipe driver</a> <li><a href="vmware-guest.html" target="_parent">VMware SVGA3D guest driver</a> <li><a href="postprocess.html" target="_parent">Gallium post-processing</a> +<li><a href="application-issues.html" target="_parent">Application Issues</a> <li><a href="viewperf.html" target="_parent">Viewperf Issues</a> </ul> diff --git a/mesalib/src/gallium/auxiliary/Makefile.sources b/mesalib/src/gallium/auxiliary/Makefile.sources index 898abe024..79def2177 100644 --- a/mesalib/src/gallium/auxiliary/Makefile.sources +++ b/mesalib/src/gallium/auxiliary/Makefile.sources @@ -37,6 +37,11 @@ C_SOURCES := \ draw/draw_vs.c \ draw/draw_vs_exec.c \ draw/draw_vs_variant.c \ + hud/font.c \ + hud/hud_context.c \ + hud/hud_cpu.c \ + hud/hud_fps.c \ + hud/hud_driver_query.c \ os/os_misc.c \ os/os_time.c \ pipebuffer/pb_buffer_fenced.c \ diff --git a/mesalib/src/gallium/auxiliary/hud/font.c b/mesalib/src/gallium/auxiliary/hud/font.c new file mode 100644 index 000000000..6747874ee --- /dev/null +++ b/mesalib/src/gallium/auxiliary/hud/font.c @@ -0,0 +1,446 @@ +/************************************************************************** + * + * Copyright 2013 Marek Olšák <maraeo@gmail.com> + * All Rights Reserved. + * + * 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, sub license, 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 NON-INFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS 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. + * + **************************************************************************/ + +/* This is the "8_BY_13" font extracted from freeglut. */ + +/* + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, <olszta@sourceforge.net> + * Creation date: Thu Dec 16 1999 + * + * 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 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 + * PAWEL W. OLSZTA 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. + */ + +#include "hud/font.h" + +#include "pipe/p_compiler.h" +#include "pipe/p_screen.h" +#include "pipe/p_state.h" +#include "pipe/p_context.h" +#include "util/u_inlines.h" + +typedef unsigned char GLubyte; /* 1-byte unsigned */ +typedef struct tagSFG_Font SFG_Font; + +struct tagSFG_Font +{ + char* Name; /* The source font name */ + int Quantity; /* Number of chars in font */ + int Height; /* Height of the characters */ + const GLubyte** Characters; /* The characters mapping */ + + float xorig, yorig; /* Relative origin of the character */ +}; + +static const GLubyte Fixed8x13_Character_000[] = { 8, 0, 0, 0,170, 0,130, 0,130, 0,130, 0,170, 0, 0}; +static const GLubyte Fixed8x13_Character_001[] = { 8, 0, 0, 0, 0, 16, 56,124,254,124, 56, 16, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_002[] = { 8, 0,170, 85,170, 85,170, 85,170, 85,170, 85,170, 85,170}; +static const GLubyte Fixed8x13_Character_003[] = { 8, 0, 0, 0, 4, 4, 4, 4,174,160,224,160,160, 0, 0}; +static const GLubyte Fixed8x13_Character_004[] = { 8, 0, 0, 0, 8, 8, 12, 8,142,128,192,128,224, 0, 0}; +static const GLubyte Fixed8x13_Character_005[] = { 8, 0, 0, 0, 10, 10, 12, 10,108,128,128,128, 96, 0, 0}; +static const GLubyte Fixed8x13_Character_006[] = { 8, 0, 0, 0, 8, 8, 12, 8,238,128,128,128,128, 0, 0}; +static const GLubyte Fixed8x13_Character_007[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 24, 36, 36, 24, 0, 0}; +static const GLubyte Fixed8x13_Character_008[] = { 8, 0, 0, 0, 0,124, 0, 16, 16,124, 16, 16, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_009[] = { 8, 0, 0, 0, 14, 8, 8, 8,168,160,160,160,192, 0, 0}; +static const GLubyte Fixed8x13_Character_010[] = { 8, 0, 0, 0, 4, 4, 4, 4, 46, 80, 80,136,136, 0, 0}; +static const GLubyte Fixed8x13_Character_011[] = { 8, 0, 0, 0, 0, 0, 0, 0,240, 16, 16, 16, 16, 16, 16}; +static const GLubyte Fixed8x13_Character_012[] = { 8, 0, 16, 16, 16, 16, 16, 16,240, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_013[] = { 8, 0, 16, 16, 16, 16, 16, 16, 31, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_014[] = { 8, 0, 0, 0, 0, 0, 0, 0, 31, 16, 16, 16, 16, 16, 16}; +static const GLubyte Fixed8x13_Character_015[] = { 8, 0, 16, 16, 16, 16, 16, 16,255, 16, 16, 16, 16, 16, 16}; +static const GLubyte Fixed8x13_Character_016[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255}; +static const GLubyte Fixed8x13_Character_017[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_018[] = { 8, 0, 0, 0, 0, 0, 0, 0,255, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_019[] = { 8, 0, 0, 0, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_020[] = { 8, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_021[] = { 8, 0, 16, 16, 16, 16, 16, 16, 31, 16, 16, 16, 16, 16, 16}; +static const GLubyte Fixed8x13_Character_022[] = { 8, 0, 16, 16, 16, 16, 16, 16,240, 16, 16, 16, 16, 16, 16}; +static const GLubyte Fixed8x13_Character_023[] = { 8, 0, 0, 0, 0, 0, 0, 0,255, 16, 16, 16, 16, 16, 16}; +static const GLubyte Fixed8x13_Character_024[] = { 8, 0, 16, 16, 16, 16, 16, 16,255, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_025[] = { 8, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}; +static const GLubyte Fixed8x13_Character_026[] = { 8, 0, 0, 0,254, 0, 14, 48,192, 48, 14, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_027[] = { 8, 0, 0, 0,254, 0,224, 24, 6, 24,224, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_028[] = { 8, 0, 0, 0, 68, 68, 68, 68, 68,254, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_029[] = { 8, 0, 0, 0, 32, 32,126, 16, 8,126, 4, 4, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_030[] = { 8, 0, 0, 0,220, 98, 32, 32, 32,112, 32, 34, 28, 0, 0}; +static const GLubyte Fixed8x13_Character_031[] = { 8, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_032[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_033[] = { 8, 0, 0, 0, 16, 0, 16, 16, 16, 16, 16, 16, 16, 0, 0}; +static const GLubyte Fixed8x13_Character_034[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 36, 36, 0, 0}; +static const GLubyte Fixed8x13_Character_035[] = { 8, 0, 0, 0, 0, 36, 36,126, 36,126, 36, 36, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_036[] = { 8, 0, 0, 0, 16,120, 20, 20, 56, 80, 80, 60, 16, 0, 0}; +static const GLubyte Fixed8x13_Character_037[] = { 8, 0, 0, 0, 68, 42, 36, 16, 8, 8, 36, 82, 34, 0, 0}; +static const GLubyte Fixed8x13_Character_038[] = { 8, 0, 0, 0, 58, 68, 74, 48, 72, 72, 48, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_039[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 48, 56, 0, 0}; +static const GLubyte Fixed8x13_Character_040[] = { 8, 0, 0, 0, 4, 8, 8, 16, 16, 16, 8, 8, 4, 0, 0}; +static const GLubyte Fixed8x13_Character_041[] = { 8, 0, 0, 0, 32, 16, 16, 8, 8, 8, 16, 16, 32, 0, 0}; +static const GLubyte Fixed8x13_Character_042[] = { 8, 0, 0, 0, 0, 0, 36, 24,126, 24, 36, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_043[] = { 8, 0, 0, 0, 0, 0, 16, 16,124, 16, 16, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_044[] = { 8, 0, 0, 64, 48, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_045[] = { 8, 0, 0, 0, 0, 0, 0, 0,126, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_046[] = { 8, 0, 0, 16, 56, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_047[] = { 8, 0, 0, 0,128,128, 64, 32, 16, 8, 4, 2, 2, 0, 0}; +static const GLubyte Fixed8x13_Character_048[] = { 8, 0, 0, 0, 24, 36, 66, 66, 66, 66, 66, 36, 24, 0, 0}; +static const GLubyte Fixed8x13_Character_049[] = { 8, 0, 0, 0,124, 16, 16, 16, 16, 16, 80, 48, 16, 0, 0}; +static const GLubyte Fixed8x13_Character_050[] = { 8, 0, 0, 0,126, 64, 32, 24, 4, 2, 66, 66, 60, 0, 0}; +static const GLubyte Fixed8x13_Character_051[] = { 8, 0, 0, 0, 60, 66, 2, 2, 28, 8, 4, 2,126, 0, 0}; +static const GLubyte Fixed8x13_Character_052[] = { 8, 0, 0, 0, 4, 4,126, 68, 68, 36, 20, 12, 4, 0, 0}; +static const GLubyte Fixed8x13_Character_053[] = { 8, 0, 0, 0, 60, 66, 2, 2, 98, 92, 64, 64,126, 0, 0}; +static const GLubyte Fixed8x13_Character_054[] = { 8, 0, 0, 0, 60, 66, 66, 98, 92, 64, 64, 32, 28, 0, 0}; +static const GLubyte Fixed8x13_Character_055[] = { 8, 0, 0, 0, 32, 32, 16, 16, 8, 8, 4, 2,126, 0, 0}; +static const GLubyte Fixed8x13_Character_056[] = { 8, 0, 0, 0, 60, 66, 66, 66, 60, 66, 66, 66, 60, 0, 0}; +static const GLubyte Fixed8x13_Character_057[] = { 8, 0, 0, 0, 56, 4, 2, 2, 58, 70, 66, 66, 60, 0, 0}; +static const GLubyte Fixed8x13_Character_058[] = { 8, 0, 0, 16, 56, 16, 0, 0, 16, 56, 16, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_059[] = { 8, 0, 0, 64, 48, 56, 0, 0, 16, 56, 16, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_060[] = { 8, 0, 0, 0, 2, 4, 8, 16, 32, 16, 8, 4, 2, 0, 0}; +static const GLubyte Fixed8x13_Character_061[] = { 8, 0, 0, 0, 0, 0,126, 0, 0,126, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_062[] = { 8, 0, 0, 0, 64, 32, 16, 8, 4, 8, 16, 32, 64, 0, 0}; +static const GLubyte Fixed8x13_Character_063[] = { 8, 0, 0, 0, 8, 0, 8, 8, 4, 2, 66, 66, 60, 0, 0}; +static const GLubyte Fixed8x13_Character_064[] = { 8, 0, 0, 0, 60, 64, 74, 86, 82, 78, 66, 66, 60, 0, 0}; +static const GLubyte Fixed8x13_Character_065[] = { 8, 0, 0, 0, 66, 66, 66,126, 66, 66, 66, 36, 24, 0, 0}; +static const GLubyte Fixed8x13_Character_066[] = { 8, 0, 0, 0,252, 66, 66, 66,124, 66, 66, 66,252, 0, 0}; +static const GLubyte Fixed8x13_Character_067[] = { 8, 0, 0, 0, 60, 66, 64, 64, 64, 64, 64, 66, 60, 0, 0}; +static const GLubyte Fixed8x13_Character_068[] = { 8, 0, 0, 0,252, 66, 66, 66, 66, 66, 66, 66,252, 0, 0}; +static const GLubyte Fixed8x13_Character_069[] = { 8, 0, 0, 0,126, 64, 64, 64,120, 64, 64, 64,126, 0, 0}; +static const GLubyte Fixed8x13_Character_070[] = { 8, 0, 0, 0, 64, 64, 64, 64,120, 64, 64, 64,126, 0, 0}; +static const GLubyte Fixed8x13_Character_071[] = { 8, 0, 0, 0, 58, 70, 66, 78, 64, 64, 64, 66, 60, 0, 0}; +static const GLubyte Fixed8x13_Character_072[] = { 8, 0, 0, 0, 66, 66, 66, 66,126, 66, 66, 66, 66, 0, 0}; +static const GLubyte Fixed8x13_Character_073[] = { 8, 0, 0, 0,124, 16, 16, 16, 16, 16, 16, 16,124, 0, 0}; +static const GLubyte Fixed8x13_Character_074[] = { 8, 0, 0, 0, 56, 68, 4, 4, 4, 4, 4, 4, 31, 0, 0}; +static const GLubyte Fixed8x13_Character_075[] = { 8, 0, 0, 0, 66, 68, 72, 80, 96, 80, 72, 68, 66, 0, 0}; +static const GLubyte Fixed8x13_Character_076[] = { 8, 0, 0, 0,126, 64, 64, 64, 64, 64, 64, 64, 64, 0, 0}; +static const GLubyte Fixed8x13_Character_077[] = { 8, 0, 0, 0,130,130,130,146,146,170,198,130,130, 0, 0}; +static const GLubyte Fixed8x13_Character_078[] = { 8, 0, 0, 0, 66, 66, 66, 70, 74, 82, 98, 66, 66, 0, 0}; +static const GLubyte Fixed8x13_Character_079[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 66, 60, 0, 0}; +static const GLubyte Fixed8x13_Character_080[] = { 8, 0, 0, 0, 64, 64, 64, 64,124, 66, 66, 66,124, 0, 0}; +static const GLubyte Fixed8x13_Character_081[] = { 8, 0, 0, 2, 60, 74, 82, 66, 66, 66, 66, 66, 60, 0, 0}; +static const GLubyte Fixed8x13_Character_082[] = { 8, 0, 0, 0, 66, 68, 72, 80,124, 66, 66, 66,124, 0, 0}; +static const GLubyte Fixed8x13_Character_083[] = { 8, 0, 0, 0, 60, 66, 2, 2, 60, 64, 64, 66, 60, 0, 0}; +static const GLubyte Fixed8x13_Character_084[] = { 8, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16,254, 0, 0}; +static const GLubyte Fixed8x13_Character_085[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 66, 66, 0, 0}; +static const GLubyte Fixed8x13_Character_086[] = { 8, 0, 0, 0, 16, 40, 40, 40, 68, 68, 68,130,130, 0, 0}; +static const GLubyte Fixed8x13_Character_087[] = { 8, 0, 0, 0, 68,170,146,146,146,130,130,130,130, 0, 0}; +static const GLubyte Fixed8x13_Character_088[] = { 8, 0, 0, 0,130,130, 68, 40, 16, 40, 68,130,130, 0, 0}; +static const GLubyte Fixed8x13_Character_089[] = { 8, 0, 0, 0, 16, 16, 16, 16, 16, 40, 68,130,130, 0, 0}; +static const GLubyte Fixed8x13_Character_090[] = { 8, 0, 0, 0,126, 64, 64, 32, 16, 8, 4, 2,126, 0, 0}; +static const GLubyte Fixed8x13_Character_091[] = { 8, 0, 0, 0, 60, 32, 32, 32, 32, 32, 32, 32, 60, 0, 0}; +static const GLubyte Fixed8x13_Character_092[] = { 8, 0, 0, 0, 2, 2, 4, 8, 16, 32, 64,128,128, 0, 0}; +static const GLubyte Fixed8x13_Character_093[] = { 8, 0, 0, 0,120, 8, 8, 8, 8, 8, 8, 8,120, 0, 0}; +static const GLubyte Fixed8x13_Character_094[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 40, 16, 0, 0}; +static const GLubyte Fixed8x13_Character_095[] = { 8, 0, 0,254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_096[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 24, 56, 0, 0}; +static const GLubyte Fixed8x13_Character_097[] = { 8, 0, 0, 0, 58, 70, 66, 62, 2, 60, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_098[] = { 8, 0, 0, 0, 92, 98, 66, 66, 98, 92, 64, 64, 64, 0, 0}; +static const GLubyte Fixed8x13_Character_099[] = { 8, 0, 0, 0, 60, 66, 64, 64, 66, 60, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_100[] = { 8, 0, 0, 0, 58, 70, 66, 66, 70, 58, 2, 2, 2, 0, 0}; +static const GLubyte Fixed8x13_Character_101[] = { 8, 0, 0, 0, 60, 66, 64,126, 66, 60, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_102[] = { 8, 0, 0, 0, 32, 32, 32, 32,124, 32, 32, 34, 28, 0, 0}; +static const GLubyte Fixed8x13_Character_103[] = { 8, 0, 60, 66, 60, 64, 56, 68, 68, 58, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_104[] = { 8, 0, 0, 0, 66, 66, 66, 66, 98, 92, 64, 64, 64, 0, 0}; +static const GLubyte Fixed8x13_Character_105[] = { 8, 0, 0, 0,124, 16, 16, 16, 16, 48, 0, 16, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_106[] = { 8, 0, 56, 68, 68, 4, 4, 4, 4, 12, 0, 4, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_107[] = { 8, 0, 0, 0, 66, 68, 72,112, 72, 68, 64, 64, 64, 0, 0}; +static const GLubyte Fixed8x13_Character_108[] = { 8, 0, 0, 0,124, 16, 16, 16, 16, 16, 16, 16, 48, 0, 0}; +static const GLubyte Fixed8x13_Character_109[] = { 8, 0, 0, 0,130,146,146,146,146,236, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_110[] = { 8, 0, 0, 0, 66, 66, 66, 66, 98, 92, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_111[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 60, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_112[] = { 8, 0, 64, 64, 64, 92, 98, 66, 98, 92, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_113[] = { 8, 0, 2, 2, 2, 58, 70, 66, 70, 58, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_114[] = { 8, 0, 0, 0, 32, 32, 32, 32, 34, 92, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_115[] = { 8, 0, 0, 0, 60, 66, 12, 48, 66, 60, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_116[] = { 8, 0, 0, 0, 28, 34, 32, 32, 32,124, 32, 32, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_117[] = { 8, 0, 0, 0, 58, 68, 68, 68, 68, 68, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_118[] = { 8, 0, 0, 0, 16, 40, 40, 68, 68, 68, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_119[] = { 8, 0, 0, 0, 68,170,146,146,130,130, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_120[] = { 8, 0, 0, 0, 66, 36, 24, 24, 36, 66, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_121[] = { 8, 0, 60, 66, 2, 58, 70, 66, 66, 66, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_122[] = { 8, 0, 0, 0,126, 32, 16, 8, 4,126, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_123[] = { 8, 0, 0, 0, 14, 16, 16, 8, 48, 8, 16, 16, 14, 0, 0}; +static const GLubyte Fixed8x13_Character_124[] = { 8, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0}; +static const GLubyte Fixed8x13_Character_125[] = { 8, 0, 0, 0,112, 8, 8, 16, 12, 16, 8, 8,112, 0, 0}; +static const GLubyte Fixed8x13_Character_126[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 84, 36, 0, 0}; +static const GLubyte Fixed8x13_Character_127[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_128[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_129[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_130[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_131[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_132[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_133[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_134[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_135[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_136[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_137[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_138[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_139[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_140[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_141[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_142[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_143[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_144[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_145[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_146[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_147[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_148[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_149[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_150[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_151[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_152[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_153[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_154[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_155[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_156[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_157[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_158[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_159[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_160[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_161[] = { 8, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 0, 16, 0, 0}; +static const GLubyte Fixed8x13_Character_162[] = { 8, 0, 0, 0, 0, 16, 56, 84, 80, 80, 84, 56, 16, 0, 0}; +static const GLubyte Fixed8x13_Character_163[] = { 8, 0, 0, 0,220, 98, 32, 32, 32,112, 32, 34, 28, 0, 0}; +static const GLubyte Fixed8x13_Character_164[] = { 8, 0, 0, 0, 0, 66, 60, 36, 36, 60, 66, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_165[] = { 8, 0, 0, 0, 16, 16,124, 16,124, 40, 68,130,130, 0, 0}; +static const GLubyte Fixed8x13_Character_166[] = { 8, 0, 0, 0, 16, 16, 16, 16, 0, 16, 16, 16, 16, 0, 0}; +static const GLubyte Fixed8x13_Character_167[] = { 8, 0, 0, 0, 24, 36, 4, 24, 36, 36, 24, 32, 36, 24, 0}; +static const GLubyte Fixed8x13_Character_168[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,108, 0, 0}; +static const GLubyte Fixed8x13_Character_169[] = { 8, 0, 0, 0, 0, 56, 68,146,170,162,170,146, 68, 56, 0}; +static const GLubyte Fixed8x13_Character_170[] = { 8, 0, 0, 0, 0, 0,124, 0, 60, 68, 60, 4, 56, 0, 0}; +static const GLubyte Fixed8x13_Character_171[] = { 8, 0, 0, 0, 0, 18, 36, 72,144, 72, 36, 18, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_172[] = { 8, 0, 0, 0, 0, 2, 2, 2,126, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_173[] = { 8, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_174[] = { 8, 0, 0, 0, 0, 56, 68,170,178,170,170,146, 68, 56, 0}; +static const GLubyte Fixed8x13_Character_175[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 0, 0}; +static const GLubyte Fixed8x13_Character_176[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 24, 36, 36, 24, 0, 0}; +static const GLubyte Fixed8x13_Character_177[] = { 8, 0, 0, 0, 0,124, 0, 16, 16,124, 16, 16, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_178[] = { 8, 0, 0, 0, 0, 0, 0, 0,120, 64, 48, 8, 72, 48, 0}; +static const GLubyte Fixed8x13_Character_179[] = { 8, 0, 0, 0, 0, 0, 0, 0, 48, 72, 8, 16, 72, 48, 0}; +static const GLubyte Fixed8x13_Character_180[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 8, 0}; +static const GLubyte Fixed8x13_Character_181[] = { 8, 0, 0, 64, 90,102, 66, 66, 66, 66, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_182[] = { 8, 0, 0, 0, 20, 20, 20, 20, 52,116,116,116, 62, 0, 0}; +static const GLubyte Fixed8x13_Character_183[] = { 8, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_184[] = { 8, 0, 24, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_185[] = { 8, 0, 0, 0, 0, 0, 0, 0,112, 32, 32, 32, 96, 32, 0}; +static const GLubyte Fixed8x13_Character_186[] = { 8, 0, 0, 0, 0, 0, 0,120, 0, 48, 72, 72, 48, 0, 0}; +static const GLubyte Fixed8x13_Character_187[] = { 8, 0, 0, 0, 0,144, 72, 36, 18, 36, 72,144, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_188[] = { 8, 0, 0, 0, 6, 26, 18, 10,230, 66, 64, 64,192, 64, 0}; +static const GLubyte Fixed8x13_Character_189[] = { 8, 0, 0, 0, 30, 16, 12, 2,242, 76, 64, 64,192, 64, 0}; +static const GLubyte Fixed8x13_Character_190[] = { 8, 0, 0, 0, 6, 26, 18, 10,102,146, 16, 32,144, 96, 0}; +static const GLubyte Fixed8x13_Character_191[] = { 8, 0, 0, 0, 60, 66, 66, 64, 32, 16, 16, 0, 16, 0, 0}; +static const GLubyte Fixed8x13_Character_192[] = { 8, 0, 0, 0, 66, 66,126, 66, 66, 36, 24, 0, 8, 16, 0}; +static const GLubyte Fixed8x13_Character_193[] = { 8, 0, 0, 0, 66, 66,126, 66, 66, 36, 24, 0, 16, 8, 0}; +static const GLubyte Fixed8x13_Character_194[] = { 8, 0, 0, 0, 66, 66,126, 66, 66, 36, 24, 0, 36, 24, 0}; +static const GLubyte Fixed8x13_Character_195[] = { 8, 0, 0, 0, 66, 66,126, 66, 66, 36, 24, 0, 76, 50, 0}; +static const GLubyte Fixed8x13_Character_196[] = { 8, 0, 0, 0, 66, 66,126, 66, 66, 36, 24, 0, 36, 36, 0}; +static const GLubyte Fixed8x13_Character_197[] = { 8, 0, 0, 0, 66, 66,126, 66, 66, 36, 24, 24, 36, 24, 0}; +static const GLubyte Fixed8x13_Character_198[] = { 8, 0, 0, 0,158,144,144,240,156,144,144,144,110, 0, 0}; +static const GLubyte Fixed8x13_Character_199[] = { 8, 0, 16, 8, 60, 66, 64, 64, 64, 64, 64, 66, 60, 0, 0}; +static const GLubyte Fixed8x13_Character_200[] = { 8, 0, 0, 0,126, 64, 64,120, 64, 64,126, 0, 8, 16, 0}; +static const GLubyte Fixed8x13_Character_201[] = { 8, 0, 0, 0,126, 64, 64,120, 64, 64,126, 0, 16, 8, 0}; +static const GLubyte Fixed8x13_Character_202[] = { 8, 0, 0, 0,126, 64, 64,120, 64, 64,126, 0, 36, 24, 0}; +static const GLubyte Fixed8x13_Character_203[] = { 8, 0, 0, 0,126, 64, 64,120, 64, 64,126, 0, 36, 36, 0}; +static const GLubyte Fixed8x13_Character_204[] = { 8, 0, 0, 0,124, 16, 16, 16, 16, 16,124, 0, 16, 32, 0}; +static const GLubyte Fixed8x13_Character_205[] = { 8, 0, 0, 0,124, 16, 16, 16, 16, 16,124, 0, 16, 8, 0}; +static const GLubyte Fixed8x13_Character_206[] = { 8, 0, 0, 0,124, 16, 16, 16, 16, 16,124, 0, 36, 24, 0}; +static const GLubyte Fixed8x13_Character_207[] = { 8, 0, 0, 0,124, 16, 16, 16, 16, 16,124, 0, 40, 40, 0}; +static const GLubyte Fixed8x13_Character_208[] = { 8, 0, 0, 0,120, 68, 66, 66,226, 66, 66, 68,120, 0, 0}; +static const GLubyte Fixed8x13_Character_209[] = { 8, 0, 0, 0,130,134,138,146,162,194,130, 0,152,100, 0}; +static const GLubyte Fixed8x13_Character_210[] = { 8, 0, 0, 0,124,130,130,130,130,130,124, 0, 16, 32, 0}; +static const GLubyte Fixed8x13_Character_211[] = { 8, 0, 0, 0,124,130,130,130,130,130,124, 0, 16, 8, 0}; +static const GLubyte Fixed8x13_Character_212[] = { 8, 0, 0, 0,124,130,130,130,130,130,124, 0, 36, 24, 0}; +static const GLubyte Fixed8x13_Character_213[] = { 8, 0, 0, 0,124,130,130,130,130,130,124, 0,152,100, 0}; +static const GLubyte Fixed8x13_Character_214[] = { 8, 0, 0, 0,124,130,130,130,130,130,124, 0, 40, 40, 0}; +static const GLubyte Fixed8x13_Character_215[] = { 8, 0, 0, 0, 0, 66, 36, 24, 24, 36, 66, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_216[] = { 8, 0, 0, 64, 60, 98, 82, 82, 82, 74, 74, 70, 60, 2, 0}; +static const GLubyte Fixed8x13_Character_217[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 0, 8, 16, 0}; +static const GLubyte Fixed8x13_Character_218[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 0, 16, 8, 0}; +static const GLubyte Fixed8x13_Character_219[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 0, 36, 24, 0}; +static const GLubyte Fixed8x13_Character_220[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 0, 36, 36, 0}; +static const GLubyte Fixed8x13_Character_221[] = { 8, 0, 0, 0, 16, 16, 16, 16, 40, 68, 68, 0, 16, 8, 0}; +static const GLubyte Fixed8x13_Character_222[] = { 8, 0, 0, 0, 64, 64, 64,124, 66, 66, 66,124, 64, 0, 0}; +static const GLubyte Fixed8x13_Character_223[] = { 8, 0, 0, 0, 92, 66, 66, 76, 80, 72, 68, 68, 56, 0, 0}; +static const GLubyte Fixed8x13_Character_224[] = { 8, 0, 0, 0, 58, 70, 66, 62, 2, 60, 0, 0, 8, 16, 0}; +static const GLubyte Fixed8x13_Character_225[] = { 8, 0, 0, 0, 58, 70, 66, 62, 2, 60, 0, 0, 8, 4, 0}; +static const GLubyte Fixed8x13_Character_226[] = { 8, 0, 0, 0, 58, 70, 66, 62, 2, 60, 0, 0, 36, 24, 0}; +static const GLubyte Fixed8x13_Character_227[] = { 8, 0, 0, 0, 58, 70, 66, 62, 2, 60, 0, 0, 76, 50, 0}; +static const GLubyte Fixed8x13_Character_228[] = { 8, 0, 0, 0, 58, 70, 66, 62, 2, 60, 0, 0, 36, 36, 0}; +static const GLubyte Fixed8x13_Character_229[] = { 8, 0, 0, 0, 58, 70, 66, 62, 2, 60, 0, 24, 36, 24, 0}; +static const GLubyte Fixed8x13_Character_230[] = { 8, 0, 0, 0,108,146,144,124, 18,108, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_231[] = { 8, 0, 16, 8, 60, 66, 64, 64, 66, 60, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_232[] = { 8, 0, 0, 0, 60, 66, 64,126, 66, 60, 0, 0, 8, 16, 0}; +static const GLubyte Fixed8x13_Character_233[] = { 8, 0, 0, 0, 60, 66, 64,126, 66, 60, 0, 0, 16, 8, 0}; +static const GLubyte Fixed8x13_Character_234[] = { 8, 0, 0, 0, 60, 66, 64,126, 66, 60, 0, 0, 36, 24, 0}; +static const GLubyte Fixed8x13_Character_235[] = { 8, 0, 0, 0, 60, 66, 64,126, 66, 60, 0, 0, 36, 36, 0}; +static const GLubyte Fixed8x13_Character_236[] = { 8, 0, 0, 0,124, 16, 16, 16, 16, 48, 0, 0, 16, 32, 0}; +static const GLubyte Fixed8x13_Character_237[] = { 8, 0, 0, 0,124, 16, 16, 16, 16, 48, 0, 0, 32, 16, 0}; +static const GLubyte Fixed8x13_Character_238[] = { 8, 0, 0, 0,124, 16, 16, 16, 16, 48, 0, 0, 72, 48, 0}; +static const GLubyte Fixed8x13_Character_239[] = { 8, 0, 0, 0,124, 16, 16, 16, 16, 48, 0, 0, 40, 40, 0}; +static const GLubyte Fixed8x13_Character_240[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 60, 4, 40, 24, 36, 0}; +static const GLubyte Fixed8x13_Character_241[] = { 8, 0, 0, 0, 66, 66, 66, 66, 98, 92, 0, 0, 76, 50, 0}; +static const GLubyte Fixed8x13_Character_242[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 60, 0, 0, 16, 32, 0}; +static const GLubyte Fixed8x13_Character_243[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 60, 0, 0, 16, 8, 0}; +static const GLubyte Fixed8x13_Character_244[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 60, 0, 0, 36, 24, 0}; +static const GLubyte Fixed8x13_Character_245[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 60, 0, 0, 76, 50, 0}; +static const GLubyte Fixed8x13_Character_246[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 60, 0, 0, 36, 36, 0}; +static const GLubyte Fixed8x13_Character_247[] = { 8, 0, 0, 0, 0, 16, 16, 0,124, 0, 16, 16, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_248[] = { 8, 0, 0, 64, 60, 98, 82, 74, 70, 60, 2, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_249[] = { 8, 0, 0, 0, 58, 68, 68, 68, 68, 68, 0, 0, 16, 32, 0}; +static const GLubyte Fixed8x13_Character_250[] = { 8, 0, 0, 0, 58, 68, 68, 68, 68, 68, 0, 0, 16, 8, 0}; +static const GLubyte Fixed8x13_Character_251[] = { 8, 0, 0, 0, 58, 68, 68, 68, 68, 68, 0, 0, 36, 24, 0}; +static const GLubyte Fixed8x13_Character_252[] = { 8, 0, 0, 0, 58, 68, 68, 68, 68, 68, 0, 0, 40, 40, 0}; +static const GLubyte Fixed8x13_Character_253[] = { 8, 0, 60, 66, 2, 58, 70, 66, 66, 66, 0, 0, 16, 8, 0}; +static const GLubyte Fixed8x13_Character_254[] = { 8, 0, 64, 64, 92, 98, 66, 66, 98, 92, 64, 64, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_255[] = { 8, 0, 60, 66, 2, 58, 70, 66, 66, 66, 0, 0, 36, 36, 0}; + +/* The font characters mapping: */ +static const GLubyte* Fixed8x13_Character_Map[] = {Fixed8x13_Character_000,Fixed8x13_Character_001,Fixed8x13_Character_002,Fixed8x13_Character_003,Fixed8x13_Character_004,Fixed8x13_Character_005,Fixed8x13_Character_006,Fixed8x13_Character_007,Fixed8x13_Character_008,Fixed8x13_Character_009,Fixed8x13_Character_010,Fixed8x13_Character_011,Fixed8x13_Character_012,Fixed8x13_Character_013,Fixed8x13_Character_014,Fixed8x13_Character_015, + Fixed8x13_Character_016,Fixed8x13_Character_017,Fixed8x13_Character_018,Fixed8x13_Character_019,Fixed8x13_Character_020,Fixed8x13_Character_021,Fixed8x13_Character_022,Fixed8x13_Character_023,Fixed8x13_Character_024,Fixed8x13_Character_025,Fixed8x13_Character_026,Fixed8x13_Character_027,Fixed8x13_Character_028,Fixed8x13_Character_029,Fixed8x13_Character_030,Fixed8x13_Character_031, + Fixed8x13_Character_032,Fixed8x13_Character_033,Fixed8x13_Character_034,Fixed8x13_Character_035,Fixed8x13_Character_036,Fixed8x13_Character_037,Fixed8x13_Character_038,Fixed8x13_Character_039,Fixed8x13_Character_040,Fixed8x13_Character_041,Fixed8x13_Character_042,Fixed8x13_Character_043,Fixed8x13_Character_044,Fixed8x13_Character_045,Fixed8x13_Character_046,Fixed8x13_Character_047, + Fixed8x13_Character_048,Fixed8x13_Character_049,Fixed8x13_Character_050,Fixed8x13_Character_051,Fixed8x13_Character_052,Fixed8x13_Character_053,Fixed8x13_Character_054,Fixed8x13_Character_055,Fixed8x13_Character_056,Fixed8x13_Character_057,Fixed8x13_Character_058,Fixed8x13_Character_059,Fixed8x13_Character_060,Fixed8x13_Character_061,Fixed8x13_Character_062,Fixed8x13_Character_063, + Fixed8x13_Character_064,Fixed8x13_Character_065,Fixed8x13_Character_066,Fixed8x13_Character_067,Fixed8x13_Character_068,Fixed8x13_Character_069,Fixed8x13_Character_070,Fixed8x13_Character_071,Fixed8x13_Character_072,Fixed8x13_Character_073,Fixed8x13_Character_074,Fixed8x13_Character_075,Fixed8x13_Character_076,Fixed8x13_Character_077,Fixed8x13_Character_078,Fixed8x13_Character_079, + Fixed8x13_Character_080,Fixed8x13_Character_081,Fixed8x13_Character_082,Fixed8x13_Character_083,Fixed8x13_Character_084,Fixed8x13_Character_085,Fixed8x13_Character_086,Fixed8x13_Character_087,Fixed8x13_Character_088,Fixed8x13_Character_089,Fixed8x13_Character_090,Fixed8x13_Character_091,Fixed8x13_Character_092,Fixed8x13_Character_093,Fixed8x13_Character_094,Fixed8x13_Character_095, + Fixed8x13_Character_096,Fixed8x13_Character_097,Fixed8x13_Character_098,Fixed8x13_Character_099,Fixed8x13_Character_100,Fixed8x13_Character_101,Fixed8x13_Character_102,Fixed8x13_Character_103,Fixed8x13_Character_104,Fixed8x13_Character_105,Fixed8x13_Character_106,Fixed8x13_Character_107,Fixed8x13_Character_108,Fixed8x13_Character_109,Fixed8x13_Character_110,Fixed8x13_Character_111, + Fixed8x13_Character_112,Fixed8x13_Character_113,Fixed8x13_Character_114,Fixed8x13_Character_115,Fixed8x13_Character_116,Fixed8x13_Character_117,Fixed8x13_Character_118,Fixed8x13_Character_119,Fixed8x13_Character_120,Fixed8x13_Character_121,Fixed8x13_Character_122,Fixed8x13_Character_123,Fixed8x13_Character_124,Fixed8x13_Character_125,Fixed8x13_Character_126,Fixed8x13_Character_032, + Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032, + Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032, + Fixed8x13_Character_160,Fixed8x13_Character_161,Fixed8x13_Character_162,Fixed8x13_Character_163,Fixed8x13_Character_164,Fixed8x13_Character_165,Fixed8x13_Character_166,Fixed8x13_Character_167,Fixed8x13_Character_168,Fixed8x13_Character_169,Fixed8x13_Character_170,Fixed8x13_Character_171,Fixed8x13_Character_172,Fixed8x13_Character_173,Fixed8x13_Character_174,Fixed8x13_Character_175, + Fixed8x13_Character_176,Fixed8x13_Character_177,Fixed8x13_Character_178,Fixed8x13_Character_179,Fixed8x13_Character_180,Fixed8x13_Character_181,Fixed8x13_Character_182,Fixed8x13_Character_183,Fixed8x13_Character_184,Fixed8x13_Character_185,Fixed8x13_Character_186,Fixed8x13_Character_187,Fixed8x13_Character_188,Fixed8x13_Character_189,Fixed8x13_Character_190,Fixed8x13_Character_191, + Fixed8x13_Character_192,Fixed8x13_Character_193,Fixed8x13_Character_194,Fixed8x13_Character_195,Fixed8x13_Character_196,Fixed8x13_Character_197,Fixed8x13_Character_198,Fixed8x13_Character_199,Fixed8x13_Character_200,Fixed8x13_Character_201,Fixed8x13_Character_202,Fixed8x13_Character_203,Fixed8x13_Character_204,Fixed8x13_Character_205,Fixed8x13_Character_206,Fixed8x13_Character_207, + Fixed8x13_Character_208,Fixed8x13_Character_209,Fixed8x13_Character_210,Fixed8x13_Character_211,Fixed8x13_Character_212,Fixed8x13_Character_213,Fixed8x13_Character_214,Fixed8x13_Character_215,Fixed8x13_Character_216,Fixed8x13_Character_217,Fixed8x13_Character_218,Fixed8x13_Character_219,Fixed8x13_Character_220,Fixed8x13_Character_221,Fixed8x13_Character_222,Fixed8x13_Character_223, + Fixed8x13_Character_224,Fixed8x13_Character_225,Fixed8x13_Character_226,Fixed8x13_Character_227,Fixed8x13_Character_228,Fixed8x13_Character_229,Fixed8x13_Character_230,Fixed8x13_Character_231,Fixed8x13_Character_232,Fixed8x13_Character_233,Fixed8x13_Character_234,Fixed8x13_Character_235,Fixed8x13_Character_236,Fixed8x13_Character_237,Fixed8x13_Character_238,Fixed8x13_Character_239, + Fixed8x13_Character_240,Fixed8x13_Character_241,Fixed8x13_Character_242,Fixed8x13_Character_243,Fixed8x13_Character_244,Fixed8x13_Character_245,Fixed8x13_Character_246,Fixed8x13_Character_247,Fixed8x13_Character_248,Fixed8x13_Character_249,Fixed8x13_Character_250,Fixed8x13_Character_251,Fixed8x13_Character_252,Fixed8x13_Character_253,Fixed8x13_Character_254,Fixed8x13_Character_255,NULL}; + +/* The font structure: */ +static const SFG_Font fgFontFixed8x13 = { "-misc-fixed-medium-r-normal--13-120-75-75-C-80-iso8859-1", 256, 14, Fixed8x13_Character_Map, 0, 3 }; + + +static void +util_font_draw_character(void *dst_mem, unsigned dst_stride, unsigned character) +{ + unsigned char *dst = (unsigned char*)dst_mem; + const SFG_Font *font = &fgFontFixed8x13; + unsigned width = font->Characters[character][0]; + unsigned bitmap_stride = (width + 7) / 8; + unsigned j,i; + const GLubyte *bitmap = font->Characters[character]+1 + bitmap_stride * (font->Height - 1); + + for (j = 0; j < font->Height; j++) { + for (i = 0; i < width; i++) { + dst[i] = bitmap[i/8] & (128 >> (i%8)) ? 0xff : 0; + } + dst += dst_stride; + bitmap -= bitmap_stride; + } +} + +static boolean +util_font_create_fixed_8x13(struct pipe_context *pipe, + struct util_font *out_font) +{ + struct pipe_screen *screen = pipe->screen; + struct pipe_resource tex_templ, *tex; + struct pipe_transfer *transfer = NULL; + char *map; + enum pipe_format tex_format; + int i; + + if (screen->is_format_supported(screen, PIPE_FORMAT_I8_UNORM, + PIPE_TEXTURE_RECT, 0, + PIPE_BIND_SAMPLER_VIEW)) { + tex_format = PIPE_FORMAT_I8_UNORM; + } + else if (screen->is_format_supported(screen, PIPE_FORMAT_L8_UNORM, + PIPE_TEXTURE_RECT, 0, + PIPE_BIND_SAMPLER_VIEW)) { + tex_format = PIPE_FORMAT_L8_UNORM; + } + else { + return FALSE; + } + + memset(&tex_templ, 0, sizeof(tex_templ)); + tex_templ.target = PIPE_TEXTURE_RECT; + tex_templ.format = tex_format; + tex_templ.width0 = 128; + tex_templ.height0 = 256; + tex_templ.depth0 = 1; + tex_templ.array_size = 1; + tex_templ.usage = PIPE_USAGE_STATIC; + tex_templ.bind = PIPE_BIND_SAMPLER_VIEW; + + tex = screen->resource_create(screen, &tex_templ); + if (!tex) { + return FALSE; + } + + map = pipe_transfer_map(pipe, tex, 0, 0, PIPE_TRANSFER_WRITE, 0, 0, + tex->width0, tex->height0, &transfer); + if (!map) { + pipe_resource_reference(&tex, NULL); + return FALSE; + } + + for (i = 0; i < 256; i++) { + int x = (i % 16) * 8; + int y = (i / 16) * 14; + + util_font_draw_character(map + y * transfer->stride + x, + transfer->stride, i); + } + + pipe_transfer_unmap(pipe, transfer); + + pipe_resource_reference(&out_font->texture, NULL); + out_font->texture = tex; + out_font->glyph_width = 8; + out_font->glyph_height = 14; + return TRUE; +} + + +boolean +util_font_create(struct pipe_context *pipe, enum util_font_name name, + struct util_font *out_font) +{ + switch (name) { + case UTIL_FONT_FIXED_8X13: + return util_font_create_fixed_8x13(pipe, out_font); + } + return FALSE; +} diff --git a/mesalib/src/gallium/auxiliary/hud/font.h b/mesalib/src/gallium/auxiliary/hud/font.h new file mode 100644 index 000000000..cf1c87984 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/hud/font.h @@ -0,0 +1,59 @@ +/************************************************************************** + * + * Copyright 2013 Marek Olšák <maraeo@gmail.com> + * All Rights Reserved. + * + * 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, sub license, 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 NON-INFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS 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. + * + **************************************************************************/ + +#ifndef FONT_H +#define FONT_H + +#include "pipe/p_compiler.h" + +struct pipe_resource; +struct pipe_context; + +enum util_font_name { + UTIL_FONT_FIXED_8X13 +}; + +/* The font is stored in a RECT texture. There are 256 glyphs + * drawn in a 16x16 matrix. The texture coordinates of a glyph + * within the matrix should be calculated as follows: + * + * x1 = (glyph % 16) * glyph_width; + * y1 = (glyph / 16) * glyph_height; + * x2 = x1 + glyph_width; + * y2 = y1 + glyph_height; + */ +struct util_font { + struct pipe_resource *texture; + unsigned glyph_width; + unsigned glyph_height; +}; + +boolean +util_font_create(struct pipe_context *pipe, enum util_font_name name, + struct util_font *out_font); + +#endif diff --git a/mesalib/src/gallium/auxiliary/hud/hud_context.c b/mesalib/src/gallium/auxiliary/hud/hud_context.c new file mode 100644 index 000000000..983f05756 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/hud/hud_context.c @@ -0,0 +1,1078 @@ +/************************************************************************** + * + * Copyright 2013 Marek Olšák <maraeo@gmail.com> + * All Rights Reserved. + * + * 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, sub license, 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 NON-INFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS 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. + * + **************************************************************************/ + +/* This head-up display module can draw transparent graphs on top of what + * the app is rendering, visualizing various data like framerate, cpu load, + * performance counters, etc. It can be hook up into any state tracker. + * + * The HUD is controlled with the GALLIUM_HUD environment variable. + * Set GALLIUM_HUD=help for more info. + */ + +#include "hud/hud_context.h" +#include "hud/hud_private.h" +#include "hud/font.h" + +#include "cso_cache/cso_context.h" +#include "util/u_draw_quad.h" +#include "util/u_inlines.h" +#include "util/u_memory.h" +#include "util/u_math.h" +#include "util/u_simple_shaders.h" +#include "util/u_string.h" +#include "util/u_upload_mgr.h" +#include "tgsi/tgsi_text.h" +#include "tgsi/tgsi_dump.h" + + +struct hud_context { + struct pipe_context *pipe; + struct cso_context *cso; + struct u_upload_mgr *uploader; + + struct list_head pane_list; + + /* states */ + struct pipe_blend_state alpha_blend; + struct pipe_depth_stencil_alpha_state dsa; + void *fs_color, *fs_text; + struct pipe_rasterizer_state rasterizer; + void *vs; + struct pipe_vertex_element velems[2]; + + /* font */ + struct util_font font; + struct pipe_sampler_view *font_sampler_view; + struct pipe_sampler_state font_sampler_state; + + /* VS constant buffer */ + struct { + float color[4]; + float two_div_fb_width; + float two_div_fb_height; + float translate[2]; + float scale[2]; + float padding[2]; + } constants; + struct pipe_constant_buffer constbuf; + + unsigned fb_width, fb_height; + + /* vertices for text and background drawing are accumulated here and then + * drawn all at once */ + struct vertex_queue { + float *vertices; + struct pipe_vertex_buffer vbuf; + unsigned max_num_vertices; + unsigned num_vertices; + } text, bg, whitelines; + + struct { + boolean query_pipeline_statistics; + } cap; +}; + + +static void +hud_draw_colored_prims(struct hud_context *hud, unsigned prim, + float *buffer, unsigned num_vertices, + float r, float g, float b, float a, + int xoffset, int yoffset, float yscale) +{ + struct cso_context *cso = hud->cso; + struct pipe_vertex_buffer vbuffer = {0}; + + hud->constants.color[0] = r; + hud->constants.color[1] = g; + hud->constants.color[2] = b; + hud->constants.color[3] = a; + hud->constants.translate[0] = xoffset; + hud->constants.translate[1] = yoffset; + hud->constants.scale[0] = 1; + hud->constants.scale[1] = yscale; + cso_set_constant_buffer(cso, PIPE_SHADER_VERTEX, 0, &hud->constbuf); + + vbuffer.user_buffer = buffer; + vbuffer.stride = 2 * sizeof(float); + + cso_set_vertex_buffers(cso, cso_get_aux_vertex_buffer_slot(cso), + 1, &vbuffer); + cso_set_fragment_shader_handle(hud->cso, hud->fs_color); + cso_draw_arrays(cso, prim, 0, num_vertices); +} + +static void +hud_draw_colored_quad(struct hud_context *hud, unsigned prim, + unsigned x1, unsigned y1, unsigned x2, unsigned y2, + float r, float g, float b, float a) +{ + float buffer[] = { + x1, y1, + x1, y2, + x2, y2, + x2, y1, + }; + + hud_draw_colored_prims(hud, prim, buffer, 4, r, g, b, a, 0, 0, 1); +} + +static void +hud_draw_background_quad(struct hud_context *hud, + unsigned x1, unsigned y1, unsigned x2, unsigned y2) +{ + float *vertices = hud->bg.vertices + hud->bg.num_vertices*2; + unsigned num = 0; + + assert(hud->bg.num_vertices + 4 <= hud->bg.max_num_vertices); + + vertices[num++] = x1; + vertices[num++] = y1; + + vertices[num++] = x1; + vertices[num++] = y2; + + vertices[num++] = x2; + vertices[num++] = y2; + + vertices[num++] = x2; + vertices[num++] = y1; + + hud->bg.num_vertices += num/2; +} + +static void +hud_draw_string(struct hud_context *hud, unsigned x, unsigned y, + const char *str, ...) +{ + char buf[256]; + char *s = buf; + float *vertices = hud->text.vertices + hud->text.num_vertices*4; + unsigned num = 0; + + va_list ap; + va_start(ap, str); + util_vsnprintf(buf, sizeof(buf), str, ap); + va_end(ap); + + if (!*s) + return; + + hud_draw_background_quad(hud, + x, y, + x + strlen(buf)*hud->font.glyph_width, + y + hud->font.glyph_height); + + while (*s) { + unsigned x1 = x; + unsigned y1 = y; + unsigned x2 = x + hud->font.glyph_width; + unsigned y2 = y + hud->font.glyph_height; + unsigned tx1 = (*s % 16) * hud->font.glyph_width; + unsigned ty1 = (*s / 16) * hud->font.glyph_height; + unsigned tx2 = tx1 + hud->font.glyph_width; + unsigned ty2 = ty1 + hud->font.glyph_height; + + if (*s == ' ') { + x += hud->font.glyph_width; + s++; + continue; + } + + assert(hud->text.num_vertices + num/4 + 4 <= hud->text.max_num_vertices); + + vertices[num++] = x1; + vertices[num++] = y1; + vertices[num++] = tx1; + vertices[num++] = ty1; + + vertices[num++] = x1; + vertices[num++] = y2; + vertices[num++] = tx1; + vertices[num++] = ty2; + + vertices[num++] = x2; + vertices[num++] = y2; + vertices[num++] = tx2; + vertices[num++] = ty2; + + vertices[num++] = x2; + vertices[num++] = y1; + vertices[num++] = tx2; + vertices[num++] = ty1; + + x += hud->font.glyph_width; + s++; + } + + hud->text.num_vertices += num/4; +} + +static void +number_to_human_readable(uint64_t num, boolean is_in_bytes, char *out) +{ + static const char *byte_units[] = + {"", " KB", " MB", " GB", " TB", " PB", " EB"}; + static const char *metric_units[] = + {"", " k", " M", " G", " T", " P", " E"}; + const char **units = is_in_bytes ? byte_units : metric_units; + double divisor = is_in_bytes ? 1024 : 1000; + int unit = 0; + double d = num; + + while (d > divisor) { + d /= divisor; + unit++; + } + + if (d >= 100 || d == (int)d) + sprintf(out, "%.0f%s", d, units[unit]); + else if (d >= 10 || d*10 == (int)(d*10)) + sprintf(out, "%.1f%s", d, units[unit]); + else + sprintf(out, "%.2f%s", d, units[unit]); +} + +static void +hud_draw_graph_line_strip(struct hud_context *hud, const struct hud_graph *gr, + unsigned xoffset, unsigned yoffset, float yscale) +{ + if (gr->num_vertices <= 1) + return; + + assert(gr->index <= gr->num_vertices); + + hud_draw_colored_prims(hud, PIPE_PRIM_LINE_STRIP, + gr->vertices, gr->index, + gr->color[0], gr->color[1], gr->color[2], 1, + xoffset + (gr->pane->max_num_vertices - gr->index - 1) * 2 - 1, + yoffset, yscale); + + if (gr->num_vertices <= gr->index) + return; + + hud_draw_colored_prims(hud, PIPE_PRIM_LINE_STRIP, + gr->vertices + gr->index*2, + gr->num_vertices - gr->index, + gr->color[0], gr->color[1], gr->color[2], 1, + xoffset - gr->index*2 - 1, yoffset, yscale); +} + +static void +hud_pane_accumulate_vertices(struct hud_context *hud, + const struct hud_pane *pane) +{ + struct hud_graph *gr; + float *line_verts = hud->whitelines.vertices + hud->whitelines.num_vertices*2; + unsigned i, num = 0; + char str[32]; + + /* draw background */ + hud_draw_background_quad(hud, + pane->x1, pane->y1, + pane->x2, pane->y2); + + /* draw numbers on the right-hand side */ + for (i = 0; i < 6; i++) { + unsigned x = pane->x2 + 2; + unsigned y = pane->inner_y1 + pane->inner_height * (5 - i) / 5 - + hud->font.glyph_height / 2; + + number_to_human_readable(pane->max_value * i / 5, + pane->uses_byte_units, str); + hud_draw_string(hud, x, y, str); + } + + /* draw info below the pane */ + i = 0; + LIST_FOR_EACH_ENTRY(gr, &pane->graph_list, head) { + unsigned x = pane->x1 + 2; + unsigned y = pane->y2 + 2 + i*hud->font.glyph_height; + + number_to_human_readable(gr->current_value, + pane->uses_byte_units, str); + hud_draw_string(hud, x, y, " %s: %s", gr->name, str); + i++; + } + + /* draw border */ + assert(hud->whitelines.num_vertices + num/2 + 8 <= hud->whitelines.max_num_vertices); + line_verts[num++] = pane->x1; + line_verts[num++] = pane->y1; + line_verts[num++] = pane->x2; + line_verts[num++] = pane->y1; + + line_verts[num++] = pane->x2; + line_verts[num++] = pane->y1; + line_verts[num++] = pane->x2; + line_verts[num++] = pane->y2; + + line_verts[num++] = pane->x1; + line_verts[num++] = pane->y2; + line_verts[num++] = pane->x2; + line_verts[num++] = pane->y2; + + line_verts[num++] = pane->x1; + line_verts[num++] = pane->y1; + line_verts[num++] = pane->x1; + line_verts[num++] = pane->y2; + + /* draw horizontal lines inside the graph */ + for (i = 0; i <= 5; i++) { + float y = round((pane->max_value * i / 5.0) * pane->yscale + pane->inner_y2); + + assert(hud->whitelines.num_vertices + num/2 + 2 <= hud->whitelines.max_num_vertices); + line_verts[num++] = pane->x1; + line_verts[num++] = y; + line_verts[num++] = pane->x2; + line_verts[num++] = y; + } + + hud->whitelines.num_vertices += num/2; +} + +static void +hud_pane_draw_colored_objects(struct hud_context *hud, + const struct hud_pane *pane) +{ + struct hud_graph *gr; + unsigned i; + + /* draw colored quads below the pane */ + i = 0; + LIST_FOR_EACH_ENTRY(gr, &pane->graph_list, head) { + unsigned x = pane->x1 + 2; + unsigned y = pane->y2 + 2 + i*hud->font.glyph_height; + + hud_draw_colored_quad(hud, PIPE_PRIM_QUADS, x + 1, y + 1, x + 12, y + 13, + gr->color[0], gr->color[1], gr->color[2], 1); + i++; + } + + /* draw the line strips */ + LIST_FOR_EACH_ENTRY(gr, &pane->graph_list, head) { + hud_draw_graph_line_strip(hud, gr, pane->inner_x1, pane->inner_y2, pane->yscale); + } +} + +static void +hud_alloc_vertices(struct hud_context *hud, struct vertex_queue *v, + unsigned num_vertices, unsigned stride) +{ + v->num_vertices = 0; + v->max_num_vertices = num_vertices; + v->vbuf.stride = stride; + u_upload_alloc(hud->uploader, 0, v->vbuf.stride * v->max_num_vertices, + &v->vbuf.buffer_offset, &v->vbuf.buffer, + (void**)&v->vertices); +} + +/** + * Draw the HUD to the texture \p tex. + * The texture is usually the back buffer being displayed. + */ +void +hud_draw(struct hud_context *hud, struct pipe_resource *tex) +{ + struct cso_context *cso = hud->cso; + struct pipe_context *pipe = hud->pipe; + struct pipe_framebuffer_state fb; + struct pipe_surface surf_templ, *surf; + struct pipe_viewport_state viewport; + const struct pipe_sampler_state *sampler_states[] = + { &hud->font_sampler_state }; + struct hud_pane *pane; + struct hud_graph *gr; + + hud->fb_width = tex->width0; + hud->fb_height = tex->height0; + hud->constants.two_div_fb_width = 2.0 / hud->fb_width; + hud->constants.two_div_fb_height = 2.0 / hud->fb_height; + + cso_save_framebuffer(cso); + cso_save_sample_mask(cso); + cso_save_blend(cso); + cso_save_depth_stencil_alpha(cso); + cso_save_fragment_shader(cso); + cso_save_sampler_views(cso, PIPE_SHADER_FRAGMENT); + cso_save_samplers(cso, PIPE_SHADER_FRAGMENT); + cso_save_rasterizer(cso); + cso_save_viewport(cso); + cso_save_stream_outputs(cso); + cso_save_geometry_shader(cso); + cso_save_vertex_shader(cso); + cso_save_vertex_elements(cso); + cso_save_aux_vertex_buffer_slot(cso); + cso_save_constant_buffer_slot0(cso, PIPE_SHADER_VERTEX); + cso_save_render_condition(cso); + + /* set states */ + memset(&surf_templ, 0, sizeof(surf_templ)); + surf_templ.format = tex->format; + surf = pipe->create_surface(pipe, tex, &surf_templ); + + memset(&fb, 0, sizeof(fb)); + fb.nr_cbufs = 1; + fb.cbufs[0] = surf; + fb.zsbuf = NULL; + fb.width = hud->fb_width; + fb.height = hud->fb_height; + + viewport.scale[0] = 0.5f * hud->fb_width; + viewport.scale[1] = 0.5f * hud->fb_height; + viewport.scale[2] = 1.0f; + viewport.scale[3] = 1.0f; + viewport.translate[0] = 0.5f * hud->fb_width; + viewport.translate[1] = 0.5f * hud->fb_height; + viewport.translate[2] = 0.0f; + viewport.translate[3] = 0.0f; + + cso_set_framebuffer(cso, &fb); + cso_set_sample_mask(cso, ~0); + cso_set_blend(cso, &hud->alpha_blend); + cso_set_depth_stencil_alpha(cso, &hud->dsa); + cso_set_rasterizer(cso, &hud->rasterizer); + cso_set_viewport(cso, &viewport); + cso_set_stream_outputs(cso, 0, NULL, 0); + cso_set_geometry_shader_handle(cso, NULL); + cso_set_vertex_shader_handle(cso, hud->vs); + cso_set_vertex_elements(cso, 2, hud->velems); + cso_set_render_condition(cso, NULL, 0); + cso_set_sampler_views(cso, PIPE_SHADER_FRAGMENT, 1, + &hud->font_sampler_view); + cso_set_samplers(cso, PIPE_SHADER_FRAGMENT, 1, sampler_states); + cso_set_constant_buffer(cso, PIPE_SHADER_VERTEX, 0, &hud->constbuf); + + /* prepare vertex buffers */ + hud_alloc_vertices(hud, &hud->bg, 4 * 64, 2 * sizeof(float)); + hud_alloc_vertices(hud, &hud->whitelines, 4 * 256, 2 * sizeof(float)); + hud_alloc_vertices(hud, &hud->text, 4 * 512, 4 * sizeof(float)); + + /* prepare all graphs */ + LIST_FOR_EACH_ENTRY(pane, &hud->pane_list, head) { + LIST_FOR_EACH_ENTRY(gr, &pane->graph_list, head) { + gr->query_new_value(gr); + } + + hud_pane_accumulate_vertices(hud, pane); + } + + /* unmap the uploader's vertex buffer before drawing */ + u_upload_flush(hud->uploader); + + /* draw accumulated vertices for background quads */ + cso_set_fragment_shader_handle(hud->cso, hud->fs_color); + + if (hud->bg.num_vertices) { + hud->constants.color[0] = 0; + hud->constants.color[1] = 0; + hud->constants.color[2] = 0; + hud->constants.color[3] = 0.666; + hud->constants.translate[0] = 0; + hud->constants.translate[1] = 0; + hud->constants.scale[0] = 1; + hud->constants.scale[1] = 1; + + cso_set_constant_buffer(cso, PIPE_SHADER_VERTEX, 0, &hud->constbuf); + cso_set_vertex_buffers(cso, cso_get_aux_vertex_buffer_slot(cso), 1, + &hud->bg.vbuf); + cso_draw_arrays(cso, PIPE_PRIM_QUADS, 0, hud->bg.num_vertices); + } + pipe_resource_reference(&hud->bg.vbuf.buffer, NULL); + + /* draw accumulated vertices for white lines */ + hud->constants.color[0] = 1; + hud->constants.color[1] = 1; + hud->constants.color[2] = 1; + hud->constants.color[3] = 1; + hud->constants.translate[0] = 0; + hud->constants.translate[1] = 0; + hud->constants.scale[0] = 1; + hud->constants.scale[1] = 1; + cso_set_constant_buffer(cso, PIPE_SHADER_VERTEX, 0, &hud->constbuf); + + if (hud->whitelines.num_vertices) { + cso_set_vertex_buffers(cso, cso_get_aux_vertex_buffer_slot(cso), 1, + &hud->whitelines.vbuf); + cso_set_fragment_shader_handle(hud->cso, hud->fs_color); + cso_draw_arrays(cso, PIPE_PRIM_LINES, 0, hud->whitelines.num_vertices); + } + pipe_resource_reference(&hud->whitelines.vbuf.buffer, NULL); + + /* draw accumulated vertices for text */ + if (hud->text.num_vertices) { + cso_set_vertex_buffers(cso, cso_get_aux_vertex_buffer_slot(cso), 1, + &hud->text.vbuf); + cso_set_fragment_shader_handle(hud->cso, hud->fs_text); + cso_draw_arrays(cso, PIPE_PRIM_QUADS, 0, hud->text.num_vertices); + } + pipe_resource_reference(&hud->text.vbuf.buffer, NULL); + + /* draw the rest */ + LIST_FOR_EACH_ENTRY(pane, &hud->pane_list, head) { + if (pane) + hud_pane_draw_colored_objects(hud, pane); + } + + /* restore states */ + cso_restore_framebuffer(cso); + cso_restore_sample_mask(cso); + cso_restore_blend(cso); + cso_restore_depth_stencil_alpha(cso); + cso_restore_fragment_shader(cso); + cso_restore_sampler_views(cso, PIPE_SHADER_FRAGMENT); + cso_restore_samplers(cso, PIPE_SHADER_FRAGMENT); + cso_restore_rasterizer(cso); + cso_restore_viewport(cso); + cso_restore_stream_outputs(cso); + cso_restore_geometry_shader(cso); + cso_restore_vertex_shader(cso); + cso_restore_vertex_elements(cso); + cso_restore_aux_vertex_buffer_slot(cso); + cso_restore_constant_buffer_slot0(cso, PIPE_SHADER_VERTEX); + cso_restore_render_condition(cso); + + pipe_surface_reference(&surf, NULL); +} + +/** + * Set the maximum value for the Y axis of the graph. + * This scales the graph accordingly. + */ +void +hud_pane_set_max_value(struct hud_pane *pane, uint64_t value) +{ + pane->max_value = value; + pane->yscale = -(int)pane->inner_height / (double)pane->max_value; +} + +static struct hud_pane * +hud_pane_create(unsigned x1, unsigned y1, unsigned x2, unsigned y2, + unsigned period, uint64_t max_value) +{ + struct hud_pane *pane = CALLOC_STRUCT(hud_pane); + + if (!pane) + return NULL; + + pane->x1 = x1; + pane->y1 = y1; + pane->x2 = x2; + pane->y2 = y2; + pane->inner_x1 = x1 + 1; + pane->inner_x2 = x2 - 1; + pane->inner_y1 = y1 + 1; + pane->inner_y2 = y2 - 1; + pane->inner_width = pane->inner_x2 - pane->inner_x1; + pane->inner_height = pane->inner_y2 - pane->inner_y1; + pane->period = period; + pane->max_num_vertices = (x2 - x1 + 2) / 2; + hud_pane_set_max_value(pane, max_value); + LIST_INITHEAD(&pane->graph_list); + return pane; +} + +/** + * Add a graph to an existing pane. + * One pane can contain multiple graphs over each other. + */ +void +hud_pane_add_graph(struct hud_pane *pane, struct hud_graph *gr) +{ + static const float colors[][3] = { + {0, 1, 0}, + {1, 0, 0}, + {0, 1, 1}, + {1, 0, 1}, + {1, 1, 0}, + {0.5, 0.5, 1}, + {0.5, 0.5, 0.5}, + }; + char *name = gr->name; + + /* replace '-' with a space */ + while (*name) { + if (*name == '-') + *name = ' '; + name++; + } + + assert(pane->num_graphs < Elements(colors)); + gr->vertices = MALLOC(pane->max_num_vertices * sizeof(float) * 2); + gr->color[0] = colors[pane->num_graphs][0]; + gr->color[1] = colors[pane->num_graphs][1]; + gr->color[2] = colors[pane->num_graphs][2]; + gr->pane = pane; + LIST_ADDTAIL(&gr->head, &pane->graph_list); + pane->num_graphs++; +} + +void +hud_graph_add_value(struct hud_graph *gr, uint64_t value) +{ + if (gr->index == gr->pane->max_num_vertices) { + gr->vertices[0] = 0; + gr->vertices[1] = gr->vertices[(gr->index-1)*2+1]; + gr->index = 1; + } + gr->vertices[(gr->index)*2+0] = gr->index*2; + gr->vertices[(gr->index)*2+1] = value; + gr->index++; + + if (gr->num_vertices < gr->pane->max_num_vertices) { + gr->num_vertices++; + } + + gr->current_value = value; + if (value > gr->pane->max_value) { + hud_pane_set_max_value(gr->pane, value); + } +} + +static void +hud_graph_destroy(struct hud_graph *graph) +{ + FREE(graph->vertices); + if (graph->free_query_data) + graph->free_query_data(graph->query_data); + FREE(graph); +} + +/** + * Read a string from the environment variable. + * The separators "+", ",", ":", and ";" terminate the string. + * Return the number of read characters. + */ +static int +parse_string(const char *s, char *out) +{ + int i; + + for (i = 0; *s && *s != '+' && *s != ',' && *s != ':' && *s != ';'; + s++, out++, i++) + *out = *s; + + *out = 0; + + if (*s && !i) + fprintf(stderr, "gallium_hud: syntax error: unexpected '%c' (%i) while " + "parsing a string\n", *s, *s); + return i; +} + +static boolean +has_occlusion_query(struct pipe_screen *screen) +{ + return screen->get_param(screen, PIPE_CAP_OCCLUSION_QUERY) != 0; +} + +static boolean +has_streamout(struct pipe_screen *screen) +{ + return screen->get_param(screen, PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS) != 0; +} + +static void +hud_parse_env_var(struct hud_context *hud, const char *env) +{ + unsigned num, i; + char name[256], s[256]; + struct hud_pane *pane = NULL; + unsigned x = 10, y = 10; + unsigned width = 251, height = 100; + unsigned period = 500 * 1000; /* default period (1/2 second) */ + const char *period_env; + + /* + * The GALLIUM_HUD_PERIOD env var sets the graph update rate. + * The env var is in seconds (a float). + * Zero means update after every frame. + */ + period_env = getenv("GALLIUM_HUD_PERIOD"); + if (period_env) { + float p = atof(period_env); + if (p >= 0.0) { + period = (unsigned) (p * 1000 * 1000); + } + } + + while ((num = parse_string(env, name)) != 0) { + env += num; + + if (!pane) { + pane = hud_pane_create(x, y, x + width, y + height, period, 10); + if (!pane) + return; + } + + /* add a graph */ + if (strcmp(name, "fps") == 0) { + hud_fps_graph_install(pane); + } + else if (strcmp(name, "cpu") == 0) { + hud_cpu_graph_install(pane, ALL_CPUS); + } + else if (sscanf(name, "cpu%u%s", &i, s) == 1) { + hud_cpu_graph_install(pane, i); + } + else if (strcmp(name, "samples-passed") == 0 && + has_occlusion_query(hud->pipe->screen)) { + hud_pipe_query_install(pane, hud->pipe, "samples-passed", + PIPE_QUERY_OCCLUSION_COUNTER, 0, 0, FALSE); + } + else if (strcmp(name, "primitives-generated") == 0 && + has_streamout(hud->pipe->screen)) { + hud_pipe_query_install(pane, hud->pipe, "primitives-generated", + PIPE_QUERY_PRIMITIVES_GENERATED, 0, 0, FALSE); + } + else if (strncmp(name, "pipeline-statistics-", 20) == 0) { + if (hud->cap.query_pipeline_statistics) { + static const char *pipeline_statistics_names[] = + { + "ia-vertices", + "ia-primitives", + "vs-invocations", + "gs-invocations", + "gs-primitives", + "clipper-invocations", + "clipper-primitives-generated", + "ps-invocations", + "hs-invocations", + "ds-invocations", + "cs-invocations" + }; + for (i = 0; i < Elements(pipeline_statistics_names); ++i) + if (strcmp(&name[20], pipeline_statistics_names[i]) == 0) + break; + if (i < Elements(pipeline_statistics_names)) + hud_pipe_query_install(pane, hud->pipe, &name[20], + PIPE_QUERY_PIPELINE_STATISTICS, i, + 0, FALSE); + else + fprintf(stderr, "gallium_hud: invalid pipeline-statistics-*\n"); + } else { + fprintf(stderr, "gallium_hud: PIPE_QUERY_PIPELINE_STATISTICS " + "not supported by the driver\n"); + } + } + else { + if (!hud_driver_query_install(pane, hud->pipe, name)){ + fprintf(stderr, "gallium_hud: unknown driver query '%s'\n", name); + } + } + + if (*env == ':') { + env++; + + if (!pane) { + fprintf(stderr, "gallium_hud: syntax error: unexpected ':', " + "expected a name\n"); + break; + } + + num = parse_string(env, s); + env += num; + + if (num && sscanf(s, "%u", &i) == 1) { + hud_pane_set_max_value(pane, i); + } + else { + fprintf(stderr, "gallium_hud: syntax error: unexpected '%c' (%i) " + "after ':'\n", *env, *env); + } + } + + if (*env == 0) + break; + + /* parse a separator */ + switch (*env) { + case '+': + env++; + break; + + case ',': + env++; + y += height + hud->font.glyph_height * (pane->num_graphs + 2); + + if (pane && pane->num_graphs) { + LIST_ADDTAIL(&pane->head, &hud->pane_list); + pane = NULL; + } + break; + + case ';': + env++; + y = 10; + x += width + hud->font.glyph_width * 7; + + if (pane && pane->num_graphs) { + LIST_ADDTAIL(&pane->head, &hud->pane_list); + pane = NULL; + } + break; + + default: + fprintf(stderr, "gallium_hud: syntax error: unexpected '%c'\n", *env); + } + } + + if (pane) { + if (pane->num_graphs) { + LIST_ADDTAIL(&pane->head, &hud->pane_list); + } + else { + FREE(pane); + } + } +} + +static void +print_help(struct pipe_screen *screen) +{ + int i, num_queries, num_cpus = hud_get_num_cpus(); + + puts("Syntax: GALLIUM_HUD=name1[+name2][...][:value1][,nameI...][;nameJ...]"); + puts(""); + puts(" Names are identifiers of data sources which will be drawn as graphs"); + puts(" in panes. Multiple graphs can be drawn in the same pane."); + puts(" There can be multiple panes placed in rows and columns."); + puts(""); + puts(" '+' separates names which will share a pane."); + puts(" ':[value]' specifies the initial maximum value of the Y axis"); + puts(" for the given pane."); + puts(" ',' creates a new pane below the last one."); + puts(" ';' creates a new pane at the top of the next column."); + puts(""); + puts(" Example: GALLIUM_HUD=\"cpu,fps;primitives-generated\""); + puts(""); + puts(" Available names:"); + puts(" fps"); + puts(" cpu"); + + for (i = 0; i < num_cpus; i++) + printf(" cpu%i\n", i); + + if (has_occlusion_query(screen)) + puts(" pixels-rendered"); + if (has_streamout(screen)) + puts(" primitives-generated"); + + if (screen->get_driver_query_info){ + struct pipe_driver_query_info info; + num_queries = screen->get_driver_query_info(screen, 0, NULL); + + for (i = 0; i < num_queries; i++){ + screen->get_driver_query_info(screen, i, &info); + printf(" %s\n", info.name); + } + } + + puts(""); +} + +struct hud_context * +hud_create(struct pipe_context *pipe, struct cso_context *cso) +{ + struct hud_context *hud; + struct pipe_sampler_view view_templ; + unsigned i; + const char *env = debug_get_option("GALLIUM_HUD", NULL); + + if (!env || !*env) + return NULL; + + if (strcmp(env, "help") == 0) { + print_help(pipe->screen); + return NULL; + } + + hud = CALLOC_STRUCT(hud_context); + if (!hud) + return NULL; + + hud->pipe = pipe; + hud->cso = cso; + hud->uploader = u_upload_create(pipe, 256 * 1024, 16, + PIPE_BIND_VERTEX_BUFFER); + + /* font */ + if (!util_font_create(pipe, UTIL_FONT_FIXED_8X13, &hud->font)) { + u_upload_destroy(hud->uploader); + FREE(hud); + return NULL; + } + + /* blend state */ + hud->alpha_blend.rt[0].colormask = PIPE_MASK_RGBA; + hud->alpha_blend.rt[0].blend_enable = 1; + hud->alpha_blend.rt[0].rgb_func = PIPE_BLEND_ADD; + hud->alpha_blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA; + hud->alpha_blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; + hud->alpha_blend.rt[0].alpha_func = PIPE_BLEND_ADD; + hud->alpha_blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO; + hud->alpha_blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE; + + /* fragment shader */ + hud->fs_color = + util_make_fragment_passthrough_shader(pipe, + TGSI_SEMANTIC_COLOR, + TGSI_INTERPOLATE_CONSTANT); + + { + /* Read a texture and do .xxxx swizzling. */ + static const char *fragment_shader_text = { + "FRAG\n" + "DCL IN[0], GENERIC[0], LINEAR\n" + "DCL SAMP[0]\n" + "DCL OUT[0], COLOR[0]\n" + "DCL TEMP[0]\n" + + "TEX TEMP[0], IN[0], SAMP[0], RECT\n" + "MOV OUT[0], TEMP[0].xxxx\n" + "END\n" + }; + + struct tgsi_token tokens[1000]; + struct pipe_shader_state state = {tokens}; + + if (!tgsi_text_translate(fragment_shader_text, tokens, Elements(tokens))) { + assert(0); + pipe_resource_reference(&hud->font.texture, NULL); + u_upload_destroy(hud->uploader); + FREE(hud); + return NULL; + } + + hud->fs_text = pipe->create_fs_state(pipe, &state); + } + + /* rasterizer */ + hud->rasterizer.gl_rasterization_rules = 1; + hud->rasterizer.depth_clip = 1; + hud->rasterizer.line_width = 1; + hud->rasterizer.line_last_pixel = 1; + + /* vertex shader */ + { + static const char *vertex_shader_text = { + "VERT\n" + "DCL IN[0..1]\n" + "DCL OUT[0], POSITION\n" + "DCL OUT[1], COLOR[0]\n" /* color */ + "DCL OUT[2], GENERIC[0]\n" /* texcoord */ + /* [0] = color, + * [1] = (2/fb_width, 2/fb_height, xoffset, yoffset) + * [2] = (xscale, yscale, 0, 0) */ + "DCL CONST[0..2]\n" + "DCL TEMP[0]\n" + "IMM[0] FLT32 { -1, 0, 0, 1 }\n" + + /* v = in * (xscale, yscale) + (xoffset, yoffset) */ + "MAD TEMP[0].xy, IN[0], CONST[2].xyyy, CONST[1].zwww\n" + /* pos = v * (2 / fb_width, 2 / fb_height) - (1, 1) */ + "MAD OUT[0].xy, TEMP[0], CONST[1].xyyy, IMM[0].xxxx\n" + "MOV OUT[0].zw, IMM[0]\n" + + "MOV OUT[1], CONST[0]\n" + "MOV OUT[2], IN[1]\n" + "END\n" + }; + + struct tgsi_token tokens[1000]; + struct pipe_shader_state state = {tokens}; + + if (!tgsi_text_translate(vertex_shader_text, tokens, Elements(tokens))) { + assert(0); + pipe_resource_reference(&hud->font.texture, NULL); + u_upload_destroy(hud->uploader); + FREE(hud); + return NULL; + } + + hud->vs = pipe->create_vs_state(pipe, &state); + } + + /* vertex elements */ + for (i = 0; i < 2; i++) { + hud->velems[i].src_offset = i * 2 * sizeof(float); + hud->velems[i].src_format = PIPE_FORMAT_R32G32_FLOAT; + hud->velems[i].vertex_buffer_index = cso_get_aux_vertex_buffer_slot(cso); + } + + /* sampler view */ + memset(&view_templ, 0, sizeof(view_templ)); + view_templ.format = hud->font.texture->format; + view_templ.swizzle_r = PIPE_SWIZZLE_RED; + view_templ.swizzle_g = PIPE_SWIZZLE_GREEN; + view_templ.swizzle_b = PIPE_SWIZZLE_BLUE; + view_templ.swizzle_a = PIPE_SWIZZLE_ALPHA; + hud->font_sampler_view = pipe->create_sampler_view(pipe, hud->font.texture, + &view_templ); + + /* sampler state (for font drawing) */ + hud->font_sampler_state.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + hud->font_sampler_state.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + hud->font_sampler_state.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + hud->font_sampler_state.normalized_coords = 0; + + /* constants */ + hud->constbuf.buffer_size = sizeof(hud->constants); + hud->constbuf.user_buffer = &hud->constants; + + LIST_INITHEAD(&hud->pane_list); + + hud->cap.query_pipeline_statistics = + pipe->screen->get_param(pipe->screen, PIPE_CAP_QUERY_PIPELINE_STATISTICS); + + hud_parse_env_var(hud, env); + return hud; +} + +void +hud_destroy(struct hud_context *hud) +{ + struct pipe_context *pipe = hud->pipe; + struct hud_pane *pane, *pane_tmp; + struct hud_graph *graph, *graph_tmp; + + LIST_FOR_EACH_ENTRY_SAFE(pane, pane_tmp, &hud->pane_list, head) { + LIST_FOR_EACH_ENTRY_SAFE(graph, graph_tmp, &pane->graph_list, head) { + LIST_DEL(&graph->head); + hud_graph_destroy(graph); + } + LIST_DEL(&pane->head); + FREE(pane); + } + + pipe->delete_fs_state(pipe, hud->fs_color); + pipe->delete_fs_state(pipe, hud->fs_text); + pipe->delete_vs_state(pipe, hud->vs); + pipe_sampler_view_reference(&hud->font_sampler_view, NULL); + pipe_resource_reference(&hud->font.texture, NULL); + u_upload_destroy(hud->uploader); + FREE(hud); +} diff --git a/mesalib/src/gallium/auxiliary/hud/hud_context.h b/mesalib/src/gallium/auxiliary/hud/hud_context.h new file mode 100644 index 000000000..abf2ad586 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/hud/hud_context.h @@ -0,0 +1,45 @@ +/************************************************************************** + * + * Copyright 2013 Marek Olšák <maraeo@gmail.com> + * All Rights Reserved. + * + * 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, sub license, 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 NON-INFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS 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. + * + **************************************************************************/ + +#ifndef HUD_CONTEXT_H +#define HUD_CONTEXT_H + +struct hud_context; +struct cso_context; +struct pipe_context; +struct pipe_resource; + +struct hud_context * +hud_create(struct pipe_context *pipe, struct cso_context *cso); + +void +hud_destroy(struct hud_context *hud); + +void +hud_draw(struct hud_context *hud, struct pipe_resource *tex); + +#endif diff --git a/mesalib/src/gallium/auxiliary/hud/hud_cpu.c b/mesalib/src/gallium/auxiliary/hud/hud_cpu.c new file mode 100644 index 000000000..ce98115d5 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/hud/hud_cpu.c @@ -0,0 +1,166 @@ +/************************************************************************** + * + * Copyright 2013 Marek Olšák <maraeo@gmail.com> + * All Rights Reserved. + * + * 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, sub license, 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 NON-INFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS 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. + * + **************************************************************************/ + +/* This file contains code for reading CPU load for displaying on the HUD. + */ + +#include "hud/hud_private.h" +#include "os/os_time.h" +#include "util/u_memory.h" +#include <stdio.h> +#include <inttypes.h> + +static boolean +get_cpu_stats(unsigned cpu_index, uint64_t *busy_time, uint64_t *total_time) +{ + char cpuname[32]; + char line[1024]; + FILE *f; + + if (cpu_index == ALL_CPUS) + strcpy(cpuname, "cpu"); + else + sprintf(cpuname, "cpu%u", cpu_index); + + f = fopen("/proc/stat", "r"); + if (!f) + return FALSE; + + while (!feof(f) && fgets(line, sizeof(line), f)) { + if (strstr(line, cpuname) == line) { + uint64_t v[12]; + int i, num; + + num = sscanf(line, + "%s %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64 + " %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64 + " %"PRIu64" %"PRIu64"", + cpuname, &v[0], &v[1], &v[2], &v[3], &v[4], &v[5], + &v[6], &v[7], &v[8], &v[9], &v[10], &v[11]); + if (num < 5) { + fclose(f); + return FALSE; + } + + /* user + nice + system */ + *busy_time = v[0] + v[1] + v[2]; + *total_time = *busy_time; + + /* ... + idle + iowait + irq + softirq + ... */ + for (i = 3; i < num-1; i++) { + *total_time += v[i]; + } + fclose(f); + return TRUE; + } + } + fclose(f); + return FALSE; +} + +struct cpu_info { + unsigned cpu_index; + uint64_t last_cpu_busy, last_cpu_total, last_time; +}; + +static void +query_cpu_load(struct hud_graph *gr) +{ + struct cpu_info *info = gr->query_data; + uint64_t now = os_time_get(); + + if (info->last_time) { + if (info->last_time + gr->pane->period <= now) { + uint64_t cpu_busy, cpu_total, cpu_load; + + get_cpu_stats(info->cpu_index, &cpu_busy, &cpu_total); + + cpu_load = (cpu_busy - info->last_cpu_busy) * 100 / + (double)(cpu_total - info->last_cpu_total); + hud_graph_add_value(gr, cpu_load); + + info->last_cpu_busy = cpu_busy; + info->last_cpu_total = cpu_total; + info->last_time = now; + } + } + else { + /* initialize */ + info->last_time = now; + get_cpu_stats(info->cpu_index, &info->last_cpu_busy, + &info->last_cpu_total); + } +} + +void +hud_cpu_graph_install(struct hud_pane *pane, unsigned cpu_index) +{ + struct hud_graph *gr; + struct cpu_info *info; + uint64_t busy, total; + + /* see if the cpu exists */ + if (cpu_index != ALL_CPUS && !get_cpu_stats(cpu_index, &busy, &total)) { + return; + } + + gr = CALLOC_STRUCT(hud_graph); + if (!gr) + return; + + if (cpu_index == ALL_CPUS) + strcpy(gr->name, "cpu"); + else + sprintf(gr->name, "cpu%u", cpu_index); + + gr->query_data = CALLOC_STRUCT(cpu_info); + if (!gr->query_data) { + FREE(gr); + return; + } + + gr->query_new_value = query_cpu_load; + gr->free_query_data = free; + + info = gr->query_data; + info->cpu_index = cpu_index; + + hud_pane_add_graph(pane, gr); + hud_pane_set_max_value(pane, 100); +} + +int +hud_get_num_cpus(void) +{ + uint64_t busy, total; + int i = 0; + + while (get_cpu_stats(i, &busy, &total)) + i++; + + return i; +} diff --git a/mesalib/src/gallium/auxiliary/hud/hud_driver_query.c b/mesalib/src/gallium/auxiliary/hud/hud_driver_query.c new file mode 100644 index 000000000..0f52e18cc --- /dev/null +++ b/mesalib/src/gallium/auxiliary/hud/hud_driver_query.c @@ -0,0 +1,210 @@ +/************************************************************************** + * + * Copyright 2013 Marek Olšák <maraeo@gmail.com> + * All Rights Reserved. + * + * 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, sub license, 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 NON-INFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS 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. + * + **************************************************************************/ + +/* This file contains code for reading values from pipe queries + * for displaying on the HUD. To prevent stalls when reading queries, we + * keep a list of busy queries in a ring. We read only those queries which + * are idle. + */ + +#include "hud/hud_private.h" +#include "pipe/p_screen.h" +#include "os/os_time.h" +#include "util/u_memory.h" +#include <stdio.h> + +#define NUM_QUERIES 8 + +struct query_info { + struct pipe_context *pipe; + unsigned query_type; + unsigned result_index; /* unit depends on query_type */ + + /* Ring of queries. If a query is busy, we use another slot. */ + struct pipe_query *query[NUM_QUERIES]; + unsigned head, tail; + unsigned num_queries; + + uint64_t last_time; + uint64_t results_cumulative; + unsigned num_results; +}; + +static void +query_new_value(struct hud_graph *gr) +{ + struct query_info *info = gr->query_data; + struct pipe_context *pipe = info->pipe; + uint64_t now = os_time_get(); + + if (info->last_time) { + pipe->end_query(pipe, info->query[info->head]); + + /* read query results */ + while (1) { + struct pipe_query *query = info->query[info->tail]; + union pipe_query_result result; + uint64_t *res64 = (uint64_t *)&result; + + if (pipe->get_query_result(pipe, query, FALSE, &result)) { + info->results_cumulative += res64[info->result_index]; + info->num_results++; + + if (info->tail == info->head) + break; + + info->tail = (info->tail+1) % NUM_QUERIES; + } + else { + /* the oldest query is busy */ + if ((info->head+1) % NUM_QUERIES == info->tail) { + /* all queries are busy, throw away the last query and create + * a new one */ + fprintf(stderr, + "gallium_hud: all queries are busy after %i frames, " + "can't add another query\n", + NUM_QUERIES); + pipe->destroy_query(pipe, info->query[info->head]); + info->query[info->head] = + pipe->create_query(pipe, info->query_type); + } + else { + /* the last query is busy, we need to add a new one we can use + * for this frame */ + info->head = (info->head+1) % NUM_QUERIES; + if (!info->query[info->head]) { + info->query[info->head] = + pipe->create_query(pipe, info->query_type); + } + } + break; + } + } + + if (info->num_results && info->last_time + gr->pane->period <= now) { + /* compute the average value across all frames */ + hud_graph_add_value(gr, info->results_cumulative / info->num_results); + + info->last_time = now; + info->results_cumulative = 0; + info->num_results = 0; + } + + pipe->begin_query(pipe, info->query[info->head]); + } + else { + /* initialize */ + info->last_time = now; + info->query[info->head] = pipe->create_query(pipe, info->query_type); + pipe->begin_query(pipe, info->query[info->head]); + } +} + +static void +free_query_info(void *ptr) +{ + struct query_info *info = ptr; + + if (info->last_time) { + struct pipe_context *pipe = info->pipe; + int i; + + pipe->end_query(pipe, info->query[info->head]); + + for (i = 0; i < Elements(info->query); i++) { + if (info->query[i]) { + pipe->destroy_query(pipe, info->query[i]); + } + } + } + FREE(info); +} + +void +hud_pipe_query_install(struct hud_pane *pane, struct pipe_context *pipe, + const char *name, unsigned query_type, + unsigned result_index, + uint64_t max_value, boolean uses_byte_units) +{ + struct hud_graph *gr; + struct query_info *info; + + gr = CALLOC_STRUCT(hud_graph); + if (!gr) + return; + + strcpy(gr->name, name); + gr->query_data = CALLOC_STRUCT(query_info); + if (!gr->query_data) { + FREE(gr); + return; + } + + gr->query_new_value = query_new_value; + gr->free_query_data = free_query_info; + + info = gr->query_data; + info->pipe = pipe; + info->query_type = query_type; + info->result_index = result_index; + + hud_pane_add_graph(pane, gr); + if (pane->max_value < max_value) + hud_pane_set_max_value(pane, max_value); + if (uses_byte_units) + pane->uses_byte_units = TRUE; +} + +boolean +hud_driver_query_install(struct hud_pane *pane, struct pipe_context *pipe, + const char *name) +{ + struct pipe_screen *screen = pipe->screen; + struct pipe_driver_query_info query; + unsigned num_queries, i; + boolean found = FALSE; + + if (!screen->get_driver_query_info) + return FALSE; + + num_queries = screen->get_driver_query_info(screen, 0, NULL); + + for (i = 0; i < num_queries; i++) { + if (screen->get_driver_query_info(screen, i, &query) && + strcmp(query.name, name) == 0) { + found = TRUE; + break; + } + } + + if (!found) + return FALSE; + + hud_pipe_query_install(pane, pipe, query.name, query.query_type, 0, + query.max_value, query.uses_byte_units); + return TRUE; +} diff --git a/mesalib/src/gallium/auxiliary/hud/hud_fps.c b/mesalib/src/gallium/auxiliary/hud/hud_fps.c new file mode 100644 index 000000000..71cdfd04e --- /dev/null +++ b/mesalib/src/gallium/auxiliary/hud/hud_fps.c @@ -0,0 +1,81 @@ +/************************************************************************** + * + * Copyright 2013 Marek Olšák <maraeo@gmail.com> + * All Rights Reserved. + * + * 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, sub license, 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 NON-INFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS 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. + * + **************************************************************************/ + +/* This file contains code for calculating framerate for displaying on the HUD. + */ + +#include "hud/hud_private.h" +#include "os/os_time.h" +#include "util/u_memory.h" + +struct fps_info { + int frames; + uint64_t last_time; +}; + +static void +query_fps(struct hud_graph *gr) +{ + struct fps_info *info = gr->query_data; + uint64_t now = os_time_get(); + + info->frames++; + + if (info->last_time) { + if (info->last_time + gr->pane->period <= now) { + double fps = info->frames * 1000000 / (double)(now - info->last_time); + info->frames = 0; + info->last_time = now; + + hud_graph_add_value(gr, fps); + } + } + else { + info->last_time = now; + } +} + +void +hud_fps_graph_install(struct hud_pane *pane) +{ + struct hud_graph *gr = CALLOC_STRUCT(hud_graph); + + if (!gr) + return; + + strcpy(gr->name, "fps"); + gr->query_data = CALLOC_STRUCT(fps_info); + if (!gr->query_data) { + FREE(gr); + return; + } + + gr->query_new_value = query_fps; + gr->free_query_data = free; + + hud_pane_add_graph(pane, gr); +} diff --git a/mesalib/src/gallium/auxiliary/hud/hud_private.h b/mesalib/src/gallium/auxiliary/hud/hud_private.h new file mode 100644 index 000000000..2b7d56bb1 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/hud/hud_private.h @@ -0,0 +1,92 @@ +/************************************************************************** + * + * Copyright 2013 Marek Olšák <maraeo@gmail.com> + * All Rights Reserved. + * + * 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, sub license, 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 NON-INFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS 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. + * + **************************************************************************/ + +#ifndef HUD_PRIVATE_H +#define HUD_PRIVATE_H + +#include "pipe/p_context.h" +#include "util/u_double_list.h" + +struct hud_graph { + /* initialized by common code */ + struct list_head head; + struct hud_pane *pane; + float color[3]; + float *vertices; /* ring buffer of vertices */ + + /* name and query */ + char name[128]; + void *query_data; + void (*query_new_value)(struct hud_graph *gr); + void (*free_query_data)(void *ptr); + + /* mutable variables */ + unsigned num_vertices; + unsigned index; /* vertex index being updated */ + uint64_t current_value; +}; + +struct hud_pane { + struct list_head head; + unsigned x1, y1, x2, y2; + unsigned inner_x1; + unsigned inner_y1; + unsigned inner_x2; + unsigned inner_y2; + unsigned inner_width; + unsigned inner_height; + float yscale; + unsigned max_num_vertices; + uint64_t max_value; + boolean uses_byte_units; + uint64_t period; /* in microseconds */ + + struct list_head graph_list; + unsigned num_graphs; +}; + + +/* core */ +void hud_pane_add_graph(struct hud_pane *pane, struct hud_graph *gr); +void hud_pane_set_max_value(struct hud_pane *pane, uint64_t value); +void hud_graph_add_value(struct hud_graph *gr, uint64_t value); + +/* graphs/queries */ +#define ALL_CPUS ~0 /* optionally set as cpu_index */ + +int hud_get_num_cpus(void); + +void hud_fps_graph_install(struct hud_pane *pane); +void hud_cpu_graph_install(struct hud_pane *pane, unsigned cpu_index); +void hud_pipe_query_install(struct hud_pane *pane, struct pipe_context *pipe, + const char *name, unsigned query_type, + unsigned result_index, + uint64_t max_value, boolean uses_byte_units); +boolean hud_driver_query_install(struct hud_pane *pane, + struct pipe_context *pipe, const char *name); + +#endif diff --git a/mesalib/src/gallium/auxiliary/util/u_blitter.c b/mesalib/src/gallium/auxiliary/util/u_blitter.c index 70fec9118..2a4a13e9f 100644 --- a/mesalib/src/gallium/auxiliary/util/u_blitter.c +++ b/mesalib/src/gallium/auxiliary/util/u_blitter.c @@ -1135,18 +1135,17 @@ static boolean is_blit_generic_supported(struct blitter_context *blitter, if (dst) { unsigned bind; - boolean is_stencil; const struct util_format_description *desc = util_format_description(dst_format); - - is_stencil = util_format_has_stencil(desc); + boolean dst_has_stencil = util_format_has_stencil(desc); /* Stencil export must be supported for stencil copy. */ - if ((mask & PIPE_MASK_S) && is_stencil && !ctx->has_stencil_export) { + if ((mask & PIPE_MASK_S) && dst_has_stencil && + !ctx->has_stencil_export) { return FALSE; } - if (is_stencil || util_format_has_depth(desc)) + if (dst_has_stencil || util_format_has_depth(desc)) bind = PIPE_BIND_DEPTH_STENCIL; else bind = PIPE_BIND_RENDER_TARGET; @@ -1168,15 +1167,18 @@ static boolean is_blit_generic_supported(struct blitter_context *blitter, } /* Check stencil sampler support for stencil copy. */ - if (util_format_has_stencil(util_format_description(src_format))) { - enum pipe_format stencil_format = + if (mask & PIPE_MASK_S) { + if (util_format_has_stencil(util_format_description(src_format))) { + enum pipe_format stencil_format = util_format_stencil_only(src_format); - assert(stencil_format != PIPE_FORMAT_NONE); + assert(stencil_format != PIPE_FORMAT_NONE); - if (stencil_format != src_format && - !screen->is_format_supported(screen, stencil_format, src->target, - src->nr_samples, PIPE_BIND_SAMPLER_VIEW)) { - return FALSE; + if (stencil_format != src_format && + !screen->is_format_supported(screen, stencil_format, + src->target, src->nr_samples, + PIPE_BIND_SAMPLER_VIEW)) { + return FALSE; + } } } } diff --git a/mesalib/src/gallium/auxiliary/util/u_cpu_detect.c b/mesalib/src/gallium/auxiliary/util/u_cpu_detect.c index 03280515b..7e6df9df1 100644 --- a/mesalib/src/gallium/auxiliary/util/u_cpu_detect.c +++ b/mesalib/src/gallium/auxiliary/util/u_cpu_detect.c @@ -279,6 +279,7 @@ util_cpu_detect(void) util_cpu_caps.has_sse4_1 = (regs2[2] >> 19) & 1; util_cpu_caps.has_sse4_2 = (regs2[2] >> 20) & 1; util_cpu_caps.has_avx = (regs2[2] >> 28) & 1; + util_cpu_caps.has_f16c = (regs2[2] >> 29) & 1; util_cpu_caps.has_mmx2 = util_cpu_caps.has_sse; /* SSE cpus supports mmxext too */ cacheline = ((regs2[1] >> 8) & 0xFF) * 8; diff --git a/mesalib/src/gallium/auxiliary/util/u_cpu_detect.h b/mesalib/src/gallium/auxiliary/util/u_cpu_detect.h index acac68658..21c2f048f 100644 --- a/mesalib/src/gallium/auxiliary/util/u_cpu_detect.h +++ b/mesalib/src/gallium/auxiliary/util/u_cpu_detect.h @@ -63,6 +63,7 @@ struct util_cpu_caps { unsigned has_sse4_1:1; unsigned has_sse4_2:1; unsigned has_avx:1; + unsigned has_f16c:1; unsigned has_3dnow:1; unsigned has_3dnow_ext:1; unsigned has_altivec:1; diff --git a/mesalib/src/gallium/auxiliary/util/u_debug_memory.c b/mesalib/src/gallium/auxiliary/util/u_debug_memory.c index 4bf26a524..472354781 100644 --- a/mesalib/src/gallium/auxiliary/util/u_debug_memory.c +++ b/mesalib/src/gallium/auxiliary/util/u_debug_memory.c @@ -76,6 +76,7 @@ struct debug_memory_header #endif unsigned magic; + unsigned tag; }; struct debug_memory_footer @@ -140,6 +141,7 @@ debug_malloc(const char *file, unsigned line, const char *function, hdr->function = function; hdr->size = size; hdr->magic = DEBUG_MEMORY_MAGIC; + hdr->tag = 0; #if DEBUG_FREED_MEMORY hdr->freed = FALSE; #endif @@ -263,6 +265,7 @@ debug_realloc(const char *file, unsigned line, const char *function, new_hdr->function = old_hdr->function; new_hdr->size = new_size; new_hdr->magic = DEBUG_MEMORY_MAGIC; + new_hdr->tag = 0; #if DEBUG_FREED_MEMORY new_hdr->freed = FALSE; #endif @@ -348,6 +351,58 @@ debug_memory_end(unsigned long start_no) /** + * Put a tag (arbitrary integer) on a memory block. + * Can be useful for debugging. + */ +void +debug_memory_tag(void *ptr, unsigned tag) +{ + struct debug_memory_header *hdr; + + if (!ptr) + return; + + hdr = header_from_data(ptr); + if (hdr->magic != DEBUG_MEMORY_MAGIC) { + debug_printf("%s corrupted memory at %p\n", __FUNCTION__, ptr); + debug_assert(0); + } + + hdr->tag = tag; +} + + +/** + * Check the given block of memory for validity/corruption. + */ +void +debug_memory_check_block(void *ptr) +{ + struct debug_memory_header *hdr; + struct debug_memory_footer *ftr; + + if (!ptr) + return; + + hdr = header_from_data(ptr); + ftr = footer_from_header(hdr); + + if (hdr->magic != DEBUG_MEMORY_MAGIC) { + debug_printf("%s:%u:%s: bad or corrupted memory %p\n", + hdr->file, hdr->line, hdr->function, ptr); + debug_assert(0); + } + + if (ftr->magic != DEBUG_MEMORY_MAGIC) { + debug_printf("%s:%u:%s: buffer overflow %p\n", + hdr->file, hdr->line, hdr->function, ptr); + debug_assert(0); + } +} + + + +/** * We can periodically call this from elsewhere to do a basic sanity * check of the heap memory we've allocated. */ diff --git a/mesalib/src/gallium/auxiliary/util/u_format.h b/mesalib/src/gallium/auxiliary/util/u_format.h index 00301265d..ed942fb16 100644 --- a/mesalib/src/gallium/auxiliary/util/u_format.h +++ b/mesalib/src/gallium/auxiliary/util/u_format.h @@ -447,6 +447,7 @@ util_format_is_compressed(enum pipe_format format) switch (desc->layout) { case UTIL_FORMAT_LAYOUT_S3TC: case UTIL_FORMAT_LAYOUT_RGTC: + case UTIL_FORMAT_LAYOUT_ETC: /* XXX add other formats in the future */ return TRUE; default: diff --git a/mesalib/src/gallium/auxiliary/util/u_inlines.h b/mesalib/src/gallium/auxiliary/util/u_inlines.h index ba745ebb5..7770cd514 100644 --- a/mesalib/src/gallium/auxiliary/util/u_inlines.h +++ b/mesalib/src/gallium/auxiliary/util/u_inlines.h @@ -517,7 +517,7 @@ util_query_clear_result(union pipe_query_result *result, unsigned type) memset(&result->pipeline_statistics, 0, sizeof(result->pipeline_statistics)); break; default: - assert(0); + memset(result, 0, sizeof(*result)); } } @@ -583,7 +583,7 @@ util_copy_constant_buffer(struct pipe_constant_buffer *dst, } static INLINE unsigned -util_max_layer(struct pipe_resource *r, unsigned level) +util_max_layer(const struct pipe_resource *r, unsigned level) { switch (r->target) { case PIPE_TEXTURE_CUBE: diff --git a/mesalib/src/gallium/auxiliary/util/u_resource.c b/mesalib/src/gallium/auxiliary/util/u_resource.c index a32c4f6df..66caaae84 100644 --- a/mesalib/src/gallium/auxiliary/util/u_resource.c +++ b/mesalib/src/gallium/auxiliary/util/u_resource.c @@ -1,76 +1,65 @@ +/* + * Copyright 2013 VMware, Inc. + * All Rights Reserved. + * + * 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, sub license, 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 NON-INFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS 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. + */ -#include "util/u_inlines.h" -#include "util/u_transfer.h" +#include "pipe/p_defines.h" +#include "pipe/p_state.h" +#include "util/u_format.h" +#include "util/u_math.h" +#include "util/u_resource.h" -static INLINE struct u_resource * -u_resource( struct pipe_resource *res ) -{ - return (struct u_resource *)res; -} -boolean u_resource_get_handle_vtbl(struct pipe_screen *screen, - struct pipe_resource *resource, - struct winsys_handle *handle) +/** + * Return the size of the resource in bytes. + */ +unsigned +util_resource_size(const struct pipe_resource *res) { - struct u_resource *ur = u_resource(resource); - return ur->vtbl->resource_get_handle(screen, resource, handle); -} + unsigned width = res->width0; + unsigned height = res->height0; + unsigned depth = res->depth0; + unsigned size = 0; + unsigned level; -void u_resource_destroy_vtbl(struct pipe_screen *screen, - struct pipe_resource *resource) -{ - struct u_resource *ur = u_resource(resource); - ur->vtbl->resource_destroy(screen, resource); -} + for (level = 0; level <= res->last_level; level++) { + unsigned slices; -void *u_transfer_map_vtbl(struct pipe_context *context, - struct pipe_resource *resource, - unsigned level, - unsigned usage, - const struct pipe_box *box, - struct pipe_transfer **transfer) -{ - struct u_resource *ur = u_resource(resource); - return ur->vtbl->transfer_map(context, resource, level, usage, box, - transfer); -} + if (res->target == PIPE_TEXTURE_CUBE) + slices = 6; + else if (res->target == PIPE_TEXTURE_3D) + slices = depth; + else + slices = res->array_size; -void u_transfer_flush_region_vtbl( struct pipe_context *pipe, - struct pipe_transfer *transfer, - const struct pipe_box *box) -{ - struct u_resource *ur = u_resource(transfer->resource); - ur->vtbl->transfer_flush_region(pipe, transfer, box); -} + size += (util_format_get_nblocksy(res->format, height) * + util_format_get_stride(res->format, width) * slices); -void u_transfer_unmap_vtbl( struct pipe_context *pipe, - struct pipe_transfer *transfer ) -{ - struct u_resource *ur = u_resource(transfer->resource); - ur->vtbl->transfer_unmap(pipe, transfer); -} + width = u_minify(width, 1); + height = u_minify(height, 1); + depth = u_minify(depth, 1); + } -void u_transfer_inline_write_vtbl( struct pipe_context *pipe, - struct pipe_resource *resource, - unsigned level, - unsigned usage, - const struct pipe_box *box, - const void *data, - unsigned stride, - unsigned layer_stride) -{ - struct u_resource *ur = u_resource(resource); - ur->vtbl->transfer_inline_write(pipe, - resource, - level, - usage, - box, - data, - stride, - layer_stride); + return size; } - - - - diff --git a/mesalib/src/gallium/auxiliary/util/u_resource.h b/mesalib/src/gallium/auxiliary/util/u_resource.h new file mode 100644 index 000000000..977e0136b --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_resource.h @@ -0,0 +1,34 @@ +/* + * Copyright 2013 VMware, Inc. + * All Rights Reserved. + * + * 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, sub license, 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 NON-INFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS 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. + */ + +#ifndef U_RESOURCE_H +#define U_RESOURCE_H + +struct pipe_resource; + +unsigned +util_resource_size(const struct pipe_resource *res); + +#endif diff --git a/mesalib/src/gallium/auxiliary/util/u_transfer.c b/mesalib/src/gallium/auxiliary/util/u_transfer.c index 861682553..56e059bfd 100644 --- a/mesalib/src/gallium/auxiliary/util/u_transfer.c +++ b/mesalib/src/gallium/auxiliary/util/u_transfer.c @@ -87,3 +87,76 @@ void u_default_transfer_unmap( struct pipe_context *pipe, struct pipe_transfer *transfer ) { } + + +static INLINE struct u_resource * +u_resource( struct pipe_resource *res ) +{ + return (struct u_resource *)res; +} + +boolean u_resource_get_handle_vtbl(struct pipe_screen *screen, + struct pipe_resource *resource, + struct winsys_handle *handle) +{ + struct u_resource *ur = u_resource(resource); + return ur->vtbl->resource_get_handle(screen, resource, handle); +} + +void u_resource_destroy_vtbl(struct pipe_screen *screen, + struct pipe_resource *resource) +{ + struct u_resource *ur = u_resource(resource); + ur->vtbl->resource_destroy(screen, resource); +} + +void *u_transfer_map_vtbl(struct pipe_context *context, + struct pipe_resource *resource, + unsigned level, + unsigned usage, + const struct pipe_box *box, + struct pipe_transfer **transfer) +{ + struct u_resource *ur = u_resource(resource); + return ur->vtbl->transfer_map(context, resource, level, usage, box, + transfer); +} + +void u_transfer_flush_region_vtbl( struct pipe_context *pipe, + struct pipe_transfer *transfer, + const struct pipe_box *box) +{ + struct u_resource *ur = u_resource(transfer->resource); + ur->vtbl->transfer_flush_region(pipe, transfer, box); +} + +void u_transfer_unmap_vtbl( struct pipe_context *pipe, + struct pipe_transfer *transfer ) +{ + struct u_resource *ur = u_resource(transfer->resource); + ur->vtbl->transfer_unmap(pipe, transfer); +} + +void u_transfer_inline_write_vtbl( struct pipe_context *pipe, + struct pipe_resource *resource, + unsigned level, + unsigned usage, + const struct pipe_box *box, + const void *data, + unsigned stride, + unsigned layer_stride) +{ + struct u_resource *ur = u_resource(resource); + ur->vtbl->transfer_inline_write(pipe, + resource, + level, + usage, + box, + data, + stride, + layer_stride); +} + + + + diff --git a/mesalib/src/glsl/Makefile.sources b/mesalib/src/glsl/Makefile.sources index c294aa429..b5282a604 100644 --- a/mesalib/src/glsl/Makefile.sources +++ b/mesalib/src/glsl/Makefile.sources @@ -80,6 +80,7 @@ LIBGLSL_FILES = \ $(GLSL_SRCDIR)/opt_dead_code.cpp \ $(GLSL_SRCDIR)/opt_dead_code_local.cpp \ $(GLSL_SRCDIR)/opt_dead_functions.cpp \ + $(GLSL_SRCDIR)/opt_flatten_nested_if_blocks.cpp \ $(GLSL_SRCDIR)/opt_function_inlining.cpp \ $(GLSL_SRCDIR)/opt_if_simplification.cpp \ $(GLSL_SRCDIR)/opt_noop_swizzle.cpp \ diff --git a/mesalib/src/glsl/glcpp/glcpp-parse.y b/mesalib/src/glsl/glcpp/glcpp-parse.y index d6afe8814..00edbbfbd 100644 --- a/mesalib/src/glsl/glcpp/glcpp-parse.y +++ b/mesalib/src/glsl/glcpp/glcpp-parse.y @@ -1233,6 +1233,9 @@ glcpp_parser_create (const struct gl_extensions *extensions, int api) if (extensions->ARB_texture_multisample) add_builtin_define(parser, "GL_ARB_texture_multisample", 1); + + if (extensions->ARB_texture_query_lod) + add_builtin_define(parser, "GL_ARB_texture_query_lod", 1); } } diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp index 56082f761..099229410 100644 --- a/mesalib/src/glsl/glsl_parser_extras.cpp +++ b/mesalib/src/glsl/glsl_parser_extras.cpp @@ -467,6 +467,7 @@ static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = { EXT(ARB_texture_cube_map_array, true, false, true, true, false, ARB_texture_cube_map_array), EXT(ARB_shading_language_packing, true, false, true, true, false, ARB_shading_language_packing), EXT(ARB_texture_multisample, true, false, true, true, false, ARB_texture_multisample), + EXT(ARB_texture_query_lod, false, false, true, true, false, ARB_texture_query_lod), }; #undef EXT @@ -1217,6 +1218,7 @@ do_common_optimization(exec_list *ir, bool linked, progress = do_structure_splitting(ir) || progress; } progress = do_if_simplification(ir) || progress; + progress = opt_flatten_nested_if_blocks(ir) || progress; progress = do_copy_propagation(ir) || progress; progress = do_copy_propagation_elements(ir) || progress; if (linked) diff --git a/mesalib/src/glsl/glsl_parser_extras.h b/mesalib/src/glsl/glsl_parser_extras.h index ad296f0ea..37a47cf9a 100644 --- a/mesalib/src/glsl/glsl_parser_extras.h +++ b/mesalib/src/glsl/glsl_parser_extras.h @@ -286,6 +286,8 @@ struct _mesa_glsl_parse_state { bool ARB_shading_language_packing_warn; bool ARB_texture_multisample_enable; bool ARB_texture_multisample_warn; + bool ARB_texture_query_lod_enable; + bool ARB_texture_query_lod_warn; /*@}*/ /** Extensions supported by the OpenGL implementation. */ diff --git a/mesalib/src/glsl/glsl_types.cpp b/mesalib/src/glsl/glsl_types.cpp index 8b0a24805..419761a7d 100644 --- a/mesalib/src/glsl/glsl_types.cpp +++ b/mesalib/src/glsl/glsl_types.cpp @@ -476,6 +476,8 @@ const glsl_type *glsl_type::get_scalar_type() const return int_type; case GLSL_TYPE_FLOAT: return float_type; + case GLSL_TYPE_BOOL: + return bool_type; default: /* Handle everything else */ return type; diff --git a/mesalib/src/glsl/ir.cpp b/mesalib/src/glsl/ir.cpp index 60ef8b95a..05b77da2c 100644 --- a/mesalib/src/glsl/ir.cpp +++ b/mesalib/src/glsl/ir.cpp @@ -1307,7 +1307,7 @@ ir_dereference::is_lvalue() const } -static const char *tex_opcode_strs[] = { "tex", "txb", "txl", "txd", "txf", "txf_ms", "txs" }; +static const char *tex_opcode_strs[] = { "tex", "txb", "txl", "txd", "txf", "txf_ms", "txs", "lod" }; const char *ir_texture::opcode_string() { @@ -1338,6 +1338,9 @@ ir_texture::set_sampler(ir_dereference *sampler, const glsl_type *type) if (this->op == ir_txs) { assert(type->base_type == GLSL_TYPE_INT); + } else if (this->op == ir_lod) { + assert(type->vector_elements == 2); + assert(type->base_type == GLSL_TYPE_FLOAT); } else { assert(sampler->type->sampler_type == (int) type->base_type); if (sampler->type->sampler_shadow) diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h index bbfec695f..0c3e39979 100644 --- a/mesalib/src/glsl/ir.h +++ b/mesalib/src/glsl/ir.h @@ -120,6 +120,7 @@ public: virtual class ir_dereference * as_dereference() { return NULL; } virtual class ir_dereference_array * as_dereference_array() { return NULL; } virtual class ir_dereference_variable *as_dereference_variable() { return NULL; } + virtual class ir_dereference_record *as_dereference_record() { return NULL; } virtual class ir_expression * as_expression() { return NULL; } virtual class ir_rvalue * as_rvalue() { return NULL; } virtual class ir_loop * as_loop() { return NULL; } @@ -1425,7 +1426,8 @@ enum ir_texture_opcode { ir_txd, /**< Texture look-up with partial derivatvies */ ir_txf, /**< Texel fetch with explicit LOD */ ir_txf_ms, /**< Multisample texture fetch */ - ir_txs /**< Texture size */ + ir_txs, /**< Texture size */ + ir_lod /**< Texture lod query */ }; @@ -1449,6 +1451,7 @@ enum ir_texture_opcode { * (txf_ms * <type> <sampler> <coordinate> <sample_index>) * (txs <type> <sampler> <lod>) + * (lod <type> <sampler> <coordinate>) */ class ir_texture : public ir_rvalue { public: @@ -1738,6 +1741,11 @@ public: virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL); + virtual ir_dereference_record *as_dereference_record() + { + return this; + } + /** * Get the variable that is ultimately referenced by an r-value */ diff --git a/mesalib/src/glsl/ir_clone.cpp b/mesalib/src/glsl/ir_clone.cpp index 4797451d7..5b42935f8 100644 --- a/mesalib/src/glsl/ir_clone.cpp +++ b/mesalib/src/glsl/ir_clone.cpp @@ -243,6 +243,7 @@ ir_texture::clone(void *mem_ctx, struct hash_table *ht) const switch (this->op) { case ir_tex: + case ir_lod: break; case ir_txb: new_tex->lod_info.bias = this->lod_info.bias->clone(mem_ctx, ht); diff --git a/mesalib/src/glsl/ir_constant_expression.cpp b/mesalib/src/glsl/ir_constant_expression.cpp index c2d0dc46c..c09e56a3d 100644 --- a/mesalib/src/glsl/ir_constant_expression.cpp +++ b/mesalib/src/glsl/ir_constant_expression.cpp @@ -1398,7 +1398,7 @@ ir_dereference_array::constant_referenced(struct hash_table *variable_context, return; } - const glsl_type *vt = substore->type; + const glsl_type *vt = array->type; if (vt->is_array()) { store = substore->get_array_element(index); offset = 0; diff --git a/mesalib/src/glsl/ir_hv_accept.cpp b/mesalib/src/glsl/ir_hv_accept.cpp index 5fa75011e..559b71af3 100644 --- a/mesalib/src/glsl/ir_hv_accept.cpp +++ b/mesalib/src/glsl/ir_hv_accept.cpp @@ -213,6 +213,7 @@ ir_texture::accept(ir_hierarchical_visitor *v) switch (this->op) { case ir_tex: + case ir_lod: break; case ir_txb: s = this->lod_info.bias->accept(v); diff --git a/mesalib/src/glsl/ir_optimization.h b/mesalib/src/glsl/ir_optimization.h index 2454bbe6f..a8885d722 100644 --- a/mesalib/src/glsl/ir_optimization.h +++ b/mesalib/src/glsl/ir_optimization.h @@ -82,6 +82,7 @@ bool do_function_inlining(exec_list *instructions); bool do_lower_jumps(exec_list *instructions, bool pull_out_jumps = true, bool lower_sub_return = true, bool lower_main_return = false, bool lower_continue = false, bool lower_break = false); bool do_lower_texture_projection(exec_list *instructions); bool do_if_simplification(exec_list *instructions); +bool opt_flatten_nested_if_blocks(exec_list *instructions); bool do_discard_simplification(exec_list *instructions); bool lower_if_to_cond_assign(exec_list *instructions, unsigned max_depth = 0); bool do_mat_op_to_vec(exec_list *instructions); diff --git a/mesalib/src/glsl/ir_print_visitor.cpp b/mesalib/src/glsl/ir_print_visitor.cpp index 3bdea9bbc..597d2813f 100644 --- a/mesalib/src/glsl/ir_print_visitor.cpp +++ b/mesalib/src/glsl/ir_print_visitor.cpp @@ -278,6 +278,7 @@ void ir_print_visitor::visit(ir_texture *ir) switch (ir->op) { case ir_tex: + case ir_lod: break; case ir_txb: ir->lod_info.bias->accept(this); diff --git a/mesalib/src/glsl/ir_reader.cpp b/mesalib/src/glsl/ir_reader.cpp index 22ce03b0d..16fdc41b4 100644 --- a/mesalib/src/glsl/ir_reader.cpp +++ b/mesalib/src/glsl/ir_reader.cpp @@ -917,6 +917,8 @@ ir_reader::read_texture(s_expression *expr) s_pattern tex_pattern[] = { "tex", s_type, s_sampler, s_coord, s_offset, s_proj, s_shadow }; + s_pattern lod_pattern[] = + { "lod", s_type, s_sampler, s_coord }; s_pattern txf_pattern[] = { "txf", s_type, s_sampler, s_coord, s_offset, s_lod }; s_pattern txf_ms_pattern[] = @@ -926,7 +928,9 @@ ir_reader::read_texture(s_expression *expr) s_pattern other_pattern[] = { tag, s_type, s_sampler, s_coord, s_offset, s_proj, s_shadow, s_lod }; - if (MATCH(expr, tex_pattern)) { + if (MATCH(expr, lod_pattern)) { + op = ir_lod; + } else if (MATCH(expr, tex_pattern)) { op = ir_tex; } else if (MATCH(expr, txf_pattern)) { op = ir_txf; @@ -939,7 +943,7 @@ ir_reader::read_texture(s_expression *expr) if (op == -1) return NULL; } else { - ir_read_error(NULL, "unexpected texture pattern"); + ir_read_error(NULL, "unexpected texture pattern %s", tag->value()); return NULL; } @@ -971,7 +975,7 @@ ir_reader::read_texture(s_expression *expr) return NULL; } - if (op != ir_txf_ms) { + if (op != ir_txf_ms && op != ir_lod) { // Read texel offset - either 0 or an rvalue. s_int *si_offset = SX_AS_INT(s_offset); if (si_offset == NULL || si_offset->value() != 0) { @@ -984,7 +988,7 @@ ir_reader::read_texture(s_expression *expr) } } - if (op != ir_txf && op != ir_txf_ms && op != ir_txs) { + if (op != ir_txf && op != ir_txf_ms && op != ir_txs && op != ir_lod) { s_int *proj_as_int = SX_AS_INT(s_proj); if (proj_as_int && proj_as_int->value() == 1) { tex->projector = NULL; @@ -1054,7 +1058,7 @@ ir_reader::read_texture(s_expression *expr) break; } default: - // tex doesn't have any extra parameters. + // tex and lod don't have any extra parameters. break; }; return tex; diff --git a/mesalib/src/glsl/ir_rvalue_visitor.cpp b/mesalib/src/glsl/ir_rvalue_visitor.cpp index 543c54496..3504a4dda 100644 --- a/mesalib/src/glsl/ir_rvalue_visitor.cpp +++ b/mesalib/src/glsl/ir_rvalue_visitor.cpp @@ -57,6 +57,7 @@ ir_rvalue_base_visitor::rvalue_visit(ir_texture *ir) switch (ir->op) { case ir_tex: + case ir_lod: break; case ir_txb: handle_rvalue(&ir->lod_info.bias); diff --git a/mesalib/src/glsl/ir_validate.cpp b/mesalib/src/glsl/ir_validate.cpp index 24ea506dc..699c192cd 100644 --- a/mesalib/src/glsl/ir_validate.cpp +++ b/mesalib/src/glsl/ir_validate.cpp @@ -701,6 +701,11 @@ check_node_type(ir_instruction *ir, void *data) void validate_ir_tree(exec_list *instructions) { + /* We shouldn't have any reason to validate IR in a release build, + * and it's half composed of assert()s anyway which wouldn't do + * anything. + */ +#ifdef DEBUG ir_validate v; v.run(instructions); @@ -710,4 +715,5 @@ validate_ir_tree(exec_list *instructions) visit_tree(ir, check_node_type, NULL); } +#endif } diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp index 29856b080..2b30d2b65 100644 --- a/mesalib/src/glsl/linker.cpp +++ b/mesalib/src/glsl/linker.cpp @@ -1067,13 +1067,11 @@ link_intrastage_shaders(void *mem_ctx, free(linking_shaders); -#ifdef DEBUG /* At this point linked should contain all of the linked IR, so * validate it to make sure nothing went wrong. */ if (linked) validate_ir_tree(linked->ir); -#endif /* Make a pass over all variable declarations to ensure that arrays with * unspecified sizes have a size specified. The size is inferred from the diff --git a/mesalib/src/glsl/lower_jumps.cpp b/mesalib/src/glsl/lower_jumps.cpp index 92813f567..bfc8c013b 100644 --- a/mesalib/src/glsl/lower_jumps.cpp +++ b/mesalib/src/glsl/lower_jumps.cpp @@ -1002,10 +1002,12 @@ do_lower_jumps(exec_list *instructions, bool pull_out_jumps, bool lower_sub_retu v.lower_sub_return = lower_sub_return; v.lower_main_return = lower_main_return; + bool progress_ever = false; do { v.progress = false; visit_exec_list(instructions, &v); + progress_ever = v.progress || progress_ever; } while (v.progress); - return v.progress; + return progress_ever; } diff --git a/mesalib/src/glsl/lower_ubo_reference.cpp b/mesalib/src/glsl/lower_ubo_reference.cpp index 026197df7..aade203e7 100644 --- a/mesalib/src/glsl/lower_ubo_reference.cpp +++ b/mesalib/src/glsl/lower_ubo_reference.cpp @@ -356,18 +356,14 @@ lower_ubo_reference_visitor::emit_ubo_loads(ir_dereference *deref, unsigned matrix_stride = 16; for (unsigned i = 0; i < deref->type->vector_elements; i++) { - ir_rvalue *chan = new(mem_ctx) ir_constant((int)i); - ir_dereference *deref_chan = - new(mem_ctx) ir_dereference_array(deref->clone(mem_ctx, NULL), - chan); - ir_rvalue *chan_offset = add(base_offset, new(mem_ctx) ir_constant(deref_offset + i * matrix_stride)); - base_ir->insert_before(assign(deref_chan, + base_ir->insert_before(assign(deref->clone(mem_ctx, NULL), ubo_load(glsl_type::float_type, - chan_offset))); + chan_offset), + (1U << i))); } } } diff --git a/mesalib/src/glsl/opt_flatten_nested_if_blocks.cpp b/mesalib/src/glsl/opt_flatten_nested_if_blocks.cpp new file mode 100644 index 000000000..c70210204 --- /dev/null +++ b/mesalib/src/glsl/opt_flatten_nested_if_blocks.cpp @@ -0,0 +1,103 @@ +/* + * Copyright © 2013 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 opt_flatten_nested_if_blocks.cpp + * + * Flattens nested if blocks such as: + * + * if (x) { + * if (y) { + * ... + * } + * } + * + * into a single if block with a combined condition: + * + * if (x && y) { + * ... + * } + */ + +#include "ir.h" +#include "ir_builder.h" + +using namespace ir_builder; + +namespace { + +class nested_if_flattener : public ir_hierarchical_visitor { +public: + nested_if_flattener() + { + progress = false; + } + + ir_visitor_status visit_leave(ir_if *); + ir_visitor_status visit_enter(ir_assignment *); + + bool progress; +}; + +} /* unnamed namespace */ + +/* We only care about the top level "if" instructions, so don't + * descend into expressions. + */ +ir_visitor_status +nested_if_flattener::visit_enter(ir_assignment *ir) +{ + (void) ir; + return visit_continue_with_parent; +} + +bool +opt_flatten_nested_if_blocks(exec_list *instructions) +{ + nested_if_flattener v; + + v.run(instructions); + return v.progress; +} + + +ir_visitor_status +nested_if_flattener::visit_leave(ir_if *ir) +{ + /* Only handle a single ir_if within the then clause of an ir_if. No extra + * instructions, no else clauses, nothing. + */ + if (ir->then_instructions.is_empty() || !ir->else_instructions.is_empty()) + return visit_continue; + + ir_if *inner = ((ir_instruction *) ir->then_instructions.head)->as_if(); + if (!inner || !inner->next->is_tail_sentinel() || + !inner->else_instructions.is_empty()) + return visit_continue; + + ir->condition = logic_and(ir->condition, inner->condition); + inner->then_instructions.move_nodes_to(&ir->then_instructions); + + progress = true; + return visit_continue; +} diff --git a/mesalib/src/glsl/opt_tree_grafting.cpp b/mesalib/src/glsl/opt_tree_grafting.cpp index 985540196..9aceb134d 100644 --- a/mesalib/src/glsl/opt_tree_grafting.cpp +++ b/mesalib/src/glsl/opt_tree_grafting.cpp @@ -274,6 +274,7 @@ ir_tree_grafting_visitor::visit_enter(ir_texture *ir) switch (ir->op) { case ir_tex: + case ir_lod: break; case ir_txb: if (do_graft(&ir->lod_info.bias)) diff --git a/mesalib/src/glsl/standalone_scaffolding.cpp b/mesalib/src/glsl/standalone_scaffolding.cpp index b5ef768bd..0c1f52f48 100644 --- a/mesalib/src/glsl/standalone_scaffolding.cpp +++ b/mesalib/src/glsl/standalone_scaffolding.cpp @@ -103,6 +103,7 @@ void initialize_context_to_defaults(struct gl_context *ctx, gl_api api) ctx->Extensions.OES_standard_derivatives = true; ctx->Extensions.ARB_texture_cube_map_array = true; ctx->Extensions.ARB_texture_multisample = true; + ctx->Extensions.ARB_texture_query_lod = true; ctx->Const.GLSLVersion = 120; diff --git a/mesalib/src/mapi/glapi/gen/ARB_texture_storage_multisample.xml b/mesalib/src/mapi/glapi/gen/ARB_texture_storage_multisample.xml new file mode 100644 index 000000000..0f9d323d4 --- /dev/null +++ b/mesalib/src/mapi/glapi/gen/ARB_texture_storage_multisample.xml @@ -0,0 +1,31 @@ +<?xml version="1.0"?> +<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd"> + +<!-- Note: no GLX protocol info yet. --> + +<OpenGLAPI> + +<category name="GL_ARB_texture_storage_multisample" number="141"> + + <function name="TexStorage2DMultisample" offset="assign"> + <param name="target" type="GLenum"/> + <param name="samples" type="GLsizei"/> + <param name="internalformat" type="GLenum"/> + <param name="width" type="GLsizei"/> + <param name="height" type="GLsizei"/> + <param name="fixedsamplelocations" type="GLboolean"/> + </function> + + <function name="TexStorage3DMultisample" offset="assign"> + <param name="target" type="GLenum"/> + <param name="samples" type="GLsizei"/> + <param name="internalformat" type="GLenum"/> + <param name="width" type="GLsizei"/> + <param name="height" type="GLsizei"/> + <param name="depth" type="GLsizei"/> + <param name="fixedsamplelocations" type="GLboolean"/> + </function> + +</category> + +</OpenGLAPI> diff --git a/mesalib/src/mapi/glapi/gen/gl_API.xml b/mesalib/src/mapi/glapi/gen/gl_API.xml index e313013f3..d57b5e8a7 100755 --- a/mesalib/src/mapi/glapi/gen/gl_API.xml +++ b/mesalib/src/mapi/glapi/gen/gl_API.xml @@ -8321,6 +8321,10 @@ <xi:include href="ARB_texture_buffer_range.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> +<!-- 140. GL_ARB_texture_query_levels --> + +<xi:include href="ARB_texture_storage_multisample.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> + <!-- Non-ARB extensions sorted by extension number. --> <category name="GL_EXT_blend_color" number="2"> diff --git a/mesalib/src/mesa/drivers/common/driverfuncs.c b/mesalib/src/mesa/drivers/common/driverfuncs.c index 731d46658..a98dfc607 100644 --- a/mesalib/src/mesa/drivers/common/driverfuncs.c +++ b/mesalib/src/mesa/drivers/common/driverfuncs.c @@ -28,6 +28,7 @@ #include "main/accum.h" #include "main/arrayobj.h" #include "main/context.h" +#include "main/formatquery.h" #include "main/framebuffer.h" #include "main/mipmap.h" #include "main/queryobj.h" @@ -90,7 +91,7 @@ _mesa_init_driver_functions(struct dd_function_table *driver) /* Texture functions */ driver->ChooseTextureFormat = _mesa_choose_tex_format; - driver->QuerySamplesForFormat = NULL; + driver->QuerySamplesForFormat = _mesa_query_samples_for_format; driver->TexImage = _mesa_store_teximage; driver->TexSubImage = _mesa_store_texsubimage; driver->GetTexImage = _mesa_meta_GetTexImage; diff --git a/mesalib/src/mesa/drivers/common/meta.c b/mesalib/src/mesa/drivers/common/meta.c index 8114550ba..e3ab82bfe 100644 --- a/mesalib/src/mesa/drivers/common/meta.c +++ b/mesalib/src/mesa/drivers/common/meta.c @@ -757,7 +757,8 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state) * it's for the pixel path (ClampFragmentColor is GL_TRUE), * regardless of the internal implementation of the metaops. */ - if (ctx->Color.ClampFragmentColor != GL_TRUE) + if (ctx->Color.ClampFragmentColor != GL_TRUE && + ctx->Extensions.ARB_color_buffer_float) _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE); } @@ -767,7 +768,8 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state) /* Generally in here we never want vertex color clamping -- * result clamping is only dependent on fragment clamping. */ - _mesa_ClampColor(GL_CLAMP_VERTEX_COLOR, GL_FALSE); + if (ctx->Extensions.ARB_color_buffer_float) + _mesa_ClampColor(GL_CLAMP_VERTEX_COLOR, GL_FALSE); } if (state & MESA_META_CONDITIONAL_RENDER) { @@ -1091,11 +1093,13 @@ _mesa_meta_end(struct gl_context *ctx) _mesa_DepthRange(save->DepthNear, save->DepthFar); } - if (state & MESA_META_CLAMP_FRAGMENT_COLOR) { + if (state & MESA_META_CLAMP_FRAGMENT_COLOR && + ctx->Extensions.ARB_color_buffer_float) { _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR, save->ClampFragmentColor); } - if (state & MESA_META_CLAMP_VERTEX_COLOR) { + if (state & MESA_META_CLAMP_VERTEX_COLOR && + ctx->Extensions.ARB_color_buffer_float) { _mesa_ClampColor(GL_CLAMP_VERTEX_COLOR, save->ClampVertexColor); } @@ -2044,7 +2048,8 @@ _mesa_meta_Clear(struct gl_context *ctx, GLbitfield buffers) /* leave colormask, glDrawBuffer state as-is */ /* Clears never have the color clamped. */ - _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE); + if (ctx->Extensions.ARB_color_buffer_float) + _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE); } else { ASSERT(metaSave & MESA_META_COLOR_MASK); @@ -2295,7 +2300,8 @@ _mesa_meta_glsl_Clear(struct gl_context *ctx, GLbitfield buffers) /* leave colormask, glDrawBuffer state as-is */ /* Clears never have the color clamped. */ - _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE); + if (ctx->Extensions.ARB_color_buffer_float) + _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE); } else { ASSERT(metaSave & MESA_META_COLOR_MASK); diff --git a/mesalib/src/mesa/drivers/dri/common/Android.mk b/mesalib/src/mesa/drivers/dri/common/Android.mk index f428c3855..b3dac29dd 100644 --- a/mesalib/src/mesa/drivers/dri/common/Android.mk +++ b/mesalib/src/mesa/drivers/dri/common/Android.mk @@ -77,7 +77,8 @@ $(intermediates)/xmlpool/options.h: PRIVATE_SCRIPT := $(LOCAL_PATH)/xmlpool/gen_ $(intermediates)/xmlpool/options.h: PRIVATE_LOCALEDIR := $(intermediates)/xmlpool $(intermediates)/xmlpool/options.h: PRIVATE_TEMPLATE_HEADER := $(LOCAL_PATH)/xmlpool/t_options.h $(intermediates)/xmlpool/options.h: PRIVATE_MO_FILES := $(MESA_DRI_OPTIONS_LANGS:%=$(intermediates)/xmlpool/%/LC_MESSAGES/options.mo) -$(intermediates)/xmlpool/options.h: $(PRIVATE_SCRIPT) $(PRIVATE_TEMPLATE_HEADER) $(PRIVATE_MO_FILES) +.SECONDEXPANSION: +$(intermediates)/xmlpool/options.h: $$(PRIVATE_SCRIPT) $$(PRIVATE_TEMPLATE_HEADER) $$(PRIVATE_MO_FILES) mkdir -p $(dir $@) mkdir -p $(PRIVATE_LOCALEDIR) $(MESA_PYTHON2) $(PRIVATE_SCRIPT) $(PRIVATE_TEMPLATE_HEADER) \ diff --git a/mesalib/src/mesa/drivers/dri/common/drirc b/mesalib/src/mesa/drivers/dri/common/drirc index a13941f68..556d1b599 100644 --- a/mesalib/src/mesa/drivers/dri/common/drirc +++ b/mesalib/src/mesa/drivers/dri/common/drirc @@ -25,5 +25,11 @@ <application name="Savage 2" executable="savage2.bin"> <option name="disable_glsl_line_continuations" value="true" /> </application> + <application name="Topogun (32-bit)" executable="topogun32"> + <option name="always_have_depth_buffer" value="true" /> + </application> + <application name="Topogun (64-bit)" executable="topogun64"> + <option name="always_have_depth_buffer" value="true" /> + </application> </device> </driconf> diff --git a/mesalib/src/mesa/main/attrib.c b/mesalib/src/mesa/main/attrib.c index 3b991bcac..a672845bf 100644 --- a/mesalib/src/mesa/main/attrib.c +++ b/mesalib/src/mesa/main/attrib.c @@ -986,7 +986,9 @@ _mesa_PopAttrib(void) _mesa_set_enable(ctx, GL_INDEX_LOGIC_OP, color->IndexLogicOpEnabled); _mesa_set_enable(ctx, GL_DITHER, color->DitherFlag); - _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR_ARB, color->ClampFragmentColor); + if (ctx->Extensions.ARB_color_buffer_float) + _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR_ARB, + color->ClampFragmentColor); _mesa_ClampColor(GL_CLAMP_READ_COLOR_ARB, color->ClampReadColor); /* GL_ARB_framebuffer_sRGB / GL_EXT_framebuffer_sRGB */ @@ -1114,7 +1116,10 @@ _mesa_PopAttrib(void) /* materials */ memcpy(&ctx->Light.Material, &light->Material, sizeof(struct gl_material)); - _mesa_ClampColor(GL_CLAMP_VERTEX_COLOR_ARB, light->ClampVertexColor); + if (ctx->Extensions.ARB_color_buffer_float) { + _mesa_ClampColor(GL_CLAMP_VERTEX_COLOR_ARB, + light->ClampVertexColor); + } } break; case GL_LINE_BIT: diff --git a/mesalib/src/mesa/main/blend.c b/mesalib/src/mesa/main/blend.c index 309f1d538..09a1c9ae8 100644 --- a/mesalib/src/mesa/main/blend.c +++ b/mesalib/src/mesa/main/blend.c @@ -765,24 +765,96 @@ _mesa_ClampColor(GLenum target, GLenum clamp) switch (target) { case GL_CLAMP_VERTEX_COLOR_ARB: + if (ctx->API == API_OPENGL_CORE && + !ctx->Extensions.ARB_color_buffer_float) { + goto invalid_enum; + } FLUSH_VERTICES(ctx, _NEW_LIGHT); ctx->Light.ClampVertexColor = clamp; + _mesa_update_clamp_vertex_color(ctx); break; case GL_CLAMP_FRAGMENT_COLOR_ARB: + if (ctx->API == API_OPENGL_CORE && + !ctx->Extensions.ARB_color_buffer_float) { + goto invalid_enum; + } FLUSH_VERTICES(ctx, _NEW_FRAG_CLAMP); ctx->Color.ClampFragmentColor = clamp; + _mesa_update_clamp_fragment_color(ctx); break; case GL_CLAMP_READ_COLOR_ARB: FLUSH_VERTICES(ctx, _NEW_COLOR); ctx->Color.ClampReadColor = clamp; break; default: - _mesa_error(ctx, GL_INVALID_ENUM, "glClampColorARB(target)"); - return; + goto invalid_enum; } + return; + +invalid_enum: + _mesa_error(ctx, GL_INVALID_ENUM, "glClampColor(%s)", + _mesa_lookup_enum_by_nr(target)); +} + +static GLboolean +get_clamp_color(const struct gl_framebuffer *fb, GLenum clamp) +{ + if (clamp == GL_TRUE || clamp == GL_FALSE) + return clamp; + + ASSERT(clamp == GL_FIXED_ONLY); + if (!fb) + return GL_TRUE; + + return fb->_AllColorBuffersFixedPoint; +} + +GLboolean +_mesa_get_clamp_fragment_color(const struct gl_context *ctx) +{ + return get_clamp_color(ctx->DrawBuffer, + ctx->Color.ClampFragmentColor); +} + +GLboolean +_mesa_get_clamp_vertex_color(const struct gl_context *ctx) +{ + return get_clamp_color(ctx->DrawBuffer, ctx->Light.ClampVertexColor); +} + +GLboolean +_mesa_get_clamp_read_color(const struct gl_context *ctx) +{ + return get_clamp_color(ctx->ReadBuffer, ctx->Color.ClampReadColor); } +/** + * Update the ctx->Color._ClampFragmentColor field + */ +void +_mesa_update_clamp_fragment_color(struct gl_context *ctx) +{ + struct gl_framebuffer *fb = ctx->DrawBuffer; + /* Don't clamp if: + * - there is no colorbuffer + * - all colorbuffers are unsigned normalized, so clamping has no effect + * - there is an integer colorbuffer + */ + if (!fb || !fb->_HasSNormOrFloatColorBuffer || fb->_IntegerColor) + ctx->Color._ClampFragmentColor = GL_FALSE; + else + ctx->Color._ClampFragmentColor = _mesa_get_clamp_fragment_color(ctx); +} + +/** + * Update the ctx->Color._ClampVertexColor field + */ +void +_mesa_update_clamp_vertex_color(struct gl_context *ctx) +{ + ctx->Light._ClampVertexColor = _mesa_get_clamp_vertex_color(ctx); +} /**********************************************************************/ @@ -832,10 +904,10 @@ void _mesa_init_color( struct gl_context * ctx ) ctx->Color.DrawBuffer[0] = GL_FRONT; } - ctx->Color.ClampFragmentColor = GL_FIXED_ONLY_ARB; - ctx->Color._ClampFragmentColor = GL_TRUE; + ctx->Color.ClampFragmentColor = ctx->API == API_OPENGL_COMPAT ? + GL_FIXED_ONLY_ARB : GL_FALSE; + ctx->Color._ClampFragmentColor = GL_FALSE; ctx->Color.ClampReadColor = GL_FIXED_ONLY_ARB; - ctx->Color._ClampReadColor = GL_TRUE; if (ctx->API == API_OPENGLES2) { /* GLES 3 behaves as though GL_FRAMEBUFFER_SRGB is always enabled. */ diff --git a/mesalib/src/mesa/main/blend.h b/mesalib/src/mesa/main/blend.h index a539aa809..621311d55 100644 --- a/mesalib/src/mesa/main/blend.h +++ b/mesalib/src/mesa/main/blend.h @@ -99,6 +99,20 @@ _mesa_ColorMaski( GLuint buf, GLboolean red, GLboolean green, extern void GLAPIENTRY _mesa_ClampColor(GLenum target, GLenum clamp); +extern GLboolean +_mesa_get_clamp_fragment_color(const struct gl_context *ctx); + +extern GLboolean +_mesa_get_clamp_vertex_color(const struct gl_context *ctx); + +extern GLboolean +_mesa_get_clamp_read_color(const struct gl_context *ctx); + +extern void +_mesa_update_clamp_fragment_color(struct gl_context *ctx); + +extern void +_mesa_update_clamp_vertex_color(struct gl_context *ctx); extern void _mesa_init_color( struct gl_context * ctx ); diff --git a/mesalib/src/mesa/main/compiler.h b/mesalib/src/mesa/main/compiler.h index 8b23665e6..8431534c3 100644 --- a/mesalib/src/mesa/main/compiler.h +++ b/mesalib/src/mesa/main/compiler.h @@ -256,7 +256,7 @@ static INLINE GLuint CPU_TO_LE32(GLuint x) */ #define STATIC_ASSERT(COND) \ do { \ - typedef int static_assertion_failed[(!!(COND))*2-1]; \ + (void) sizeof(char [1 - 2*!(COND)]); \ } while (0) diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c index e90a29680..c7f038b88 100644 --- a/mesalib/src/mesa/main/extensions.c +++ b/mesalib/src/mesa/main/extensions.c @@ -144,10 +144,12 @@ static const struct extension extension_table[] = { { "GL_ARB_texture_mirrored_repeat", o(dummy_true), GLL, 2001 }, { "GL_ARB_texture_multisample", o(ARB_texture_multisample), GL, 2009 }, { "GL_ARB_texture_non_power_of_two", o(ARB_texture_non_power_of_two), GL, 2003 }, + { "GL_ARB_texture_query_lod", o(ARB_texture_query_lod), GL, 2009 }, { "GL_ARB_texture_rectangle", o(NV_texture_rectangle), GL, 2004 }, { "GL_ARB_texture_rgb10_a2ui", o(ARB_texture_rgb10_a2ui), GL, 2009 }, { "GL_ARB_texture_rg", o(ARB_texture_rg), GL, 2008 }, { "GL_ARB_texture_storage", o(ARB_texture_storage), GL, 2011 }, + { "GL_ARB_texture_storage_multisample", o(ARB_texture_storage_multisample), GL, 2012 }, { "GL_ARB_texture_swizzle", o(EXT_texture_swizzle), GL, 2008 }, { "GL_ARB_timer_query", o(ARB_timer_query), GL, 2010 }, { "GL_ARB_transform_feedback2", o(ARB_transform_feedback2), GL, 2010 }, diff --git a/mesalib/src/mesa/main/fbobject.c b/mesalib/src/mesa/main/fbobject.c index 3fdf62667..fc2b2620b 100644 --- a/mesalib/src/mesa/main/fbobject.c +++ b/mesalib/src/mesa/main/fbobject.c @@ -784,6 +784,8 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx, numImages = 0; fb->Width = 0; fb->Height = 0; + fb->_AllColorBuffersFixedPoint = GL_TRUE; + fb->_HasSNormOrFloatColorBuffer = GL_FALSE; /* Start at -2 to more easily loop over all attachment points. * -2: depth buffer @@ -900,6 +902,19 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx, /* check if integer color */ fb->_IntegerColor = _mesa_is_format_integer_color(attFormat); + /* Update _AllColorBuffersFixedPoint and _HasSNormOrFloatColorBuffer. */ + if (i >= 0) { + GLenum type = _mesa_get_format_datatype(attFormat); + + fb->_AllColorBuffersFixedPoint = + fb->_AllColorBuffersFixedPoint && + (type == GL_UNSIGNED_NORMALIZED || type == GL_SIGNED_NORMALIZED); + + fb->_HasSNormOrFloatColorBuffer = + fb->_HasSNormOrFloatColorBuffer || + type == GL_SIGNED_NORMALIZED || type == GL_FLOAT; + } + /* Error-check width, height, format */ if (numImages == 1) { /* save format */ @@ -1537,15 +1552,16 @@ renderbuffer_storage(GLenum target, GLenum internalFormat, /* NumSamples == 0 indicates non-multisampling */ samples = 0; } - - /* check the sample count; - * note: driver may choose to use more samples than what's requested - */ - sample_count_error = _mesa_check_sample_count(ctx, target, - internalFormat, samples); - if (sample_count_error != GL_NO_ERROR) { - _mesa_error(ctx, sample_count_error, "%s(samples)", func); - return; + else { + /* check the sample count; + * note: driver may choose to use more samples than what's requested + */ + sample_count_error = _mesa_check_sample_count(ctx, target, + internalFormat, samples); + if (sample_count_error != GL_NO_ERROR) { + _mesa_error(ctx, sample_count_error, "%s(samples)", func); + return; + } } rb = ctx->CurrentRenderbuffer; diff --git a/mesalib/src/mesa/main/formatquery.c b/mesalib/src/mesa/main/formatquery.c index 78c5fbe5e..e45dc8680 100644 --- a/mesalib/src/mesa/main/formatquery.c +++ b/mesalib/src/mesa/main/formatquery.c @@ -30,6 +30,21 @@ #include "fbobject.h" #include "formatquery.h" +/* default implementation of QuerySamplesForFormat driverfunc, for + * non-multisample-capable drivers. */ +size_t +_mesa_query_samples_for_format(struct gl_context *ctx, GLenum target, + GLenum internalFormat, int samples[16]) +{ + (void) target; + (void) internalFormat; + (void) ctx; + + samples[0] = 1; + return 1; +} + + void GLAPIENTRY _mesa_GetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params) diff --git a/mesalib/src/mesa/main/formatquery.h b/mesalib/src/mesa/main/formatquery.h index 585c3eb64..603400059 100644 --- a/mesalib/src/mesa/main/formatquery.h +++ b/mesalib/src/mesa/main/formatquery.h @@ -28,6 +28,10 @@ #include "compiler.h" #include "glheader.h" +size_t +_mesa_query_samples_for_format(struct gl_context *ctx, GLenum target, + GLenum internalFormat, int samples[16]); + extern void GLAPIENTRY _mesa_GetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params); diff --git a/mesalib/src/mesa/main/framebuffer.c b/mesalib/src/mesa/main/framebuffer.c index 619aaa337..6c6977431 100644 --- a/mesalib/src/mesa/main/framebuffer.c +++ b/mesalib/src/mesa/main/framebuffer.c @@ -32,6 +32,7 @@ #include "glheader.h" #include "imports.h" +#include "blend.h" #include "buffers.h" #include "context.h" #include "enums.h" @@ -154,6 +155,8 @@ _mesa_initialize_window_framebuffer(struct gl_framebuffer *fb, fb->Delete = _mesa_destroy_framebuffer; fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT; + fb->_AllColorBuffersFixedPoint = !visual->floatMode; + fb->_HasSNormOrFloatColorBuffer = visual->floatMode; compute_depth_max(fb); } @@ -740,6 +743,9 @@ _mesa_update_framebuffer(struct gl_context *ctx) update_framebuffer(ctx, drawFb); if (readFb != drawFb) update_framebuffer(ctx, readFb); + + _mesa_update_clamp_vertex_color(ctx); + _mesa_update_clamp_fragment_color(ctx); } diff --git a/mesalib/src/mesa/main/get.c b/mesalib/src/mesa/main/get.c index 582ef3198..2ba868c0d 100644 --- a/mesalib/src/mesa/main/get.c +++ b/mesalib/src/mesa/main/get.c @@ -24,6 +24,7 @@ #include "glheader.h" #include "context.h" +#include "blend.h" #include "enable.h" #include "enums.h" #include "extensions.h" @@ -358,6 +359,13 @@ EXTRA_EXT(ARB_texture_buffer_range); EXTRA_EXT(ARB_texture_multisample); static const int +extra_ARB_color_buffer_float_or_glcore[] = { + EXT(ARB_color_buffer_float), + EXTRA_API_GL_CORE, + EXTRA_END +}; + +static const int extra_NV_primitive_restart[] = { EXT(NV_primitive_restart), EXTRA_END @@ -767,13 +775,13 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu break; case GL_FOG_COLOR: - if(ctx->Color._ClampFragmentColor) + if (_mesa_get_clamp_fragment_color(ctx)) COPY_4FV(v->value_float_4, ctx->Fog.Color); else COPY_4FV(v->value_float_4, ctx->Fog.ColorUnclamped); break; case GL_COLOR_CLEAR_VALUE: - if(ctx->Color._ClampFragmentColor) { + if (_mesa_get_clamp_fragment_color(ctx)) { v->value_float_4[0] = CLAMP(ctx->Color.ClearColor.f[0], 0.0F, 1.0F); v->value_float_4[1] = CLAMP(ctx->Color.ClearColor.f[1], 0.0F, 1.0F); v->value_float_4[2] = CLAMP(ctx->Color.ClearColor.f[2], 0.0F, 1.0F); @@ -782,13 +790,13 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu COPY_4FV(v->value_float_4, ctx->Color.ClearColor.f); break; case GL_BLEND_COLOR_EXT: - if(ctx->Color._ClampFragmentColor) + if (_mesa_get_clamp_fragment_color(ctx)) COPY_4FV(v->value_float_4, ctx->Color.BlendColor); else COPY_4FV(v->value_float_4, ctx->Color.BlendColorUnclamped); break; case GL_ALPHA_TEST_REF: - if(ctx->Color._ClampFragmentColor) + if (_mesa_get_clamp_fragment_color(ctx)) v->value_float = ctx->Color.AlphaRef; else v->value_float = ctx->Color.AlphaRefUnclamped; @@ -868,7 +876,7 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu * \param func name of calling glGet*v() function for error reporting * \param d the struct value_desc that has the extra constraints * - * \return GL_FALSE if one of the constraints was not satisfied, + * \return GL_FALSE if all of the constraints were not satisfied, * otherwise GL_TRUE. */ static GLboolean diff --git a/mesalib/src/mesa/main/get_hash_params.py b/mesalib/src/mesa/main/get_hash_params.py index 7d4f7e2a4..4ef23247b 100644 --- a/mesalib/src/mesa/main/get_hash_params.py +++ b/mesalib/src/mesa/main/get_hash_params.py @@ -96,7 +96,7 @@ descriptor=[ # GL_ARB_color_buffer_float [ "CLAMP_VERTEX_COLOR", "CONTEXT_ENUM(Light.ClampVertexColor), extra_ARB_color_buffer_float" ], [ "CLAMP_FRAGMENT_COLOR", "CONTEXT_ENUM(Color.ClampFragmentColor), extra_ARB_color_buffer_float" ], - [ "CLAMP_READ_COLOR", "CONTEXT_ENUM(Color.ClampReadColor), extra_ARB_color_buffer_float" ], + [ "CLAMP_READ_COLOR", "CONTEXT_ENUM(Color.ClampReadColor), extra_ARB_color_buffer_float_or_glcore" ], # GL_ARB_copy_buffer [ "COPY_READ_BUFFER", "LOC_CUSTOM, TYPE_INT, 0, NO_EXTRA" ], diff --git a/mesalib/src/mesa/main/imports.h b/mesalib/src/mesa/main/imports.h index 4b783818b..c4110ef10 100644 --- a/mesalib/src/mesa/main/imports.h +++ b/mesalib/src/mesa/main/imports.h @@ -500,17 +500,11 @@ _mesa_realloc( void *oldBuffer, size_t oldSize, size_t newSize ); #ifndef FFS_DEFINED #define FFS_DEFINED 1 #ifdef __GNUC__ - -#if defined(__MINGW32__) || defined(__CYGWIN__) || defined(ANDROID) || defined(__APPLE__) #define ffs __builtin_ffs #define ffsll __builtin_ffsll -#endif - #else - extern int ffs(int i); extern int ffsll(long long int i); - #endif /*__ GNUC__ */ #endif /* FFS_DEFINED */ diff --git a/mesalib/src/mesa/main/light.c b/mesalib/src/mesa/main/light.c index 3c43ec766..c694bebe6 100644 --- a/mesalib/src/mesa/main/light.c +++ b/mesalib/src/mesa/main/light.c @@ -1202,7 +1202,8 @@ _mesa_init_lighting( struct gl_context *ctx ) NULL ); ctx->Light.ColorMaterialEnabled = GL_FALSE; - ctx->Light.ClampVertexColor = GL_TRUE; + ctx->Light.ClampVertexColor = ctx->API == API_OPENGL_COMPAT; + ctx->Light._ClampVertexColor = ctx->API == API_OPENGL_COMPAT; /* Miscellaneous */ ctx->Light._NeedEyeCoords = GL_FALSE; diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index a0e7e281d..008f68bda 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -146,9 +146,6 @@ typedef enum * VERT_ATTRIB_TEX * include the classic texture coordinate attributes. * Is a subset of VERT_ATTRIB_FF. - * VERT_ATTRIB_GENERIC_NV - * include the NV shader attributes. - * Is a subset of VERT_ATTRIB_FF. * VERT_ATTRIB_GENERIC * include the OpenGL 2.0+ GLSL generic shader attributes. * These alias the generic GL_ARB_vertex_shader attributes. @@ -159,9 +156,6 @@ typedef enum #define VERT_ATTRIB_TEX(i) (VERT_ATTRIB_TEX0 + (i)) #define VERT_ATTRIB_TEX_MAX MAX_TEXTURE_COORD_UNITS -#define VERT_ATTRIB_GENERIC_NV(i) (VERT_ATTRIB_POS + (i)) -#define VERT_ATTRIB_GENERIC_NV_MAX MAX_VERTEX_GENERIC_ATTRIBS - #define VERT_ATTRIB_GENERIC(i) (VERT_ATTRIB_GENERIC0 + (i)) #define VERT_ATTRIB_GENERIC_MAX MAX_VERTEX_GENERIC_ATTRIBS @@ -198,10 +192,6 @@ typedef enum #define VERT_BIT_TEX_ALL \ BITFIELD64_RANGE(VERT_ATTRIB_TEX(0), VERT_ATTRIB_TEX_MAX) -#define VERT_BIT_GENERIC_NV(i) VERT_BIT(VERT_ATTRIB_GENERIC_NV(i)) -#define VERT_BIT_GENERIC_NV_ALL \ - BITFIELD64_RANGE(VERT_ATTRIB_GENERIC_NV(0), VERT_ATTRIB_GENERIC_NV_MAX) - #define VERT_BIT_GENERIC(i) VERT_BIT(VERT_ATTRIB_GENERIC(i)) #define VERT_BIT_GENERIC_ALL \ BITFIELD64_RANGE(VERT_ATTRIB_GENERIC(0), VERT_ATTRIB_GENERIC_MAX) @@ -683,7 +673,6 @@ struct gl_colorbuffer_attrib GLenum ClampFragmentColor; /**< GL_TRUE, GL_FALSE or GL_FIXED_ONLY_ARB */ GLboolean _ClampFragmentColor; /** < with GL_FIXED_ONLY_ARB resolved */ GLenum ClampReadColor; /**< GL_TRUE, GL_FALSE or GL_FIXED_ONLY_ARB */ - GLboolean _ClampReadColor; /** < with GL_FIXED_ONLY_ARB resolved */ GLboolean sRGBEnabled; /**< Framebuffer sRGB blending/updating requested */ }; @@ -1025,6 +1014,7 @@ struct gl_stencil_attrib GLboolean TestTwoSide; /**< GL_EXT_stencil_two_side */ GLubyte ActiveFace; /**< GL_EXT_stencil_two_side (0 or 2) */ GLboolean _Enabled; /**< Enabled and stencil buffer present */ + GLboolean _WriteEnabled; /**< _Enabled and non-zero writemasks */ GLboolean _TestTwoSide; GLubyte _BackFace; /**< Current back stencil state (1 or 2) */ GLenum Function[3]; /**< Stencil function */ @@ -2670,6 +2660,10 @@ struct gl_framebuffer /** Integer color values */ GLboolean _IntegerColor; + /* ARB_color_buffer_float */ + GLboolean _AllColorBuffersFixedPoint; /* no integer, no float */ + GLboolean _HasSNormOrFloatColorBuffer; + /** Array of all renderbuffer attachments, indexed by BUFFER_* tokens. */ struct gl_renderbuffer_attachment Attachment[BUFFER_COUNT]; @@ -3002,9 +2996,11 @@ struct gl_extensions GLboolean ARB_texture_float; GLboolean ARB_texture_multisample; GLboolean ARB_texture_non_power_of_two; + GLboolean ARB_texture_query_lod; GLboolean ARB_texture_rg; GLboolean ARB_texture_rgb10_a2ui; GLboolean ARB_texture_storage; + GLboolean ARB_texture_storage_multisample; GLboolean ARB_timer_query; GLboolean ARB_transform_feedback2; GLboolean ARB_transform_feedback3; diff --git a/mesalib/src/mesa/main/readpix.c b/mesalib/src/mesa/main/readpix.c index d3d09dea3..0dee38063 100644 --- a/mesalib/src/mesa/main/readpix.c +++ b/mesalib/src/mesa/main/readpix.c @@ -24,6 +24,7 @@ #include "glheader.h" #include "imports.h" +#include "blend.h" #include "bufferobj.h" #include "context.h" #include "enums.h" @@ -80,7 +81,7 @@ get_readpixels_transfer_ops(const struct gl_context *ctx, gl_format texFormat, if (uses_blit) { /* For blit-based ReadPixels packing, the clamping is done automatically * unless the type is float. */ - if (ctx->Color._ClampReadColor == GL_TRUE && + if (_mesa_get_clamp_read_color(ctx) && (type == GL_FLOAT || type == GL_HALF_FLOAT)) { transferOps |= IMAGE_CLAMP_BIT; } @@ -88,7 +89,7 @@ get_readpixels_transfer_ops(const struct gl_context *ctx, gl_format texFormat, else { /* For CPU-based ReadPixels packing, the clamping must always be done * for non-float types, */ - if (ctx->Color._ClampReadColor == GL_TRUE || + if (_mesa_get_clamp_read_color(ctx) || (type != GL_FLOAT && type != GL_HALF_FLOAT)) { transferOps |= IMAGE_CLAMP_BIT; } diff --git a/mesalib/src/mesa/main/shaderapi.c b/mesalib/src/mesa/main/shaderapi.c index be6946798..2c307e79c 100644 --- a/mesalib/src/mesa/main/shaderapi.c +++ b/mesalib/src/mesa/main/shaderapi.c @@ -518,9 +518,11 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, GLint *param GLint max_len = 0; for (i = 0; i < shProg->NumUserUniformStorage; i++) { - /* Add one for the terminating NUL character. + /* Add one for the terminating NUL character for a non-array, and + * 4 for the "[0]" and the NUL for an array. */ - const GLint len = strlen(shProg->UniformStorage[i].name) + 1; + const GLint len = strlen(shProg->UniformStorage[i].name) + 1 + + ((shProg->UniformStorage[i].array_elements != 0) ? 3 : 0); if (len > max_len) max_len = len; diff --git a/mesalib/src/mesa/main/state.c b/mesalib/src/mesa/main/state.c index fb8b71cfe..251c1aea9 100644 --- a/mesalib/src/mesa/main/state.c +++ b/mesalib/src/mesa/main/state.c @@ -51,6 +51,7 @@ #include "texobj.h" #include "texstate.h" #include "varray.h" +#include "blend.h" static void @@ -308,47 +309,6 @@ update_multisample(struct gl_context *ctx) /** - * Update the ctx->Color._ClampFragmentColor field - */ -static void -update_clamp_fragment_color(struct gl_context *ctx) -{ - if (ctx->Color.ClampFragmentColor == GL_FIXED_ONLY_ARB) - ctx->Color._ClampFragmentColor = - !ctx->DrawBuffer || !ctx->DrawBuffer->Visual.floatMode; - else - ctx->Color._ClampFragmentColor = ctx->Color.ClampFragmentColor; -} - - -/** - * Update the ctx->Color._ClampVertexColor field - */ -static void -update_clamp_vertex_color(struct gl_context *ctx) -{ - if (ctx->Light.ClampVertexColor == GL_FIXED_ONLY_ARB) - ctx->Light._ClampVertexColor = - !ctx->DrawBuffer || !ctx->DrawBuffer->Visual.floatMode; - else - ctx->Light._ClampVertexColor = ctx->Light.ClampVertexColor; -} - - -/** - * Update the ctx->Color._ClampReadColor field - */ -static void -update_clamp_read_color(struct gl_context *ctx) -{ - if (ctx->Color.ClampReadColor == GL_FIXED_ONLY_ARB) - ctx->Color._ClampReadColor = - !ctx->ReadBuffer || !ctx->ReadBuffer->Visual.floatMode; - else - ctx->Color._ClampReadColor = ctx->Color.ClampReadColor; -} - -/** * Update the ctx->VertexProgram._TwoSideEnabled flag. */ static void @@ -507,9 +467,6 @@ _mesa_update_state_locked( struct gl_context *ctx ) if (new_state & (_NEW_LIGHT | _NEW_PROGRAM)) update_twoside( ctx ); - if (new_state & (_NEW_LIGHT | _NEW_BUFFERS)) - update_clamp_vertex_color(ctx); - if (new_state & (_NEW_STENCIL | _NEW_BUFFERS)) _mesa_update_stencil( ctx ); @@ -525,12 +482,6 @@ _mesa_update_state_locked( struct gl_context *ctx ) if (new_state & (_NEW_MULTISAMPLE | _NEW_BUFFERS)) update_multisample( ctx ); - if (new_state & (_NEW_COLOR | _NEW_BUFFERS)) - update_clamp_read_color(ctx); - - if(new_state & (_NEW_FRAG_CLAMP | _NEW_BUFFERS)) - update_clamp_fragment_color(ctx); - #if 0 if (new_state & (_NEW_POINT | _NEW_LINE | _NEW_POLYGON | _NEW_LIGHT | _NEW_STENCIL | _MESA_NEW_SEPARATE_SPECULAR)) diff --git a/mesalib/src/mesa/main/stencil.c b/mesalib/src/mesa/main/stencil.c index c161808e5..330841731 100644 --- a/mesalib/src/mesa/main/stencil.c +++ b/mesalib/src/mesa/main/stencil.c @@ -551,6 +551,11 @@ _mesa_update_stencil(struct gl_context *ctx) ctx->Stencil.Ref[0] != ctx->Stencil.Ref[face] || ctx->Stencil.ValueMask[0] != ctx->Stencil.ValueMask[face] || ctx->Stencil.WriteMask[0] != ctx->Stencil.WriteMask[face]); + + ctx->Stencil._WriteEnabled = + ctx->Stencil._Enabled && + (ctx->Stencil.WriteMask[0] != 0 || + (ctx->Stencil._TestTwoSide && ctx->Stencil.WriteMask[face] != 0)); } diff --git a/mesalib/src/mesa/main/texenv.c b/mesalib/src/mesa/main/texenv.c index 0fe5fbd7a..2979e6706 100644 --- a/mesalib/src/mesa/main/texenv.c +++ b/mesalib/src/mesa/main/texenv.c @@ -32,6 +32,7 @@ #include "main/glheader.h" #include "main/context.h" +#include "main/blend.h" #include "main/enums.h" #include "main/macros.h" #include "main/mtypes.h" @@ -680,7 +681,7 @@ _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params ) if (pname == GL_TEXTURE_ENV_COLOR) { if(ctx->NewState & (_NEW_BUFFERS | _NEW_FRAG_CLAMP)) _mesa_update_state(ctx); - if(ctx->Color._ClampFragmentColor) + if (_mesa_get_clamp_fragment_color(ctx)) COPY_4FV( params, texUnit->EnvColor ); else COPY_4FV( params, texUnit->EnvColorUnclamped ); diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c index bc755ae79..784b389a7 100644 --- a/mesalib/src/mesa/main/teximage.c +++ b/mesalib/src/mesa/main/teximage.c @@ -47,6 +47,7 @@ #include "teximage.h" #include "texobj.h" #include "texstate.h" +#include "texstorage.h" #include "mtypes.h" #include "glformats.h" @@ -4194,7 +4195,8 @@ check_multisample_target(GLuint dims, GLenum target) static void teximagemultisample(GLuint dims, GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, - GLsizei depth, GLboolean fixedsamplelocations) + GLsizei depth, GLboolean fixedsamplelocations, + GLboolean immutable, const char *func) { struct gl_texture_object *texObj; struct gl_texture_image *texImage; @@ -4206,12 +4208,12 @@ teximagemultisample(GLuint dims, GLenum target, GLsizei samples, if (!(ctx->Extensions.ARB_texture_multisample && _mesa_is_desktop_gl(ctx))) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glTexImage%uDMultisample", dims); + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func); return; } if (!check_multisample_target(dims, target)) { - _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage%uDMultisample(target)", dims); + _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func); return; } @@ -4219,26 +4221,40 @@ teximagemultisample(GLuint dims, GLenum target, GLsizei samples, * refer GL3.1 spec 4.4.4 */ + if (immutable && !_mesa_is_legal_tex_storage_format(ctx, internalformat)) { + _mesa_error(ctx, GL_INVALID_ENUM, + "%s(internalformat=%s not legal for immutable-format)", + func, _mesa_lookup_enum_by_nr(internalformat)); + return; + } + if (!is_renderable_texture_format(ctx, internalformat)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glTexImage%uDMultisample(internalformat=%s)", - dims, - _mesa_lookup_enum_by_nr(internalformat)); + "%s(internalformat=%s)", + func, _mesa_lookup_enum_by_nr(internalformat)); return; } sample_count_error = _mesa_check_sample_count(ctx, target, internalformat, samples); if (sample_count_error != GL_NO_ERROR) { - _mesa_error(ctx, sample_count_error, "glTexImage%uDMultisample(samples)", dims); + _mesa_error(ctx, sample_count_error, "%s(samples)", func); return; } texObj = _mesa_get_current_tex_object(ctx, target); + + if (immutable && (!texObj || (texObj->Name == 0))) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(texture object 0)", + func); + return; + } + texImage = _mesa_get_tex_image(ctx, texObj, 0, 0); if (texImage == NULL) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage%uDMultisample()", dims); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s()", func); return; } @@ -4268,13 +4284,19 @@ teximagemultisample(GLuint dims, GLenum target, GLsizei samples, else { if (!dimensionsOK) { _mesa_error(ctx, GL_INVALID_VALUE, - "glTexImage%uDMultisample(invalid width or height)", dims); + "%s(invalid width or height)", func); return; } if (!sizeOK) { _mesa_error(ctx, GL_OUT_OF_MEMORY, - "glTexImage%uDMultisample(texture too large)", dims); + "%s(texture too large)", func); + return; + } + + /* Check if texObj->Immutable is set */ + if (texObj->Immutable) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(immutable)", func); return; } @@ -4299,6 +4321,7 @@ teximagemultisample(GLuint dims, GLenum target, GLsizei samples, } } + texObj->Immutable = immutable; _mesa_update_fbo_texture(ctx, texObj, 0, 0); } } @@ -4309,7 +4332,7 @@ _mesa_TexImage2DMultisample(GLenum target, GLsizei samples, GLsizei height, GLboolean fixedsamplelocations) { teximagemultisample(2, target, samples, internalformat, - width, height, 1, fixedsamplelocations); + width, height, 1, fixedsamplelocations, GL_FALSE, "glTexImage2DMultisample"); } void GLAPIENTRY @@ -4319,5 +4342,25 @@ _mesa_TexImage3DMultisample(GLenum target, GLsizei samples, GLboolean fixedsamplelocations) { teximagemultisample(3, target, samples, internalformat, - width, height, depth, fixedsamplelocations); + width, height, depth, fixedsamplelocations, GL_FALSE, "glTexImage3DMultisample"); +} + + +void GLAPIENTRY +_mesa_TexStorage2DMultisample(GLenum target, GLsizei samples, + GLenum internalformat, GLsizei width, + GLsizei height, GLboolean fixedsamplelocations) +{ + teximagemultisample(2, target, samples, internalformat, + width, height, 1, fixedsamplelocations, GL_TRUE, "glTexStorage2DMultisample"); +} + +void GLAPIENTRY +_mesa_TexStorage3DMultisample(GLenum target, GLsizei samples, + GLenum internalformat, GLsizei width, + GLsizei height, GLsizei depth, + GLboolean fixedsamplelocations) +{ + teximagemultisample(3, target, samples, internalformat, + width, height, depth, fixedsamplelocations, GL_TRUE, "glTexStorage3DMultisample"); } diff --git a/mesalib/src/mesa/main/teximage.h b/mesalib/src/mesa/main/teximage.h index 744c47a8a..bb295c7a7 100644 --- a/mesalib/src/mesa/main/teximage.h +++ b/mesalib/src/mesa/main/teximage.h @@ -305,6 +305,17 @@ _mesa_TexImage3DMultisample(GLenum target, GLsizei samples, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); +extern void GLAPIENTRY +_mesa_TexStorage2DMultisample(GLenum target, GLsizei samples, + GLenum internalformat, GLsizei width, + GLsizei height, GLboolean fixedsamplelocations); + +extern void GLAPIENTRY +_mesa_TexStorage3DMultisample(GLenum target, GLsizei samples, + GLenum internalformat, GLsizei width, + GLsizei height, GLsizei depth, + GLboolean fixedsamplelocations); + /*@}*/ #ifdef __cplusplus diff --git a/mesalib/src/mesa/main/texparam.c b/mesalib/src/mesa/main/texparam.c index bd2f75170..f60eb204e 100644 --- a/mesalib/src/mesa/main/texparam.c +++ b/mesalib/src/mesa/main/texparam.c @@ -31,6 +31,7 @@ #include <stdbool.h> #include "main/glheader.h" +#include "main/blend.h" #include "main/colormac.h" #include "main/context.h" #include "main/enums.h" @@ -175,6 +176,16 @@ get_texobj(struct gl_context *ctx, GLenum target, GLboolean get) return texUnit->CurrentTex[TEXTURE_CUBE_ARRAY_INDEX]; } break; + case GL_TEXTURE_2D_MULTISAMPLE: + if (ctx->Extensions.ARB_texture_storage_multisample) { + return texUnit->CurrentTex[TEXTURE_2D_MULTISAMPLE_INDEX]; + } + break; + case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: + if (ctx->Extensions.ARB_texture_storage_multisample) { + return texUnit->CurrentTex[TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX]; + } + break; default: ; } @@ -250,6 +261,20 @@ incomplete(struct gl_context *ctx, struct gl_texture_object *texObj) } +static GLboolean +target_allows_setting_sampler_parameters(GLenum target) +{ + switch (target) { + case GL_TEXTURE_2D_MULTISAMPLE: + case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: + return GL_FALSE; + + default: + return GL_TRUE; + } +} + + /** * Set an integer-valued texture parameter * \return GL_TRUE if legal AND the value changed, GL_FALSE otherwise @@ -261,6 +286,9 @@ set_tex_parameteri(struct gl_context *ctx, { switch (pname) { case GL_TEXTURE_MIN_FILTER: + if (!target_allows_setting_sampler_parameters(texObj->Target)) + goto invalid_operation; + if (texObj->Sampler.MinFilter == params[0]) return GL_FALSE; switch (params[0]) { @@ -286,6 +314,9 @@ set_tex_parameteri(struct gl_context *ctx, return GL_FALSE; case GL_TEXTURE_MAG_FILTER: + if (!target_allows_setting_sampler_parameters(texObj->Target)) + goto invalid_operation; + if (texObj->Sampler.MagFilter == params[0]) return GL_FALSE; switch (params[0]) { @@ -300,6 +331,9 @@ set_tex_parameteri(struct gl_context *ctx, return GL_FALSE; case GL_TEXTURE_WRAP_S: + if (!target_allows_setting_sampler_parameters(texObj->Target)) + goto invalid_operation; + if (texObj->Sampler.WrapS == params[0]) return GL_FALSE; if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) { @@ -310,6 +344,9 @@ set_tex_parameteri(struct gl_context *ctx, return GL_FALSE; case GL_TEXTURE_WRAP_T: + if (!target_allows_setting_sampler_parameters(texObj->Target)) + goto invalid_operation; + if (texObj->Sampler.WrapT == params[0]) return GL_FALSE; if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) { @@ -320,6 +357,9 @@ set_tex_parameteri(struct gl_context *ctx, return GL_FALSE; case GL_TEXTURE_WRAP_R: + if (!target_allows_setting_sampler_parameters(texObj->Target)) + goto invalid_operation; + if (texObj->Sampler.WrapR == params[0]) return GL_FALSE; if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) { @@ -335,6 +375,11 @@ set_tex_parameteri(struct gl_context *ctx, if (texObj->BaseLevel == params[0]) return GL_FALSE; + + if ((texObj->Target == GL_TEXTURE_2D_MULTISAMPLE || + texObj->Target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) && params[0] != 0) + goto invalid_operation; + if (params[0] < 0 || (texObj->Target == GL_TEXTURE_RECTANGLE_ARB && params[0] != 0)) { _mesa_error(ctx, GL_INVALID_VALUE, @@ -348,6 +393,7 @@ set_tex_parameteri(struct gl_context *ctx, case GL_TEXTURE_MAX_LEVEL: if (texObj->MaxLevel == params[0]) return GL_FALSE; + if (params[0] < 0 || texObj->Target == GL_TEXTURE_RECTANGLE_ARB) { _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param=%d)", params[0]); @@ -373,6 +419,10 @@ set_tex_parameteri(struct gl_context *ctx, case GL_TEXTURE_COMPARE_MODE_ARB: if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_shadow) || _mesa_is_gles3(ctx)) { + + if (!target_allows_setting_sampler_parameters(texObj->Target)) + goto invalid_operation; + if (texObj->Sampler.CompareMode == params[0]) return GL_FALSE; if (params[0] == GL_NONE || @@ -388,6 +438,10 @@ set_tex_parameteri(struct gl_context *ctx, case GL_TEXTURE_COMPARE_FUNC_ARB: if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_shadow) || _mesa_is_gles3(ctx)) { + + if (!target_allows_setting_sampler_parameters(texObj->Target)) + goto invalid_operation; + if (texObj->Sampler.CompareFunc == params[0]) return GL_FALSE; switch (params[0]) { @@ -489,7 +543,11 @@ set_tex_parameteri(struct gl_context *ctx, case GL_TEXTURE_SRGB_DECODE_EXT: if (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_sRGB_decode) { - GLenum decode = params[0]; + GLenum decode = params[0]; + + if (!target_allows_setting_sampler_parameters(texObj->Target)) + goto invalid_operation; + if (decode == GL_DECODE_EXT || decode == GL_SKIP_DECODE_EXT) { if (texObj->Sampler.sRGBDecode != decode) { flush(ctx); @@ -504,6 +562,10 @@ set_tex_parameteri(struct gl_context *ctx, if (_mesa_is_desktop_gl(ctx) && ctx->Extensions.AMD_seamless_cubemap_per_texture) { GLenum param = params[0]; + + if (!target_allows_setting_sampler_parameters(texObj->Target)) + goto invalid_operation; + if (param != GL_TRUE && param != GL_FALSE) { goto invalid_param; } @@ -528,6 +590,11 @@ invalid_param: _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(param=%s)", _mesa_lookup_enum_by_nr(params[0])); return GL_FALSE; + +invalid_operation: + _mesa_error(ctx, GL_INVALID_OPERATION, "glTexParameter(pname=%s)", + _mesa_lookup_enum_by_nr(pname)); + return GL_FALSE; } @@ -545,6 +612,9 @@ set_tex_parameterf(struct gl_context *ctx, if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) goto invalid_pname; + if (!target_allows_setting_sampler_parameters(texObj->Target)) + goto invalid_operation; + if (texObj->Sampler.MinLod == params[0]) return GL_FALSE; flush(ctx); @@ -555,6 +625,9 @@ set_tex_parameterf(struct gl_context *ctx, if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) goto invalid_pname; + if (!target_allows_setting_sampler_parameters(texObj->Target)) + goto invalid_operation; + if (texObj->Sampler.MaxLod == params[0]) return GL_FALSE; flush(ctx); @@ -571,6 +644,9 @@ set_tex_parameterf(struct gl_context *ctx, case GL_TEXTURE_MAX_ANISOTROPY_EXT: if (ctx->Extensions.EXT_texture_filter_anisotropic) { + if (!target_allows_setting_sampler_parameters(texObj->Target)) + goto invalid_operation; + if (texObj->Sampler.MaxAnisotropy == params[0]) return GL_FALSE; if (params[0] < 1.0) { @@ -598,6 +674,9 @@ set_tex_parameterf(struct gl_context *ctx, if (ctx->API != API_OPENGL_COMPAT) goto invalid_pname; + if (!target_allows_setting_sampler_parameters(texObj->Target)) + goto invalid_operation; + if (texObj->Sampler.LodBias != params[0]) { flush(ctx); texObj->Sampler.LodBias = params[0]; @@ -609,6 +688,9 @@ set_tex_parameterf(struct gl_context *ctx, if (!_mesa_is_desktop_gl(ctx)) goto invalid_pname; + if (!target_allows_setting_sampler_parameters(texObj->Target)) + goto invalid_operation; + flush(ctx); /* ARB_texture_float disables clamping */ if (ctx->Extensions.ARB_texture_float) { @@ -633,6 +715,11 @@ invalid_pname: _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=%s)", _mesa_lookup_enum_by_nr(pname)); return GL_FALSE; + +invalid_operation: + _mesa_error(ctx, GL_INVALID_OPERATION, "glTexParameter(pname=%s)", + _mesa_lookup_enum_by_nr(pname)); + return GL_FALSE; } @@ -1329,7 +1416,7 @@ _mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params ) if (ctx->NewState & (_NEW_BUFFERS | _NEW_FRAG_CLAMP)) _mesa_update_state_locked(ctx); - if (ctx->Color._ClampFragmentColor) { + if (_mesa_get_clamp_fragment_color(ctx)) { params[0] = CLAMP(obj->Sampler.BorderColor.f[0], 0.0F, 1.0F); params[1] = CLAMP(obj->Sampler.BorderColor.f[1], 0.0F, 1.0F); params[2] = CLAMP(obj->Sampler.BorderColor.f[2], 0.0F, 1.0F); diff --git a/mesalib/src/mesa/main/texstorage.c b/mesalib/src/mesa/main/texstorage.c index 675fd745b..6309b5716 100644 --- a/mesalib/src/mesa/main/texstorage.c +++ b/mesalib/src/mesa/main/texstorage.c @@ -202,20 +202,9 @@ clear_texture_fields(struct gl_context *ctx, } -/** - * Do error checking for calls to glTexStorage1/2/3D(). - * If an error is found, record it with _mesa_error(), unless the target - * is a proxy texture. - * \return GL_TRUE if any error, GL_FALSE otherwise. - */ -static GLboolean -tex_storage_error_check(struct gl_context *ctx, GLuint dims, GLenum target, - GLsizei levels, GLenum internalformat, - GLsizei width, GLsizei height, GLsizei depth) +GLboolean +_mesa_is_legal_tex_storage_format(struct gl_context *ctx, GLenum internalformat) { - struct gl_texture_object *texObj; - GLboolean legalFormat; - /* check internal format - note that only sized formats are allowed */ switch (internalformat) { case GL_ALPHA: @@ -250,13 +239,27 @@ tex_storage_error_check(struct gl_context *ctx, GLuint dims, GLenum target, case GL_LUMINANCE_INTEGER_EXT: case GL_LUMINANCE_ALPHA_INTEGER_EXT: /* these unsized formats are illegal */ - legalFormat = GL_FALSE; - break; + return GL_FALSE; default: - legalFormat = _mesa_base_tex_format(ctx, internalformat) > 0; + return _mesa_base_tex_format(ctx, internalformat) > 0; } +} + + +/** + * Do error checking for calls to glTexStorage1/2/3D(). + * If an error is found, record it with _mesa_error(), unless the target + * is a proxy texture. + * \return GL_TRUE if any error, GL_FALSE otherwise. + */ +static GLboolean +tex_storage_error_check(struct gl_context *ctx, GLuint dims, GLenum target, + GLsizei levels, GLenum internalformat, + GLsizei width, GLsizei height, GLsizei depth) +{ + struct gl_texture_object *texObj; - if (!legalFormat) { + if (!_mesa_is_legal_tex_storage_format(ctx, internalformat)) { _mesa_error(ctx, GL_INVALID_ENUM, "glTexStorage%uD(internalformat = %s)", dims, _mesa_lookup_enum_by_nr(internalformat)); diff --git a/mesalib/src/mesa/main/texstorage.h b/mesalib/src/mesa/main/texstorage.h index 99382df51..9f172e1ca 100644 --- a/mesalib/src/mesa/main/texstorage.h +++ b/mesalib/src/mesa/main/texstorage.h @@ -57,5 +57,8 @@ _mesa_TextureStorage3DEXT(GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +extern GLboolean +_mesa_is_legal_tex_storage_format(struct gl_context *ctx, GLenum internalformat); + #endif /* TEXSTORAGE_H */ diff --git a/mesalib/src/mesa/main/version.c b/mesalib/src/mesa/main/version.c index 8c8192595..c4ae2a6ce 100644 --- a/mesalib/src/mesa/main/version.c +++ b/mesalib/src/mesa/main/version.c @@ -233,7 +233,8 @@ compute_version(struct gl_context *ctx) const GLboolean ver_3_0 = (ver_2_1 && ctx->Const.GLSLVersion >= 130 && ctx->Const.MaxSamples >= 4 && - ctx->Extensions.ARB_color_buffer_float && + (ctx->API == API_OPENGL_CORE || + ctx->Extensions.ARB_color_buffer_float) && ctx->Extensions.ARB_depth_buffer_float && ctx->Extensions.ARB_half_float_pixel && ctx->Extensions.ARB_half_float_vertex && diff --git a/mesalib/src/mesa/program/ir_to_mesa.cpp b/mesalib/src/mesa/program/ir_to_mesa.cpp index 2cb5f02f4..14cf5baa7 100644 --- a/mesalib/src/mesa/program/ir_to_mesa.cpp +++ b/mesalib/src/mesa/program/ir_to_mesa.cpp @@ -2048,6 +2048,9 @@ ir_to_mesa_visitor::visit(ir_texture *ir) case ir_txf_ms: assert(!"Unexpected ir_txf_ms opcode"); break; + case ir_lod: + assert(!"Unexpected ir_lod opcode"); + break; } const glsl_type *sampler_type = ir->sampler->type; diff --git a/mesalib/src/mesa/program/prog_cache.c b/mesalib/src/mesa/program/prog_cache.c index 47f926b1b..1f1c6142d 100644 --- a/mesalib/src/mesa/program/prog_cache.c +++ b/mesalib/src/mesa/program/prog_cache.c @@ -37,6 +37,7 @@ struct cache_item { GLuint hash; + unsigned keysize; void *key; struct gl_program *program; struct cache_item *next; @@ -174,7 +175,8 @@ struct gl_program * _mesa_search_program_cache(struct gl_program_cache *cache, const void *key, GLuint keysize) { - if (cache->last && + if (cache->last && + cache->last->keysize == keysize && memcmp(cache->last->key, key, keysize) == 0) { return cache->last->program; } @@ -183,7 +185,10 @@ _mesa_search_program_cache(struct gl_program_cache *cache, struct cache_item *c; for (c = cache->items[hash % cache->size]; c; c = c->next) { - if (c->hash == hash && memcmp(c->key, key, keysize) == 0) { + if (c->hash == hash && + c->keysize == keysize && + memcmp(c->key, key, keysize) == 0) { + cache->last = c; return c->program; } @@ -207,6 +212,7 @@ _mesa_program_cache_insert(struct gl_context *ctx, c->key = malloc(keysize); memcpy(c->key, key, keysize); + c->keysize = keysize; c->program = program; /* no refcount change */ @@ -235,6 +241,7 @@ _mesa_shader_cache_insert(struct gl_context *ctx, c->key = malloc(keysize); memcpy(c->key, key, keysize); + c->keysize = keysize; c->program = (struct gl_program *)program; /* no refcount change */ diff --git a/mesalib/src/mesa/program/prog_statevars.c b/mesalib/src/mesa/program/prog_statevars.c index 5a350798c..09d2a568a 100644 --- a/mesalib/src/mesa/program/prog_statevars.c +++ b/mesalib/src/mesa/program/prog_statevars.c @@ -31,6 +31,7 @@ #include "main/glheader.h" #include "main/context.h" +#include "main/blend.h" #include "main/imports.h" #include "main/macros.h" #include "main/mtypes.h" @@ -239,14 +240,14 @@ _mesa_fetch_state(struct gl_context *ctx, const gl_state_index state[], { /* state[1] is the texture unit */ const GLuint unit = (GLuint) state[1]; - if(ctx->Color._ClampFragmentColor) + if (_mesa_get_clamp_fragment_color(ctx)) COPY_4V(value, ctx->Texture.Unit[unit].EnvColor); else COPY_4V(value, ctx->Texture.Unit[unit].EnvColorUnclamped); } return; case STATE_FOG_COLOR: - if(ctx->Color._ClampFragmentColor) + if (_mesa_get_clamp_fragment_color(ctx)) COPY_4V(value, ctx->Fog.Color); else COPY_4V(value, ctx->Fog.ColorUnclamped); @@ -871,6 +872,9 @@ append_token(char *dst, gl_state_index k) case STATE_CURRENT_ATTRIB: append(dst, "current"); break; + case STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED: + append(dst, "currentAttribMaybeVPClamped"); + break; case STATE_NORMAL_SCALE: append(dst, "normalScale"); break; diff --git a/mesalib/src/mesa/program/register_allocate.c b/mesalib/src/mesa/program/register_allocate.c index a9064c38c..2c826fc66 100644 --- a/mesalib/src/mesa/program/register_allocate.c +++ b/mesalib/src/mesa/program/register_allocate.c @@ -70,6 +70,7 @@ * this during ra_set_finalize(). */ +#include <stdbool.h> #include <ralloc.h> #include "main/imports.h" @@ -93,6 +94,8 @@ struct ra_regs { struct ra_class **classes; unsigned int class_count; + + bool round_robin; }; struct ra_class { @@ -185,6 +188,22 @@ ra_alloc_reg_set(void *mem_ctx, unsigned int count) return regs; } +/** + * The register allocator by default prefers to allocate low register numbers, + * since it was written for hardware (gen4/5 Intel) that is limited in its + * multithreadedness by the number of registers used in a given shader. + * + * However, for hardware without that restriction, densely packed register + * allocation can put serious constraints on instruction scheduling. This + * function tells the allocator to rotate around the registers if possible as + * it allocates the nodes. + */ +void +ra_set_allocate_round_robin(struct ra_regs *regs) +{ + regs->round_robin = true; +} + static void ra_add_conflict_list(struct ra_regs *regs, unsigned int r1, unsigned int r2) { @@ -436,16 +455,19 @@ GLboolean ra_select(struct ra_graph *g) { int i; + int start_search_reg = 0; while (g->stack_count != 0) { - unsigned int r; + unsigned int ri; + unsigned int r = -1; int n = g->stack[g->stack_count - 1]; struct ra_class *c = g->regs->classes[g->nodes[n].class]; /* Find the lowest-numbered reg which is not used by a member * of the graph adjacent to us. */ - for (r = 0; r < g->regs->count; r++) { + for (ri = 0; ri < g->regs->count; ri++) { + r = (start_search_reg + ri) % g->regs->count; if (!c->regs[r]) continue; @@ -461,12 +483,15 @@ ra_select(struct ra_graph *g) if (i == g->nodes[n].adjacency_count) break; } - if (r == g->regs->count) + if (ri == g->regs->count) return GL_FALSE; g->nodes[n].reg = r; g->nodes[n].in_stack = GL_FALSE; g->stack_count--; + + if (g->regs->round_robin) + start_search_reg = r + 1; } return GL_TRUE; diff --git a/mesalib/src/mesa/program/register_allocate.h b/mesalib/src/mesa/program/register_allocate.h index 2a9d61191..fa119e320 100644 --- a/mesalib/src/mesa/program/register_allocate.h +++ b/mesalib/src/mesa/program/register_allocate.h @@ -37,6 +37,7 @@ struct ra_regs; * two real registers from which they are composed. */ struct ra_regs *ra_alloc_reg_set(void *mem_ctx, unsigned int count); +void ra_set_allocate_round_robin(struct ra_regs *regs); unsigned int ra_alloc_reg_class(struct ra_regs *regs); void ra_add_reg_conflict(struct ra_regs *regs, unsigned int r1, unsigned int r2); diff --git a/mesalib/src/mesa/state_tracker/st_atom_constbuf.c b/mesalib/src/mesa/state_tracker/st_atom_constbuf.c index 961fb28a9..56ba96fe3 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_constbuf.c +++ b/mesalib/src/mesa/state_tracker/st_atom_constbuf.c @@ -39,6 +39,7 @@ #include "pipe/p_defines.h" #include "util/u_inlines.h" #include "util/u_upload_mgr.h" +#include "cso_cache/cso_context.h" #include "st_debug.h" #include "st_context.h" @@ -96,16 +97,17 @@ void st_upload_constants( struct st_context *st, _mesa_print_parameter_list(params); } - st->pipe->set_constant_buffer(st->pipe, shader_type, 0, &cb); + cso_set_constant_buffer(st->cso_context, shader_type, 0, &cb); pipe_resource_reference(&cb.buffer, NULL); st->state.constants[shader_type].ptr = params->ParameterValues; st->state.constants[shader_type].size = paramBytes; } else if (st->state.constants[shader_type].ptr) { + /* Unbind. */ st->state.constants[shader_type].ptr = NULL; st->state.constants[shader_type].size = 0; - st->pipe->set_constant_buffer(st->pipe, shader_type, 0, NULL); + cso_set_constant_buffer(st->cso_context, shader_type, 0, NULL); } } @@ -196,7 +198,7 @@ static void st_bind_ubos(struct st_context *st, cb.buffer_size = st_obj->buffer->width0 - binding->Offset; - st->pipe->set_constant_buffer(st->pipe, shader_type, 1 + i, &cb); + cso_set_constant_buffer(st->cso_context, shader_type, 1 + i, &cb); pipe_resource_reference(&cb.buffer, NULL); } } diff --git a/mesalib/src/mesa/state_tracker/st_atom_rasterizer.c b/mesalib/src/mesa/state_tracker/st_atom_rasterizer.c index 866e5627d..62464b475 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_rasterizer.c +++ b/mesalib/src/mesa/state_tracker/st_atom_rasterizer.c @@ -227,8 +227,7 @@ static void update_raster_state( struct st_context *st ) /* _NEW_FRAG_CLAMP */ raster->clamp_fragment_color = !st->clamp_frag_color_in_shader && - ctx->Color._ClampFragmentColor && - !ctx->DrawBuffer->_IntegerColor; + ctx->Color._ClampFragmentColor; raster->gl_rasterization_rules = 1; /* _NEW_RASTERIZER_DISCARD */ diff --git a/mesalib/src/mesa/state_tracker/st_atom_shader.c b/mesalib/src/mesa/state_tracker/st_atom_shader.c index c1d7c80bb..c0239e929 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_shader.c +++ b/mesalib/src/mesa/state_tracker/st_atom_shader.c @@ -86,8 +86,7 @@ update_fp( struct st_context *st ) /* _NEW_FRAG_CLAMP */ key.clamp_color = st->clamp_frag_color_in_shader && - st->ctx->Color._ClampFragmentColor && - !st->ctx->DrawBuffer->_IntegerColor; + st->ctx->Color._ClampFragmentColor; st->fp_variant = st_get_fp_variant(st, stfp, &key); diff --git a/mesalib/src/mesa/state_tracker/st_cb_bitmap.c b/mesalib/src/mesa/state_tracker/st_cb_bitmap.c index bae9ff858..b3ca40501 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_bitmap.c +++ b/mesalib/src/mesa/state_tracker/st_cb_bitmap.c @@ -417,8 +417,7 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, key.st = st; key.bitmap = GL_TRUE; key.clamp_color = st->clamp_frag_color_in_shader && - st->ctx->Color._ClampFragmentColor && - !st->ctx->DrawBuffer->_IntegerColor; + st->ctx->Color._ClampFragmentColor; fpv = st_get_fp_variant(st, st->fp, &key); @@ -766,6 +765,7 @@ st_Bitmap(struct gl_context *ctx, GLint x, GLint y, /* create pass-through vertex shader now */ const uint semantic_names[] = { TGSI_SEMANTIC_POSITION, TGSI_SEMANTIC_COLOR, + st->needs_texcoord_semantic ? TGSI_SEMANTIC_TEXCOORD : TGSI_SEMANTIC_GENERIC }; const uint semantic_indexes[] = { 0, 0, 0 }; st->bitmap.vs = util_make_vertex_passthrough_shader(st->pipe, 3, diff --git a/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c b/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c index f0baa3435..f5a1e27f7 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c @@ -294,6 +294,9 @@ static void * make_passthrough_vertex_shader(struct st_context *st, GLboolean passColor) { + const unsigned texcoord_semantic = st->needs_texcoord_semantic ? + TGSI_SEMANTIC_TEXCOORD : TGSI_SEMANTIC_GENERIC; + if (!st->drawpix.vert_shaders[passColor]) { struct ureg_program *ureg = ureg_create( TGSI_PROCESSOR_VERTEX ); @@ -307,7 +310,7 @@ make_passthrough_vertex_shader(struct st_context *st, /* MOV result.texcoord0, vertex.attr[1]; */ ureg_MOV(ureg, - ureg_DECL_output( ureg, TGSI_SEMANTIC_GENERIC, 0 ), + ureg_DECL_output( ureg, texcoord_semantic, 0 ), ureg_DECL_vs_input( ureg, 1 )); if (passColor) { @@ -707,8 +710,7 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, struct pipe_rasterizer_state rasterizer; memset(&rasterizer, 0, sizeof(rasterizer)); rasterizer.clamp_fragment_color = !st->clamp_frag_color_in_shader && - ctx->Color._ClampFragmentColor && - !ctx->DrawBuffer->_IntegerColor; + ctx->Color._ClampFragmentColor; rasterizer.gl_rasterization_rules = 1; rasterizer.depth_clip = !ctx->Transform.DepthClamp; rasterizer.scissor = ctx->Scissor.Enabled; @@ -1034,8 +1036,7 @@ get_color_fp_variant(struct st_context *st) ctx->Pixel.AlphaScale != 1.0); key.pixelMaps = ctx->Pixel.MapColorFlag; key.clamp_color = st->clamp_frag_color_in_shader && - st->ctx->Color._ClampFragmentColor && - !st->ctx->DrawBuffer->_IntegerColor; + st->ctx->Color._ClampFragmentColor; fpv = st_get_fp_variant(st, st->fp, &key); diff --git a/mesalib/src/mesa/state_tracker/st_cb_drawtex.c b/mesalib/src/mesa/state_tracker/st_cb_drawtex.c index a8806c91e..c4efce02f 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_drawtex.c +++ b/mesalib/src/mesa/state_tracker/st_cb_drawtex.c @@ -209,7 +209,9 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z, SET_ATTRIB(2, attr, s1, t1, 0.0f, 1.0f); /* upper right */ SET_ATTRIB(3, attr, s0, t1, 0.0f, 1.0f); /* upper left */ - semantic_names[attr] = TGSI_SEMANTIC_GENERIC; + semantic_names[attr] = st->needs_texcoord_semantic ? + TGSI_SEMANTIC_TEXCOORD : TGSI_SEMANTIC_GENERIC; + /* XXX: should this use semantic index i instead of 0 ? */ semantic_indexes[attr] = 0; attr++; diff --git a/mesalib/src/mesa/state_tracker/st_cb_readpixels.c b/mesalib/src/mesa/state_tracker/st_cb_readpixels.c index bfed98870..9fab113fa 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_readpixels.c +++ b/mesalib/src/mesa/state_tracker/st_cb_readpixels.c @@ -133,7 +133,6 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, !screen->is_format_supported(screen, src_format, src->target, src->nr_samples, PIPE_BIND_SAMPLER_VIEW)) { - printf("fallback: src format unsupported %s\n", util_format_short_name(src_format)); goto fallback; } @@ -147,8 +146,6 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, dst_format = st_choose_matching_format(screen, bind, format, type, pack->SwapBytes); if (dst_format == PIPE_FORMAT_NONE) { - printf("fallback: no matching format for %s, %s\n", - _mesa_lookup_enum_by_nr(format), _mesa_lookup_enum_by_nr(type)); goto fallback; } diff --git a/mesalib/src/mesa/state_tracker/st_cb_texture.c b/mesalib/src/mesa/state_tracker/st_cb_texture.c index 94fbbf7be..0cd0d77af 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_texture.c +++ b/mesalib/src/mesa/state_tracker/st_cb_texture.c @@ -868,7 +868,7 @@ st_GetTexImage(struct gl_context * ctx, goto fallback; } - if (!stImage->pt) { + if (!stImage->pt || !src) { goto fallback; } diff --git a/mesalib/src/mesa/state_tracker/st_extensions.c b/mesalib/src/mesa/state_tracker/st_extensions.c index 11db9d3f3..2d8b9efec 100644 --- a/mesalib/src/mesa/state_tracker/st_extensions.c +++ b/mesalib/src/mesa/state_tracker/st_extensions.c @@ -629,6 +629,7 @@ void st_init_extensions(struct st_context *st) ctx->Const.PrimitiveRestartInSoftware = GL_TRUE; } + /* ARB_color_buffer_float. */ if (screen->get_param(screen, PIPE_CAP_VERTEX_COLOR_UNCLAMPED)) { ctx->Extensions.ARB_color_buffer_float = GL_TRUE; @@ -639,6 +640,16 @@ void st_init_extensions(struct st_context *st) if (!screen->get_param(screen, PIPE_CAP_FRAGMENT_COLOR_CLAMPED)) { st->clamp_frag_color_in_shader = TRUE; } + + /* For drivers which cannot do color clamping, it's better to just + * disable ARB_color_buffer_float in the core profile, because + * the clamping is deprecated there anyway. */ + if (ctx->API == API_OPENGL_CORE && + (st->clamp_frag_color_in_shader || st->clamp_vert_color_in_shader)) { + st->clamp_vert_color_in_shader = GL_FALSE; + st->clamp_frag_color_in_shader = GL_FALSE; + ctx->Extensions.ARB_color_buffer_float = GL_FALSE; + } } if (screen->fence_finish) { diff --git a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp index e3718eeda..338c652cb 100644 --- a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -1009,7 +1009,9 @@ glsl_to_tgsi_visitor::get_temp(const glsl_type *type) src.reladdr = NULL; src.negate = 0; - if (type->is_array() || type->is_matrix()) { + if (!options->EmitNoIndirectTemp && + (type->is_array() || type->is_matrix())) { + src.file = PROGRAM_ARRAY; src.index = next_array << 16 | 0x8000; array_sizes[next_array] = type_size(type); @@ -2772,6 +2774,9 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir) case ir_txf_ms: assert(!"Unexpected ir_txf_ms opcode"); break; + case ir_lod: + assert(!"Unexpected ir_lod opcode"); + break; } if (ir->projector) { @@ -3191,7 +3196,7 @@ glsl_to_tgsi_visitor::simplify_cmp(void) prevWriteMask = tempWrites[inst->dst.index]; tempWrites[inst->dst.index] |= inst->dst.writemask; } else - break; + continue; /* For a CMP to be considered a conditional write, the destination * register and source register two must be the same. */ diff --git a/mesalib/src/mesa/state_tracker/st_manager.c b/mesalib/src/mesa/state_tracker/st_manager.c index 0b025d9d5..03e086a72 100644 --- a/mesalib/src/mesa/state_tracker/st_manager.c +++ b/mesalib/src/mesa/state_tracker/st_manager.c @@ -170,9 +170,8 @@ st_context_validate(struct st_context *st, /** * Validate a framebuffer to make sure up-to-date pipe_textures are used. - * The context we need to pass in is s dummy context needed only to be - * able to get a pipe context to create pipe surfaces, and to have a - * context to call _mesa_resize_framebuffer(): + * The context is only used for creating pipe surfaces and for calling + * _mesa_resize_framebuffer(). * (That should probably be rethought, since those surfaces become * drawable state, not context state, and can be freed by another pipe * context). diff --git a/mesalib/src/mesa/swrast/s_blit.c b/mesalib/src/mesa/swrast/s_blit.c index 82fa43f1c..051354dc8 100644 --- a/mesalib/src/mesa/swrast/s_blit.c +++ b/mesalib/src/mesa/swrast/s_blit.c @@ -110,8 +110,8 @@ blit_nearest(struct gl_context *ctx, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield buffer) { - struct gl_renderbuffer *readRb, *drawRb; - struct gl_renderbuffer_attachment *readAtt, *drawAtt; + struct gl_renderbuffer *readRb, *drawRb = NULL; + struct gl_renderbuffer_attachment *readAtt = NULL, *drawAtt = NULL; struct gl_framebuffer *readFb = ctx->ReadBuffer; struct gl_framebuffer *drawFb = ctx->DrawBuffer; GLuint numDrawBuffers = 0; @@ -135,12 +135,12 @@ blit_nearest(struct gl_context *ctx, UNPACK_Z_FLOAT, UNPACK_Z_INT, UNPACK_S, - } mode; + } mode = DIRECT; GLubyte *srcMap, *dstMap; GLint srcRowStride, dstRowStride; GLint dstRow; - GLint pixelSize; + GLint pixelSize = 0; GLvoid *srcBuffer, *dstBuffer; GLint prevY = -1; |