diff options
344 files changed, 19774 insertions, 11147 deletions
@@ -345,7 +345,9 @@ DRI_FILES = \ $(DIRECTORY)/src/mesa/drivers/dri/common/xmlpool/*.[ch] \ $(DIRECTORY)/src/mesa/drivers/dri/common/xmlpool/*.po \ $(DIRECTORY)/src/mesa/drivers/dri/*/*.[chS] \ + $(DIRECTORY)/src/mesa/drivers/dri/*/*/*.[chS] \ $(DIRECTORY)/src/mesa/drivers/dri/*/Makefile \ + $(DIRECTORY)/src/mesa/drivers/dri/*/*/Makefile \ $(DIRECTORY)/src/mesa/drivers/dri/*/Doxyfile \ $(DIRECTORY)/src/mesa/drivers/dri/*/server/*.[ch] @@ -425,6 +427,7 @@ DEMO_FILES = \ $(DIRECTORY)/progs/glsl/*.c \ $(DIRECTORY)/progs/glsl/*.frag \ $(DIRECTORY)/progs/glsl/*.vert \ + $(DIRECTORY)/progs/glsl/*.shtest \ $(DIRECTORY)/progs/windml/Makefile.ugl \ $(DIRECTORY)/progs/windml/*.c \ $(DIRECTORY)/progs/windml/*.bmp \ @@ -971,5 +971,6 @@ esac # if [ ${INSTALLDIR} != "." ] ; then echo "mklib: Installing" ${FINAL_LIBS} "in" ${INSTALLDIR} + test -d ${INSTALLDIR} || mkdir -p ${INSTALLDIR} mv ${FINAL_LIBS} ${INSTALLDIR}/ fi diff --git a/configure.ac b/configure.ac index 9b65d96b39..9d318b3fc2 100644 --- a/configure.ac +++ b/configure.ac @@ -1159,6 +1159,21 @@ AC_ARG_WITH([xorg-driver-dir], [XORG_DRIVER_INSTALL_DIR="${libdir}/xorg/modules/drivers"]) AC_SUBST([XORG_DRIVER_INSTALL_DIR]) +AC_ARG_WITH([max-width], + [AS_HELP_STRING([--with-max-width=N], + [Maximum framebuffer width (4096)])], + [DEFINES="${DEFINES} -DMAX_WIDTH=${withval}"; + AS_IF([test "${withval}" -gt "4096"], + [AC_MSG_WARN([Large framebuffer: see s_tritemp.h comments.])])] +) +AC_ARG_WITH([max-height], + [AS_HELP_STRING([--with-max-height=N], + [Maximum framebuffer height (4096)])], + [DEFINES="${DEFINES} -DMAX_HEIGHT=${withval}"; + AS_IF([test "${withval}" -gt "4096"], + [AC_MSG_WARN([Large framebuffer: see s_tritemp.h comments.])])] +) + dnl dnl Gallium Intel configuration dnl diff --git a/docs/faq.html b/docs/faq.html index 11b5d43255..65e279aac5 100644 --- a/docs/faq.html +++ b/docs/faq.html @@ -316,6 +316,19 @@ Basically, applying a translation of (0.375, 0.375, 0.0) to your coordinates will fix the problem. </p> +<h2>3.6 How can I change the maximum framebuffer size in Mesa's +<tt>swrast</tt> backend?</h2> +<p> +These can be overridden by using the <tt>--with-max-width</tt> and +<tt>--with-max-height</tt> options. The two need not be equal. +</p><p> +Do note that Mesa uses these values to size some internal buffers, +so increasing these sizes will cause Mesa to require additional +memory. Furthermore, increasing these limits beyond <tt>4096</tt> +may introduce rasterization artifacts; see the leading comments in +<tt>src/mesa/swrast/s_tritemp.h</tt>. +</p> + <br> <br> diff --git a/docs/relnotes-7.5.1.html b/docs/relnotes-7.5.1.html index 0f475ad2b4..1da086de3b 100644 --- a/docs/relnotes-7.5.1.html +++ b/docs/relnotes-7.5.1.html @@ -37,12 +37,19 @@ tbd <h2>New features</h2> <ul> +<li>Added configure --with-max-width=W, --with-max-height=H options to specify + max framebuffer, viewport size. </ul> <h2>Bug fixes</h2> <ul> <li>Added missing GLEW library to MesaDemos tarballs. +<li>Fixed swapbuffers jerkiness in Doom3/etc in Intel drivers. +<li>Fixed front buffer rendering bug in Intel drivers. +<li>Fixed minor GLX memory leaks. +<li>Fixed some texture env / fragment program state bugs. +<li>Fixed some Gallium glBlitFramebuffer() bugs </ul> diff --git a/docs/relnotes-7.6.html b/docs/relnotes-7.6.html index 560d50d0d6..691c0f04ca 100644 --- a/docs/relnotes-7.6.html +++ b/docs/relnotes-7.6.html @@ -48,6 +48,8 @@ This was written by Zack Rusin at Tungsten Graphics. <li>r300 driver support for GL_EXT_vertex_array_bgra, GL_EXT_texture_sRGB <li>i915/945 driver support for GL_ARB_point_sprite, GL_EXT_stencil_two_side and GL_ATI_separate_stencil extensions +<li>Added configure --with-max-width=W, --with-max-height=H options to specify + max framebuffer, viewport size. </ul> diff --git a/include/GL/glext.h b/include/GL/glext.h index 5429287d3f..24e6c5dc80 100644 --- a/include/GL/glext.h +++ b/include/GL/glext.h @@ -29,9 +29,9 @@ extern "C" { */ /* Header file version number, required by OpenGL ABI for Linux */ -/* glext.h last updated $Date: 2009-05-05 15:27:42 -0700 (Tue, 05 May 2009) $ */ +/* glext.h last updated $Date: 2009-08-03 02:13:51 -0700 (Mon, 03 Aug 2009) $ */ /* Current version at http://www.opengl.org/registry/ */ -#define GL_GLEXT_VERSION 52 +#define GL_GLEXT_VERSION 54 /* Function declaration macros - to move into glplatform.h */ @@ -510,6 +510,8 @@ extern "C" { #define GL_CLIP_DISTANCE3 0x3003 #define GL_CLIP_DISTANCE4 0x3004 #define GL_CLIP_DISTANCE5 0x3005 +#define GL_CLIP_DISTANCE6 0x3006 +#define GL_CLIP_DISTANCE7 0x3007 #define GL_MAX_CLIP_DISTANCES 0x0D32 #define GL_MAJOR_VERSION 0x821B #define GL_MINOR_VERSION 0x821C @@ -600,6 +602,9 @@ extern "C" { #define GL_QUERY_NO_WAIT 0x8E14 #define GL_QUERY_BY_REGION_WAIT 0x8E15 #define GL_QUERY_BY_REGION_NO_WAIT 0x8E16 +#define GL_BUFFER_ACCESS_FLAGS 0x911F +#define GL_BUFFER_MAP_LENGTH 0x9120 +#define GL_BUFFER_MAP_OFFSET 0x9121 /* Reuse tokens from ARB_depth_buffer_float */ /* reuse GL_DEPTH_COMPONENT32F */ /* reuse GL_DEPTH32F_STENCIL8 */ @@ -804,6 +809,84 @@ extern "C" { /* reuse GL_INVALID_INDEX */ #endif +#ifndef GL_VERSION_3_2 +#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001 +#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002 +#define GL_LINES_ADJACENCY 0x000A +#define GL_LINE_STRIP_ADJACENCY 0x000B +#define GL_TRIANGLES_ADJACENCY 0x000C +#define GL_TRIANGLE_STRIP_ADJACENCY 0x000D +#define GL_PROGRAM_POINT_SIZE 0x8642 +#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29 +#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8 +#define GL_GEOMETRY_SHADER 0x8DD9 +#define GL_GEOMETRY_VERTICES_OUT 0x8916 +#define GL_GEOMETRY_INPUT_TYPE 0x8917 +#define GL_GEOMETRY_OUTPUT_TYPE 0x8918 +#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF +#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0 +#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1 +#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122 +#define GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123 +#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124 +#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125 +#define GL_CONTEXT_PROFILE_MASK 0x9126 +/* reuse GL_MAX_VARYING_COMPONENTS */ +/* reuse GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER */ +/* Reuse tokens from ARB_depth_clamp */ +/* reuse GL_DEPTH_CLAMP */ +/* Would reuse tokens from ARB_draw_elements_base_vertex, but it has none */ +/* Would reuse tokens from ARB_fragment_coord_conventions, but it has none */ +/* Reuse tokens from ARB_provoking_vertex */ +/* reuse GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION */ +/* reuse GL_FIRST_VERTEX_CONVENTION */ +/* reuse GL_LAST_VERTEX_CONVENTION */ +/* reuse GL_PROVOKING_VERTEX */ +/* Reuse tokens from ARB_seamless_cube_map */ +/* reuse GL_TEXTURE_CUBE_MAP_SEAMLESS */ +/* Reuse tokens from ARB_sync */ +/* reuse GL_MAX_SERVER_WAIT_TIMEOUT */ +/* reuse GL_OBJECT_TYPE */ +/* reuse GL_SYNC_CONDITION */ +/* reuse GL_SYNC_STATUS */ +/* reuse GL_SYNC_FLAGS */ +/* reuse GL_SYNC_FENCE */ +/* reuse GL_SYNC_GPU_COMMANDS_COMPLETE */ +/* reuse GL_UNSIGNALED */ +/* reuse GL_SIGNALED */ +/* reuse GL_ALREADY_SIGNALED */ +/* reuse GL_TIMEOUT_EXPIRED */ +/* reuse GL_CONDITION_SATISFIED */ +/* reuse GL_WAIT_FAILED */ +/* reuse GL_TIMEOUT_IGNORED */ +/* reuse GL_SYNC_FLUSH_COMMANDS_BIT */ +/* reuse GL_TIMEOUT_IGNORED */ +/* Reuse tokens from ARB_texture_multisample */ +/* reuse GL_SAMPLE_POSITION */ +/* reuse GL_SAMPLE_MASK */ +/* reuse GL_SAMPLE_MASK_VALUE */ +/* reuse GL_MAX_SAMPLE_MASK_WORDS */ +/* reuse GL_TEXTURE_2D_MULTISAMPLE */ +/* reuse GL_PROXY_TEXTURE_2D_MULTISAMPLE */ +/* reuse GL_TEXTURE_2D_MULTISAMPLE_ARRAY */ +/* reuse GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY */ +/* reuse GL_TEXTURE_BINDING_2D_MULTISAMPLE */ +/* reuse GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY */ +/* reuse GL_TEXTURE_SAMPLES */ +/* reuse GL_TEXTURE_FIXED_SAMPLE_LOCATIONS */ +/* reuse GL_SAMPLER_2D_MULTISAMPLE */ +/* reuse GL_INT_SAMPLER_2D_MULTISAMPLE */ +/* reuse GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE */ +/* reuse GL_SAMPLER_2D_MULTISAMPLE_ARRAY */ +/* reuse GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY */ +/* reuse GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY */ +/* reuse GL_MAX_COLOR_TEXTURE_SAMPLES */ +/* reuse GL_MAX_DEPTH_TEXTURE_SAMPLES */ +/* reuse GL_MAX_INTEGER_SAMPLES */ +/* Don't need to reuse tokens from ARB_vertex_array_bgra since they're already in 1.2 core */ +#endif + #ifndef GL_ARB_multitexture #define GL_TEXTURE0_ARB 0x84C0 #define GL_TEXTURE1_ARB 0x84C1 @@ -1530,6 +1613,100 @@ extern "C" { #ifndef GL_ARB_shader_texture_lod #endif +#ifndef GL_ARB_depth_clamp +#define GL_DEPTH_CLAMP 0x864F +#endif + +#ifndef GL_ARB_draw_elements_base_vertex +#endif + +#ifndef GL_ARB_fragment_coord_conventions +#endif + +#ifndef GL_ARB_provoking_vertex +#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION 0x8E4C +#define GL_FIRST_VERTEX_CONVENTION 0x8E4D +#define GL_LAST_VERTEX_CONVENTION 0x8E4E +#define GL_PROVOKING_VERTEX 0x8E4F +#endif + +#ifndef GL_ARB_seamless_cube_map +#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F +#endif + +#ifndef GL_ARB_sync +#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111 +#define GL_OBJECT_TYPE 0x9112 +#define GL_SYNC_CONDITION 0x9113 +#define GL_SYNC_STATUS 0x9114 +#define GL_SYNC_FLAGS 0x9115 +#define GL_SYNC_FENCE 0x9116 +#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117 +#define GL_UNSIGNALED 0x9118 +#define GL_SIGNALED 0x9119 +#define GL_ALREADY_SIGNALED 0x911A +#define GL_TIMEOUT_EXPIRED 0x911B +#define GL_CONDITION_SATISFIED 0x911C +#define GL_WAIT_FAILED 0x911D +#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001 +#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull +#endif + +#ifndef GL_ARB_texture_multisample +#define GL_SAMPLE_POSITION 0x8E50 +#define GL_SAMPLE_MASK 0x8E51 +#define GL_SAMPLE_MASK_VALUE 0x8E52 +#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59 +#define GL_TEXTURE_2D_MULTISAMPLE 0x9100 +#define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101 +#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102 +#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103 +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104 +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105 +#define GL_TEXTURE_SAMPLES 0x9106 +#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107 +#define GL_SAMPLER_2D_MULTISAMPLE 0x9108 +#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109 +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A +#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B +#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D +#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E +#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F +#define GL_MAX_INTEGER_SAMPLES 0x9110 +#endif + +#ifndef GL_ARB_vertex_array_bgra +/* reuse GL_BGRA */ +#endif + +#ifndef GL_ARB_draw_buffers_blend +#endif + +#ifndef GL_ARB_sample_shading +#define GL_SAMPLE_SHADING 0x8C36 +#define GL_MIN_SAMPLE_SHADING_VALUE 0x8C37 +#endif + +#ifndef GL_ARB_texture_cube_map_array +#define GL_TEXTURE_CUBE_MAP_ARRAY 0x9009 +#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY 0x900A +#define GL_PROXY_TEXTURE_CUBE_MAP_ARRAY 0x900B +#define GL_SAMPLER_CUBE_MAP_ARRAY 0x900C +#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D +#define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E +#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F +#endif + +#ifndef GL_ARB_texture_gather +#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5E +#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5F +#define GL_MAX_PROGRAM_TEXTURE_GATHER_COMPONENTS 0x8F9F +#endif + +#ifndef GL_ARB_texture_query_lod +#endif + #ifndef GL_EXT_abgr #define GL_ABGR_EXT 0x8000 #endif @@ -3996,11 +4173,11 @@ extern "C" { #define GL_SAMPLE_MASK_VALUE_NV 0x8E52 #define GL_TEXTURE_BINDING_RENDERBUFFER_NV 0x8E53 #define GL_TEXTURE_RENDERBUFFER_DATA_STORE_BINDING_NV 0x8E54 -#define GL_MAX_SAMPLE_MASK_WORDS_NV 0x8E59 #define GL_TEXTURE_RENDERBUFFER_NV 0x8E55 #define GL_SAMPLER_RENDERBUFFER_NV 0x8E56 #define GL_INT_SAMPLER_RENDERBUFFER_NV 0x8E57 #define GL_UNSIGNED_INT_SAMPLER_RENDERBUFFER_NV 0x8E58 +#define GL_MAX_SAMPLE_MASK_WORDS_NV 0x8E59 #endif #ifndef GL_NV_transform_feedback2 @@ -4046,6 +4223,94 @@ extern "C" { #define GL_PROVOKING_VERTEX_EXT 0x8E4F #endif +#ifndef GL_EXT_texture_snorm +#define GL_ALPHA_SNORM 0x9010 +#define GL_LUMINANCE_SNORM 0x9011 +#define GL_LUMINANCE_ALPHA_SNORM 0x9012 +#define GL_INTENSITY_SNORM 0x9013 +#define GL_ALPHA8_SNORM 0x9014 +#define GL_LUMINANCE8_SNORM 0x9015 +#define GL_LUMINANCE8_ALPHA8_SNORM 0x9016 +#define GL_INTENSITY8_SNORM 0x9017 +#define GL_ALPHA16_SNORM 0x9018 +#define GL_LUMINANCE16_SNORM 0x9019 +#define GL_LUMINANCE16_ALPHA16_SNORM 0x901A +#define GL_INTENSITY16_SNORM 0x901B +/* reuse GL_R_SNORM */ +/* reuse GL_RG_SNORM */ +/* reuse GL_RGB_SNORM */ +/* reuse GL_RGBA_SNORM */ +/* reuse GL_R8_SNORM */ +/* reuse GL_RG8_SNORM */ +/* reuse GL_RGB8_SNORM */ +/* reuse GL_RGBA8_SNORM */ +/* reuse GL_R16_SNORM */ +/* reuse GL_RG16_SNORM */ +/* reuse GL_RGB16_SNORM */ +/* reuse GL_RGBA16_SNORM */ +/* reuse GL_SIGNED_NORMALIZED */ +#endif + +#ifndef GL_AMD_draw_buffers_blend +#endif + +#ifndef GL_APPLE_texture_range +#define GL_TEXTURE_RANGE_LENGTH_APPLE 0x85B7 +#define GL_TEXTURE_RANGE_POINTER_APPLE 0x85B8 +#define GL_TEXTURE_STORAGE_HINT_APPLE 0x85BC +#define GL_STORAGE_PRIVATE_APPLE 0x85BD +/* reuse GL_STORAGE_CACHED_APPLE */ +/* reuse GL_STORAGE_SHARED_APPLE */ +#endif + +#ifndef GL_APPLE_float_pixels +#define GL_HALF_APPLE 0x140B +#define GL_RGBA_FLOAT32_APPLE 0x8814 +#define GL_RGB_FLOAT32_APPLE 0x8815 +#define GL_ALPHA_FLOAT32_APPLE 0x8816 +#define GL_INTENSITY_FLOAT32_APPLE 0x8817 +#define GL_LUMINANCE_FLOAT32_APPLE 0x8818 +#define GL_LUMINANCE_ALPHA_FLOAT32_APPLE 0x8819 +#define GL_RGBA_FLOAT16_APPLE 0x881A +#define GL_RGB_FLOAT16_APPLE 0x881B +#define GL_ALPHA_FLOAT16_APPLE 0x881C +#define GL_INTENSITY_FLOAT16_APPLE 0x881D +#define GL_LUMINANCE_FLOAT16_APPLE 0x881E +#define GL_LUMINANCE_ALPHA_FLOAT16_APPLE 0x881F +#define GL_COLOR_FLOAT_APPLE 0x8A0F +#endif + +#ifndef GL_APPLE_vertex_program_evaluators +#define GL_VERTEX_ATTRIB_MAP1_APPLE 0x8A00 +#define GL_VERTEX_ATTRIB_MAP2_APPLE 0x8A01 +#define GL_VERTEX_ATTRIB_MAP1_SIZE_APPLE 0x8A02 +#define GL_VERTEX_ATTRIB_MAP1_COEFF_APPLE 0x8A03 +#define GL_VERTEX_ATTRIB_MAP1_ORDER_APPLE 0x8A04 +#define GL_VERTEX_ATTRIB_MAP1_DOMAIN_APPLE 0x8A05 +#define GL_VERTEX_ATTRIB_MAP2_SIZE_APPLE 0x8A06 +#define GL_VERTEX_ATTRIB_MAP2_COEFF_APPLE 0x8A07 +#define GL_VERTEX_ATTRIB_MAP2_ORDER_APPLE 0x8A08 +#define GL_VERTEX_ATTRIB_MAP2_DOMAIN_APPLE 0x8A09 +#endif + +#ifndef GL_APPLE_aux_depth_stencil +#define GL_AUX_DEPTH_STENCIL_APPLE 0x8A14 +#endif + +#ifndef GL_APPLE_object_purgeable +#define GL_BUFFER_OBJECT_APPLE 0x85B3 +#define GL_RELEASED_APPLE 0x8A19 +#define GL_VOLATILE_APPLE 0x8A1A +#define GL_RETAINED_APPLE 0x8A1B +#define GL_UNDEFINED_APPLE 0x8A1C +#define GL_PURGEABLE_APPLE 0x8A1D +#endif + +#ifndef GL_APPLE_row_bytes +#define GL_PACK_ROW_BYTES_APPLE 0x8A15 +#define GL_UNPACK_ROW_BYTES_APPLE 0x8A16 +#endif + /*************************************************************/ @@ -4125,6 +4390,12 @@ typedef int64_t GLint64EXT; typedef uint64_t GLuint64EXT; #endif +#ifndef ARB_sync +typedef int64_t GLint64; +typedef uint64_t GLuint64; +typedef struct __GLsync *GLsync; +#endif + #ifndef GL_VERSION_1_2 #define GL_VERSION_1_2 1 #ifdef GL_GLEXT_PROTOTYPES @@ -4698,6 +4969,26 @@ GLAPI void APIENTRY glEndConditionalRender (void); GLAPI void APIENTRY glVertexAttribIPointer (GLuint, GLint, GLenum, GLsizei, const GLvoid *); GLAPI void APIENTRY glGetVertexAttribIiv (GLuint, GLenum, GLint *); GLAPI void APIENTRY glGetVertexAttribIuiv (GLuint, GLenum, GLuint *); +GLAPI void APIENTRY glVertexAttribI1i (GLuint, GLint); +GLAPI void APIENTRY glVertexAttribI2i (GLuint, GLint, GLint); +GLAPI void APIENTRY glVertexAttribI3i (GLuint, GLint, GLint, GLint); +GLAPI void APIENTRY glVertexAttribI4i (GLuint, GLint, GLint, GLint, GLint); +GLAPI void APIENTRY glVertexAttribI1ui (GLuint, GLuint); +GLAPI void APIENTRY glVertexAttribI2ui (GLuint, GLuint, GLuint); +GLAPI void APIENTRY glVertexAttribI3ui (GLuint, GLuint, GLuint, GLuint); +GLAPI void APIENTRY glVertexAttribI4ui (GLuint, GLuint, GLuint, GLuint, GLuint); +GLAPI void APIENTRY glVertexAttribI1iv (GLuint, const GLint *); +GLAPI void APIENTRY glVertexAttribI2iv (GLuint, const GLint *); +GLAPI void APIENTRY glVertexAttribI3iv (GLuint, const GLint *); +GLAPI void APIENTRY glVertexAttribI4iv (GLuint, const GLint *); +GLAPI void APIENTRY glVertexAttribI1uiv (GLuint, const GLuint *); +GLAPI void APIENTRY glVertexAttribI2uiv (GLuint, const GLuint *); +GLAPI void APIENTRY glVertexAttribI3uiv (GLuint, const GLuint *); +GLAPI void APIENTRY glVertexAttribI4uiv (GLuint, const GLuint *); +GLAPI void APIENTRY glVertexAttribI4bv (GLuint, const GLbyte *); +GLAPI void APIENTRY glVertexAttribI4sv (GLuint, const GLshort *); +GLAPI void APIENTRY glVertexAttribI4ubv (GLuint, const GLubyte *); +GLAPI void APIENTRY glVertexAttribI4usv (GLuint, const GLushort *); GLAPI void APIENTRY glGetUniformuiv (GLuint, GLint, GLuint *); GLAPI void APIENTRY glBindFragDataLocation (GLuint, GLuint, const GLchar *); GLAPI GLint APIENTRY glGetFragDataLocation (GLuint, const GLchar *); @@ -4737,52 +5028,6 @@ typedef void (APIENTRYP PFNGLENDCONDITIONALRENDERPROC) (void); typedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIIVPROC) (GLuint index, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIUIVPROC) (GLuint index, GLenum pname, GLuint *params); -typedef void (APIENTRYP PFNGLGETUNIFORMUIVPROC) (GLuint program, GLint location, GLuint *params); -typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONPROC) (GLuint program, GLuint color, const GLchar *name); -typedef GLint (APIENTRYP PFNGLGETFRAGDATALOCATIONPROC) (GLuint program, const GLchar *name); -typedef void (APIENTRYP PFNGLUNIFORM1UIPROC) (GLint location, GLuint v0); -typedef void (APIENTRYP PFNGLUNIFORM2UIPROC) (GLint location, GLuint v0, GLuint v1); -typedef void (APIENTRYP PFNGLUNIFORM3UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2); -typedef void (APIENTRYP PFNGLUNIFORM4UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); -typedef void (APIENTRYP PFNGLUNIFORM1UIVPROC) (GLint location, GLsizei count, const GLuint *value); -typedef void (APIENTRYP PFNGLUNIFORM2UIVPROC) (GLint location, GLsizei count, const GLuint *value); -typedef void (APIENTRYP PFNGLUNIFORM3UIVPROC) (GLint location, GLsizei count, const GLuint *value); -typedef void (APIENTRYP PFNGLUNIFORM4UIVPROC) (GLint location, GLsizei count, const GLuint *value); -typedef void (APIENTRYP PFNGLTEXPARAMETERIIVPROC) (GLenum target, GLenum pname, const GLint *params); -typedef void (APIENTRYP PFNGLTEXPARAMETERIUIVPROC) (GLenum target, GLenum pname, const GLuint *params); -typedef void (APIENTRYP PFNGLGETTEXPARAMETERIIVPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETTEXPARAMETERIUIVPROC) (GLenum target, GLenum pname, GLuint *params); -typedef void (APIENTRYP PFNGLCLEARBUFFERIVPROC) (GLenum buffer, GLint drawbuffer, const GLint *value); -typedef void (APIENTRYP PFNGLCLEARBUFFERUIVPROC) (GLenum buffer, GLint drawbuffer, const GLuint *value); -typedef void (APIENTRYP PFNGLCLEARBUFFERFVPROC) (GLenum buffer, GLint drawbuffer, const GLfloat *value); -typedef void (APIENTRYP PFNGLCLEARBUFFERFIPROC) (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); -typedef const GLubyte * (APIENTRYP PFNGLGETSTRINGIPROC) (GLenum name, GLuint index); -#endif - -#ifndef GL_VERSION_3_0_DEPRECATED -#define GL_VERSION_3_0_DEPRECATED 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glVertexAttribI1i (GLuint, GLint); -GLAPI void APIENTRY glVertexAttribI2i (GLuint, GLint, GLint); -GLAPI void APIENTRY glVertexAttribI3i (GLuint, GLint, GLint, GLint); -GLAPI void APIENTRY glVertexAttribI4i (GLuint, GLint, GLint, GLint, GLint); -GLAPI void APIENTRY glVertexAttribI1ui (GLuint, GLuint); -GLAPI void APIENTRY glVertexAttribI2ui (GLuint, GLuint, GLuint); -GLAPI void APIENTRY glVertexAttribI3ui (GLuint, GLuint, GLuint, GLuint); -GLAPI void APIENTRY glVertexAttribI4ui (GLuint, GLuint, GLuint, GLuint, GLuint); -GLAPI void APIENTRY glVertexAttribI1iv (GLuint, const GLint *); -GLAPI void APIENTRY glVertexAttribI2iv (GLuint, const GLint *); -GLAPI void APIENTRY glVertexAttribI3iv (GLuint, const GLint *); -GLAPI void APIENTRY glVertexAttribI4iv (GLuint, const GLint *); -GLAPI void APIENTRY glVertexAttribI1uiv (GLuint, const GLuint *); -GLAPI void APIENTRY glVertexAttribI2uiv (GLuint, const GLuint *); -GLAPI void APIENTRY glVertexAttribI3uiv (GLuint, const GLuint *); -GLAPI void APIENTRY glVertexAttribI4uiv (GLuint, const GLuint *); -GLAPI void APIENTRY glVertexAttribI4bv (GLuint, const GLbyte *); -GLAPI void APIENTRY glVertexAttribI4sv (GLuint, const GLshort *); -GLAPI void APIENTRY glVertexAttribI4ubv (GLuint, const GLubyte *); -GLAPI void APIENTRY glVertexAttribI4usv (GLuint, const GLushort *); -#endif /* GL_GLEXT_PROTOTYPES */ typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IPROC) (GLuint index, GLint x); typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IPROC) (GLuint index, GLint x, GLint y); typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IPROC) (GLuint index, GLint x, GLint y, GLint z); @@ -4803,6 +5048,26 @@ typedef void (APIENTRYP PFNGLVERTEXATTRIBI4BVPROC) (GLuint index, const GLbyte * typedef void (APIENTRYP PFNGLVERTEXATTRIBI4SVPROC) (GLuint index, const GLshort *v); typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UBVPROC) (GLuint index, const GLubyte *v); typedef void (APIENTRYP PFNGLVERTEXATTRIBI4USVPROC) (GLuint index, const GLushort *v); +typedef void (APIENTRYP PFNGLGETUNIFORMUIVPROC) (GLuint program, GLint location, GLuint *params); +typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONPROC) (GLuint program, GLuint color, const GLchar *name); +typedef GLint (APIENTRYP PFNGLGETFRAGDATALOCATIONPROC) (GLuint program, const GLchar *name); +typedef void (APIENTRYP PFNGLUNIFORM1UIPROC) (GLint location, GLuint v0); +typedef void (APIENTRYP PFNGLUNIFORM2UIPROC) (GLint location, GLuint v0, GLuint v1); +typedef void (APIENTRYP PFNGLUNIFORM3UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2); +typedef void (APIENTRYP PFNGLUNIFORM4UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +typedef void (APIENTRYP PFNGLUNIFORM1UIVPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (APIENTRYP PFNGLUNIFORM2UIVPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (APIENTRYP PFNGLUNIFORM3UIVPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (APIENTRYP PFNGLUNIFORM4UIVPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (APIENTRYP PFNGLTEXPARAMETERIIVPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLTEXPARAMETERIUIVPROC) (GLenum target, GLenum pname, const GLuint *params); +typedef void (APIENTRYP PFNGLGETTEXPARAMETERIIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETTEXPARAMETERIUIVPROC) (GLenum target, GLenum pname, GLuint *params); +typedef void (APIENTRYP PFNGLCLEARBUFFERIVPROC) (GLenum buffer, GLint drawbuffer, const GLint *value); +typedef void (APIENTRYP PFNGLCLEARBUFFERUIVPROC) (GLenum buffer, GLint drawbuffer, const GLuint *value); +typedef void (APIENTRYP PFNGLCLEARBUFFERFVPROC) (GLenum buffer, GLint drawbuffer, const GLfloat *value); +typedef void (APIENTRYP PFNGLCLEARBUFFERFIPROC) (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); +typedef const GLubyte * (APIENTRYP PFNGLGETSTRINGIPROC) (GLenum name, GLuint index); #endif #ifndef GL_VERSION_3_1 @@ -4822,6 +5087,27 @@ typedef void (APIENTRYP PFNGLTEXBUFFERPROC) (GLenum target, GLenum internalforma typedef void (APIENTRYP PFNGLPRIMITIVERESTARTINDEXPROC) (GLuint index); #endif +#ifndef GL_VERSION_3_2 +#define GL_VERSION_3_2 1 +/* OpenGL 3.2 also reuses entry points from these extensions: */ +/* ARB_draw_elements_base_vertex */ +/* ARB_provoking_vertex */ +/* ARB_sync */ +/* ARB_texture_multisample */ +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glGetInteger64i_v (GLenum, GLuint, GLint64 *); +GLAPI void APIENTRY glGetBufferParameteri64v (GLenum, GLenum, GLint64 *); +GLAPI void APIENTRY glProgramParameteri (GLuint, GLenum, GLint); +GLAPI void APIENTRY glFramebufferTexture (GLenum, GLenum, GLuint, GLint); +GLAPI void APIENTRY glFramebufferTextureFace (GLenum, GLenum, GLuint, GLint, GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLGETINTEGER64I_VPROC) (GLenum target, GLuint index, GLint64 *data); +typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERI64VPROC) (GLenum target, GLenum pname, GLint64 *params); +typedef void (APIENTRYP PFNGLPROGRAMPARAMETERIPROC) (GLuint program, GLenum pname, GLint value); +typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level); +typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREFACEPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face); +#endif + #ifndef GL_ARB_multitexture #define GL_ARB_multitexture 1 #ifdef GL_GLEXT_PROTOTYPES @@ -5567,6 +5853,112 @@ typedef void (APIENTRYP PFNGLCOPYBUFFERSUBDATAPROC) (GLenum readTarget, GLenum w #define GL_ARB_shader_texture_lod 1 #endif +#ifndef GL_ARB_depth_clamp +#define GL_ARB_depth_clamp 1 +#endif + +#ifndef GL_ARB_draw_elements_base_vertex +#define GL_ARB_draw_elements_base_vertex 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDrawElementsBaseVertex (GLenum, GLsizei, GLenum, const GLvoid *, GLint); +GLAPI void APIENTRY glDrawRangeElementsBaseVertex (GLenum, GLuint, GLuint, GLsizei, GLenum, const GLvoid *, GLint); +GLAPI void APIENTRY glDrawElementsInstancedBaseVertex (GLenum, GLsizei, GLenum, const GLvoid *, GLsizei, GLint); +GLAPI void APIENTRY glMultiDrawElementsBaseVertex (GLenum, const GLsizei *, GLenum, const GLvoid* *, GLsizei, const GLint *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex); +typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex); +typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount, GLint basevertex); +typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount, const GLint *basevertex); +#endif + +#ifndef GL_ARB_fragment_coord_conventions +#define GL_ARB_fragment_coord_conventions 1 +#endif + +#ifndef GL_ARB_provoking_vertex +#define GL_ARB_provoking_vertex 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glProvokingVertex (GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLPROVOKINGVERTEXPROC) (GLenum mode); +#endif + +#ifndef GL_ARB_seamless_cube_map +#define GL_ARB_seamless_cube_map 1 +#endif + +#ifndef GL_ARB_sync +#define GL_ARB_sync 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI GLsync APIENTRY glFenceSync (GLenum, GLbitfield); +GLAPI GLboolean APIENTRY glIsSync (GLsync); +GLAPI void APIENTRY glDeleteSync (GLsync); +GLAPI GLenum APIENTRY glClientWaitSync (GLsync, GLbitfield, GLuint64); +GLAPI void APIENTRY glWaitSync (GLsync, GLbitfield, GLuint64); +GLAPI void APIENTRY glGetInteger64v (GLenum, GLint64 *); +GLAPI void APIENTRY glGetSynciv (GLsync, GLenum, GLsizei, GLsizei *, GLint *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef GLsync (APIENTRYP PFNGLFENCESYNCPROC) (GLenum condition, GLbitfield flags); +typedef GLboolean (APIENTRYP PFNGLISSYNCPROC) (GLsync sync); +typedef void (APIENTRYP PFNGLDELETESYNCPROC) (GLsync sync); +typedef GLenum (APIENTRYP PFNGLCLIENTWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout); +typedef void (APIENTRYP PFNGLWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout); +typedef void (APIENTRYP PFNGLGETINTEGER64VPROC) (GLenum pname, GLint64 *params); +typedef void (APIENTRYP PFNGLGETSYNCIVPROC) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values); +#endif + +#ifndef GL_ARB_texture_multisample +#define GL_ARB_texture_multisample 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glTexImage2DMultisample (GLenum, GLsizei, GLint, GLsizei, GLsizei, GLboolean); +GLAPI void APIENTRY glTexImage3DMultisample (GLenum, GLsizei, GLint, GLsizei, GLsizei, GLsizei, GLboolean); +GLAPI void APIENTRY glGetMultisamplefv (GLenum, GLuint, GLfloat *); +GLAPI void APIENTRY glSampleMaski (GLuint, GLbitfield); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLTEXIMAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); +typedef void (APIENTRYP PFNGLTEXIMAGE3DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); +typedef void (APIENTRYP PFNGLGETMULTISAMPLEFVPROC) (GLenum pname, GLuint index, GLfloat *val); +typedef void (APIENTRYP PFNGLSAMPLEMASKIPROC) (GLuint index, GLbitfield mask); +#endif + +#ifndef GL_ARB_vertex_array_bgra +#define GL_ARB_vertex_array_bgra 1 +#endif + +#ifndef GL_ARB_draw_buffers_blend +#define GL_ARB_draw_buffers_blend 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBlendEquationi (GLuint, GLenum); +GLAPI void APIENTRY glBlendEquationSeparatei (GLuint, GLenum, GLenum); +GLAPI void APIENTRY glBlendFunci (GLuint, GLenum, GLenum); +GLAPI void APIENTRY glBlendFuncSeparatei (GLuint, GLenum, GLenum, GLenum, GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLBLENDEQUATIONIPROC) (GLuint buf, GLenum mode); +typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEIPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha); +typedef void (APIENTRYP PFNGLBLENDFUNCIPROC) (GLuint buf, GLenum src, GLenum dst); +typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEIPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +#endif + +#ifndef GL_ARB_sample_shading +#define GL_ARB_sample_shading 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glMinSampleShading (GLclampf); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLMINSAMPLESHADINGPROC) (GLclampf value); +#endif + +#ifndef GL_ARB_texture_cube_map_array +#define GL_ARB_texture_cube_map_array 1 +#endif + +#ifndef GL_ARB_texture_gather +#define GL_ARB_texture_gather 1 +#endif + +#ifndef GL_ARB_texture_query_lod +#define GL_ARB_texture_query_lod 1 +#endif + #ifndef GL_EXT_abgr #define GL_EXT_abgr 1 #endif @@ -8204,7 +8596,7 @@ GLAPI void APIENTRY glTransformFeedbackAttribsNV (GLuint, const GLint *, GLenum) GLAPI void APIENTRY glBindBufferRangeNV (GLenum, GLuint, GLuint, GLintptr, GLsizeiptr); GLAPI void APIENTRY glBindBufferOffsetNV (GLenum, GLuint, GLuint, GLintptr); GLAPI void APIENTRY glBindBufferBaseNV (GLenum, GLuint, GLuint); -GLAPI void APIENTRY glTransformFeedbackVaryingsNV (GLuint, GLsizei, const GLint *, GLenum); +GLAPI void APIENTRY glTransformFeedbackVaryingsNV (GLuint, GLsizei, const GLchar* *, GLenum); GLAPI void APIENTRY glActiveVaryingNV (GLuint, const GLchar *); GLAPI GLint APIENTRY glGetVaryingLocationNV (GLuint, const GLchar *); GLAPI void APIENTRY glGetActiveVaryingNV (GLuint, GLuint, GLsizei, GLsizei *, GLsizei *, GLenum *, GLchar *); @@ -8216,7 +8608,7 @@ typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC) (GLuint count, cons typedef void (APIENTRYP PFNGLBINDBUFFERRANGENVPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); typedef void (APIENTRYP PFNGLBINDBUFFEROFFSETNVPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset); typedef void (APIENTRYP PFNGLBINDBUFFERBASENVPROC) (GLenum target, GLuint index, GLuint buffer); -typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSNVPROC) (GLuint program, GLsizei count, const GLint *locations, GLenum bufferMode); +typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSNVPROC) (GLuint program, GLsizei count, const GLchar* *varyings, GLenum bufferMode); typedef void (APIENTRYP PFNGLACTIVEVARYINGNVPROC) (GLuint program, const GLchar *name); typedef GLint (APIENTRYP PFNGLGETVARYINGLOCATIONNVPROC) (GLuint program, const GLchar *name); typedef void (APIENTRYP PFNGLGETACTIVEVARYINGNVPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name); @@ -8781,6 +9173,78 @@ GLAPI void APIENTRY glProvokingVertexEXT (GLenum); typedef void (APIENTRYP PFNGLPROVOKINGVERTEXEXTPROC) (GLenum mode); #endif +#ifndef GL_EXT_texture_snorm +#define GL_EXT_texture_snorm 1 +#endif + +#ifndef GL_AMD_draw_buffers_blend +#define GL_AMD_draw_buffers_blend 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBlendFuncIndexedAMD (GLuint, GLenum, GLenum); +GLAPI void APIENTRY glBlendFuncSeparateIndexedAMD (GLuint, GLenum, GLenum, GLenum, GLenum); +GLAPI void APIENTRY glBlendEquationIndexedAMD (GLuint, GLenum); +GLAPI void APIENTRY glBlendEquationSeparateIndexedAMD (GLuint, GLenum, GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLBLENDFUNCINDEXEDAMDPROC) (GLuint buf, GLenum src, GLenum dst); +typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEINDEXEDAMDPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +typedef void (APIENTRYP PFNGLBLENDEQUATIONINDEXEDAMDPROC) (GLuint buf, GLenum mode); +typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEINDEXEDAMDPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha); +#endif + +#ifndef GL_APPLE_texture_range +#define GL_APPLE_texture_range 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glTextureRangeAPPLE (GLenum, GLsizei, const GLvoid *); +GLAPI void APIENTRY glGetTexParameterPointervAPPLE (GLenum, GLenum, GLvoid* *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLTEXTURERANGEAPPLEPROC) (GLenum target, GLsizei length, const GLvoid *pointer); +typedef void (APIENTRYP PFNGLGETTEXPARAMETERPOINTERVAPPLEPROC) (GLenum target, GLenum pname, GLvoid* *params); +#endif + +#ifndef GL_APPLE_float_pixels +#define GL_APPLE_float_pixels 1 +#endif + +#ifndef GL_APPLE_vertex_program_evaluators +#define GL_APPLE_vertex_program_evaluators 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glEnableVertexAttribAPPLE (GLuint, GLenum); +GLAPI void APIENTRY glDisableVertexAttribAPPLE (GLuint, GLenum); +GLAPI GLboolean APIENTRY glIsVertexAttribEnabledAPPLE (GLuint, GLenum); +GLAPI void APIENTRY glMapVertexAttrib1dAPPLE (GLuint, GLuint, GLdouble, GLdouble, GLint, GLint, const GLdouble *); +GLAPI void APIENTRY glMapVertexAttrib1fAPPLE (GLuint, GLuint, GLfloat, GLfloat, GLint, GLint, const GLfloat *); +GLAPI void APIENTRY glMapVertexAttrib2dAPPLE (GLuint, GLuint, GLdouble, GLdouble, GLint, GLint, GLdouble, GLdouble, GLint, GLint, const GLdouble *); +GLAPI void APIENTRY glMapVertexAttrib2fAPPLE (GLuint, GLuint, GLfloat, GLfloat, GLint, GLint, GLfloat, GLfloat, GLint, GLint, const GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBAPPLEPROC) (GLuint index, GLenum pname); +typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBAPPLEPROC) (GLuint index, GLenum pname); +typedef GLboolean (APIENTRYP PFNGLISVERTEXATTRIBENABLEDAPPLEPROC) (GLuint index, GLenum pname); +typedef void (APIENTRYP PFNGLMAPVERTEXATTRIB1DAPPLEPROC) (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points); +typedef void (APIENTRYP PFNGLMAPVERTEXATTRIB1FAPPLEPROC) (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points); +typedef void (APIENTRYP PFNGLMAPVERTEXATTRIB2DAPPLEPROC) (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points); +typedef void (APIENTRYP PFNGLMAPVERTEXATTRIB2FAPPLEPROC) (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points); +#endif + +#ifndef GL_APPLE_aux_depth_stencil +#define GL_APPLE_aux_depth_stencil 1 +#endif + +#ifndef GL_APPLE_object_purgeable +#define GL_APPLE_object_purgeable 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI GLenum APIENTRY glObjectPurgeableAPPLE (GLenum, GLuint, GLenum); +GLAPI GLenum APIENTRY glObjectUnpurgeableAPPLE (GLenum, GLuint, GLenum); +GLAPI void APIENTRY glGetObjectParameterivAPPLE (GLenum, GLuint, GLenum, GLint *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef GLenum (APIENTRYP PFNGLOBJECTPURGEABLEAPPLEPROC) (GLenum objectType, GLuint name, GLenum option); +typedef GLenum (APIENTRYP PFNGLOBJECTUNPURGEABLEAPPLEPROC) (GLenum objectType, GLuint name, GLenum option); +typedef void (APIENTRYP PFNGLGETOBJECTPARAMETERIVAPPLEPROC) (GLenum objectType, GLuint name, GLenum pname, GLint *params); +#endif + +#ifndef GL_APPLE_row_bytes +#define GL_APPLE_row_bytes 1 +#endif + #ifdef __cplusplus } diff --git a/include/GL/glxext.h b/include/GL/glxext.h index 536fb25a76..eac09f94fa 100644 --- a/include/GL/glxext.h +++ b/include/GL/glxext.h @@ -6,7 +6,7 @@ extern "C" { #endif /* -** Copyright (c) 2007 The Khronos Group Inc. +** Copyright (c) 2007-2009 The Khronos Group Inc. ** ** Permission is hereby granted, free of charge, to any person obtaining a ** copy of this software and/or associated documentation files (the @@ -28,6 +28,8 @@ extern "C" { ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. */ +/* Function declaration macros - to move into glplatform.h */ + #if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) #define WIN32_LEAN_AND_MEAN 1 #include <windows.h> @@ -46,9 +48,9 @@ extern "C" { /*************************************************************/ /* Header file version number, required by OpenGL ABI for Linux */ -/* glxext.h last updated 2008/10/22 */ +/* glxext.h last updated 2009/08/03 */ /* Current version at http://www.opengl.org/registry/ */ -#define GLX_GLXEXT_VERSION 21 +#define GLX_GLXEXT_VERSION 23 #ifndef GLX_VERSION_1_3 #define GLX_WINDOW_BIT 0x00000001 @@ -135,6 +137,12 @@ extern "C" { #define GLX_CONTEXT_FLAGS_ARB 0x2094 #endif +#ifndef GLX_ARB_create_context_profile +#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 +#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 +#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126 +#endif + #ifndef GLX_SGIS_multisample #define GLX_SAMPLE_BUFFERS_SGIS 100000 #define GLX_SAMPLES_SGIS 100001 @@ -518,6 +526,10 @@ extern GLXContext glXCreateContextAttribsARB (Display *, GLXFBConfig, GLXContext typedef GLXContext ( * PFNGLXCREATECONTEXTATTRIBSARBPROC) (Display *dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list); #endif +#ifndef GLX_ARB_create_context_profile +#define GLX_ARB_create_context_profile 1 +#endif + #ifndef GLX_SGIS_multisample #define GLX_SGIS_multisample 1 #endif diff --git a/include/GL/wglext.h b/include/GL/wglext.h index 3c492dd634..1f096fb919 100644 --- a/include/GL/wglext.h +++ b/include/GL/wglext.h @@ -48,9 +48,9 @@ extern "C" { /*************************************************************/ /* Header file version number */ -/* wglext.h last updated 2009/03/03 */ +/* wglext.h last updated 2009/08/03 */ /* Current version at http://www.opengl.org/registry/ */ -#define WGL_WGLEXT_VERSION 12 +#define WGL_WGLEXT_VERSION 15 #ifndef WGL_ARB_buffer_region #define WGL_FRONT_COLOR_BUFFER_BIT_ARB 0x00000001 @@ -176,8 +176,8 @@ extern "C" { #endif #ifndef WGL_ARB_create_context -#define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001 -#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002 +#define WGL_CONTEXT_DEBUG_BIT_ARB 0x00000001 +#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002 #define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 #define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 #define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093 @@ -185,6 +185,13 @@ extern "C" { #define ERROR_INVALID_VERSION_ARB 0x2095 #endif +#ifndef WGL_ARB_create_context_profile +#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 +#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 +#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 +#define ERROR_INVALID_PROFILE_ARB 0x2096 +#endif + #ifndef WGL_EXT_make_current_read #define ERROR_INVALID_PIXEL_TYPE_EXT 0x2043 #endif @@ -497,6 +504,10 @@ extern HGLRC WINAPI wglCreateContextAttribsARB (HDC, HGLRC, const int *); typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShareContext, const int *attribList); #endif +#ifndef WGL_ARB_create_context_profile +#define WGL_ARB_create_context_profile 1 +#endif + #ifndef WGL_EXT_display_color_table #define WGL_EXT_display_color_table 1 #ifdef WGL_WGLEXT_PROTOTYPES diff --git a/progs/egl/Makefile b/progs/egl/Makefile index d3c32d46f7..fd72f540ca 100644 --- a/progs/egl/Makefile +++ b/progs/egl/Makefile @@ -17,6 +17,7 @@ PROGRAMS = \ eglgears \ eglscreen \ peglgears \ + xeglbindtex \ xeglgears \ xeglthreads \ xegl_tri @@ -84,6 +85,12 @@ peglgears.o: peglgears.c $(HEADERS) $(CC) -c $(CFLAGS) -I$(TOP)/include peglgears.c +xeglbindtex: xeglbindtex.o $(TOP)/$(LIB_DIR)/libEGL.so + $(CC) $(CFLAGS) xeglbindtex.o -L$(TOP)/$(LIB_DIR) -lEGL -lGL $(LIBDRM_LIB) $(APP_LIB_DEPS) -o $@ + +xeglbindtex.o: xeglbindtex.c $(HEADERS) + $(CC) -c $(CFLAGS) -I$(TOP)/include xeglbindtex.c + xeglgears: xeglgears.o $(TOP)/$(LIB_DIR)/libEGL.so $(CC) $(CFLAGS) xeglgears.o -L$(TOP)/$(LIB_DIR) -lEGL -lGL $(LIBDRM_LIB) $(APP_LIB_DEPS) -o $@ diff --git a/progs/egl/xeglbindtex.c b/progs/egl/xeglbindtex.c new file mode 100644 index 0000000000..fdd9fe2b87 --- /dev/null +++ b/progs/egl/xeglbindtex.c @@ -0,0 +1,474 @@ +/* + * Simple demo for eglBindTexImage. Based on xegl_tri.c by + * + * Copyright (C) 2008 Brian Paul 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, 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 + * BRIAN PAUL 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. + */ + +/* + * The spec says that eglBindTexImage supports only OpenGL ES context, but this + * demo uses OpenGL context. Keep in mind that this is non-standard. + */ + +#include <math.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/keysym.h> +#include <GL/gl.h> +#include <EGL/egl.h> + +static EGLDisplay dpy; +static EGLContext ctx_win, ctx_pbuf; +static EGLSurface surf_win, surf_pbuf; +static GLuint tex_pbuf; + +static GLfloat view_rotx = 0.0, view_roty = 0.0, view_rotz = 0.0; +static GLboolean blend = GL_TRUE; +static GLuint color_flow; + +static void +make_pbuffer(int width, int height) +{ + static const EGLint config_attribs[] = { + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE, + EGL_NONE + }; + EGLint pbuf_attribs[] = { + EGL_WIDTH, width, + EGL_HEIGHT, height, + EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGB, + EGL_TEXTURE_TARGET, EGL_TEXTURE_2D, + EGL_NONE + }; + EGLConfig config; + EGLint num_configs; + + if (!eglChooseConfig(dpy, config_attribs, &config, 1, &num_configs)) { + printf("Error: couldn't get an EGL visual config for pbuffer\n"); + exit(1); + } + + eglBindAPI(EGL_OPENGL_API); + ctx_pbuf = eglCreateContext(dpy, config, EGL_NO_CONTEXT, NULL ); + surf_pbuf = eglCreatePbufferSurface(dpy, config, pbuf_attribs); + if (surf_pbuf == EGL_NO_SURFACE) { + printf("failed to allocate pbuffer\n"); + exit(1); + } + + glGenTextures(1, &tex_pbuf); +} + +static void +use_pbuffer(void) +{ + static int initialized; + + eglMakeCurrent(dpy, surf_pbuf, surf_pbuf, ctx_pbuf); + if (!initialized) { + EGLint width, height; + GLfloat ar; + + initialized = 1; + + eglQuerySurface(dpy, surf_pbuf, EGL_WIDTH, &width); + eglQuerySurface(dpy, surf_pbuf, EGL_WIDTH, &height); + ar = (GLfloat) width / (GLfloat) height; + + glViewport(0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum(-ar, ar, -1, 1, 1.0, 10.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + /* y-inverted */ + glScalef(1.0, -1.0, 1.0); + + glTranslatef(0.0, 0.0, -5.0); + + glClearColor(0.2, 0.2, 0.2, 0.0); + } +} + +static void +make_window(Display *x_dpy, const char *name, + int x, int y, int width, int height, + Window *winRet) +{ + static const EGLint attribs[] = { + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_DEPTH_SIZE, 8, + EGL_NONE + }; + + int scrnum; + XSetWindowAttributes attr; + unsigned long mask; + Window root; + Window win; + XVisualInfo *visInfo, visTemplate; + int num_visuals; + EGLConfig config; + EGLint num_configs, vid; + + scrnum = DefaultScreen( x_dpy ); + root = RootWindow( x_dpy, scrnum ); + + if (!eglChooseConfig(dpy, attribs, &config, 1, &num_configs)) { + printf("Error: couldn't get an EGL visual config\n"); + exit(1); + } + + if (!eglGetConfigAttrib(dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) { + printf("Error: eglGetConfigAttrib() failed\n"); + exit(1); + } + + /* The X window visual must match the EGL config */ + visTemplate.visualid = vid; + visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals); + if (!visInfo) { + printf("Error: couldn't get X visual\n"); + exit(1); + } + + /* window attributes */ + attr.background_pixel = 0; + attr.border_pixel = 0; + attr.colormap = XCreateColormap( x_dpy, root, visInfo->visual, AllocNone); + attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; + attr.override_redirect = 0; + mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect; + + win = XCreateWindow( x_dpy, root, 0, 0, width, height, + 0, visInfo->depth, InputOutput, + visInfo->visual, mask, &attr ); + + /* set hints and properties */ + { + XSizeHints sizehints; + sizehints.x = x; + sizehints.y = y; + sizehints.width = width; + sizehints.height = height; + sizehints.flags = USSize | USPosition; + XSetNormalHints(x_dpy, win, &sizehints); + XSetStandardProperties(x_dpy, win, name, name, + None, (char **)NULL, 0, &sizehints); + } + + eglBindAPI(EGL_OPENGL_API); + ctx_win = eglCreateContext(dpy, config, EGL_NO_CONTEXT, NULL ); + if (!ctx_win) { + printf("Error: glXCreateContext failed\n"); + exit(1); + } + + surf_win = eglCreateWindowSurface(dpy, config, win, NULL); + + XFree(visInfo); + + *winRet = win; +} + +static void +use_window(void) +{ + static int initialized; + + eglMakeCurrent(dpy, surf_win, surf_win, ctx_win); + if (!initialized) { + initialized = 1; + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, tex_pbuf); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } +} + +static void +draw_triangle(void) +{ + static const GLfloat verts[3][2] = { + { -3, -3 }, + { 3, -3 }, + { 0, 3 } + }; + GLfloat colors[3][3] = { + { 1, 0, 0 }, + { 0, 1, 0 }, + { 0, 0, 1 } + }; + GLint i; + + /* flow the color */ + for (i = 0; i < 3; i++) { + GLint first = (i + color_flow / 256) % 3; + GLint second = (first + 1) % 3; + GLint third = (second + 1) % 3; + GLfloat c = (color_flow % 256) / 256.0f; + + c = c * c * c; + colors[i][first] = 1.0f - c; + colors[i][second] = c; + colors[i][third] = 0.0f; + } + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glVertexPointer(2, GL_FLOAT, 0, verts); + glColorPointer(3, GL_FLOAT, 0, colors); + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + + glDrawArrays(GL_TRIANGLES, 0, 3); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); +} + +static void +draw_textured_cube(void) +{ + static const GLfloat verts[][2] = { + { -4, -4 }, + { 4, -4 }, + { 4, 4 }, + { -4, 4 } + }; + static const GLfloat colors[][4] = { + { 1, 1, 1, 0.5 }, + { 1, 1, 1, 0.5 }, + { 1, 1, 1, 0.5 }, + { 1, 1, 1, 0.5 } + }; + static const GLfloat texs[][2] = { + { 0, 0 }, + { 1, 0 }, + { 1, 1 }, + { 0, 1 } + }; + static const GLfloat xforms[6][4] = { + { 0, 0, 1, 0 }, + { 90, 0, 1, 0 }, + { 180, 0, 1, 0 }, + { 270, 0, 1, 0 }, + { 90, 1, 0, 0 }, + { -90, 1, 0, 0 } + }; + GLint i; + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + if (blend) { + glDisable(GL_DEPTH_TEST); + glEnable(GL_BLEND); + } else { + glEnable(GL_DEPTH_TEST); + glDisable(GL_BLEND); + } + + glVertexPointer(2, GL_FLOAT, 0, verts); + glColorPointer(4, GL_FLOAT, 0, colors); + glTexCoordPointer(2, GL_FLOAT, 0, texs); + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + + for (i = 0; i < 6; i++) { + glPushMatrix(); + glRotatef(xforms[i][0], xforms[i][1], xforms[i][2], xforms[i][3]); + glTranslatef(0, 0, 4.1); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + glPopMatrix(); + } + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); +} + +static void +draw(void) +{ + use_pbuffer(); + draw_triangle(); + + use_window(); + + eglBindTexImage(dpy, surf_pbuf, EGL_BACK_BUFFER); + + glPushMatrix(); + glRotatef(view_rotx, 1, 0, 0); + glRotatef(view_roty, 0, 1, 0); + glRotatef(view_rotz, 0, 0, 1); + + draw_textured_cube(); + + glPopMatrix(); + + eglReleaseTexImage(dpy, surf_pbuf, EGL_BACK_BUFFER); +} + +/* new window size or exposure */ +static void +reshape(int width, int height) +{ + GLfloat ar = (GLfloat) width / (GLfloat) height; + + use_window(); + + glViewport(0, 0, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum(-ar, ar, -1, 1, 5.0, 60.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0.0, 0.0, -40.0); +} + +static void +event_loop(Display *x_dpy, Window win) +{ + while (1) { + int redraw = 1; + + if (XPending(x_dpy) > 0) { + XEvent event; + XNextEvent(x_dpy, &event); + + switch (event.type) { + case Expose: + redraw = 1; + break; + case ConfigureNotify: + reshape(event.xconfigure.width, event.xconfigure.height); + break; + case KeyPress: + { + char buffer[10]; + int r, code; + code = XLookupKeysym(&event.xkey, 0); + if (code == XK_Left) { + view_roty += 5.0; + } + else if (code == XK_Right) { + view_roty -= 5.0; + } + else if (code == XK_Up) { + view_rotx += 5.0; + } + else if (code == XK_Down) { + view_rotx -= 5.0; + } + else if (code == XK_b) { + blend = !blend; + } + else { + r = XLookupString(&event.xkey, buffer, sizeof(buffer), + NULL, NULL); + if (buffer[0] == 27) { + /* escape */ + return; + } + } + } + redraw = 1; + break; + default: + ; /*no-op*/ + } + } + + if (redraw) { + view_rotx += 1.0; + view_roty += 2.0; + view_rotz += 1.5; + color_flow += 20; + draw(); + eglSwapBuffers(dpy, surf_win); + } + } +} + +int +main(int argc, char *argv[]) +{ + const int winWidth = 300, winHeight = 300; + Display *x_dpy; + Window win; + char *dpyName = NULL; + EGLint egl_major, egl_minor; + const char *s; + + x_dpy = XOpenDisplay(dpyName); + if (!x_dpy) { + printf("Error: couldn't open display %s\n", + dpyName ? dpyName : getenv("DISPLAY")); + return -1; + } + + dpy = eglGetDisplay(x_dpy); + if (!dpy) { + printf("Error: eglGetDisplay() failed\n"); + return -1; + } + + if (!eglInitialize(dpy, &egl_major, &egl_minor)) { + printf("Error: eglInitialize() failed\n"); + return -1; + } + + s = eglQueryString(dpy, EGL_VERSION); + printf("EGL_VERSION = %s\n", s); + + make_window(x_dpy, "color flow", 0, 0, winWidth, winHeight, &win); + make_pbuffer(winWidth, winHeight); + + XMapWindow(x_dpy, win); + + reshape(winWidth, winHeight); + event_loop(x_dpy, win); + + glDeleteTextures(1, &tex_pbuf); + + eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglTerminate(dpy); + + XDestroyWindow(x_dpy, win); + XCloseDisplay(x_dpy); + + return 0; +} diff --git a/progs/glsl/Makefile b/progs/glsl/Makefile index eedd866c95..0875bdd795 100644 --- a/progs/glsl/Makefile +++ b/progs/glsl/Makefile @@ -14,6 +14,11 @@ LIBS = -L$(TOP)/$(LIB_DIR) -l$(GLUT_LIB) -l$(GLEW_LIB) -l$(GLU_LIB) -l$(GL_LIB) INCLUDE_DIRS = -I$(TOP)/progs/util +# using : to avoid APP_CC pointing to CC loop +CC:=$(APP_CC) +CFLAGS += -I$(INCDIR) +LDLIBS=$(LIBS) + DEMO_SOURCES = \ array.c \ bitmap.c \ @@ -33,6 +38,7 @@ DEMO_SOURCES = \ points.c \ samplers.c \ shadow_sampler.c \ + shtest.c \ skinning.c \ texaaline.c \ texdemo1.c \ @@ -52,28 +58,16 @@ UTIL_SOURCES = \ readtex.c UTIL_OBJS = $(UTIL_SOURCES:.c=.o) - - +PROG_OBJS = $(DEMO_SOURCES:.c=.o) PROGS = $(DEMO_SOURCES:%.c=%) - - -##### RULES ##### - -# make .o file from .c file: -.c.o: - $(APP_CC) -c -I$(INCDIR) $(CFLAGS) $< -o $@ - - -# make executable from .o files -.o: - $(APP_CC) $(INCLUDES) $(CFLAGS) $(LDFLAGS) $< $(UTIL_OBJS) $(LIBS) -o $@ - - ##### TARGETS ##### default: $(PROGS) +$(PROG_OBJS): $(UTIL_HEADERS) + +$(PROGS): $(UTIL_OBJS) clean: -rm -f $(PROGS) @@ -83,7 +77,6 @@ clean: -rm -f readtex.* - ##### Extra dependencies extfuncs.h: $(TOP)/progs/util/extfuncs.h @@ -101,138 +94,3 @@ shaderutil.c: $(TOP)/progs/util/shaderutil.c shaderutil.h: $(TOP)/progs/util/shaderutil.h cp $< . - - -array.o: $(UTIL_HEADERS) - -array: array.o $(UTIL_OBJS) - - -bitmap.o: $(UTIL_HEADERS) - -bitmap: bitmap.o $(UTIL_OBJS) - - -brick.o: $(UTIL_HEADERS) - -brick: brick.o $(UTIL_OBJS) - - -bump.o: $(UTIL_HEADERS) - -bump: bump.o $(UTIL_OBJS) - - -convolutions.o: $(UTIL_HEADERS) - -convolutions: convolutions.o $(UTIL_OBJS) - - -deriv.o: deriv.c $(UTIL_HEADERS) - -deriv: deriv.o $(UTIL_OBJS) - - -identity.o: $(UTIL_HEADERS) - -identity: identity.o $(UTIL_OBJS) - - -fragcoord.o: $(UTIL_HEADERS) - -fragcoord: fragcoord.o $(UTIL_OBJS) - - -linktest.o: $(UTIL_HEADERS) - -linktest: linktest.o $(UTIL_OBJS) - - -mandelbrot.o: $(UTIL_HEADERS) - -mandelbrot: mandelbrot.o $(UTIL_OBJS) - - -multinoise.o: $(UTIL_HEADERS) - -multinoise: multinoise.o $(UTIL_OBJS) - - -multitex.o: $(UTIL_HEADERS) - -multitex: multitex.o $(UTIL_OBJS) - - -noise.o: $(UTIL_HEADERS) - -noise: noise.o $(UTIL_OBJS) - - -noise2.o: $(UTIL_HEADERS) - -noise2: noise2.o $(UTIL_OBJS) - - -points.o: $(UTIL_HEADERS) - -points: points.o $(UTIL_OBJS) - - -pointcoord.o: $(UTIL_HEADERS) - -pointcoord: pointcoord.o $(UTIL_OBJS) - - -samplers.o: $(UTIL_HEADERS) - -samplers: samplers.o $(UTIL_OBJS) - - -samplers_array.o: $(UTIL_HEADERS) - -samplers_array: samplers_array.o $(UTIL_OBJS) - - -shadow_sampler.o: $(UTIL_HEADERS) - -shadow_sampler: shadow_sampler.o $(UTIL_OBJS) - - -skinning.o: $(UTIL_HEADERS) - -skinning: skinning.o $(UTIL_OBJS) - - -texaaline.o: $(UTIL_HEADERS) - -texaaline: texaaline.o $(UTIL_OBJS) - - -texdemo1.o: $(UTIL_HEADERS) - -texdemo1: texdemo1.o $(UTIL_OBJS) - - -toyball.o: $(UTIL_HEADERS) - -toyball: toyball.o $(UTIL_OBJS) - - -twoside.o: $(UTIL_HEADERS) - -twoside: twoside.o $(UTIL_OBJS) - - -trirast.o: $(UTIL_HEADERS) - -trirast: trirast.o $(UTIL_OBJS) - - -vert-or-frag-only.o: $(UTIL_HEADERS) - -vert-or-frag-only: vert-or-frag-only.o $(UTIL_OBJS) - - -vert-tex.o: $(UTIL_HEADERS) - -vert-tex: vert-tex.o $(UTIL_OBJS) diff --git a/progs/glsl/brick.c b/progs/glsl/brick.c index 1d08b231e7..0653c592e5 100644 --- a/progs/glsl/brick.c +++ b/progs/glsl/brick.c @@ -24,12 +24,12 @@ static GLuint program; static struct uniform_info Uniforms[] = { /* vert */ - { "LightPosition", 3, GL_FLOAT, { 0.1, 0.1, 9.0, 0}, -1 }, + { "LightPosition", 1, GL_FLOAT_VEC3, { 0.1, 0.1, 9.0, 0}, -1 }, /* frag */ - { "BrickColor", 3, GL_FLOAT, { 0.8, 0.2, 0.2, 0 }, -1 }, - { "MortarColor", 3, GL_FLOAT, { 0.6, 0.6, 0.6, 0 }, -1 }, - { "BrickSize", 2, GL_FLOAT, { 1.0, 0.3, 0, 0 }, -1 }, - { "BrickPct", 2, GL_FLOAT, { 0.9, 0.8, 0, 0 }, -1 }, + { "BrickColor", 1, GL_FLOAT_VEC3, { 0.8, 0.2, 0.2, 0 }, -1 }, + { "MortarColor", 1, GL_FLOAT_VEC3, { 0.6, 0.6, 0.6, 0 }, -1 }, + { "BrickSize", 1, GL_FLOAT_VEC2, { 1.0, 0.3, 0, 0 }, -1 }, + { "BrickPct", 1, GL_FLOAT_VEC2, { 0.9, 0.8, 0, 0 }, -1 }, END_OF_UNIFORMS }; @@ -148,7 +148,8 @@ Init(void) glUseProgram(program); - InitUniforms(program, Uniforms); + SetUniformValues(program, Uniforms); + PrintUniforms(Uniforms); assert(glGetError() == 0); diff --git a/progs/glsl/brick.shtest b/progs/glsl/brick.shtest new file mode 100644 index 0000000000..8a2152692e --- /dev/null +++ b/progs/glsl/brick.shtest @@ -0,0 +1,8 @@ +vs CH06-brick.vert +fs CH06-brick.frag +uniform LightPosition GL_FLOAT_VEC3 0.1 0.1 9.0 +uniform BrickColor GL_FLOAT_VEC3 0.8 0.2 0.2 +uniform MortarColor GL_FLOAT_VEC3 0.6 0.6 0.6 +uniform BrickSize GL_FLOAT_VEC2 1.0 0.3 +uniform BrickPct GL_FLOAT_VEC2 0.9 0.8 + diff --git a/progs/glsl/bump.c b/progs/glsl/bump.c index ddb986abcb..c0d39c049d 100644 --- a/progs/glsl/bump.c +++ b/progs/glsl/bump.c @@ -24,11 +24,11 @@ static GLuint program; static struct uniform_info Uniforms[] = { - { "LightPosition", 3, GL_FLOAT, { 0.57737, 0.57735, 0.57735, 0.0 }, -1 }, - { "SurfaceColor", 3, GL_FLOAT, { 0.8, 0.8, 0.2, 0 }, -1 }, - { "BumpDensity", 1, GL_FLOAT, { 10.0, 0, 0, 0 }, -1 }, - { "BumpSize", 1, GL_FLOAT, { 0.125, 0, 0, 0 }, -1 }, - { "SpecularFactor", 1, GL_FLOAT, { 0.5, 0, 0, 0 }, -1 }, + { "LightPosition", 1, GL_FLOAT_VEC3, { 0.57737, 0.57735, 0.57735, 0.0 }, -1 }, + { "SurfaceColor", 1, GL_FLOAT_VEC3, { 0.8, 0.8, 0.2, 0 }, -1 }, + { "BumpDensity", 1, GL_FLOAT, { 10.0, 0, 0, 0 }, -1 }, + { "BumpSize", 1, GL_FLOAT, { 0.125, 0, 0, 0 }, -1 }, + { "SpecularFactor", 1, GL_FLOAT, { 0.5, 0, 0, 0 }, -1 }, END_OF_UNIFORMS }; @@ -242,7 +242,8 @@ Init(void) CheckError(__LINE__); - InitUniforms(program, Uniforms); + SetUniformValues(program, Uniforms); + PrintUniforms(Uniforms); CheckError(__LINE__); diff --git a/progs/glsl/mandelbrot.c b/progs/glsl/mandelbrot.c index 38dffc3e74..729a6f125a 100644 --- a/progs/glsl/mandelbrot.c +++ b/progs/glsl/mandelbrot.c @@ -25,7 +25,7 @@ static GLuint program; static struct uniform_info Uniforms[] = { /* vert */ - { "LightPosition", 3, GL_FLOAT, { 0.1, 0.1, 9.0, 0}, -1 }, + { "LightPosition", 1, GL_FLOAT_VEC3, { 0.1, 0.1, 9.0, 0}, -1 }, { "SpecularContribution", 1, GL_FLOAT, { 0.5, 0, 0, 0 }, -1 }, { "DiffuseContribution", 1, GL_FLOAT, { 0.5, 0, 0, 0 }, -1 }, { "Shininess", 1, GL_FLOAT, { 20.0, 0, 0, 0 }, -1 }, @@ -34,9 +34,9 @@ static struct uniform_info Uniforms[] = { { "Zoom", 1, GL_FLOAT, { 0.125, 0, 0, 0 }, -1 }, { "Xcenter", 1, GL_FLOAT, { -1.5, 0, 0, 0 }, -1 }, { "Ycenter", 1, GL_FLOAT, { .005, 0, 0, 0 }, -1 }, - { "InnerColor", 3, GL_FLOAT, { 1, 0, 0, 0 }, -1 }, - { "OuterColor1", 3, GL_FLOAT, { 0, 1, 0, 0 }, -1 }, - { "OuterColor2", 3, GL_FLOAT, { 0, 0, 1, 0 }, -1 }, + { "InnerColor", 1, GL_FLOAT_VEC3, { 1, 0, 0, 0 }, -1 }, + { "OuterColor1", 1, GL_FLOAT_VEC3, { 0, 1, 0, 0 }, -1 }, + { "OuterColor2", 1, GL_FLOAT_VEC3, { 0, 0, 1, 0 }, -1 }, END_OF_UNIFORMS }; @@ -159,7 +159,8 @@ Init(void) glUseProgram(program); - InitUniforms(program, Uniforms); + SetUniformValues(program, Uniforms); + PrintUniforms(Uniforms); uZoom = glGetUniformLocation(program, "Zoom"); uXcenter = glGetUniformLocation(program, "Xcenter"); diff --git a/progs/glsl/mandelbrot.shtest b/progs/glsl/mandelbrot.shtest new file mode 100644 index 0000000000..4f4e5c747e --- /dev/null +++ b/progs/glsl/mandelbrot.shtest @@ -0,0 +1,13 @@ +vs CH18-mandel.vert +fs CH18-mandel.frag +uniform LightPosition GL_FLOAT_VEC3 0.1 0.1 9.0 +uniform SpecularContribution GL_FLOAT 0.5 +uniform DiffuseContribution GL_FLOAT 0.5 +uniform Shininess GL_FLOAT 20.0 +uniform Iterations GL_FLOAT 12 +uniform Zoom GL_FLOAT 0.125 +uniform Xcenter GL_FLOAT -1.5 +uniform Ycenter GL_FLOAT .005 +uniform InnerColor GL_FLOAT_VEC3 1 0 0 +uniform OuterColor1 GL_FLOAT_VEC3 0 1 0 +uniform OuterColor2 GL_FLOAT_VEC3 0 0 1 diff --git a/progs/glsl/multitex.c b/progs/glsl/multitex.c index 5e971716ad..6ec9c833e6 100644 --- a/progs/glsl/multitex.c +++ b/progs/glsl/multitex.c @@ -59,8 +59,8 @@ static GLint VertCoord_attr = -1, TexCoord0_attr = -1, TexCoord1_attr = -1; /* value[0] = tex unit */ static struct uniform_info Uniforms[] = { - { "tex1", 1, GL_INT, { 0, 0, 0, 0 }, -1 }, - { "tex2", 1, GL_INT, { 1, 0, 0, 0 }, -1 }, + { "tex1", 1, GL_SAMPLER_2D, { 0, 0, 0, 0 }, -1 }, + { "tex2", 1, GL_SAMPLER_2D, { 1, 0, 0, 0 }, -1 }, END_OF_UNIFORMS }; @@ -134,7 +134,7 @@ DrawPolygonArray(void) if (VertCoord_attr >= 0) { glVertexAttribPointer(VertCoord_attr, 2, GL_FLOAT, GL_FALSE, - 0, VertCoords); + 0, vertPtr); glEnableVertexAttribArray(VertCoord_attr); } else { @@ -143,11 +143,11 @@ DrawPolygonArray(void) } glVertexAttribPointer(TexCoord0_attr, 2, GL_FLOAT, GL_FALSE, - 0, Tex0Coords); + 0, tex0Ptr); glEnableVertexAttribArray(TexCoord0_attr); glVertexAttribPointer(TexCoord1_attr, 2, GL_FLOAT, GL_FALSE, - 0, Tex1Coords); + 0, tex1Ptr); glEnableVertexAttribArray(TexCoord1_attr); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); @@ -328,7 +328,8 @@ CreateProgram(const char *vertProgFile, const char *fragProgFile, glUseProgram(program); - InitUniforms(program, uniforms); + SetUniformValues(program, uniforms); + PrintUniforms(Uniforms); VertCoord_attr = glGetAttribLocation(program, "VertCoord"); if (VertCoord_attr > 0) { diff --git a/progs/glsl/multitex.shtest b/progs/glsl/multitex.shtest new file mode 100644 index 0000000000..5be45f6c7c --- /dev/null +++ b/progs/glsl/multitex.shtest @@ -0,0 +1,6 @@ +vs multitex.vert +fs multitex.frag +texture 0 ../images/tile.rgb +texture 1 ../images/tree2.rgba +uniform tex1 GL_SAMPLER_2D 0 +uniform tex2 GL_SAMPLER_2D 1 diff --git a/progs/glsl/noise.c b/progs/glsl/noise.c index 59f594e78b..8c36e1c59b 100644 --- a/progs/glsl/noise.c +++ b/progs/glsl/noise.c @@ -35,8 +35,8 @@ static const char *FragShaderText = static struct uniform_info Uniforms[] = { - { "Scale", 4, GL_FLOAT, { 0.5, 0.4, 0.0, 0}, -1 }, - { "Bias", 4, GL_FLOAT, { 0.5, 0.3, 0.0, 0}, -1 }, + { "Scale", 1, GL_FLOAT_VEC4, { 0.5, 0.4, 0.0, 0}, -1 }, + { "Bias", 1, GL_FLOAT_VEC4, { 0.5, 0.3, 0.0, 0}, -1 }, { "Slice", 1, GL_FLOAT, { 0.5, 0, 0, 0}, -1 }, END_OF_UNIFORMS }; @@ -179,7 +179,8 @@ Init(void) glUseProgram(program); - InitUniforms(program, Uniforms); + SetUniformValues(program, Uniforms); + PrintUniforms(Uniforms); assert(glGetError() == 0); diff --git a/progs/glsl/shtest.c b/progs/glsl/shtest.c new file mode 100644 index 0000000000..97f6f9f8a4 --- /dev/null +++ b/progs/glsl/shtest.c @@ -0,0 +1,630 @@ +/* + * Simple shader test harness. + * Brian Paul + * 13 Aug 2009 + * + * Usage: + * shtest --vs vertShaderFile --fs fragShaderFile + * + * In this case the given vertex/frag shaders are read and compiled. + * Random values are assigned to the uniforms. + * + * or: + * shtest configFile + * + * In this case a config file is read that specifies the file names + * of the shaders plus initial values for uniforms. + * + * Example config file: + * + * vs shader.vert + * fs shader.frag + * uniform pi 3.14159 + * uniform v1 1.0 0.5 0.2 0.3 + * + */ + + +#include <assert.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include <GL/glew.h> +#include <GL/glu.h> +#include <GL/glut.h> +#include "shaderutil.h" +#include "readtex.h" + + +typedef enum +{ + SPHERE, + CUBE, + NUM_SHAPES +} shape; + + +static char *FragShaderFile = NULL; +static char *VertShaderFile = NULL; +static char *ConfigFile = NULL; + +/* program/shader objects */ +static GLuint fragShader; +static GLuint vertShader; +static GLuint Program; + + +#define MAX_UNIFORMS 100 +static struct uniform_info Uniforms[MAX_UNIFORMS]; +static GLuint NumUniforms = 0; + + +#define MAX_ATTRIBS 100 +static struct attrib_info Attribs[MAX_ATTRIBS]; +static GLuint NumAttribs = 0; + + +/** + * Config file info. + */ +struct config_file +{ + struct name_value + { + char name[100]; + float value[4]; + int type; + } uniforms[100]; + + int num_uniforms; +}; + + +static GLint win = 0; +static GLboolean Anim = GL_FALSE; +static GLfloat TexRot = 0.0; +static GLfloat xRot = 0.0f, yRot = 0.0f, zRot = 0.0f; +static shape Object = SPHERE; + + +static float +RandomFloat(float min, float max) +{ + int k = rand() % 10000; + float x = min + (max - min) * k / 10000.0; + return x; +} + + +/** Set new random values for uniforms */ +static void +RandomUniformValues(void) +{ + GLuint i; + for (i = 0; i < NumUniforms; i++) { + if (Uniforms[i].type == GL_FLOAT) { + Uniforms[i].value[0] = RandomFloat(0.0, 1.0); + } + else { + Uniforms[i].value[0] = RandomFloat(-1.0, 2.0); + Uniforms[i].value[1] = RandomFloat(-1.0, 2.0); + Uniforms[i].value[2] = RandomFloat(-1.0, 2.0); + Uniforms[i].value[3] = RandomFloat(-1.0, 2.0); + } + } +} + + +static void +Idle(void) +{ + yRot += 2.0; + if (yRot > 360.0) + yRot -= 360.0; + glutPostRedisplay(); +} + + + +static void +SquareVertex(GLfloat s, GLfloat t, GLfloat size) +{ + GLfloat x = -size + s * 2.0 * size; + GLfloat y = -size + t * 2.0 * size; + GLuint i; + + glMultiTexCoord2f(GL_TEXTURE0, s, t); + glMultiTexCoord2f(GL_TEXTURE1, s, t); + glMultiTexCoord2f(GL_TEXTURE2, s, t); + glMultiTexCoord2f(GL_TEXTURE3, s, t); + + /* assign (s,t) to the generic attributes */ + for (i = 0; i < NumAttribs; i++) { + if (Attribs[i].location >= 0) { + glVertexAttrib2f(Attribs[i].location, s, t); + } + } + + glVertex2f(x, y); +} + + +/* + * Draw a square, specifying normal and tangent vectors. + */ +static void +Square(GLfloat size) +{ + GLint tangentAttrib = 1; + glNormal3f(0, 0, 1); + glVertexAttrib3f(tangentAttrib, 1, 0, 0); + glBegin(GL_POLYGON); +#if 1 + SquareVertex(0, 0, size); + SquareVertex(1, 0, size); + SquareVertex(1, 1, size); + SquareVertex(0, 1, size); +#else + glTexCoord2f(0, 0); glVertex2f(-size, -size); + glTexCoord2f(1, 0); glVertex2f( size, -size); + glTexCoord2f(1, 1); glVertex2f( size, size); + glTexCoord2f(0, 1); glVertex2f(-size, size); +#endif + glEnd(); +} + + +static void +Cube(GLfloat size) +{ + /* +X */ + glPushMatrix(); + glRotatef(90, 0, 1, 0); + glTranslatef(0, 0, size); + Square(size); + glPopMatrix(); + + /* -X */ + glPushMatrix(); + glRotatef(-90, 0, 1, 0); + glTranslatef(0, 0, size); + Square(size); + glPopMatrix(); + + /* +Y */ + glPushMatrix(); + glRotatef(90, 1, 0, 0); + glTranslatef(0, 0, size); + Square(size); + glPopMatrix(); + + /* -Y */ + glPushMatrix(); + glRotatef(-90, 1, 0, 0); + glTranslatef(0, 0, size); + Square(size); + glPopMatrix(); + + + /* +Z */ + glPushMatrix(); + glTranslatef(0, 0, size); + Square(size); + glPopMatrix(); + + /* -Z */ + glPushMatrix(); + glRotatef(180, 0, 1, 0); + glTranslatef(0, 0, size); + Square(size); + glPopMatrix(); +} + + +static void +Sphere(GLfloat radius, GLint slices, GLint stacks) +{ + static GLUquadricObj *q = NULL; + + if (!q) { + q = gluNewQuadric(); + gluQuadricDrawStyle(q, GLU_FILL); + gluQuadricNormals(q, GLU_SMOOTH); + gluQuadricTexture(q, GL_TRUE); + } + + gluSphere(q, radius, slices, stacks); +} + + +static void +Redisplay(void) +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix(); + glRotatef(xRot, 1.0f, 0.0f, 0.0f); + glRotatef(yRot, 0.0f, 1.0f, 0.0f); + glRotatef(zRot, 0.0f, 0.0f, 1.0f); + + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glRotatef(TexRot, 0.0f, 1.0f, 0.0f); + glMatrixMode(GL_MODELVIEW); + + if (Object == SPHERE) { + Sphere(2.0, 20, 10); + } + else if (Object == CUBE) { + Cube(2.0); + } + + glPopMatrix(); + + glutSwapBuffers(); +} + + +static void +Reshape(int width, int height) +{ + glViewport(0, 0, width, height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0.0f, 0.0f, -15.0f); +} + + +static void +CleanUp(void) +{ + glDeleteShader(fragShader); + glDeleteShader(vertShader); + glDeleteProgram(Program); + glutDestroyWindow(win); +} + + +static void +Key(unsigned char key, int x, int y) +{ + const GLfloat step = 2.0; + (void) x; + (void) y; + + switch(key) { + case 'a': + Anim = !Anim; + if (Anim) + glutIdleFunc(Idle); + else + glutIdleFunc(NULL); + break; + case 'z': + zRot += step; + break; + case 'Z': + zRot -= step; + break; + case 'o': + Object = (Object + 1) % NUM_SHAPES; + break; + case 'r': + RandomUniformValues(); + SetUniformValues(Program, Uniforms); + PrintUniforms(Uniforms); + break; + case 27: + CleanUp(); + exit(0); + break; + } + glutPostRedisplay(); +} + + +static void +SpecialKey(int key, int x, int y) +{ + const GLfloat step = 2.0; + + (void) x; + (void) y; + + switch(key) { + case GLUT_KEY_UP: + xRot += step; + break; + case GLUT_KEY_DOWN: + xRot -= step; + break; + case GLUT_KEY_LEFT: + yRot -= step; + break; + case GLUT_KEY_RIGHT: + yRot += step; + break; + } + glutPostRedisplay(); +} + + +static void +InitUniforms(const struct config_file *conf, + struct uniform_info uniforms[]) +{ + int i; + + for (i = 0; i < conf->num_uniforms; i++) { + int j; + for (j = 0; uniforms[j].name; j++) { + if (strcmp(uniforms[j].name, conf->uniforms[i].name) == 0) { + uniforms[j].type = conf->uniforms[i].type; + uniforms[j].value[0] = conf->uniforms[i].value[0]; + uniforms[j].value[1] = conf->uniforms[i].value[1]; + uniforms[j].value[2] = conf->uniforms[i].value[2]; + uniforms[j].value[3] = conf->uniforms[i].value[3]; + } + } + } +} + + +static void +LoadTexture(GLint unit, const char *texFileName) +{ + GLint imgWidth, imgHeight; + GLenum imgFormat; + GLubyte *image = NULL; + GLuint tex; + GLenum filter = GL_LINEAR; + + image = LoadRGBImage(texFileName, &imgWidth, &imgHeight, &imgFormat); + if (!image) { + printf("Couldn't read %s\n", texFileName); + exit(1); + } + + printf("Load Texture: unit %d: %s %d x %d\n", + unit, texFileName, imgWidth, imgHeight); + + glActiveTexture(GL_TEXTURE0 + unit); + glGenTextures(1, &tex); + glBindTexture(GL_TEXTURE_2D, tex); + + gluBuild2DMipmaps(GL_TEXTURE_2D, 4, imgWidth, imgHeight, + imgFormat, GL_UNSIGNED_BYTE, image); + free(image); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); +} + + +static GLenum +TypeFromName(const char *n) +{ + static const struct { + const char *name; + GLenum type; + } types[] = { + { "GL_FLOAT", GL_FLOAT }, + { "GL_FLOAT_VEC2", GL_FLOAT_VEC2 }, + { "GL_FLOAT_VEC3", GL_FLOAT_VEC3 }, + { "GL_FLOAT_VEC4", GL_FLOAT_VEC4 }, + { "GL_INT", GL_INT }, + { "GL_INT_VEC2", GL_INT_VEC2 }, + { "GL_INT_VEC3", GL_INT_VEC3 }, + { "GL_INT_VEC4", GL_INT_VEC4 }, + { "GL_SAMPLER_2D", GL_SAMPLER_2D }, + { NULL, 0 } + }; + GLuint i; + + for (i = 0; types[i].name; i++) { + if (strcmp(types[i].name, n) == 0) + return types[i].type; + } + abort(); + return GL_NONE; +} + + + +/** + * Read a config file. + */ +static void +ReadConfigFile(const char *filename, struct config_file *conf) +{ + char line[1000]; + FILE *f; + + f = fopen(filename, "r"); + if (!f) { + fprintf(stderr, "Unable to open config file %s\n", filename); + exit(1); + } + + conf->num_uniforms = 0; + + /* ugly but functional parser */ + while (!feof(f)) { + fgets(line, sizeof(line), f); + if (!feof(f) && line[0]) { + if (strncmp(line, "vs ", 3) == 0) { + VertShaderFile = strdup(line + 3); + VertShaderFile[strlen(VertShaderFile) - 1] = 0; + } + else if (strncmp(line, "fs ", 3) == 0) { + FragShaderFile = strdup(line + 3); + FragShaderFile[strlen(FragShaderFile) - 1] = 0; + } + else if (strncmp(line, "texture ", 8) == 0) { + char texFileName[100]; + int unit, k; + k = sscanf(line + 8, "%d %s", &unit, texFileName); + assert(k == 2); + LoadTexture(unit, texFileName); + } + else if (strncmp(line, "uniform ", 8) == 0) { + char name[1000], typeName[100]; + int k; + float v1 = 0.0F, v2 = 0.0F, v3 = 0.0F, v4 = 0.0F; + GLenum type; + + k = sscanf(line + 8, "%s %s %f %f %f %f", name, typeName, + &v1, &v2, &v3, &v4); + + type = TypeFromName(typeName); + + strcpy(conf->uniforms[conf->num_uniforms].name, name); + conf->uniforms[conf->num_uniforms].value[0] = v1; + conf->uniforms[conf->num_uniforms].value[1] = v2; + conf->uniforms[conf->num_uniforms].value[2] = v3; + conf->uniforms[conf->num_uniforms].value[3] = v4; + conf->uniforms[conf->num_uniforms].type = type; + conf->num_uniforms++; + } + else { + if (strlen(line) > 1) { + fprintf(stderr, "syntax error in: %s\n", line); + break; + } + } + } + } + + fclose(f); +} + + +static void +Init(void) +{ + struct config_file config; + memset(&config, 0, sizeof(config)); + + if (ConfigFile) + ReadConfigFile(ConfigFile, &config); + + if (!VertShaderFile) { + fprintf(stderr, "Error: no vertex shader\n"); + exit(1); + } + + if (!FragShaderFile) { + fprintf(stderr, "Error: no fragment shader\n"); + exit(1); + } + + if (!ShadersSupported()) + exit(1); + + vertShader = CompileShaderFile(GL_VERTEX_SHADER, VertShaderFile); + fragShader = CompileShaderFile(GL_FRAGMENT_SHADER, FragShaderFile); + Program = LinkShaders(vertShader, fragShader); + + glUseProgram(Program); + + NumUniforms = GetUniforms(Program, Uniforms); + if (config.num_uniforms) { + InitUniforms(&config, Uniforms); + } + else { + RandomUniformValues(); + } + SetUniformValues(Program, Uniforms); + PrintUniforms(Uniforms); + + NumAttribs = GetAttribs(Program, Attribs); + PrintAttribs(Attribs); + + //assert(glGetError() == 0); + + glClearColor(0.4f, 0.4f, 0.8f, 0.0f); + + glEnable(GL_DEPTH_TEST); + + glColor3f(1, 0, 0); +} + + +static void +Keys(void) +{ + printf("Keyboard:\n"); + printf(" a Animation toggle\n"); + printf(" r Randomize uniform values\n"); + printf(" o Change object\n"); + printf(" arrows Rotate object\n"); + printf(" ESC Exit\n"); +} + + +static void +Usage(void) +{ + printf("Usage:\n"); + printf(" shtest config.shtest\n"); + printf(" Run w/ given config file.\n"); + printf(" shtest --vs vertShader --fs fragShader\n"); + printf(" Load/compile given shaders.\n"); +} + + +static void +ParseOptions(int argc, char *argv[]) +{ + int i; + + if (argc == 1) { + Usage(); + exit(1); + } + + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "--fs") == 0) { + FragShaderFile = argv[i+1]; + i++; + } + else if (strcmp(argv[i], "--vs") == 0) { + VertShaderFile = argv[i+1]; + i++; + } + else { + /* assume the arg is a config file */ + ConfigFile = argv[i]; + break; + } + } +} + + +int +main(int argc, char *argv[]) +{ + glutInit(&argc, argv); + glutInitWindowPosition( 0, 0); + glutInitWindowSize(400, 400); + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); + win = glutCreateWindow(argv[0]); + glewInit(); + glutReshapeFunc(Reshape); + glutKeyboardFunc(Key); + glutSpecialFunc(SpecialKey); + glutDisplayFunc(Redisplay); + ParseOptions(argc, argv); + Init(); + Keys(); + glutMainLoop(); + return 0; +} + diff --git a/progs/glsl/texdemo1.c b/progs/glsl/texdemo1.c index d55f9e7dd9..5b1913a722 100644 --- a/progs/glsl/texdemo1.c +++ b/progs/glsl/texdemo1.c @@ -53,14 +53,14 @@ static int win = 0; static struct uniform_info ReflectUniforms[] = { - { "cubeTex", 1, GL_INT, { 0, 0, 0, 0 }, -1 }, - { "lightPos", 3, GL_FLOAT, { 10, 10, 20, 0 }, -1 }, + { "cubeTex", 1, GL_SAMPLER_CUBE, { 0, 0, 0, 0 }, -1 }, + { "lightPos", 1, GL_FLOAT_VEC3, { 10, 10, 20, 0 }, -1 }, END_OF_UNIFORMS }; static struct uniform_info SimpleUniforms[] = { - { "tex2d", 1, GL_INT, { 1, 0, 0, 0 }, -1 }, - { "lightPos", 3, GL_FLOAT, { 10, 10, 20, 0 }, -1 }, + { "tex2d", 1, GL_SAMPLER_2D, { 1, 0, 0, 0 }, -1 }, + { "lightPos", 1, GL_FLOAT_VEC3, { 10, 10, 20, 0 }, -1 }, END_OF_UNIFORMS }; @@ -382,7 +382,8 @@ CreateProgram(const char *vertProgFile, const char *fragProgFile, glUseProgram(program); - InitUniforms(program, uniforms); + SetUniformValues(program, uniforms); + PrintUniforms(uniforms); return program; } diff --git a/progs/glsl/toyball.c b/progs/glsl/toyball.c index 7fe27aebfe..89733d6175 100644 --- a/progs/glsl/toyball.c +++ b/progs/glsl/toyball.c @@ -24,18 +24,18 @@ static GLuint program; static struct uniform_info Uniforms[] = { - { "LightDir", 4, GL_FLOAT, { 0.57737, 0.57735, 0.57735, 0.0 }, -1 }, - { "HVector", 4, GL_FLOAT, { 0.32506, 0.32506, 0.88808, 0.0 }, -1 }, - { "BallCenter", 4, GL_FLOAT, { 0.0, 0.0, 0.0, 1.0 }, -1 }, - { "SpecularColor", 4, GL_FLOAT, { 0.4, 0.4, 0.4, 60.0 }, -1 }, - { "Red", 4, GL_FLOAT, { 0.6, 0.0, 0.0, 1.0 }, -1 }, - { "Blue", 4, GL_FLOAT, { 0.0, 0.3, 0.6, 1.0 }, -1 }, - { "Yellow", 4, GL_FLOAT, { 0.6, 0.5, 0.0, 1.0 }, -1 }, - { "HalfSpace0", 4, GL_FLOAT, { 1.0, 0.0, 0.0, 0.2 }, -1 }, - { "HalfSpace1", 4, GL_FLOAT, { 0.309016994, 0.951056516, 0.0, 0.2 }, -1 }, - { "HalfSpace2", 4, GL_FLOAT, { -0.809016994, 0.587785252, 0.0, 0.2 }, -1 }, - { "HalfSpace3", 4, GL_FLOAT, { -0.809016994, -0.587785252, 0.0, 0.2 }, -1 }, - { "HalfSpace4", 4, GL_FLOAT, { 0.309116994, -0.951056516, 0.0, 0.2 }, -1 }, + { "LightDir", 1, GL_FLOAT_VEC4, { 0.57737, 0.57735, 0.57735, 0.0 }, -1 }, + { "HVector", 1, GL_FLOAT_VEC4, { 0.32506, 0.32506, 0.88808, 0.0 }, -1 }, + { "BallCenter", 1, GL_FLOAT_VEC4, { 0.0, 0.0, 0.0, 1.0 }, -1 }, + { "SpecularColor", 1, GL_FLOAT_VEC4, { 0.4, 0.4, 0.4, 60.0 }, -1 }, + { "Red", 1, GL_FLOAT_VEC4, { 0.6, 0.0, 0.0, 1.0 }, -1 }, + { "Blue", 1, GL_FLOAT_VEC4, { 0.0, 0.3, 0.6, 1.0 }, -1 }, + { "Yellow", 1, GL_FLOAT_VEC4, { 0.6, 0.5, 0.0, 1.0 }, -1 }, + { "HalfSpace0", 1, GL_FLOAT_VEC4, { 1.0, 0.0, 0.0, 0.2 }, -1 }, + { "HalfSpace1", 1, GL_FLOAT_VEC4, { 0.309016994, 0.951056516, 0.0, 0.2 }, -1 }, + { "HalfSpace2", 1, GL_FLOAT_VEC4, { -0.809016994, 0.587785252, 0.0, 0.2 }, -1 }, + { "HalfSpace3", 1, GL_FLOAT_VEC4, { -0.809016994, -0.587785252, 0.0, 0.2 }, -1 }, + { "HalfSpace4", 1, GL_FLOAT_VEC4, { 0.309116994, -0.951056516, 0.0, 0.2 }, -1 }, { "InOrOutInit", 1, GL_FLOAT, { -3.0, 0, 0, 0 }, -1 }, { "StripeWidth", 1, GL_FLOAT, { 0.3, 0, 0, 0 }, -1 }, { "FWidth", 1, GL_FLOAT, { 0.005, 0, 0, 0 }, -1 }, @@ -173,7 +173,8 @@ Init(void) glUseProgram(program); - InitUniforms(program, Uniforms); + SetUniformValues(program, Uniforms); + PrintUniforms(Uniforms); assert(glGetError() == 0); diff --git a/progs/glsl/toyball.shtest b/progs/glsl/toyball.shtest new file mode 100644 index 0000000000..887663abd3 --- /dev/null +++ b/progs/glsl/toyball.shtest @@ -0,0 +1,17 @@ +vs CH11-toyball.vert +fs CH11-toyball.frag +uniform LightDir GL_FLOAT_VEC4 0.57737 0.57735 0.57735 0.0 +uniform HVector GL_FLOAT_VEC4 0.32506 0.32506 0.88808 0.0 +uniform BallCenter GL_FLOAT_VEC4 0.0 0.0 0.0 1.0 +uniform SpecularColor GL_FLOAT_VEC4 0.4 0.4 0.4 60.0 +uniform Red GL_FLOAT_VEC4 0.6 0.0 0.0 1.0 +uniform Blue GL_FLOAT_VEC4 0.0 0.3 0.6 1.0 +uniform Yellow GL_FLOAT_VEC4 0.6 0.5 0.0 1.0 +uniform HalfSpace0 GL_FLOAT_VEC4 1.0 0.0 0.0 0.2 +uniform HalfSpace1 GL_FLOAT_VEC4 .309016994 0.951056516 0.0 0.2 +uniform HalfSpace2 GL_FLOAT_VEC4 -0.809016994 0.587785252 0.0 0.2 +uniform HalfSpace3 GL_FLOAT_VEC4 -0.809016994 -0.587785252 0.0 0.2 +uniform HalfSpace4 GL_FLOAT_VEC4 .309116994 -0.951056516 0.0 0.2 +uniform InOrOutInit GL_FLOAT -3.0 +uniform StripeWidth GL_FLOAT 0.3 +uniform FWidth GL_FLOAT .005 diff --git a/progs/glsl/vert-tex.c b/progs/glsl/vert-tex.c index e791a5759a..4c8bfa587a 100644 --- a/progs/glsl/vert-tex.c +++ b/progs/glsl/vert-tex.c @@ -43,7 +43,7 @@ static GLfloat xRot = -70.0f, yRot = 0.0f, zRot = 0.0f; /* value[0] = tex unit */ static struct uniform_info Uniforms[] = { - { "tex1", 1, GL_INT, { 0, 0, 0, 0 }, -1 }, + { "tex1", 1, GL_SAMPLER_2D, { 0, 0, 0, 0 }, -1 }, END_OF_UNIFORMS }; diff --git a/progs/tests/floattex.c b/progs/tests/floattex.c index ad14cacdcb..39302ce3af 100644 --- a/progs/tests/floattex.c +++ b/progs/tests/floattex.c @@ -33,7 +33,7 @@ static const char *VertShaderText = "} \n"; static struct uniform_info Uniforms[] = { - { "tex1", 1, GL_INT, { 0, 0, 0, 0 }, -1 }, + { "tex1", 1, GL_SAMPLER_2D, { 0, 0, 0, 0 }, -1 }, END_OF_UNIFORMS }; @@ -189,7 +189,7 @@ CreateProgram(void) glUseProgram_func(program); - InitUniforms(program, Uniforms); + SetUniformValues(program, Uniforms); return program; } diff --git a/progs/tests/getprocaddress.c b/progs/tests/getprocaddress.c index ca66025d2d..a09ea58e1d 100644 --- a/progs/tests/getprocaddress.c +++ b/progs/tests/getprocaddress.c @@ -39,13 +39,2600 @@ typedef void (*generic_func)(); #define EQUAL(X, Y) (fabs((X) - (Y)) < 0.001) -/** +/* This macro simplifies the task of querying an extension function + * pointer and checking to see whether it resolved. + */ +#define DECLARE_GLFUNC_PTR(name,type) \ + type name = (type) glXGetProcAddressARB((const GLubyte *) "gl" #name) + +/******************************************************************** + * Generic helper functions used by the test functions. + */ + +static void CheckGLError(int line, const char *file, const char *function) +{ + int errorCode; + glFinish(); + errorCode = glGetError(); + if (errorCode == GL_NO_ERROR) return; + while (errorCode != GL_NO_ERROR) { + fprintf(stderr, "OpenGL error 0x%x (%s) at line %d of file %s in function %s()\n", + errorCode, + errorCode == GL_INVALID_VALUE? "GL_INVALID_VALUE": + errorCode == GL_INVALID_ENUM? "GL_INVALID_ENUM": + errorCode == GL_INVALID_OPERATION? "GL_INVALID_OPERATION": + errorCode == GL_STACK_OVERFLOW? "GL_STACK_OVERFLOW": + errorCode == GL_STACK_UNDERFLOW? "GL_STACK_UNDERFLOW": + errorCode == GL_OUT_OF_MEMORY? "GL_OUT_OF_MEMORY": + "unknown", + line, file, function); + errorCode = glGetError(); + } + fflush(stderr); +} + +static GLboolean +compare_bytes(const char *errorLabel, GLuint expectedSize, + const GLubyte *expectedData, GLuint actualSize, const GLubyte *actualData) +{ + int i; + + if (expectedSize == actualSize && + memcmp(expectedData, actualData, actualSize) == 0) { + /* All is well */ + return GL_TRUE; + } + + /* Trouble; we don't match. Print out why. */ + fprintf(stderr, "%s: actual data is not as expected\n", errorLabel); + for (i = 0; i <= 1; i++) { + const GLubyte *ptr; + int size; + char *label; + int j; + + switch(i) { + case 0: + label = "expected"; + size = expectedSize; + ptr = expectedData; + break; + case 1: + label = " actual"; + size = actualSize; + ptr = actualData; + break; + } + + fprintf(stderr, " %s: size %d: {", label, size); + for (j = 0; j < size; j++) { + fprintf(stderr, "%s0x%02x", j > 0 ? ", " : "", ptr[j]); + } + fprintf(stderr, "}\n"); + } + + /* We fail if the data is unexpected. */ + return GL_FALSE; +} + + +static GLboolean +compare_ints(const char *errorLabel, GLuint expectedSize, + const GLint *expectedData, GLuint actualSize, const GLint *actualData) +{ + int i; + + if (expectedSize == actualSize && + memcmp(expectedData, actualData, actualSize*sizeof(*expectedData)) == 0) { + /* All is well */ + return GL_TRUE; + } + + /* Trouble; we don't match. Print out why. */ + fprintf(stderr, "%s: actual data is not as expected\n", errorLabel); + for (i = 0; i <= 1; i++) { + const GLint *ptr; + int size; + char *label; + int j; + + switch(i) { + case 0: + label = "expected"; + size = expectedSize; + ptr = expectedData; + break; + case 1: + label = " actual"; + size = actualSize; + ptr = actualData; + break; + } + + fprintf(stderr, " %s: size %d: {", label, size); + for (j = 0; j < size; j++) { + fprintf(stderr, "%s%d", j > 0 ? ", " : "", ptr[j]); + } + fprintf(stderr, "}\n"); + } + + /* We fail if the data is unexpected. */ + return GL_FALSE; +} + +#define MAX_CONVERTED_VALUES 4 +static GLboolean +compare_shorts_to_ints(const char *errorLabel, GLuint expectedSize, + const GLshort *expectedData, GLuint actualSize, const GLint *actualData) +{ + int i; + GLint convertedValues[MAX_CONVERTED_VALUES]; + + if (expectedSize > MAX_CONVERTED_VALUES) { + fprintf(stderr, "%s: too much data [need %d values, have %d values]\n", + errorLabel, expectedSize, MAX_CONVERTED_VALUES); + return GL_FALSE; + } + + for (i = 0; i < expectedSize; i++) { + convertedValues[i] = (GLint) expectedData[i]; + } + + return compare_ints(errorLabel, expectedSize, convertedValues, + actualSize, actualData); +} + +static GLboolean +compare_floats(const char *errorLabel, GLuint expectedSize, + const GLfloat *expectedData, GLuint actualSize, const GLfloat *actualData) +{ + int i; + + if (expectedSize == actualSize && + memcmp(expectedData, actualData, actualSize*sizeof(*expectedData)) == 0) { + /* All is well */ + return GL_TRUE; + } + + /* Trouble; we don't match. Print out why. */ + fprintf(stderr, "%s: actual data is not as expected\n", errorLabel); + for (i = 0; i <= 1; i++) { + const GLfloat *ptr; + int size; + char *label; + int j; + + switch(i) { + case 0: + label = "expected"; + size = expectedSize; + ptr = expectedData; + break; + case 1: + label = " actual"; + size = actualSize; + ptr = actualData; + break; + } + + fprintf(stderr, " %s: size %d: {", label, size); + for (j = 0; j < size; j++) { + fprintf(stderr, "%s%f", j > 0 ? ", " : "", ptr[j]); + } + fprintf(stderr, "}\n"); + } + + /* We fail if the data is unexpected. */ + return GL_FALSE; +} + +static GLboolean +compare_doubles(const char *errorLabel, GLuint expectedSize, + const GLdouble *expectedData, GLuint actualSize, const GLdouble *actualData) +{ + int i; + + if (expectedSize == actualSize || + memcmp(expectedData, actualData, actualSize*sizeof(*expectedData)) == 0) { + /* All is well */ + return GL_TRUE; + } + + /* Trouble; we don't match. Print out why. */ + fprintf(stderr, "%s: actual data is not as expected\n", errorLabel); + for (i = 0; i <= 1; i++) { + const GLdouble *ptr; + int size; + char *label; + int j; + + switch(i) { + case 0: + label = "expected"; + size = expectedSize; + ptr = expectedData; + break; + case 1: + label = " actual"; + size = actualSize; + ptr = actualData; + break; + } + + fprintf(stderr, " %s: size %d: {", label, size); + for (j = 0; j < size; j++) { + fprintf(stderr, "%s%f", j > 0 ? ", " : "", ptr[j]); + } + fprintf(stderr, "}\n"); + } + + /* We fail if the data is unexpected. */ + return GL_FALSE; +} + +/******************************************************************** + * Functions to assist with GL_ARB_texture_compressiong testing + */ + +static GLboolean +check_texture_format_supported(GLenum format) +{ + GLint numFormats; + GLint *formats; + register int i; + + glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB, &numFormats); + formats = malloc(numFormats * sizeof(GLint)); + if (formats == NULL) { + fprintf(stderr, "check_texture_format_supported: could not allocate memory for %d GLints\n", + numFormats); + return GL_FALSE; + } + + memset(formats, 0, numFormats * sizeof(GLint)); + glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS_ARB, formats); + + for (i = 0; i < numFormats; i++) { + if (formats[i] == format) { + free(formats); + return GL_TRUE; + } + } + + /* We didn't find the format we were looking for. Give an error. */ +#define FORMAT_NAME(x) (\ + x == GL_COMPRESSED_RGB_FXT1_3DFX ? "GL_COMPRESSED_RGB_FXT1_3DFX" : \ + x == GL_COMPRESSED_RGBA_FXT1_3DFX ? "GL_COMPRESSED_RGBA_FXT1_3DFX" : \ + x == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ? "GL_COMPRESSED_RGB_S3TC_DXT1_EXT" : \ + x == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ? "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT" : \ + x == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT ? "GL_COMPRESSED_RGBA_S3TC_DXT3_EXT" : \ + x == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT ? "GL_COMPRESSED_RGBA_S3TC_DXT5_EXT" : \ + x == GL_RGB_S3TC ? "GL_RGB_S3TC" : \ + x == GL_RGB4_S3TC ? "GL_RGB4_S3TC" : \ + x == GL_RGBA_S3TC ? "GL_RGBA_S3TC" : \ + x == GL_RGBA4_S3TC ? "GL_RGBA4_S3TC" : \ + "unknown") + fprintf(stderr, "check_texture_format_supported: unsupported format 0x%04x [%s]\n", + format, FORMAT_NAME(format)); + fprintf(stderr, "supported formats:"); + for (i = 0; i < numFormats; i++) { + fprintf(stderr, " 0x%04x [%s]", formats[i], FORMAT_NAME(formats[i])); + } + fprintf(stderr, "\n"); + return GL_FALSE; +} + +/* This helper function compresses an RGBA texture and compares it + * against the expected compressed data. It returns GL_TRUE if all + * went as expected, or GL_FALSE in the case of error. + */ +static GLboolean +check_texture_compression(const char *message, GLenum dimension, + GLint width, GLint height, GLint depth, const GLubyte *texture, + int expectedCompressedSize, const GLubyte *expectedCompressedData) +{ + /* These are the data we query about the texture. */ + GLint isCompressed; + GLenum compressedFormat; + GLint compressedSize; + GLubyte *compressedData; + + /* We need this function pointer to operate. */ + DECLARE_GLFUNC_PTR(GetCompressedTexImageARB, PFNGLGETCOMPRESSEDTEXIMAGEARBPROC); + if (GetCompressedTexImageARB == NULL) { + fprintf(stderr, + "%s: could not query GetCompressedTexImageARB function pointer\n", + message); + return GL_FALSE; + } + + /* Verify that we actually have the GL_COMPRESSED_RGBA_S3TC_DXT3_EXT format available. */ + if (!check_texture_format_supported(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT)) { + return GL_FALSE; + } + + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + /* Set up the base image, requesting that the GL library compress it. */ + switch(dimension) { + case GL_TEXTURE_1D: + glTexImage1D(GL_TEXTURE_1D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, + width, 0, + GL_RGBA, GL_UNSIGNED_BYTE, texture); + break; + case GL_TEXTURE_2D: + glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, + width, height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, texture); + break; + case GL_TEXTURE_3D: + glTexImage3D(GL_TEXTURE_3D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, + width, height, depth, 0, + GL_RGBA, GL_UNSIGNED_BYTE, texture); + break; + default: + fprintf(stderr, "%s: unknown dimension 0x%04x.\n", message, dimension); + return GL_FALSE; + } + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Make sure the texture is compressed, and pull it out if it is. */ + glGetTexLevelParameteriv(dimension, 0, GL_TEXTURE_COMPRESSED_ARB, + &isCompressed); + if (!isCompressed) { + fprintf(stderr, "%s: could not compress GL_COMPRESSED_RGBA_S3TC_DXT3_EXT texture\n", + message); + return GL_FALSE; + } + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + glGetTexLevelParameteriv(dimension, 0, GL_TEXTURE_INTERNAL_FORMAT, + (GLint *)&compressedFormat); + if (compressedFormat != GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) { + fprintf(stderr, "%s: got internal format 0x%04x, expected GL_COMPRESSED_RGBA_S3TC_DXT3_EXT [0x%04x]\n", + __FUNCTION__, compressedFormat, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT); + return GL_FALSE; + } + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + glGetTexLevelParameteriv(dimension, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB, &compressedSize); + compressedData = malloc(compressedSize); + if (compressedData == NULL) { + fprintf(stderr, "%s: could not malloc %d bytes for compressed texture\n", + message, compressedSize); + return GL_FALSE; + } + memset(compressedData, 0, compressedSize); + (*GetCompressedTexImageARB)(dimension, 0, compressedData); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Compare it to the expected compressed data. The compare_bytes() + * call will print out diagnostics in the case of failure. + */ + if (!compare_bytes(message, + expectedCompressedSize, expectedCompressedData, + compressedSize, compressedData)) { + + free(compressedData); + return GL_FALSE; + } + + /* All done. Free our allocated data and return success. */ + free(compressedData); + return GL_TRUE; +} + +/* We'll use one function to exercise 1D, 2D, and 3D textures. */ + +/* The test function for compressed 3D texture images requires several + * different function pointers that have to be queried. This function + * gets all the function pointers it needs itself, and so is suitable for + * use to test any and all of the incorporated functions. + */ + +static GLboolean +exercise_CompressedTextures(GLenum dimension) +{ + /* Set up a basic (uncompressed) texture. We're doing a blue/yellow + * checkerboard. The 8x4/32-pixel board is well-suited to S3TC + * compression, which works on 4x4 blocks of pixels. + */ +#define B 0,0,255,255 +#define Y 255,255,0,255 +#define TEXTURE_WIDTH 16 +#define TEXTURE_HEIGHT 4 +#define TEXTURE_DEPTH 1 + static GLubyte texture[TEXTURE_WIDTH*TEXTURE_HEIGHT*TEXTURE_DEPTH*4] = { + B, B, Y, Y, B, B, Y, Y, B, B, Y, Y, B, B, Y, Y, + B, B, Y, Y, B, B, Y, Y, B, B, Y, Y, B, B, Y, Y, + Y, Y, B, B, Y, Y, B, B, Y, Y, B, B, Y, Y, B, B, + Y, Y, B, B, Y, Y, B, B, Y, Y, B, B, Y, Y, B, B, + }; +#undef B +#undef Y + GLubyte uncompressedTexture[TEXTURE_WIDTH*TEXTURE_HEIGHT*TEXTURE_DEPTH*4]; + + /* We'll use this as a texture subimage. */ +#define R 255,0,0,255 +#define G 0,255,0,255 +#define SUBTEXTURE_WIDTH 4 +#define SUBTEXTURE_HEIGHT 4 +#define SUBTEXTURE_DEPTH 1 + static GLubyte subtexture[SUBTEXTURE_WIDTH*SUBTEXTURE_HEIGHT*SUBTEXTURE_DEPTH*4] = { + G, G, R, R, + G, G, R, R, + R, R, G, G, + R, R, G, G, + }; +#undef R +#undef G + + /* These are the expected compressed textures. (In the case of + * a failed comparison, the test program will print out the + * actual compressed data in a format that can be directly used + * here, if desired.) The brave of heart can calculate the compression + * themselves based on the formulae described at: + * http://en.wikipedia.org/wiki/S3_Texture_Compression + * In a nutshell, each group of 16 bytes encodes a 4x4 texture block. + * The first eight bytes of each group are 4-bit alpha values + * for each of the 16 pixels in the texture block. + * The next four bytes in each group are LSB-first RGB565 colors; the + * first two bytes are identified as the color C0, and the next two + * are the color C1. (Two more colors C2 and C3 will be calculated + * from these, but do not appear in the compression data.) The + * last 4 bytes of the group are sixteen 2-bit indices that, for + * each of the 16 pixels in the texture block, select one of the + * colors C0, C1, C2, or C3. + * + * For example, our blue/yellow checkerboard is made up of + * four identical 4x4 blocks. Each of those blocks will + * be encoded as: eight bytes of 0xff (16 alpha values, each 0xf), + * C0 as the RGB565 color yellow (0xffe0), encoded LSB-first; + * C1 as the RGB565 color blue (0x001f), encoded LSB-first; + * and 4 bytes of 16 2-bit color indices reflecting the + * choice of color for each of the 16 pixels: + * 00, 00, 01, 01, = 0x05 + * 00, 00, 01, 01, = 0x05 + * 01, 01, 00, 00, = 0x50 + * 01, 01, 00, 00, = 0x50 + */ + static GLubyte compressedTexture[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xe0, 0xff, 0x1f, 0x00, 0x05, 0x05, 0x50, 0x50, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xe0, 0xff, 0x1f, 0x00, 0x05, 0x05, 0x50, 0x50, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xe0, 0xff, 0x1f, 0x00, 0x05, 0x05, 0x50, 0x50, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xe0, 0xff, 0x1f, 0x00, 0x05, 0x05, 0x50, 0x50 + }; + + /* The similar calculations for the 4x4 subtexture are left + * as an exercise for the reader. + */ + static GLubyte compressedSubTexture[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0xf8, 0xe0, 0x07, 0x05, 0x05, 0x50, 0x50, + }; + + /* The combined texture replaces the initial blue/yellow + * block with the green/red block. (I'd wanted to do + * the more interesting exercise of putting the + * green/red block in the middle of the blue/yellow + * texture, which is a non-trivial replacement, but + * the attempt produces GL_INVALID_OPERATION, showing + * that you can only replace whole blocks of + * subimages with S3TC.) The combined texture looks + * like: + * G G R R B B Y Y B B Y Y B B Y Y + * G G R R B B Y Y B B Y Y B B Y Y + * R R G G Y Y B B Y Y B B Y Y B B + * R R G G Y Y B B Y Y B B Y Y B B + * which encodes just like the green/red block followed + * by 3 copies of the yellow/blue block. + */ + static GLubyte compressedCombinedTexture[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0xf8, 0xe0, 0x07, 0x05, 0x05, 0x50, 0x50, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xe0, 0xff, 0x1f, 0x00, 0x05, 0x05, 0x50, 0x50, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xe0, 0xff, 0x1f, 0x00, 0x05, 0x05, 0x50, 0x50, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xe0, 0xff, 0x1f, 0x00, 0x05, 0x05, 0x50, 0x50 + }; + + /* These are the data we query about the texture. */ + GLint queryIsCompressed; + GLenum queryCompressedFormat; + GLint queryCompressedSize; + GLubyte queryCompressedData[sizeof(compressedTexture)]; + + /* Query the function pointers we need. We actually won't need most + * of these (the "dimension" parameter dictates whether we're testing + * 1D, 2D, or 3D textures), but we'll have them all ready just in case. + */ + DECLARE_GLFUNC_PTR(GetCompressedTexImageARB, PFNGLGETCOMPRESSEDTEXIMAGEARBPROC); + DECLARE_GLFUNC_PTR(CompressedTexImage3DARB, PFNGLCOMPRESSEDTEXIMAGE3DARBPROC); + DECLARE_GLFUNC_PTR(CompressedTexSubImage3DARB, PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC); + DECLARE_GLFUNC_PTR(CompressedTexImage2DARB, PFNGLCOMPRESSEDTEXIMAGE2DARBPROC); + DECLARE_GLFUNC_PTR(CompressedTexSubImage2DARB, PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC); + DECLARE_GLFUNC_PTR(CompressedTexImage1DARB, PFNGLCOMPRESSEDTEXIMAGE1DARBPROC); + DECLARE_GLFUNC_PTR(CompressedTexSubImage1DARB, PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC); + + /* If the necessary functions are missing, we can't continue */ + if (GetCompressedTexImageARB == NULL) { + fprintf(stderr, "%s: GetCompressedTexImageARB function is missing\n", + __FUNCTION__); + return GL_FALSE; + } + switch (dimension) { + case GL_TEXTURE_1D: + if (CompressedTexImage1DARB == NULL || CompressedTexSubImage1DARB == NULL) { + fprintf(stderr, "%s: 1D compressed texture functions are missing\n", + __FUNCTION__); + return GL_FALSE; + }; + break; + case GL_TEXTURE_2D: + if (CompressedTexImage2DARB == NULL || CompressedTexSubImage2DARB == NULL) { + fprintf(stderr, "%s: 2D compressed texture functions are missing\n", + __FUNCTION__); + return GL_FALSE; + }; + break; + case GL_TEXTURE_3D: + if (CompressedTexImage3DARB == NULL || CompressedTexSubImage3DARB == NULL) { + fprintf(stderr, "%s: 3D compressed texture functions are missing\n", + __FUNCTION__); + return GL_FALSE; + }; + break; + default: + fprintf(stderr, "%s: unknown texture dimension 0x%04x passed.\n", + __FUNCTION__, dimension); + return GL_FALSE; + } + + /* Check the compression of our base texture image. */ + if (!check_texture_compression("texture compression", dimension, + TEXTURE_WIDTH, TEXTURE_HEIGHT, TEXTURE_DEPTH, texture, + sizeof(compressedTexture), compressedTexture)) { + + /* Something's wrong with texture compression. The function + * above will have printed an appropriate error. + */ + return GL_FALSE; + } + + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Do the same for our texture subimage */ + if (!check_texture_compression("subtexture compression", dimension, + SUBTEXTURE_WIDTH, SUBTEXTURE_HEIGHT, SUBTEXTURE_DEPTH, subtexture, + sizeof(compressedSubTexture), compressedSubTexture)) { + + /* Something's wrong with texture compression. The function + * above will have printed an appropriate error. + */ + return GL_FALSE; + } + + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Send the base compressed texture down to the hardware. */ + switch(dimension) { + case GL_TEXTURE_3D: + (*CompressedTexImage3DARB)(GL_TEXTURE_3D, 0, + GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, + TEXTURE_WIDTH, TEXTURE_HEIGHT, TEXTURE_DEPTH, 0, + sizeof(compressedTexture), compressedTexture); + break; + + case GL_TEXTURE_2D: + (*CompressedTexImage2DARB)(GL_TEXTURE_2D, 0, + GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, + TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, + sizeof(compressedTexture), compressedTexture); + break; + + case GL_TEXTURE_1D: + (*CompressedTexImage1DARB)(GL_TEXTURE_1D, 0, + GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, + TEXTURE_WIDTH, 0, + sizeof(compressedTexture), compressedTexture); + break; + } + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* For grins, query it to make sure it is as expected. */ + glGetTexLevelParameteriv(dimension, 0, GL_TEXTURE_COMPRESSED_ARB, + &queryIsCompressed); + if (!queryIsCompressed) { + fprintf(stderr, "%s: compressed texture did not come back as compressed\n", + __FUNCTION__); + return GL_FALSE; + } + glGetTexLevelParameteriv(dimension, 0, GL_TEXTURE_INTERNAL_FORMAT, + (GLint *)&queryCompressedFormat); + if (queryCompressedFormat != GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) { + fprintf(stderr, "%s: got internal format 0x%04x, expected GL_COMPRESSED_RGBA_S3TC_DXT3_EXT [0x%04x]\n", + __FUNCTION__, queryCompressedFormat, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT); + return GL_FALSE; + } + glGetTexLevelParameteriv(dimension, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB, + &queryCompressedSize); + if (queryCompressedSize != sizeof(compressedTexture)) { + fprintf(stderr, "%s: compressed 3D texture changed size: expected %d, actual %d\n", + __FUNCTION__, sizeof(compressedTexture), queryCompressedSize); + return GL_FALSE; + } + (*GetCompressedTexImageARB)(dimension, 0, queryCompressedData); + if (!compare_bytes( + "exercise_CompressedTextures:doublechecking compressed texture", + sizeof(compressedTexture), compressedTexture, + queryCompressedSize, queryCompressedData)) { + return GL_FALSE; + } + + /* Now apply the texture subimage. The current implementation of + * S3TC requires that subimages be only applied to whole blocks. + */ + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + switch(dimension) { + case GL_TEXTURE_3D: + (*CompressedTexSubImage3DARB)(GL_TEXTURE_3D, 0, + 0, 0, 0, /* offsets */ + SUBTEXTURE_WIDTH, SUBTEXTURE_HEIGHT, SUBTEXTURE_DEPTH, + GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, + sizeof(compressedSubTexture), compressedSubTexture); + break; + case GL_TEXTURE_2D: + (*CompressedTexSubImage2DARB)(GL_TEXTURE_2D, 0, + 0, 0, /* offsets */ + SUBTEXTURE_WIDTH, SUBTEXTURE_HEIGHT, + GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, + sizeof(compressedSubTexture), compressedSubTexture); + break; + case GL_TEXTURE_1D: + (*CompressedTexSubImage2DARB)(GL_TEXTURE_2D, 0, + 0, 0, /* offsets */ + SUBTEXTURE_WIDTH, SUBTEXTURE_HEIGHT, + GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, + sizeof(compressedSubTexture), compressedSubTexture); + break; + } + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Query the compressed texture back now, and see that it + * is as expected. + */ + (*GetCompressedTexImageARB)(dimension, 0, queryCompressedData); + if (!compare_bytes("exercise_CompressedTextures:combined texture", + sizeof(compressedCombinedTexture), compressedCombinedTexture, + queryCompressedSize, queryCompressedData)) { + return GL_FALSE; + } + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Just for the exercise, uncompress the texture and pull it out. + * We don't check it because the compression is lossy, so it won't + * compare exactly to the source texture; we just + * want to exercise the code paths that convert it. + */ + glGetTexImage(dimension, 0, GL_RGBA, GL_UNSIGNED_BYTE, uncompressedTexture); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* If we survived this far, we pass. */ + return GL_TRUE; +} + +/************************************************************************** + * Functions to assist with GL_EXT_framebuffer_object and + * GL_EXT_framebuffer_blit testing. + */ + +#define FB_STATUS_NAME(x) (\ + x == GL_FRAMEBUFFER_COMPLETE_EXT ? "GL_FRAMEBUFFER_COMPLETE_EXT" : \ + x == GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT ? "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT" : \ + x == GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT ? "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT" : \ + x == GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT ? "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT" : \ + x == GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT ? "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT" : \ + x == GL_FRAMEBUFFER_UNSUPPORTED_EXT ? "GL_FRAMEBUFFER_UNSUPPORTED_EXT" : \ + x == GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT ? "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT" : \ + x == GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT ? "GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT" : \ + x == GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT ? "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT" : \ + "unknown") + +static GLboolean +exercise_framebuffer(void) +{ + GLuint framebufferID = 0; + GLuint renderbufferID = 0; + + /* Dimensions of the framebuffer and renderbuffers are arbitrary. + * Since they won't be shown on-screen, we can use whatever we want. + */ + const GLint Width = 100; + const GLint Height = 100; + + /* Every function we use will be referenced through function pointers. + * This will allow this test program to run on OpenGL implementations + * that *don't* implement these extensions (though the implementation + * used to compile them must have up-to-date header files). + */ + DECLARE_GLFUNC_PTR(GenFramebuffersEXT, PFNGLGENFRAMEBUFFERSEXTPROC); + DECLARE_GLFUNC_PTR(IsFramebufferEXT, PFNGLISFRAMEBUFFEREXTPROC); + DECLARE_GLFUNC_PTR(DeleteFramebuffersEXT, PFNGLDELETEFRAMEBUFFERSEXTPROC); + DECLARE_GLFUNC_PTR(BindFramebufferEXT, PFNGLBINDFRAMEBUFFEREXTPROC); + DECLARE_GLFUNC_PTR(GenRenderbuffersEXT, PFNGLGENRENDERBUFFERSEXTPROC); + DECLARE_GLFUNC_PTR(IsRenderbufferEXT, PFNGLISRENDERBUFFEREXTPROC); + DECLARE_GLFUNC_PTR(DeleteRenderbuffersEXT, PFNGLDELETERENDERBUFFERSEXTPROC); + DECLARE_GLFUNC_PTR(BindRenderbufferEXT, PFNGLBINDRENDERBUFFEREXTPROC); + DECLARE_GLFUNC_PTR(FramebufferRenderbufferEXT, PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC); + DECLARE_GLFUNC_PTR(RenderbufferStorageEXT, PFNGLRENDERBUFFERSTORAGEEXTPROC); + DECLARE_GLFUNC_PTR(CheckFramebufferStatusEXT, PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC); + + /* The BlitFramebuffer function comes from a different extension. + * It's possible for an implementation to implement all the above, + * but not BlitFramebuffer; so it's okay if this one comes back + * NULL, as we can still test the rest. + */ + DECLARE_GLFUNC_PTR(BlitFramebufferEXT, PFNGLBLITFRAMEBUFFEREXTPROC); + + /* We cannot test unless we have all the function pointers. */ + if ( + GenFramebuffersEXT == NULL || + IsFramebufferEXT == NULL || + DeleteFramebuffersEXT == NULL || + BindFramebufferEXT == NULL || + GenRenderbuffersEXT == NULL || + IsRenderbufferEXT == NULL || + DeleteRenderbuffersEXT == NULL || + BindRenderbufferEXT == NULL || + FramebufferRenderbufferEXT == NULL || + RenderbufferStorageEXT == NULL || + CheckFramebufferStatusEXT == NULL + ) { + fprintf(stderr, "%s: could not locate all framebuffer functions\n", + __FUNCTION__); + return GL_FALSE; + } + + /* Generate a framebuffer for us to play with. */ + (*GenFramebuffersEXT)(1, &framebufferID); + if (framebufferID == 0) { + fprintf(stderr, "%s: failed to generate a frame buffer ID.\n", + __FUNCTION__); + return GL_FALSE; + } + /* The generated name is not a framebuffer object until bound. */ + (*BindFramebufferEXT)(GL_FRAMEBUFFER_EXT, framebufferID); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + if (!(*IsFramebufferEXT)(framebufferID)) { + fprintf(stderr, "%s: generated a frame buffer ID 0x%x that wasn't a framebuffer\n", + __FUNCTION__, framebufferID); + (*BindFramebufferEXT)(GL_FRAMEBUFFER_EXT, 0); + (*DeleteFramebuffersEXT)(1, &framebufferID); + return GL_FALSE; + } + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + { + GLint queriedFramebufferID; + glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &queriedFramebufferID); + if (queriedFramebufferID != framebufferID) { + fprintf(stderr, "%s: bound frame buffer 0x%x, but queried 0x%x\n", + __FUNCTION__, framebufferID, queriedFramebufferID); + (*BindFramebufferEXT)(GL_FRAMEBUFFER_EXT, 0); + (*DeleteFramebuffersEXT)(1, &framebufferID); + return GL_FALSE; + } + } + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Create a color buffer to attach to the frame buffer object, so + * we can actually operate on it. We go through the same basic checks + * with the renderbuffer that we do with the framebuffer. + */ + (*GenRenderbuffersEXT)(1, &renderbufferID); + if (renderbufferID == 0) { + fprintf(stderr, "%s: could not generate a renderbuffer ID\n", + __FUNCTION__); + (*BindFramebufferEXT)(GL_FRAMEBUFFER_EXT, 0); + (*DeleteFramebuffersEXT)(1, &framebufferID); + return GL_FALSE; + } + (*BindRenderbufferEXT)(GL_RENDERBUFFER_EXT, renderbufferID); + if (!(*IsRenderbufferEXT)(renderbufferID)) { + fprintf(stderr, "%s: generated renderbuffer 0x%x is not a renderbuffer\n", + __FUNCTION__, renderbufferID); + (*BindRenderbufferEXT)(GL_RENDERBUFFER_EXT, 0); + (*DeleteRenderbuffersEXT)(1, &renderbufferID); + (*BindFramebufferEXT)(GL_FRAMEBUFFER_EXT, 0); + (*DeleteFramebuffersEXT)(1, &framebufferID); + return GL_FALSE; + } + { + GLint queriedRenderbufferID = 0; + glGetIntegerv(GL_RENDERBUFFER_BINDING_EXT, &queriedRenderbufferID); + if (renderbufferID != queriedRenderbufferID) { + fprintf(stderr, "%s: bound renderbuffer 0x%x, but got 0x%x\n", + __FUNCTION__, renderbufferID, queriedRenderbufferID); + (*BindRenderbufferEXT)(GL_RENDERBUFFER_EXT, 0); + (*DeleteRenderbuffersEXT)(1, &renderbufferID); + (*BindFramebufferEXT)(GL_FRAMEBUFFER_EXT, 0); + (*DeleteFramebuffersEXT)(1, &framebufferID); + return GL_FALSE; + } + } + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Add the renderbuffer as a color attachment to the current + * framebuffer (which is our generated framebuffer). + */ + (*FramebufferRenderbufferEXT)(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, + GL_RENDERBUFFER_EXT, renderbufferID); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* The renderbuffer will need some dimensions and storage space. */ + (*RenderbufferStorageEXT)(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* That should be everything we need. If we set up to draw and to + * read from our color attachment, we should be "framebuffer complete", + * meaning the framebuffer is ready to go. + */ + glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); + glReadBuffer(GL_COLOR_ATTACHMENT1_EXT); + { + GLenum status = (*CheckFramebufferStatusEXT)(GL_FRAMEBUFFER_EXT); + if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { + fprintf(stderr, "%s: framebuffer not complete; status = %s [0x%x]\n", + __FUNCTION__, FB_STATUS_NAME(status), status); + glReadBuffer(0); + glDrawBuffer(0); + (*BindRenderbufferEXT)(GL_RENDERBUFFER_EXT, 0); + (*DeleteRenderbuffersEXT)(1, &renderbufferID); + (*BindFramebufferEXT)(GL_FRAMEBUFFER_EXT, 0); + (*DeleteFramebuffersEXT)(1, &framebufferID); + return GL_FALSE; + } + } + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Define the contents of the frame buffer */ + glClearColor(0.5, 0.5, 0.5, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + + /* If the GL_EXT_framebuffer_blit is supported, attempt a framebuffer + * blit from (5,5)-(10,10) to (90,90)-(95,95). This is *not* an + * error if framebuffer_blit is *not* supported (as we can still + * effectively test the other functions). + */ + if (BlitFramebufferEXT != NULL) { + (*BlitFramebufferEXT)(5, 5, 10, 10, 90, 90, 95, 95, + GL_COLOR_BUFFER_BIT, GL_NEAREST); + } + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* We could now test to see whether the framebuffer had the desired + * contents. As this is just a touch test, we'll leave that for now. + * Clean up and go home. + */ + glReadBuffer(0); + glDrawBuffer(0); + (*BindRenderbufferEXT)(GL_RENDERBUFFER_EXT, 0); + (*DeleteRenderbuffersEXT)(1, &renderbufferID); + (*BindFramebufferEXT)(GL_FRAMEBUFFER_EXT, 0); + (*DeleteFramebuffersEXT)(1, &framebufferID); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + return GL_TRUE; +} + +/************************************************************************** + * Functions to assist with GL_ARB_shader_objects testing. + */ + +static void +print_info_log(const char *message, GLhandleARB object) +{ + DECLARE_GLFUNC_PTR(GetObjectParameterivARB, PFNGLGETOBJECTPARAMETERIVARBPROC); + DECLARE_GLFUNC_PTR(GetInfoLogARB, PFNGLGETINFOLOGARBPROC); + int logLength, queryLength; + char *log; + + if (GetObjectParameterivARB == NULL) { + fprintf(stderr, "%s: could not get GetObjectParameterivARB address\n", + message); + return; + } + if (GetInfoLogARB == NULL) { + fprintf(stderr, "%s: could not get GetInfoLogARB address\n", + message); + return; + } + + (*GetObjectParameterivARB)(object, GL_OBJECT_INFO_LOG_LENGTH_ARB, + &logLength); + if (logLength == 0) { + fprintf(stderr, "%s: info log length is 0\n", message); + return; + } + log = malloc(logLength); + if (log == NULL) { + fprintf(stderr, "%s: could not malloc %d bytes for info log\n", + message, logLength); + } + else { + (*GetInfoLogARB)(object, logLength, &queryLength, log); + fprintf(stderr, "%s: info log says '%s'\n", + message, log); + } + free(log); +} + +static GLboolean +exercise_uniform_start(const char *fragmentShaderText, const char *uniformName, + GLhandleARB *returnProgram, GLint *returnUniformLocation) +{ + DECLARE_GLFUNC_PTR(CreateShaderObjectARB, PFNGLCREATESHADEROBJECTARBPROC); + DECLARE_GLFUNC_PTR(ShaderSourceARB, PFNGLSHADERSOURCEARBPROC); + DECLARE_GLFUNC_PTR(CompileShaderARB, PFNGLCOMPILESHADERARBPROC); + DECLARE_GLFUNC_PTR(CreateProgramObjectARB, PFNGLCREATEPROGRAMOBJECTARBPROC); + DECLARE_GLFUNC_PTR(AttachObjectARB, PFNGLATTACHOBJECTARBPROC); + DECLARE_GLFUNC_PTR(LinkProgramARB, PFNGLLINKPROGRAMARBPROC); + DECLARE_GLFUNC_PTR(UseProgramObjectARB, PFNGLUSEPROGRAMOBJECTARBPROC); + DECLARE_GLFUNC_PTR(ValidateProgramARB, PFNGLVALIDATEPROGRAMARBPROC); + DECLARE_GLFUNC_PTR(GetUniformLocationARB, PFNGLGETUNIFORMLOCATIONARBPROC); + DECLARE_GLFUNC_PTR(DeleteObjectARB, PFNGLDELETEOBJECTARBPROC); + DECLARE_GLFUNC_PTR(GetObjectParameterivARB, PFNGLGETOBJECTPARAMETERIVARBPROC); + GLhandleARB fs, program; + GLint uniformLocation; + GLint shaderCompiled, programValidated; + + if (CreateShaderObjectARB == NULL || + ShaderSourceARB == NULL || + CompileShaderARB == NULL || + CreateProgramObjectARB == NULL || + AttachObjectARB == NULL || + LinkProgramARB == NULL || + UseProgramObjectARB == NULL || + ValidateProgramARB == NULL || + GetUniformLocationARB == NULL || + DeleteObjectARB == NULL || + GetObjectParameterivARB == NULL || + 0) { + return GL_FALSE; + } + + /* Create the trivial fragment shader and program. For safety + * we'll check to make sure they compile and link correctly. + */ + fs = (*CreateShaderObjectARB)(GL_FRAGMENT_SHADER_ARB); + (*ShaderSourceARB)(fs, 1, &fragmentShaderText, NULL); + (*CompileShaderARB)(fs); + (*GetObjectParameterivARB)(fs, GL_OBJECT_COMPILE_STATUS_ARB, + &shaderCompiled); + if (!shaderCompiled) { + print_info_log("shader did not compile", fs); + (*DeleteObjectARB)(fs); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + return GL_FALSE; + } + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + program = (*CreateProgramObjectARB)(); + (*AttachObjectARB)(program, fs); + (*LinkProgramARB)(program); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Make sure we're going to run successfully */ + (*ValidateProgramARB)(program); + (*GetObjectParameterivARB)(program, GL_OBJECT_VALIDATE_STATUS_ARB, + &programValidated); + if (!programValidated) {; + print_info_log("program did not validate", program); + (*DeleteObjectARB)(program); + (*DeleteObjectARB)(fs); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + return GL_FALSE; + } + + /* Put the program in place. We're not allowed to assign to uniform + * variables used by the program until the program is put into use. + */ + (*UseProgramObjectARB)(program); + + /* Once the shader is in place, we're free to delete it; this + * won't affect the copy that's part of the program. + */ + (*DeleteObjectARB)(fs); + + /* Find the location index of the uniform variable we declared; + * the caller will ned that to set the value. + */ + uniformLocation = (*GetUniformLocationARB)(program, uniformName); + if (uniformLocation == -1) { + fprintf(stderr, "%s: could not determine uniform location\n", + __FUNCTION__); + (*DeleteObjectARB)(program); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + return GL_FALSE; + } + + /* All done with what we're supposed to do - return the program + * handle and the uniform location to the caller. + */ + *returnProgram = program; + *returnUniformLocation = uniformLocation; + return GL_TRUE; +} + +static void +exercise_uniform_end(GLhandleARB program) +{ + DECLARE_GLFUNC_PTR(UseProgramObjectARB, PFNGLUSEPROGRAMOBJECTARBPROC); + DECLARE_GLFUNC_PTR(DeleteObjectARB, PFNGLDELETEOBJECTARBPROC); + if (UseProgramObjectARB == NULL || DeleteObjectARB == NULL) { + return; + } + + /* Turn off our program by setting the special value 0, and + * then delete the program object. + */ + (*UseProgramObjectARB)(0); + (*DeleteObjectARB)(program); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); +} + +/************************************************************************** + * Exercises for fences + */ +static GLboolean +exercise_fences(void) +{ + DECLARE_GLFUNC_PTR(DeleteFencesNV, PFNGLDELETEFENCESNVPROC); + DECLARE_GLFUNC_PTR(FinishFenceNV, PFNGLFINISHFENCENVPROC); + DECLARE_GLFUNC_PTR(GenFencesNV, PFNGLGENFENCESNVPROC); + DECLARE_GLFUNC_PTR(GetFenceivNV, PFNGLGETFENCEIVNVPROC); + DECLARE_GLFUNC_PTR(IsFenceNV, PFNGLISFENCENVPROC); + DECLARE_GLFUNC_PTR(SetFenceNV, PFNGLSETFENCENVPROC); + DECLARE_GLFUNC_PTR(TestFenceNV, PFNGLTESTFENCENVPROC); + GLuint fence; + GLint fenceStatus, fenceCondition; + int count; + + /* Make sure we have all the function pointers we need. */ + if (GenFencesNV == NULL || + SetFenceNV == NULL || + IsFenceNV == NULL || + GetFenceivNV == NULL || + TestFenceNV == NULL || + FinishFenceNV == NULL || + DeleteFencesNV == NULL) { + fprintf(stderr, "%s: don't have all the fence functions\n", + __FUNCTION__); + return GL_FALSE; + } + + /* Create and set a simple fence. */ + (*GenFencesNV)(1, &fence); + (*SetFenceNV)(fence, GL_ALL_COMPLETED_NV); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Make sure it reads as a fence. */ + if (!(*IsFenceNV)(fence)) { + fprintf(stderr, "%s: set fence is not a fence\n", __FUNCTION__); + (*DeleteFencesNV)(1, &fence); + return GL_FALSE; + } + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Try to read back its current status and condition. */ + (*GetFenceivNV)(fence, GL_FENCE_CONDITION_NV, &fenceCondition); + if (fenceCondition != GL_ALL_COMPLETED_NV) { + fprintf(stderr, "%s: expected fence condition 0x%x, got 0x%x\n", + __FUNCTION__, GL_ALL_COMPLETED_NV, fenceCondition); + (*DeleteFencesNV)(1, &fence); + return GL_FALSE; + } + (*GetFenceivNV)(fence, GL_FENCE_STATUS_NV, &fenceStatus); + if (fenceStatus != GL_TRUE && fenceStatus != GL_FALSE) { + fprintf(stderr,"%s: fence status should be GL_TRUE or GL_FALSE, got 0x%x\n", + __FUNCTION__, fenceStatus); + (*DeleteFencesNV)(1, &fence); + return GL_FALSE; + } + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Set the fence again, query its status, and wait for it to finish + * two different ways: once by looping on TestFence(), and a + * second time by a simple call to FinishFence(); + */ + (*SetFenceNV)(fence, GL_ALL_COMPLETED_NV); + glFlush(); + count = 1; + while (!(*TestFenceNV)(fence)) { + count++; + if (count == 0) { + break; + } + } + if (count == 0) { + fprintf(stderr, "%s: fence never returned true\n", __FUNCTION__); + (*DeleteFencesNV)(1, &fence); + return GL_FALSE; + } + (*SetFenceNV)(fence, GL_ALL_COMPLETED_NV); + (*FinishFenceNV)(fence); + if ((*TestFenceNV)(fence) != GL_TRUE) { + fprintf(stderr, "%s: finished fence does not have status GL_TRUE\n", + __FUNCTION__); + (*DeleteFencesNV)(1, &fence); + return GL_FALSE; + } + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* All done. Delete the fence and return. */ + (*DeleteFencesNV)(1, &fence); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + return GL_TRUE; +} + +/************************************************************************** + * Exercises for buffer objects + */ +enum Map_Buffer_Usage{ Use_Map_Buffer, Use_Map_Buffer_Range}; +static GLboolean +exercise_buffer_objects(enum Map_Buffer_Usage usage) +{ +#define BUFFER_DATA_SIZE 1024 + GLuint bufferID; + GLint bufferMapped; + static GLubyte data[BUFFER_DATA_SIZE] = {0}; + float *dataPtr; + + /* Get the function pointers we need. These are from + * GL_ARB_vertex_buffer_object and are required in all + * cases. + */ + DECLARE_GLFUNC_PTR(GenBuffersARB, PFNGLGENBUFFERSARBPROC); + DECLARE_GLFUNC_PTR(BindBufferARB, PFNGLBINDBUFFERARBPROC); + DECLARE_GLFUNC_PTR(BufferDataARB, PFNGLBUFFERDATAARBPROC); + DECLARE_GLFUNC_PTR(MapBufferARB, PFNGLMAPBUFFERARBPROC); + DECLARE_GLFUNC_PTR(UnmapBufferARB, PFNGLUNMAPBUFFERARBPROC); + DECLARE_GLFUNC_PTR(DeleteBuffersARB, PFNGLDELETEBUFFERSARBPROC); + DECLARE_GLFUNC_PTR(GetBufferParameterivARB, PFNGLGETBUFFERPARAMETERIVARBPROC); + + /* These are from GL_ARB_map_buffer_range, and are optional + * unless we're given Use_Map_Buffer_Range. Note that they do *not* + * have the standard "ARB" suffixes; this is because the extension + * was introduced *after* a superset was standardized in OpenGL 3.0. + * (The extension really only exists to allow the functionality on + * devices that cannot implement a full OpenGL 3.0 driver.) + */ + DECLARE_GLFUNC_PTR(FlushMappedBufferRange, PFNGLFLUSHMAPPEDBUFFERRANGEPROC); + DECLARE_GLFUNC_PTR(MapBufferRange, PFNGLMAPBUFFERRANGEPROC); + + /* This is from APPLE_flush_buffer_range, and is optional even if + * we're given Use_Map_Buffer_Range. Test it before using it. + */ + DECLARE_GLFUNC_PTR(BufferParameteriAPPLE, PFNGLBUFFERPARAMETERIAPPLEPROC); + + /* Make sure we have all the function pointers we need. */ + if (GenBuffersARB == NULL || + BindBufferARB == NULL || + BufferDataARB == NULL || + MapBufferARB == NULL || + UnmapBufferARB == NULL || + DeleteBuffersARB == NULL || + GetBufferParameterivARB == NULL) { + fprintf(stderr, "%s: missing basic MapBuffer functions\n", __FUNCTION__); + return GL_FALSE; + } + if (usage == Use_Map_Buffer_Range) { + if (FlushMappedBufferRange == NULL || MapBufferRange == NULL) { + fprintf(stderr, "%s: missing MapBufferRange functions\n", __FUNCTION__); + return GL_FALSE; + } + } + + /* Create and define a buffer */ + (*GenBuffersARB)(1, &bufferID); + (*BindBufferARB)(GL_ARRAY_BUFFER_ARB, bufferID); + (*BufferDataARB)(GL_ARRAY_BUFFER_ARB, BUFFER_DATA_SIZE, data, + GL_DYNAMIC_DRAW_ARB); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* If we're using MapBufferRange, and if the BufferParameteriAPPLE + * function is present, use it before mapping. This particular + * use is a no-op, intended just to exercise the entry point. + */ + if (usage == Use_Map_Buffer_Range && BufferParameteriAPPLE != NULL) { + (*BufferParameteriAPPLE)(GL_ARRAY_BUFFER_ARB, + GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_TRUE); + } + + /* Map it, and make sure it's mapped. */ + switch(usage) { + case Use_Map_Buffer: + dataPtr = (float *) (*MapBufferARB)( + GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); + break; + case Use_Map_Buffer_Range: + dataPtr = (float *)(*MapBufferRange)(GL_ARRAY_BUFFER_ARB, + 4, 16, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT); + break; + } + if (dataPtr == NULL) { + fprintf(stderr, "%s: %s returned NULL\n", __FUNCTION__, + usage == Use_Map_Buffer ? "MapBuffer" : "MapBufferRange"); + (*BindBufferARB)(GL_ARRAY_BUFFER_ARB, 0); + (*DeleteBuffersARB)(1, &bufferID); + return GL_FALSE; + } + (*GetBufferParameterivARB)(GL_ARRAY_BUFFER_ARB, GL_BUFFER_MAPPED_ARB, + &bufferMapped); + if (!bufferMapped) { + fprintf(stderr, "%s: buffer should be mapped but isn't\n", __FUNCTION__); + (*BindBufferARB)(GL_ARRAY_BUFFER_ARB, 0); + (*DeleteBuffersARB)(1, &bufferID); + return GL_FALSE; + } + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Write something to it, just to make sure we don't segfault. */ + *dataPtr = 1.5; + + /* Unmap to show we're finished with the buffer. Note that if we're + * using MapBufferRange, we first have to flush the range we modified. + */ + if (usage == Use_Map_Buffer_Range) { + (*FlushMappedBufferRange)(GL_ARRAY_BUFFER_ARB, 4, 16); + } + if (!(*UnmapBufferARB)(GL_ARRAY_BUFFER_ARB)) { + fprintf(stderr, "%s: UnmapBuffer failed\n", __FUNCTION__); + (*BindBufferARB)(GL_ARRAY_BUFFER_ARB, 0); + (*DeleteBuffersARB)(1, &bufferID); + return GL_FALSE; + } + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* All done. */ + (*BindBufferARB)(GL_ARRAY_BUFFER_ARB, 0); + (*DeleteBuffersARB)(1, &bufferID); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + return GL_TRUE; + +#undef BUFFER_DATA_SIZE +} + +/************************************************************************** + * Exercises for occlusion query + */ +static GLboolean +exercise_occlusion_query(void) +{ + GLuint queryObject; + GLint queryReady; + GLuint querySampleCount; + GLint queryCurrent; + GLint queryCounterBits; + + /* Get the function pointers we need. These are from + * GL_ARB_vertex_buffer_object and are required in all + * cases. + */ + DECLARE_GLFUNC_PTR(GenQueriesARB, PFNGLGENQUERIESARBPROC); + DECLARE_GLFUNC_PTR(BeginQueryARB, PFNGLBEGINQUERYARBPROC); + DECLARE_GLFUNC_PTR(GetQueryivARB, PFNGLGETQUERYIVARBPROC); + DECLARE_GLFUNC_PTR(EndQueryARB, PFNGLENDQUERYARBPROC); + DECLARE_GLFUNC_PTR(IsQueryARB, PFNGLISQUERYARBPROC); + DECLARE_GLFUNC_PTR(GetQueryObjectivARB, PFNGLGETQUERYOBJECTIVARBPROC); + DECLARE_GLFUNC_PTR(GetQueryObjectuivARB, PFNGLGETQUERYOBJECTUIVARBPROC); + DECLARE_GLFUNC_PTR(DeleteQueriesARB, PFNGLDELETEQUERIESARBPROC); + + /* Make sure we have all the function pointers we need. */ + if (GenQueriesARB == NULL || + BeginQueryARB == NULL || + GetQueryivARB == NULL || + EndQueryARB == NULL || + IsQueryARB == NULL || + GetQueryObjectivARB == NULL || + GetQueryObjectuivARB == NULL || + DeleteQueriesARB == NULL) { + fprintf(stderr, "%s: don't have all the Query functions\n", __FUNCTION__); + return GL_FALSE; + } + + /* Create a query object, and start a query. */ + (*GenQueriesARB)(1, &queryObject); + (*BeginQueryARB)(GL_SAMPLES_PASSED_ARB, queryObject); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* While we're in the query, check the functions that are supposed + * to return which query we're in and how many bits of resolution + * we get. + */ + (*GetQueryivARB)(GL_SAMPLES_PASSED_ARB, GL_CURRENT_QUERY_ARB, &queryCurrent); + if (queryCurrent != queryObject) { + fprintf(stderr, "%s: current query 0x%x != set query 0x%x\n", + __FUNCTION__, queryCurrent, queryObject); + (*EndQueryARB)(GL_SAMPLES_PASSED_ARB); + (*DeleteQueriesARB)(1, &queryObject); + return GL_FALSE; + } + (*GetQueryivARB)(GL_SAMPLES_PASSED_ARB, GL_QUERY_COUNTER_BITS_ARB, + &queryCounterBits); + if (queryCounterBits < 1) { + fprintf(stderr, "%s: query counter bits is too small (%d)\n", + __FUNCTION__, queryCounterBits); + (*EndQueryARB)(GL_SAMPLES_PASSED_ARB); + (*DeleteQueriesARB)(1, &queryObject); + return GL_FALSE; + } + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Finish up the query. Since we didn't draw anything, the result + * should be 0 passed samples. + */ + (*EndQueryARB)(GL_SAMPLES_PASSED_ARB); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Routine existence test */ + if (!(*IsQueryARB)(queryObject)) { + fprintf(stderr, "%s: query object 0x%x fails existence test\n", + __FUNCTION__, queryObject); + (*DeleteQueriesARB)(1, &queryObject); + return GL_FALSE; + } + + /* Loop until the query is ready, then get back the result. We use + * the signed query for the boolean value of whether the result is + * available, but the unsigned query to actually pull the result; + * this is just to test both entrypoints, but in a real query you may + * need the extra bit of resolution. + */ + queryReady = GL_FALSE; + do { + (*GetQueryObjectivARB)(queryObject, GL_QUERY_RESULT_AVAILABLE_ARB, + &queryReady); + } while (!queryReady); + (*GetQueryObjectuivARB)(queryObject, GL_QUERY_RESULT_ARB, &querySampleCount); + (*DeleteQueriesARB)(1, &queryObject); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* If sample count isn't 0, something's funny. */ + if (querySampleCount > 0) { + fprintf(stderr, "%s: expected query result of 0, got %ud\n", + __FUNCTION__, querySampleCount); + return GL_FALSE; + } + + /* Here, all is well. */ + return GL_TRUE; +} + +/************************************************************************** * The following functions are used to check that the named OpenGL function * actually does what it's supposed to do. - * The naming of these functions is signficant. The getprocaddress.py script + * The naming of these functions is significant. The getprocaddress.py script * scans this file and extracts these function names. */ +static GLboolean +test_WeightPointerARB(generic_func func) +{ + /* Assume we have at least 2 vertex units (or this extension makes + * no sense), and establish a set of 2-element vector weights. + * We use floats that can be represented exactly in binary + * floating point formats so we can compare correctly later. + * We also make sure the 0th entry matches the default weights, + * so we can restore the default easily. + */ +#define USE_VERTEX_UNITS 2 +#define USE_WEIGHT_INDEX 3 + static GLfloat weights[] = { + 1.0, 0.0, + 0.875, 0.125, + 0.75, 0.25, + 0.625, 0.375, + 0.5, 0.5, + 0.375, 0.625, + 0.25, 0.75, + 0.125, 0.875, + 0.0, 1.0, + }; + GLint numVertexUnits; + GLfloat *currentWeights; + int i; + int errorCount = 0; + + PFNGLWEIGHTPOINTERARBPROC WeightPointerARB = (PFNGLWEIGHTPOINTERARBPROC) func; + + /* Make sure we have at least two vertex units */ + glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &numVertexUnits); + if (numVertexUnits < USE_VERTEX_UNITS) { + fprintf(stderr, "%s: need %d vertex units, got %d\n", + __FUNCTION__, USE_VERTEX_UNITS, numVertexUnits); + return GL_FALSE; + } + + /* Make sure we allocate enough room to query all the current weights */ + currentWeights = (GLfloat *)malloc(numVertexUnits * sizeof(GLfloat)); + if (currentWeights == NULL) { + fprintf(stderr, "%s: couldn't allocate room for %d floats\n", + __FUNCTION__, numVertexUnits); + return GL_FALSE; + } + + /* Set up the pointer, enable the state, and try to send down a + * weight vector (we'll arbitrarily send index 2). + */ + (*WeightPointerARB)(USE_VERTEX_UNITS, GL_FLOAT, 0, weights); + glEnableClientState(GL_WEIGHT_ARRAY_ARB); + glArrayElement(USE_WEIGHT_INDEX); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Verify that it changed the current state. */ + glGetFloatv(GL_CURRENT_WEIGHT_ARB, currentWeights); + for (i = 0; i < numVertexUnits; i++) { + if (i < USE_VERTEX_UNITS) { + /* This is one of the units we explicitly set. */ + if (currentWeights[i] != weights[USE_VERTEX_UNITS*USE_WEIGHT_INDEX + i]) { + fprintf(stderr, "%s: current weight at index %d is %f, should be %f\n", + __FUNCTION__, i, currentWeights[i], + weights[USE_VERTEX_UNITS*USE_WEIGHT_INDEX + i]); + errorCount++; + } + } + else { + /* All other weights should be 0. */ + if (currentWeights[i] != 0.0) { + fprintf(stderr, "%s: current weight at index %d is %f, should be %f\n", + __FUNCTION__, i, 0.0, + weights[USE_VERTEX_UNITS*USE_WEIGHT_INDEX + i]); + errorCount++; + } + } + } + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Restore the old state. We know the default set of weights is in + * index 0. + */ + glArrayElement(0); + glDisableClientState(GL_WEIGHT_ARRAY_ARB); + (*WeightPointerARB)(0, GL_FLOAT, 0, NULL); + free(currentWeights); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* We're fine if we didn't get any mismatches. */ + if (errorCount == 0) { + return GL_TRUE; + } + else { + return GL_FALSE; + } +} + +/* Wrappers on the exercise_occlusion_query function */ +static GLboolean +test_GenQueriesARB(generic_func func) +{ + (void) func; + return exercise_occlusion_query(); +} +static GLboolean +test_BeginQueryARB(generic_func func) +{ + (void) func; + return exercise_occlusion_query(); +} +static GLboolean +test_GetQueryivARB(generic_func func) +{ + (void) func; + return exercise_occlusion_query(); +} +static GLboolean +test_EndQueryARB(generic_func func) +{ + (void) func; + return exercise_occlusion_query(); +} +static GLboolean +test_IsQueryARB(generic_func func) +{ + (void) func; + return exercise_occlusion_query(); +} +static GLboolean +test_GetQueryObjectivARB(generic_func func) +{ + (void) func; + return exercise_occlusion_query(); +} +static GLboolean +test_GetQueryObjectuivARB(generic_func func) +{ + (void) func; + return exercise_occlusion_query(); +} +static GLboolean +test_DeleteQueriesARB(generic_func func) +{ + (void) func; + return exercise_occlusion_query(); +} + +/* Wrappers on the exercise_buffer_objects() function */ +static GLboolean +test_GenBuffersARB(generic_func func) +{ + (void) func; + return exercise_buffer_objects(Use_Map_Buffer); +} +static GLboolean +test_BindBufferARB(generic_func func) +{ + (void) func; + return exercise_buffer_objects(Use_Map_Buffer); +} +static GLboolean +test_BufferDataARB(generic_func func) +{ + (void) func; + return exercise_buffer_objects(Use_Map_Buffer); +} +static GLboolean +test_MapBufferARB(generic_func func) +{ + (void) func; + return exercise_buffer_objects(Use_Map_Buffer); +} +static GLboolean +test_UnmapBufferARB(generic_func func) +{ + (void) func; + return exercise_buffer_objects(Use_Map_Buffer); +} +static GLboolean +test_DeleteBuffersARB(generic_func func) +{ + (void) func; + return exercise_buffer_objects(Use_Map_Buffer); +} +static GLboolean +test_GetBufferParameterivARB(generic_func func) +{ + (void) func; + return exercise_buffer_objects(Use_Map_Buffer); +} +static GLboolean +test_FlushMappedBufferRange(generic_func func) +{ + (void) func; + return exercise_buffer_objects(Use_Map_Buffer_Range); +} +static GLboolean +test_MapBufferRange(generic_func func) +{ + (void) func; + return exercise_buffer_objects(Use_Map_Buffer_Range); +} +static GLboolean +test_BufferParameteriAPPLE(generic_func func) +{ + (void) func; + return exercise_buffer_objects(Use_Map_Buffer_Range); +} + +/* Wrappers on the exercise_framebuffer() function */ +static GLboolean +test_BindFramebufferEXT(generic_func func) +{ + (void) func; + return exercise_framebuffer(); +} +static GLboolean +test_BindRenderbufferEXT(generic_func func) +{ + (void) func; + return exercise_framebuffer(); +} +static GLboolean +test_CheckFramebufferStatusEXT(generic_func func) +{ + (void) func; + return exercise_framebuffer(); +} +static GLboolean +test_DeleteFramebuffersEXT(generic_func func) +{ + (void) func; + return exercise_framebuffer(); +} +static GLboolean +test_DeleteRenderbuffersEXT(generic_func func) +{ + (void) func; + return exercise_framebuffer(); +} +static GLboolean +test_FramebufferRenderbufferEXT(generic_func func) +{ + (void) func; + return exercise_framebuffer(); +} +static GLboolean +test_GenFramebuffersEXT(generic_func func) +{ + (void) func; + return exercise_framebuffer(); +} +static GLboolean +test_GenRenderbuffersEXT(generic_func func) +{ + (void) func; + return exercise_framebuffer(); +} +static GLboolean +test_IsFramebufferEXT(generic_func func) +{ + (void) func; + return exercise_framebuffer(); +} +static GLboolean +test_IsRenderbufferEXT(generic_func func) +{ + (void) func; + return exercise_framebuffer(); +} +static GLboolean +test_RenderbufferStorageEXT(generic_func func) +{ + (void) func; + return exercise_framebuffer(); +} +static GLboolean +test_BlitFramebufferEXT(generic_func func) +{ + (void) func; + return exercise_framebuffer(); +} + +/* These are wrappers on the exercise_CompressedTextures function. + * Unfortunately, we cannot test the 1D counterparts, because the + * texture compressions available all support 2D and higher only. + */ +static GLboolean +test_CompressedTexImage2DARB(generic_func func) +{ + (void) func; + return exercise_CompressedTextures(GL_TEXTURE_2D); +} +static GLboolean +test_CompressedTexSubImage2DARB(generic_func func) +{ + (void) func; + return exercise_CompressedTextures(GL_TEXTURE_2D); +} +static GLboolean +test_CompressedTexImage3DARB(generic_func func) +{ + (void) func; + return exercise_CompressedTextures(GL_TEXTURE_3D); +} +static GLboolean +test_CompressedTexSubImage3DARB(generic_func func) +{ + (void) func; + return exercise_CompressedTextures(GL_TEXTURE_3D); +} +static GLboolean +test_GetCompressedTexImageARB(generic_func func) +{ + (void) func; + return exercise_CompressedTextures(GL_TEXTURE_3D); +} + +/* Wrappers on exercise_fences(). */ +static GLboolean +test_DeleteFencesNV(generic_func func) +{ + (void) func; + return exercise_fences(); +} +static GLboolean +test_GenFencesNV(generic_func func) +{ + (void) func; + return exercise_fences(); +} +static GLboolean +test_SetFenceNV(generic_func func) +{ + (void) func; + return exercise_fences(); +} +static GLboolean +test_TestFenceNV(generic_func func) +{ + (void) func; + return exercise_fences(); +} +static GLboolean +test_FinishFenceNV(generic_func func) +{ + (void) func; + return exercise_fences(); +} +static GLboolean +test_GetFenceivNV(generic_func func) +{ + (void) func; + return exercise_fences(); +} +static GLboolean +test_IsFenceNV(generic_func func) +{ + (void) func; + return exercise_fences(); +} + +/* A bunch of glUniform*() tests */ +static GLboolean +test_Uniform1iv(generic_func func) +{ + PFNGLUNIFORM1IVARBPROC Uniform1ivARB = (PFNGLUNIFORM1IVARBPROC) func; + DECLARE_GLFUNC_PTR(GetUniformivARB, PFNGLGETUNIFORMIVARBPROC); + + /* This is a trivial fragment shader that sets the color of the + * fragment to the uniform value passed in. + */ + static const char *fragmentShaderText = + "uniform int uniformColor;" + "void main() {gl_FragColor.r = uniformColor;}"; + static const char *uniformName = "uniformColor"; + + GLhandleARB program; + GLint uniformLocation; + const GLint uniform[1] = {1}; + GLint queriedUniform[1]; + + if (GetUniformivARB == NULL) { + return GL_FALSE; + } + + /* Call a helper function to compile up the shader and give + * us back the validated program and uniform location. + * If it fails, something's wrong and we can't continue. + */ + if (!exercise_uniform_start(fragmentShaderText, uniformName, + &program, &uniformLocation)) { + return GL_FALSE; + } + + /* Set the value of the program uniform. Note that you must + * use a compatible type. Our uniform above is an integer + * so we must set it using integer versions + * of the Uniform* functions. The "1" means we're setting + * one vector's worth of information. + */ + (*Uniform1ivARB)(uniformLocation, 1, uniform); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Query it back */ + (*GetUniformivARB)(program, uniformLocation, queriedUniform); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Clean up before we check to see whether it came back unscathed */ + exercise_uniform_end(program); + + /* Now check to see whether the uniform came back as expected. This + * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed. + */ + return compare_ints(__FUNCTION__, 1, uniform, 1, queriedUniform); +} + +static GLboolean +test_Uniform1i(generic_func func) +{ + PFNGLUNIFORM1IARBPROC Uniform1iARB = (PFNGLUNIFORM1IARBPROC) func; + DECLARE_GLFUNC_PTR(GetUniformivARB, PFNGLGETUNIFORMIVARBPROC); + + /* This is a trivial fragment shader that sets the color of the + * fragment to the uniform value passed in. + */ + static const char *fragmentShaderText = + "uniform int uniformColor;" + "void main() {gl_FragColor.r = uniformColor;}"; + static const char *uniformName = "uniformColor"; + + GLhandleARB program; + GLint uniformLocation; + const GLint uniform[1] = {1}; + GLint queriedUniform[4]; + + if (GetUniformivARB == NULL) { + return GL_FALSE; + } + + /* Call a helper function to compile up the shader and give + * us back the validated program and uniform location. + * If it fails, something's wrong and we can't continue. + */ + if (!exercise_uniform_start(fragmentShaderText, uniformName, + &program, &uniformLocation)) { + return GL_FALSE; + } + + /* Set the value of the program uniform. Note that you must + * use a compatible type. Our uniform above is an integer + * so we must set it using integer versions + * of the Uniform* functions. + */ + (*Uniform1iARB)(uniformLocation, uniform[0]); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Query it back */ + (*GetUniformivARB)(program, uniformLocation, queriedUniform); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Clean up before we check to see whether it came back unscathed */ + exercise_uniform_end(program); + + /* Now check to see whether the uniform came back as expected. This + * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed. + */ + return compare_ints(__FUNCTION__, 1, uniform, 1, queriedUniform); +} + +static GLboolean +test_Uniform1fv(generic_func func) +{ + PFNGLUNIFORM1FVARBPROC Uniform1fvARB = (PFNGLUNIFORM1FVARBPROC) func; + DECLARE_GLFUNC_PTR(GetUniformfvARB, PFNGLGETUNIFORMFVARBPROC); + + /* This is a trivial fragment shader that sets the color of the + * fragment to the uniform value passed in. + */ + static const char *fragmentShaderText = + "uniform float uniformColor;" + "void main() {gl_FragColor.r = uniformColor;}"; + static const char *uniformName = "uniformColor"; + + GLhandleARB program; + GLint uniformLocation; + const GLfloat uniform[1] = {1.1}; + GLfloat queriedUniform[1]; + + if (GetUniformfvARB == NULL) { + return GL_FALSE; + } + + /* Call a helper function to compile up the shader and give + * us back the validated program and uniform location. + * If it fails, something's wrong and we can't continue. + */ + if (!exercise_uniform_start(fragmentShaderText, uniformName, + &program, &uniformLocation)) { + return GL_FALSE; + } + + /* Set the value of the program uniform. Note that you must + * use a compatible type. Our uniform above is a float + * so we must set it using float versions + * of the Uniform* functions. The "1" means we're setting + * one vector's worth of information. + */ + (*Uniform1fvARB)(uniformLocation, 1, uniform); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Query it back */ + (*GetUniformfvARB)(program, uniformLocation, queriedUniform); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Clean up before we check to see whether it came back unscathed */ + exercise_uniform_end(program); + + /* Now check to see whether the uniform came back as expected. This + * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed. + */ + return compare_floats(__FUNCTION__, 1, uniform, 1, queriedUniform); +} + +static GLboolean +test_Uniform1f(generic_func func) +{ + PFNGLUNIFORM1FARBPROC Uniform1fARB = (PFNGLUNIFORM1FARBPROC) func; + DECLARE_GLFUNC_PTR(GetUniformfvARB, PFNGLGETUNIFORMFVARBPROC); + + /* This is a trivial fragment shader that sets the color of the + * fragment to the uniform value passed in. + */ + static const char *fragmentShaderText = + "uniform float uniformColor;" + "void main() {gl_FragColor.r = uniformColor;}"; + static const char *uniformName = "uniformColor"; + + GLhandleARB program; + GLint uniformLocation; + const GLfloat uniform[1] = {1.1}; + GLfloat queriedUniform[1]; + + if (GetUniformfvARB == NULL) { + return GL_FALSE; + } + + /* Call a helper function to compile up the shader and give + * us back the validated program and uniform location. + * If it fails, something's wrong and we can't continue. + */ + if (!exercise_uniform_start(fragmentShaderText, uniformName, + &program, &uniformLocation)) { + return GL_FALSE; + } + + /* Set the value of the program uniform. Note that you must + * use a compatible type. Our uniform above is a float + * so we must set it using float versions + * of the Uniform* functions. + */ + (*Uniform1fARB)(uniformLocation, uniform[0]); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Query it back */ + (*GetUniformfvARB)(program, uniformLocation, queriedUniform); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Clean up before we check to see whether it came back unscathed */ + exercise_uniform_end(program); + + /* Now check to see whether the uniform came back as expected. This + * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed. + */ + return compare_floats(__FUNCTION__, 1, uniform, 1, queriedUniform); +} + +static GLboolean +test_Uniform2iv(generic_func func) +{ + PFNGLUNIFORM2IVARBPROC Uniform2ivARB = (PFNGLUNIFORM2IVARBPROC) func; + DECLARE_GLFUNC_PTR(GetUniformivARB, PFNGLGETUNIFORMIVARBPROC); + + /* This is a trivial fragment shader that sets the color of the + * fragment to the uniform value passed in. + */ + static const char *fragmentShaderText = + "uniform ivec2 uniformColor;" + "void main() {gl_FragColor.rg = uniformColor;}"; + static const char *uniformName = "uniformColor"; + + GLhandleARB program; + GLint uniformLocation; + const GLint uniform[2] = {1,2}; + GLint queriedUniform[2]; + + if (GetUniformivARB == NULL) { + return GL_FALSE; + } + + /* Call a helper function to compile up the shader and give + * us back the validated program and uniform location. + * If it fails, something's wrong and we can't continue. + */ + if (!exercise_uniform_start(fragmentShaderText, uniformName, + &program, &uniformLocation)) { + return GL_FALSE; + } + + /* Set the value of the program uniform. Note that you must + * use a compatible type. Our uniform above is an integer + * vector 2 (ivec2), so we must set it using integer versions + * of the Uniform* functions. The "1" means we're setting + * one vector's worth of information. + */ + (*Uniform2ivARB)(uniformLocation, 1, uniform); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Query it back */ + (*GetUniformivARB)(program, uniformLocation, queriedUniform); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Clean up before we check to see whether it came back unscathed */ + exercise_uniform_end(program); + + /* Now check to see whether the uniform came back as expected. This + * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed. + */ + return compare_ints(__FUNCTION__, 2, uniform, 2, queriedUniform); +} + +static GLboolean +test_Uniform2i(generic_func func) +{ + PFNGLUNIFORM2IARBPROC Uniform2iARB = (PFNGLUNIFORM2IARBPROC) func; + DECLARE_GLFUNC_PTR(GetUniformivARB, PFNGLGETUNIFORMIVARBPROC); + + /* This is a trivial fragment shader that sets the color of the + * fragment to the uniform value passed in. + */ + static const char *fragmentShaderText = + "uniform ivec2 uniformColor;" + "void main() {gl_FragColor.rg = uniformColor;}"; + static const char *uniformName = "uniformColor"; + + GLhandleARB program; + GLint uniformLocation; + const GLint uniform[2] = {1,2}; + GLint queriedUniform[4]; + + if (GetUniformivARB == NULL) { + return GL_FALSE; + } + + /* Call a helper function to compile up the shader and give + * us back the validated program and uniform location. + * If it fails, something's wrong and we can't continue. + */ + if (!exercise_uniform_start(fragmentShaderText, uniformName, + &program, &uniformLocation)) { + return GL_FALSE; + } + + /* Set the value of the program uniform. Note that you must + * use a compatible type. Our uniform above is an integer + * vector 2 (ivec2), so we must set it using integer versions + * of the Uniform* functions. + */ + (*Uniform2iARB)(uniformLocation, uniform[0], uniform[1]); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Query it back */ + (*GetUniformivARB)(program, uniformLocation, queriedUniform); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Clean up before we check to see whether it came back unscathed */ + exercise_uniform_end(program); + + /* Now check to see whether the uniform came back as expected. This + * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed. + */ + return compare_ints(__FUNCTION__, 2, uniform, 2, queriedUniform); +} + +static GLboolean +test_Uniform2fv(generic_func func) +{ + PFNGLUNIFORM2FVARBPROC Uniform2fvARB = (PFNGLUNIFORM2FVARBPROC) func; + DECLARE_GLFUNC_PTR(GetUniformfvARB, PFNGLGETUNIFORMFVARBPROC); + + /* This is a trivial fragment shader that sets the color of the + * fragment to the uniform value passed in. + */ + static const char *fragmentShaderText = + "uniform vec2 uniformColor;" + "void main() {gl_FragColor.rg = uniformColor;}"; + static const char *uniformName = "uniformColor"; + + GLhandleARB program; + GLint uniformLocation; + const GLfloat uniform[2] = {1.1,2.2}; + GLfloat queriedUniform[2]; + + if (GetUniformfvARB == NULL) { + return GL_FALSE; + } + + /* Call a helper function to compile up the shader and give + * us back the validated program and uniform location. + * If it fails, something's wrong and we can't continue. + */ + if (!exercise_uniform_start(fragmentShaderText, uniformName, + &program, &uniformLocation)) { + return GL_FALSE; + } + + /* Set the value of the program uniform. Note that you must + * use a compatible type. Our uniform above is a float + * vector 2 (vec2), so we must set it using float versions + * of the Uniform* functions. The "1" means we're setting + * one vector's worth of information. + */ + (*Uniform2fvARB)(uniformLocation, 1, uniform); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Query it back */ + (*GetUniformfvARB)(program, uniformLocation, queriedUniform); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Clean up before we check to see whether it came back unscathed */ + exercise_uniform_end(program); + + /* Now check to see whether the uniform came back as expected. This + * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed. + */ + return compare_floats(__FUNCTION__, 2, uniform, 2, queriedUniform); +} + +static GLboolean +test_Uniform2f(generic_func func) +{ + PFNGLUNIFORM2FARBPROC Uniform2fARB = (PFNGLUNIFORM2FARBPROC) func; + DECLARE_GLFUNC_PTR(GetUniformfvARB, PFNGLGETUNIFORMFVARBPROC); + + /* This is a trivial fragment shader that sets the color of the + * fragment to the uniform value passed in. + */ + static const char *fragmentShaderText = + "uniform vec2 uniformColor;" + "void main() {gl_FragColor.rg = uniformColor;}"; + static const char *uniformName = "uniformColor"; + + GLhandleARB program; + GLint uniformLocation; + const GLfloat uniform[2] = {1.1,2.2}; + GLfloat queriedUniform[2]; + + if (GetUniformfvARB == NULL) { + return GL_FALSE; + } + + /* Call a helper function to compile up the shader and give + * us back the validated program and uniform location. + * If it fails, something's wrong and we can't continue. + */ + if (!exercise_uniform_start(fragmentShaderText, uniformName, + &program, &uniformLocation)) { + return GL_FALSE; + } + + /* Set the value of the program uniform. Note that you must + * use a compatible type. Our uniform above is a float + * vector 2 (vec2), so we must set it using float versions + * of the Uniform* functions. + */ + (*Uniform2fARB)(uniformLocation, uniform[0], uniform[1]); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Query it back */ + (*GetUniformfvARB)(program, uniformLocation, queriedUniform); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Clean up before we check to see whether it came back unscathed */ + exercise_uniform_end(program); + + /* Now check to see whether the uniform came back as expected. This + * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed. + */ + return compare_floats(__FUNCTION__, 2, uniform, 2, queriedUniform); +} + +static GLboolean +test_Uniform3iv(generic_func func) +{ + PFNGLUNIFORM3IVARBPROC Uniform3ivARB = (PFNGLUNIFORM3IVARBPROC) func; + DECLARE_GLFUNC_PTR(GetUniformivARB, PFNGLGETUNIFORMIVARBPROC); + + /* This is a trivial fragment shader that sets the color of the + * fragment to the uniform value passed in. + */ + static const char *fragmentShaderText = + "uniform ivec3 uniformColor;" + "void main() {gl_FragColor.rgb = uniformColor;}"; + static const char *uniformName = "uniformColor"; + + GLhandleARB program; + GLint uniformLocation; + const GLint uniform[3] = {1,2,3}; + GLint queriedUniform[3]; + + if (GetUniformivARB == NULL) { + return GL_FALSE; + } + + /* Call a helper function to compile up the shader and give + * us back the validated program and uniform location. + * If it fails, something's wrong and we can't continue. + */ + if (!exercise_uniform_start(fragmentShaderText, uniformName, + &program, &uniformLocation)) { + return GL_FALSE; + } + + /* Set the value of the program uniform. Note that you must + * use a compatible type. Our uniform above is an integer + * vector 3 (ivec3), so we must set it using integer versions + * of the Uniform* functions. The "1" means we're setting + * one vector's worth of information. + */ + (*Uniform3ivARB)(uniformLocation, 1, uniform); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Query it back */ + (*GetUniformivARB)(program, uniformLocation, queriedUniform); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Clean up before we check to see whether it came back unscathed */ + exercise_uniform_end(program); + + /* Now check to see whether the uniform came back as expected. This + * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed. + */ + return compare_ints(__FUNCTION__, 3, uniform, 3, queriedUniform); +} + +static GLboolean +test_Uniform3i(generic_func func) +{ + PFNGLUNIFORM3IARBPROC Uniform3iARB = (PFNGLUNIFORM3IARBPROC) func; + DECLARE_GLFUNC_PTR(GetUniformivARB, PFNGLGETUNIFORMIVARBPROC); + + /* This is a trivial fragment shader that sets the color of the + * fragment to the uniform value passed in. + */ + static const char *fragmentShaderText = + "uniform ivec3 uniformColor;" + "void main() {gl_FragColor.rgb = uniformColor;}"; + static const char *uniformName = "uniformColor"; + + GLhandleARB program; + GLint uniformLocation; + const GLint uniform[3] = {1,2,3}; + GLint queriedUniform[4]; + + if (GetUniformivARB == NULL) { + return GL_FALSE; + } + + /* Call a helper function to compile up the shader and give + * us back the validated program and uniform location. + * If it fails, something's wrong and we can't continue. + */ + if (!exercise_uniform_start(fragmentShaderText, uniformName, + &program, &uniformLocation)) { + return GL_FALSE; + } + + /* Set the value of the program uniform. Note that you must + * use a compatible type. Our uniform above is an integer + * vector 3 (ivec3), so we must set it using integer versions + * of the Uniform* functions. + */ + (*Uniform3iARB)(uniformLocation, uniform[0], uniform[1], uniform[2]); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Query it back */ + (*GetUniformivARB)(program, uniformLocation, queriedUniform); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Clean up before we check to see whether it came back unscathed */ + exercise_uniform_end(program); + + /* Now check to see whether the uniform came back as expected. This + * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed. + */ + return compare_ints(__FUNCTION__, 3, uniform, 3, queriedUniform); +} + +static GLboolean +test_Uniform3fv(generic_func func) +{ + PFNGLUNIFORM3FVARBPROC Uniform3fvARB = (PFNGLUNIFORM3FVARBPROC) func; + DECLARE_GLFUNC_PTR(GetUniformfvARB, PFNGLGETUNIFORMFVARBPROC); + + /* This is a trivial fragment shader that sets the color of the + * fragment to the uniform value passed in. + */ + static const char *fragmentShaderText = + "uniform vec3 uniformColor;" + "void main() {gl_FragColor.rgb = uniformColor;}"; + static const char *uniformName = "uniformColor"; + + GLhandleARB program; + GLint uniformLocation; + const GLfloat uniform[3] = {1.1,2.2,3.3}; + GLfloat queriedUniform[3]; + + if (GetUniformfvARB == NULL) { + return GL_FALSE; + } + + /* Call a helper function to compile up the shader and give + * us back the validated program and uniform location. + * If it fails, something's wrong and we can't continue. + */ + if (!exercise_uniform_start(fragmentShaderText, uniformName, + &program, &uniformLocation)) { + return GL_FALSE; + } + + /* Set the value of the program uniform. Note that you must + * use a compatible type. Our uniform above is a float + * vector 3 (vec3), so we must set it using float versions + * of the Uniform* functions. The "1" means we're setting + * one vector's worth of information. + */ + (*Uniform3fvARB)(uniformLocation, 1, uniform); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Query it back */ + (*GetUniformfvARB)(program, uniformLocation, queriedUniform); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Clean up before we check to see whether it came back unscathed */ + exercise_uniform_end(program); + + /* Now check to see whether the uniform came back as expected. This + * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed. + */ + return compare_floats(__FUNCTION__, 3, uniform, 3, queriedUniform); +} + +static GLboolean +test_Uniform3f(generic_func func) +{ + PFNGLUNIFORM3FARBPROC Uniform3fARB = (PFNGLUNIFORM3FARBPROC) func; + DECLARE_GLFUNC_PTR(GetUniformfvARB, PFNGLGETUNIFORMFVARBPROC); + + /* This is a trivial fragment shader that sets the color of the + * fragment to the uniform value passed in. + */ + static const char *fragmentShaderText = + "uniform vec3 uniformColor;" + "void main() {gl_FragColor.rgb = uniformColor;}"; + static const char *uniformName = "uniformColor"; + + GLhandleARB program; + GLint uniformLocation; + const GLfloat uniform[3] = {1.1,2.2,3.3}; + GLfloat queriedUniform[3]; + + if (GetUniformfvARB == NULL) { + return GL_FALSE; + } + + /* Call a helper function to compile up the shader and give + * us back the validated program and uniform location. + * If it fails, something's wrong and we can't continue. + */ + if (!exercise_uniform_start(fragmentShaderText, uniformName, + &program, &uniformLocation)) { + return GL_FALSE; + } + + /* Set the value of the program uniform. Note that you must + * use a compatible type. Our uniform above is a float + * vector 3 (vec3), so we must set it using float versions + * of the Uniform* functions. + */ + (*Uniform3fARB)(uniformLocation, uniform[0], uniform[1], uniform[2]); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Query it back */ + (*GetUniformfvARB)(program, uniformLocation, queriedUniform); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Clean up before we check to see whether it came back unscathed */ + exercise_uniform_end(program); + + /* Now check to see whether the uniform came back as expected. This + * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed. + */ + return compare_floats(__FUNCTION__, 3, uniform, 3, queriedUniform); +} + +static GLboolean +test_Uniform4iv(generic_func func) +{ + PFNGLUNIFORM4IVARBPROC Uniform4ivARB = (PFNGLUNIFORM4IVARBPROC) func; + DECLARE_GLFUNC_PTR(GetUniformivARB, PFNGLGETUNIFORMIVARBPROC); + + /* This is a trivial fragment shader that sets the color of the + * fragment to the uniform value passed in. + */ + static const char *fragmentShaderText = + "uniform ivec4 uniformColor; void main() {gl_FragColor = uniformColor;}"; + static const char *uniformName = "uniformColor"; + + GLhandleARB program; + GLint uniformLocation; + const GLint uniform[4] = {1,2,3,4}; + GLint queriedUniform[4]; + + if (GetUniformivARB == NULL) { + return GL_FALSE; + } + + /* Call a helper function to compile up the shader and give + * us back the validated program and uniform location. + * If it fails, something's wrong and we can't continue. + */ + if (!exercise_uniform_start(fragmentShaderText, uniformName, + &program, &uniformLocation)) { + return GL_FALSE; + } + + /* Set the value of the program uniform. Note that you must + * use a compatible type. Our uniform above is an integer + * vector (ivec4), so we must set it using integer versions + * of the Uniform* functions. The "1" means we're setting + * one vector's worth of information. + */ + (*Uniform4ivARB)(uniformLocation, 1, uniform); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Query it back */ + (*GetUniformivARB)(program, uniformLocation, queriedUniform); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Clean up before we check to see whether it came back unscathed */ + exercise_uniform_end(program); + + /* Now check to see whether the uniform came back as expected. This + * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed. + */ + return compare_ints(__FUNCTION__, 4, uniform, 4, queriedUniform); +} + +static GLboolean +test_Uniform4i(generic_func func) +{ + PFNGLUNIFORM4IARBPROC Uniform4iARB = (PFNGLUNIFORM4IARBPROC) func; + DECLARE_GLFUNC_PTR(GetUniformivARB, PFNGLGETUNIFORMIVARBPROC); + + /* This is a trivial fragment shader that sets the color of the + * fragment to the uniform value passed in. + */ + static const char *fragmentShaderText = + "uniform ivec4 uniformColor; void main() {gl_FragColor = uniformColor;}"; + static const char *uniformName = "uniformColor"; + + GLhandleARB program; + GLint uniformLocation; + const GLint uniform[4] = {1,2,3,4}; + GLint queriedUniform[4]; + + if (GetUniformivARB == NULL) { + return GL_FALSE; + } + + /* Call a helper function to compile up the shader and give + * us back the validated program and uniform location. + * If it fails, something's wrong and we can't continue. + */ + if (!exercise_uniform_start(fragmentShaderText, uniformName, + &program, &uniformLocation)) { + return GL_FALSE; + } + + /* Set the value of the program uniform. Note that you must + * use a compatible type. Our uniform above is an integer + * vector (ivec4), so we must set it using integer versions + * of the Uniform* functions. + */ + (*Uniform4iARB)(uniformLocation, uniform[0], uniform[1], uniform[2], + uniform[3]); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Query it back */ + (*GetUniformivARB)(program, uniformLocation, queriedUniform); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Clean up before we check to see whether it came back unscathed */ + exercise_uniform_end(program); + + /* Now check to see whether the uniform came back as expected. This + * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed. + */ + return compare_ints(__FUNCTION__, 4, uniform, 4, queriedUniform); +} + +static GLboolean +test_Uniform4fv(generic_func func) +{ + PFNGLUNIFORM4FVARBPROC Uniform4fvARB = (PFNGLUNIFORM4FVARBPROC) func; + DECLARE_GLFUNC_PTR(GetUniformfvARB, PFNGLGETUNIFORMFVARBPROC); + + /* This is a trivial fragment shader that sets the color of the + * fragment to the uniform value passed in. + */ + static const char *fragmentShaderText = + "uniform vec4 uniformColor; void main() {gl_FragColor = uniformColor;}"; + static const char *uniformName = "uniformColor"; + + GLhandleARB program; + GLint uniformLocation; + const GLfloat uniform[4] = {1.1,2.2,3.3,4.4}; + GLfloat queriedUniform[4]; + + if (GetUniformfvARB == NULL) { + return GL_FALSE; + } + + /* Call a helper function to compile up the shader and give + * us back the validated program and uniform location. + * If it fails, something's wrong and we can't continue. + */ + if (!exercise_uniform_start(fragmentShaderText, uniformName, + &program, &uniformLocation)) { + return GL_FALSE; + } + + /* Set the value of the program uniform. Note that you must + * use a compatible type. Our uniform above is a float + * vector (vec4), so we must set it using float versions + * of the Uniform* functions. The "1" means we're setting + * one vector's worth of information. + */ + (*Uniform4fvARB)(uniformLocation, 1, uniform); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Query it back */ + (*GetUniformfvARB)(program, uniformLocation, queriedUniform); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Clean up before we check to see whether it came back unscathed */ + exercise_uniform_end(program); + + /* Now check to see whether the uniform came back as expected. This + * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed. + */ + return compare_floats(__FUNCTION__, 4, uniform, 4, queriedUniform); +} + +static GLboolean +test_Uniform4f(generic_func func) +{ + PFNGLUNIFORM4FARBPROC Uniform4fARB = (PFNGLUNIFORM4FARBPROC) func; + DECLARE_GLFUNC_PTR(GetUniformfvARB, PFNGLGETUNIFORMFVARBPROC); + + /* This is a trivial fragment shader that sets the color of the + * fragment to the uniform value passed in. + */ + static const char *fragmentShaderText = + "uniform vec4 uniformColor; void main() {gl_FragColor = uniformColor;}"; + static const char *uniformName = "uniformColor"; + + GLhandleARB program; + GLint uniformLocation; + const GLfloat uniform[4] = {1.1,2.2,3.3,4.4}; + GLfloat queriedUniform[4]; + + if (GetUniformfvARB == NULL) { + return GL_FALSE; + } + + /* Call a helper function to compile up the shader and give + * us back the validated program and uniform location. + * If it fails, something's wrong and we can't continue. + */ + if (!exercise_uniform_start(fragmentShaderText, uniformName, + &program, &uniformLocation)) { + return GL_FALSE; + } + + /* Set the value of the program uniform. Note that you must + * use a compatible type. Our uniform above is an integer + * vector (ivec4), so we must set it using integer versions + * of the Uniform* functions. + */ + (*Uniform4fARB)(uniformLocation, uniform[0], uniform[1], uniform[2], + uniform[3]); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Query it back */ + (*GetUniformfvARB)(program, uniformLocation, queriedUniform); + CheckGLError(__LINE__, __FILE__, __FUNCTION__); + + /* Clean up before we check to see whether it came back unscathed */ + exercise_uniform_end(program); + + /* Now check to see whether the uniform came back as expected. This + * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed. + */ + return compare_floats(__FUNCTION__, 4, uniform, 4, queriedUniform); +} static GLboolean test_ActiveTextureARB(generic_func func) @@ -107,6 +2694,40 @@ test_VertexAttrib1fvARB(generic_func func) } static GLboolean +test_VertexAttrib1dvARB(generic_func func) +{ + PFNGLVERTEXATTRIB1DVARBPROC vertexAttrib1dvARB = (PFNGLVERTEXATTRIB1DVARBPROC) func; + PFNGLGETVERTEXATTRIBDVARBPROC getVertexAttribdvARB = (PFNGLGETVERTEXATTRIBDVARBPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvARB"); + + const GLdouble v[1] = {25.0}; + const GLdouble def[1] = {0}; + GLdouble res[4]; + GLboolean pass; + (*vertexAttrib1dvARB)(6, v); + (*getVertexAttribdvARB)(6, GL_CURRENT_VERTEX_ATTRIB_ARB, res); + pass = (res[0] == 25.0 && res[1] == 0.0 && res[2] == 0.0 && res[3] == 1.0); + (*vertexAttrib1dvARB)(6, def); + return pass; +} + +static GLboolean +test_VertexAttrib1svARB(generic_func func) +{ + PFNGLVERTEXATTRIB1SVARBPROC vertexAttrib1svARB = (PFNGLVERTEXATTRIB1SVARBPROC) func; + PFNGLGETVERTEXATTRIBIVARBPROC getVertexAttribivARB = (PFNGLGETVERTEXATTRIBIVARBPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivARB"); + + const GLshort v[1] = {25.0}; + const GLshort def[1] = {0}; + GLint res[4]; + GLboolean pass; + (*vertexAttrib1svARB)(6, v); + (*getVertexAttribivARB)(6, GL_CURRENT_VERTEX_ATTRIB_ARB, res); + pass = (res[0] == 25 && res[1] == 0 && res[2] == 0 && res[3] == 1); + (*vertexAttrib1svARB)(6, def); + return pass; +} + +static GLboolean test_VertexAttrib4NubvARB(generic_func func) { PFNGLVERTEXATTRIB4NUBVARBPROC vertexAttrib4NubvARB = (PFNGLVERTEXATTRIB4NUBVARBPROC) func; @@ -177,7 +2798,6 @@ test_VertexAttrib4NsvARB(generic_func func) return pass; } - static GLboolean test_VertexAttrib4NusvARB(generic_func func) { @@ -195,42 +2815,110 @@ test_VertexAttrib4NusvARB(generic_func func) return pass; } +static GLboolean +test_VertexAttrib1sNV(generic_func func) +{ + PFNGLVERTEXATTRIB1SNVPROC vertexAttrib1sNV = (PFNGLVERTEXATTRIB1SNVPROC) func; + PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV"); + + const GLshort v[4] = {2, 0, 0, 1}; + const GLshort def[4] = {0, 0, 0, 1}; + GLint res[4]; + (*vertexAttrib1sNV)(6, v[0]); + (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res); + (*vertexAttrib1sNV)(6, def[0]); + return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res); +} static GLboolean -test_VertexAttrib4ubNV(generic_func func) +test_VertexAttrib1fNV(generic_func func) { - PFNGLVERTEXATTRIB4UBNVPROC vertexAttrib4ubNV = (PFNGLVERTEXATTRIB4UBNVPROC) func; + PFNGLVERTEXATTRIB1FNVPROC vertexAttrib1fNV = (PFNGLVERTEXATTRIB1FNVPROC) func; PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV"); - const GLubyte v[4] = {255, 0, 255, 0}; - const GLubyte def[4] = {0, 0, 0, 255}; + const GLfloat v[4] = {2.5, 0.0, 0.0, 1.0}; + const GLfloat def[4] = {0, 0, 0, 1}; GLfloat res[4]; - GLboolean pass; - (*vertexAttrib4ubNV)(6, v[0], v[1], v[2], v[3]); + (*vertexAttrib1fNV)(6, v[0]); (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res); - pass = (res[0] == 1.0 && res[1] == 0.0 && res[2] == 1.0 && res[3] == 0.0); - (*vertexAttrib4ubNV)(6, def[0], def[1], def[2], def[3]); - return pass; + (*vertexAttrib1fNV)(6, def[0]); + return compare_floats(__FUNCTION__, 4, v, 4, res); } +static GLboolean +test_VertexAttrib1dNV(generic_func func) +{ + PFNGLVERTEXATTRIB1DNVPROC vertexAttrib1dNV = (PFNGLVERTEXATTRIB1DNVPROC) func; + PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV"); + + const GLdouble v[4] = {2.5, 0.0, 0.0, 1.0}; + const GLdouble def[4] = {0, 0, 0, 1}; + GLdouble res[4]; + (*vertexAttrib1dNV)(6, v[0]); + (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res); + (*vertexAttrib1dNV)(6, def[0]); + return compare_doubles(__FUNCTION__, 4, v, 4, res); +} static GLboolean test_VertexAttrib2sNV(generic_func func) { PFNGLVERTEXATTRIB2SNVPROC vertexAttrib2sNV = (PFNGLVERTEXATTRIB2SNVPROC) func; + PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV"); + + const GLshort v[4] = {2, 4, 0, 1}; + const GLshort def[4] = {0, 0, 0, 1}; + GLint res[4]; + (*vertexAttrib2sNV)(6, v[0], v[1]); + (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res); + (*vertexAttrib2sNV)(6, def[0], def[1]); + return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res); +} + +static GLboolean +test_VertexAttrib2fNV(generic_func func) +{ + PFNGLVERTEXATTRIB2FNVPROC vertexAttrib2fNV = (PFNGLVERTEXATTRIB2FNVPROC) func; PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV"); - const GLshort v[2] = {2, -4,}; - const GLshort def[2] = {0, 0}; + const GLfloat v[4] = {2.5, 4.25, 0.0, 1.0}; + const GLfloat def[4] = {0, 0, 0, 1}; GLfloat res[4]; - GLboolean pass; - (*vertexAttrib2sNV)(6, v[0], v[1]); + (*vertexAttrib2fNV)(6, v[0], v[1]); (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res); - pass = (EQUAL(res[0], 2) && EQUAL(res[1], -4) && EQUAL(res[2], 0) && res[3] == 1.0); - (*vertexAttrib2sNV)(6, def[0], def[1]); - return pass; + (*vertexAttrib2fNV)(6, def[0], def[1]); + return compare_floats(__FUNCTION__, 4, v, 4, res); +} + +static GLboolean +test_VertexAttrib2dNV(generic_func func) +{ + PFNGLVERTEXATTRIB2DNVPROC vertexAttrib2dNV = (PFNGLVERTEXATTRIB2DNVPROC) func; + PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV"); + + const GLdouble v[4] = {2.5, 4.25, 0.0, 1.0}; + const GLdouble def[4] = {0, 0, 0, 1}; + GLdouble res[4]; + (*vertexAttrib2dNV)(6, v[0], v[1]); + (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res); + (*vertexAttrib2dNV)(6, def[0], def[1]); + return compare_doubles(__FUNCTION__, 4, v, 4, res); } +static GLboolean +test_VertexAttrib3sNV(generic_func func) +{ + PFNGLVERTEXATTRIB3SNVPROC vertexAttrib3sNV = (PFNGLVERTEXATTRIB3SNVPROC) func; + PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV"); + + const GLshort v[4] = {2, 4, 7, 1}; + const GLshort def[4] = {0, 0, 0, 1}; + GLint res[4]; + (*vertexAttrib3sNV)(6, v[0], v[1], v[2]); + (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res); + (*vertexAttrib3sNV)(6, def[0], def[1], def[2]); + return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res); +} static GLboolean test_VertexAttrib3fNV(generic_func func) @@ -238,35 +2926,467 @@ test_VertexAttrib3fNV(generic_func func) PFNGLVERTEXATTRIB3FNVPROC vertexAttrib3fNV = (PFNGLVERTEXATTRIB3FNVPROC) func; PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV"); - const GLfloat v[3] = {0.2, 0.4, 0.8}; - const GLfloat def[3] = {0, 0, 0}; + const GLfloat v[4] = {2.5, 4.25, 7.125, 1.0}; + const GLfloat def[4] = {0, 0, 0, 1}; GLfloat res[4]; - GLboolean pass; (*vertexAttrib3fNV)(6, v[0], v[1], v[2]); (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res); - pass = (EQUAL(res[0], 0.2) && EQUAL(res[1], 0.4) && EQUAL(res[2], 0.8) && res[3] == 1.0); (*vertexAttrib3fNV)(6, def[0], def[1], def[2]); - return pass; + return compare_floats(__FUNCTION__, 4, v, 4, res); } +static GLboolean +test_VertexAttrib3dNV(generic_func func) +{ + PFNGLVERTEXATTRIB3DNVPROC vertexAttrib3dNV = (PFNGLVERTEXATTRIB3DNVPROC) func; + PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV"); + + const GLdouble v[4] = {2.5, 4.25, 7.125, 1.0}; + const GLdouble def[4] = {0, 0, 0, 1}; + GLdouble res[4]; + (*vertexAttrib3dNV)(6, v[0], v[1], v[2]); + (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res); + (*vertexAttrib3dNV)(6, def[0], def[1], def[2]); + return compare_doubles(__FUNCTION__, 4, v, 4, res); +} + +static GLboolean +test_VertexAttrib4sNV(generic_func func) +{ + PFNGLVERTEXATTRIB4SNVPROC vertexAttrib4sNV = (PFNGLVERTEXATTRIB4SNVPROC) func; + PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV"); + + const GLshort v[4] = {2, 4, 7, 5}; + const GLshort def[4] = {0, 0, 0, 1}; + GLint res[4]; + (*vertexAttrib4sNV)(6, v[0], v[1], v[2], v[3]); + (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res); + (*vertexAttrib4sNV)(6, def[0], def[1], def[2], def[3]); + return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res); +} + +static GLboolean +test_VertexAttrib4fNV(generic_func func) +{ + PFNGLVERTEXATTRIB4FNVPROC vertexAttrib4fNV = (PFNGLVERTEXATTRIB4FNVPROC) func; + PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV"); + + const GLfloat v[4] = {2.5, 4.25, 7.125, 5.0625}; + const GLfloat def[4] = {0, 0, 0, 1}; + GLfloat res[4]; + (*vertexAttrib4fNV)(6, v[0], v[1], v[2], v[3]); + (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res); + (*vertexAttrib4fNV)(6, def[0], def[1], def[2], def[3]); + return compare_floats(__FUNCTION__, 4, v, 4, res); +} + +static GLboolean +test_VertexAttrib4dNV(generic_func func) +{ + PFNGLVERTEXATTRIB4DNVPROC vertexAttrib4dNV = (PFNGLVERTEXATTRIB4DNVPROC) func; + PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV"); + + const GLdouble v[4] = {2.5, 4.25, 7.125, 5.0625}; + const GLdouble def[4] = {0, 0, 0, 1}; + GLdouble res[4]; + (*vertexAttrib4dNV)(6, v[0], v[1], v[2], v[3]); + (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res); + (*vertexAttrib4dNV)(6, def[0], def[1], def[2], def[3]); + return compare_doubles(__FUNCTION__, 4, v, 4, res); +} + +static GLboolean +test_VertexAttrib4ubNV(generic_func func) +{ + PFNGLVERTEXATTRIB4UBNVPROC vertexAttrib4ubNV = (PFNGLVERTEXATTRIB4UBNVPROC) func; + PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV"); + + const GLubyte v[4] = {255, 0, 255, 0}; + const GLubyte def[4] = {0, 0, 0, 255}; + GLfloat res[4]; + /* There's no byte-value query; so we use the float-value query. + * Bytes are interpreted as steps between 0 and 1, so the + * expected float values will be 0.0 for byte value 0 and 1.0 for + * byte value 255. + */ + GLfloat expectedResults[4] = {1.0, 0.0, 1.0, 0.0}; + (*vertexAttrib4ubNV)(6, v[0], v[1], v[2], v[3]); + (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res); + (*vertexAttrib4ubNV)(6, def[0], def[1], def[2], def[3]); + return compare_floats(__FUNCTION__, 4, expectedResults, 4, res); +} + +static GLboolean +test_VertexAttrib1fvNV(generic_func func) +{ + PFNGLVERTEXATTRIB1FVNVPROC vertexAttrib1fvNV = (PFNGLVERTEXATTRIB1FVNVPROC) func; + PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV"); + + const GLfloat v[4] = {2.5, 0.0, 0.0, 1.0}; + const GLfloat def[4] = {0, 0, 0, 1}; + GLfloat res[4]; + (*vertexAttrib1fvNV)(6, v); + (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res); + (*vertexAttrib1fvNV)(6, def); + return compare_floats(__FUNCTION__, 4, v, 4, res); +} + +static GLboolean +test_VertexAttrib1dvNV(generic_func func) +{ + PFNGLVERTEXATTRIB1DVNVPROC vertexAttrib1dvNV = (PFNGLVERTEXATTRIB1DVNVPROC) func; + PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV"); + + const GLdouble v[4] = {2.5, 0.0, 0.0, 1.0}; + const GLdouble def[4] = {0, 0, 0, 1}; + GLdouble res[4]; + (*vertexAttrib1dvNV)(6, v); + (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res); + (*vertexAttrib1dvNV)(6, def); + return compare_doubles(__FUNCTION__, 4, v, 4, res); +} + +static GLboolean +test_VertexAttrib2svNV(generic_func func) +{ + PFNGLVERTEXATTRIB2SVNVPROC vertexAttrib2svNV = (PFNGLVERTEXATTRIB2SVNVPROC) func; + PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV"); + + const GLshort v[4] = {2, 4, 0, 1}; + const GLshort def[4] = {0, 0, 0, 1}; + GLint res[4]; + (*vertexAttrib2svNV)(6, v); + (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res); + (*vertexAttrib2svNV)(6, def); + return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res); +} + +static GLboolean +test_VertexAttrib2fvNV(generic_func func) +{ + PFNGLVERTEXATTRIB2FVNVPROC vertexAttrib2fvNV = (PFNGLVERTEXATTRIB2FVNVPROC) func; + PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV"); + + const GLfloat v[4] = {2.5, 4.25, 0.0, 1.0}; + const GLfloat def[4] = {0, 0, 0, 1}; + GLfloat res[4]; + (*vertexAttrib2fvNV)(6, v); + (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res); + (*vertexAttrib2fvNV)(6, def); + return compare_floats(__FUNCTION__, 4, v, 4, res); +} + +static GLboolean +test_VertexAttrib2dvNV(generic_func func) +{ + PFNGLVERTEXATTRIB2DVNVPROC vertexAttrib2dvNV = (PFNGLVERTEXATTRIB2DVNVPROC) func; + PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV"); + + const GLdouble v[4] = {2.5, 4.25, 0.0, 1.0}; + const GLdouble def[4] = {0, 0, 0, 1}; + GLdouble res[4]; + (*vertexAttrib2dvNV)(6, v); + (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res); + (*vertexAttrib2dvNV)(6, def); + return compare_doubles(__FUNCTION__, 4, v, 4, res); +} + +static GLboolean +test_VertexAttrib3svNV(generic_func func) +{ + PFNGLVERTEXATTRIB3SVNVPROC vertexAttrib3svNV = (PFNGLVERTEXATTRIB3SVNVPROC) func; + PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV"); + + const GLshort v[4] = {2, 4, 7, 1}; + const GLshort def[4] = {0, 0, 0, 1}; + GLint res[4]; + (*vertexAttrib3svNV)(6, v); + (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res); + (*vertexAttrib3svNV)(6, def); + return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res); +} + +static GLboolean +test_VertexAttrib3fvNV(generic_func func) +{ + PFNGLVERTEXATTRIB3FVNVPROC vertexAttrib3fvNV = (PFNGLVERTEXATTRIB3FVNVPROC) func; + PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV"); + + const GLfloat v[4] = {2.5, 4.25, 7.125, 1.0}; + const GLfloat def[4] = {0, 0, 0, 1}; + GLfloat res[4]; + (*vertexAttrib3fvNV)(6, v); + (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res); + (*vertexAttrib3fvNV)(6, def); + return compare_floats(__FUNCTION__, 4, v, 4, res); +} + +static GLboolean +test_VertexAttrib3dvNV(generic_func func) +{ + PFNGLVERTEXATTRIB3DVNVPROC vertexAttrib3dvNV = (PFNGLVERTEXATTRIB3DVNVPROC) func; + PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV"); + + const GLdouble v[4] = {2.5, 4.25, 7.125, 1.0}; + const GLdouble def[4] = {0, 0, 0, 1}; + GLdouble res[4]; + (*vertexAttrib3dvNV)(6, v); + (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res); + (*vertexAttrib3dvNV)(6, def); + return compare_doubles(__FUNCTION__, 4, v, 4, res); +} + +static GLboolean +test_VertexAttrib4svNV(generic_func func) +{ + PFNGLVERTEXATTRIB4SVNVPROC vertexAttrib4svNV = (PFNGLVERTEXATTRIB4SVNVPROC) func; + PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV"); + + const GLshort v[4] = {2, 4, 7, 5}; + const GLshort def[4] = {0, 0, 0, 1}; + GLint res[4]; + (*vertexAttrib4svNV)(6, v); + (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res); + (*vertexAttrib4svNV)(6, def); + return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res); +} + +static GLboolean +test_VertexAttrib4fvNV(generic_func func) +{ + PFNGLVERTEXATTRIB4FVNVPROC vertexAttrib4fvNV = (PFNGLVERTEXATTRIB4FVNVPROC) func; + PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV"); + + const GLfloat v[4] = {2.5, 4.25, 7.125, 5.0625}; + const GLfloat def[4] = {0, 0, 0, 1}; + GLfloat res[4]; + (*vertexAttrib4fvNV)(6, v); + (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res); + (*vertexAttrib4fvNV)(6, def); + return compare_floats(__FUNCTION__, 4, v, 4, res); +} static GLboolean test_VertexAttrib4dvNV(generic_func func) { PFNGLVERTEXATTRIB4DVNVPROC vertexAttrib4dvNV = (PFNGLVERTEXATTRIB4DVNVPROC) func; + PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV"); + + const GLdouble v[4] = {2.5, 4.25, 7.125, 5.0625}; + const GLdouble def[4] = {0, 0, 0, 1}; + GLdouble res[4]; + (*vertexAttrib4dvNV)(6, v); + (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res); + (*vertexAttrib4dvNV)(6, def); + return compare_doubles(__FUNCTION__, 4, v, 4, res); +} + +static GLboolean +test_VertexAttrib4ubvNV(generic_func func) +{ + PFNGLVERTEXATTRIB4UBVNVPROC vertexAttrib4ubvNV = (PFNGLVERTEXATTRIB4UBVNVPROC) func; + PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV"); + + const GLubyte v[4] = {255, 0, 255, 0}; + const GLubyte def[4] = {0, 0, 0, 255}; + GLfloat res[4]; + /* There's no byte-value query; so we use the float-value query. + * Bytes are interpreted as steps between 0 and 1, so the + * expected float values will be 0.0 for byte value 0 and 1.0 for + * byte value 255. + */ + GLfloat expectedResults[4] = {1.0, 0.0, 1.0, 0.0}; + (*vertexAttrib4ubvNV)(6, v); + (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res); + (*vertexAttrib4ubvNV)(6, def); + return compare_floats(__FUNCTION__, 4, expectedResults, 4, res); +} + +static GLboolean +test_VertexAttribs1fvNV(generic_func func) +{ + PFNGLVERTEXATTRIBS1FVNVPROC vertexAttribs1fvNV = (PFNGLVERTEXATTRIBS1FVNVPROC) func; PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV"); - const GLdouble v[4] = {0.2, 0.4, 0.8, 1.2}; + const GLfloat v[4] = {2.5, 0.0, 0.0, 1.0}; + const GLfloat def[4] = {0, 0, 0, 1}; + GLfloat res[4]; + (*vertexAttribs1fvNV)(6, 1, v); + (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res); + (*vertexAttribs1fvNV)(6, 1, def); + return compare_floats(__FUNCTION__, 4, v, 4, res); +} + +static GLboolean +test_VertexAttribs1dvNV(generic_func func) +{ + PFNGLVERTEXATTRIBS1DVNVPROC vertexAttribs1dvNV = (PFNGLVERTEXATTRIBS1DVNVPROC) func; + PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV"); + + const GLdouble v[4] = {2.5, 0.0, 0.0, 1.0}; const GLdouble def[4] = {0, 0, 0, 1}; + GLdouble res[4]; + (*vertexAttribs1dvNV)(6, 1, v); + (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res); + (*vertexAttribs1dvNV)(6, 1, def); + return compare_doubles(__FUNCTION__, 4, v, 4, res); +} + +static GLboolean +test_VertexAttribs2svNV(generic_func func) +{ + PFNGLVERTEXATTRIBS2SVNVPROC vertexAttribs2svNV = (PFNGLVERTEXATTRIBS2SVNVPROC) func; + PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV"); + + const GLshort v[4] = {2, 4, 0, 1}; + const GLshort def[4] = {0, 0, 0, 1}; + GLint res[4]; + (*vertexAttribs2svNV)(6, 1, v); + (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res); + (*vertexAttribs2svNV)(6, 1, def); + return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res); +} + +static GLboolean +test_VertexAttribs2fvNV(generic_func func) +{ + PFNGLVERTEXATTRIBS2FVNVPROC vertexAttribs2fvNV = (PFNGLVERTEXATTRIBS2FVNVPROC) func; + PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV"); + + const GLfloat v[4] = {2.5, 4.25, 0.0, 1.0}; + const GLfloat def[4] = {0, 0, 0, 1}; GLfloat res[4]; - GLboolean pass; - (*vertexAttrib4dvNV)(6, v); + (*vertexAttribs2fvNV)(6, 1, v); (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res); - pass = (EQUAL(res[0], 0.2) && EQUAL(res[1], 0.4) && EQUAL(res[2], 0.8) && EQUAL(res[3], 1.2)); - (*vertexAttrib4dvNV)(6, def); - return pass; + (*vertexAttribs2fvNV)(6, 1, def); + return compare_floats(__FUNCTION__, 4, v, 4, res); +} + +static GLboolean +test_VertexAttribs2dvNV(generic_func func) +{ + PFNGLVERTEXATTRIBS2DVNVPROC vertexAttribs2dvNV = (PFNGLVERTEXATTRIBS2DVNVPROC) func; + PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV"); + + const GLdouble v[4] = {2.5, 4.25, 0.0, 1.0}; + const GLdouble def[4] = {0, 0, 0, 1}; + GLdouble res[4]; + (*vertexAttribs2dvNV)(6, 1, v); + (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res); + (*vertexAttribs2dvNV)(6, 1, def); + return compare_doubles(__FUNCTION__, 4, v, 4, res); } +static GLboolean +test_VertexAttribs3svNV(generic_func func) +{ + PFNGLVERTEXATTRIBS3SVNVPROC vertexAttribs3svNV = (PFNGLVERTEXATTRIBS3SVNVPROC) func; + PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV"); + + const GLshort v[4] = {2, 4, 7, 1}; + const GLshort def[4] = {0, 0, 0, 1}; + GLint res[4]; + (*vertexAttribs3svNV)(6, 1, v); + (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res); + (*vertexAttribs3svNV)(6, 1, def); + return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res); +} + +static GLboolean +test_VertexAttribs3fvNV(generic_func func) +{ + PFNGLVERTEXATTRIBS3FVNVPROC vertexAttribs3fvNV = (PFNGLVERTEXATTRIBS3FVNVPROC) func; + PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV"); + + const GLfloat v[4] = {2.5, 4.25, 7.125, 1.0}; + const GLfloat def[4] = {0, 0, 0, 1}; + GLfloat res[4]; + (*vertexAttribs3fvNV)(6, 1, v); + (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res); + (*vertexAttribs3fvNV)(6, 1, def); + return compare_floats(__FUNCTION__, 4, v, 4, res); +} + +static GLboolean +test_VertexAttribs3dvNV(generic_func func) +{ + PFNGLVERTEXATTRIBS3DVNVPROC vertexAttribs3dvNV = (PFNGLVERTEXATTRIBS3DVNVPROC) func; + PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV"); + + const GLdouble v[4] = {2.5, 4.25, 7.125, 1.0}; + const GLdouble def[4] = {0, 0, 0, 1}; + GLdouble res[4]; + (*vertexAttribs3dvNV)(6, 1, v); + (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res); + (*vertexAttribs3dvNV)(6, 1, def); + return compare_doubles(__FUNCTION__, 4, v, 4, res); +} + +static GLboolean +test_VertexAttribs4svNV(generic_func func) +{ + PFNGLVERTEXATTRIBS4SVNVPROC vertexAttribs4svNV = (PFNGLVERTEXATTRIBS4SVNVPROC) func; + PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV"); + + const GLshort v[4] = {2, 4, 7, 5}; + const GLshort def[4] = {0, 0, 0, 1}; + GLint res[4]; + (*vertexAttribs4svNV)(6, 1, v); + (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res); + (*vertexAttribs4svNV)(6, 1, def); + return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res); +} + +static GLboolean +test_VertexAttribs4fvNV(generic_func func) +{ + PFNGLVERTEXATTRIBS4FVNVPROC vertexAttribs4fvNV = (PFNGLVERTEXATTRIBS4FVNVPROC) func; + PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV"); + + const GLfloat v[4] = {2.5, 4.25, 7.125, 5.0625}; + const GLfloat def[4] = {0, 0, 0, 1}; + GLfloat res[4]; + (*vertexAttribs4fvNV)(6, 1, v); + (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res); + (*vertexAttribs4fvNV)(6, 1, def); + return compare_floats(__FUNCTION__, 4, v, 4, res); +} + +static GLboolean +test_VertexAttribs4dvNV(generic_func func) +{ + PFNGLVERTEXATTRIBS4DVNVPROC vertexAttribs4dvNV = (PFNGLVERTEXATTRIBS4DVNVPROC) func; + PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV"); + + const GLdouble v[4] = {2.5, 4.25, 7.125, 5.0625}; + const GLdouble def[4] = {0, 0, 0, 1}; + GLdouble res[4]; + (*vertexAttribs4dvNV)(6, 1, v); + (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res); + (*vertexAttribs4dvNV)(6, 1, def); + return compare_doubles(__FUNCTION__, 4, v, 4, res); +} + +static GLboolean +test_VertexAttribs4ubvNV(generic_func func) +{ + PFNGLVERTEXATTRIBS4UBVNVPROC vertexAttribs4ubvNV = (PFNGLVERTEXATTRIBS4UBVNVPROC) func; + PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV"); + + const GLubyte v[4] = {255, 0, 255, 0}; + const GLubyte def[4] = {0, 0, 0, 255}; + GLfloat res[4]; + /* There's no byte-value query; so we use the float-value query. + * Bytes are interpreted as steps between 0 and 1, so the + * expected float values will be 0.0 for byte value 0 and 1.0 for + * byte value 255. + */ + GLfloat expectedResults[4] = {1.0, 0.0, 1.0, 0.0}; + (*vertexAttribs4ubvNV)(6, 1, v); + (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res); + (*vertexAttribs4ubvNV)(6, 1, def); + return compare_floats(__FUNCTION__, 4, expectedResults, 4, res); +} static GLboolean test_StencilFuncSeparateATI(generic_func func) @@ -387,17 +3507,32 @@ extension_supported(const char *haystack, const char *needle) } -static void +/* Run all the known extension function tests, if the extension is supported. + * Return a count of how many failed. + */ +static int check_functions( const char *extensions ) { struct name_test_pair *entry; - int failures = 0, passes = 0; - int totalFail = 0, totalPass = 0; + int failures = 0, passes = 0, untested = 0; + int totalFail = 0, totalPass = 0, totalUntested = 0, totalUnsupported = 0; int doTests; - + const char *version = (const char *) glGetString(GL_VERSION); + + /* The functions list will have "real" entries (consisting of + * a GL function name and a pointer to an exercise function for + * that GL function), and "group" entries (indicated as + * such by having a "-" as the first character of the name). + * "Group" names always start with the "-" character, and can + * be numeric (e.g. "-1.0", "-2.1"), indicating that a particular + * OpenGL version is required for the following functions; or can be + * an extension name (e.g. "-GL_ARB_multitexture") that means + * that the named extension is required for the following functions. + */ for (entry = functions; entry->name; entry++) { + /* Check if this is a group indicator */ if (entry->name[0] == '-') { - const char *version = (const char *) glGetString(GL_VERSION); + /* A group indicator; check if it's an OpenGL version group */ if (entry->name[1] == '1') { /* check GL version 1.x */ if (version[0] == '1' && @@ -419,14 +3554,27 @@ check_functions( const char *extensions ) /* check if the named extension is available */ doTests = extension_supported(extensions, entry->name+1); } + + /* doTests is now set if we're starting an OpenGL version + * group, and the running OpenGL version is at least the + * version required; or if we're starting an OpenGL extension + * group, and the extension is supported. + */ if (doTests) printf("Testing %s functions\n", entry->name + 1); - totalFail += failures; - totalPass += passes; + + /* Each time we hit a title function, reset the function + * counts. + */ failures = 0; passes = 0; + untested = 0; } else if (doTests) { + /* Here, we know we're trying to exercise a function for + * a supported extension. See whether we have a test for + * it, and try to run it. + */ generic_func funcPtr = (generic_func) glXGetProcAddressARB((const GLubyte *) entry->name); if (funcPtr) { if (entry->test) { @@ -436,21 +3584,36 @@ check_functions( const char *extensions ) if (b) { printf(" Pass\n"); passes++; + totalPass++; } else { printf(" FAIL!!!\n"); failures++; + totalFail++; } } else { - passes++; + untested++; + totalUntested++; } } else { printf(" glXGetProcAddress(%s) failed!\n", entry->name); failures++; + totalFail++; } } + else { + /* Here, we have a function that belongs to a group that + * is known to be unsupported. + */ + totalUnsupported++; + } + + /* Make sure a poor test case doesn't leave any lingering + * OpenGL errors. + */ + CheckGLError(__LINE__, __FILE__, __FUNCTION__); if (doTests && (!(entry+1)->name || (entry+1)->name[0] == '-')) { if (failures > 0) { @@ -459,18 +3622,29 @@ check_functions( const char *extensions ) if (passes > 0) { printf(" %d passed.\n", passes); } + if (untested > 0) { + printf(" %d untested.\n", untested); + } } } - totalFail += failures; - totalPass += passes; printf("-----------------------------\n"); - printf("Total: %d pass %d fail\n", totalPass, totalFail); + printf("Total: %d pass %d fail %d untested %d unsupported %d total\n", + totalPass, totalFail, totalUntested, totalUnsupported, + totalPass + totalFail + totalUntested + totalUnsupported); + + return totalFail; } +/* Return an error code */ +#define ERROR_NONE 0 +#define ERROR_NO_VISUAL 1 +#define ERROR_NO_CONTEXT 2 +#define ERROR_NO_MAKECURRENT 3 +#define ERROR_FAILED 4 -static void +static int print_screen_info(Display *dpy, int scrnum, Bool allowDirect) { Window win; @@ -496,6 +3670,7 @@ print_screen_info(Display *dpy, int scrnum, Bool allowDirect) GLXContext ctx; XVisualInfo *visinfo; int width = 100, height = 100; + int failures; root = RootWindow(dpy, scrnum); @@ -504,7 +3679,7 @@ print_screen_info(Display *dpy, int scrnum, Bool allowDirect) visinfo = glXChooseVisual(dpy, scrnum, attribDouble); if (!visinfo) { fprintf(stderr, "Error: couldn't find RGB GLX visual\n"); - return; + return ERROR_NO_VISUAL; } } @@ -521,26 +3696,29 @@ print_screen_info(Display *dpy, int scrnum, Bool allowDirect) if (!ctx) { fprintf(stderr, "Error: glXCreateContext failed\n"); XDestroyWindow(dpy, win); - return; + return ERROR_NO_CONTEXT; } - if (glXMakeCurrent(dpy, win, ctx)) { - check_functions( (const char *) glGetString(GL_EXTENSIONS) ); - } - else { + if (!glXMakeCurrent(dpy, win, ctx)) { fprintf(stderr, "Error: glXMakeCurrent failed\n"); + glXDestroyContext(dpy, ctx); + XDestroyWindow(dpy, win); + return ERROR_NO_MAKECURRENT; } + failures = check_functions( (const char *) glGetString(GL_EXTENSIONS) ); glXDestroyContext(dpy, ctx); XDestroyWindow(dpy, win); -} + return (failures == 0 ? ERROR_NONE : ERROR_FAILED); +} int main(int argc, char *argv[]) { char *displayName = NULL; Display *dpy; + int returnCode; dpy = XOpenDisplay(displayName); if (!dpy) { @@ -548,9 +3726,9 @@ main(int argc, char *argv[]) return -1; } - print_screen_info(dpy, 0, GL_TRUE); + returnCode = print_screen_info(dpy, 0, GL_TRUE); XCloseDisplay(dpy); - return 0; + return returnCode; } diff --git a/progs/tests/getprocaddress.py b/progs/tests/getprocaddress.py index 8adfc51bd6..699195bd48 100644 --- a/progs/tests/getprocaddress.py +++ b/progs/tests/getprocaddress.py @@ -52,7 +52,7 @@ static struct name_test_pair functions[] = {""" prev_category = None - for f in api.functionIterateByOffset(): + for f in api.functionIterateByCategory(): [category, num] = api.get_category_for_name( f.name ) if category != prev_category: print ' { "-%s", NULL},' % category diff --git a/progs/tests/getteximage.c b/progs/tests/getteximage.c index efd77db60e..71f29b4ac8 100644 --- a/progs/tests/getteximage.c +++ b/progs/tests/getteximage.c @@ -15,7 +15,7 @@ static int Win; static void -TestGetTexImage(void) +TestGetTexImage(GLboolean npot) { GLuint iter; GLubyte *data = (GLubyte *) malloc(1024 * 1024 * 4); @@ -27,8 +27,8 @@ TestGetTexImage(void) for (iter = 0; iter < 8; iter++) { GLint p = (iter % 8) + 3; - GLint w = (1 << p); - GLint h = (1 << p); + GLint w = npot ? (p * 20) : (1 << p); + GLint h = npot ? (p * 10) : (1 << p); GLuint i; GLint level = 0; @@ -83,63 +83,94 @@ ColorsEqual(const GLubyte ref[4], const GLubyte act[4]) static void -TestGetTexImageRTT(void) +TestGetTexImageRTT(GLboolean npot) { GLuint iter; - GLuint fb, tex; - GLint w = 512; - GLint h = 256; - GLint level = 0; - - glGenTextures(1, &tex); - glGenFramebuffersEXT(1, &fb); - - glBindTexture(GL_TEXTURE_2D, tex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, - GL_RGBA, GL_UNSIGNED_BYTE, NULL); - - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, - GL_TEXTURE_2D, tex, level); printf("Render to texture + glGetTexImage:\n"); - printf(" Testing %d x %d tex image\n", w, h); + for (iter = 0; iter < 8; iter++) { - GLubyte color[4]; - GLubyte *data2 = (GLubyte *) malloc(w * h * 4); - GLuint i; - /* random clear color */ - for (i = 0; i < 4; i++) { - color[i] = rand() % 256; + GLuint fb, tex; + GLint w, h; + GLint level = 0; + + if (npot) { + w = 200 + iter * 40; + h = 200 + iter * 12; + } + else { + w = 4 << iter; + h = 4 << iter; } - glClearColor(color[0] / 255.0, - color[1] / 255.0, - color[2] / 255.0, - color[3] / 255.0); + glGenTextures(1, &tex); + glGenFramebuffersEXT(1, &fb); - glClear(GL_COLOR_BUFFER_BIT); + glBindTexture(GL_TEXTURE_2D, tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, + GL_RGBA, GL_UNSIGNED_BYTE, NULL); - /* get */ - glGetTexImage(GL_TEXTURE_2D, level, GL_RGBA, GL_UNSIGNED_BYTE, data2); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, + GL_TEXTURE_2D, tex, level); - /* compare */ - for (i = 0; i < w * h; i += 4) { - if (!ColorsEqual(color, data2 + i * 4)) { - printf("Render to texture failure!\n"); - abort(); + glViewport(0, 0, w, h); + + printf(" Testing %d x %d tex image\n", w, h); + { + static const GLubyte blue[4] = {0, 0, 255, 255}; + GLubyte color[4]; + GLubyte *data2 = (GLubyte *) malloc(w * h * 4); + GLuint i; + + /* random clear color */ + for (i = 0; i < 4; i++) { + color[i] = rand() % 256; + } + + glClearColor(color[0] / 255.0, + color[1] / 255.0, + color[2] / 255.0, + color[3] / 255.0); + + glClear(GL_COLOR_BUFFER_BIT); + + /* draw polygon over top half, in blue */ + glColor4ubv(blue); + glRectf(0, 0.5, 1.0, 1.0); + + /* get */ + glGetTexImage(GL_TEXTURE_2D, level, GL_RGBA, GL_UNSIGNED_BYTE, data2); + + /* compare */ + for (i = 0; i < w * h; i += 4) { + if (i < w * h / 2) { + /* lower half */ + if (!ColorsEqual(color, data2 + i * 4)) { + printf("Render to texture failure (expected clear color)!\n"); + abort(); + } + } + else { + /* upper half */ + if (!ColorsEqual(blue, data2 + i * 4)) { + printf("Render to texture failure (expected blue)!\n"); + abort(); + } + } } + + free(data2); } - free(data2); - } + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glDeleteFramebuffersEXT(1, &fb); + glDeleteTextures(1, &tex); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - glDeleteFramebuffersEXT(1, &fb); - glDeleteTextures(1, &tex); + } printf("Passed\n"); } @@ -152,11 +183,16 @@ Draw(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - TestGetTexImage(); + TestGetTexImage(GL_FALSE); + if (glutExtensionSupported("GL_ARB_texture_non_power_of_two")) + TestGetTexImage(GL_TRUE); if (glutExtensionSupported("GL_EXT_framebuffer_object") || - glutExtensionSupported("GL_ARB_framebuffer_object")) - TestGetTexImageRTT(); + glutExtensionSupported("GL_ARB_framebuffer_object")) { + TestGetTexImageRTT(GL_FALSE); + if (glutExtensionSupported("GL_ARB_texture_non_power_of_two")) + TestGetTexImageRTT(GL_TRUE); + } glutDestroyWindow(Win); exit(0); @@ -171,10 +207,10 @@ Reshape(int width, int height) glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); - glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0); + glOrtho(0, 1, 0, 1, -1, 1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - glTranslatef(0.0, 0.0, -15.0); + glTranslatef(0.0, 0.0, 0.0); } diff --git a/progs/tests/texcompsub.c b/progs/tests/texcompsub.c index 79a5f958a1..50106bf1e2 100644 --- a/progs/tests/texcompsub.c +++ b/progs/tests/texcompsub.c @@ -6,6 +6,7 @@ #include <assert.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <GL/glew.h> #include <GL/glut.h> @@ -31,6 +32,8 @@ CheckError(int line) static void LoadCompressedImage(void) { + unsigned char ImgDataTemp[ImgSize / 4]; + unsigned i; const GLenum filter = GL_LINEAR; glTexImage2D(Target, 0, CompFormat, ImgWidth, ImgHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); @@ -40,11 +43,24 @@ LoadCompressedImage(void) 0, 0, /* pos */ ImgWidth, ImgHeight / 2, CompFormat, ImgSize / 2, ImgData + ImgSize / 2); - /* top half */ + + /* top left */ + for (i = 0; i < ImgHeight / 8; i++) { + memcpy(&ImgDataTemp[i * ImgWidth], &ImgData[i * 2 * ImgWidth], ImgWidth); + } glCompressedTexSubImage2DARB(Target, 0, 0, ImgHeight / 2, /* pos */ - ImgWidth, ImgHeight / 2, - CompFormat, ImgSize / 2, ImgData); + ImgWidth / 2, ImgHeight / 2, + CompFormat, ImgSize / 4, ImgDataTemp); + + /* top right */ + for (i = 0; i < ImgHeight / 8; i++) { + memcpy(&ImgDataTemp[i * ImgWidth], &ImgData[i * 2 * ImgWidth + ImgWidth], ImgWidth); + } + glCompressedTexSubImage2DARB(Target, 0, + ImgWidth / 2, ImgHeight / 2, /* pos */ + ImgWidth / 2, ImgHeight / 2, + CompFormat, ImgSize / 4, ImgDataTemp); glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, filter); glTexParameteri(Target, GL_TEXTURE_MAG_FILTER, filter); diff --git a/progs/tests/texwrap.c b/progs/tests/texwrap.c index 12f045b72e..92c8a2f14c 100644 --- a/progs/tests/texwrap.c +++ b/progs/tests/texwrap.c @@ -258,8 +258,26 @@ static void Init( void ) } glBindTexture(GL_TEXTURE_2D, BORDER_TEXTURE); +#ifdef TEST_PBO_DLIST + /* test fetching teximage from PBO in display list */ + { + GLuint b = 42, l = 10; + + glBindBufferARB(GL_PIXEL_UNPACK_BUFFER, b); + glBufferDataARB(GL_PIXEL_UNPACK_BUFFER, sizeof(BorderImage), + BorderImage, GL_STREAM_DRAW); + + glNewList(l, GL_COMPILE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SIZE+2, SIZE+2, 1, + GL_RGBA, GL_UNSIGNED_BYTE, (void *) 0/* BorderImage*/); + glEndList(); + glCallList(l); + glBindBufferARB(GL_PIXEL_UNPACK_BUFFER, 0); + } +#else glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SIZE+2, SIZE+2, 1, GL_RGBA, GL_UNSIGNED_BYTE, (void *) BorderImage); +#endif for (i = 0; i < SIZE; i++) { for (j = 0; j < SIZE; j++) { diff --git a/progs/util/shaderutil.c b/progs/util/shaderutil.c index 13b68d90e0..489e71cc30 100644 --- a/progs/util/shaderutil.c +++ b/progs/util/shaderutil.c @@ -9,21 +9,12 @@ #include <assert.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <GL/glew.h> #include <GL/glut.h> #include "shaderutil.h" -static void -Init(void) -{ - static GLboolean firstCall = GL_TRUE; - if (firstCall) { - firstCall = GL_FALSE; - } -} - - GLboolean ShadersSupported(void) { @@ -47,8 +38,6 @@ CompileShaderText(GLenum shaderType, const char *text) GLuint shader; GLint stat; - Init(); - shader = glCreateShader(shaderType); glShaderSource(shader, 1, (const GLchar **) &text, NULL); glCompileShader(shader); @@ -79,9 +68,6 @@ CompileShaderFile(GLenum shaderType, const char *filename) GLuint shader; FILE *f; - Init(); - - f = fopen(filename, "r"); if (!f) { fprintf(stderr, "Unable to open shader file %s\n", filename); @@ -136,7 +122,7 @@ LinkShaders(GLuint vertShader, GLuint fragShader) void -InitUniforms(GLuint program, struct uniform_info uniforms[]) +SetUniformValues(GLuint program, struct uniform_info uniforms[]) { GLuint i; @@ -144,28 +130,133 @@ InitUniforms(GLuint program, struct uniform_info uniforms[]) uniforms[i].location = glGetUniformLocation(program, uniforms[i].name); - printf("Uniform %s location: %d\n", uniforms[i].name, - uniforms[i].location); - - switch (uniforms[i].size) { - case 1: - if (uniforms[i].type == GL_INT) - glUniform1i(uniforms[i].location, - (GLint) uniforms[i].value[0]); - else - glUniform1fv(uniforms[i].location, 1, uniforms[i].value); + switch (uniforms[i].type) { + case GL_INT: + case GL_SAMPLER_1D: + case GL_SAMPLER_2D: + case GL_SAMPLER_3D: + case GL_SAMPLER_CUBE: + case GL_SAMPLER_2D_RECT_ARB: + glUniform1i(uniforms[i].location, + (GLint) uniforms[i].value[0]); + break; + case GL_FLOAT: + glUniform1fv(uniforms[i].location, 1, uniforms[i].value); break; - case 2: + case GL_FLOAT_VEC2: glUniform2fv(uniforms[i].location, 1, uniforms[i].value); break; - case 3: + case GL_FLOAT_VEC3: glUniform3fv(uniforms[i].location, 1, uniforms[i].value); break; - case 4: + case GL_FLOAT_VEC4: glUniform4fv(uniforms[i].location, 1, uniforms[i].value); break; default: - abort(); + if (strncmp(uniforms[i].name, "gl_", 3) == 0) { + /* built-in uniform: ignore */ + } + else { + fprintf(stderr, + "Unexpected uniform data type in SetUniformValues\n"); + abort(); + } } } } + + +/** Get list of uniforms used in the program */ +GLuint +GetUniforms(GLuint program, struct uniform_info uniforms[]) +{ + GLint n, max, i; + + glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &n); + glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max); + + for (i = 0; i < n; i++) { + GLint size, len; + GLenum type; + char name[100]; + + glGetActiveUniform(program, i, 100, &len, &size, &type, name); + + uniforms[i].name = strdup(name); + uniforms[i].size = size; + uniforms[i].type = type; + uniforms[i].location = glGetUniformLocation(program, name); + } + + uniforms[i].name = NULL; /* end of list */ + + return n; +} + + +void +PrintUniforms(const struct uniform_info uniforms[]) +{ + GLint i; + + printf("Uniforms:\n"); + + for (i = 0; uniforms[i].name; i++) { + printf(" %d: %s size=%d type=0x%x loc=%d value=%g, %g, %g, %g\n", + i, + uniforms[i].name, + uniforms[i].size, + uniforms[i].type, + uniforms[i].location, + uniforms[i].value[0], + uniforms[i].value[1], + uniforms[i].value[2], + uniforms[i].value[3]); + } +} + + +/** Get list of attribs used in the program */ +GLuint +GetAttribs(GLuint program, struct attrib_info attribs[]) +{ + GLint n, max, i; + + glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &n); + glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max); + + for (i = 0; i < n; i++) { + GLint size, len; + GLenum type; + char name[100]; + + glGetActiveAttrib(program, i, 100, &len, &size, &type, name); + + attribs[i].name = strdup(name); + attribs[i].size = size; + attribs[i].type = type; + attribs[i].location = glGetAttribLocation(program, name); + } + + attribs[i].name = NULL; /* end of list */ + + return n; +} + + +void +PrintAttribs(const struct attrib_info attribs[]) +{ + GLint i; + + printf("Attribs:\n"); + + for (i = 0; attribs[i].name; i++) { + printf(" %d: %s size=%d type=0x%x loc=%d\n", + i, + attribs[i].name, + attribs[i].size, + attribs[i].type, + attribs[i].location); + } +} diff --git a/progs/util/shaderutil.h b/progs/util/shaderutil.h index cfb8c1f3b0..0a6be02675 100644 --- a/progs/util/shaderutil.h +++ b/progs/util/shaderutil.h @@ -6,8 +6,8 @@ struct uniform_info { const char *name; - GLuint size; - GLenum type; /**< GL_FLOAT or GL_INT */ + GLuint size; /**< number of value[] elements: 1, 2, 3 or 4 */ + GLenum type; /**< GL_FLOAT, GL_FLOAT_VEC4, GL_INT, etc */ GLfloat value[4]; GLint location; /**< filled in by InitUniforms() */ }; @@ -15,6 +15,15 @@ struct uniform_info #define END_OF_UNIFORMS { NULL, 0, GL_NONE, { 0, 0, 0, 0 }, -1 } +struct attrib_info +{ + const char *name; + GLuint size; /**< number of value[] elements: 1, 2, 3 or 4 */ + GLenum type; /**< GL_FLOAT, GL_FLOAT_VEC4, GL_INT, etc */ + GLint location; +}; + + extern GLboolean ShadersSupported(void); @@ -28,7 +37,18 @@ extern GLuint LinkShaders(GLuint vertShader, GLuint fragShader); extern void -InitUniforms(GLuint program, struct uniform_info uniforms[]); +SetUniformValues(GLuint program, struct uniform_info uniforms[]); + +extern GLuint +GetUniforms(GLuint program, struct uniform_info uniforms[]); + +extern void +PrintUniforms(const struct uniform_info uniforms[]); +extern GLuint +GetAttribs(GLuint program, struct attrib_info attribs[]); + +extern void +PrintAttribs(const struct attrib_info attribs[]); #endif /* SHADER_UTIL_H */ diff --git a/progs/xdemos/Makefile b/progs/xdemos/Makefile index 6581df8039..53e1c54ef3 100644 --- a/progs/xdemos/Makefile +++ b/progs/xdemos/Makefile @@ -26,6 +26,7 @@ PROGS = \ glxsnoop \ glxswapcontrol \ manywin \ + multictx \ offset \ overlay \ pbinfo \ diff --git a/progs/xdemos/glxcontexts.c b/progs/xdemos/glxcontexts.c index 481749be3d..9f83679acd 100644 --- a/progs/xdemos/glxcontexts.c +++ b/progs/xdemos/glxcontexts.c @@ -378,6 +378,9 @@ make_window( Display *dpy, const char *name, scrnum = DefaultScreen( dpy ); root = RootWindow( dpy, scrnum ); + if (visinfo) + XFree(visinfo); + visinfo = glXChooseVisual( dpy, scrnum, attribs ); if (!visinfo) { printf("Error: couldn't get an RGB, Double-buffered visual\n"); diff --git a/progs/xdemos/glxgears.c b/progs/xdemos/glxgears.c index bc84ee3dbd..088f25a357 100644 --- a/progs/xdemos/glxgears.c +++ b/progs/xdemos/glxgears.c @@ -23,10 +23,7 @@ * This is a port of the infamous "gears" demo to straight GLX (i.e. no GLUT) * Port by Brian Paul 23 March 2001 * - * Command line options: - * -info print GL implementation information - * -stereo use stereo enabled GLX visual - * + * See usage() below for command line options. */ @@ -45,10 +42,6 @@ typedef int (*PFNGLXGETSWAPINTERVALMESAPROC)(void); #endif -static int is_glx_extension_supported(Display *dpy, const char *query); - -static void query_vsync(Display *dpy); - #define BENCHMARK #ifdef BENCHMARK @@ -572,7 +565,7 @@ make_window( Display *dpy, const char *name, /** * Determine whether or not a GLX extension is supported. */ -int +static int is_glx_extension_supported(Display *dpy, const char *query) { const int scrnum = DefaultScreen(dpy); @@ -592,7 +585,7 @@ is_glx_extension_supported(Display *dpy, const char *query) /** * Attempt to determine whether or not the display is synched to vblank. */ -void +static void query_vsync(Display *dpy) { int interval = 0; diff --git a/progs/xdemos/glxswapcontrol.c b/progs/xdemos/glxswapcontrol.c index df9f7ad784..cd60d460a0 100644 --- a/progs/xdemos/glxswapcontrol.c +++ b/progs/xdemos/glxswapcontrol.c @@ -587,6 +587,9 @@ event_loop(Display *dpy, Window win) angle += 2.0; draw(); + + glXSwapBuffers(dpy, win); + if ( get_frame_usage != NULL ) { GLfloat temp; @@ -594,8 +597,6 @@ event_loop(Display *dpy, Window win) frame_usage += temp; } - glXSwapBuffers(dpy, win); - /* calc framerate */ { static int t0 = -1; diff --git a/progs/xdemos/multictx.c b/progs/xdemos/multictx.c new file mode 100644 index 0000000000..75255b2860 --- /dev/null +++ b/progs/xdemos/multictx.c @@ -0,0 +1,585 @@ +/* + * Copyright (C) 2009 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, 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 + * BRIAN PAUL 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. + */ + +/* + * Test rendering with two contexts into one window. + * Setup different rendering state for each context to check that + * context switching is handled properly. + * + * Brian Paul + * 6 Aug 2009 + */ + + +#include <math.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <sys/time.h> +#include <unistd.h> +#include <X11/Xlib.h> +#include <X11/keysym.h> +#include <GL/gl.h> +#include <GL/glx.h> + + + +#ifndef M_PI +#define M_PI 3.14159265 +#endif + + +/** Event handler results: */ +#define NOP 0 +#define EXIT 1 +#define DRAW 2 + +static GLfloat view_rotx = 0.0, view_roty = 210.0, view_rotz = 0.0; +static GLint gear1, gear2; +static GLfloat angle = 0.0; + +static GLboolean animate = GL_TRUE; /* Animation */ + + +static double +current_time(void) +{ + struct timeval tv; +#ifdef __VMS + (void) gettimeofday(&tv, NULL ); +#else + struct timezone tz; + (void) gettimeofday(&tv, &tz); +#endif + return (double) tv.tv_sec + tv.tv_usec / 1000000.0; +} + + +/* + * + * Draw a gear wheel. You'll probably want to call this function when + * building a display list since we do a lot of trig here. + * + * Input: inner_radius - radius of hole at center + * outer_radius - radius at center of teeth + * width - width of gear + * teeth - number of teeth + * tooth_depth - depth of tooth + */ +static void +gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width, + GLint teeth, GLfloat tooth_depth) +{ + GLint i; + GLfloat r0, r1, r2; + GLfloat angle, da; + GLfloat u, v, len; + + r0 = inner_radius; + r1 = outer_radius - tooth_depth / 2.0; + r2 = outer_radius + tooth_depth / 2.0; + + da = 2.0 * M_PI / teeth / 4.0; + + glShadeModel(GL_FLAT); + + glNormal3f(0.0, 0.0, 1.0); + + /* draw front face */ + glBegin(GL_QUAD_STRIP); + for (i = 0; i <= teeth; i++) { + angle = i * 2.0 * M_PI / teeth; + glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); + glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); + if (i < teeth) { + glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), + width * 0.5); + } + } + glEnd(); + + /* draw front sides of teeth */ + glBegin(GL_QUADS); + da = 2.0 * M_PI / teeth / 4.0; + for (i = 0; i < teeth; i++) { + angle = i * 2.0 * M_PI / teeth; + + glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); + glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); + glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), + width * 0.5); + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), + width * 0.5); + } + glEnd(); + + glNormal3f(0.0, 0.0, -1.0); + + /* draw back face */ + glBegin(GL_QUAD_STRIP); + for (i = 0; i <= teeth; i++) { + angle = i * 2.0 * M_PI / teeth; + glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); + glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); + if (i < teeth) { + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), + -width * 0.5); + glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); + } + } + glEnd(); + + /* draw back sides of teeth */ + glBegin(GL_QUADS); + da = 2.0 * M_PI / teeth / 4.0; + for (i = 0; i < teeth; i++) { + angle = i * 2.0 * M_PI / teeth; + + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), + -width * 0.5); + glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), + -width * 0.5); + glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); + glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); + } + glEnd(); + + /* draw outward faces of teeth */ + glBegin(GL_QUAD_STRIP); + for (i = 0; i < teeth; i++) { + angle = i * 2.0 * M_PI / teeth; + + glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); + glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); + u = r2 * cos(angle + da) - r1 * cos(angle); + v = r2 * sin(angle + da) - r1 * sin(angle); + len = sqrt(u * u + v * v); + u /= len; + v /= len; + glNormal3f(v, -u, 0.0); + glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); + glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); + glNormal3f(cos(angle), sin(angle), 0.0); + glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), + width * 0.5); + glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), + -width * 0.5); + u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da); + v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da); + glNormal3f(v, -u, 0.0); + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), + width * 0.5); + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), + -width * 0.5); + glNormal3f(cos(angle), sin(angle), 0.0); + } + + glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5); + glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5); + + glEnd(); + + glShadeModel(GL_SMOOTH); + + /* draw inside radius cylinder */ + glBegin(GL_QUAD_STRIP); + for (i = 0; i <= teeth; i++) { + angle = i * 2.0 * M_PI / teeth; + glNormal3f(-cos(angle), -sin(angle), 0.0); + glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); + glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); + } + glEnd(); +} + + +static void +draw(int ctx) +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix(); + glRotatef(view_rotx, 1.0, 0.0, 0.0); + glRotatef(view_roty + angle, 0.0, 1.0, 0.0); + glRotatef(view_rotz, 0.0, 0.0, 1.0); + + if (ctx == 0) { + glDisable(GL_CULL_FACE); + glPushMatrix(); + glRotatef(angle, 0.0, 0.0, 1.0); + glCallList(gear1); + glPopMatrix(); + /* This should not effect the other context's rendering */ + glEnable(GL_CULL_FACE); + glCullFace(GL_FRONT_AND_BACK); + } + else { + glPushMatrix(); + glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0); + glCallList(gear2); + glPopMatrix(); + } + + glPopMatrix(); + + /* this flush is important since we'll be switching contexts next */ + glFlush(); +} + + + +static void +draw_frame(Display *dpy, Window win, GLXContext ctx1, GLXContext ctx2) +{ + static double tRot0 = -1.0; + double dt, t = current_time(); + + if (tRot0 < 0.0) + tRot0 = t; + dt = t - tRot0; + tRot0 = t; + + if (animate) { + /* advance rotation for next frame */ + angle += 70.0 * dt; /* 70 degrees per second */ + if (angle > 3600.0) + angle -= 3600.0; + } + + glXMakeCurrent(dpy, (GLXDrawable) win, ctx1); + draw(0); + + glXMakeCurrent(dpy, (GLXDrawable) win, ctx2); + draw(1); + + glXSwapBuffers(dpy, win); +} + + +/* new window size or exposure */ +static void +reshape(Display *dpy, Window win, + GLXContext ctx1, GLXContext ctx2, int width, int height) +{ + int i; + + width /= 2; + + /* loop: left half of window, right half of window */ + for (i = 0; i < 2; i++) { + if (i == 0) + glXMakeCurrent(dpy, win, ctx1); + else + glXMakeCurrent(dpy, win, ctx2); + + glViewport(width * i, 0, width, height); + glScissor(width * i, 0, width, height); + + { + GLfloat h = (GLfloat) height / (GLfloat) width; + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0); + } + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0.0, 0.0, -30.0); + } +} + + + +static void +init(Display *dpy, Window win, GLXContext ctx1, GLXContext ctx2) +{ + static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 }; + static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 }; + static GLfloat green[4] = { 0.0, 0.8, 0.2, 0.5 }; + /*static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 };*/ + + /* first ctx */ + { + static GLuint stipple[32] = { + 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, + 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, + + 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, + 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, + + 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, + 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, + + 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, + 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00 + }; + + glXMakeCurrent(dpy, win, ctx1); + + glLightfv(GL_LIGHT0, GL_POSITION, pos); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_DEPTH_TEST); + + gear1 = glGenLists(1); + glNewList(gear1, GL_COMPILE); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red); + gear(1.0, 4.0, 1.0, 20, 0.7); + glEndList(); + + glEnable(GL_NORMALIZE); + glEnable(GL_SCISSOR_TEST); + glClearColor(0.4, 0.4, 0.4, 1.0); + + glPolygonStipple((GLubyte *) stipple); + glEnable(GL_POLYGON_STIPPLE); + } + + /* second ctx */ + { + glXMakeCurrent(dpy, win, ctx2); + + glLightfv(GL_LIGHT0, GL_POSITION, pos); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_DEPTH_TEST); + + gear2 = glGenLists(1); + glNewList(gear2, GL_COMPILE); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green); + gear(1.5, 3.0, 1.5, 16, 0.7); + glEndList(); + + glEnable(GL_NORMALIZE); + glEnable(GL_SCISSOR_TEST); + glClearColor(0.6, 0.6, 0.6, 1.0); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } +} + + +/** + * Create an RGB, double-buffered window. + * Return the window and two context handles. + */ +static void +make_window_and_contexts( Display *dpy, const char *name, + int x, int y, int width, int height, + Window *winRet, + GLXContext *ctxRet1, + GLXContext *ctxRet2) +{ + int attribs[] = { GLX_RGBA, + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + GLX_DOUBLEBUFFER, + GLX_DEPTH_SIZE, 1, + None }; + int scrnum; + XSetWindowAttributes attr; + unsigned long mask; + Window root; + Window win; + XVisualInfo *visinfo; + + scrnum = DefaultScreen( dpy ); + root = RootWindow( dpy, scrnum ); + + visinfo = glXChooseVisual( dpy, scrnum, attribs ); + if (!visinfo) { + printf("Error: couldn't get an RGB, Double-buffered visual\n"); + exit(1); + } + + /* window attributes */ + attr.background_pixel = 0; + attr.border_pixel = 0; + attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone); + attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; + mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; + + win = XCreateWindow( dpy, root, x, y, width, height, + 0, visinfo->depth, InputOutput, + visinfo->visual, mask, &attr ); + + /* set hints and properties */ + { + XSizeHints sizehints; + sizehints.x = x; + sizehints.y = y; + sizehints.width = width; + sizehints.height = height; + sizehints.flags = USSize | USPosition; + XSetNormalHints(dpy, win, &sizehints); + XSetStandardProperties(dpy, win, name, name, + None, (char **)NULL, 0, &sizehints); + } + + *winRet = win; + *ctxRet1 = glXCreateContext( dpy, visinfo, NULL, True ); + *ctxRet2 = glXCreateContext( dpy, visinfo, NULL, True ); + + if (!*ctxRet1 || !*ctxRet2) { + printf("Error: glXCreateContext failed\n"); + exit(1); + } + + XFree(visinfo); +} + + +/** + * Handle one X event. + * \return NOP, EXIT or DRAW + */ +static int +handle_event(Display *dpy, Window win, GLXContext ctx1, GLXContext ctx2, + XEvent *event) +{ + (void) dpy; + (void) win; + + switch (event->type) { + case Expose: + return DRAW; + case ConfigureNotify: + reshape(dpy, win, ctx1, ctx2, + event->xconfigure.width, event->xconfigure.height); + break; + case KeyPress: + { + char buffer[10]; + int r, code; + code = XLookupKeysym(&event->xkey, 0); + if (code == XK_Left) { + view_roty += 5.0; + } + else if (code == XK_Right) { + view_roty -= 5.0; + } + else if (code == XK_Up) { + view_rotx += 5.0; + } + else if (code == XK_Down) { + view_rotx -= 5.0; + } + else { + r = XLookupString(&event->xkey, buffer, sizeof(buffer), + NULL, NULL); + if (buffer[0] == 27) { + /* escape */ + return EXIT; + } + else if (buffer[0] == 'a' || buffer[0] == 'A') { + animate = !animate; + } + } + return DRAW; + } + } + return NOP; +} + + +static void +event_loop(Display *dpy, Window win, GLXContext ctx1, GLXContext ctx2) +{ + while (1) { + int op; + while (!animate || XPending(dpy) > 0) { + XEvent event; + XNextEvent(dpy, &event); + op = handle_event(dpy, win, ctx1, ctx2, &event); + if (op == EXIT) + return; + else if (op == DRAW) + break; + } + + draw_frame(dpy, win, ctx1, ctx2); + } +} + + +int +main(int argc, char *argv[]) +{ + unsigned int winWidth = 800, winHeight = 400; + int x = 0, y = 0; + Display *dpy; + Window win; + GLXContext ctx1, ctx2; + char *dpyName = NULL; + GLboolean printInfo = GL_FALSE; + int i; + + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-display") == 0) { + dpyName = argv[i+1]; + i++; + } + else { + return 1; + } + } + + dpy = XOpenDisplay(dpyName); + if (!dpy) { + printf("Error: couldn't open display %s\n", + dpyName ? dpyName : getenv("DISPLAY")); + return -1; + } + + make_window_and_contexts(dpy, "multictx", x, y, winWidth, winHeight, + &win, &ctx1, &ctx2); + XMapWindow(dpy, win); + + if (printInfo) { + printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); + printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION)); + printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR)); + printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS)); + } + + init(dpy, win, ctx1, ctx2); + + /* Set initial projection/viewing transformation. + * We can't be sure we'll get a ConfigureNotify event when the window + * first appears. + */ + reshape(dpy, win, ctx1, ctx2, winWidth, winHeight); + + event_loop(dpy, win, ctx1, ctx2); + + glDeleteLists(gear1, 1); + glDeleteLists(gear2, 1); + glXDestroyContext(dpy, ctx1); + glXDestroyContext(dpy, ctx2); + XDestroyWindow(dpy, win); + XCloseDisplay(dpy); + + return 0; +} diff --git a/scons/gallium.py b/scons/gallium.py index e9e799dc78..bf6172b4d7 100644 --- a/scons/gallium.py +++ b/scons/gallium.py @@ -462,6 +462,8 @@ def generate(env): shlinkflags += [ '-Wl,-Bsymbolic', ] + # Handle circular dependencies in the libraries + env['_LIBFLAGS'] = '-Wl,--start-group ' + env['_LIBFLAGS'] + ' -Wl,--end-group' if platform == 'windows' and msvc: # See also: # - http://msdn2.microsoft.com/en-us/library/y0zzbyt4.aspx diff --git a/src/egl/drivers/demo/demo.c b/src/egl/drivers/demo/demo.c index f316974d83..e8c0c1df5e 100644 --- a/src/egl/drivers/demo/demo.c +++ b/src/egl/drivers/demo/demo.c @@ -236,7 +236,7 @@ demoDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface) { DemoSurface *fs = LookupDemoSurface(surface); _eglUnlinkSurface(&fs->Base); - if (!fs->Base.IsBound) + if (!_eglIsSurfaceBound(&fs->Base)) free(fs); return EGL_TRUE; } @@ -247,7 +247,7 @@ demoDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext context) { DemoContext *fc = LookupDemoContext(context); _eglUnlinkContext(&fc->Base); - if (!fc->Base.IsBound) + if (!_eglIsContextBound(&fc->Base)) free(fc); return EGL_TRUE; } diff --git a/src/egl/drivers/dri/Makefile b/src/egl/drivers/dri/Makefile index 567edfae97..7339c97c77 100644 --- a/src/egl/drivers/dri/Makefile +++ b/src/egl/drivers/dri/Makefile @@ -55,6 +55,7 @@ install: clean: -rm -f *.o -rm -f *.so + -rm -f depend depend.bak depend: $(SOURCES) $(HEADERS) @ echo "running $(MKDEP)" diff --git a/src/egl/drivers/dri/egldri.c b/src/egl/drivers/dri/egldri.c index 3f9617a8f9..9e400be624 100644 --- a/src/egl/drivers/dri/egldri.c +++ b/src/egl/drivers/dri/egldri.c @@ -296,7 +296,7 @@ _eglDRIDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface) fs->drawable.destroyDrawable(disp, fs->drawable.private); - if (!fs->Base.IsBound) + if (!_eglIsSurfaceBound(&fs->Base)) free(fs); return EGL_TRUE; } @@ -312,7 +312,7 @@ _eglDRIDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext context) fc->driContext.destroyContext(disp, 0, fc->driContext.private); - if (!fc->Base.IsBound) + if (!_eglIsContextBound(&fc->Base)) free(fc); return EGL_TRUE; } diff --git a/src/egl/drivers/glx/egl_glx.c b/src/egl/drivers/glx/egl_glx.c index 207b1ea779..5ed4b6883f 100644 --- a/src/egl/drivers/glx/egl_glx.c +++ b/src/egl/drivers/glx/egl_glx.c @@ -739,7 +739,7 @@ GLX_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface) return EGL_TRUE; if (surf) { _eglUnlinkSurface(surf); - if (!surf->IsBound) + if (!_eglIsSurfaceBound(surf)) free(surf); return EGL_TRUE; diff --git a/src/egl/drivers/xdri/egl_xdri.c b/src/egl/drivers/xdri/egl_xdri.c index e040efdd43..d8d29fcef4 100644 --- a/src/egl/drivers/xdri/egl_xdri.c +++ b/src/egl/drivers/xdri/egl_xdri.c @@ -958,7 +958,7 @@ xdri_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface) struct xdri_egl_surface *xdri_surf = lookup_surface(surface); if (xdri_surf) { _eglUnlinkSurface(&xdri_surf->Base); - if (!xdri_surf->Base.IsBound) { + if (!_eglIsSurfaceBound(&xdri_surf->Base)) { /* st_unreference_framebuffer(surf->Framebuffer); */ diff --git a/src/egl/main/Makefile b/src/egl/main/Makefile index 7cab005214..ab61d68f2b 100644 --- a/src/egl/main/Makefile +++ b/src/egl/main/Makefile @@ -20,6 +20,7 @@ HEADERS = \ eglhash.h \ eglmisc.h \ eglmode.h \ + eglmutex.h \ eglscreen.h \ eglstring.h \ eglsurface.h \ @@ -74,6 +75,7 @@ install: default clean: -rm -f *.o *.so* -rm -f core.* + -rm -f depend depend.bak depend: $(SOURCES) $(HEADERS) diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c index f0a6f7f935..fde6b7316c 100644 --- a/src/egl/main/eglapi.c +++ b/src/egl/main/eglapi.c @@ -50,7 +50,6 @@ EGLDisplay EGLAPIENTRY eglGetDisplay(NativeDisplayType nativeDisplay) { _EGLDisplay *dpy; - _eglInitGlobals(); dpy = _eglFindDisplay(nativeDisplay); if (!dpy) { dpy = _eglNewDisplay(nativeDisplay); diff --git a/src/egl/main/eglcontext.c b/src/egl/main/eglcontext.c index 9ab4286d3a..88de60d69b 100644 --- a/src/egl/main/eglcontext.c +++ b/src/egl/main/eglcontext.c @@ -96,7 +96,7 @@ _eglDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx) _EGLContext *context = _eglLookupContext(ctx); if (context) { _eglUnlinkContext(context); - if (!context->IsBound) + if (!_eglIsContextBound(context)) free(context); return EGL_TRUE; } @@ -146,10 +146,11 @@ _eglQueryContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx, * Then, the driver will do its device-dependent Make-Current stuff. */ EGLBoolean -_eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d, +_eglMakeCurrent(_EGLDriver *drv, EGLDisplay display, EGLSurface d, EGLSurface r, EGLContext context) { _EGLThreadInfo *t = _eglGetCurrentThread(); + _EGLDisplay *dpy = _eglLookupDisplay(display); _EGLContext *ctx = _eglLookupContext(context); _EGLSurface *draw = _eglLookupSurface(d); _EGLSurface *read = _eglLookupSurface(r); @@ -160,21 +161,23 @@ _eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d, if (_eglIsCurrentThreadDummy()) return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent"); + if (dpy == NULL) + return _eglError(EGL_BAD_DISPLAY, "eglMakeCurrent"); - /* error checking */ if (ctx) { + /* error checking */ + if (ctx->Binding && ctx->Binding != t) + return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); if (draw == NULL || read == NULL) { - _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); - return EGL_FALSE; - } - if (draw->Config != ctx->Config) { - _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); - return EGL_FALSE; - } - if (read->Config != ctx->Config) { - _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); - return EGL_FALSE; + EGLint err = (d == EGL_NO_SURFACE || r == EGL_NO_SURFACE) + ? EGL_BAD_MATCH : EGL_BAD_SURFACE; + return _eglError(err, "eglMakeCurrent"); } + if (draw->Config != ctx->Config || read->Config != ctx->Config) + return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); + if ((draw->Binding && draw->Binding->Binding != t) || + (read->Binding && read->Binding->Binding != t)) + return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); #ifdef EGL_VERSION_1_4 /* OpenGL and OpenGL ES are conflicting */ @@ -194,6 +197,10 @@ _eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d, apiIndex = _eglConvertApiToIndex(ctx->ClientAPI); } else { + if (context != EGL_NO_CONTEXT) + return _eglError(EGL_BAD_CONTEXT, "eglMakeCurrent"); + if (draw != NULL || read != NULL) + return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); apiIndex = t->CurrentAPIIndex; } @@ -201,60 +208,47 @@ _eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d, if (oldContext) { oldDrawSurface = oldContext->DrawSurface; oldReadSurface = oldContext->ReadSurface; - } + assert(oldDrawSurface); + assert(oldReadSurface); - /* - * check if the old context or surfaces need to be deleted - */ - if (oldDrawSurface != NULL) { - oldDrawSurface->IsBound = EGL_FALSE; + /* break old bindings */ + t->CurrentContexts[apiIndex] = NULL; + oldContext->Binding = NULL; + oldContext->DrawSurface = NULL; + oldContext->ReadSurface = NULL; + oldDrawSurface->Binding = NULL; + oldReadSurface->Binding = NULL; + + /* + * check if the old context or surfaces need to be deleted + * FIXME They are linked so that they can be unlinked. This is ugly. + */ if (!_eglIsSurfaceLinked(oldDrawSurface)) { - /* make sure we don't try to rebind a deleted surface */ - if (draw == oldDrawSurface || draw == oldReadSurface) { - draw = NULL; - } - /* really delete surface now */ - drv->API.DestroySurface(drv, dpy, oldDrawSurface->Handle); + assert(draw != oldDrawSurface && read != oldDrawSurface); + drv->API.DestroySurface(drv, display, + _eglLinkSurface(oldDrawSurface, dpy)); } - } - if (oldReadSurface != NULL && oldReadSurface != oldDrawSurface) { - oldReadSurface->IsBound = EGL_FALSE; - if (!_eglIsSurfaceLinked(oldReadSurface)) { - /* make sure we don't try to rebind a deleted surface */ - if (read == oldDrawSurface || read == oldReadSurface) { - read = NULL; - } - /* really delete surface now */ - drv->API.DestroySurface(drv, dpy, oldReadSurface->Handle); + if (oldReadSurface != oldDrawSurface && + !_eglIsSurfaceLinked(oldReadSurface)) { + assert(draw != oldReadSurface && read != oldReadSurface); + drv->API.DestroySurface(drv, display, + _eglLinkSurface(oldReadSurface, dpy)); } - } - if (oldContext != NULL) { - oldContext->IsBound = EGL_FALSE; if (!_eglIsContextLinked(oldContext)) { - /* make sure we don't try to rebind a deleted context */ - if (ctx == oldContext) { - ctx = NULL; - } - /* really delete context now */ - drv->API.DestroyContext(drv, dpy, _eglGetContextHandle(oldContext)); + assert(ctx != oldContext); + drv->API.DestroyContext(drv, display, + _eglLinkContext(oldContext, dpy)); } } + /* build new bindings */ if (ctx) { - /* check read/draw again, in case we deleted them above */ - if (draw == NULL || read == NULL) { - _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); - return EGL_FALSE; - } + t->CurrentContexts[apiIndex] = ctx; + ctx->Binding = t; ctx->DrawSurface = draw; ctx->ReadSurface = read; - ctx->IsBound = EGL_TRUE; - draw->IsBound = EGL_TRUE; - read->IsBound = EGL_TRUE; - t->CurrentContexts[apiIndex] = ctx; - } - else { - t->CurrentContexts[apiIndex] = NULL; + draw->Binding = ctx; + read->Binding = ctx; } return EGL_TRUE; diff --git a/src/egl/main/eglcontext.h b/src/egl/main/eglcontext.h index 2fb28d38b9..4276c0980e 100644 --- a/src/egl/main/eglcontext.h +++ b/src/egl/main/eglcontext.h @@ -15,12 +15,12 @@ struct _egl_context _EGLDisplay *Display; _EGLContext *Next; - _EGLConfig *Config; - + /* The bound status of the context */ + _EGLThreadInfo *Binding; _EGLSurface *DrawSurface; _EGLSurface *ReadSurface; - EGLBoolean IsBound; + _EGLConfig *Config; EGLint ClientAPI; /**< EGL_OPENGL_ES_API, EGL_OPENGL_API, EGL_OPENVG_API */ EGLint ClientVersion; /**< 1 = OpenGLES 1.x, 2 = OpenGLES 2.x */ @@ -51,4 +51,15 @@ _eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw, EGLSurface rea extern EGLBoolean _eglCopyContextMESA(_EGLDriver *drv, EGLDisplay dpy, EGLContext source, EGLContext dest, EGLint mask); + +/** + * Return true if the context is bound to a thread. + */ +static INLINE EGLBoolean +_eglIsContextBound(_EGLContext *ctx) +{ + return (ctx->Binding != NULL); +} + + #endif /* EGLCONTEXT_INCLUDED */ diff --git a/src/egl/main/eglcurrent.c b/src/egl/main/eglcurrent.c index 96152db19f..4431f964f6 100644 --- a/src/egl/main/eglcurrent.c +++ b/src/egl/main/eglcurrent.c @@ -3,61 +3,127 @@ #include "eglcurrent.h" #include "eglcontext.h" #include "egllog.h" +#include "eglmutex.h" +#include "eglglobals.h" +/* This should be kept in sync with _eglInitThreadInfo() */ +#define _EGL_THREAD_INFO_INITIALIZER \ + { EGL_SUCCESS, { NULL }, 1 } + /* a fallback thread info to guarantee that every thread always has one */ -static _EGLThreadInfo dummy_thread; +static _EGLThreadInfo dummy_thread = _EGL_THREAD_INFO_INITIALIZER; #ifdef GLX_USE_TLS static __thread const _EGLThreadInfo *_egl_TSD; __attribute__ ((tls_model("initial-exec"))); -static INLINE EGLBoolean _eglInitTSD(void) { return EGL_TRUE; } -static INLINE void _eglFiniTSD(void) { } -static INLINE void _eglSetTSD(const _EGLThreadInfo *t) { _egl_TSD = t; } +static INLINE void _eglSetTSD(const _EGLThreadInfo *t) +{ + _egl_TSD = t; +} static INLINE _EGLThreadInfo *_eglGetTSD(void) { return (_EGLThreadInfo *) _egl_TSD; } +static INLINE void _eglFiniTSD(void) +{ +} + +static INLINE EGLBoolean _eglInitTSD(void (*dtor)(_EGLThreadInfo *)) +{ + /* TODO destroy TSD */ + (void) dtor; + (void) _eglFiniTSD; + return EGL_TRUE; +} + #elif PTHREADS #include <pthread.h> +static _EGL_DECLARE_MUTEX(_egl_TSDMutex); +static EGLBoolean _egl_TSDInitialized; static pthread_key_t _egl_TSD; +static void (*_egl_FreeTSD)(_EGLThreadInfo *); -static INLINE EGLBoolean _eglInitTSD(void) +static INLINE void _eglSetTSD(const _EGLThreadInfo *t) { - return (pthread_key_create(&_egl_TSD, NULL) == 0); + pthread_setspecific(_egl_TSD, (const void *) t); } -static INLINE void _eglFiniTSD(void) +static INLINE _EGLThreadInfo *_eglGetTSD(void) { - pthread_key_delete(_egl_TSD); + return (_EGLThreadInfo *) pthread_getspecific(_egl_TSD); } -static INLINE void _eglSetTSD(const _EGLThreadInfo *t) +static INLINE void _eglFiniTSD(void) { - pthread_setspecific(_egl_TSD, (const void *) t); + _eglLockMutex(&_egl_TSDMutex); + if (_egl_TSDInitialized) { + _EGLThreadInfo *t = _eglGetTSD(); + + _egl_TSDInitialized = EGL_FALSE; + if (t && _egl_FreeTSD) + _egl_FreeTSD((void *) t); + pthread_key_delete(_egl_TSD); + } + _eglUnlockMutex(&_egl_TSDMutex); } -static INLINE _EGLThreadInfo *_eglGetTSD(void) +static INLINE EGLBoolean _eglInitTSD(void (*dtor)(_EGLThreadInfo *)) { - return (_EGLThreadInfo *) pthread_getspecific(_egl_TSD); + if (!_egl_TSDInitialized) { + _eglLockMutex(&_egl_TSDMutex); + + /* check again after acquiring lock */ + if (!_egl_TSDInitialized) { + if (pthread_key_create(&_egl_TSD, (void (*)(void *)) dtor) != 0) { + _eglUnlockMutex(&_egl_TSDMutex); + return EGL_FALSE; + } + _egl_FreeTSD = dtor; + _eglAddAtExitCall(_eglFiniTSD); + _egl_TSDInitialized = EGL_TRUE; + } + + _eglUnlockMutex(&_egl_TSDMutex); + } + + return EGL_TRUE; } #else /* PTHREADS */ static const _EGLThreadInfo *_egl_TSD; +static void (*_egl_FreeTSD)(_EGLThreadInfo *); -static INLINE EGLBoolean _eglInitTSD(void) { return EGL_TRUE; } -static INLINE void _eglFiniTSD(void) { } -static INLINE void _eglSetTSD(const _EGLThreadInfo *t) { _egl_TSD = t; } +static INLINE void _eglSetTSD(const _EGLThreadInfo *t) +{ + _egl_TSD = t; +} static INLINE _EGLThreadInfo *_eglGetTSD(void) { return (_EGLThreadInfo *) _egl_TSD; } + +static INLINE void _eglFiniTSD(void) +{ + if (_egl_FreeTSD && _egl_TSD) + _egl_FreeTSD((_EGLThreadInfo *) _egl_TSD); +} + +static INLINE EGLBoolean _eglInitTSD(void (*dtor)(_EGLThreadInfo *)) +{ + if (!_egl_FreeTSD && dtor) { + _egl_FreeTSD = dtor; + _eglAddAtExitCall(_eglFiniTSD); + } + return EGL_TRUE; +} + #endif /* !PTHREADS */ @@ -98,24 +164,17 @@ _eglDestroyThreadInfo(_EGLThreadInfo *t) /** - * Initialize "current thread" management. + * Make sure TSD is initialized and return current value. */ -EGLBoolean -_eglInitCurrent(void) +static INLINE _EGLThreadInfo * +_eglCheckedGetTSD(void) { - _eglInitThreadInfo(&dummy_thread); - return _eglInitTSD(); -} - + if (_eglInitTSD(&_eglDestroyThreadInfo) != EGL_TRUE) { + _eglLog(_EGL_FATAL, "failed to initialize \"current\" system"); + return NULL; + } -/** - * Finish "current thread" management. - */ -void -_eglFiniCurrent(void) -{ - /* TODO trace and release all threads... */ - _eglFiniTSD(); + return _eglGetTSD(); } @@ -129,7 +188,7 @@ _eglFiniCurrent(void) _EGLThreadInfo * _eglGetCurrentThread(void) { - _EGLThreadInfo *t = _eglGetTSD(); + _EGLThreadInfo *t = _eglCheckedGetTSD(); if (!t) { t = _eglCreateThreadInfo(); _eglSetTSD(t); @@ -145,7 +204,7 @@ _eglGetCurrentThread(void) void _eglDestroyCurrentThread(void) { - _EGLThreadInfo *t = _eglGetTSD(); + _EGLThreadInfo *t = _eglCheckedGetTSD(); if (t) { _eglDestroyThreadInfo(t); _eglSetTSD(NULL); @@ -162,7 +221,7 @@ _eglDestroyCurrentThread(void) EGLBoolean _eglIsCurrentThreadDummy(void) { - _EGLThreadInfo *t = _eglGetTSD(); + _EGLThreadInfo *t = _eglCheckedGetTSD(); return (!t || t == &dummy_thread); } diff --git a/src/egl/main/eglcurrent.h b/src/egl/main/eglcurrent.h index f9fdf7bd0f..8eb241029e 100644 --- a/src/egl/main/eglcurrent.h +++ b/src/egl/main/eglcurrent.h @@ -20,14 +20,6 @@ struct _egl_thread_info }; -extern EGLBoolean -_eglInitCurrent(void); - - -extern void -_eglFiniCurrent(void); - - /** * Return true if a client API enum can be converted to an index. */ diff --git a/src/egl/main/egldisplay.c b/src/egl/main/egldisplay.c index 5304b84a26..feae1d6040 100644 --- a/src/egl/main/egldisplay.c +++ b/src/egl/main/egldisplay.c @@ -1,4 +1,3 @@ - /** * Functions related to EGLDisplay. */ @@ -13,6 +12,67 @@ #include "eglglobals.h" #include "eglhash.h" #include "eglstring.h" +#include "eglmutex.h" +#include "egllog.h" + + +static _EGL_DECLARE_MUTEX(_eglDisplayInitMutex); +static _EGLHashtable *_eglDisplayHash; +/* TODO surface hash table should be per-display */ +static _EGLHashtable *_eglSurfaceHash; + + +/** + * Finish display management. + */ +static void +_eglFiniDisplay(void) +{ + _eglLockMutex(&_eglDisplayInitMutex); + if (_eglDisplayHash) { + EGLuint key = _eglHashFirstEntry(_eglDisplayHash); + + while (key) { + _EGLDisplay *dpy = (_EGLDisplay *) + _eglHashLookup(_eglDisplayHash, key); + assert(dpy); + + if (dpy->ContextList || dpy->SurfaceList) + _eglLog(_EGL_DEBUG, "Display %u is destroyed with resources", key); + + _eglCleanupDisplay(dpy); + free(dpy); + + key = _eglHashNextEntry(_eglDisplayHash, key); + } + + _eglDeleteHashTable(_eglDisplayHash); + _eglDisplayHash = NULL; + _eglDeleteHashTable(_eglSurfaceHash); + _eglSurfaceHash = NULL; + } + _eglUnlockMutex(&_eglDisplayInitMutex); +} + + +/* This can be avoided if hash table can be statically initialized */ +static INLINE void +_eglInitDisplay(void) +{ + if (!_eglDisplayHash) { + _eglLockMutex(&_eglDisplayInitMutex); + + /* check again after acquiring lock */ + if (!_eglDisplayHash) { + _eglDisplayHash = _eglNewHashTable(); + _eglSurfaceHash = _eglNewHashTable(); + + _eglAddAtExitCall(_eglFiniDisplay); + } + + _eglUnlockMutex(&_eglDisplayInitMutex); + } +} /** @@ -31,6 +91,9 @@ _eglNewDisplay(NativeDisplayType nativeDisplay) dpy->Xdpy = (Display *) nativeDisplay; #endif + _eglInitDisplay(); + dpy->SurfaceHash = _eglSurfaceHash; + dpy->DriverName = _eglChooseDriver(dpy); if (!dpy->DriverName) { free(dpy); @@ -49,10 +112,13 @@ EGLDisplay _eglLinkDisplay(_EGLDisplay *dpy) { EGLuint key; - key = _eglHashGenKey(_eglGlobal.Displays); + + _eglInitDisplay(); + + key = _eglHashGenKey(_eglDisplayHash); assert(key); /* "link" the display to the hash table */ - _eglHashInsert(_eglGlobal.Displays, key, dpy); + _eglHashInsert(_eglDisplayHash, key, dpy); dpy->Handle = (EGLDisplay) _eglUIntToPointer(key); return dpy->Handle; @@ -67,7 +133,10 @@ void _eglUnlinkDisplay(_EGLDisplay *dpy) { EGLuint key = _eglPointerToUInt((void *) dpy->Handle); - _eglHashRemove(_eglGlobal.Displays, key); + + _eglInitDisplay(); + + _eglHashRemove(_eglDisplayHash, key); dpy->Handle = EGL_NO_DISPLAY; } @@ -84,7 +153,7 @@ _eglGetDisplayHandle(_EGLDisplay *display) return EGL_NO_DISPLAY; } - + /** * Lookup a handle to find the linked display. * Return NULL if the handle has no corresponding linked display. @@ -93,7 +162,10 @@ _EGLDisplay * _eglLookupDisplay(EGLDisplay dpy) { EGLuint key = _eglPointerToUInt((void *) dpy); - return (_EGLDisplay *) _eglHashLookup(_eglGlobal.Displays, key); + + _eglInitDisplay(); + + return (_EGLDisplay *) _eglHashLookup(_eglDisplayHash, key); } @@ -104,17 +176,20 @@ _eglLookupDisplay(EGLDisplay dpy) _EGLDisplay * _eglFindDisplay(NativeDisplayType nativeDisplay) { - EGLuint key = _eglHashFirstEntry(_eglGlobal.Displays); + EGLuint key; + + _eglInitDisplay(); /* Walk the hash table. Should switch to list if it is a problem. */ + key = _eglHashFirstEntry(_eglDisplayHash); while (key) { _EGLDisplay *dpy = (_EGLDisplay *) - _eglHashLookup(_eglGlobal.Displays, key); + _eglHashLookup(_eglDisplayHash, key); assert(dpy); if (dpy->NativeDisplay == nativeDisplay) return dpy; - key = _eglHashNextEntry(_eglGlobal.Displays, key); + key = _eglHashNextEntry(_eglDisplayHash, key); } return NULL; @@ -254,9 +329,9 @@ _eglLinkSurface(_EGLSurface *surf, _EGLDisplay *dpy) surf->Next = dpy->SurfaceList; dpy->SurfaceList = surf; - key = _eglHashGenKey(_eglGlobal.Surfaces); + key = _eglHashGenKey(dpy->SurfaceHash); assert(key); - _eglHashInsert(_eglGlobal.Surfaces, key, surf); + _eglHashInsert(dpy->SurfaceHash, key, surf); surf->Handle = (EGLSurface) _eglUIntToPointer(key); return surf->Handle; @@ -273,7 +348,7 @@ _eglUnlinkSurface(_EGLSurface *surf) _EGLSurface *prev; EGLuint key = _eglPointerToUInt((void *) surf->Handle); - _eglHashRemove(_eglGlobal.Surfaces, key); + _eglHashRemove(surf->Display->SurfaceHash, key); surf->Handle = EGL_NO_SURFACE; prev = surf->Display->SurfaceList; @@ -317,5 +392,5 @@ _EGLSurface * _eglLookupSurface(EGLSurface surf) { EGLuint key = _eglPointerToUInt((void *) surf); - return (_EGLSurface *) _eglHashLookup(_eglGlobal.Surfaces, key); + return (_EGLSurface *) _eglHashLookup(_eglSurfaceHash, key); } diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h index 2ef5db8a18..70c59ef5e4 100644 --- a/src/egl/main/egldisplay.h +++ b/src/egl/main/egldisplay.h @@ -6,6 +6,7 @@ #endif #include "egltypedefs.h" +#include "eglhash.h" struct _egl_display @@ -26,6 +27,10 @@ struct _egl_display /* lists of linked contexts and surface */ _EGLContext *ContextList; _EGLSurface *SurfaceList; + + /* hash table to map surfaces to handles */ + _EGLHashtable *SurfaceHash; + #ifdef _EGL_PLATFORM_X Display *Xdpy; #endif diff --git a/src/egl/main/eglglobals.c b/src/egl/main/eglglobals.c index 55de394ef5..e93b48e03b 100644 --- a/src/egl/main/eglglobals.c +++ b/src/egl/main/eglglobals.c @@ -1,41 +1,53 @@ #include <stdlib.h> +#include <assert.h> #include "eglglobals.h" +#include "egldisplay.h" #include "egllog.h" +#include "eglmutex.h" -struct _egl_global _eglGlobal = -{ - EGL_FALSE -}; -/** - * Init the fields in the _eglGlobal struct - * May be safely called more than once. - */ -void -_eglInitGlobals(void) +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + + +static _EGL_DECLARE_MUTEX(_eglGlobalMutex); +struct _egl_global _eglGlobal = { - if (!_eglGlobal.Initialized) { - _eglGlobal.Displays = _eglNewHashTable(); - _eglGlobal.Surfaces = _eglNewHashTable(); - _eglGlobal.FreeScreenHandle = 1; - _eglGlobal.Initialized = EGL_TRUE; + &_eglGlobalMutex, /* Mutex */ + 1, /* FreeScreenHandle */ + 0x0, /* ClientAPIsMask */ + { 0x0 }, /* ClientAPIs */ + 0, /* NumDrivers */ + { NULL }, /* Drivers */ + 0, /* NumAtExitCalls */ + { NULL }, /* AtExitCalls */ +}; - _eglGlobal.ClientAPIsMask = 0x0; - if (!_eglInitCurrent()) - _eglLog(_EGL_FATAL, "failed to initialize \"current\" system"); - } +static void +_eglAtExit(void) +{ + EGLint i; + for (i = _eglGlobal.NumAtExitCalls - 1; i >= 0; i--) + _eglGlobal.AtExitCalls[i](); } -/** - * Should call this via an atexit handler. - */ void -_eglDestroyGlobals(void) +_eglAddAtExitCall(void (*func)(void)) { - _eglFiniCurrent(); - /* XXX TODO walk over table entries, deleting each */ - _eglDeleteHashTable(_eglGlobal.Displays); - _eglDeleteHashTable(_eglGlobal.Surfaces); + if (func) { + static EGLBoolean registered = EGL_FALSE; + + _eglLockMutex(_eglGlobal.Mutex); + + if (!registered) { + atexit(_eglAtExit); + registered = EGL_TRUE; + } + + assert(_eglGlobal.NumAtExitCalls < ARRAY_SIZE(_eglGlobal.AtExitCalls)); + _eglGlobal.AtExitCalls[_eglGlobal.NumAtExitCalls++] = func; + + _eglUnlockMutex(_eglGlobal.Mutex); + } } diff --git a/src/egl/main/eglglobals.h b/src/egl/main/eglglobals.h index a9443cfbdd..1e2c674263 100644 --- a/src/egl/main/eglglobals.h +++ b/src/egl/main/eglglobals.h @@ -4,6 +4,7 @@ #include "egltypedefs.h" #include "eglhash.h" #include "eglcurrent.h" +#include "eglmutex.h" /** @@ -11,12 +12,7 @@ */ struct _egl_global { - EGLBoolean Initialized; - - /* these are private to egldisplay.c */ - _EGLHashtable *Displays; - _EGLHashtable *Surfaces; - + _EGLMutex *Mutex; EGLScreenMESA FreeScreenHandle; /* bitmaks of supported APIs (supported by _some_ driver) */ @@ -26,6 +22,9 @@ struct _egl_global EGLint NumDrivers; _EGLDriver *Drivers[10]; + + EGLint NumAtExitCalls; + void (*AtExitCalls[10])(void); }; @@ -33,11 +32,7 @@ extern struct _egl_global _eglGlobal; extern void -_eglInitGlobals(void); - - -extern void -_eglDestroyGlobals(void); +_eglAddAtExitCall(void (*func)(void)); #endif /* EGLGLOBALS_INCLUDED */ diff --git a/src/egl/main/eglmutex.h b/src/egl/main/eglmutex.h new file mode 100644 index 0000000000..29faba0f24 --- /dev/null +++ b/src/egl/main/eglmutex.h @@ -0,0 +1,52 @@ +#ifndef EGLMUTEX_INCLUDED +#define EGLMUTEX_INCLUDED + +#include "eglcompiler.h" + +#ifdef PTHREADS +#include <pthread.h> + +typedef pthread_mutex_t _EGLMutex; + +static INLINE void _eglInitMutex(_EGLMutex *m) +{ + pthread_mutex_init(m, NULL); +} + +static INLINE void +_eglDestroyMutex(_EGLMutex *m) +{ + pthread_mutex_destroy(m); +} + +static INLINE void +_eglLockMutex(_EGLMutex *m) +{ + pthread_mutex_lock(m); +} + +static INLINE void +_eglUnlockMutex(_EGLMutex *m) +{ + pthread_mutex_unlock(m); +} + +#define _EGL_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER +#define _EGL_DECLARE_MUTEX(m) \ + _EGLMutex m = _EGL_MUTEX_INITIALIZER + +#else + +typedef int _EGLMutex; +static INLINE void _eglInitMutex(_EGLMutex *m) { (void) m; } +static INLINE void _eglDestroyMutex(_EGLMutex *m) { (void) m; } +static INLINE void _eglLockMutex(_EGLMutex *m) { (void) m; } +static INLINE void _eglUnlockMutex(_EGLMutex *m) { (void) m; } + +#define _EGL_MUTEX_INITIALIZER 0 +#define _EGL_DECLARE_MUTEX(m) \ + _EGLMutex m = _EGL_MUTEX_INITIALIZER + +#endif + +#endif /* EGLMUTEX_INCLUDED */ diff --git a/src/egl/main/eglsurface.c b/src/egl/main/eglsurface.c index 9821e63628..3947051127 100644 --- a/src/egl/main/eglsurface.c +++ b/src/egl/main/eglsurface.c @@ -26,7 +26,8 @@ _eglInitSurface(_EGLDriver *drv, _EGLSurface *surf, EGLint type, { const char *func; EGLint width = 0, height = 0, largest = 0; - EGLint texFormat = 0, texTarget = 0, mipmapTex = 0; + EGLint texFormat = EGL_NO_TEXTURE, texTarget = EGL_NO_TEXTURE; + EGLint mipmapTex = EGL_FALSE; EGLint renderBuffer = EGL_BACK_BUFFER; #ifdef EGL_VERSION_1_2 EGLint colorspace = EGL_COLORSPACE_sRGB; @@ -413,7 +414,7 @@ _eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface) _EGLSurface *surf = _eglLookupSurface(surface); if (surf) { _eglUnlinkSurface(surf); - if (!surf->IsBound) + if (!_eglIsSurfaceBound(surf)) free(surf); return EGL_TRUE; } diff --git a/src/egl/main/eglsurface.h b/src/egl/main/eglsurface.h index f9413eb9d7..8864176844 100644 --- a/src/egl/main/eglsurface.h +++ b/src/egl/main/eglsurface.h @@ -15,12 +15,12 @@ struct _egl_surface _EGLSurface *Next; EGLSurface Handle; - _EGLConfig *Config; - - /* May need reference counting here */ - EGLBoolean IsBound; + /* The bound status of the surface */ + _EGLContext *Binding; EGLBoolean BoundToTexture; + _EGLConfig *Config; + EGLint Type; /* one of EGL_WINDOW_BIT, EGL_PIXMAP_BIT or EGL_PBUFFER_BIT */ EGLint Width, Height; EGLint TextureFormat, TextureTarget; @@ -100,5 +100,16 @@ _eglCreatePbufferFromClientBuffer(_EGLDriver *drv, EGLDisplay dpy, #endif /* EGL_VERSION_1_2 */ +/** + * Return true if the surface is bound to a thread. + * A surface bound to a texutre is not considered bound by + * this function. + */ +static INLINE EGLBoolean +_eglIsSurfaceBound(_EGLSurface *surf) +{ + return (surf->Binding != NULL); +} + #endif /* EGLSURFACE_INCLUDED */ diff --git a/src/gallium/Makefile.template b/src/gallium/Makefile.template index 98487d43bd..2e3da436cd 100644 --- a/src/gallium/Makefile.template +++ b/src/gallium/Makefile.template @@ -31,8 +31,8 @@ INCLUDES = \ default: depend lib$(LIBNAME).a -lib$(LIBNAME).a: $(OBJECTS) Makefile $(TOP)/src/gallium/Makefile.template - $(MKLIB) -o $(LIBNAME) -static $(OBJECTS) +lib$(LIBNAME).a: $(OBJECTS) $(EXTRA_OBJECTS) Makefile $(TOP)/src/gallium/Makefile.template + $(MKLIB) -o $(LIBNAME) -static $(OBJECTS) $(EXTRA_OBJECTS) depend: $(C_SOURCES) $(CPP_SOURCES) $(ASM_SOURCES) $(SYMLINKS) rm -f depend diff --git a/src/gallium/auxiliary/draw/draw_pipe.c b/src/gallium/auxiliary/draw/draw_pipe.c index 2e3f5b2fc0..1c6d657297 100644 --- a/src/gallium/auxiliary/draw/draw_pipe.c +++ b/src/gallium/auxiliary/draw/draw_pipe.c @@ -158,6 +158,60 @@ static void do_triangle( struct draw_context *draw, +#define QUAD(i0,i1,i2,i3) \ + do_triangle( draw, \ + ( DRAW_PIPE_RESET_STIPPLE | \ + DRAW_PIPE_EDGE_FLAG_0 | \ + DRAW_PIPE_EDGE_FLAG_2 ), \ + verts + stride * elts[i0], \ + verts + stride * elts[i1], \ + verts + stride * elts[i3]); \ + do_triangle( draw, \ + ( DRAW_PIPE_EDGE_FLAG_0 | \ + DRAW_PIPE_EDGE_FLAG_1 ), \ + verts + stride * elts[i1], \ + verts + stride * elts[i2], \ + verts + stride * elts[i3]) + +#define TRIANGLE(flags,i0,i1,i2) \ + do_triangle( draw, \ + elts[i0], /* flags */ \ + verts + stride * (elts[i0] & ~DRAW_PIPE_FLAG_MASK), \ + verts + stride * elts[i1], \ + verts + stride * elts[i2]) + +#define LINE(flags,i0,i1) \ + do_line( draw, \ + elts[i0], \ + verts + stride * (elts[i0] & ~DRAW_PIPE_FLAG_MASK), \ + verts + stride * elts[i1]) + +#define POINT(i0) \ + do_point( draw, \ + verts + stride * elts[i0] ) + +#define FUNC pipe_run +#define ARGS \ + struct draw_context *draw, \ + unsigned prim, \ + struct vertex_header *vertices, \ + unsigned stride, \ + const ushort *elts + +#define LOCAL_VARS \ + char *verts = (char *)vertices; \ + boolean flatfirst = (draw->rasterizer->flatshade && \ + draw->rasterizer->flatshade_first); \ + unsigned i; \ + ushort flags + +#define FLUSH + +#include "draw_pt_decompose.h" +#undef ARGS +#undef LOCAL_VARS + + /* Code to run the pipeline on a fairly arbitary collection of vertices. * @@ -178,34 +232,12 @@ void draw_pipeline_run( struct draw_context *draw, unsigned count ) { char *verts = (char *)vertices; - unsigned i; draw->pipeline.verts = verts; draw->pipeline.vertex_stride = stride; draw->pipeline.vertex_count = vertex_count; - switch (prim) { - case PIPE_PRIM_POINTS: - for (i = 0; i < count; i++) - do_point( draw, - verts + stride * elts[i] ); - break; - case PIPE_PRIM_LINES: - for (i = 0; i+1 < count; i += 2) - do_line( draw, - elts[i+0], /* flags */ - verts + stride * (elts[i+0] & ~DRAW_PIPE_FLAG_MASK), - verts + stride * elts[i+1]); - break; - case PIPE_PRIM_TRIANGLES: - for (i = 0; i+2 < count; i += 3) - do_triangle( draw, - elts[i+0], /* flags */ - verts + stride * (elts[i+0] & ~DRAW_PIPE_FLAG_MASK), - verts + stride * elts[i+1], - verts + stride * elts[i+2]); - break; - } + pipe_run(draw, prim, vertices, stride, elts, count); draw->pipeline.verts = NULL; draw->pipeline.vertex_count = 0; diff --git a/src/gallium/auxiliary/draw/draw_pipe_wide_point.c b/src/gallium/auxiliary/draw/draw_pipe_wide_point.c index 014d8c7346..7d76a7dbf3 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_wide_point.c +++ b/src/gallium/auxiliary/draw/draw_pipe_wide_point.c @@ -28,6 +28,30 @@ /* Authors: Keith Whitwell <keith@tungstengraphics.com> */ +/** + * Notes on wide points and sprite mode: + * + * In wide point/sprite mode we effectively need to convert each incoming + * vertex into four outgoing vertices specifying the corners of a quad. + * Since we don't (yet) have geometry shaders, we have to handle this here + * in the draw module. + * + * For sprites, it also means that this is where we have to handle texcoords + * for the vertices of the quad. OpenGL's GL_COORD_REPLACE state specifies + * if/how enabled texcoords are automatically generated for sprites. We pass + * that info through gallium in the pipe_rasterizer_state::sprite_coord_mode + * array. + * + * Additionally, GLSL's gl_PointCoord fragment attribute has to be handled + * here as well. This is basically an additional texture/generic attribute + * that varies .x from 0 to 1 horizontally across the point and varies .y + * vertically from 0 to 1 down the sprite. + * + * With geometry shaders, the state tracker could create a GS to do + * most/all of this. + */ + + #include "util/u_math.h" #include "util/u_memory.h" #include "pipe/p_defines.h" @@ -52,7 +76,7 @@ struct widepoint_stage { int psize_slot; - int point_coord_fs_input; /**< input for pointcoord (and fog) */ + int point_coord_fs_input; /**< input for pointcoord */ }; @@ -64,8 +88,6 @@ widepoint_stage( struct draw_stage *stage ) } - - /** * Set the vertex texcoords for sprite mode. * Coords may be left untouched or set to a right-side-up or upside-down @@ -89,10 +111,12 @@ static void set_texcoords(const struct widepoint_stage *wide, } if (wide->point_coord_fs_input >= 0) { - /* put gl_PointCoord into extra vertex output's zw components */ - uint k = wide->stage.draw->extra_vp_outputs.slot; - v->data[k][2] = tc[0]; - v->data[k][3] = tc[1]; + /* put gl_PointCoord into the extra vertex slot */ + uint slot = wide->stage.draw->extra_vp_outputs.slot; + v->data[slot][0] = tc[0]; + v->data[slot][1] = tc[1]; + v->data[slot][2] = 0.0F; + v->data[slot][3] = 1.0F; } } @@ -182,10 +206,10 @@ static void widepoint_point( struct draw_stage *stage, static int -find_fog_input_attrib(struct draw_context *draw) +find_pntc_input_attrib(struct draw_context *draw) { - /* Scan the fragment program's input decls to find the fogcoord - * attribute. The z/w components will store the point coord. + /* Scan the fragment program's input decls to find the pointcoord + * attribute. The xy components will store the point coord. */ return 0; /* XXX fix this */ } @@ -229,8 +253,8 @@ static void widepoint_first_point( struct draw_stage *stage, } wide->num_texcoords = j; - /* find fragment shader PointCoord/Fog input */ - wide->point_coord_fs_input = find_fog_input_attrib(draw); + /* find fragment shader PointCoord input */ + wide->point_coord_fs_input = find_pntc_input_attrib(draw); /* setup extra vp output (point coord implemented as a texcoord) */ draw->extra_vp_outputs.semantic_name = TGSI_SEMANTIC_GENERIC; diff --git a/src/gallium/auxiliary/tgsi/Makefile b/src/gallium/auxiliary/tgsi/Makefile index b4900e8dba..5f0a580b09 100644 --- a/src/gallium/auxiliary/tgsi/Makefile +++ b/src/gallium/auxiliary/tgsi/Makefile @@ -16,6 +16,7 @@ C_SOURCES = \ tgsi_sse2.c \ tgsi_text.c \ tgsi_transform.c \ + tgsi_ureg.c \ tgsi_util.c include ../../Makefile.template diff --git a/src/gallium/auxiliary/tgsi/SConscript b/src/gallium/auxiliary/tgsi/SConscript index 8200cce42f..b6bc2924f0 100644 --- a/src/gallium/auxiliary/tgsi/SConscript +++ b/src/gallium/auxiliary/tgsi/SConscript @@ -16,6 +16,7 @@ tgsi = env.ConvenienceLibrary( 'tgsi_sse2.c', 'tgsi_text.c', 'tgsi_transform.c', + 'tgsi_ureg.c', 'tgsi_util.c', ]) diff --git a/src/gallium/auxiliary/tgsi/tgsi_info.c b/src/gallium/auxiliary/tgsi/tgsi_info.c index cd8871e32d..ccf4b205ff 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_info.c +++ b/src/gallium/auxiliary/tgsi/tgsi_info.c @@ -170,3 +170,12 @@ tgsi_get_opcode_info( uint opcode ) assert( 0 ); return NULL; } + + +const char * +tgsi_get_opcode_name( uint opcode ) +{ + const struct tgsi_opcode_info *info = tgsi_get_opcode_info(opcode); + return info->mnemonic; +} + diff --git a/src/gallium/auxiliary/tgsi/tgsi_info.h b/src/gallium/auxiliary/tgsi/tgsi_info.h index 16577598bb..b2375c6971 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_info.h +++ b/src/gallium/auxiliary/tgsi/tgsi_info.h @@ -47,6 +47,10 @@ struct tgsi_opcode_info const struct tgsi_opcode_info * tgsi_get_opcode_info( uint opcode ); +const char * +tgsi_get_opcode_name( uint opcode ); + + #if defined __cplusplus } #endif diff --git a/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h b/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h new file mode 100644 index 0000000000..ed594a3e2c --- /dev/null +++ b/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h @@ -0,0 +1,173 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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 TUNGSTEN GRAPHICS 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 OP12_TEX +#define OP12_TEX(a) OP12(a) +#endif + +#ifndef OP14_TEX +#define OP14_TEX(a) OP14(a) +#endif + +#ifndef OP00_LBL +#define OP00_LBL(a) OP00(a) +#endif + +#ifndef OP01_LBL +#define OP01_LBL(a) OP01(a) +#endif + +OP11(ARL) +OP11(MOV) +OP11(LIT) +OP11(RCP) +OP11(RSQ) +OP11(EXP) +OP11(LOG) +OP12(MUL) +OP12(ADD) +OP12(DP3) +OP12(DP4) +OP12(DST) +OP12(MIN) +OP12(MAX) +OP12(SLT) +OP12(SGE) +OP13(MAD) +OP12(SUB) +OP13(LRP) +OP13(CND) +OP13(CND0) +OP13(DP2A) +OP11(FRC) +OP13(CLAMP) +OP11(FLR) +OP11(ROUND) +OP11(EX2) +OP11(LG2) +OP12(POW) +OP12(XPD) +OP11(ABS) +OP11(RCC) +OP12(DPH) +OP11(COS) +OP11(DDX) +OP11(DDY) +OP00(KILP) +OP11(PK2H) +OP11(PK2US) +OP11(PK4B) +OP11(PK4UB) +OP12(RFL) +OP12(SEQ) +OP12(SFL) +OP12(SGT) +OP11(SIN) +OP12(SLE) +OP12(SNE) +OP12(STR) +OP12_TEX(TEX) +OP14_TEX(TXD) +OP12_TEX(TXP) +OP11(UP2H) +OP11(UP2US) +OP11(UP4B) +OP11(UP4UB) +OP13(X2D) +OP11(ARA) +OP11(ARR) +OP01(BRA) +OP00_LBL(CAL) +OP00(RET) +OP11(SSG) +OP13(CMP) +OP11(SCS) +OP12_TEX(TXB) +OP11(NRM) +OP12(DIV) +OP12(DP2) +OP12_TEX(TXL) +OP00(BRK) +OP01_LBL(IF) +OP11(BGNFOR) +OP01(REP) +OP00_LBL(ELSE) +OP00(ENDIF) +OP10(ENDFOR) +OP00(ENDREP) +OP01(PUSHA) +OP10(POPA) +OP11(CEIL) +OP11(I2F) +OP11(NOT) +OP11(TRUNC) +OP12(SHL) +OP12(SHR) +OP12(AND) +OP12(OR) +OP12(MOD) +OP12(XOR) +OP13(SAD) +OP12_TEX(TXF) +OP12_TEX(TXQ) +OP00(CONT) +OP00(EMIT) +OP00(ENDPRIM) +OP00_LBL(BGNLOOP) +OP00(BGNSUB) +OP00_LBL(ENDLOOP) +OP00(ENDSUB) +OP11(NOISE1) +OP11(NOISE2) +OP11(NOISE3) +OP11(NOISE4) +OP00(NOP) +OP11(NRM4) +OP01(CALLNZ) +OP01(IFC) +OP01(BREAKC) +OP01(KIL) +OP00(END) +OP11(SWZ) + + +#undef OP00 +#undef OP01 +#undef OP10 +#undef OP11 +#undef OP12 +#undef OP13 + +#ifdef OP14 +#undef OP14 +#endif + +#undef OP00_LBL +#undef OP01_LBL + +#undef OP12_TEX +#undef OP14_TEX + diff --git a/src/gallium/auxiliary/tgsi/tgsi_ppc.c b/src/gallium/auxiliary/tgsi/tgsi_ppc.c index 8fa21f6c40..2d6ad12ffb 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_ppc.c +++ b/src/gallium/auxiliary/tgsi/tgsi_ppc.c @@ -38,6 +38,7 @@ #include "util/u_math.h" #include "util/u_memory.h" #include "util/u_sse.h" +#include "tgsi/tgsi_info.h" #include "tgsi/tgsi_parse.h" #include "tgsi/tgsi_util.h" #include "tgsi_dump.h" @@ -1317,8 +1318,10 @@ tgsi_emit_ppc(const struct tgsi_token *tokens, ok = emit_instruction(&gen, &parse.FullToken.FullInstruction); if (!ok) { - debug_printf("failed to translate tgsi opcode %d to PPC (%s)\n", - parse.FullToken.FullInstruction.Instruction.Opcode, + uint opcode = parse.FullToken.FullInstruction.Instruction.Opcode; + debug_printf("failed to translate tgsi opcode %d (%s) to PPC (%s)\n", + opcode, + tgsi_get_opcode_name(opcode), parse.FullHeader.Processor.Processor == TGSI_PROCESSOR_VERTEX ? "vertex shader" : "fragment shader"); } diff --git a/src/gallium/auxiliary/tgsi/tgsi_sse2.c b/src/gallium/auxiliary/tgsi/tgsi_sse2.c index 52186770e6..cfec5cfc01 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_sse2.c +++ b/src/gallium/auxiliary/tgsi/tgsi_sse2.c @@ -36,6 +36,7 @@ #if defined(PIPE_ARCH_SSE) #include "util/u_sse.h" #endif +#include "tgsi/tgsi_info.h" #include "tgsi/tgsi_parse.h" #include "tgsi/tgsi_util.h" #include "tgsi_exec.h" @@ -2917,8 +2918,10 @@ tgsi_emit_sse2( &parse.FullToken.FullInstruction ); if (!ok) { - debug_printf("failed to translate tgsi opcode %d to SSE (%s)\n", - parse.FullToken.FullInstruction.Instruction.Opcode, + uint opcode = parse.FullToken.FullInstruction.Instruction.Opcode; + debug_printf("failed to translate tgsi opcode %d (%s) to SSE (%s)\n", + opcode, + tgsi_get_opcode_name(opcode), parse.FullHeader.Processor.Processor == TGSI_PROCESSOR_VERTEX ? "vertex shader" : "fragment shader"); } diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.c b/src/gallium/auxiliary/tgsi/tgsi_ureg.c new file mode 100644 index 0000000000..ba84a82b2b --- /dev/null +++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.c @@ -0,0 +1,797 @@ +/************************************************************************** + * + * Copyright 2009 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 VMWARE, INC 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 "pipe/p_context.h" +#include "pipe/p_state.h" +#include "tgsi/tgsi_ureg.h" +#include "tgsi/tgsi_dump.h" +#include "util/u_memory.h" + +union tgsi_any_token { + struct tgsi_version version; + struct tgsi_header header; + struct tgsi_processor processor; + struct tgsi_token token; + struct tgsi_declaration decl; + struct tgsi_declaration_range decl_range; + struct tgsi_declaration_semantic decl_semantic; + struct tgsi_immediate imm; + union tgsi_immediate_data imm_data; + struct tgsi_instruction insn; + struct tgsi_instruction_ext_nv insn_ext_nv; + struct tgsi_instruction_ext_label insn_ext_label; + struct tgsi_instruction_ext_texture insn_ext_texture; + struct tgsi_instruction_ext_predicate insn_ext_predicate; + struct tgsi_src_register src; + struct tgsi_src_register_ext_swz src_ext_swz; + struct tgsi_src_register_ext_mod src_ext_mod; + struct tgsi_dimension dim; + struct tgsi_dst_register dst; + struct tgsi_dst_register_ext_concode dst_ext_code; + struct tgsi_dst_register_ext_modulate dst_ext_mod; + struct tgsi_dst_register_ext_predicate dst_ext_pred; + unsigned value; +}; + + +struct ureg_tokens { + union tgsi_any_token *tokens; + unsigned size; + unsigned order; + unsigned count; +}; + +#define UREG_MAX_INPUT PIPE_MAX_ATTRIBS +#define UREG_MAX_OUTPUT PIPE_MAX_ATTRIBS +#define UREG_MAX_IMMEDIATE 32 +#define UREG_MAX_TEMP 256 + +#define DOMAIN_DECL 0 +#define DOMAIN_INSN 1 + +struct ureg_program +{ + unsigned processor; + struct pipe_context *pipe; + + struct { + unsigned semantic_name; + unsigned semantic_index; + unsigned interp; + } input[UREG_MAX_INPUT]; + unsigned nr_inputs; + + struct { + unsigned semantic_name; + unsigned semantic_index; + } output[UREG_MAX_OUTPUT]; + unsigned nr_outputs; + + struct { + float v[4]; + unsigned nr; + } immediate[UREG_MAX_IMMEDIATE]; + unsigned nr_immediates; + + unsigned temps_active[UREG_MAX_TEMP / 32]; + unsigned nr_temps; + + unsigned nr_constants; + unsigned nr_samplers; + + struct ureg_tokens domain[2]; +}; + +static union tgsi_any_token error_tokens[32]; + +static void tokens_error( struct ureg_tokens *tokens ) +{ + tokens->tokens = error_tokens; + tokens->size = Elements(error_tokens); + tokens->count = 0; +} + + +static void tokens_expand( struct ureg_tokens *tokens, + unsigned count ) +{ + unsigned old_size = tokens->size * sizeof(unsigned); + + if (tokens->tokens == error_tokens) + goto fail; + + while (tokens->count + count > tokens->size) { + tokens->size = (1 << ++tokens->order); + } + + tokens->tokens = REALLOC(tokens->tokens, + old_size, + tokens->size * sizeof(unsigned)); + if (tokens->tokens == NULL) + goto fail; + + return; + +fail: + tokens_error(tokens); +} + +static void set_bad( struct ureg_program *ureg ) +{ + tokens_error(&ureg->domain[0]); +} + + + +static union tgsi_any_token *get_tokens( struct ureg_program *ureg, + unsigned domain, + unsigned count ) +{ + struct ureg_tokens *tokens = &ureg->domain[domain]; + union tgsi_any_token *result; + + if (tokens->count + count > tokens->size) + tokens_expand(tokens, count); + + result = &tokens->tokens[tokens->count]; + tokens->count += count; + return result; +} + + +static union tgsi_any_token *retrieve_token( struct ureg_program *ureg, + unsigned domain, + unsigned nr ) +{ + if (ureg->domain[domain].tokens == error_tokens) + return &error_tokens[0]; + + return &ureg->domain[domain].tokens[nr]; +} + + + +static INLINE struct ureg_dst +ureg_dst_register( unsigned file, + unsigned index ) +{ + struct ureg_dst dst; + + dst.File = file; + dst.WriteMask = TGSI_WRITEMASK_XYZW; + dst.Indirect = 0; + dst.Saturate = 0; + dst.Index = index; + dst.Pad1 = 0; + dst.Pad2 = 0; + + return dst; +} + +static INLINE struct ureg_src +ureg_src_register( unsigned file, + unsigned index ) +{ + struct ureg_src src; + + src.File = file; + src.SwizzleX = TGSI_SWIZZLE_X; + src.SwizzleY = TGSI_SWIZZLE_Y; + src.SwizzleZ = TGSI_SWIZZLE_Z; + src.SwizzleW = TGSI_SWIZZLE_W; + src.Pad = 0; + src.Indirect = 0; + src.Absolute = 0; + src.Index = index; + src.Negate = 0; + + return src; +} + + + + +static struct ureg_src +ureg_DECL_input( struct ureg_program *ureg, + unsigned name, + unsigned index, + unsigned interp_mode ) +{ + unsigned i; + + for (i = 0; i < ureg->nr_inputs; i++) { + if (ureg->input[i].semantic_name == name && + ureg->input[i].semantic_index == index) + goto out; + } + + if (ureg->nr_inputs < UREG_MAX_INPUT) { + ureg->input[i].semantic_name = name; + ureg->input[i].semantic_index = index; + ureg->input[i].interp = interp_mode; + ureg->nr_inputs++; + } + else { + set_bad( ureg ); + } + +out: + return ureg_src_register( TGSI_FILE_INPUT, i ); +} + + + +struct ureg_src +ureg_DECL_fs_input( struct ureg_program *ureg, + unsigned name, + unsigned index, + unsigned interp ) +{ + return ureg_DECL_input( ureg, name, index, interp ); +} + + +struct ureg_src +ureg_DECL_vs_input( struct ureg_program *ureg, + unsigned name, + unsigned index ) +{ + return ureg_DECL_input( ureg, name, index, TGSI_INTERPOLATE_CONSTANT ); +} + + +struct ureg_dst +ureg_DECL_output( struct ureg_program *ureg, + unsigned name, + unsigned index ) +{ + unsigned i; + + for (i = 0; i < ureg->nr_outputs; i++) { + if (ureg->output[i].semantic_name == name && + ureg->output[i].semantic_index == index) + goto out; + } + + if (ureg->nr_outputs < UREG_MAX_OUTPUT) { + ureg->output[i].semantic_name = name; + ureg->output[i].semantic_index = index; + ureg->nr_outputs++; + } + else { + set_bad( ureg ); + } + +out: + return ureg_dst_register( TGSI_FILE_OUTPUT, i ); +} + + +/* Returns a new constant register. Keep track of which have been + * referred to so that we can emit decls later. + * + * There is nothing in this code to bind this constant to any tracked + * value or manage any constant_buffer contents -- that's the + * resposibility of the calling code. + */ +struct ureg_src ureg_DECL_constant(struct ureg_program *ureg ) +{ + return ureg_src_register( TGSI_FILE_TEMPORARY, ureg->nr_constants++ ); +} + + +/* Allocate a new temporary. Temporaries greater than UREG_MAX_TEMP + * are legal, but will not be released. + */ +struct ureg_dst ureg_DECL_temporary( struct ureg_program *ureg ) +{ + unsigned i; + + for (i = 0; i < UREG_MAX_TEMP; i += 32) { + int bit = ffs(~ureg->temps_active[i/32]); + if (bit != 0) { + i += bit - 1; + goto out; + } + } + + /* No reusable temps, so allocate a new one: + */ + i = ureg->nr_temps++; + +out: + if (i < UREG_MAX_TEMP) + ureg->temps_active[i/32] |= 1 << (i % 32); + + if (i >= ureg->nr_temps) + ureg->nr_temps = i + 1; + + return ureg_dst_register( TGSI_FILE_TEMPORARY, i ); +} + + +void ureg_release_temporary( struct ureg_program *ureg, + struct ureg_dst tmp ) +{ + if (tmp.Index < UREG_MAX_TEMP) + ureg->temps_active[tmp.Index/32] &= ~(1 << (tmp.Index % 32)); +} + + +/* Allocate a new sampler. + */ +struct ureg_src ureg_DECL_sampler( struct ureg_program *ureg ) +{ + return ureg_src_register( TGSI_FILE_SAMPLER, ureg->nr_samplers++ ); +} + + + + +static int match_or_expand_immediate( const float *v, + unsigned nr, + float *v2, + unsigned *nr2, + unsigned *swizzle ) +{ + unsigned i, j; + + for (i = 0; i < nr; i++) { + boolean found = FALSE; + + for (j = 0; j < *nr2 && !found; j++) { + if (v[i] == v2[j]) { + *swizzle |= j << (i * 2); + found = TRUE; + } + } + + if (!found) { + if (*nr2 >= 4) + return FALSE; + + v2[*nr2] = v[i]; + *swizzle |= *nr2 << (i * 2); + (*nr2)++; + } + } + + return TRUE; +} + + + + +struct ureg_src ureg_DECL_immediate( struct ureg_program *ureg, + const float *v, + unsigned nr ) +{ + unsigned i; + unsigned swizzle; + + /* Could do a first pass where we examine all existing immediates + * without expanding. + */ + + for (i = 0; i < ureg->nr_immediates; i++) { + if (match_or_expand_immediate( v, + nr, + ureg->immediate[i].v, + &ureg->immediate[i].nr, + &swizzle )) + goto out; + } + + if (ureg->nr_immediates < UREG_MAX_IMMEDIATE) { + i = ureg->nr_immediates++; + if (match_or_expand_immediate( v, + nr, + ureg->immediate[i].v, + &ureg->immediate[i].nr, + &swizzle )) + goto out; + } + + set_bad( ureg ); + +out: + return ureg_swizzle( ureg_src_register( TGSI_FILE_IMMEDIATE, i ), + (swizzle >> 0) & 0x3, + (swizzle >> 2) & 0x3, + (swizzle >> 4) & 0x3, + (swizzle >> 6) & 0x3); +} + + +void +ureg_emit_src( struct ureg_program *ureg, + struct ureg_src src ) +{ + unsigned size = (1 + + (src.Absolute ? 1 : 0) + + (src.Indirect ? 1 : 0)); + + union tgsi_any_token *out = get_tokens( ureg, DOMAIN_INSN, size ); + unsigned n = 0; + + out[n].value = 0; + out[n].src.File = src.File; + out[n].src.SwizzleX = src.SwizzleX; + out[n].src.SwizzleY = src.SwizzleY; + out[n].src.SwizzleZ = src.SwizzleZ; + out[n].src.SwizzleW = src.SwizzleW; + out[n].src.Indirect = src.Indirect; + out[n].src.Index = src.Index; + n++; + + if (src.Absolute) { + out[n].value = 0; + out[n].src_ext_mod.Absolute = 1; + n++; + } + + if (src.Indirect) { + out[n].value = 0; + out[n].src.File = TGSI_FILE_ADDRESS; + out[n].src.SwizzleX = TGSI_SWIZZLE_X; + out[n].src.SwizzleY = TGSI_SWIZZLE_X; + out[n].src.SwizzleZ = TGSI_SWIZZLE_X; + out[n].src.SwizzleW = TGSI_SWIZZLE_X; + out[n].src.Indirect = 0; + out[n].src.Index = 0; + n++; + } + + assert(n == size); +} + + +void +ureg_emit_dst( struct ureg_program *ureg, + struct ureg_dst dst ) +{ + unsigned size = (1 + + (dst.Indirect ? 1 : 0)); + + union tgsi_any_token *out = get_tokens( ureg, DOMAIN_INSN, size ); + unsigned n = 0; + + out[n].value = 0; + out[n].dst.File = dst.File; + out[n].dst.WriteMask = dst.WriteMask; + out[n].dst.Indirect = dst.Indirect; + out[n].dst.Index = dst.Index; + n++; + + if (dst.Indirect) { + out[n].value = 0; + out[n].src.File = TGSI_FILE_ADDRESS; + out[n].src.SwizzleX = TGSI_SWIZZLE_X; + out[n].src.SwizzleY = TGSI_SWIZZLE_X; + out[n].src.SwizzleZ = TGSI_SWIZZLE_X; + out[n].src.SwizzleW = TGSI_SWIZZLE_X; + out[n].src.Indirect = 0; + out[n].src.Index = 0; + n++; + } + + assert(n == size); +} + + + +unsigned +ureg_emit_insn(struct ureg_program *ureg, + unsigned opcode, + boolean saturate, + unsigned num_dst, + unsigned num_src ) +{ + union tgsi_any_token *out; + + out = get_tokens( ureg, DOMAIN_INSN, 1 ); + out[0].value = 0; + out[0].insn.Type = TGSI_TOKEN_TYPE_INSTRUCTION; + out[0].insn.NrTokens = 0; + out[0].insn.Opcode = opcode; + out[0].insn.Saturate = saturate; + out[0].insn.NrTokens = 0; + out[0].insn.NumDstRegs = num_dst; + out[0].insn.NumSrcRegs = num_src; + out[0].insn.Padding = 0; + out[0].insn.Extended = 0; + + return ureg->domain[DOMAIN_INSN].count - 1; +} + + +void +ureg_emit_label(struct ureg_program *ureg, + unsigned insn_token, + unsigned *label_token ) +{ + union tgsi_any_token *out, *insn; + + out = get_tokens( ureg, DOMAIN_INSN, 1 ); + insn = retrieve_token( ureg, DOMAIN_INSN, insn_token ); + + insn->insn.Extended = 1; + + out[0].value = 0; + out[0].insn_ext_label.Type = TGSI_INSTRUCTION_EXT_TYPE_LABEL; +} + + +void +ureg_emit_texture(struct ureg_program *ureg, + unsigned insn_token, + unsigned target ) +{ + union tgsi_any_token *out, *insn; + + out = get_tokens( ureg, DOMAIN_INSN, 1 ); + insn = retrieve_token( ureg, DOMAIN_INSN, insn_token ); + + insn->insn.Extended = 1; + + out[0].value = 0; + out[0].insn_ext_texture.Type = TGSI_INSTRUCTION_EXT_TYPE_TEXTURE; + out[0].insn_ext_texture.Texture = target; +} + + +void +ureg_fixup_insn_size(struct ureg_program *ureg, + unsigned insn ) +{ + union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_INSN, insn ); + + out->insn.NrTokens = ureg->domain[DOMAIN_INSN].count - insn - 1; +} + + + + + +static void emit_decl( struct ureg_program *ureg, + unsigned file, + unsigned index, + unsigned semantic_name, + unsigned semantic_index, + unsigned interp ) +{ + union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 3 ); + + out[0].value = 0; + out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION; + out[0].decl.NrTokens = 3; + out[0].decl.File = file; + out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW; /* FIXME! */ + out[0].decl.Interpolate = interp; + out[0].decl.Semantic = 1; + + out[1].value = 0; + out[1].decl_range.First = + out[1].decl_range.Last = index; + + out[2].value = 0; + out[2].decl_semantic.SemanticName = semantic_name; + out[2].decl_semantic.SemanticIndex = semantic_index; + +} + + +static void emit_decl_range( struct ureg_program *ureg, + unsigned file, + unsigned first, + unsigned count ) +{ + union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 2 ); + + out[0].value = 0; + out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION; + out[0].decl.NrTokens = 2; + out[0].decl.File = file; + out[0].decl.UsageMask = 0xf; + out[0].decl.Interpolate = TGSI_INTERPOLATE_CONSTANT; + out[0].decl.Semantic = 0; + + out[1].value = 0; + out[1].decl_range.First = first; + out[1].decl_range.Last = first + count - 1; +} + +static void emit_immediate( struct ureg_program *ureg, + const float *v ) +{ + union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 5 ); + + out[0].value = 0; + out[0].imm.Type = TGSI_TOKEN_TYPE_IMMEDIATE; + out[0].imm.NrTokens = 5; + out[0].imm.DataType = TGSI_IMM_FLOAT32; + out[0].imm.Padding = 0; + out[0].imm.Extended = 0; + + out[1].imm_data.Float = v[0]; + out[2].imm_data.Float = v[1]; + out[3].imm_data.Float = v[2]; + out[4].imm_data.Float = v[3]; +} + + + + +static void emit_decls( struct ureg_program *ureg ) +{ + unsigned i; + + for (i = 0; i < ureg->nr_inputs; i++) { + emit_decl( ureg, + TGSI_FILE_INPUT, + i, + ureg->input[i].semantic_name, + ureg->input[i].semantic_index, + ureg->input[i].interp ); + } + + for (i = 0; i < ureg->nr_outputs; i++) { + emit_decl( ureg, + TGSI_FILE_OUTPUT, + i, + ureg->output[i].semantic_name, + ureg->output[i].semantic_index, + TGSI_INTERPOLATE_CONSTANT ); + } + + if (ureg->nr_samplers) { + emit_decl_range( ureg, + TGSI_FILE_SAMPLER, + 0, ureg->nr_samplers ); + } + + if (ureg->nr_constants) { + emit_decl_range( ureg, + TGSI_FILE_CONSTANT, + 0, ureg->nr_constants ); + } + + if (ureg->nr_temps) { + emit_decl_range( ureg, + TGSI_FILE_TEMPORARY, + 0, ureg->nr_temps ); + } + + for (i = 0; i < ureg->nr_immediates; i++) { + emit_immediate( ureg, + ureg->immediate[i].v ); + } +} + +/* Append the instruction tokens onto the declarations to build a + * contiguous stream suitable to send to the driver. + */ +static void copy_instructions( struct ureg_program *ureg ) +{ + unsigned nr_tokens = ureg->domain[DOMAIN_INSN].count; + union tgsi_any_token *out = get_tokens( ureg, + DOMAIN_DECL, + nr_tokens ); + + memcpy(out, + ureg->domain[DOMAIN_INSN].tokens, + nr_tokens * sizeof out[0] ); +} + + +static void +fixup_header_size(struct ureg_program *ureg, + unsigned insn ) +{ + union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_DECL, 1 ); + + out->header.BodySize = ureg->domain[DOMAIN_DECL].count - 3; +} + + +static void +emit_header( struct ureg_program *ureg ) +{ + union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 3 ); + + out[0].version.MajorVersion = 1; + out[0].version.MinorVersion = 1; + out[0].version.Padding = 0; + + out[1].header.HeaderSize = 2; + out[1].header.BodySize = 0; + + out[2].processor.Processor = ureg->processor; + out[2].processor.Padding = 0; +} + + +void *ureg_create_shader( struct ureg_program *ureg ) +{ + struct pipe_shader_state state; + unsigned insn; + + emit_header( ureg ); + emit_decls( ureg ); + copy_instructions( ureg ); + fixup_header_size( ureg, insn ); + + if (ureg->domain[0].tokens == error_tokens || + ureg->domain[1].tokens == error_tokens) { + debug_printf("%s: error in generated shader\n", __FUNCTION__); + assert(0); + return NULL; + } + + state.tokens = (const struct tgsi_token *)ureg->domain[DOMAIN_DECL].tokens; + + if (0) { + debug_printf("%s: emitted shader %d tokens:\n", __FUNCTION__, + ureg->domain[DOMAIN_DECL].count); + tgsi_dump( state.tokens, 0 ); + } + + if (ureg->processor == TGSI_PROCESSOR_VERTEX) + return ureg->pipe->create_vs_state( ureg->pipe, &state ); + else + return ureg->pipe->create_fs_state( ureg->pipe, &state ); +} + + + + +struct ureg_program *ureg_create( struct pipe_context *pipe, + unsigned processor ) +{ + struct ureg_program *ureg = CALLOC_STRUCT( ureg_program ); + if (ureg == NULL) + return NULL; + + ureg->pipe = pipe; + ureg->processor = processor; + return ureg; +} + + +void ureg_destroy( struct ureg_program *ureg ) +{ + unsigned i; + + for (i = 0; i < Elements(ureg->domain); i++) { + if (ureg->domain[i].tokens && + ureg->domain[i].tokens != error_tokens) + FREE(ureg->domain[i].tokens); + } + + FREE(ureg); +} diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.h b/src/gallium/auxiliary/tgsi/tgsi_ureg.h new file mode 100644 index 0000000000..0a976fd63b --- /dev/null +++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.h @@ -0,0 +1,439 @@ +/************************************************************************** + * + * Copyright 2009 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 VMWARE, INC 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 TGSI_UREG_H +#define TGSI_UREG_H + +#include "pipe/p_compiler.h" +#include "pipe/p_shader_tokens.h" + +struct ureg_program; + +/* Almost a tgsi_src_register, but we need to pull in the Absolute + * flag from the _ext token. Indirect flag always implies ADDR[0]. + */ +struct ureg_src +{ + unsigned File : 4; /* TGSI_FILE_ */ + unsigned SwizzleX : 2; /* TGSI_SWIZZLE_ */ + unsigned SwizzleY : 2; /* TGSI_SWIZZLE_ */ + unsigned SwizzleZ : 2; /* TGSI_SWIZZLE_ */ + unsigned SwizzleW : 2; /* TGSI_SWIZZLE_ */ + unsigned Pad : 1; /* BOOL */ + unsigned Indirect : 1; /* BOOL */ + unsigned Absolute : 1; /* BOOL */ + int Index : 16; /* SINT */ + unsigned Negate : 1; /* BOOL */ +}; + +/* Very similar to a tgsi_dst_register, removing unsupported fields + * and adding a Saturate flag. It's easier to push saturate into the + * destination register than to try and create a _SAT varient of each + * instruction function. + */ +struct ureg_dst +{ + unsigned File : 4; /* TGSI_FILE_ */ + unsigned WriteMask : 4; /* TGSI_WRITEMASK_ */ + unsigned Indirect : 1; /* BOOL */ + unsigned Saturate : 1; /* BOOL */ + int Index : 16; /* SINT */ + unsigned Pad1 : 5; + unsigned Pad2 : 1; /* BOOL */ +}; + +struct pipe_context; + +struct ureg_program * +ureg_create( struct pipe_context *pipe, + unsigned processor ); + +void * +ureg_create_shader( struct ureg_program * ); + +void +ureg_destroy( struct ureg_program * ); + + +/*********************************************************************** + * Convenience routine: + */ +static INLINE void *ureg_create_shader_and_destroy( struct ureg_program *p ) +{ + void *result = ureg_create_shader( p ); + ureg_destroy( p ); + return result; +} + + + +/*********************************************************************** + * Build shader declarations: + */ + +struct ureg_src +ureg_DECL_fs_input( struct ureg_program *, + unsigned semantic_name, + unsigned semantic_index, + unsigned interp_mode ); + +struct ureg_src +ureg_DECL_vs_input( struct ureg_program *, + unsigned semantic_name, + unsigned semantic_index ); + +struct ureg_dst +ureg_DECL_output( struct ureg_program *, + unsigned semantic_name, + unsigned semantic_index ); + +struct ureg_src +ureg_DECL_immediate( struct ureg_program *, + const float *v, + unsigned nr ); + +struct ureg_src +ureg_DECL_constant( struct ureg_program * ); + +struct ureg_dst +ureg_DECL_temporary( struct ureg_program * ); + +void +ureg_release_temporary( struct ureg_program *ureg, + struct ureg_dst tmp ); + +struct ureg_src +ureg_DECL_sampler( struct ureg_program * ); + + +static INLINE struct ureg_src +ureg_DECL_immediate4f( struct ureg_program *ureg, + float a, float b, + float c, float d) +{ + float v[4]; + v[0] = a; + v[1] = b; + v[2] = c; + v[3] = d; + return ureg_DECL_immediate( ureg, v, 4 ); +} + +static INLINE struct ureg_src +ureg_DECL_immediate3f( struct ureg_program *ureg, + float a, float b, + float c) +{ + float v[3]; + v[0] = a; + v[1] = b; + v[2] = c; + return ureg_DECL_immediate( ureg, v, 3 ); +} + +static INLINE struct ureg_src +ureg_DECL_immediate2f( struct ureg_program *ureg, + float a, float b) +{ + float v[2]; + v[0] = a; + v[1] = b; + return ureg_DECL_immediate( ureg, v, 2 ); +} + +static INLINE struct ureg_src +ureg_DECL_immediate1f( struct ureg_program *ureg, + float a) +{ + float v[1]; + v[0] = a; + return ureg_DECL_immediate( ureg, v, 1 ); +} + +/*********************************************************************** + * Internal instruction helpers, don't call these directly: + */ + +unsigned +ureg_emit_insn(struct ureg_program *ureg, + unsigned opcode, + boolean saturate, + unsigned num_dst, + unsigned num_src ); + +void +ureg_emit_label(struct ureg_program *ureg, + unsigned insn_token, + unsigned *label_token ); + +void +ureg_emit_texture(struct ureg_program *ureg, + unsigned insn_token, + unsigned target ); + +void +ureg_emit_dst( struct ureg_program *ureg, + struct ureg_dst dst ); + +void +ureg_emit_src( struct ureg_program *ureg, + struct ureg_src src ); + +void +ureg_fixup_insn_size(struct ureg_program *ureg, + unsigned insn ); + + +#define OP00( op ) \ +static INLINE void ureg_##op( struct ureg_program *ureg ) \ +{ \ + unsigned opcode = TGSI_OPCODE_##op; \ + unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 0 ); \ + ureg_fixup_insn_size( ureg, insn ); \ +} + +#define OP01( op ) \ +static INLINE void ureg_##op( struct ureg_program *ureg, \ + struct ureg_src src ) \ +{ \ + unsigned opcode = TGSI_OPCODE_##op; \ + unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 1 ); \ + ureg_emit_src( ureg, src ); \ + ureg_fixup_insn_size( ureg, insn ); \ +} + +#define OP00_LBL( op ) \ +static INLINE void ureg_##op( struct ureg_program *ureg, \ + unsigned *label_token ) \ +{ \ + unsigned opcode = TGSI_OPCODE_##op; \ + unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 0 ); \ + ureg_emit_label( ureg, insn, label_token ); \ + ureg_fixup_insn_size( ureg, insn ); \ +} + +#define OP01_LBL( op ) \ +static INLINE void ureg_##op( struct ureg_program *ureg, \ + struct ureg_src src, \ + unsigned *label_token ) \ +{ \ + unsigned opcode = TGSI_OPCODE_##op; \ + unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 1 ); \ + ureg_emit_label( ureg, insn, label_token ); \ + ureg_emit_src( ureg, src ); \ + ureg_fixup_insn_size( ureg, insn ); \ +} + +#define OP10( op ) \ +static INLINE void ureg_##op( struct ureg_program *ureg, \ + struct ureg_dst dst ) \ +{ \ + unsigned opcode = TGSI_OPCODE_##op; \ + unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 0 ); \ + ureg_emit_dst( ureg, dst ); \ + ureg_fixup_insn_size( ureg, insn ); \ +} + + +#define OP11( op ) \ +static INLINE void ureg_##op( struct ureg_program *ureg, \ + struct ureg_dst dst, \ + struct ureg_src src ) \ +{ \ + unsigned opcode = TGSI_OPCODE_##op; \ + unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 1 ); \ + ureg_emit_dst( ureg, dst ); \ + ureg_emit_src( ureg, src ); \ + ureg_fixup_insn_size( ureg, insn ); \ +} + +#define OP12( op ) \ +static INLINE void ureg_##op( struct ureg_program *ureg, \ + struct ureg_dst dst, \ + struct ureg_src src0, \ + struct ureg_src src1 ) \ +{ \ + unsigned opcode = TGSI_OPCODE_##op; \ + unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 2 ); \ + ureg_emit_dst( ureg, dst ); \ + ureg_emit_src( ureg, src0 ); \ + ureg_emit_src( ureg, src1 ); \ + ureg_fixup_insn_size( ureg, insn ); \ +} + +#define OP12_TEX( op ) \ +static INLINE void ureg_##op( struct ureg_program *ureg, \ + struct ureg_dst dst, \ + unsigned target, \ + struct ureg_src src0, \ + struct ureg_src src1 ) \ +{ \ + unsigned opcode = TGSI_OPCODE_##op; \ + unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 2 ); \ + ureg_emit_texture( ureg, insn, target ); \ + ureg_emit_dst( ureg, dst ); \ + ureg_emit_src( ureg, src0 ); \ + ureg_emit_src( ureg, src1 ); \ + ureg_fixup_insn_size( ureg, insn ); \ +} + +#define OP13( op ) \ +static INLINE void ureg_##op( struct ureg_program *ureg, \ + struct ureg_dst dst, \ + struct ureg_src src0, \ + struct ureg_src src1, \ + struct ureg_src src2 ) \ +{ \ + unsigned opcode = TGSI_OPCODE_##op; \ + unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 3 ); \ + ureg_emit_dst( ureg, dst ); \ + ureg_emit_src( ureg, src0 ); \ + ureg_emit_src( ureg, src1 ); \ + ureg_emit_src( ureg, src2 ); \ + ureg_fixup_insn_size( ureg, insn ); \ +} + +#define OP14_TEX( op ) \ +static INLINE void ureg_##op( struct ureg_program *ureg, \ + struct ureg_dst dst, \ + unsigned target, \ + struct ureg_src src0, \ + struct ureg_src src1, \ + struct ureg_src src2, \ + struct ureg_src src3 ) \ +{ \ + unsigned opcode = TGSI_OPCODE_##op; \ + unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 4 ); \ + ureg_emit_texture( ureg, insn, target ); \ + ureg_emit_dst( ureg, dst ); \ + ureg_emit_src( ureg, src0 ); \ + ureg_emit_src( ureg, src1 ); \ + ureg_emit_src( ureg, src2 ); \ + ureg_emit_src( ureg, src3 ); \ + ureg_fixup_insn_size( ureg, insn ); \ +} + + +/* Use a template include to generate a correctly-typed ureg_OP() + * function for each TGSI opcode: + */ +#include "tgsi_opcode_tmp.h" + + +/*********************************************************************** + * Inline helpers for manipulating register structs: + */ +static INLINE struct ureg_src +ureg_negate( struct ureg_src reg ) +{ + reg.Negate ^= 1; + return reg; +} + +static INLINE struct ureg_src +ureg_abs( struct ureg_src reg ) +{ + reg.Absolute = 1; + reg.Negate = 0; + return reg; +} + +static INLINE struct ureg_src +ureg_swizzle( struct ureg_src reg, + int x, int y, int z, int w ) +{ + unsigned swz = ( (reg.SwizzleX << 0) | + (reg.SwizzleY << 2) | + (reg.SwizzleZ << 4) | + (reg.SwizzleW << 6)); + + reg.SwizzleX = (swz >> (x*2)) & 0x3; + reg.SwizzleY = (swz >> (y*2)) & 0x3; + reg.SwizzleZ = (swz >> (z*2)) & 0x3; + reg.SwizzleW = (swz >> (w*2)) & 0x3; + return reg; +} + +static INLINE struct ureg_src +ureg_scalar( struct ureg_src reg, int x ) +{ + return ureg_swizzle(reg, x, x, x, x); +} + +static INLINE struct ureg_dst +ureg_writemask( struct ureg_dst reg, + unsigned writemask ) +{ + reg.WriteMask &= writemask; + return reg; +} + +static INLINE struct ureg_dst +ureg_saturate( struct ureg_dst reg ) +{ + reg.Saturate = 1; + return reg; +} + +static INLINE struct ureg_dst +ureg_dst( struct ureg_src src ) +{ + struct ureg_dst dst; + + dst.File = src.File; + dst.WriteMask = TGSI_WRITEMASK_XYZW; + dst.Indirect = src.Indirect; + dst.Saturate = 0; + dst.Index = src.Index; + dst.Pad1 = 0; + dst.Pad2 = 0; + + return dst; +} + +static INLINE struct ureg_src +ureg_src( struct ureg_dst dst ) +{ + struct ureg_src src; + + src.File = dst.File; + src.SwizzleX = TGSI_SWIZZLE_X; + src.SwizzleY = TGSI_SWIZZLE_Y; + src.SwizzleZ = TGSI_SWIZZLE_Z; + src.SwizzleW = TGSI_SWIZZLE_W; + src.Pad = 0; + src.Indirect = dst.Indirect; + src.Absolute = 0; + src.Index = dst.Index; + src.Negate = 0; + + return src; +} + + + +#endif diff --git a/src/gallium/auxiliary/util/u_blit.c b/src/gallium/auxiliary/util/u_blit.c index 414cf91025..cda6dbd46d 100644 --- a/src/gallium/auxiliary/util/u_blit.c +++ b/src/gallium/auxiliary/util/u_blit.c @@ -45,6 +45,7 @@ #include "util/u_math.h" #include "util/u_memory.h" #include "util/u_simple_shaders.h" +#include "util/u_surface.h" #include "cso_cache/cso_context.h" @@ -155,7 +156,11 @@ util_destroy_blit(struct blit_state *ctx) } -static unsigned get_next_slot( struct blit_state *ctx ) +/** + * Get offset of next free slot in vertex buffer for quad vertices. + */ +static unsigned +get_next_slot( struct blit_state *ctx ) { const unsigned max_slots = 4096 / sizeof ctx->vertices; @@ -173,7 +178,6 @@ static unsigned get_next_slot( struct blit_state *ctx ) } - /** * Setup vertex data for the textured quad we'll draw. * Note: y=0=top @@ -260,9 +264,38 @@ setup_vertex_data_tex(struct blit_state *ctx, return offset; } + + +/** + * \return TRUE if two regions overlap, FALSE otherwise + */ +static boolean +regions_overlap(int srcX0, int srcY0, + int srcX1, int srcY1, + int dstX0, int dstY0, + int dstX1, int dstY1) +{ + if (MAX2(srcX0, srcX1) < MIN2(dstX0, dstX1)) + return FALSE; /* src completely left of dst */ + + if (MAX2(dstX0, dstX1) < MIN2(srcX0, srcX1)) + return FALSE; /* dst completely left of src */ + + if (MAX2(srcY0, srcY1) < MIN2(dstY0, dstY1)) + return FALSE; /* src completely above dst */ + + if (MAX2(dstY0, dstY1) < MIN2(srcY0, srcY1)) + return FALSE; /* dst completely above src */ + + return TRUE; /* some overlap */ +} + + /** * Copy pixel block from src surface to dst surface. * Overlapping regions are acceptable. + * Flipping and stretching are supported. + * XXX what about clipping??? * XXX need some control over blitting Z and/or stencil. */ void @@ -285,10 +318,41 @@ util_blit_pixels(struct blit_state *ctx, const int srcLeft = MIN2(srcX0, srcX1); const int srcTop = MIN2(srcY0, srcY1); unsigned offset; + boolean overlap; assert(filter == PIPE_TEX_MIPFILTER_NEAREST || filter == PIPE_TEX_MIPFILTER_LINEAR); + assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D, + PIPE_TEXTURE_USAGE_SAMPLER, 0)); + assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D, + PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)); + + /* do the regions overlap? */ + overlap = util_same_surface(src, dst) && + regions_overlap(srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1); + + /* + * Check for simple case: no format conversion, no flipping, no stretching, + * no overlapping. + * Filter mode should not matter since there's no stretching. + */ + if (dst->format == src->format && + srcX0 < srcX1 && + dstX0 < dstX1 && + srcY0 < srcY1 && + dstY0 < dstY1 && + (dstX1 - dstX0) == (srcX1 - srcX0) && + (dstY1 - dstY0) == (srcY1 - srcY0) && + !overlap) { + pipe->surface_copy(pipe, + dst, dstX0, dstY0, /* dest */ + src, srcX0, srcY0, /* src */ + srcW, srcH); /* size */ + return; + } + if (srcLeft != srcX0) { /* left-right flip */ int tmp = dstX0; @@ -303,20 +367,6 @@ util_blit_pixels(struct blit_state *ctx, dstY1 = tmp; } - assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_SAMPLER, 0)); - assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_SAMPLER, 0)); - - if(dst->format == src->format && (dstX1 - dstX0) == srcW && (dstY1 - dstY0) == srcH) { - /* FIXME: this will most surely fail for overlapping rectangles */ - pipe->surface_copy(pipe, - dst, dstX0, dstY0, /* dest */ - src, srcX0, srcY0, /* src */ - srcW, srcH); /* size */ - return; - } - assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)); diff --git a/src/gallium/auxiliary/util/u_gen_mipmap.c b/src/gallium/auxiliary/util/u_gen_mipmap.c index ca797486a0..edc37561ab 100644 --- a/src/gallium/auxiliary/util/u_gen_mipmap.c +++ b/src/gallium/auxiliary/util/u_gen_mipmap.c @@ -46,10 +46,6 @@ #include "util/u_gen_mipmap.h" #include "util/u_simple_shaders.h" -#include "tgsi/tgsi_build.h" -#include "tgsi/tgsi_dump.h" -#include "tgsi/tgsi_parse.h" - #include "cso_cache/cso_context.h" diff --git a/src/gallium/auxiliary/util/u_math.h b/src/gallium/auxiliary/util/u_math.h index 30e6e2f6b3..57410e78b0 100644 --- a/src/gallium/auxiliary/util/u_math.h +++ b/src/gallium/auxiliary/util/u_math.h @@ -53,11 +53,11 @@ __inline double ceil(double val) { double ceil_val; - if((val - (long) val) == 0) { + if ((val - (long) val) == 0) { ceil_val = val; } else { - if(val > 0) { + if (val > 0) { ceil_val = (long) val + 1; } else { @@ -73,11 +73,11 @@ __inline double floor(double val) { double floor_val; - if((val - (long) val) == 0) { + if ((val - (long) val) == 0) { floor_val = val; } else { - if(val > 0) { + if (val > 0) { floor_val = (long) val; } else { @@ -189,7 +189,10 @@ static INLINE double log2( double x ) extern float pow2_table[POW2_TABLE_SIZE]; - +/** + * Initialize math module. This should be called before using any + * other functions in this module. + */ extern void util_init_math(void); @@ -220,7 +223,7 @@ util_fast_exp2(float x) if(x > 129.00000f) return 3.402823466e+38f; - if(x < -126.99999f) + if (x < -126.99999f) return 0.0f; ipart = (int32_t) x; @@ -228,7 +231,8 @@ util_fast_exp2(float x) /* same as * epart.f = (float) (1 << ipart) - * but faster and without integer overflow for ipart > 31 */ + * but faster and without integer overflow for ipart > 31 + */ epart.i = (ipart + 127 ) << 23; mpart = pow2_table[POW2_TABLE_OFFSET + (int)(fpart * POW2_TABLE_SCALE)]; @@ -254,6 +258,9 @@ util_fast_exp(float x) extern float log2_table[LOG2_TABLE_SIZE]; +/** + * Fast approximation to log2(x). + */ static INLINE float util_fast_log2(float x) { @@ -267,6 +274,9 @@ util_fast_log2(float x) } +/** + * Fast approximation to x^y. + */ static INLINE float util_fast_pow(float x, float y) { @@ -274,7 +284,6 @@ util_fast_pow(float x, float y) } - /** * Floor(x), returned as int. */ @@ -284,8 +293,8 @@ util_ifloor(float f) int ai, bi; double af, bf; union fi u; - af = (3 << 22) + 0.5 + (double)f; - bf = (3 << 22) + 0.5 - (double)f; + af = (3 << 22) + 0.5 + (double) f; + bf = (3 << 22) + 0.5 - (double) f; u.f = (float) af; ai = u.i; u.f = (float) bf; bi = u.i; return (ai - bi) >> 1; @@ -305,9 +314,9 @@ util_iround(float f) #elif defined(PIPE_CC_MSVC) && defined(PIPE_ARCH_X86) int r; _asm { - fld f - fistp r - } + fld f + fistp r + } return r; #else if (f >= 0.0f) @@ -340,7 +349,7 @@ static INLINE unsigned long ffs( unsigned long u ) { unsigned long i; - if(_BitScanForward(&i, u)) + if (_BitScanForward(&i, u)) return i + 1; else return 0; @@ -351,7 +360,7 @@ unsigned ffs( unsigned u ) { unsigned i; - if( u == 0 ) { + if (u == 0) { return 0; } @@ -378,7 +387,10 @@ fui( float f ) } - +/** + * Convert ubyte to float in [0, 1]. + * XXX a 256-entry lookup table would be slightly faster. + */ static INLINE float ubyte_to_float(ubyte ub) { @@ -422,7 +434,10 @@ util_logbase2(unsigned n) } - +/** + * Clamp X to [MIN, MAX]. + * This is a macro to allow float, int, uint, etc. types. + */ #define CLAMP( X, MIN, MAX ) ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) ) #define MIN2( A, B ) ( (A)<(B) ? (A) : (B) ) @@ -435,6 +450,11 @@ align(int value, int alignment) return (value + alignment - 1) & ~(alignment - 1); } +static INLINE unsigned +minify(unsigned value) +{ + return MAX2(1, value >> 1); +} #ifndef COPY_4V #define COPY_4V( DST, SRC ) \ diff --git a/src/gallium/auxiliary/util/u_memory.h b/src/gallium/auxiliary/util/u_memory.h index 0b18d043ad..c3f8c91833 100644 --- a/src/gallium/auxiliary/util/u_memory.h +++ b/src/gallium/auxiliary/util/u_memory.h @@ -100,8 +100,14 @@ ExFreePool(void *P); #define MALLOC( SIZE ) malloc( SIZE ) #define CALLOC( COUNT, SIZE ) calloc( COUNT, SIZE ) #define FREE( PTR ) free( PTR ) -#define REALLOC( OLDPTR, OLDSIZE, NEWSIZE ) realloc( OLDPTR, NEWSIZE ) +static INLINE void * +_REALLOC( void *old_ptr, unsigned old_size, unsigned new_size ) +{ + (void) old_size; + return realloc(old_ptr, new_size); +} +#define REALLOC( a, b, c ) _REALLOC( a, b, c ) #endif diff --git a/src/gallium/auxiliary/util/u_simple_screen.c b/src/gallium/auxiliary/util/u_simple_screen.c index 8114b53cd0..f01296b40f 100644 --- a/src/gallium/auxiliary/util/u_simple_screen.c +++ b/src/gallium/auxiliary/util/u_simple_screen.c @@ -65,12 +65,13 @@ pass_surface_buffer_create(struct pipe_screen *screen, unsigned width, unsigned height, enum pipe_format format, unsigned usage, + unsigned tex_usage, unsigned *stride) { struct pipe_buffer *buffer = screen->winsys->surface_buffer_create(screen->winsys, width, height, - format, usage, stride); + format, usage, tex_usage, stride); buffer->screen = screen; diff --git a/src/gallium/auxiliary/util/u_simple_shaders.c b/src/gallium/auxiliary/util/u_simple_shaders.c index e519c354d2..1152d62e73 100644 --- a/src/gallium/auxiliary/util/u_simple_shaders.c +++ b/src/gallium/auxiliary/util/u_simple_shaders.c @@ -42,9 +42,7 @@ #include "util/u_memory.h" #include "util/u_simple_shaders.h" -#include "tgsi/tgsi_build.h" -#include "tgsi/tgsi_dump.h" -#include "tgsi/tgsi_parse.h" +#include "tgsi/tgsi_ureg.h" @@ -58,93 +56,31 @@ util_make_vertex_passthrough_shader(struct pipe_context *pipe, const uint *semantic_indexes) { - struct pipe_shader_state shader; - struct tgsi_token tokens[100]; - struct tgsi_header *header; - struct tgsi_processor *processor; - struct tgsi_full_declaration decl; - struct tgsi_full_instruction inst; - const uint procType = TGSI_PROCESSOR_VERTEX; - uint ti, i; + struct ureg_program *ureg; + uint i; - /* shader header - */ - *(struct tgsi_version *) &tokens[0] = tgsi_build_version(); + ureg = ureg_create( pipe, TGSI_PROCESSOR_VERTEX ); + if (ureg == NULL) + return NULL; - header = (struct tgsi_header *) &tokens[1]; - *header = tgsi_build_header(); - - processor = (struct tgsi_processor *) &tokens[2]; - *processor = tgsi_build_processor( procType, header ); - - ti = 3; - - /* declare inputs */ - for (i = 0; i < num_attribs; i++) { - decl = tgsi_default_full_declaration(); - decl.Declaration.File = TGSI_FILE_INPUT; - - decl.Declaration.Semantic = 1; - decl.Semantic.SemanticName = semantic_names[i]; - decl.Semantic.SemanticIndex = semantic_indexes[i]; - - decl.DeclarationRange.First = - decl.DeclarationRange.Last = i; - ti += tgsi_build_full_declaration(&decl, - &tokens[ti], - header, - Elements(tokens) - ti); - } - - /* declare outputs */ for (i = 0; i < num_attribs; i++) { - decl = tgsi_default_full_declaration(); - decl.Declaration.File = TGSI_FILE_OUTPUT; - decl.Declaration.Semantic = 1; - decl.Semantic.SemanticName = semantic_names[i]; - decl.Semantic.SemanticIndex = semantic_indexes[i]; - decl.DeclarationRange.First = - decl.DeclarationRange.Last = i; - ti += tgsi_build_full_declaration(&decl, - &tokens[ti], - header, - Elements(tokens) - ti); + struct ureg_src src; + struct ureg_dst dst; + + src = ureg_DECL_vs_input( ureg, + semantic_names[i], + semantic_indexes[i]); + + dst = ureg_DECL_output( ureg, + semantic_names[i], + semantic_indexes[i]); + + ureg_MOV( ureg, dst, src ); } - /* emit MOV instructions */ - for (i = 0; i < num_attribs; i++) { - /* MOVE out[i], in[i]; */ - inst = tgsi_default_full_instruction(); - inst.Instruction.Opcode = TGSI_OPCODE_MOV; - inst.Instruction.NumDstRegs = 1; - inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT; - inst.FullDstRegisters[0].DstRegister.Index = i; - inst.Instruction.NumSrcRegs = 1; - inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT; - inst.FullSrcRegisters[0].SrcRegister.Index = i; - ti += tgsi_build_full_instruction(&inst, - &tokens[ti], - header, - Elements(tokens) - ti ); - } - - /* END instruction */ - inst = tgsi_default_full_instruction(); - inst.Instruction.Opcode = TGSI_OPCODE_END; - inst.Instruction.NumDstRegs = 0; - inst.Instruction.NumSrcRegs = 0; - ti += tgsi_build_full_instruction(&inst, - &tokens[ti], - header, - Elements(tokens) - ti ); - -#if 0 /*debug*/ - tgsi_dump(tokens, 0); -#endif - - shader.tokens = tokens; + ureg_END( ureg ); - return pipe->create_vs_state(pipe, &shader); + return ureg_create_shader_and_destroy( ureg ); } @@ -158,99 +94,29 @@ util_make_vertex_passthrough_shader(struct pipe_context *pipe, void * util_make_fragment_tex_shader(struct pipe_context *pipe) { - struct pipe_shader_state shader; - struct tgsi_token tokens[100]; - struct tgsi_header *header; - struct tgsi_processor *processor; - struct tgsi_full_declaration decl; - struct tgsi_full_instruction inst; - const uint procType = TGSI_PROCESSOR_FRAGMENT; - uint ti; - - /* shader header - */ - *(struct tgsi_version *) &tokens[0] = tgsi_build_version(); - - header = (struct tgsi_header *) &tokens[1]; - *header = tgsi_build_header(); - - processor = (struct tgsi_processor *) &tokens[2]; - *processor = tgsi_build_processor( procType, header ); - - ti = 3; - - /* declare TEX[0] input */ - decl = tgsi_default_full_declaration(); - decl.Declaration.File = TGSI_FILE_INPUT; - /* XXX this could be linear... */ - decl.Declaration.Interpolate = TGSI_INTERPOLATE_PERSPECTIVE; - decl.Declaration.Semantic = 1; - decl.Semantic.SemanticName = TGSI_SEMANTIC_GENERIC; - decl.Semantic.SemanticIndex = 0; - decl.DeclarationRange.First = - decl.DeclarationRange.Last = 0; - ti += tgsi_build_full_declaration(&decl, - &tokens[ti], - header, - Elements(tokens) - ti); - - /* declare color[0] output */ - decl = tgsi_default_full_declaration(); - decl.Declaration.File = TGSI_FILE_OUTPUT; - decl.Declaration.Semantic = 1; - decl.Semantic.SemanticName = TGSI_SEMANTIC_COLOR; - decl.Semantic.SemanticIndex = 0; - decl.DeclarationRange.First = - decl.DeclarationRange.Last = 0; - ti += tgsi_build_full_declaration(&decl, - &tokens[ti], - header, - Elements(tokens) - ti); - - /* declare sampler */ - decl = tgsi_default_full_declaration(); - decl.Declaration.File = TGSI_FILE_SAMPLER; - decl.DeclarationRange.First = - decl.DeclarationRange.Last = 0; - ti += tgsi_build_full_declaration(&decl, - &tokens[ti], - header, - Elements(tokens) - ti); - - /* TEX instruction */ - inst = tgsi_default_full_instruction(); - inst.Instruction.Opcode = TGSI_OPCODE_TEX; - inst.Instruction.NumDstRegs = 1; - inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT; - inst.FullDstRegisters[0].DstRegister.Index = 0; - inst.Instruction.NumSrcRegs = 2; - inst.InstructionExtTexture.Texture = TGSI_TEXTURE_2D; - inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT; - inst.FullSrcRegisters[0].SrcRegister.Index = 0; - inst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER; - inst.FullSrcRegisters[1].SrcRegister.Index = 0; - ti += tgsi_build_full_instruction(&inst, - &tokens[ti], - header, - Elements(tokens) - ti ); - - /* END instruction */ - inst = tgsi_default_full_instruction(); - inst.Instruction.Opcode = TGSI_OPCODE_END; - inst.Instruction.NumDstRegs = 0; - inst.Instruction.NumSrcRegs = 0; - ti += tgsi_build_full_instruction(&inst, - &tokens[ti], - header, - Elements(tokens) - ti ); - -#if 0 /*debug*/ - tgsi_dump(tokens, 0); -#endif - - shader.tokens = tokens; - - return pipe->create_fs_state(pipe, &shader); + struct ureg_program *ureg; + struct ureg_src sampler; + struct ureg_src tex; + struct ureg_dst out; + + ureg = ureg_create( pipe, TGSI_PROCESSOR_FRAGMENT ); + if (ureg == NULL) + return NULL; + + sampler = ureg_DECL_sampler( ureg ); + + tex = ureg_DECL_fs_input( ureg, + TGSI_SEMANTIC_GENERIC, 0, + TGSI_INTERPOLATE_PERSPECTIVE ); + + out = ureg_DECL_output( ureg, + TGSI_SEMANTIC_COLOR, + 0 ); + + ureg_TEX( ureg, out, TGSI_TEXTURE_2D, tex, sampler ); + ureg_END( ureg ); + + return ureg_create_shader_and_destroy( ureg ); } @@ -263,87 +129,23 @@ util_make_fragment_tex_shader(struct pipe_context *pipe) void * util_make_fragment_passthrough_shader(struct pipe_context *pipe) { - struct pipe_shader_state shader; - struct tgsi_token tokens[40]; - struct tgsi_header *header; - struct tgsi_processor *processor; - struct tgsi_full_declaration decl; - struct tgsi_full_instruction inst; - const uint procType = TGSI_PROCESSOR_FRAGMENT; - uint ti; - - /* shader header - */ - *(struct tgsi_version *) &tokens[0] = tgsi_build_version(); - - header = (struct tgsi_header *) &tokens[1]; - *header = tgsi_build_header(); - - processor = (struct tgsi_processor *) &tokens[2]; - *processor = tgsi_build_processor( procType, header ); - - ti = 3; - - /* declare input */ - decl = tgsi_default_full_declaration(); - decl.Declaration.File = TGSI_FILE_INPUT; - decl.Declaration.Semantic = 1; - decl.Semantic.SemanticName = TGSI_SEMANTIC_COLOR; - decl.Semantic.SemanticIndex = 0; - decl.DeclarationRange.First = - decl.DeclarationRange.Last = 0; - ti += tgsi_build_full_declaration(&decl, - &tokens[ti], - header, - Elements(tokens) - ti); - - /* declare output */ - decl = tgsi_default_full_declaration(); - decl.Declaration.File = TGSI_FILE_OUTPUT; - decl.Declaration.Semantic = 1; - decl.Semantic.SemanticName = TGSI_SEMANTIC_COLOR; - decl.Semantic.SemanticIndex = 0; - decl.DeclarationRange.First = - decl.DeclarationRange.Last = 0; - ti += tgsi_build_full_declaration(&decl, - &tokens[ti], - header, - Elements(tokens) - ti); - - - /* MOVE out[0], in[0]; */ - inst = tgsi_default_full_instruction(); - inst.Instruction.Opcode = TGSI_OPCODE_MOV; - inst.Instruction.NumDstRegs = 1; - inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT; - inst.FullDstRegisters[0].DstRegister.Index = 0; - inst.Instruction.NumSrcRegs = 1; - inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT; - inst.FullSrcRegisters[0].SrcRegister.Index = 0; - ti += tgsi_build_full_instruction(&inst, - &tokens[ti], - header, - Elements(tokens) - ti ); - - /* END instruction */ - inst = tgsi_default_full_instruction(); - inst.Instruction.Opcode = TGSI_OPCODE_END; - inst.Instruction.NumDstRegs = 0; - inst.Instruction.NumSrcRegs = 0; - ti += tgsi_build_full_instruction(&inst, - &tokens[ti], - header, - Elements(tokens) - ti ); - - assert(ti < Elements(tokens)); - -#if 0 /*debug*/ - tgsi_dump(tokens, 0); -#endif - - shader.tokens = tokens; - - return pipe->create_fs_state(pipe, &shader); + struct ureg_program *ureg; + struct ureg_src src; + struct ureg_dst dst; + + ureg = ureg_create( pipe, TGSI_PROCESSOR_FRAGMENT ); + if (ureg == NULL) + return NULL; + + src = ureg_DECL_fs_input( ureg, TGSI_SEMANTIC_COLOR, 0, + TGSI_INTERPOLATE_PERSPECTIVE ); + + dst = ureg_DECL_output( ureg, TGSI_SEMANTIC_COLOR, 0 ); + + ureg_MOV( ureg, dst, src ); + ureg_END( ureg ); + + return ureg_create_shader_and_destroy( ureg ); } diff --git a/src/gallium/auxiliary/util/u_surface.h b/src/gallium/auxiliary/util/u_surface.h index a5b73cfc20..ce84ed7ad0 100644 --- a/src/gallium/auxiliary/util/u_surface.h +++ b/src/gallium/auxiliary/util/u_surface.h @@ -37,6 +37,23 @@ struct pipe_texture; struct pipe_surface; +/** + * Are s1 and s2 the same surface? + * Surfaces are basically views into textures so check if the two surfaces + * name the same part of the same texture. + */ +static INLINE boolean +util_same_surface(const struct pipe_surface *s1, const struct pipe_surface *s2) +{ + return (s1->texture == s2->texture && + s1->face == s2->face && + s1->level == s2->level && + s1->zslice == s2->zslice); +} + + + + extern boolean util_create_rgba_surface(struct pipe_screen *screen, uint width, uint height, diff --git a/src/gallium/auxiliary/util/u_timed_winsys.c b/src/gallium/auxiliary/util/u_timed_winsys.c index 77b2a3a1c8..178acdca4d 100644 --- a/src/gallium/auxiliary/util/u_timed_winsys.c +++ b/src/gallium/auxiliary/util/u_timed_winsys.c @@ -212,13 +212,14 @@ timed_surface_buffer_create(struct pipe_winsys *winsys, unsigned width, unsigned height, enum pipe_format format, unsigned usage, + unsigned tex_usage, unsigned *stride) { struct pipe_winsys *backend = timed_winsys(winsys)->backend; uint64_t start = time_start(); struct pipe_buffer *ret = backend->surface_buffer_create( backend, width, height, - format, usage, stride ); + format, usage, tex_usage, stride ); time_finish(winsys, start, 7, __FUNCTION__); diff --git a/src/gallium/drivers/cell/ppu/cell_texture.c b/src/gallium/drivers/cell/ppu/cell_texture.c index e26594448f..80418f5aa2 100644 --- a/src/gallium/drivers/cell/ppu/cell_texture.c +++ b/src/gallium/drivers/cell/ppu/cell_texture.c @@ -44,13 +44,6 @@ -static unsigned -minify(unsigned d) -{ - return MAX2(1, d>>1); -} - - static void cell_texture_layout(struct cell_texture *ct) { diff --git a/src/gallium/drivers/i915simple/i915_batch.h b/src/gallium/drivers/i915simple/i915_batch.h index a433cf054d..c6e68ea38a 100644 --- a/src/gallium/drivers/i915simple/i915_batch.h +++ b/src/gallium/drivers/i915simple/i915_batch.h @@ -50,8 +50,8 @@ i915_batchbuffer_check( struct i915_batchbuffer *batch, size_t dwords, size_t relocs ) { - /** TODO JB: Check relocs */ - return dwords * 4 <= batch->size - (batch->ptr - batch->map); + return dwords * 4 <= batch->size - (batch->ptr - batch->map) && + relocs <= (batch->max_relocs - batch->relocs); } static INLINE size_t diff --git a/src/gallium/drivers/i915simple/i915_context.c b/src/gallium/drivers/i915simple/i915_context.c index ccf9bb31fb..bf69c8e9f5 100644 --- a/src/gallium/drivers/i915simple/i915_context.c +++ b/src/gallium/drivers/i915simple/i915_context.c @@ -142,10 +142,14 @@ i915_is_texture_referenced( struct pipe_context *pipe, unsigned face, unsigned level) { /** - * FIXME: Optimize. + * FIXME: Return the corrent result. We can't alays return referenced + * since it causes a double flush within the vbo module. */ - +#if 0 return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; +#else + return 0; +#endif } static unsigned int @@ -153,10 +157,14 @@ i915_is_buffer_referenced( struct pipe_context *pipe, struct pipe_buffer *buf) { /** - * FIXME: Optimize. + * FIXME: Return the corrent result. We can't alays return referenced + * since it causes a double flush within the vbo module. */ - +#if 0 return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; +#else + return 0; +#endif } diff --git a/src/gallium/drivers/i915simple/i915_screen.c b/src/gallium/drivers/i915simple/i915_screen.c index f4aa8e60d8..a3de38d586 100644 --- a/src/gallium/drivers/i915simple/i915_screen.c +++ b/src/gallium/drivers/i915simple/i915_screen.c @@ -232,6 +232,8 @@ i915_get_tex_transfer(struct pipe_screen *screen, if (trans) { pipe_texture_reference(&trans->base.texture, texture); trans->base.format = trans->base.format; + trans->base.x = x; + trans->base.y = y; trans->base.width = w; trans->base.height = h; trans->base.block = texture->block; diff --git a/src/gallium/drivers/i915simple/i915_texture.c b/src/gallium/drivers/i915simple/i915_texture.c index ca8e87af8d..03f0e14e7c 100644 --- a/src/gallium/drivers/i915simple/i915_texture.c +++ b/src/gallium/drivers/i915simple/i915_texture.c @@ -72,11 +72,6 @@ static const int step_offsets[6][2] = { {-1, 1} }; -static unsigned minify( unsigned d ) -{ - return MAX2(1, d>>1); -} - static unsigned power_of_two(unsigned x) { @@ -160,10 +155,10 @@ i915_miptree_set_image_offset(struct i915_texture *tex, /** - * Special case to deal with display targets. + * Special case to deal with scanout textures. */ static boolean -i915_displaytarget_layout(struct i915_texture *tex) +i915_scanout_layout(struct i915_texture *tex) { struct pipe_texture *pt = &tex->base; @@ -177,9 +172,13 @@ i915_displaytarget_layout(struct i915_texture *tex) i915_miptree_set_image_offset( tex, 0, 0, 0, 0 ); if (tex->base.width[0] >= 128) { +#if 0 tex->stride = power_of_two(tex->base.nblocksx[0] * pt->block.size); +#else + tex->stride = 2048 * 4; /* TODO fix when backend is smarter */ +#endif tex->total_nblocksy = round_up(tex->base.nblocksy[0], 8); -#if 0 /* used for tiled display targets */ +#if 0 /* used for tiled textures */ tex->tiled = 1; #endif } else { @@ -209,9 +208,9 @@ i945_miptree_layout_2d( struct i915_texture *tex ) unsigned nblocksx = pt->nblocksx[0]; unsigned nblocksy = pt->nblocksy[0]; - /* used for tiled display targets */ - if (0) - if (i915_displaytarget_layout(tex)) + /* used for scanouts that need special layouts */ + if (tex->base.tex_usage & PIPE_TEXTURE_USAGE_PRIMARY) + if (i915_scanout_layout(tex)) return; tex->stride = round_up(pt->nblocksx[0] * pt->block.size, 4); @@ -584,6 +583,7 @@ i915_texture_create(struct pipe_screen *screen, struct i915_screen *i915screen = i915_screen(screen); struct i915_texture *tex = CALLOC_STRUCT(i915_texture); size_t tex_size; + unsigned buf_usage = 0; if (!tex) return NULL; @@ -605,9 +605,11 @@ i915_texture_create(struct pipe_screen *screen, tex_size = tex->stride * tex->total_nblocksy; - tex->buffer = screen->buffer_create(screen, 64, - PIPE_BUFFER_USAGE_PIXEL, - tex_size); + buf_usage = PIPE_BUFFER_USAGE_PIXEL; + if (templat->tex_usage & PIPE_TEXTURE_USAGE_PRIMARY) + buf_usage |= I915_BUFFER_USAGE_SCANOUT; + + tex->buffer = screen->buffer_create(screen, 64, buf_usage, tex_size); if (!tex->buffer) goto fail; diff --git a/src/gallium/drivers/i915simple/i915_winsys.h b/src/gallium/drivers/i915simple/i915_winsys.h index ff5b34f193..711db91c36 100644 --- a/src/gallium/drivers/i915simple/i915_winsys.h +++ b/src/gallium/drivers/i915simple/i915_winsys.h @@ -109,6 +109,7 @@ struct i915_winsys { #define I915_BUFFER_ACCESS_READ 0x2 #define I915_BUFFER_USAGE_LIT_VERTEX (PIPE_BUFFER_USAGE_CUSTOM << 0) +#define I915_BUFFER_USAGE_SCANOUT (PIPE_BUFFER_USAGE_CUSTOM << 1) /** diff --git a/src/gallium/drivers/i965simple/brw_tex_layout.c b/src/gallium/drivers/i965simple/brw_tex_layout.c index 8aea8c0558..998ffaeac4 100644 --- a/src/gallium/drivers/i965simple/brw_tex_layout.c +++ b/src/gallium/drivers/i965simple/brw_tex_layout.c @@ -65,11 +65,6 @@ unsigned intel_compressed_alignment(unsigned internalFormat) } #endif -static unsigned minify( unsigned d ) -{ - return MAX2(1, d>>1); -} - static void intel_miptree_set_image_offset(struct brw_texture *tex, unsigned level, diff --git a/src/gallium/drivers/identity/id_context.c b/src/gallium/drivers/identity/id_context.c index a500ec6045..4e700089e3 100644 --- a/src/gallium/drivers/identity/id_context.c +++ b/src/gallium/drivers/identity/id_context.c @@ -501,7 +501,7 @@ identity_set_sampler_textures(struct pipe_context *_pipe, pipe->set_sampler_textures(pipe, num_textures, - _textures); + textures); } static void diff --git a/src/gallium/drivers/identity/id_drm.c b/src/gallium/drivers/identity/id_drm.c index 555220f853..e5342ac06e 100644 --- a/src/gallium/drivers/identity/id_drm.c +++ b/src/gallium/drivers/identity/id_drm.c @@ -60,7 +60,7 @@ identity_drm_create_screen(struct drm_api *_api, int fd, screen = api->create_screen(api, fd, arg); return identity_screen_create(screen); -}; +} static struct pipe_context * identity_drm_create_context(struct drm_api *_api, @@ -77,7 +77,7 @@ identity_drm_create_context(struct drm_api *_api, pipe = identity_context_create(_screen, pipe); return pipe; -}; +} static boolean identity_drm_buffer_from_texture(struct drm_api *_api, diff --git a/src/gallium/drivers/identity/id_screen.c b/src/gallium/drivers/identity/id_screen.c index 259f1be36e..26439637d0 100644 --- a/src/gallium/drivers/identity/id_screen.c +++ b/src/gallium/drivers/identity/id_screen.c @@ -289,6 +289,7 @@ identity_screen_surface_buffer_create(struct pipe_screen *_screen, unsigned height, enum pipe_format format, unsigned usage, + unsigned tex_usage, unsigned *stride) { struct identity_screen *id_screen = identity_screen(_screen); @@ -300,6 +301,7 @@ identity_screen_surface_buffer_create(struct pipe_screen *_screen, height, format, usage, + tex_usage, stride); if (result) diff --git a/src/gallium/drivers/nv50/nv50_context.h b/src/gallium/drivers/nv50/nv50_context.h index 9b8cc4d37d..5cbc2c8f82 100644 --- a/src/gallium/drivers/nv50/nv50_context.h +++ b/src/gallium/drivers/nv50/nv50_context.h @@ -71,6 +71,7 @@ struct nv50_sampler_stateobj { struct nv50_miptree_level { int *image_offset; unsigned pitch; + unsigned tile_mode; }; struct nv50_miptree { diff --git a/src/gallium/drivers/nv50/nv50_miptree.c b/src/gallium/drivers/nv50/nv50_miptree.c index c8392799ed..7493ef3af2 100644 --- a/src/gallium/drivers/nv50/nv50_miptree.c +++ b/src/gallium/drivers/nv50/nv50_miptree.c @@ -87,20 +87,27 @@ nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *tmp) lvl->image_offset = CALLOC(mt->image_nr, sizeof(int)); lvl->pitch = align(pt->width[l] * pt->block.size, 64); + lvl->tile_mode = tile_mode; width = MAX2(1, width >> 1); height = MAX2(1, height >> 1); depth = MAX2(1, depth >> 1); + + if (tile_mode && height <= (tile_h >> 1)) { + tile_mode--; + tile_h >>= 1; + } } for (i = 0; i < mt->image_nr; i++) { for (l = 0; l <= pt->last_level; l++) { struct nv50_miptree_level *lvl = &mt->level[l]; int size; + tile_h = 1 << (lvl->tile_mode + 2); size = align(pt->width[l], 8) * pt->block.size; size = align(size, 64); - size *= align(pt->height[l], tile_h) * pt->block.size; + size *= align(pt->height[l], tile_h); lvl->image_offset[i] = mt->total_size; @@ -109,7 +116,7 @@ nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *tmp) } ret = nouveau_bo_new_tile(dev, NOUVEAU_BO_VRAM, 256, mt->total_size, - tile_mode, tile_flags, &mt->bo); + mt->level[0].tile_mode, tile_flags, &mt->bo); if (ret) { FREE(mt); return NULL; diff --git a/src/gallium/drivers/nv50/nv50_program.c b/src/gallium/drivers/nv50/nv50_program.c index 4ec9c03305..fefccd0b2a 100644 --- a/src/gallium/drivers/nv50/nv50_program.c +++ b/src/gallium/drivers/nv50/nv50_program.c @@ -296,7 +296,7 @@ kill_temp_temp(struct nv50_pc *pc) static int ctor_immd(struct nv50_pc *pc, float x, float y, float z, float w) { - pc->immd_buf = REALLOC(pc->immd_buf, (pc->immd_nr * r * sizeof(float)), + pc->immd_buf = REALLOC(pc->immd_buf, (pc->immd_nr * 4 * sizeof(float)), (pc->immd_nr + 1) * 4 * sizeof(float)); pc->immd_buf[(pc->immd_nr * 4) + 0] = x; pc->immd_buf[(pc->immd_nr * 4) + 1] = y; diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c index 0f6b1aed96..e13536e84a 100644 --- a/src/gallium/drivers/nv50/nv50_screen.c +++ b/src/gallium/drivers/nv50/nv50_screen.c @@ -291,8 +291,9 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) so_method(so, screen->tesla, 0x13bc, 1); so_data (so, 0x54); + /* origin is top left (set to 1 for bottom left) */ so_method(so, screen->tesla, 0x13ac, 1); - so_data (so, 1); + so_data (so, 0); so_method(so, screen->tesla, 0x16b8, 1); so_data (so, 8); diff --git a/src/gallium/drivers/nv50/nv50_state_validate.c b/src/gallium/drivers/nv50/nv50_state_validate.c index 4a49b107a5..42ecf05580 100644 --- a/src/gallium/drivers/nv50/nv50_state_validate.c +++ b/src/gallium/drivers/nv50/nv50_state_validate.c @@ -124,19 +124,19 @@ nv50_state_validate_fb(struct nv50_context *nv50) so_method(so, tesla, NV50TCL_VIEWPORT_HORIZ, 2); so_data (so, w << 16); so_data (so, h << 16); - /* set window scissor rectangle to window extents */ - so_method(so, tesla, NV50TCL_SCISSOR_HORIZ, 2); - so_data (so, w << 16); - so_data (so, h << 16); /* set window lower left corner */ so_method(so, tesla, NV50TCL_WINDOW_LEFT, 2); so_data (so, 0); - so_data (so, h); + so_data (so, 0); /* set screen scissor rectangle */ so_method(so, tesla, NV50TCL_SCREEN_SCISSOR_HORIZ, 2); so_data (so, w << 16); so_data (so, h << 16); + /* we set scissors to framebuffer size when they're 'turned off' */ + nv50->dirty |= NV50_NEW_SCISSOR; + so_ref(NULL, &nv50->state.scissor); + so_ref(so, &nv50->state.fb); so_ref(NULL, &so); } @@ -246,11 +246,8 @@ nv50_state_validate(struct nv50_context *nv50) so = so_new(3, 0); so_method(so, tesla, NV50TCL_SCISSOR_HORIZ, 2); if (nv50->state.scissor_enabled) { - /* the hw has y = 0 = bottom here */ - unsigned top = nv50->framebuffer.height - s->miny; - unsigned bottom = nv50->framebuffer.height - s->maxy; so_data(so, (s->maxx << 16) | s->minx); - so_data(so, (top << 16) | bottom); + so_data(so, (s->maxy << 16) | s->miny); } else { so_data(so, (nv50->framebuffer.width << 16)); so_data(so, (nv50->framebuffer.height << 16)); @@ -263,7 +260,6 @@ scissor_uptodate: if (nv50->dirty & (NV50_NEW_VIEWPORT | NV50_NEW_RASTERIZER)) { unsigned bypass; - float y_translate = (float)nv50->framebuffer.height; if (!nv50->rasterizer->pipe.bypass_vs_clip_and_viewport) bypass = 0; @@ -277,33 +273,27 @@ scissor_uptodate: nv50->state.viewport_bypass = bypass; so = so_new(12, 0); - so_method(so, tesla, NV50TCL_VIEW_VOLUME_CLIP_CTRL, 1); if (!bypass) { - so_data(so, 0x0000); - y_translate -= nv50->viewport.translate[1]; so_method(so, tesla, NV50TCL_VIEWPORT_TRANSLATE(0), 3); so_data (so, fui(nv50->viewport.translate[0])); - so_data (so, fui(y_translate)); + so_data (so, fui(nv50->viewport.translate[1])); so_data (so, fui(nv50->viewport.translate[2])); so_method(so, tesla, NV50TCL_VIEWPORT_SCALE(0), 3); so_data (so, fui(nv50->viewport.scale[0])); - so_data (so, fui(-nv50->viewport.scale[1])); + so_data (so, fui(nv50->viewport.scale[1])); so_data (so, fui(nv50->viewport.scale[2])); + + so_method(so, tesla, NV50TCL_VIEWPORT_TRANSFORM_EN, 1); + so_data (so, 1); + /* no idea what 0f90 does */ + so_method(so, tesla, 0x0f90, 1); + so_data (so, 0); } else { - /* don't do xy-clipping in NDC space */ - so_data(so, 0x0800); - /* in bypass mode, y = 0 would be bottom */ - so_method(so, tesla, NV50TCL_VIEWPORT_TRANSLATE(0), 3); - so_data (so, fui(0.0f)); - so_data (so, fui(y_translate)); - so_data (so, fui(0.0f)); - so_method(so, tesla, NV50TCL_VIEWPORT_SCALE(0), 3); - so_data (so, fui(1.0f)); - so_data (so, fui(-1.0f)); - so_data (so, fui(1.0f)); + so_method(so, tesla, NV50TCL_VIEWPORT_TRANSFORM_EN, 1); + so_data (so, 0); + so_method(so, tesla, 0x0f90, 1); + so_data (so, 1); } - so_method(so, tesla, NV50TCL_VIEWPORT_TRANSFORM_EN, 1); - so_data (so, 1); so_ref(so, &nv50->state.viewport); so_ref(NULL, &so); diff --git a/src/gallium/drivers/nv50/nv50_transfer.c b/src/gallium/drivers/nv50/nv50_transfer.c index 6ff375951e..1c47c30968 100644 --- a/src/gallium/drivers/nv50/nv50_transfer.c +++ b/src/gallium/drivers/nv50/nv50_transfer.c @@ -8,6 +8,7 @@ struct nv50_transfer { struct pipe_transfer base; struct nouveau_bo *bo; unsigned level_offset; + unsigned level_tiling; int level_pitch; int level_width; int level_height; @@ -16,11 +17,14 @@ struct nv50_transfer { }; static void -nv50_transfer_rect_m2mf(struct pipe_screen *pscreen, struct nouveau_bo *src_bo, - unsigned src_offset, int src_pitch, int sx, int sy, - int sw, int sh, struct nouveau_bo *dst_bo, - unsigned dst_offset, int dst_pitch, int dx, int dy, - int dw, int dh, int cpp, int width, int height, +nv50_transfer_rect_m2mf(struct pipe_screen *pscreen, + struct nouveau_bo *src_bo, unsigned src_offset, + int src_pitch, unsigned src_tile_mode, + int sx, int sy, int sw, int sh, + struct nouveau_bo *dst_bo, unsigned dst_offset, + int dst_pitch, unsigned dst_tile_mode, + int dx, int dy, int dw, int dh, + int cpp, int width, int height, unsigned src_reloc, unsigned dst_reloc) { struct nv50_screen *screen = nv50_screen(pscreen); @@ -41,7 +45,7 @@ nv50_transfer_rect_m2mf(struct pipe_screen *pscreen, struct nouveau_bo *src_bo, } else { BEGIN_RING(chan, m2mf, 0x0200, 6); OUT_RING (chan, 0); - OUT_RING (chan, src_bo->tile_mode << 4); + OUT_RING (chan, src_tile_mode << 4); OUT_RING (chan, sw * cpp); OUT_RING (chan, sh); OUT_RING (chan, 1); @@ -57,7 +61,7 @@ nv50_transfer_rect_m2mf(struct pipe_screen *pscreen, struct nouveau_bo *src_bo, } else { BEGIN_RING(chan, m2mf, 0x021c, 6); OUT_RING (chan, 0); - OUT_RING (chan, dst_bo->tile_mode << 4); + OUT_RING (chan, dst_tile_mode << 4); OUT_RING (chan, dw * cpp); OUT_RING (chan, dh); OUT_RING (chan, 1); @@ -136,6 +140,7 @@ nv50_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt, tx->level_width = mt->base.width[level]; tx->level_height = mt->base.height[level]; tx->level_offset = lvl->image_offset[image]; + tx->level_tiling = lvl->tile_mode; tx->level_x = x; tx->level_y = y; ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0, @@ -147,9 +152,11 @@ nv50_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt, if (usage != PIPE_TRANSFER_WRITE) { nv50_transfer_rect_m2mf(pscreen, mt->bo, tx->level_offset, - tx->level_pitch, x, y, tx->level_width, - tx->level_height, tx->bo, 0, - tx->base.stride, 0, 0, + tx->level_pitch, tx->level_tiling, + x, y, + tx->level_width, tx->level_height, + tx->bo, 0, tx->base.stride, + tx->bo->tile_mode, 0, 0, tx->base.width, tx->base.height, tx->base.block.size, w, h, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART, @@ -168,12 +175,14 @@ nv50_transfer_del(struct pipe_transfer *ptx) if (ptx->usage != PIPE_TRANSFER_READ) { struct pipe_screen *pscreen = ptx->texture->screen; nv50_transfer_rect_m2mf(pscreen, tx->bo, 0, tx->base.stride, - 0, 0, tx->base.width, tx->base.height, - mt->bo, tx->level_offset, - tx->level_pitch, tx->level_x, - tx->level_y, tx->level_width, - tx->level_height, tx->base.block.size, + tx->bo->tile_mode, 0, 0, tx->base.width, tx->base.height, + mt->bo, tx->level_offset, + tx->level_pitch, tx->level_tiling, + tx->level_x, tx->level_y, + tx->level_width, tx->level_height, + tx->base.block.size, tx->base.width, + tx->base.height, NOUVEAU_BO_GART, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART); } diff --git a/src/gallium/drivers/r300/Makefile b/src/gallium/drivers/r300/Makefile index faceec9842..d7a2c8c462 100644 --- a/src/gallium/drivers/r300/Makefile +++ b/src/gallium/drivers/r300/Makefile @@ -9,7 +9,6 @@ C_SOURCES = \ r300_chipset.c \ r300_clear.c \ r300_context.c \ - r300_debug.c \ r300_emit.c \ r300_flush.c \ r300_fs.c \ @@ -21,6 +20,22 @@ C_SOURCES = \ r300_state_invariant.c \ r300_vs.c \ r300_surface.c \ - r300_texture.c + r300_texture.c \ + r300_tgsi_to_rc.c + +LIBRARY_INCLUDES = \ + -I$(TOP)/src/mesa/drivers/dri/r300/compiler \ + -I$(TOP)/src/mesa \ + -I$(TOP)/include + +COMPILER_ARCHIVE = $(TOP)/src/mesa/drivers/dri/r300/compiler/libr300compiler.a + +EXTRA_OBJECTS = \ + $(COMPILER_ARCHIVE) include ../../Makefile.template + +.PHONY : $(COMPILER_ARCHIVE) + +$(COMPILER_ARCHIVE): + cd $(TOP)/src/mesa/drivers/dri/r300/compiler; make diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c index 233a32b53c..c8510bc63e 100644 --- a/src/gallium/drivers/r300/r300_context.c +++ b/src/gallium/drivers/r300/r300_context.c @@ -52,7 +52,7 @@ static boolean r300_draw_range_elements(struct pipe_context* pipe, draw_set_mapped_constant_buffer(r300->draw, r300->shader_constants[PIPE_SHADER_VERTEX].constants, - r300->shader_constants[PIPE_SHADER_VERTEX].user_count * + r300->shader_constants[PIPE_SHADER_VERTEX].count * (sizeof(float) * 4)); draw_arrays(r300->draw, mode, start, count); diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index d891fd6265..fc8a449893 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -34,6 +34,9 @@ #include "r300_screen.h" #include "r300_winsys.h" +struct r300_fragment_shader; +struct r300_vertex_shader; + struct r300_blend_state { uint32_t blend_control; /* R300_RB3D_CBLEND: 0x4e04 */ uint32_t alpha_blend_control; /* R300_RB3D_ABLEND: 0x4e08 */ @@ -143,71 +146,10 @@ struct r300_constant_buffer { /* Buffer of constants */ /* XXX first number should be raised */ float constants[32][4]; - /* Number of user-defined constants */ - unsigned user_count; /* Total number of constants */ unsigned count; }; -struct r300_fragment_shader { - /* Parent class */ - struct pipe_shader_state state; - struct tgsi_shader_info info; - - /* Has this shader been translated yet? */ - boolean translated; - - /* Pixel stack size */ - int stack_size; - - /* Are there immediates in this shader? - * If not, we can heavily optimize recompilation. */ - boolean uses_imms; -}; - -struct r3xx_fragment_shader { - /* Parent class */ - struct r300_fragment_shader shader; - - /* Number of ALU instructions */ - int alu_instruction_count; - - /* Number of texture instructions */ - int tex_instruction_count; - - /* Number of texture indirections */ - int indirections; - - /* Indirection node offsets */ - int alu_offset[4]; - - /* Machine instructions */ - struct { - uint32_t alu_rgb_inst; - uint32_t alu_rgb_addr; - uint32_t alu_alpha_inst; - uint32_t alu_alpha_addr; - } instructions[64]; /* XXX magic num */ -}; - -struct r5xx_fragment_shader { - /* Parent class */ - struct r300_fragment_shader shader; - - /* Number of used instructions */ - int instruction_count; - - /* Machine instructions */ - struct { - uint32_t inst0; - uint32_t inst1; - uint32_t inst2; - uint32_t inst3; - uint32_t inst4; - uint32_t inst5; - } instructions[256]; /*< XXX magic number */ -}; - struct r300_texture { /* Parent class */ struct pipe_texture tex; @@ -242,33 +184,6 @@ struct r300_vertex_format { int fs_tab[16]; }; -struct r300_vertex_shader { - /* Parent class */ - struct pipe_shader_state state; - struct tgsi_shader_info info; - - /* Fallback shader, because Draw has issues */ - struct draw_vertex_shader* draw; - - /* Has this shader been translated yet? */ - boolean translated; - - /* Are there immediates in this shader? - * If not, we can heavily optimize recompilation. */ - boolean uses_imms; - - /* Number of used instructions */ - int instruction_count; - - /* Machine instructions */ - struct { - uint32_t inst0; - uint32_t inst1; - uint32_t inst2; - uint32_t inst3; - } instructions[128]; /*< XXX magic number */ -}; - static struct pipe_viewport_state r300_viewport_identity = { .scale = {1.0, 1.0, 1.0, 1.0}, .translate = {0.0, 0.0, 0.0, 0.0}, diff --git a/src/gallium/drivers/r300/r300_debug.c b/src/gallium/drivers/r300/r300_debug.c deleted file mode 100644 index c83e8526cf..0000000000 --- a/src/gallium/drivers/r300/r300_debug.c +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright 2009 Corbin Simpson <MostAwesomeDude@gmail.com> - * - * 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 - * on 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 AUTHOR(S) AND/OR THEIR 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 "r300_debug.h" - -void r3xx_dump_fs(struct r3xx_fragment_shader* fs) -{ - int i; - - for (i = 0; i < fs->alu_instruction_count; i++) { - } -} - -void r5xx_fs_dump(struct r5xx_fragment_shader* fs) -{ - int i; - uint32_t inst; - - for (i = 0; i < fs->instruction_count; i++) { - inst = fs->instructions[i].inst0; - debug_printf("%d: 0: CMN_INST 0x%08x:", i, inst); - switch (inst & 0x3) { - case R500_INST_TYPE_ALU: - debug_printf("ALU "); - break; - case R500_INST_TYPE_OUT: - debug_printf("OUT "); - break; - case R500_INST_TYPE_FC: - debug_printf("FC "); - break; - case R500_INST_TYPE_TEX: - debug_printf("TEX "); - break; - } - debug_printf("%s %s %s %s ", - inst & R500_INST_TEX_SEM_WAIT ? "TEX_WAIT" : "", - inst & R500_INST_LAST ? "LAST" : "", - inst & R500_INST_NOP ? "NOP" : "", - inst & R500_INST_ALU_WAIT ? "ALU_WAIT" : ""); - debug_printf("wmask: %s omask: %s\n", - r5xx_fs_mask[(inst >> 11) & 0xf], - r5xx_fs_mask[(inst >> 15) & 0xf]); - switch (inst & 0x3) { - case R500_INST_TYPE_ALU: - case R500_INST_TYPE_OUT: - inst = fs->instructions[i].inst1; - debug_printf(" 1: RGB_ADDR 0x%08x:", inst); - debug_printf("Addr0: %d%c, Addr1: %d%c, " - "Addr2: %d%c, srcp:%d\n", - inst & 0xff, (inst & (1 << 8)) ? 'c' : 't', - (inst >> 10) & 0xff, (inst & (1 << 18)) ? 'c' : 't', - (inst >> 20) & 0xff, (inst & (1 << 28)) ? 'c' : 't', - (inst >> 30)); - - inst = fs->instructions[i].inst2; - debug_printf(" 2: ALPHA_ADDR 0x%08x:", inst); - debug_printf("Addr0: %d%c, Addr1: %d%c, " - "Addr2: %d%c, srcp:%d\n", - inst & 0xff, (inst & (1 << 8)) ? 'c' : 't', - (inst >> 10) & 0xff, (inst & (1 << 18)) ? 'c' : 't', - (inst >> 20) & 0xff, (inst & (1 << 28)) ? 'c' : 't', - (inst >> 30)); - - inst = fs->instructions[i].inst3; - debug_printf(" 3: RGB_INST 0x%08x:", inst); - debug_printf("rgb_A_src:%d %s/%s/%s %d " - "rgb_B_src:%d %s/%s/%s %d\n", - inst & 0x3, r5xx_fs_swiz[(inst >> 2) & 0x7], - r5xx_fs_swiz[(inst >> 5) & 0x7], - r5xx_fs_swiz[(inst >> 8) & 0x7], - (inst >> 11) & 0x3, (inst >> 13) & 0x3, - r5xx_fs_swiz[(inst >> 15) & 0x7], - r5xx_fs_swiz[(inst >> 18) & 0x7], - r5xx_fs_swiz[(inst >> 21) & 0x7], - (inst >> 24) & 0x3); - - inst = fs->instructions[i].inst4; - debug_printf(" 4: ALPHA_INST 0x%08x:", inst); - debug_printf("%s dest:%d%s alp_A_src:%d %s %d " - "alp_B_src:%d %s %d w:%d\n", - r5xx_fs_op_alpha[inst & 0xf], (inst >> 4) & 0x7f, - inst & (1<<11) ? "(rel)":"", (inst >> 12) & 0x3, - r5xx_fs_swiz[(inst >> 14) & 0x7], (inst >> 17) & 0x3, - (inst >> 19) & 0x3, r5xx_fs_swiz[(inst >> 21) & 0x7], - (inst >> 24) & 0x3, (inst >> 31) & 0x1); - - inst = fs->instructions[i].inst5; - debug_printf(" 5: RGBA_INST 0x%08x:", inst); - debug_printf("%s dest:%d%s rgb_C_src:%d %s/%s/%s %d " - "alp_C_src:%d %s %d\n", - r5xx_fs_op_rgb[inst & 0xf], (inst >> 4) & 0x7f, - inst & (1 << 11) ? "(rel)":"", (inst >> 12) & 0x3, - r5xx_fs_swiz[(inst >> 14) & 0x7], - r5xx_fs_swiz[(inst >> 17) & 0x7], - r5xx_fs_swiz[(inst >> 20) & 0x7], - (inst >> 23) & 0x3, (inst >> 25) & 0x3, - r5xx_fs_swiz[(inst >> 27) & 0x7], (inst >> 30) & 0x3); - break; - case R500_INST_TYPE_FC: - /* XXX don't even bother yet */ - break; - case R500_INST_TYPE_TEX: - inst = fs->instructions[i].inst1; - debug_printf(" 1: TEX_INST 0x%08x: id: %d " - "op:%s, %s, %s %s\n", - inst, (inst >> 16) & 0xf, - r5xx_fs_tex[(inst >> 22) & 0x7], - (inst & (1 << 25)) ? "ACQ" : "", - (inst & (1 << 26)) ? "IGNUNC" : "", - (inst & (1 << 27)) ? "UNSCALED" : "SCALED"); - - inst = fs->instructions[i].inst2; - debug_printf(" 2: TEX_ADDR 0x%08x: " - "src: %d%s %s/%s/%s/%s dst: %d%s %s/%s/%s/%s\n", - inst, inst & 0x7f, inst & (1 << 7) ? "(rel)" : "", - r5xx_fs_swiz[(inst >> 8) & 0x3], - r5xx_fs_swiz[(inst >> 10) & 0x3], - r5xx_fs_swiz[(inst >> 12) & 0x3], - r5xx_fs_swiz[(inst >> 14) & 0x3], - (inst >> 16) & 0x7f, inst & (1 << 23) ? "(rel)" : "", - r5xx_fs_swiz[(inst >> 24) & 0x3], - r5xx_fs_swiz[(inst >> 26) & 0x3], - r5xx_fs_swiz[(inst >> 28) & 0x3], - r5xx_fs_swiz[(inst >> 30) & 0x3]); - - inst = fs->instructions[i].inst3; - debug_printf(" 3: TEX_DXDY 0x%08x\n", inst); - break; - } - } -} - -static void r300_vs_op_dump(uint32_t op) -{ - debug_printf(" dst: %d%s op: ", - (op >> 13) & 0x7f, r300_vs_dst_debug[(op >> 8) & 0x7]); - if (op & 0x80) { - if (op & 0x1) { - debug_printf("PVS_MACRO_OP_2CLK_M2X_ADD\n"); - } else { - debug_printf(" PVS_MACRO_OP_2CLK_MADD\n"); - } - } else if (op & 0x40) { - debug_printf("%s\n", r300_vs_me_ops[op & 0x1f]); - } else { - debug_printf("%s\n", r300_vs_ve_ops[op & 0x1f]); - } -} - -void r300_vs_src_dump(uint32_t src) -{ - debug_printf(" reg: %d%s swiz: %s%s/%s%s/%s%s/%s%s\n", - (src >> 5) & 0x7f, r300_vs_src_debug[src & 0x3], - src & (1 << 25) ? "-" : " ", - r300_vs_swiz_debug[(src >> 13) & 0x7], - src & (1 << 26) ? "-" : " ", - r300_vs_swiz_debug[(src >> 16) & 0x7], - src & (1 << 27) ? "-" : " ", - r300_vs_swiz_debug[(src >> 19) & 0x7], - src & (1 << 28) ? "-" : " ", - r300_vs_swiz_debug[(src >> 22) & 0x7]); -} - -void r300_vs_dump(struct r300_vertex_shader* vs) -{ - int i; - - for (i = 0; i < vs->instruction_count; i++) { - debug_printf("%d: op: 0x%08x", i, vs->instructions[i].inst0); - r300_vs_op_dump(vs->instructions[i].inst0); - debug_printf(" src0: 0x%08x", vs->instructions[i].inst1); - r300_vs_src_dump(vs->instructions[i].inst1); - debug_printf(" src1: 0x%08x", vs->instructions[i].inst2); - r300_vs_src_dump(vs->instructions[i].inst2); - debug_printf(" src2: 0x%08x", vs->instructions[i].inst3); - r300_vs_src_dump(vs->instructions[i].inst3); - } -} diff --git a/src/gallium/drivers/r300/r300_debug.h b/src/gallium/drivers/r300/r300_debug.h deleted file mode 100644 index 6b58c1e250..0000000000 --- a/src/gallium/drivers/r300/r300_debug.h +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright 2009 Corbin Simpson <MostAwesomeDude@gmail.com> - * - * 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 - * on 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 AUTHOR(S) AND/OR THEIR 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 R300_DEBUG_H -#define R300_DEBUG_H - -#include "r300_reg.h" -#include "r300_fs.h" -#include "r300_vs.h" - -static char* r5xx_fs_swiz[] = { - " R", - " G", - " B", - " A", - " 0", - ".5", - " 1", - " U", -}; - -static char* r5xx_fs_op_rgb[] = { - "MAD", - "DP3", - "DP4", - "D2A", - "MIN", - "MAX", - "---", - "CND", - "CMP", - "FRC", - "SOP", - "MDH", - "MDV", -}; - -static char* r5xx_fs_op_alpha[] = { - "MAD", - " DP", - "MIN", - "MAX", - "---", - "CND", - "CMP", - "FRC", - "EX2", - "LN2", - "RCP", - "RSQ", - "SIN", - "COS", - "MDH", - "MDV", -}; - -static char* r5xx_fs_mask[] = { - "NONE", - "R ", - " G ", - "RG ", - " B ", - "R B ", - " GB ", - "RGB ", - " A", - "R A", - " G A", - "RG A", - " BA", - "R BA", - " GBA", - "RGBA", -}; - -static char* r5xx_fs_tex[] = { - " NOP", - " LD", - "TEXKILL", - " PROJ", - "LODBIAS", - " LOD", - " DXDY", -}; - -static char* r300_vs_ve_ops[] = { - /* R300 vector ops */ - " VE_NO_OP", - " VE_DOT_PRODUCT", - " VE_MULTIPLY", - " VE_ADD", - " VE_MULTIPLY_ADD", - " VE_DISTANCE_FACTOR", - " VE_FRACTION", - " VE_MAXIMUM", - " VE_MINIMUM", - "VE_SET_GREATER_THAN_EQUAL", - " VE_SET_LESS_THAN", - " VE_MULTIPLYX2_ADD", - " VE_MULTIPLY_CLAMP", - " VE_FLT2FIX_DX", - " VE_FLT2FIX_DX_RND", - /* R500 vector ops */ - " VE_PRED_SET_EQ_PUSH", - " VE_PRED_SET_GT_PUSH", - " VE_PRED_SET_GTE_PUSH", - " VE_PRED_SET_NEQ_PUSH", - " VE_COND_WRITE_EQ", - " VE_COND_WRITE_GT", - " VE_COND_WRITE_GTE", - " VE_COND_WRITE_NEQ", - " VE_SET_GREATER_THAN", - " VE_SET_EQUAL", - " VE_SET_NOT_EQUAL", - " (reserved)", - " (reserved)", - " (reserved)", -}; - -static char* r300_vs_me_ops[] = { - /* R300 math ops */ - " ME_NO_OP", - " ME_EXP_BASE2_DX", - " ME_LOG_BASE2_DX", - " ME_EXP_BASEE_FF", - " ME_LIGHT_COEFF_DX", - " ME_POWER_FUNC_FF", - " ME_RECIP_DX", - " ME_RECIP_FF", - " ME_RECIP_SQRT_DX", - " ME_RECIP_SQRT_FF", - " ME_MULTIPLY", - " ME_EXP_BASE2_FULL_DX", - " ME_LOG_BASE2_FULL_DX", - " ME_POWER_FUNC_FF_CLAMP_B", - "ME_POWER_FUNC_FF_CLAMP_B1", - "ME_POWER_FUNC_FF_CLAMP_01", - " ME_SIN", - " ME_COS", - /* R500 math ops */ - " ME_LOG_BASE2_IEEE", - " ME_RECIP_IEEE", - " ME_RECIP_SQRT_IEEE", - " ME_PRED_SET_EQ", - " ME_PRED_SET_GT", - " ME_PRED_SET_GTE", - " ME_PRED_SET_NEQ", - " ME_PRED_SET_CLR", - " ME_PRED_SET_INV", - " ME_PRED_SET_POP", - " ME_PRED_SET_RESTORE", - " (reserved)", - " (reserved)", - " (reserved)", -}; - -/* XXX refactor to avoid clashing symbols */ -static char* r300_vs_src_debug[] = { - "t", - "i", - "c", - "a", -}; - -static char* r300_vs_dst_debug[] = { - "t", - "a0", - "o", - "ox", - "a", - "i", - "u", - "u", -}; - -static char* r300_vs_swiz_debug[] = { - "X", - "Y", - "Z", - "W", - "0", - "1", - "U", - "U", -}; - -void r5xx_fs_dump(struct r5xx_fragment_shader* fs); -void r3xx_dump_fs(struct r3xx_fragment_shader* fs); - -void r300_vs_dump(struct r300_vertex_shader* vs); - -#endif /* R300_DEBUG_H */ diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c index ac510ffc2e..53256fc6dd 100644 --- a/src/gallium/drivers/r300/r300_emit.c +++ b/src/gallium/drivers/r300/r300_emit.c @@ -24,6 +24,9 @@ #include "r300_emit.h" +#include "r300_fs.h" +#include "r300_vs.h" + void r300_emit_blend_state(struct r300_context* r300, struct r300_blend_state* blend) { @@ -109,73 +112,158 @@ void r300_emit_dsa_state(struct r300_context* r300, END_CS; } -void r300_emit_fragment_shader(struct r300_context* r300, - struct r3xx_fragment_shader* fs) +static const float * get_shader_constant( + struct r300_context * r300, + struct rc_constant * constant, + struct r300_constant_buffer * externals) +{ + static const float zero[4] = { 0.0, 0.0, 0.0, 0.0 }; + switch(constant->Type) { + case RC_CONSTANT_EXTERNAL: + return externals->constants[constant->u.External]; + + case RC_CONSTANT_IMMEDIATE: + return constant->u.Immediate; + + default: + debug_printf("r300: Implementation error: Unhandled constant type %i\n", + constant->Type); + return zero; + } +} + +/* Convert a normal single-precision float into the 7.16 format + * used by the R300 fragment shader. + */ +static uint32_t pack_float24(float f) { + union { + float fl; + uint32_t u; + } u; + float mantissa; + int exponent; + uint32_t float24 = 0; + + if (f == 0.0) + return 0; + + u.fl = f; + + mantissa = frexpf(f, &exponent); + + /* Handle -ve */ + if (mantissa < 0) { + float24 |= (1 << 23); + mantissa = mantissa * -1.0; + } + /* Handle exponent, bias of 63 */ + exponent += 62; + float24 |= (exponent << 16); + /* Kill 7 LSB of mantissa */ + float24 |= (u.u & 0x7FFFFF) >> 7; + + return float24; +} + +void r300_emit_fragment_program_code(struct r300_context* r300, + struct rX00_fragment_program_code* generic_code, + struct r300_constant_buffer* externals) +{ + struct r300_fragment_program_code * code = &generic_code->code.r300; + struct rc_constant_list * constants = &generic_code->constants; int i; CS_LOCALS(r300); - BEGIN_CS(22); - - OUT_CS_REG(R300_US_CONFIG, fs->indirections); - OUT_CS_REG(R300_US_PIXSIZE, fs->shader.stack_size); - /* XXX figure out exactly how big the sizes are on this reg */ - OUT_CS_REG(R300_US_CODE_OFFSET, 0x40); - /* XXX figure these ones out a bit better kthnx */ - OUT_CS_REG(R300_US_CODE_ADDR_0, 0x0); - OUT_CS_REG(R300_US_CODE_ADDR_1, 0x0); - OUT_CS_REG(R300_US_CODE_ADDR_2, 0x0); - OUT_CS_REG(R300_US_CODE_ADDR_3, 0x40 | R300_RGBA_OUT); - - for (i = 0; i < fs->alu_instruction_count; i++) { - OUT_CS_REG(R300_US_ALU_RGB_INST_0 + (4 * i), - fs->instructions[i].alu_rgb_inst); - OUT_CS_REG(R300_US_ALU_RGB_ADDR_0 + (4 * i), - fs->instructions[i].alu_rgb_addr); - OUT_CS_REG(R300_US_ALU_ALPHA_INST_0 + (4 * i), - fs->instructions[i].alu_alpha_inst); - OUT_CS_REG(R300_US_ALU_ALPHA_ADDR_0 + (4 * i), - fs->instructions[i].alu_alpha_addr); + BEGIN_CS(15 + + code->alu.length * 4 + + (code->tex.length ? (1 + code->tex.length) : 0) + + (constants->Count ? (1 + constants->Count * 4) : 0)); + + OUT_CS_REG(R300_US_CONFIG, code->config); + OUT_CS_REG(R300_US_PIXSIZE, code->pixsize); + OUT_CS_REG(R300_US_CODE_OFFSET, code->code_offset); + + OUT_CS_REG_SEQ(R300_US_CODE_ADDR_0, 4); + for(i = 0; i < 4; ++i) + OUT_CS(code->code_addr[i]); + + OUT_CS_REG_SEQ(R300_US_ALU_RGB_INST_0, code->alu.length); + for (i = 0; i < code->alu.length; i++) + OUT_CS(code->alu.inst[i].rgb_inst); + + OUT_CS_REG_SEQ(R300_US_ALU_RGB_ADDR_0, code->alu.length); + for (i = 0; i < code->alu.length; i++) + OUT_CS(code->alu.inst[i].rgb_addr); + + OUT_CS_REG_SEQ(R300_US_ALU_ALPHA_INST_0, code->alu.length); + for (i = 0; i < code->alu.length; i++) + OUT_CS(code->alu.inst[i].alpha_inst); + + OUT_CS_REG_SEQ(R300_US_ALU_ALPHA_ADDR_0, code->alu.length); + for (i = 0; i < code->alu.length; i++) + OUT_CS(code->alu.inst[i].alpha_addr); + + if (code->tex.length) { + OUT_CS_REG_SEQ(R300_US_TEX_INST_0, code->tex.length); + for(i = 0; i < code->tex.length; ++i) + OUT_CS(code->tex.inst[i]); + } + + if (constants->Count) { + OUT_CS_ONE_REG(R300_PFS_PARAM_0_X, constants->Count * 4); + for(i = 0; i < constants->Count; ++i) { + const float * data = get_shader_constant(r300, &constants->Constants[i], externals); + OUT_CS(pack_float24(data[0])); + OUT_CS(pack_float24(data[1])); + OUT_CS(pack_float24(data[2])); + OUT_CS(pack_float24(data[3])); + } } END_CS; } -void r500_emit_fragment_shader(struct r300_context* r300, - struct r5xx_fragment_shader* fs) +void r500_emit_fragment_program_code(struct r300_context* r300, + struct rX00_fragment_program_code* generic_code, + struct r300_constant_buffer* externals) { + struct r500_fragment_program_code * code = &generic_code->code.r500; + struct rc_constant_list * constants = &generic_code->constants; int i; - struct r300_constant_buffer* constants = - &r300->shader_constants[PIPE_SHADER_FRAGMENT]; CS_LOCALS(r300); - BEGIN_CS(9 + (fs->instruction_count * 6) + (constants->count ? 3 : 0) + - (constants->count * 4)); - OUT_CS_REG(R500_US_CONFIG, R500_ZERO_TIMES_ANYTHING_EQUALS_ZERO); - OUT_CS_REG(R500_US_PIXSIZE, fs->shader.stack_size); - OUT_CS_REG(R500_US_CODE_ADDR, R500_US_CODE_START_ADDR(0) | - R500_US_CODE_END_ADDR(fs->instruction_count)); + BEGIN_CS(13 + + ((code->inst_end + 1) * 6) + + (constants->Count ? (3 + (constants->Count * 4)) : 0)); + OUT_CS_REG(R500_US_CONFIG, 0); + OUT_CS_REG(R500_US_PIXSIZE, code->max_temp_idx); + OUT_CS_REG(R500_US_CODE_RANGE, + R500_US_CODE_RANGE_ADDR(0) | R500_US_CODE_RANGE_SIZE(code->inst_end)); + OUT_CS_REG(R500_US_CODE_OFFSET, 0); + OUT_CS_REG(R500_US_CODE_ADDR, + R500_US_CODE_START_ADDR(0) | R500_US_CODE_END_ADDR(code->inst_end)); OUT_CS_REG(R500_GA_US_VECTOR_INDEX, R500_GA_US_VECTOR_INDEX_TYPE_INSTR); - OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, fs->instruction_count * 6); - for (i = 0; i < fs->instruction_count; i++) { - OUT_CS(fs->instructions[i].inst0); - OUT_CS(fs->instructions[i].inst1); - OUT_CS(fs->instructions[i].inst2); - OUT_CS(fs->instructions[i].inst3); - OUT_CS(fs->instructions[i].inst4); - OUT_CS(fs->instructions[i].inst5); - } - - if (constants->count) { - OUT_CS_REG(R500_GA_US_VECTOR_INDEX, - R500_GA_US_VECTOR_INDEX_TYPE_CONST); - OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, constants->count * 4); - for (i = 0; i < constants->count; i++) { - OUT_CS_32F(constants->constants[i][0]); - OUT_CS_32F(constants->constants[i][1]); - OUT_CS_32F(constants->constants[i][2]); - OUT_CS_32F(constants->constants[i][3]); + OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, (code->inst_end + 1) * 6); + for (i = 0; i <= code->inst_end; i++) { + OUT_CS(code->inst[i].inst0); + OUT_CS(code->inst[i].inst1); + OUT_CS(code->inst[i].inst2); + OUT_CS(code->inst[i].inst3); + OUT_CS(code->inst[i].inst4); + OUT_CS(code->inst[i].inst5); + } + + if (constants->Count) { + OUT_CS_REG(R500_GA_US_VECTOR_INDEX, R500_GA_US_VECTOR_INDEX_TYPE_CONST); + OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, constants->Count * 4); + for (i = 0; i < constants->Count; i++) { + const float * data = get_shader_constant(r300, &constants->Constants[i], externals); + OUT_CS_32F(data[0]); + OUT_CS_32F(data[1]); + OUT_CS_32F(data[2]); + OUT_CS_32F(data[3]); } } @@ -190,7 +278,7 @@ void r300_emit_fb_state(struct r300_context* r300, int i; CS_LOCALS(r300); - BEGIN_CS((8 * fb->nr_cbufs) + (fb->zsbuf ? 8 : 0) + 4); + BEGIN_CS((10 * fb->nr_cbufs) + (fb->zsbuf ? 10 : 0) + 4); for (i = 0; i < fb->nr_cbufs; i++) { tex = (struct r300_texture*)fb->cbufs[i]->texture; assert(tex && tex->buffer && "cbuf is marked, but NULL!"); @@ -199,8 +287,10 @@ void r300_emit_fb_state(struct r300_context* r300, OUT_CS_REG_SEQ(R300_RB3D_COLOROFFSET0 + (4 * i), 1); OUT_CS_RELOC(tex->buffer, 0, 0, RADEON_GEM_DOMAIN_VRAM, 0); - OUT_CS_REG(R300_RB3D_COLORPITCH0 + (4 * i), pixpitch | - r300_translate_colorformat(tex->tex.format)); + OUT_CS_REG_SEQ(R300_RB3D_COLORPITCH0 + (4 * i), 1); + OUT_CS_RELOC(tex->buffer, pixpitch | + r300_translate_colorformat(tex->tex.format), 0, + RADEON_GEM_DOMAIN_VRAM, 0); OUT_CS_REG(R300_US_OUT_FMT_0 + (4 * i), r300_translate_out_fmt(fb->cbufs[i]->format)); @@ -216,7 +306,8 @@ void r300_emit_fb_state(struct r300_context* r300, OUT_CS_REG(R300_ZB_FORMAT, r300_translate_zsformat(tex->tex.format)); - OUT_CS_REG(R300_ZB_DEPTHPITCH, pixpitch); + OUT_CS_REG_SEQ(R300_ZB_DEPTHPITCH, 1); + OUT_CS_RELOC(tex->buffer, pixpitch, 0, RADEON_GEM_DOMAIN_VRAM, 0); } OUT_CS_REG(R300_RB3D_DSTCACHE_CTLSTAT, @@ -380,13 +471,13 @@ void r300_emit_vertex_format_state(struct r300_context* r300) END_CS; } -void r300_emit_vertex_shader(struct r300_context* r300, - struct r300_vertex_shader* vs) +void r300_emit_vertex_program_code(struct r300_context* r300, + struct r300_vertex_program_code* code, + struct r300_constant_buffer* constants) { int i; struct r300_screen* r300screen = r300_screen(r300->context.screen); - struct r300_constant_buffer* constants = - &r300->shader_constants[PIPE_SHADER_VERTEX]; + unsigned instruction_count = code->length / 4; CS_LOCALS(r300); if (!r300screen->caps->has_tcl) { @@ -395,10 +486,10 @@ void r300_emit_vertex_shader(struct r300_context* r300, return; } - if (constants->count) { - BEGIN_CS(14 + (vs->instruction_count * 4) + (constants->count * 4)); + if (code->constants.Count) { + BEGIN_CS(14 + code->length + (code->constants.Count * 4)); } else { - BEGIN_CS(11 + (vs->instruction_count * 4)); + BEGIN_CS(11 + code->length); } /* R300_VAP_PVS_CODE_CNTL_0 @@ -408,30 +499,27 @@ void r300_emit_vertex_shader(struct r300_context* r300, * XXX these could be optimized to select better values... */ OUT_CS_REG_SEQ(R300_VAP_PVS_CODE_CNTL_0, 3); OUT_CS(R300_PVS_FIRST_INST(0) | - R300_PVS_XYZW_VALID_INST(vs->instruction_count - 1) | - R300_PVS_LAST_INST(vs->instruction_count - 1)); - OUT_CS(R300_PVS_MAX_CONST_ADDR(constants->count - 1)); - OUT_CS(vs->instruction_count - 1); + R300_PVS_XYZW_VALID_INST(instruction_count - 1) | + R300_PVS_LAST_INST(instruction_count - 1)); + OUT_CS(R300_PVS_MAX_CONST_ADDR(code->constants.Count - 1)); + OUT_CS(instruction_count - 1); OUT_CS_REG(R300_VAP_PVS_VECTOR_INDX_REG, 0); - OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, vs->instruction_count * 4); - for (i = 0; i < vs->instruction_count; i++) { - OUT_CS(vs->instructions[i].inst0); - OUT_CS(vs->instructions[i].inst1); - OUT_CS(vs->instructions[i].inst2); - OUT_CS(vs->instructions[i].inst3); - } + OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, code->length); + for (i = 0; i < code->length; i++) + OUT_CS(code->body.d[i]); - if (constants->count) { + if (code->constants.Count) { OUT_CS_REG(R300_VAP_PVS_VECTOR_INDX_REG, (r300screen->caps->is_r500 ? R500_PVS_CONST_START : R300_PVS_CONST_START)); - OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, constants->count * 4); - for (i = 0; i < constants->count; i++) { - OUT_CS_32F(constants->constants[i][0]); - OUT_CS_32F(constants->constants[i][1]); - OUT_CS_32F(constants->constants[i][2]); - OUT_CS_32F(constants->constants[i][3]); + OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, code->constants.Count * 4); + for (i = 0; i < code->constants.Count; i++) { + const float * data = get_shader_constant(r300, &code->constants.Constants[i], constants); + OUT_CS_32F(data[0]); + OUT_CS_32F(data[1]); + OUT_CS_32F(data[2]); + OUT_CS_32F(data[3]); } } @@ -443,6 +531,12 @@ void r300_emit_vertex_shader(struct r300_context* r300, END_CS; } +void r300_emit_vertex_shader(struct r300_context* r300, + struct r300_vertex_shader* vs) +{ + r300_emit_vertex_program_code(r300, &vs->code, &r300->shader_constants[PIPE_SHADER_VERTEX]); +} + void r300_emit_viewport_state(struct r300_context* r300, struct r300_viewport_state* viewport) { @@ -564,11 +658,9 @@ validate: if (r300->dirty_state & R300_NEW_FRAGMENT_SHADER) { if (r300screen->caps->is_r500) { - r500_emit_fragment_shader(r300, - (struct r5xx_fragment_shader*)r300->fs); + r500_emit_fragment_program_code(r300, &r300->fs->code, &r300->shader_constants[PIPE_SHADER_FRAGMENT]); } else { - r300_emit_fragment_shader(r300, - (struct r3xx_fragment_shader*)r300->fs); + r300_emit_fragment_program_code(r300, &r300->fs->code, &r300->shader_constants[PIPE_SHADER_FRAGMENT]); } r300->dirty_state &= ~R300_NEW_FRAGMENT_SHADER; } diff --git a/src/gallium/drivers/r300/r300_emit.h b/src/gallium/drivers/r300/r300_emit.h index fda26f3948..350691d592 100644 --- a/src/gallium/drivers/r300/r300_emit.h +++ b/src/gallium/drivers/r300/r300_emit.h @@ -30,6 +30,9 @@ #include "r300_screen.h" #include "r300_state_inlines.h" +struct rX00_fragment_program_code; +struct r300_vertex_program_code; + void r300_emit_blend_state(struct r300_context* r300, struct r300_blend_state* blend); @@ -42,11 +45,13 @@ void r300_emit_clip_state(struct r300_context* r300, void r300_emit_dsa_state(struct r300_context* r300, struct r300_dsa_state* dsa); -void r300_emit_fragment_shader(struct r300_context* r300, - struct r3xx_fragment_shader* fs); +void r300_emit_fragment_program_code(struct r300_context* r300, + struct rX00_fragment_program_code* generic_code, + struct r300_constant_buffer* externals); -void r500_emit_fragment_shader(struct r300_context* r300, - struct r5xx_fragment_shader* fs); +void r500_emit_fragment_program_code(struct r300_context* r300, + struct rX00_fragment_program_code* generic_code, + struct r300_constant_buffer* externals); void r300_emit_fb_state(struct r300_context* r300, struct pipe_framebuffer_state* fb); @@ -68,6 +73,10 @@ void r300_emit_vertex_buffer(struct r300_context* r300); void r300_emit_vertex_format_state(struct r300_context* r300); +void r300_emit_vertex_program_code(struct r300_context* r300, + struct r300_vertex_program_code* code, + struct r300_constant_buffer* constants); + void r300_emit_vertex_shader(struct r300_context* r300, struct r300_vertex_shader* vs); diff --git a/src/gallium/drivers/r300/r300_fs.c b/src/gallium/drivers/r300/r300_fs.c index ca8ef99902..36463b9a2e 100644 --- a/src/gallium/drivers/r300/r300_fs.c +++ b/src/gallium/drivers/r300/r300_fs.c @@ -23,89 +23,115 @@ #include "r300_fs.h" -void r300_translate_fragment_shader(struct r300_context* r300, - struct r300_fragment_shader* fs) -{ - struct tgsi_parse_context parser; - int i; - boolean is_r500 = r300_screen(r300->context.screen)->caps->is_r500; - struct r300_constant_buffer* consts = - &r300->shader_constants[PIPE_SHADER_FRAGMENT]; +#include "r300_tgsi_to_rc.h" - struct r300_fs_asm* assembler = CALLOC_STRUCT(r300_fs_asm); - if (assembler == NULL) { - return; - } - /* Setup starting offset for immediates. */ - assembler->imm_offset = consts->user_count; - /* Enable depth writes, if needed. */ - assembler->writes_depth = fs->info.writes_z; - - /* Make sure we start at the beginning of the shader. */ - if (is_r500) { - ((struct r5xx_fragment_shader*)fs)->instruction_count = 0; - } +#include "radeon_compiler.h" - tgsi_parse_init(&parser, fs->state.tokens); +static void find_output_registers(struct r300_fragment_program_compiler * compiler, + struct r300_fragment_shader * fs) +{ + unsigned i; - while (!tgsi_parse_end_of_tokens(&parser)) { - tgsi_parse_token(&parser); + /* Mark the outputs as not present initially */ + compiler->OutputColor = fs->info.num_outputs; + compiler->OutputDepth = fs->info.num_outputs; - /* This is seriously the lamest way to create fragment programs ever. - * I blame TGSI. */ - switch (parser.FullToken.Token.Type) { - case TGSI_TOKEN_TYPE_DECLARATION: - /* Allocated registers sitting at the beginning - * of the program. */ - r300_fs_declare(assembler, &parser.FullToken.FullDeclaration); + /* Now see where they really are. */ + for(i = 0; i < fs->info.num_outputs; ++i) { + switch(fs->info.output_semantic_name[i]) { + case TGSI_SEMANTIC_COLOR: + compiler->OutputColor = i; + break; + case TGSI_SEMANTIC_POSITION: + compiler->OutputDepth = i; break; - case TGSI_TOKEN_TYPE_IMMEDIATE: - debug_printf("r300: Emitting immediate to constant buffer, " - "position %d\n", - assembler->imm_offset + assembler->imm_count); - /* I am not amused by the length of these. */ - for (i = 0; i < 4; i++) { - consts->constants[assembler->imm_offset + - assembler->imm_count][i] = - parser.FullToken.FullImmediate.u[i].Float; - } - assembler->imm_count++; + } + } +} + +static void allocate_hardware_inputs( + struct r300_fragment_program_compiler * c, + void (*allocate)(void * data, unsigned input, unsigned hwreg), + void * mydata) +{ + struct tgsi_shader_info* info = &((struct r300_fragment_shader*)c->UserData)->info; + int total_colors = 0; + int colors = 0; + int total_generic = 0; + int generic = 0; + int i; + + for (i = 0; i < info->num_inputs; i++) { + switch (info->input_semantic_name[i]) { + case TGSI_SEMANTIC_COLOR: + total_colors++; break; - case TGSI_TOKEN_TYPE_INSTRUCTION: - if (is_r500) { - r5xx_fs_instruction((struct r5xx_fragment_shader*)fs, - assembler, &parser.FullToken.FullInstruction); - } else { - r3xx_fs_instruction((struct r3xx_fragment_shader*)fs, - assembler, &parser.FullToken.FullInstruction); - } + case TGSI_SEMANTIC_FOG: + case TGSI_SEMANTIC_GENERIC: + total_generic++; break; } } - debug_printf("r300: fs: %d texs and %d colors, first free reg is %d\n", - assembler->tex_count, assembler->color_count, - assembler->tex_count + assembler->color_count); - - consts->count = consts->user_count + assembler->imm_count; - fs->uses_imms = assembler->imm_count; - debug_printf("r300: fs: %d total constants, " - "%d from user and %d from immediates\n", consts->count, - consts->user_count, assembler->imm_count); - r3xx_fs_finalize(fs, assembler); - if (is_r500) { - r5xx_fs_finalize((struct r5xx_fragment_shader*)fs, assembler); + for(i = 0; i < info->num_inputs; i++) { + switch (info->input_semantic_name[i]) { + case TGSI_SEMANTIC_COLOR: + allocate(mydata, i, colors); + colors++; + break; + case TGSI_SEMANTIC_FOG: + case TGSI_SEMANTIC_GENERIC: + allocate(mydata, i, total_colors + generic); + generic++; + break; + } } +} + +void r300_translate_fragment_shader(struct r300_context* r300, + struct r300_fragment_shader* fs) +{ + struct r300_fragment_program_compiler compiler; + struct tgsi_to_rc ttr; - tgsi_dump(fs->state.tokens, 0); - /* XXX finish r300 dumper too */ - if (is_r500) { - r5xx_fs_dump((struct r5xx_fragment_shader*)fs); + memset(&compiler, 0, sizeof(compiler)); + rc_init(&compiler.Base); + compiler.Base.Debug = 1; + + compiler.code = &fs->code; + compiler.is_r500 = r300_screen(r300->context.screen)->caps->is_r500; + compiler.AllocateHwInputs = &allocate_hardware_inputs; + compiler.UserData = fs; + + /* TODO: Program compilation depends on texture compare modes, + * which are sampler state. Therefore, programs need to be recompiled + * depending on this state as in the classic Mesa driver. + * + * This is not yet handled correctly. + */ + + find_output_registers(&compiler, fs); + + if (compiler.Base.Debug) { + debug_printf("r300: Initial fragment program\n"); + tgsi_dump(fs->state.tokens, 0); } - tgsi_parse_free(&parser); - FREE(assembler); + /* Translate TGSI to our internal representation */ + ttr.compiler = &compiler.Base; + ttr.info = &fs->info; + + r300_tgsi_to_rc(&ttr, fs->state.tokens); + + /* Invoke the compiler */ + r3xx_compile_fragment_program(&compiler); + if (compiler.Base.Error) { + /* Todo: Fail gracefully */ + fprintf(stderr, "r300 FP: Compiler error\n"); + abort(); + } /* And, finally... */ + rc_destroy(&compiler.Base); fs->translated = TRUE; } diff --git a/src/gallium/drivers/r300/r300_fs.h b/src/gallium/drivers/r300/r300_fs.h index 18deb7a05e..9fab789402 100644 --- a/src/gallium/drivers/r300/r300_fs.h +++ b/src/gallium/drivers/r300/r300_fs.h @@ -30,6 +30,21 @@ #include "r3xx_fs.h" #include "r5xx_fs.h" +#include "radeon_code.h" + +struct r300_fragment_shader { + /* Parent class */ + struct pipe_shader_state state; + struct tgsi_shader_info info; + + /* Has this shader been translated yet? */ + boolean translated; + + /* Compiled code */ + struct rX00_fragment_program_code code; +}; + + void r300_translate_fragment_shader(struct r300_context* r300, struct r300_fragment_shader* fs); diff --git a/src/gallium/drivers/r300/r300_fs_inlines.h b/src/gallium/drivers/r300/r300_fs_inlines.h deleted file mode 100644 index be4be9465e..0000000000 --- a/src/gallium/drivers/r300/r300_fs_inlines.h +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com> - * Joakim Sindholt <opensource@zhasha.com> - * - * 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 - * on 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 AUTHOR(S) AND/OR THEIR 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 R300_FS_INLINES_H -#define R300_FS_INLINES_H - -#include "tgsi/tgsi_parse.h" - -#include "r300_context.h" -#include "r300_debug.h" -#include "r300_reg.h" -#include "r300_screen.h" -#include "r300_shader_inlines.h" - -/* Temporary struct used to hold assembly state while putting together - * fragment programs. */ -struct r300_fs_asm { - /* Pipe context. */ - struct r300_context* r300; - /* Number of colors. */ - unsigned color_count; - /* Number of texcoords. */ - unsigned tex_count; - /* Offset for temporary registers. Inputs and temporaries have no - * distinguishing markings, so inputs start at 0 and the first usable - * temporary register is after all inputs. */ - unsigned temp_offset; - /* Number of requested temporary registers. */ - unsigned temp_count; - /* Offset for immediate constants. Neither R300 nor R500 can do four - * inline constants per source, so instead we copy immediates into the - * constant buffer. */ - unsigned imm_offset; - /* Number of immediate constants. */ - unsigned imm_count; - /* Are depth writes enabled? */ - boolean writes_depth; - /* Depth write offset. This is the TGSI output that corresponds to - * depth writes. */ - unsigned depth_output; -}; - -static INLINE void r300_fs_declare(struct r300_fs_asm* assembler, - struct tgsi_full_declaration* decl) -{ - switch (decl->Declaration.File) { - case TGSI_FILE_INPUT: - switch (decl->Semantic.SemanticName) { - case TGSI_SEMANTIC_COLOR: - assembler->color_count++; - break; - case TGSI_SEMANTIC_FOG: - case TGSI_SEMANTIC_GENERIC: - assembler->tex_count++; - break; - default: - debug_printf("r300: fs: Bad semantic declaration %d\n", - decl->Semantic.SemanticName); - break; - } - break; - case TGSI_FILE_OUTPUT: - /* Depth write. Mark the position of the output so we can - * identify it later. */ - if (decl->Semantic.SemanticName == TGSI_SEMANTIC_POSITION) { - assembler->depth_output = decl->DeclarationRange.First; - } - break; - case TGSI_FILE_CONSTANT: - break; - case TGSI_FILE_TEMPORARY: - assembler->temp_count++; - break; - default: - debug_printf("r300: fs: Bad file %d\n", decl->Declaration.File); - break; - } - - assembler->temp_offset = assembler->color_count + assembler->tex_count; -} - -static INLINE unsigned r300_fs_src(struct r300_fs_asm* assembler, - struct tgsi_src_register* src) -{ - switch (src->File) { - case TGSI_FILE_NULL: - return 0; - case TGSI_FILE_INPUT: - /* XXX may be wrong */ - return src->Index; - break; - case TGSI_FILE_TEMPORARY: - return src->Index + assembler->temp_offset; - break; - case TGSI_FILE_IMMEDIATE: - return (src->Index + assembler->imm_offset) | (1 << 8); - break; - case TGSI_FILE_CONSTANT: - /* XXX magic */ - return src->Index | (1 << 8); - break; - default: - debug_printf("r300: fs: Unimplemented src %d\n", src->File); - break; - } - return 0; -} - -static INLINE unsigned r300_fs_dst(struct r300_fs_asm* assembler, - struct tgsi_dst_register* dst) -{ - switch (dst->File) { - case TGSI_FILE_NULL: - /* This happens during KIL instructions. */ - return 0; - break; - case TGSI_FILE_OUTPUT: - return 0; - break; - case TGSI_FILE_TEMPORARY: - return dst->Index + assembler->temp_offset; - break; - default: - debug_printf("r300: fs: Unimplemented dst %d\n", dst->File); - break; - } - return 0; -} - -static INLINE boolean r300_fs_is_depr(struct r300_fs_asm* assembler, - struct tgsi_dst_register* dst) -{ - return (assembler->writes_depth && - (dst->File == TGSI_FILE_OUTPUT) && - (dst->Index == assembler->depth_output)); -} - -#endif /* R300_FS_INLINES_H */ diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c index 258e4ac7b2..96a7304621 100644 --- a/src/gallium/drivers/r300/r300_screen.c +++ b/src/gallium/drivers/r300/r300_screen.c @@ -322,13 +322,14 @@ r300_get_tex_transfer(struct pipe_screen *screen, trans = CALLOC_STRUCT(r300_transfer); if (trans) { pipe_texture_reference(&trans->transfer.texture, texture); - trans->transfer.format = trans->transfer.format; + trans->transfer.format = texture->format; trans->transfer.width = w; trans->transfer.height = h; trans->transfer.block = texture->block; trans->transfer.nblocksx = texture->nblocksx[level]; trans->transfer.nblocksy = texture->nblocksy[level]; - trans->transfer.stride = tex->stride; + trans->transfer.stride = align(pf_get_stride(&trans->transfer.block, + texture->width[level]), 32); trans->transfer.usage = usage; trans->offset = offset; } diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index 162740f594..a02fb34b2a 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -32,6 +32,7 @@ #include "r300_reg.h" #include "r300_state_inlines.h" #include "r300_fs.h" +#include "r300_vs.h" /* r300_state: Functions used to intialize state context by translating * Gallium state objects into semi-native r300 state objects. */ @@ -137,7 +138,6 @@ static void const struct pipe_constant_buffer* buffer) { struct r300_context* r300 = r300_context(pipe); - int i = r300->shader_constants[shader].user_count; /* This entire chunk of code seems ever-so-slightly baked. * It's as if I've got pipe_buffer* matryoshkas... */ @@ -148,27 +148,13 @@ static void map, buffer->buffer->size); pipe->winsys->buffer_unmap(pipe->winsys, buffer->buffer); - r300->shader_constants[shader].user_count = + r300->shader_constants[shader].count = buffer->buffer->size / (sizeof(float) * 4); } else { - r300->shader_constants[shader].user_count = 0; + r300->shader_constants[shader].count = 0; } r300->dirty_state |= R300_NEW_CONSTANTS; -#if 0 - /* If the number of constants have changed, invalidate the shader. */ - if (r300->shader_constants[shader].user_count != i) { - if (shader == PIPE_SHADER_FRAGMENT && r300->fs && - r300->fs->uses_imms) { - r300->fs->translated = FALSE; - r300_translate_fragment_shader(r300, r300->fs); - } else if (shader == PIPE_SHADER_VERTEX && r300->vs && - r300->vs->uses_imms) { - r300->vs->translated = FALSE; - r300_translate_vertex_shader(r300, r300->vs); - } - } -#endif } /* Create a new depth, stencil, and alpha state based on the CSO dsa state. @@ -285,14 +271,9 @@ static void static void* r300_create_fs_state(struct pipe_context* pipe, const struct pipe_shader_state* shader) { - struct r300_context* r300 = r300_context(pipe); struct r300_fragment_shader* fs = NULL; - if (r300_screen(r300->context.screen)->caps->is_r500) { - fs = (struct r300_fragment_shader*)CALLOC_STRUCT(r5xx_fragment_shader); - } else { - fs = (struct r300_fragment_shader*)CALLOC_STRUCT(r3xx_fragment_shader); - } + fs = (struct r300_fragment_shader*)CALLOC_STRUCT(r300_fragment_shader); /* Copy state directly into shader. */ fs->state = *shader; @@ -325,6 +306,7 @@ static void r300_bind_fs_state(struct pipe_context* pipe, void* shader) static void r300_delete_fs_state(struct pipe_context* pipe, void* shader) { struct r300_fragment_shader* fs = (struct r300_fragment_shader*)shader; + rc_constants_destroy(&fs->code.constants); FREE(fs->state.tokens); FREE(shader); } @@ -688,6 +670,7 @@ static void r300_delete_vs_state(struct pipe_context* pipe, void* shader) if (r300_screen(pipe->screen)->caps->has_tcl) { struct r300_vertex_shader* vs = (struct r300_vertex_shader*)shader; + rc_constants_destroy(&vs->code.constants); draw_delete_vertex_shader(r300->draw, vs->draw); FREE(vs->state.tokens); FREE(shader); diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c index 2477b30822..ea670f41fb 100644 --- a/src/gallium/drivers/r300/r300_state_derived.c +++ b/src/gallium/drivers/r300/r300_state_derived.c @@ -22,6 +22,9 @@ #include "r300_state_derived.h" +#include "r300_fs.h" +#include "r300_vs.h" + /* r300_state_derived: Various bits of state which are dependent upon * currently bound CSO data. */ diff --git a/src/gallium/drivers/r300/r300_state_invariant.c b/src/gallium/drivers/r300/r300_state_invariant.c index 430129d5bd..1e92374a4e 100644 --- a/src/gallium/drivers/r300/r300_state_invariant.c +++ b/src/gallium/drivers/r300/r300_state_invariant.c @@ -34,7 +34,7 @@ void r300_emit_invariant_state(struct r300_context* r300) struct r300_capabilities* caps = r300_screen(r300->context.screen)->caps; CS_LOCALS(r300); - BEGIN_CS(22 + (caps->has_tcl ? 2: 0)); + BEGIN_CS(24 + (caps->has_tcl ? 2: 0)); /*** Graphics Backend (GB) ***/ /* Various GB enables */ @@ -56,6 +56,7 @@ void r300_emit_invariant_state(struct r300_context* r300) OUT_CS_REG(R300_FG_FOG_COLOR_G, 0x0); OUT_CS_REG(R300_FG_FOG_COLOR_B, 0x0); OUT_CS_REG(R300_FG_DEPTH_SRC, 0x0); + OUT_CS_REG(R300_US_W_FMT, 0x0); /*** VAP ***/ /* Max and min vertex index clamp. */ @@ -72,7 +73,7 @@ void r300_emit_invariant_state(struct r300_context* r300) END_CS; /* XXX unsorted stuff from surface_fill */ - BEGIN_CS(71 + (caps->has_tcl ? 5 : 0) + (caps->is_r500 ? 4 : 0)); + BEGIN_CS(64 + (caps->has_tcl ? 5 : 0) + (caps->is_r500 ? 4 : 0)); /* Flush PVS. */ OUT_CS_REG(R300_VAP_PVS_STATE_FLUSH_REG, 0x0); @@ -132,11 +133,5 @@ void r300_emit_invariant_state(struct r300_context* r300) /* XXX */ OUT_CS_REG(R300_SC_CLIP_RULE, 0xaaaa); - OUT_CS_REG_SEQ(R300_US_OUT_FMT_0, 4); - OUT_CS(R300_C0_SEL_B | R300_C1_SEL_G | R300_C2_SEL_R | R300_C3_SEL_A); - OUT_CS(R300_US_OUT_FMT_UNUSED); - OUT_CS(R300_US_OUT_FMT_UNUSED); - OUT_CS(R300_US_OUT_FMT_UNUSED); - OUT_CS_REG(R300_US_W_FMT, R300_W_FMT_W0); END_CS; } diff --git a/src/gallium/drivers/r300/r300_surface.c b/src/gallium/drivers/r300/r300_surface.c index 25168ce5e9..a093f83945 100644 --- a/src/gallium/drivers/r300/r300_surface.c +++ b/src/gallium/drivers/r300/r300_surface.c @@ -37,7 +37,7 @@ static void r300_surface_setup(struct r300_context* r300, r300_emit_dsa_state(r300, &dsa_clear_state); r300_emit_rs_state(r300, &rs_clear_state); - BEGIN_CS(24); + BEGIN_CS(26); /* Viewport setup */ OUT_CS_REG_SEQ(R300_SE_VPORT_XSCALE, 6); @@ -78,8 +78,10 @@ static void r300_surface_setup(struct r300_context* r300, /* Setup colorbuffer. */ OUT_CS_REG_SEQ(R300_RB3D_COLOROFFSET0, 1); OUT_CS_RELOC(dest->buffer, 0, 0, RADEON_GEM_DOMAIN_VRAM, 0); - OUT_CS_REG(R300_RB3D_COLORPITCH0, pixpitch | - r300_translate_colorformat(dest->tex.format)); + OUT_CS_REG_SEQ(R300_RB3D_COLORPITCH0, 1); + OUT_CS_RELOC(dest->buffer, pixpitch | + r300_translate_colorformat(dest->tex.format), 0, + RADEON_GEM_DOMAIN_VRAM, 0); OUT_CS_REG(RB3D_COLOR_CHANNEL_MASK, 0xf); END_CS; @@ -139,10 +141,14 @@ validate: /* Vertex shader setup */ if (caps->has_tcl) { - r300_emit_vertex_shader(r300, &r300_passthrough_vertex_shader); + r300_emit_vertex_program_code(r300, &r300_passthrough_vertex_shader, 0); } else { BEGIN_CS(4); - OUT_CS_REG(R300_VAP_CNTL_STATUS, R300_VAP_TCL_BYPASS); + OUT_CS_REG(R300_VAP_CNTL_STATUS, +#ifdef PIPE_ARCH_BIG_ENDIAN + R300_VC_32BIT_SWAP | +#endif + R300_VAP_TCL_BYPASS); OUT_CS_REG(R300_VAP_CNTL, R300_PVS_NUM_SLOTS(5) | R300_PVS_NUM_CNTLRS(5) | R300_PVS_NUM_FPUS(caps->num_vert_fpus) | @@ -152,10 +158,10 @@ validate: /* Fragment shader setup */ if (caps->is_r500) { - r500_emit_fragment_shader(r300, &r5xx_passthrough_fragment_shader); + r500_emit_fragment_program_code(r300, &r5xx_passthrough_fragment_shader, 0); r300_emit_rs_block_state(r300, &r5xx_rs_block_clear_state); } else { - r300_emit_fragment_shader(r300, &r3xx_passthrough_fragment_shader); + r300_emit_fragment_program_code(r300, &r3xx_passthrough_fragment_shader, 0); r300_emit_rs_block_state(r300, &r3xx_rs_block_clear_state); } @@ -277,10 +283,14 @@ validate: /* Vertex shader setup */ if (caps->has_tcl) { - r300_emit_vertex_shader(r300, &r300_passthrough_vertex_shader); + r300_emit_vertex_program_code(r300, &r300_passthrough_vertex_shader, 0); } else { BEGIN_CS(4); - OUT_CS_REG(R300_VAP_CNTL_STATUS, R300_VAP_TCL_BYPASS); + OUT_CS_REG(R300_VAP_CNTL_STATUS, +#ifdef PIPE_ARCH_BIG_ENDIAN + R300_VC_32BIT_SWAP | +#endif + R300_VAP_TCL_BYPASS); OUT_CS_REG(R300_VAP_CNTL, R300_PVS_NUM_SLOTS(5) | R300_PVS_NUM_CNTLRS(5) | R300_PVS_NUM_FPUS(caps->num_vert_fpus) | @@ -290,10 +300,10 @@ validate: /* Fragment shader setup */ if (caps->is_r500) { - r500_emit_fragment_shader(r300, &r5xx_texture_fragment_shader); + r500_emit_fragment_program_code(r300, &r5xx_texture_fragment_shader, 0); r300_emit_rs_block_state(r300, &r5xx_rs_block_copy_state); } else { - r300_emit_fragment_shader(r300, &r3xx_texture_fragment_shader); + r300_emit_fragment_program_code(r300, &r3xx_texture_fragment_shader, 0); r300_emit_rs_block_state(r300, &r3xx_rs_block_copy_state); } diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c index daf1647bee..590052509c 100644 --- a/src/gallium/drivers/r300/r300_texture.c +++ b/src/gallium/drivers/r300/r300_texture.c @@ -22,13 +22,6 @@ #include "r300_texture.h" -/* XXX maths need to go to util */ - -static int minify(int i) -{ - return MAX2(1, i >> 1); -} - static void r300_setup_texture_state(struct r300_texture* tex, unsigned width, unsigned height, @@ -81,13 +74,11 @@ static void r300_setup_miptree(struct r300_texture* tex) * XXX * POT, uncompressed, unmippmapped textures can be aligned to 32, * instead of 64. */ - stride = align( - (base->nblocksx[i] * base->block.size) / base->block.width, - 32); + stride = align(pf_get_stride(&base->block, base->width[i]), 32); size = stride * base->nblocksy[i] * base->depth[i]; tex->offset[i] = align(tex->size, 32); - tex->size += tex->offset[i] + size; + tex->size = tex->offset[i] + size; debug_printf("r300: Texture miptree: Level %d " "(%dx%dx%d px, pitch %d bytes)\n", diff --git a/src/gallium/drivers/r300/r300_tgsi_to_rc.c b/src/gallium/drivers/r300/r300_tgsi_to_rc.c new file mode 100644 index 0000000000..3adbb715f3 --- /dev/null +++ b/src/gallium/drivers/r300/r300_tgsi_to_rc.c @@ -0,0 +1,337 @@ +/* + * Copyright 2009 Nicolai Hähnle <nhaehnle@gmail.com> + * + * 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 + * on 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 COPYRIGHT HOLDER(S) AND/OR THEIR 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 "r300_tgsi_to_rc.h" + +#include "radeon_compiler.h" +#include "radeon_program.h" + +#include "tgsi/tgsi_parse.h" +#include "tgsi/tgsi_scan.h" +#include "tgsi/tgsi_util.h" + + +static unsigned translate_opcode(unsigned opcode) +{ + switch(opcode) { + case TGSI_OPCODE_ARL: return OPCODE_ARL; + case TGSI_OPCODE_MOV: return OPCODE_MOV; + case TGSI_OPCODE_LIT: return OPCODE_LIT; + case TGSI_OPCODE_RCP: return OPCODE_RCP; + case TGSI_OPCODE_RSQ: return OPCODE_RSQ; + case TGSI_OPCODE_EXP: return OPCODE_EXP; + case TGSI_OPCODE_LOG: return OPCODE_LOG; + case TGSI_OPCODE_MUL: return OPCODE_MUL; + case TGSI_OPCODE_ADD: return OPCODE_ADD; + case TGSI_OPCODE_DP3: return OPCODE_DP3; + case TGSI_OPCODE_DP4: return OPCODE_DP4; + case TGSI_OPCODE_DST: return OPCODE_DST; + case TGSI_OPCODE_MIN: return OPCODE_MIN; + case TGSI_OPCODE_MAX: return OPCODE_MAX; + case TGSI_OPCODE_SLT: return OPCODE_SLT; + case TGSI_OPCODE_SGE: return OPCODE_SGE; + case TGSI_OPCODE_MAD: return OPCODE_MAD; + case TGSI_OPCODE_SUB: return OPCODE_SUB; + case TGSI_OPCODE_LRP: return OPCODE_LRP; + /* case TGSI_OPCODE_CND: return OPCODE_CND; */ + /* case TGSI_OPCODE_CND0: return OPCODE_CND0; */ + case TGSI_OPCODE_DP2A: return OPCODE_DP2A; + /* gap */ + case TGSI_OPCODE_FRC: return OPCODE_FRC; + /* case TGSI_OPCODE_CLAMP: return OPCODE_CLAMP; */ + case TGSI_OPCODE_FLR: return OPCODE_FLR; + /* case TGSI_OPCODE_ROUND: return OPCODE_ROUND; */ + case TGSI_OPCODE_EX2: return OPCODE_EX2; + case TGSI_OPCODE_LG2: return OPCODE_LG2; + case TGSI_OPCODE_POW: return OPCODE_POW; + case TGSI_OPCODE_XPD: return OPCODE_XPD; + /* gap */ + case TGSI_OPCODE_ABS: return OPCODE_ABS; + case TGSI_OPCODE_RCC: return OPCODE_RCC; + case TGSI_OPCODE_DPH: return OPCODE_DPH; + case TGSI_OPCODE_COS: return OPCODE_COS; + case TGSI_OPCODE_DDX: return OPCODE_DDX; + case TGSI_OPCODE_DDY: return OPCODE_DDY; + /* case TGSI_OPCODE_KILP: return OPCODE_KILP; */ + case TGSI_OPCODE_PK2H: return OPCODE_PK2H; + case TGSI_OPCODE_PK2US: return OPCODE_PK2US; + case TGSI_OPCODE_PK4B: return OPCODE_PK4B; + case TGSI_OPCODE_PK4UB: return OPCODE_PK4UB; + case TGSI_OPCODE_RFL: return OPCODE_RFL; + case TGSI_OPCODE_SEQ: return OPCODE_SEQ; + case TGSI_OPCODE_SFL: return OPCODE_SFL; + case TGSI_OPCODE_SGT: return OPCODE_SGT; + case TGSI_OPCODE_SIN: return OPCODE_SIN; + case TGSI_OPCODE_SLE: return OPCODE_SLE; + case TGSI_OPCODE_SNE: return OPCODE_SNE; + case TGSI_OPCODE_STR: return OPCODE_STR; + case TGSI_OPCODE_TEX: return OPCODE_TEX; + case TGSI_OPCODE_TXD: return OPCODE_TXD; + case TGSI_OPCODE_TXP: return OPCODE_TXP; + case TGSI_OPCODE_UP2H: return OPCODE_UP2H; + case TGSI_OPCODE_UP2US: return OPCODE_UP2US; + case TGSI_OPCODE_UP4B: return OPCODE_UP4B; + case TGSI_OPCODE_UP4UB: return OPCODE_UP4UB; + case TGSI_OPCODE_X2D: return OPCODE_X2D; + case TGSI_OPCODE_ARA: return OPCODE_ARA; + case TGSI_OPCODE_ARR: return OPCODE_ARR; + case TGSI_OPCODE_BRA: return OPCODE_BRA; + case TGSI_OPCODE_CAL: return OPCODE_CAL; + case TGSI_OPCODE_RET: return OPCODE_RET; + case TGSI_OPCODE_SSG: return OPCODE_SSG; + case TGSI_OPCODE_CMP: return OPCODE_CMP; + case TGSI_OPCODE_SCS: return OPCODE_SCS; + case TGSI_OPCODE_TXB: return OPCODE_TXB; + /* case TGSI_OPCODE_NRM: return OPCODE_NRM; */ + /* case TGSI_OPCODE_DIV: return OPCODE_DIV; */ + case TGSI_OPCODE_DP2: return OPCODE_DP2; + case TGSI_OPCODE_TXL: return OPCODE_TXL; + case TGSI_OPCODE_BRK: return OPCODE_BRK; + case TGSI_OPCODE_IF: return OPCODE_IF; + /* case TGSI_OPCODE_LOOP: return OPCODE_LOOP; */ + /* case TGSI_OPCODE_REP: return OPCODE_REP; */ + case TGSI_OPCODE_ELSE: return OPCODE_ELSE; + case TGSI_OPCODE_ENDIF: return OPCODE_ENDIF; + case TGSI_OPCODE_ENDLOOP: return OPCODE_ENDLOOP; + /* case TGSI_OPCODE_ENDREP: return OPCODE_ENDREP; */ + case TGSI_OPCODE_PUSHA: return OPCODE_PUSHA; + case TGSI_OPCODE_POPA: return OPCODE_POPA; + /* case TGSI_OPCODE_CEIL: return OPCODE_CEIL; */ + /* case TGSI_OPCODE_I2F: return OPCODE_I2F; */ + case TGSI_OPCODE_NOT: return OPCODE_NOT; + case TGSI_OPCODE_TRUNC: return OPCODE_TRUNC; + /* case TGSI_OPCODE_SHL: return OPCODE_SHL; */ + /* case TGSI_OPCODE_SHR: return OPCODE_SHR; */ + case TGSI_OPCODE_AND: return OPCODE_AND; + case TGSI_OPCODE_OR: return OPCODE_OR; + /* case TGSI_OPCODE_MOD: return OPCODE_MOD; */ + case TGSI_OPCODE_XOR: return OPCODE_XOR; + /* case TGSI_OPCODE_SAD: return OPCODE_SAD; */ + /* case TGSI_OPCODE_TXF: return OPCODE_TXF; */ + /* case TGSI_OPCODE_TXQ: return OPCODE_TXQ; */ + case TGSI_OPCODE_CONT: return OPCODE_CONT; + /* case TGSI_OPCODE_EMIT: return OPCODE_EMIT; */ + /* case TGSI_OPCODE_ENDPRIM: return OPCODE_ENDPRIM; */ + /* case TGSI_OPCODE_BGNLOOP2: return OPCODE_BGNLOOP2; */ + case TGSI_OPCODE_BGNSUB: return OPCODE_BGNSUB; + /* case TGSI_OPCODE_ENDLOOP2: return OPCODE_ENDLOOP2; */ + case TGSI_OPCODE_ENDSUB: return OPCODE_ENDSUB; + case TGSI_OPCODE_NOISE1: return OPCODE_NOISE1; + case TGSI_OPCODE_NOISE2: return OPCODE_NOISE2; + case TGSI_OPCODE_NOISE3: return OPCODE_NOISE3; + case TGSI_OPCODE_NOISE4: return OPCODE_NOISE4; + case TGSI_OPCODE_NOP: return OPCODE_NOP; + /* gap */ + case TGSI_OPCODE_NRM4: return OPCODE_NRM4; + /* case TGSI_OPCODE_CALLNZ: return OPCODE_CALLNZ; */ + /* case TGSI_OPCODE_IFC: return OPCODE_IFC; */ + /* case TGSI_OPCODE_BREAKC: return OPCODE_BREAKC; */ + case TGSI_OPCODE_KIL: return OPCODE_KIL; + case TGSI_OPCODE_END: return OPCODE_END; + case TGSI_OPCODE_SWZ: return OPCODE_SWZ; + } + + fprintf(stderr, "Unknown opcode: %i\n", opcode); + abort(); +} + +static unsigned translate_saturate(unsigned saturate) +{ + switch(saturate) { + case TGSI_SAT_NONE: return SATURATE_OFF; + case TGSI_SAT_ZERO_ONE: return SATURATE_ZERO_ONE; + case TGSI_SAT_MINUS_PLUS_ONE: return SATURATE_PLUS_MINUS_ONE; + } + + fprintf(stderr, "Unknown saturate mode: %i\n", saturate); + abort(); +} + +static unsigned translate_register_file(unsigned file) +{ + switch(file) { + case TGSI_FILE_CONSTANT: return PROGRAM_CONSTANT; + case TGSI_FILE_IMMEDIATE: return PROGRAM_CONSTANT; + case TGSI_FILE_INPUT: return PROGRAM_INPUT; + case TGSI_FILE_OUTPUT: return PROGRAM_OUTPUT; + case TGSI_FILE_TEMPORARY: return PROGRAM_TEMPORARY; + case TGSI_FILE_ADDRESS: return PROGRAM_ADDRESS; + } + + fprintf(stderr, "Unhandled register file: %i\n", file); + abort(); +} + +static int translate_register_index( + struct tgsi_to_rc * ttr, + unsigned file, + int index) +{ + if (file == TGSI_FILE_IMMEDIATE) + return ttr->immediate_offset + index; + + return index; +} + +static void transform_dstreg( + struct tgsi_to_rc * ttr, + struct prog_dst_register * dst, + struct tgsi_full_dst_register * src) +{ + dst->File = translate_register_file(src->DstRegister.File); + dst->Index = translate_register_index(ttr, src->DstRegister.File, src->DstRegister.Index); + dst->WriteMask = src->DstRegister.WriteMask; + dst->RelAddr = src->DstRegister.Indirect; +} + +static void transform_srcreg( + struct tgsi_to_rc * ttr, + struct prog_src_register * dst, + struct tgsi_full_src_register * src) +{ + dst->File = translate_register_file(src->SrcRegister.File); + dst->Index = translate_register_index(ttr, src->SrcRegister.File, src->SrcRegister.Index); + dst->RelAddr = src->SrcRegister.Indirect; + dst->Swizzle = tgsi_util_get_full_src_register_extswizzle(src, 0); + dst->Swizzle |= tgsi_util_get_full_src_register_extswizzle(src, 1) << 3; + dst->Swizzle |= tgsi_util_get_full_src_register_extswizzle(src, 2) << 6; + dst->Swizzle |= tgsi_util_get_full_src_register_extswizzle(src, 3) << 9; + dst->Abs = src->SrcRegisterExtMod.Absolute; + dst->Negate = + src->SrcRegisterExtSwz.NegateX | + (src->SrcRegisterExtSwz.NegateY << 1) | + (src->SrcRegisterExtSwz.NegateZ << 2) | + (src->SrcRegisterExtSwz.NegateW << 3); + dst->Negate ^= src->SrcRegister.Negate ? NEGATE_XYZW : 0; +} + +static void transform_texture(struct rc_instruction * dst, struct tgsi_instruction_ext_texture src) +{ + switch(src.Texture) { + case TGSI_TEXTURE_1D: + dst->I.TexSrcTarget = TEXTURE_1D_INDEX; + break; + case TGSI_TEXTURE_2D: + dst->I.TexSrcTarget = TEXTURE_2D_INDEX; + break; + case TGSI_TEXTURE_3D: + dst->I.TexSrcTarget = TEXTURE_3D_INDEX; + break; + case TGSI_TEXTURE_CUBE: + dst->I.TexSrcTarget = TEXTURE_CUBE_INDEX; + break; + case TGSI_TEXTURE_RECT: + dst->I.TexSrcTarget = TEXTURE_RECT_INDEX; + break; + case TGSI_TEXTURE_SHADOW1D: + dst->I.TexSrcTarget = TEXTURE_1D_INDEX; + dst->I.TexShadow = 1; + break; + case TGSI_TEXTURE_SHADOW2D: + dst->I.TexSrcTarget = TEXTURE_2D_INDEX; + dst->I.TexShadow = 1; + break; + case TGSI_TEXTURE_SHADOWRECT: + dst->I.TexSrcTarget = TEXTURE_RECT_INDEX; + dst->I.TexShadow = 1; + break; + } +} + +static void transform_instruction(struct tgsi_to_rc * ttr, struct tgsi_full_instruction * src) +{ + if (src->Instruction.Opcode == TGSI_OPCODE_END) + return; + + struct rc_instruction * dst = rc_insert_new_instruction(ttr->compiler, ttr->compiler->Program.Instructions.Prev); + int i; + + dst->I.Opcode = translate_opcode(src->Instruction.Opcode); + dst->I.SaturateMode = translate_saturate(src->Instruction.Saturate); + + if (src->Instruction.NumDstRegs) + transform_dstreg(ttr, &dst->I.DstReg, &src->FullDstRegisters[0]); + + for(i = 0; i < src->Instruction.NumSrcRegs; ++i) { + if (src->FullSrcRegisters[i].SrcRegister.File == TGSI_FILE_SAMPLER) + dst->I.TexSrcUnit = src->FullSrcRegisters[i].SrcRegister.Index; + else + transform_srcreg(ttr, &dst->I.SrcReg[i], &src->FullSrcRegisters[i]); + } + + /* Texturing. */ + transform_texture(dst, src->InstructionExtTexture); +} + +static void handle_immediate(struct tgsi_to_rc * ttr, struct tgsi_full_immediate * imm) +{ + struct rc_constant constant; + int i; + + constant.Type = RC_CONSTANT_IMMEDIATE; + constant.Size = 4; + for(i = 0; i < 4; ++i) + constant.u.Immediate[i] = imm->u[i].Float; + rc_constants_add(&ttr->compiler->Program.Constants, &constant); +} + +void r300_tgsi_to_rc(struct tgsi_to_rc * ttr, const struct tgsi_token * tokens) +{ + struct tgsi_parse_context parser; + int i; + + /* Allocate constants placeholders. + * + * Note: What if declared constants are not contiguous? */ + for(i = 0; i <= ttr->info->file_max[TGSI_FILE_CONSTANT]; ++i) { + struct rc_constant constant; + memset(&constant, 0, sizeof(constant)); + constant.Type = RC_CONSTANT_EXTERNAL; + constant.Size = 4; + constant.u.External = i; + rc_constants_add(&ttr->compiler->Program.Constants, &constant); + } + + ttr->immediate_offset = ttr->compiler->Program.Constants.Count; + + tgsi_parse_init(&parser, tokens); + + while (!tgsi_parse_end_of_tokens(&parser)) { + tgsi_parse_token(&parser); + + switch (parser.FullToken.Token.Type) { + case TGSI_TOKEN_TYPE_DECLARATION: + break; + case TGSI_TOKEN_TYPE_IMMEDIATE: + handle_immediate(ttr, &parser.FullToken.FullImmediate); + break; + case TGSI_TOKEN_TYPE_INSTRUCTION: + transform_instruction(ttr, &parser.FullToken.FullInstruction); + break; + } + } + + tgsi_parse_free(&parser); + + rc_calculate_inputs_outputs(ttr->compiler); +} + diff --git a/src/gallium/drivers/r300/r300_tgsi_to_rc.h b/src/gallium/drivers/r300/r300_tgsi_to_rc.h new file mode 100644 index 0000000000..93e90ec6d2 --- /dev/null +++ b/src/gallium/drivers/r300/r300_tgsi_to_rc.h @@ -0,0 +1,41 @@ +/* + * Copyright 2009 Nicolai Hähnle <nhaehnle@gmail.com> + * + * 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 + * on 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 COPYRIGHT HOLDER(S) AND/OR THEIR 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 R300_TGSI_TO_RC_H +#define R300_TGSI_TO_RC_H + +struct radeon_compiler; + +struct tgsi_full_declaration; +struct tgsi_shader_info; +struct tgsi_token; + +struct tgsi_to_rc { + struct radeon_compiler * compiler; + const struct tgsi_shader_info * info; + + int immediate_offset; +}; + +void r300_tgsi_to_rc(struct tgsi_to_rc * ttr, const struct tgsi_token * tokens); + +#endif /* R300_TGSI_TO_RC_H */ diff --git a/src/gallium/drivers/r300/r300_vs.c b/src/gallium/drivers/r300/r300_vs.c index 741a1b6989..2cb903bba2 100644 --- a/src/gallium/drivers/r300/r300_vs.c +++ b/src/gallium/drivers/r300/r300_vs.c @@ -22,393 +22,213 @@ #include "r300_vs.h" -static void r300_vs_declare(struct r300_vs_asm* assembler, - struct tgsi_full_declaration* decl) -{ - switch (decl->Declaration.File) { - case TGSI_FILE_INPUT: - break; - case TGSI_FILE_OUTPUT: - switch (decl->Semantic.SemanticName) { - case TGSI_SEMANTIC_POSITION: - assembler->tab[decl->DeclarationRange.First] = 0; - break; - case TGSI_SEMANTIC_COLOR: - assembler->tab[decl->DeclarationRange.First] = - (assembler->point_size ? 1 : 0) + - assembler->out_colors; - break; - case TGSI_SEMANTIC_FOG: - case TGSI_SEMANTIC_GENERIC: - /* XXX multiple? */ - assembler->tab[decl->DeclarationRange.First] = - (assembler->point_size ? 1 : 0) + - assembler->out_colors + - assembler->out_texcoords; - break; - case TGSI_SEMANTIC_PSIZE: - assembler->tab[decl->DeclarationRange.First] = 1; - break; - default: - debug_printf("r300: vs: Bad semantic declaration %d\n", - decl->Semantic.SemanticName); - break; - } - break; - case TGSI_FILE_CONSTANT: - break; - case TGSI_FILE_TEMPORARY: - assembler->temp_count++; - break; - default: - debug_printf("r300: vs: Bad file %d\n", decl->Declaration.File); - break; - } -} - -static INLINE unsigned r300_vs_src_type(struct r300_vs_asm* assembler, - struct tgsi_src_register* src) -{ - switch (src->File) { - case TGSI_FILE_NULL: - case TGSI_FILE_INPUT: - /* Probably a zero or one swizzle */ - return R300_PVS_SRC_REG_INPUT; - case TGSI_FILE_TEMPORARY: - return R300_PVS_SRC_REG_TEMPORARY; - case TGSI_FILE_CONSTANT: - case TGSI_FILE_IMMEDIATE: - return R300_PVS_SRC_REG_CONSTANT; - default: - debug_printf("r300: vs: Unimplemented src type %d\n", src->File); - break; - } - return 0; -} - -static INLINE unsigned r300_vs_src(struct r300_vs_asm* assembler, - struct tgsi_src_register* src) -{ - switch (src->File) { - case TGSI_FILE_NULL: - case TGSI_FILE_INPUT: - case TGSI_FILE_TEMPORARY: - case TGSI_FILE_CONSTANT: - return src->Index; - case TGSI_FILE_IMMEDIATE: - return src->Index + assembler->imm_offset; - default: - debug_printf("r300: vs: Unimplemented src type %d\n", src->File); - break; - } - return 0; -} - -static INLINE unsigned r300_vs_dst_type(struct r300_vs_asm* assembler, - struct tgsi_dst_register* dst) -{ - switch (dst->File) { - case TGSI_FILE_TEMPORARY: - return R300_PVS_DST_REG_TEMPORARY; - case TGSI_FILE_OUTPUT: - return R300_PVS_DST_REG_OUT; - default: - debug_printf("r300: vs: Unimplemented dst type %d\n", dst->File); - break; - } - return 0; -} - -static INLINE unsigned r300_vs_dst(struct r300_vs_asm* assembler, - struct tgsi_dst_register* dst) -{ - switch (dst->File) { - case TGSI_FILE_TEMPORARY: - return dst->Index; - case TGSI_FILE_OUTPUT: - return assembler->tab[dst->Index]; - default: - debug_printf("r300: vs: Unimplemented dst %d\n", dst->File); - break; - } - return 0; -} - -static uint32_t r300_vs_op(unsigned op) -{ - switch (op) { - case TGSI_OPCODE_DP3: - case TGSI_OPCODE_DP4: - return R300_VE_DOT_PRODUCT; - case TGSI_OPCODE_MUL: - return R300_VE_MULTIPLY; - case TGSI_OPCODE_ADD: - case TGSI_OPCODE_MOV: - case TGSI_OPCODE_SUB: - case TGSI_OPCODE_SWZ: - return R300_VE_ADD; - case TGSI_OPCODE_MAX: - return R300_VE_MAXIMUM; - case TGSI_OPCODE_SLT: - return R300_VE_SET_LESS_THAN; - case TGSI_OPCODE_RSQ: - return R300_PVS_DST_MATH_INST | R300_ME_RECIP_DX; - case TGSI_OPCODE_MAD: - return R300_PVS_DST_MACRO_INST | R300_PVS_MACRO_OP_2CLK_MADD; - default: - break; - } - return 0; -} - -static uint32_t r300_vs_swiz(struct tgsi_full_src_register* reg) -{ - if (reg->SrcRegister.Extended) { - return (reg->SrcRegister.Negate ? (0xf << 12) : 0) | - reg->SrcRegisterExtSwz.ExtSwizzleX | - (reg->SrcRegisterExtSwz.ExtSwizzleY << 3) | - (reg->SrcRegisterExtSwz.ExtSwizzleZ << 6) | - (reg->SrcRegisterExtSwz.ExtSwizzleW << 9); - } else { - return (reg->SrcRegister.Negate ? (0xf << 12) : 0) | - reg->SrcRegister.SwizzleX | - (reg->SrcRegister.SwizzleY << 3) | - (reg->SrcRegister.SwizzleZ << 6) | - (reg->SrcRegister.SwizzleW << 9); - } -} +#include "r300_context.h" +#include "r300_tgsi_to_rc.h" -/* XXX icky icky icky icky */ -static uint32_t r300_vs_scalar_swiz(struct tgsi_full_src_register* reg) -{ - if (reg->SrcRegister.Extended) { - return (reg->SrcRegister.Negate ? (0xf << 12) : 0) | - reg->SrcRegisterExtSwz.ExtSwizzleX | - (reg->SrcRegisterExtSwz.ExtSwizzleX << 3) | - (reg->SrcRegisterExtSwz.ExtSwizzleX << 6) | - (reg->SrcRegisterExtSwz.ExtSwizzleX << 9); - } else { - return (reg->SrcRegister.Negate ? (0xf << 12) : 0) | - reg->SrcRegister.SwizzleX | - (reg->SrcRegister.SwizzleX << 3) | - (reg->SrcRegister.SwizzleX << 6) | - (reg->SrcRegister.SwizzleX << 9); - } -} +#include "tgsi/tgsi_dump.h" +#include "tgsi/tgsi_parse.h" -/* XXX scalar stupidity */ -static void r300_vs_emit_inst(struct r300_vertex_shader* vs, - struct r300_vs_asm* assembler, - struct tgsi_full_src_register* src, - struct tgsi_full_dst_register* dst, - unsigned op, - unsigned count, - boolean is_scalar) -{ - int i = vs->instruction_count; - vs->instructions[i].inst0 = R300_PVS_DST_OPCODE(r300_vs_op(op)) | - R300_PVS_DST_REG_TYPE(r300_vs_dst_type(assembler, &dst->DstRegister)) | - R300_PVS_DST_OFFSET(r300_vs_dst(assembler, &dst->DstRegister)) | - R300_PVS_DST_WE(dst->DstRegister.WriteMask); - switch (count) { - case 3: - vs->instructions[i].inst3 = - R300_PVS_SRC_REG_TYPE(r300_vs_src_type(assembler, - &src[2].SrcRegister)) | - R300_PVS_SRC_OFFSET(r300_vs_src(assembler, - &src[2].SrcRegister)) | - R300_PVS_SRC_SWIZZLE(r300_vs_swiz(&src[2])); - /* Fall through */ - case 2: - vs->instructions[i].inst2 = - R300_PVS_SRC_REG_TYPE(r300_vs_src_type(assembler, - &src[1].SrcRegister)) | - R300_PVS_SRC_OFFSET(r300_vs_src(assembler, - &src[1].SrcRegister)) | - R300_PVS_SRC_SWIZZLE(r300_vs_swiz(&src[1])); - /* Fall through */ - case 1: - vs->instructions[i].inst1 = - R300_PVS_SRC_REG_TYPE(r300_vs_src_type(assembler, - &src[0].SrcRegister)) | - R300_PVS_SRC_OFFSET(r300_vs_src(assembler, - &src[0].SrcRegister)) | - /* XXX the icky, it burns */ - R300_PVS_SRC_SWIZZLE(is_scalar ? r300_vs_scalar_swiz(&src[0]) - : r300_vs_swiz(&src[0])); - break; - } - vs->instruction_count++; -} +#include "radeon_compiler.h" -static void r300_vs_instruction(struct r300_vertex_shader* vs, - struct r300_vs_asm* assembler, - struct tgsi_full_instruction* inst) -{ - switch (inst->Instruction.Opcode) { - case TGSI_OPCODE_RSQ: - r300_vs_emit_inst(vs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], inst->Instruction.Opcode, - 1, TRUE); - break; - case TGSI_OPCODE_SUB: - inst->FullSrcRegisters[1].SrcRegister.Negate = - !inst->FullSrcRegisters[1].SrcRegister.Negate; - /* Fall through */ - case TGSI_OPCODE_ADD: - case TGSI_OPCODE_MUL: - case TGSI_OPCODE_MAX: - case TGSI_OPCODE_SLT: - r300_vs_emit_inst(vs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], inst->Instruction.Opcode, - 2, FALSE); - break; - case TGSI_OPCODE_DP3: - /* Set alpha swizzle to zero for src0 and src1 */ - if (!inst->FullSrcRegisters[0].SrcRegister.Extended) { - inst->FullSrcRegisters[0].SrcRegister.Extended = TRUE; - inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleX = - inst->FullSrcRegisters[0].SrcRegister.SwizzleX; - inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleY = - inst->FullSrcRegisters[0].SrcRegister.SwizzleY; - inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleZ = - inst->FullSrcRegisters[0].SrcRegister.SwizzleZ; - } - inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleW = - TGSI_EXTSWIZZLE_ZERO; - if (!inst->FullSrcRegisters[1].SrcRegister.Extended) { - inst->FullSrcRegisters[1].SrcRegister.Extended = TRUE; - inst->FullSrcRegisters[1].SrcRegisterExtSwz.ExtSwizzleX = - inst->FullSrcRegisters[1].SrcRegister.SwizzleX; - inst->FullSrcRegisters[1].SrcRegisterExtSwz.ExtSwizzleY = - inst->FullSrcRegisters[1].SrcRegister.SwizzleY; - inst->FullSrcRegisters[1].SrcRegisterExtSwz.ExtSwizzleZ = - inst->FullSrcRegisters[1].SrcRegister.SwizzleZ; - } - inst->FullSrcRegisters[1].SrcRegisterExtSwz.ExtSwizzleW = - TGSI_EXTSWIZZLE_ZERO; - /* Fall through */ - case TGSI_OPCODE_DP4: - r300_vs_emit_inst(vs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], inst->Instruction.Opcode, - 2, FALSE); - break; - case TGSI_OPCODE_MOV: - case TGSI_OPCODE_SWZ: - inst->FullSrcRegisters[1] = r300_constant_zero; - r300_vs_emit_inst(vs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], inst->Instruction.Opcode, - 2, FALSE); - break; - case TGSI_OPCODE_MAD: - r300_vs_emit_inst(vs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], inst->Instruction.Opcode, - 3, FALSE); - break; - case TGSI_OPCODE_END: - break; - default: - debug_printf("r300: vs: Bad opcode %d\n", - inst->Instruction.Opcode); - break; - } -} -static void r300_vs_init(struct r300_vertex_shader* vs, - struct r300_vs_asm* assembler) +static void set_vertex_inputs_outputs(struct r300_vertex_program_compiler * c) { + struct r300_vertex_shader * vs = c->UserData; struct tgsi_shader_info* info = &vs->info; + boolean pointsize = false; + int out_colors = 0; + int colors = 0; + int out_generic = 0; + int generic = 0; int i; + /* Fill in the input mapping */ + for (i = 0; i < info->num_inputs; i++) + c->code->inputs[i] = i; + + /* Fill in the output mapping */ for (i = 0; i < info->num_outputs; i++) { switch (info->output_semantic_name[i]) { case TGSI_SEMANTIC_PSIZE: - assembler->point_size = TRUE; + pointsize = true; break; case TGSI_SEMANTIC_COLOR: - assembler->out_colors++; + out_colors++; break; case TGSI_SEMANTIC_FOG: case TGSI_SEMANTIC_GENERIC: - assembler->out_texcoords++; + out_generic++; break; } } - vs->instruction_count = 0; -} - -void r300_translate_vertex_shader(struct r300_context* r300, - struct r300_vertex_shader* vs) -{ struct tgsi_parse_context parser; - int i; - struct r300_constant_buffer* consts = - &r300->shader_constants[PIPE_SHADER_VERTEX]; - - struct r300_vs_asm* assembler = CALLOC_STRUCT(r300_vs_asm); - if (assembler == NULL) { - return; - } - - /* Init assembler. */ - r300_vs_init(vs, assembler); - - /* Setup starting offset for immediates. */ - assembler->imm_offset = consts->user_count; tgsi_parse_init(&parser, vs->state.tokens); while (!tgsi_parse_end_of_tokens(&parser)) { tgsi_parse_token(&parser); - /* This is seriously the lamest way to create fragment programs ever. - * I blame TGSI. */ - switch (parser.FullToken.Token.Type) { - case TGSI_TOKEN_TYPE_DECLARATION: - /* Allocated registers sitting at the beginning - * of the program. */ - r300_vs_declare(assembler, &parser.FullToken.FullDeclaration); + if (parser.FullToken.Token.Type != TGSI_TOKEN_TYPE_DECLARATION) + continue; + + struct tgsi_full_declaration * decl = &parser.FullToken.FullDeclaration; + + if (decl->Declaration.File != TGSI_FILE_OUTPUT) + continue; + + switch (decl->Semantic.SemanticName) { + case TGSI_SEMANTIC_POSITION: + c->code->outputs[decl->DeclarationRange.First] = 0; + break; + case TGSI_SEMANTIC_PSIZE: + c->code->outputs[decl->DeclarationRange.First] = 1; + break; + case TGSI_SEMANTIC_COLOR: + c->code->outputs[decl->DeclarationRange.First] = 1 + + (pointsize ? 1 : 0) + + colors++; break; - case TGSI_TOKEN_TYPE_IMMEDIATE: - debug_printf("r300: Emitting immediate to constant buffer, " - "position %d\n", - assembler->imm_offset + assembler->imm_count); - /* I am not amused by the length of these. */ - for (i = 0; i < 4; i++) { - consts->constants[assembler->imm_offset + - assembler->imm_count][i] = - parser.FullToken.FullImmediate.u[i].Float; - } - assembler->imm_count++; + case TGSI_SEMANTIC_FOG: + case TGSI_SEMANTIC_GENERIC: + c->code->outputs[decl->DeclarationRange.First] = 1 + + (pointsize ? 1 : 0) + + out_colors + + generic++; break; - case TGSI_TOKEN_TYPE_INSTRUCTION: - r300_vs_instruction(vs, assembler, - &parser.FullToken.FullInstruction); + default: + debug_printf("r300: vs: Bad semantic declaration %d\n", + decl->Semantic.SemanticName); break; } } - debug_printf("r300: vs: %d texs and %d colors, first free reg is %d\n", - assembler->tex_count, assembler->color_count, - assembler->tex_count + assembler->color_count); + tgsi_parse_free(&parser); +} - consts->count = consts->user_count + assembler->imm_count; - vs->uses_imms = assembler->imm_count; - debug_printf("r300: vs: %d total constants, " - "%d from user and %d from immediates\n", consts->count, - consts->user_count, assembler->imm_count); - debug_printf("r300: vs: tab: %d %d %d %d\n", assembler->tab[0], - assembler->tab[1], assembler->tab[2], assembler->tab[3]); +void r300_translate_vertex_shader(struct r300_context* r300, + struct r300_vertex_shader* vs) +{ + struct r300_vertex_program_compiler compiler; + struct tgsi_to_rc ttr; - tgsi_dump(vs->state.tokens, 0); - /* XXX finish r300 vertex shader dumper */ - r300_vs_dump(vs); + /* Setup the compiler */ + rc_init(&compiler.Base); - tgsi_parse_free(&parser); - FREE(assembler); + compiler.Base.Debug = 1; + compiler.code = &vs->code; + compiler.UserData = vs; + + if (compiler.Base.Debug) { + debug_printf("r300: Initial vertex program\n"); + tgsi_dump(vs->state.tokens, 0); + } + + /* Translate TGSI to our internal representation */ + ttr.compiler = &compiler.Base; + ttr.info = &vs->info; + + r300_tgsi_to_rc(&ttr, vs->state.tokens); + + compiler.RequiredOutputs = ~(~0 << vs->info.num_outputs); + compiler.SetHwInputOutput = &set_vertex_inputs_outputs; + + /* Invoke the compiler */ + r3xx_compile_vertex_program(&compiler); + if (compiler.Base.Error) { + /* Todo: Fail gracefully */ + fprintf(stderr, "r300 VP: Compiler error\n"); + abort(); + } /* And, finally... */ + rc_destroy(&compiler.Base); vs->translated = TRUE; } + + +/* XXX get these to r300_reg */ +#define R300_PVS_DST_OPCODE(x) ((x) << 0) +# define R300_VE_DOT_PRODUCT 1 +# define R300_VE_MULTIPLY 2 +# define R300_VE_ADD 3 +# define R300_VE_MAXIMUM 7 +# define R300_VE_SET_LESS_THAN 10 +#define R300_PVS_DST_MATH_INST (1 << 6) +# define R300_ME_RECIP_DX 6 +#define R300_PVS_DST_MACRO_INST (1 << 7) +# define R300_PVS_MACRO_OP_2CLK_MADD 0 +#define R300_PVS_DST_REG_TYPE(x) ((x) << 8) +# define R300_PVS_DST_REG_TEMPORARY 0 +# define R300_PVS_DST_REG_A0 1 +# define R300_PVS_DST_REG_OUT 2 +# define R300_PVS_DST_REG_OUT_REPL_X 3 +# define R300_PVS_DST_REG_ALT_TEMPORARY 4 +# define R300_PVS_DST_REG_INPUT 5 +#define R300_PVS_DST_OFFSET(x) ((x) << 13) +#define R300_PVS_DST_WE(x) ((x) << 20) +#define R300_PVS_DST_WE_XYZW (0xf << 20) + +#define R300_PVS_SRC_REG_TYPE(x) ((x) << 0) +# define R300_PVS_SRC_REG_TEMPORARY 0 +# define R300_PVS_SRC_REG_INPUT 1 +# define R300_PVS_SRC_REG_CONSTANT 2 +# define R300_PVS_SRC_REG_ALT_TEMPORARY 3 +#define R300_PVS_SRC_OFFSET(x) ((x) << 5) +#define R300_PVS_SRC_SWIZZLE(x) ((x) << 13) +# define R300_PVS_SRC_SELECT_X 0 +# define R300_PVS_SRC_SELECT_Y 1 +# define R300_PVS_SRC_SELECT_Z 2 +# define R300_PVS_SRC_SELECT_W 3 +# define R300_PVS_SRC_SELECT_FORCE_0 4 +# define R300_PVS_SRC_SELECT_FORCE_1 5 +# define R300_PVS_SRC_SWIZZLE_XYZW \ + ((R300_PVS_SRC_SELECT_X | (R300_PVS_SRC_SELECT_Y << 3) | \ + (R300_PVS_SRC_SELECT_Z << 6) | (R300_PVS_SRC_SELECT_W << 9)) << 13) +# define R300_PVS_SRC_SWIZZLE_ZERO \ + ((R300_PVS_SRC_SELECT_FORCE_0 | (R300_PVS_SRC_SELECT_FORCE_0 << 3) | \ + (R300_PVS_SRC_SELECT_FORCE_0 << 6) | \ + (R300_PVS_SRC_SELECT_FORCE_0 << 9)) << 13) +# define R300_PVS_SRC_SWIZZLE_ONE \ + ((R300_PVS_SRC_SELECT_FORCE_1 | (R300_PVS_SRC_SELECT_FORCE_1 << 3) | \ + (R300_PVS_SRC_SELECT_FORCE_1 << 6) | \ + (R300_PVS_SRC_SELECT_FORCE_1 << 9)) << 13) +#define R300_PVS_MODIFIER_X (1 << 25) +#define R300_PVS_MODIFIER_Y (1 << 26) +#define R300_PVS_MODIFIER_Z (1 << 27) +#define R300_PVS_MODIFIER_W (1 << 28) +#define R300_PVS_NEGATE_XYZW \ + (R300_PVS_MODIFIER_X | R300_PVS_MODIFIER_Y | \ + R300_PVS_MODIFIER_Z | R300_PVS_MODIFIER_W) + +struct r300_vertex_program_code r300_passthrough_vertex_shader = { + .length = 8, /* two instructions */ + + /* MOV out[0], in[0] */ + .body.d[0] = R300_PVS_DST_OPCODE(R300_VE_ADD) | + R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_OUT) | + R300_PVS_DST_OFFSET(0) | R300_PVS_DST_WE_XYZW, + .body.d[1] = R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) | + R300_PVS_SRC_OFFSET(0) | R300_PVS_SRC_SWIZZLE_XYZW, + .body.d[2] = R300_PVS_SRC_SWIZZLE_ZERO, + .body.d[3] = 0x0, + + /* MOV out[1], in[1] */ + .body.d[4] = R300_PVS_DST_OPCODE(R300_VE_ADD) | + R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_OUT) | + R300_PVS_DST_OFFSET(1) | R300_PVS_DST_WE_XYZW, + .body.d[5] = R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) | + R300_PVS_SRC_OFFSET(1) | R300_PVS_SRC_SWIZZLE_XYZW, + .body.d[6] = R300_PVS_SRC_SWIZZLE_ZERO, + .body.d[7] = 0x0, + + .inputs[0] = 0, + .inputs[1] = 1, + .outputs[0] = 0, + .outputs[1] = 1, + + .InputsRead = 3, + .OutputsWritten = 3 +}; + diff --git a/src/gallium/drivers/r300/r300_vs.h b/src/gallium/drivers/r300/r300_vs.h index 165d717812..2a4ce315e3 100644 --- a/src/gallium/drivers/r300/r300_vs.h +++ b/src/gallium/drivers/r300/r300_vs.h @@ -23,134 +23,31 @@ #ifndef R300_VS_H #define R300_VS_H -#include "tgsi/tgsi_parse.h" -#include "tgsi/tgsi_dump.h" +#include "pipe/p_state.h" +#include "tgsi/tgsi_scan.h" -#include "r300_context.h" -#include "r300_debug.h" -#include "r300_reg.h" -#include "r300_screen.h" -#include "r300_shader_inlines.h" +#include "radeon_code.h" -/* XXX get these to r300_reg */ -#define R300_PVS_DST_OPCODE(x) ((x) << 0) -# define R300_VE_DOT_PRODUCT 1 -# define R300_VE_MULTIPLY 2 -# define R300_VE_ADD 3 -# define R300_VE_MAXIMUM 7 -# define R300_VE_SET_LESS_THAN 10 -#define R300_PVS_DST_MATH_INST (1 << 6) -# define R300_ME_RECIP_DX 6 -#define R300_PVS_DST_MACRO_INST (1 << 7) -# define R300_PVS_MACRO_OP_2CLK_MADD 0 -#define R300_PVS_DST_REG_TYPE(x) ((x) << 8) -# define R300_PVS_DST_REG_TEMPORARY 0 -# define R300_PVS_DST_REG_A0 1 -# define R300_PVS_DST_REG_OUT 2 -# define R300_PVS_DST_REG_OUT_REPL_X 3 -# define R300_PVS_DST_REG_ALT_TEMPORARY 4 -# define R300_PVS_DST_REG_INPUT 5 -#define R300_PVS_DST_OFFSET(x) ((x) << 13) -#define R300_PVS_DST_WE(x) ((x) << 20) -#define R300_PVS_DST_WE_XYZW (0xf << 20) +struct r300_context; -#define R300_PVS_SRC_REG_TYPE(x) ((x) << 0) -# define R300_PVS_SRC_REG_TEMPORARY 0 -# define R300_PVS_SRC_REG_INPUT 1 -# define R300_PVS_SRC_REG_CONSTANT 2 -# define R300_PVS_SRC_REG_ALT_TEMPORARY 3 -#define R300_PVS_SRC_OFFSET(x) ((x) << 5) -#define R300_PVS_SRC_SWIZZLE(x) ((x) << 13) -# define R300_PVS_SRC_SELECT_X 0 -# define R300_PVS_SRC_SELECT_Y 1 -# define R300_PVS_SRC_SELECT_Z 2 -# define R300_PVS_SRC_SELECT_W 3 -# define R300_PVS_SRC_SELECT_FORCE_0 4 -# define R300_PVS_SRC_SELECT_FORCE_1 5 -# define R300_PVS_SRC_SWIZZLE_XYZW \ - ((R300_PVS_SRC_SELECT_X | (R300_PVS_SRC_SELECT_Y << 3) | \ - (R300_PVS_SRC_SELECT_Z << 6) | (R300_PVS_SRC_SELECT_W << 9)) << 13) -# define R300_PVS_SRC_SWIZZLE_ZERO \ - ((R300_PVS_SRC_SELECT_FORCE_0 | (R300_PVS_SRC_SELECT_FORCE_0 << 3) | \ - (R300_PVS_SRC_SELECT_FORCE_0 << 6) | \ - (R300_PVS_SRC_SELECT_FORCE_0 << 9)) << 13) -# define R300_PVS_SRC_SWIZZLE_ONE \ - ((R300_PVS_SRC_SELECT_FORCE_1 | (R300_PVS_SRC_SELECT_FORCE_1 << 3) | \ - (R300_PVS_SRC_SELECT_FORCE_1 << 6) | \ - (R300_PVS_SRC_SELECT_FORCE_1 << 9)) << 13) -#define R300_PVS_MODIFIER_X (1 << 25) -#define R300_PVS_MODIFIER_Y (1 << 26) -#define R300_PVS_MODIFIER_Z (1 << 27) -#define R300_PVS_MODIFIER_W (1 << 28) -#define R300_PVS_NEGATE_XYZW \ - (R300_PVS_MODIFIER_X | R300_PVS_MODIFIER_Y | \ - R300_PVS_MODIFIER_Z | R300_PVS_MODIFIER_W) +struct r300_vertex_shader { + /* Parent class */ + struct pipe_shader_state state; + struct tgsi_shader_info info; -/* Temporary struct used to hold assembly state while putting together - * fragment programs. */ -struct r300_vs_asm { - /* Pipe context. */ - struct r300_context* r300; - /* Number of colors. */ - unsigned color_count; - /* Number of texcoords. */ - unsigned tex_count; - /* Number of requested temporary registers. */ - unsigned temp_count; - /* Offset for immediate constants. Neither R300 nor R500 can do four - * inline constants per source, so instead we copy immediates into the - * constant buffer. */ - unsigned imm_offset; - /* Number of immediate constants. */ - unsigned imm_count; - /* Number of colors to write. */ - unsigned out_colors; - /* Number of texcoords to write. */ - unsigned out_texcoords; - /* Whether to emit point size. */ - boolean point_size; - /* Tab of declared outputs to OVM outputs. */ - unsigned tab[16]; -}; + /* Fallback shader, because Draw has issues */ + struct draw_vertex_shader* draw; -static struct r300_vertex_shader r300_passthrough_vertex_shader = { - /* XXX translate these back into normal instructions */ - .instruction_count = 2, - .instructions[0].inst0 = R300_PVS_DST_OPCODE(R300_VE_ADD) | - R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_OUT) | - R300_PVS_DST_OFFSET(0) | R300_PVS_DST_WE_XYZW, - .instructions[0].inst1 = R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) | - R300_PVS_SRC_OFFSET(0) | R300_PVS_SRC_SWIZZLE_XYZW, - .instructions[0].inst2 = R300_PVS_SRC_SWIZZLE_ZERO, - .instructions[0].inst3 = 0x0, - .instructions[1].inst0 = R300_PVS_DST_OPCODE(R300_VE_ADD) | - R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_OUT) | - R300_PVS_DST_OFFSET(1) | R300_PVS_DST_WE_XYZW, - .instructions[1].inst1 = R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) | - R300_PVS_SRC_OFFSET(1) | R300_PVS_SRC_SWIZZLE_XYZW, - .instructions[1].inst2 = R300_PVS_SRC_SWIZZLE_ZERO, - .instructions[1].inst3 = 0x0, -}; + /* Has this shader been translated yet? */ + boolean translated; -static struct r300_vertex_shader r300_texture_vertex_shader = { - /* XXX translate these back into normal instructions */ - .instruction_count = 2, - .instructions[0].inst0 = R300_PVS_DST_OPCODE(R300_VE_ADD) | - R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_OUT) | - R300_PVS_DST_OFFSET(0) | R300_PVS_DST_WE_XYZW, - .instructions[0].inst1 = R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) | - R300_PVS_SRC_OFFSET(0) | R300_PVS_SRC_SWIZZLE_XYZW, - .instructions[0].inst2 = R300_PVS_SRC_SWIZZLE_ZERO, - .instructions[0].inst3 = 0x0, - .instructions[1].inst0 = R300_PVS_DST_OPCODE(R300_VE_ADD) | - R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_OUT) | - R300_PVS_DST_OFFSET(1) | R300_PVS_DST_WE_XYZW, - .instructions[1].inst1 = R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) | - R300_PVS_SRC_OFFSET(1) | R300_PVS_SRC_SWIZZLE_XYZW, - .instructions[1].inst2 = R300_PVS_SRC_SWIZZLE_ZERO, - .instructions[1].inst3 = 0x0, + /* Machine code (if translated) */ + struct r300_vertex_program_code code; }; + +extern struct r300_vertex_program_code r300_passthrough_vertex_shader; + void r300_translate_vertex_shader(struct r300_context* r300, struct r300_vertex_shader* vs); diff --git a/src/gallium/drivers/r300/r3xx_fs.c b/src/gallium/drivers/r300/r3xx_fs.c index 6e05d76977..c1c1194d58 100644 --- a/src/gallium/drivers/r300/r3xx_fs.c +++ b/src/gallium/drivers/r300/r3xx_fs.c @@ -23,74 +23,52 @@ #include "r3xx_fs.h" -static INLINE uint32_t r3xx_rgb_op(unsigned op) -{ - switch (op) { - case TGSI_OPCODE_MOV: - return R300_ALU_OUTC_CMP; - default: - return 0; - } -} +#include "r300_reg.h" -static INLINE uint32_t r3xx_alpha_op(unsigned op) -{ - switch (op) { - case TGSI_OPCODE_MOV: - return R300_ALU_OUTA_CMP; - default: - return 0; - } -} +struct rX00_fragment_program_code r3xx_passthrough_fragment_shader = { + .code.r300.alu.length = 1, + .code.r300.tex.length = 0, -static INLINE void r3xx_emit_maths(struct r3xx_fragment_shader* fs, - struct r300_fs_asm* assembler, - struct tgsi_full_src_register* src, - struct tgsi_full_dst_register* dst, - unsigned op, - unsigned count) -{ - int i = fs->alu_instruction_count; + .code.r300.config = 0, + .code.r300.pixsize = 0, + .code.r300.code_offset = 0, + .code.r300.code_addr[3] = R300_RGBA_OUT, - fs->instructions[i].alu_rgb_inst = R300_RGB_SWIZA(R300_ALU_ARGC_SRC0C_XYZ) | + .code.r300.alu.inst[0].rgb_inst = R300_RGB_SWIZA(R300_ALU_ARGC_SRC0C_XYZ) | R300_RGB_SWIZB(R300_ALU_ARGC_SRC0C_XYZ) | R300_RGB_SWIZC(R300_ALU_ARGC_ZERO) | - r3xx_rgb_op(op); - fs->instructions[i].alu_rgb_addr = R300_RGB_ADDR0(0) | R300_RGB_ADDR1(0) | - R300_RGB_ADDR2(0) | R300_ALU_DSTC_OUTPUT_XYZ; - fs->instructions[i].alu_alpha_inst = R300_ALPHA_SWIZA(R300_ALU_ARGA_SRC0A) | + R300_ALU_OUTC_CMP, + .code.r300.alu.inst[0].rgb_addr = R300_RGB_ADDR0(0) | R300_RGB_ADDR1(0) | + R300_RGB_ADDR2(0) | R300_ALU_DSTC_OUTPUT_XYZ, + .code.r300.alu.inst[0].alpha_inst = R300_ALPHA_SWIZA(R300_ALU_ARGA_SRC0A) | R300_ALPHA_SWIZB(R300_ALU_ARGA_SRC0A) | R300_ALPHA_SWIZC(R300_ALU_ARGA_ZERO) | - r3xx_alpha_op(op); - fs->instructions[i].alu_alpha_addr = R300_ALPHA_ADDR0(0) | - R300_ALPHA_ADDR1(0) | R300_ALPHA_ADDR2(0) | R300_ALU_DSTA_OUTPUT; + R300_ALU_OUTA_CMP, + .code.r300.alu.inst[0].alpha_addr = R300_ALPHA_ADDR0(0) | + R300_ALPHA_ADDR1(0) | R300_ALPHA_ADDR2(0) | R300_ALU_DSTA_OUTPUT, +}; - fs->alu_instruction_count++; -} +struct rX00_fragment_program_code r3xx_texture_fragment_shader = { + .code.r300.alu.length = 1, + .code.r300.tex.length = 1, -void r3xx_fs_finalize(struct r300_fragment_shader* fs, - struct r300_fs_asm* assembler) -{ - fs->stack_size = assembler->temp_count + assembler->temp_offset + 1; -} + .code.r300.config = R300_PFS_CNTL_FIRST_NODE_HAS_TEX, + .code.r300.pixsize = 0, + .code.r300.code_offset = 0, + .code.r300.code_addr[3] = R300_RGBA_OUT, -void r3xx_fs_instruction(struct r3xx_fragment_shader* fs, - struct r300_fs_asm* assembler, - struct tgsi_full_instruction* inst) -{ - switch (inst->Instruction.Opcode) { - case TGSI_OPCODE_MOV: - /* src0 -> src1 and src2 forced to zero */ - inst->FullSrcRegisters[1] = inst->FullSrcRegisters[0]; - inst->FullSrcRegisters[2] = r300_constant_zero; - r3xx_emit_maths(fs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], inst->Instruction.Opcode, 3); - break; - case TGSI_OPCODE_END: - break; - default: - debug_printf("r300: fs: Bad opcode %d\n", - inst->Instruction.Opcode); - break; - } -} + .code.r300.tex.inst[0] = R300_TEX_OP_LD << R300_TEX_INST_SHIFT, + + .code.r300.alu.inst[0].rgb_inst = R300_RGB_SWIZA(R300_ALU_ARGC_SRC0C_XYZ) | + R300_RGB_SWIZB(R300_ALU_ARGC_SRC0C_XYZ) | + R300_RGB_SWIZC(R300_ALU_ARGC_ZERO) | + R300_ALU_OUTC_CMP, + .code.r300.alu.inst[0].rgb_addr = R300_RGB_ADDR0(0) | R300_RGB_ADDR1(0) | + R300_RGB_ADDR2(0) | R300_ALU_DSTC_OUTPUT_XYZ, + .code.r300.alu.inst[0].alpha_inst = R300_ALPHA_SWIZA(R300_ALU_ARGA_SRC0A) | + R300_ALPHA_SWIZB(R300_ALU_ARGA_SRC0A) | + R300_ALPHA_SWIZC(R300_ALU_ARGA_ZERO) | + R300_ALU_OUTA_CMP, + .code.r300.alu.inst[0].alpha_addr = R300_ALPHA_ADDR0(0) | + R300_ALPHA_ADDR1(0) | R300_ALPHA_ADDR2(0) | R300_ALU_DSTA_OUTPUT, +}; diff --git a/src/gallium/drivers/r300/r3xx_fs.h b/src/gallium/drivers/r300/r3xx_fs.h index 3da39ec252..51cd245724 100644 --- a/src/gallium/drivers/r300/r3xx_fs.h +++ b/src/gallium/drivers/r300/r3xx_fs.h @@ -24,53 +24,9 @@ #ifndef R3XX_FS_H #define R3XX_FS_H -#include "r300_fs_inlines.h" +#include "radeon_code.h" -static struct r3xx_fragment_shader r3xx_passthrough_fragment_shader = { - .alu_instruction_count = 1, - .tex_instruction_count = 0, - .indirections = 0, - .shader.stack_size = 1, - - .instructions[0].alu_rgb_inst = R300_RGB_SWIZA(R300_ALU_ARGC_SRC0C_XYZ) | - R300_RGB_SWIZB(R300_ALU_ARGC_SRC0C_XYZ) | - R300_RGB_SWIZC(R300_ALU_ARGC_ZERO) | - R300_ALU_OUTC_CMP, - .instructions[0].alu_rgb_addr = R300_RGB_ADDR0(0) | R300_RGB_ADDR1(0) | - R300_RGB_ADDR2(0) | R300_ALU_DSTC_OUTPUT_XYZ, - .instructions[0].alu_alpha_inst = R300_ALPHA_SWIZA(R300_ALU_ARGA_SRC0A) | - R300_ALPHA_SWIZB(R300_ALU_ARGA_SRC0A) | - R300_ALPHA_SWIZC(R300_ALU_ARGA_ZERO) | - R300_ALU_OUTA_CMP, - .instructions[0].alu_alpha_addr = R300_ALPHA_ADDR0(0) | - R300_ALPHA_ADDR1(0) | R300_ALPHA_ADDR2(0) | R300_ALU_DSTA_OUTPUT, -}; - -static struct r3xx_fragment_shader r3xx_texture_fragment_shader = { - .alu_instruction_count = 1, - .tex_instruction_count = 0, - .indirections = 0, - .shader.stack_size = 1, - - .instructions[0].alu_rgb_inst = R300_RGB_SWIZA(R300_ALU_ARGC_SRC0C_XYZ) | - R300_RGB_SWIZB(R300_ALU_ARGC_SRC0C_XYZ) | - R300_RGB_SWIZC(R300_ALU_ARGC_ZERO) | - R300_ALU_OUTC_CMP, - .instructions[0].alu_rgb_addr = R300_RGB_ADDR0(0) | R300_RGB_ADDR1(0) | - R300_RGB_ADDR2(0) | R300_ALU_DSTC_OUTPUT_XYZ, - .instructions[0].alu_alpha_inst = R300_ALPHA_SWIZA(R300_ALU_ARGA_SRC0A) | - R300_ALPHA_SWIZB(R300_ALU_ARGA_SRC0A) | - R300_ALPHA_SWIZC(R300_ALU_ARGA_ZERO) | - R300_ALU_OUTA_CMP, - .instructions[0].alu_alpha_addr = R300_ALPHA_ADDR0(0) | - R300_ALPHA_ADDR1(0) | R300_ALPHA_ADDR2(0) | R300_ALU_DSTA_OUTPUT, -}; - -void r3xx_fs_finalize(struct r300_fragment_shader* fs, - struct r300_fs_asm* assembler); - -void r3xx_fs_instruction(struct r3xx_fragment_shader* fs, - struct r300_fs_asm* assembler, - struct tgsi_full_instruction* inst); +struct rX00_fragment_program_code r3xx_passthrough_fragment_shader; +struct rX00_fragment_program_code r3xx_texture_fragment_shader; #endif /* R3XX_FS_H */ diff --git a/src/gallium/drivers/r300/r5xx_fs.c b/src/gallium/drivers/r300/r5xx_fs.c index 99d826278c..f072deab0d 100644 --- a/src/gallium/drivers/r300/r5xx_fs.c +++ b/src/gallium/drivers/r300/r5xx_fs.c @@ -23,445 +23,103 @@ #include "r5xx_fs.h" -static INLINE unsigned r5xx_fix_swiz(unsigned s) -{ - /* For historical reasons, the swizzle values x, y, z, w, and 0 are - * equivalent to the actual machine code, but 1 is not. Thus, we just - * adjust it a bit... */ - if (s == TGSI_EXTSWIZZLE_ONE) { - return R500_SWIZZLE_ONE; - } else { - return s; - } -} - -static uint32_t r5xx_rgba_swiz(struct tgsi_full_src_register* reg) -{ - if (reg->SrcRegister.Extended) { - return r5xx_fix_swiz(reg->SrcRegisterExtSwz.ExtSwizzleX) | - (r5xx_fix_swiz(reg->SrcRegisterExtSwz.ExtSwizzleY) << 3) | - (r5xx_fix_swiz(reg->SrcRegisterExtSwz.ExtSwizzleZ) << 6) | - (r5xx_fix_swiz(reg->SrcRegisterExtSwz.ExtSwizzleW) << 9); - } else { - return reg->SrcRegister.SwizzleX | - (reg->SrcRegister.SwizzleY << 3) | - (reg->SrcRegister.SwizzleZ << 6) | - (reg->SrcRegister.SwizzleW << 9); - } -} - -static uint32_t r5xx_strq_swiz(struct tgsi_full_src_register* reg) -{ - return reg->SrcRegister.SwizzleX | - (reg->SrcRegister.SwizzleY << 2) | - (reg->SrcRegister.SwizzleZ << 4) | - (reg->SrcRegister.SwizzleW << 6); -} - -static INLINE uint32_t r5xx_rgb_swiz(struct tgsi_full_src_register* reg) -{ - /* Only the first 9 bits... */ - return (r5xx_rgba_swiz(reg) & 0x1ff) | - (reg->SrcRegister.Negate ? (1 << 9) : 0) | - (reg->SrcRegisterExtMod.Absolute ? (1 << 10) : 0); -} - -static INLINE uint32_t r5xx_alpha_swiz(struct tgsi_full_src_register* reg) -{ - /* Only the last 3 bits... */ - return (r5xx_rgba_swiz(reg) >> 9) | - (reg->SrcRegister.Negate ? (1 << 9) : 0) | - (reg->SrcRegisterExtMod.Absolute ? (1 << 10) : 0); -} - -static INLINE uint32_t r5xx_rgba_op(unsigned op) -{ - switch (op) { - case TGSI_OPCODE_COS: - case TGSI_OPCODE_EX2: - case TGSI_OPCODE_LG2: - case TGSI_OPCODE_RCP: - case TGSI_OPCODE_RSQ: - case TGSI_OPCODE_SIN: - return R500_ALU_RGBA_OP_SOP; - case TGSI_OPCODE_DDX: - return R500_ALU_RGBA_OP_MDH; - case TGSI_OPCODE_DDY: - return R500_ALU_RGBA_OP_MDV; - case TGSI_OPCODE_FRC: - return R500_ALU_RGBA_OP_FRC; - case TGSI_OPCODE_DP3: - return R500_ALU_RGBA_OP_DP3; - case TGSI_OPCODE_DP4: - case TGSI_OPCODE_DPH: - return R500_ALU_RGBA_OP_DP4; - case TGSI_OPCODE_ABS: - case TGSI_OPCODE_CMP: - case TGSI_OPCODE_MOV: - case TGSI_OPCODE_SWZ: - return R500_ALU_RGBA_OP_CMP; - case TGSI_OPCODE_ADD: - case TGSI_OPCODE_MAD: - case TGSI_OPCODE_MUL: - case TGSI_OPCODE_SUB: - return R500_ALU_RGBA_OP_MAD; - default: - return 0; - } -} - -static INLINE uint32_t r5xx_alpha_op(unsigned op) -{ - switch (op) { - case TGSI_OPCODE_COS: - return R500_ALPHA_OP_COS; - case TGSI_OPCODE_EX2: - return R500_ALPHA_OP_EX2; - case TGSI_OPCODE_LG2: - return R500_ALPHA_OP_LN2; - case TGSI_OPCODE_RCP: - return R500_ALPHA_OP_RCP; - case TGSI_OPCODE_RSQ: - return R500_ALPHA_OP_RSQ; - case TGSI_OPCODE_FRC: - return R500_ALPHA_OP_FRC; - case TGSI_OPCODE_SIN: - return R500_ALPHA_OP_SIN; - case TGSI_OPCODE_DDX: - return R500_ALPHA_OP_MDH; - case TGSI_OPCODE_DDY: - return R500_ALPHA_OP_MDV; - case TGSI_OPCODE_DP3: - case TGSI_OPCODE_DP4: - case TGSI_OPCODE_DPH: - return R500_ALPHA_OP_DP; - case TGSI_OPCODE_ABS: - case TGSI_OPCODE_CMP: - case TGSI_OPCODE_MOV: - case TGSI_OPCODE_SWZ: - return R500_ALPHA_OP_CMP; - case TGSI_OPCODE_ADD: - case TGSI_OPCODE_MAD: - case TGSI_OPCODE_MUL: - case TGSI_OPCODE_SUB: - return R500_ALPHA_OP_MAD; - default: - return 0; - } -} - -static INLINE uint32_t r5xx_tex_op(unsigned op) -{ - switch (op) { - case TGSI_OPCODE_KIL: - return R500_TEX_INST_TEXKILL; - case TGSI_OPCODE_TEX: - return R500_TEX_INST_LD; - case TGSI_OPCODE_TXB: - return R500_TEX_INST_LODBIAS; - case TGSI_OPCODE_TXP: - return R500_TEX_INST_PROJ; - default: - return 0; - } -} - -/* Setup an ALU operation. */ -static INLINE void r5xx_emit_maths(struct r5xx_fragment_shader* fs, - struct r300_fs_asm* assembler, - struct tgsi_full_src_register* src, - struct tgsi_full_dst_register* dst, - unsigned op, - unsigned count) -{ - int i = fs->instruction_count; - - if (dst->DstRegister.File == TGSI_FILE_OUTPUT) { - fs->instructions[i].inst0 = R500_INST_TYPE_OUT; - if (r300_fs_is_depr(assembler, dst)) { - fs->instructions[i].inst4 = R500_W_OMASK; - } else { - fs->instructions[i].inst0 |= - R500_ALU_OMASK(dst->DstRegister.WriteMask); - } - } else { - fs->instructions[i].inst0 = R500_INST_TYPE_ALU | - R500_ALU_WMASK(dst->DstRegister.WriteMask); - } - - fs->instructions[i].inst0 |= R500_INST_TEX_SEM_WAIT; - - fs->instructions[i].inst4 |= - R500_ALPHA_ADDRD(r300_fs_dst(assembler, &dst->DstRegister)); - fs->instructions[i].inst5 = - R500_ALU_RGBA_ADDRD(r300_fs_dst(assembler, &dst->DstRegister)); - - switch (count) { - case 3: - fs->instructions[i].inst1 = - R500_RGB_ADDR2(r300_fs_src(assembler, &src[2].SrcRegister)); - fs->instructions[i].inst2 = - R500_ALPHA_ADDR2(r300_fs_src(assembler, &src[2].SrcRegister)); - fs->instructions[i].inst5 |= - R500_ALU_RGBA_SEL_C_SRC2 | - R500_SWIZ_RGBA_C(r5xx_rgb_swiz(&src[2])) | - R500_ALU_RGBA_ALPHA_SEL_C_SRC2 | - R500_SWIZ_ALPHA_C(r5xx_alpha_swiz(&src[2])); - case 2: - fs->instructions[i].inst1 |= - R500_RGB_ADDR1(r300_fs_src(assembler, &src[1].SrcRegister)); - fs->instructions[i].inst2 |= - R500_ALPHA_ADDR1(r300_fs_src(assembler, &src[1].SrcRegister)); - fs->instructions[i].inst3 = - R500_ALU_RGB_SEL_B_SRC1 | - R500_SWIZ_RGB_B(r5xx_rgb_swiz(&src[1])); - fs->instructions[i].inst4 |= - R500_ALPHA_SEL_B_SRC1 | - R500_SWIZ_ALPHA_B(r5xx_alpha_swiz(&src[1])); - case 1: - case 0: - default: - fs->instructions[i].inst1 |= - R500_RGB_ADDR0(r300_fs_src(assembler, &src[0].SrcRegister)); - fs->instructions[i].inst2 |= - R500_ALPHA_ADDR0(r300_fs_src(assembler, &src[0].SrcRegister)); - fs->instructions[i].inst3 |= - R500_ALU_RGB_SEL_A_SRC0 | - R500_SWIZ_RGB_A(r5xx_rgb_swiz(&src[0])); - fs->instructions[i].inst4 |= - R500_ALPHA_SEL_A_SRC0 | - R500_SWIZ_ALPHA_A(r5xx_alpha_swiz(&src[0])); - break; - } - - fs->instructions[i].inst4 |= r5xx_alpha_op(op); - fs->instructions[i].inst5 |= r5xx_rgba_op(op); - - fs->instruction_count++; -} - -static INLINE void r5xx_emit_tex(struct r5xx_fragment_shader* fs, - struct r300_fs_asm* assembler, - struct tgsi_full_src_register* src, - struct tgsi_full_dst_register* dst, - uint32_t op) -{ - int i = fs->instruction_count; - - fs->instructions[i].inst0 = R500_INST_TYPE_TEX | - R500_TEX_WMASK(dst->DstRegister.WriteMask) | - R500_INST_TEX_SEM_WAIT; - fs->instructions[i].inst1 = R500_TEX_ID(0) | - R500_TEX_SEM_ACQUIRE | //R500_TEX_IGNORE_UNCOVERED | - r5xx_tex_op(op); - fs->instructions[i].inst2 = - R500_TEX_SRC_ADDR(r300_fs_src(assembler, &src->SrcRegister)) | - R500_SWIZ_TEX_STRQ(r5xx_strq_swiz(src)) | - R500_TEX_DST_ADDR(r300_fs_dst(assembler, &dst->DstRegister)) | +#include "r300_reg.h" + +/* XXX this all should find its way back to r300_reg */ +/* Swizzle tools */ +#define R500_SWIZZLE_ZERO 4 +#define R500_SWIZZLE_HALF 5 +#define R500_SWIZZLE_ONE 6 +#define R500_SWIZ_RGB_ZERO ((4 << 0) | (4 << 3) | (4 << 6)) +#define R500_SWIZ_RGB_ONE ((6 << 0) | (6 << 3) | (6 << 6)) +#define R500_SWIZ_RGB_RGB ((0 << 0) | (1 << 3) | (2 << 6)) +#define R500_SWIZ_MOD_NEG 1 +#define R500_SWIZ_MOD_ABS 2 +#define R500_SWIZ_MOD_NEG_ABS 3 +/* Swizzles for inst2 */ +#define R500_SWIZ_TEX_STRQ(x) ((x) << 8) +#define R500_SWIZ_TEX_RGBA(x) ((x) << 24) +/* Swizzles for inst3 */ +#define R500_SWIZ_RGB_A(x) ((x) << 2) +#define R500_SWIZ_RGB_B(x) ((x) << 15) +/* Swizzles for inst4 */ +#define R500_SWIZ_ALPHA_A(x) ((x) << 14) +#define R500_SWIZ_ALPHA_B(x) ((x) << 21) +/* Swizzle for inst5 */ +#define R500_SWIZ_RGBA_C(x) ((x) << 14) +#define R500_SWIZ_ALPHA_C(x) ((x) << 27) +/* Writemasks */ +#define R500_TEX_WMASK(x) ((x) << 11) +#define R500_ALU_WMASK(x) ((x) << 11) +#define R500_ALU_OMASK(x) ((x) << 15) +#define R500_W_OMASK (1 << 31) + +struct rX00_fragment_program_code r5xx_passthrough_fragment_shader = { + .code.r500.max_temp_idx = 0, + .code.r500.inst_end = 0, + + .code.r500.inst[0].inst0 = R500_INST_TYPE_OUT | + R500_INST_TEX_SEM_WAIT | R500_INST_LAST | + R500_INST_RGB_OMASK_RGB | R500_INST_ALPHA_OMASK | + R500_INST_RGB_CLAMP | R500_INST_ALPHA_CLAMP, + .code.r500.inst[0].inst1 = + R500_RGB_ADDR0(0) | R500_RGB_ADDR1(0) | R500_RGB_ADDR1_CONST | + R500_RGB_ADDR2(0) | R500_RGB_ADDR2_CONST, + .code.r500.inst[0].inst2 = + R500_ALPHA_ADDR0(0) | R500_ALPHA_ADDR1(0) | R500_ALPHA_ADDR1_CONST | + R500_ALPHA_ADDR2(0) | R500_ALPHA_ADDR2_CONST, + .code.r500.inst[0].inst3 = + R500_ALU_RGB_SEL_A_SRC0 | R500_ALU_RGB_R_SWIZ_A_R | + R500_ALU_RGB_G_SWIZ_A_G | R500_ALU_RGB_B_SWIZ_A_B | + R500_ALU_RGB_SEL_B_SRC0 | R500_ALU_RGB_R_SWIZ_B_R | + R500_ALU_RGB_B_SWIZ_B_G | R500_ALU_RGB_G_SWIZ_B_B, + .code.r500.inst[0].inst4 = + R500_ALPHA_OP_CMP | R500_ALPHA_SWIZ_A_A | R500_ALPHA_SWIZ_B_A, + .code.r500.inst[0].inst5 = + R500_ALU_RGBA_OP_CMP | R500_ALU_RGBA_R_SWIZ_0 | + R500_ALU_RGBA_G_SWIZ_0 | R500_ALU_RGBA_B_SWIZ_0 | + R500_ALU_RGBA_A_SWIZ_0, +}; + +struct rX00_fragment_program_code r5xx_texture_fragment_shader = { + .code.r500.max_temp_idx = 0, + .code.r500.inst_end = 1, + + .code.r500.inst[0].inst0 = R500_INST_TYPE_TEX | + R500_INST_TEX_SEM_WAIT | + R500_INST_RGB_WMASK_RGB | R500_INST_ALPHA_WMASK | + R500_INST_RGB_CLAMP | R500_INST_ALPHA_CLAMP, + .code.r500.inst[0].inst1 = R500_TEX_ID(0) | R500_TEX_INST_LD | + R500_TEX_SEM_ACQUIRE | R500_TEX_IGNORE_UNCOVERED, + .code.r500.inst[0].inst2 = R500_TEX_SRC_ADDR(0) | + R500_TEX_SRC_S_SWIZ_R | R500_TEX_SRC_T_SWIZ_G | + R500_TEX_SRC_R_SWIZ_B | R500_TEX_SRC_Q_SWIZ_A | + R500_TEX_DST_ADDR(0) | R500_TEX_DST_R_SWIZ_R | R500_TEX_DST_G_SWIZ_G | - R500_TEX_DST_B_SWIZ_B | R500_TEX_DST_A_SWIZ_A; - - if (dst->DstRegister.File == TGSI_FILE_OUTPUT) { - fs->instructions[i].inst2 |= - R500_TEX_DST_ADDR(assembler->temp_count + - assembler->temp_offset); - - fs->instruction_count++; - - /* Setup and emit a MOV. */ - src[0].SrcRegister.Index = assembler->temp_count; - src[0].SrcRegister.File = TGSI_FILE_TEMPORARY; - - src[1] = src[0]; - src[2] = r300_constant_zero; - r5xx_emit_maths(fs, assembler, src, dst, TGSI_OPCODE_MOV, 3); - } else { - fs->instruction_count++; - } -} - -void r5xx_fs_finalize(struct r5xx_fragment_shader* fs, - struct r300_fs_asm* assembler) -{ - /* XXX should this just go with OPCODE_END? */ - fs->instructions[fs->instruction_count - 1].inst0 |= - R500_INST_LAST; -} - -void r5xx_fs_instruction(struct r5xx_fragment_shader* fs, - struct r300_fs_asm* assembler, - struct tgsi_full_instruction* inst) -{ - /* Switch between opcodes. When possible, prefer using the official - * AMD/ATI names for opcodes, please, as it facilitates using the - * documentation. */ - switch (inst->Instruction.Opcode) { - /* XXX trig needs extra prep */ - case TGSI_OPCODE_COS: - case TGSI_OPCODE_SIN: - /* The simple scalar ops. */ - case TGSI_OPCODE_EX2: - case TGSI_OPCODE_LG2: - case TGSI_OPCODE_RCP: - case TGSI_OPCODE_RSQ: - /* Copy red swizzle to alpha for src0 */ - inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleW = - inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleX; - inst->FullSrcRegisters[0].SrcRegister.SwizzleW = - inst->FullSrcRegisters[0].SrcRegister.SwizzleX; - /* Fall through */ - case TGSI_OPCODE_DDX: - case TGSI_OPCODE_DDY: - case TGSI_OPCODE_FRC: - r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], inst->Instruction.Opcode, 1); - break; - - /* The dot products. */ - case TGSI_OPCODE_DPH: - /* Set alpha swizzle to one for src0 */ - if (!inst->FullSrcRegisters[0].SrcRegister.Extended) { - inst->FullSrcRegisters[0].SrcRegister.Extended = TRUE; - inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleX = - inst->FullSrcRegisters[0].SrcRegister.SwizzleX; - inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleY = - inst->FullSrcRegisters[0].SrcRegister.SwizzleY; - inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleZ = - inst->FullSrcRegisters[0].SrcRegister.SwizzleZ; - } - inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleW = - TGSI_EXTSWIZZLE_ONE; - /* Fall through */ - case TGSI_OPCODE_DP3: - case TGSI_OPCODE_DP4: - r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], inst->Instruction.Opcode, 2); - break; - - /* Simple three-source operations. */ - case TGSI_OPCODE_CMP: - /* Swap src0 and src2 */ - inst->FullSrcRegisters[3] = inst->FullSrcRegisters[2]; - inst->FullSrcRegisters[2] = inst->FullSrcRegisters[0]; - inst->FullSrcRegisters[0] = inst->FullSrcRegisters[3]; - r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], inst->Instruction.Opcode, 3); - break; - - /* The MAD variants. */ - case TGSI_OPCODE_SUB: - /* Just like ADD, but flip the negation on src1 first */ - inst->FullSrcRegisters[1].SrcRegister.Negate = - !inst->FullSrcRegisters[1].SrcRegister.Negate; - /* Fall through */ - case TGSI_OPCODE_ADD: - /* Force src0 to one, move all registers over */ - inst->FullSrcRegisters[2] = inst->FullSrcRegisters[1]; - inst->FullSrcRegisters[1] = inst->FullSrcRegisters[0]; - inst->FullSrcRegisters[0] = r300_constant_one; - r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], inst->Instruction.Opcode, 3); - break; - case TGSI_OPCODE_MUL: - /* Force our src2 to zero */ - inst->FullSrcRegisters[2] = r300_constant_zero; - r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], inst->Instruction.Opcode, 3); - break; - case TGSI_OPCODE_MAD: - r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], inst->Instruction.Opcode, 3); - break; - - /* The MOV variants. */ - case TGSI_OPCODE_ABS: - /* Set absolute value modifiers. */ - inst->FullSrcRegisters[0].SrcRegisterExtMod.Absolute = TRUE; - /* Fall through */ - case TGSI_OPCODE_MOV: - case TGSI_OPCODE_SWZ: - /* src0 -> src1 and src2 forced to zero */ - inst->FullSrcRegisters[1] = inst->FullSrcRegisters[0]; - inst->FullSrcRegisters[2] = r300_constant_zero; - r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], inst->Instruction.Opcode, 3); - break; - - /* The compound and hybrid insts. */ - case TGSI_OPCODE_LRP: - /* LRP DST A, B, C -> MAD TMP -A, C, C; MAD DST A, B, TMP */ - inst->FullSrcRegisters[3] = inst->FullSrcRegisters[1]; - inst->FullSrcRegisters[1] = inst->FullSrcRegisters[2]; - inst->FullSrcRegisters[0].SrcRegister.Negate = - !(inst->FullSrcRegisters[0].SrcRegister.Negate); - inst->FullDstRegisters[1] = inst->FullDstRegisters[0]; - inst->FullDstRegisters[0].DstRegister.Index = - assembler->temp_count; - inst->FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY; - r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], TGSI_OPCODE_MAD, 3); - inst->FullSrcRegisters[2].SrcRegister.Index = - assembler->temp_count; - inst->FullSrcRegisters[2].SrcRegister.File = TGSI_FILE_TEMPORARY; - inst->FullSrcRegisters[2].SrcRegister.SwizzleX = TGSI_SWIZZLE_X; - inst->FullSrcRegisters[2].SrcRegister.SwizzleY = TGSI_SWIZZLE_Y; - inst->FullSrcRegisters[2].SrcRegister.SwizzleZ = TGSI_SWIZZLE_Z; - inst->FullSrcRegisters[2].SrcRegister.SwizzleW = TGSI_SWIZZLE_W; - inst->FullSrcRegisters[1] = inst->FullSrcRegisters[3]; - inst->FullSrcRegisters[0].SrcRegister.Negate = - !(inst->FullSrcRegisters[0].SrcRegister.Negate); - inst->FullDstRegisters[0] = inst->FullDstRegisters[1]; - r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], TGSI_OPCODE_MAD, 3); - break; - case TGSI_OPCODE_POW: - /* POW DST A, B -> LG2 TMP A; MUL TMP TMP, B; EX2 DST TMP */ - inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleW = - inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleX; - inst->FullSrcRegisters[0].SrcRegister.SwizzleW = - inst->FullSrcRegisters[0].SrcRegister.SwizzleX; - inst->FullDstRegisters[1] = inst->FullDstRegisters[0]; - inst->FullDstRegisters[0].DstRegister.Index = - assembler->temp_count; - inst->FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY; - r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], TGSI_OPCODE_LG2, 1); - inst->FullSrcRegisters[0].SrcRegister.Index = - assembler->temp_count; - inst->FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY; - inst->FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_X; - inst->FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_Y; - inst->FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_Z; - inst->FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_W; - inst->FullSrcRegisters[2] = r300_constant_zero; - r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], TGSI_OPCODE_MUL, 3); - inst->FullDstRegisters[0] = inst->FullDstRegisters[1]; - r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], TGSI_OPCODE_EX2, 1); - break; - - /* The texture instruction set. */ - case TGSI_OPCODE_KIL: - case TGSI_OPCODE_TEX: - case TGSI_OPCODE_TXB: - case TGSI_OPCODE_TXP: - r5xx_emit_tex(fs, assembler, &inst->FullSrcRegisters[0], - &inst->FullDstRegisters[0], inst->Instruction.Opcode); - break; - - /* This is the end. My only friend, the end. */ - case TGSI_OPCODE_END: - break; - default: - debug_printf("r300: fs: Bad opcode %d\n", - inst->Instruction.Opcode); - break; - } - - /* Clamp, if saturation flags are set. */ - if (inst->Instruction.Saturate == TGSI_SAT_ZERO_ONE) { - fs->instructions[fs->instruction_count - 1].inst0 |= - R500_INST_RGB_CLAMP | R500_INST_ALPHA_CLAMP; - } -} + R500_TEX_DST_B_SWIZ_B | R500_TEX_DST_A_SWIZ_A, + .code.r500.inst[0].inst3 = 0x0, + .code.r500.inst[0].inst4 = 0x0, + .code.r500.inst[0].inst5 = 0x0, + + .code.r500.inst[1].inst0 = R500_INST_TYPE_OUT | + R500_INST_TEX_SEM_WAIT | R500_INST_LAST | + R500_INST_RGB_OMASK_RGB | R500_INST_ALPHA_OMASK | + R500_INST_RGB_CLAMP | R500_INST_ALPHA_CLAMP, + .code.r500.inst[1].inst1 = + R500_RGB_ADDR0(0) | R500_RGB_ADDR1(0) | R500_RGB_ADDR1_CONST | + R500_RGB_ADDR2(0) | R500_RGB_ADDR2_CONST, + .code.r500.inst[1].inst2 = + R500_ALPHA_ADDR0(0) | R500_ALPHA_ADDR1(0) | R500_ALPHA_ADDR1_CONST | + R500_ALPHA_ADDR2(0) | R500_ALPHA_ADDR2_CONST, + .code.r500.inst[1].inst3 = + R500_ALU_RGB_SEL_A_SRC0 | R500_ALU_RGB_R_SWIZ_A_R | + R500_ALU_RGB_G_SWIZ_A_G | R500_ALU_RGB_B_SWIZ_A_B | + R500_ALU_RGB_SEL_B_SRC0 | R500_ALU_RGB_R_SWIZ_B_R | + R500_ALU_RGB_B_SWIZ_B_G | R500_ALU_RGB_G_SWIZ_B_B, + .code.r500.inst[1].inst4 = + R500_ALPHA_OP_CMP | R500_ALPHA_SWIZ_A_A | R500_ALPHA_SWIZ_B_A, + .code.r500.inst[1].inst5 = + R500_ALU_RGBA_OP_CMP | R500_ALU_RGBA_R_SWIZ_0 | + R500_ALU_RGBA_G_SWIZ_0 | R500_ALU_RGBA_B_SWIZ_0 | + R500_ALU_RGBA_A_SWIZ_0, +}; diff --git a/src/gallium/drivers/r300/r5xx_fs.h b/src/gallium/drivers/r300/r5xx_fs.h index 629e587be4..a4addde32b 100644 --- a/src/gallium/drivers/r300/r5xx_fs.h +++ b/src/gallium/drivers/r300/r5xx_fs.h @@ -24,109 +24,9 @@ #ifndef R5XX_FS_H #define R5XX_FS_H -#include "r300_fs_inlines.h" +#include "radeon_code.h" -/* XXX this all should find its way back to r300_reg */ -/* Swizzle tools */ -#define R500_SWIZZLE_ZERO 4 -#define R500_SWIZZLE_HALF 5 -#define R500_SWIZZLE_ONE 6 -#define R500_SWIZ_RGB_ZERO ((4 << 0) | (4 << 3) | (4 << 6)) -#define R500_SWIZ_RGB_ONE ((6 << 0) | (6 << 3) | (6 << 6)) -#define R500_SWIZ_RGB_RGB ((0 << 0) | (1 << 3) | (2 << 6)) -#define R500_SWIZ_MOD_NEG 1 -#define R500_SWIZ_MOD_ABS 2 -#define R500_SWIZ_MOD_NEG_ABS 3 -/* Swizzles for inst2 */ -#define R500_SWIZ_TEX_STRQ(x) ((x) << 8) -#define R500_SWIZ_TEX_RGBA(x) ((x) << 24) -/* Swizzles for inst3 */ -#define R500_SWIZ_RGB_A(x) ((x) << 2) -#define R500_SWIZ_RGB_B(x) ((x) << 15) -/* Swizzles for inst4 */ -#define R500_SWIZ_ALPHA_A(x) ((x) << 14) -#define R500_SWIZ_ALPHA_B(x) ((x) << 21) -/* Swizzle for inst5 */ -#define R500_SWIZ_RGBA_C(x) ((x) << 14) -#define R500_SWIZ_ALPHA_C(x) ((x) << 27) -/* Writemasks */ -#define R500_TEX_WMASK(x) ((x) << 11) -#define R500_ALU_WMASK(x) ((x) << 11) -#define R500_ALU_OMASK(x) ((x) << 15) -#define R500_W_OMASK (1 << 31) - -static struct r5xx_fragment_shader r5xx_passthrough_fragment_shader = { - .shader.stack_size = 0, - .instruction_count = 1, - .instructions[0].inst0 = R500_INST_TYPE_OUT | - R500_INST_TEX_SEM_WAIT | R500_INST_LAST | - R500_INST_RGB_OMASK_RGB | R500_INST_ALPHA_OMASK | - R500_INST_RGB_CLAMP | R500_INST_ALPHA_CLAMP, - .instructions[0].inst1 = - R500_RGB_ADDR0(0) | R500_RGB_ADDR1(0) | R500_RGB_ADDR1_CONST | - R500_RGB_ADDR2(0) | R500_RGB_ADDR2_CONST, - .instructions[0].inst2 = - R500_ALPHA_ADDR0(0) | R500_ALPHA_ADDR1(0) | R500_ALPHA_ADDR1_CONST | - R500_ALPHA_ADDR2(0) | R500_ALPHA_ADDR2_CONST, - .instructions[0].inst3 = - R500_ALU_RGB_SEL_A_SRC0 | R500_ALU_RGB_R_SWIZ_A_R | - R500_ALU_RGB_G_SWIZ_A_G | R500_ALU_RGB_B_SWIZ_A_B | - R500_ALU_RGB_SEL_B_SRC0 | R500_ALU_RGB_R_SWIZ_B_R | - R500_ALU_RGB_B_SWIZ_B_G | R500_ALU_RGB_G_SWIZ_B_B, - .instructions[0].inst4 = - R500_ALPHA_OP_CMP | R500_ALPHA_SWIZ_A_A | R500_ALPHA_SWIZ_B_A, - .instructions[0].inst5 = - R500_ALU_RGBA_OP_CMP | R500_ALU_RGBA_R_SWIZ_0 | - R500_ALU_RGBA_G_SWIZ_0 | R500_ALU_RGBA_B_SWIZ_0 | - R500_ALU_RGBA_A_SWIZ_0, -}; - -static struct r5xx_fragment_shader r5xx_texture_fragment_shader = { - .shader.stack_size = 1, - .instruction_count = 2, - .instructions[0].inst0 = R500_INST_TYPE_TEX | - R500_INST_TEX_SEM_WAIT | - R500_INST_RGB_WMASK_RGB | R500_INST_ALPHA_WMASK | - R500_INST_RGB_CLAMP | R500_INST_ALPHA_CLAMP, - .instructions[0].inst1 = R500_TEX_ID(0) | R500_TEX_INST_LD | - R500_TEX_SEM_ACQUIRE | R500_TEX_IGNORE_UNCOVERED, - .instructions[0].inst2 = R500_TEX_SRC_ADDR(0) | - R500_TEX_SRC_S_SWIZ_R | R500_TEX_SRC_T_SWIZ_G | - R500_TEX_SRC_R_SWIZ_B | R500_TEX_SRC_Q_SWIZ_A | - R500_TEX_DST_ADDR(0) | - R500_TEX_DST_R_SWIZ_R | R500_TEX_DST_G_SWIZ_G | - R500_TEX_DST_B_SWIZ_B | R500_TEX_DST_A_SWIZ_A, - .instructions[0].inst3 = 0x0, - .instructions[0].inst4 = 0x0, - .instructions[0].inst5 = 0x0, - .instructions[1].inst0 = R500_INST_TYPE_OUT | - R500_INST_TEX_SEM_WAIT | R500_INST_LAST | - R500_INST_RGB_OMASK_RGB | R500_INST_ALPHA_OMASK | - R500_INST_RGB_CLAMP | R500_INST_ALPHA_CLAMP, - .instructions[1].inst1 = - R500_RGB_ADDR0(0) | R500_RGB_ADDR1(0) | R500_RGB_ADDR1_CONST | - R500_RGB_ADDR2(0) | R500_RGB_ADDR2_CONST, - .instructions[1].inst2 = - R500_ALPHA_ADDR0(0) | R500_ALPHA_ADDR1(0) | R500_ALPHA_ADDR1_CONST | - R500_ALPHA_ADDR2(0) | R500_ALPHA_ADDR2_CONST, - .instructions[1].inst3 = - R500_ALU_RGB_SEL_A_SRC0 | R500_ALU_RGB_R_SWIZ_A_R | - R500_ALU_RGB_G_SWIZ_A_G | R500_ALU_RGB_B_SWIZ_A_B | - R500_ALU_RGB_SEL_B_SRC0 | R500_ALU_RGB_R_SWIZ_B_R | - R500_ALU_RGB_B_SWIZ_B_G | R500_ALU_RGB_G_SWIZ_B_B, - .instructions[1].inst4 = - R500_ALPHA_OP_CMP | R500_ALPHA_SWIZ_A_A | R500_ALPHA_SWIZ_B_A, - .instructions[1].inst5 = - R500_ALU_RGBA_OP_CMP | R500_ALU_RGBA_R_SWIZ_0 | - R500_ALU_RGBA_G_SWIZ_0 | R500_ALU_RGBA_B_SWIZ_0 | - R500_ALU_RGBA_A_SWIZ_0, -}; - -void r5xx_fs_finalize(struct r5xx_fragment_shader* fs, - struct r300_fs_asm* assembler); - -void r5xx_fs_instruction(struct r5xx_fragment_shader* fs, - struct r300_fs_asm* assembler, - struct tgsi_full_instruction* inst); +struct rX00_fragment_program_code r5xx_passthrough_fragment_shader; +struct rX00_fragment_program_code r5xx_texture_fragment_shader; #endif /* R5XX_FS_H */ diff --git a/src/gallium/drivers/softpipe/sp_texture.c b/src/gallium/drivers/softpipe/sp_texture.c index 0c773e484b..70f0932431 100644 --- a/src/gallium/drivers/softpipe/sp_texture.c +++ b/src/gallium/drivers/softpipe/sp_texture.c @@ -48,11 +48,6 @@ /* Simple, maximally packed layout. */ -static unsigned minify( unsigned d ) -{ - return MAX2(1, d>>1); -} - /* Conventional allocation path for non-display textures: */ @@ -100,6 +95,7 @@ softpipe_displaytarget_layout(struct pipe_screen *screen, { unsigned usage = (PIPE_BUFFER_USAGE_CPU_READ_WRITE | PIPE_BUFFER_USAGE_GPU_READ_WRITE); + unsigned tex_usage = spt->base.tex_usage; spt->base.nblocksx[0] = pf_get_nblocksx(&spt->base.block, spt->base.width[0]); spt->base.nblocksy[0] = pf_get_nblocksy(&spt->base.block, spt->base.height[0]); @@ -109,6 +105,7 @@ softpipe_displaytarget_layout(struct pipe_screen *screen, spt->base.height[0], spt->base.format, usage, + tex_usage, &spt->stride[0]); return spt->buffer != NULL; @@ -130,7 +127,8 @@ softpipe_texture_create(struct pipe_screen *screen, pipe_reference_init(&spt->base.reference, 1); spt->base.screen = screen; - if (spt->base.tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET) { + if (spt->base.tex_usage & (PIPE_TEXTURE_USAGE_DISPLAY_TARGET | + PIPE_TEXTURE_USAGE_PRIMARY)) { if (!softpipe_displaytarget_layout(screen, spt)) goto fail; } diff --git a/src/gallium/drivers/trace/tr_drm.c b/src/gallium/drivers/trace/tr_drm.c index 98ac75e3fa..93c569c73a 100644 --- a/src/gallium/drivers/trace/tr_drm.c +++ b/src/gallium/drivers/trace/tr_drm.c @@ -63,7 +63,7 @@ trace_drm_create_screen(struct drm_api *_api, int fd, screen = api->create_screen(api, fd, arg); return trace_screen_create(screen); -}; +} static struct pipe_context * trace_drm_create_context(struct drm_api *_api, @@ -82,7 +82,7 @@ trace_drm_create_context(struct drm_api *_api, pipe = trace_context_create(_screen, pipe); return pipe; -}; +} static boolean trace_drm_buffer_from_texture(struct drm_api *_api, @@ -102,7 +102,7 @@ trace_drm_buffer_from_texture(struct drm_api *_api, result = api->buffer_from_texture(api, texture, &buffer, stride); if (result && _buffer) - buffer = trace_buffer_create(trace_screen(texture->screen), buffer); + buffer = trace_buffer_create(trace_screen(_texture->screen), buffer); if (_buffer) *_buffer = buffer; diff --git a/src/gallium/drivers/trace/tr_screen.c b/src/gallium/drivers/trace/tr_screen.c index 5b1e26a52d..26f1c04594 100644 --- a/src/gallium/drivers/trace/tr_screen.c +++ b/src/gallium/drivers/trace/tr_screen.c @@ -462,6 +462,7 @@ trace_screen_surface_buffer_create(struct pipe_screen *_screen, unsigned width, unsigned height, enum pipe_format format, unsigned usage, + unsigned tex_usage, unsigned *pstride) { struct trace_screen *tr_scr = trace_screen(_screen); @@ -476,11 +477,13 @@ trace_screen_surface_buffer_create(struct pipe_screen *_screen, trace_dump_arg(uint, height); trace_dump_arg(format, format); trace_dump_arg(uint, usage); + trace_dump_arg(uint, tex_usage); result = screen->surface_buffer_create(screen, width, height, format, usage, + tex_usage, pstride); stride = *pstride; diff --git a/src/gallium/include/pipe/internal/p_winsys_screen.h b/src/gallium/include/pipe/internal/p_winsys_screen.h index f4a29e63c7..a1542dada7 100644 --- a/src/gallium/include/pipe/internal/p_winsys_screen.h +++ b/src/gallium/include/pipe/internal/p_winsys_screen.h @@ -140,6 +140,7 @@ struct pipe_winsys unsigned width, unsigned height, enum pipe_format format, unsigned usage, + unsigned tex_usage, unsigned *stride); diff --git a/src/gallium/include/pipe/p_screen.h b/src/gallium/include/pipe/p_screen.h index 6cbdd75943..3f30c52a16 100644 --- a/src/gallium/include/pipe/p_screen.h +++ b/src/gallium/include/pipe/p_screen.h @@ -194,6 +194,7 @@ struct pipe_screen { unsigned width, unsigned height, enum pipe_format format, unsigned usage, + unsigned tex_usage, unsigned *stride); diff --git a/src/gallium/state_trackers/dri/dri_context.c b/src/gallium/state_trackers/dri/dri_context.c index 6c617197ec..830e511fef 100644 --- a/src/gallium/state_trackers/dri/dri_context.c +++ b/src/gallium/state_trackers/dri/dri_context.c @@ -109,9 +109,6 @@ dri_destroy_context(__DRIcontextPrivate * cPriv) */ st_flush(ctx->st, 0, NULL); - if (screen->dummyContext == ctx) - screen->dummyContext = NULL; - /* Also frees ctx->pipe? */ st_destroy_context(ctx->st); @@ -153,11 +150,6 @@ dri_make_current(__DRIcontextPrivate * cPriv, ++ctx->bind_count; - /* This is for situations in which we need a rendering context but - * there may not be any currently bound. - */ - screen->dummyContext = ctx; - if (ctx->dPriv != driDrawPriv) { ctx->dPriv = driDrawPriv; ctx->d_stamp = driDrawPriv->lastStamp - 1; diff --git a/src/gallium/state_trackers/dri/dri_drawable.c b/src/gallium/state_trackers/dri/dri_drawable.c index 1d91fbb89f..0a952f7b28 100644 --- a/src/gallium/state_trackers/dri/dri_drawable.c +++ b/src/gallium/state_trackers/dri/dri_drawable.c @@ -204,6 +204,30 @@ dri_get_buffers(__DRIdrawablePrivate * dPriv) st_resize_framebuffer(drawable->stfb, dri_drawable->w, dri_drawable->h); } +/** + * These are used for GLX_EXT_texture_from_pixmap + */ +void dri2_set_tex_buffer2(__DRIcontext *pDRICtx, GLint target, + GLint format, __DRIdrawable *dPriv) +{ + struct dri_drawable *drawable = dri_drawable(dPriv); + struct pipe_surface *ps; + + dri_get_buffers(drawable->dPriv); + st_get_framebuffer_surface(drawable->stfb, ST_SURFACE_FRONT_LEFT, &ps); + + st_bind_texture_surface(ps, target == GL_TEXTURE_2D ? ST_TEXTURE_2D : + ST_TEXTURE_RECT, 0, + format == GLX_TEXTURE_FORMAT_RGBA_EXT ? + PIPE_FORMAT_R8G8B8A8_UNORM : PIPE_FORMAT_R8G8B8X8_UNORM); +} + +void dri2_set_tex_buffer(__DRIcontext *pDRICtx, GLint target, + __DRIdrawable *dPriv) +{ + dri2_set_tex_buffer2(pDRICtx, target, GLX_TEXTURE_FORMAT_RGBA_EXT, dPriv); +} + void dri_flush_frontbuffer(struct pipe_screen *screen, struct pipe_surface *surf, void *context_private) diff --git a/src/gallium/state_trackers/dri/dri_drawable.h b/src/gallium/state_trackers/dri/dri_drawable.h index 2fbd5f1eb7..dfd0b8766d 100644 --- a/src/gallium/state_trackers/dri/dri_drawable.h +++ b/src/gallium/state_trackers/dri/dri_drawable.h @@ -91,6 +91,12 @@ void dri_get_buffers(__DRIdrawablePrivate * dPriv); void dri_destroy_buffer(__DRIdrawablePrivate * dPriv); +void dri2_set_tex_buffer2(__DRIcontext *pDRICtx, GLint target, + GLint glx_texture_format, __DRIdrawable *dPriv); + +void dri2_set_tex_buffer(__DRIcontext *pDRICtx, GLint target, + __DRIdrawable *dPriv); + void dri1_update_drawables(struct dri_context *ctx, struct dri_drawable *draw, struct dri_drawable *read); diff --git a/src/gallium/state_trackers/dri/dri_screen.c b/src/gallium/state_trackers/dri/dri_screen.c index 5f78b7264a..25555128f9 100644 --- a/src/gallium/state_trackers/dri/dri_screen.c +++ b/src/gallium/state_trackers/dri/dri_screen.c @@ -57,12 +57,19 @@ PUBLIC const char __driConfigOptions[] = const uint __driNConfigOptions = 3; +static const __DRItexBufferExtension dri2TexBufferExtension = { + { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION }, + dri2_set_tex_buffer, + dri2_set_tex_buffer2, +}; + static const __DRIextension *dri_screen_extensions[] = { &driReadDrawableExtension, &driCopySubBufferExtension.base, &driSwapControlExtension.base, &driFrameTrackingExtension.base, &driMediaStreamCounterExtension.base, + &dri2TexBufferExtension.base, NULL }; diff --git a/src/gallium/state_trackers/dri/dri_screen.h b/src/gallium/state_trackers/dri/dri_screen.h index f3335bb09f..f6c56d0f0c 100644 --- a/src/gallium/state_trackers/dri/dri_screen.h +++ b/src/gallium/state_trackers/dri/dri_screen.h @@ -49,12 +49,6 @@ struct dri_screen */ driOptionCache optionCache; - /** - * Temporary(?) context to use for SwapBuffers or other situations in - * which we need a rendering context, but none is currently bound. - */ - struct dri_context *dummyContext; - /* drm */ int fd; drmLock *drmLock; diff --git a/src/gallium/state_trackers/egl/egl_context.c b/src/gallium/state_trackers/egl/egl_context.c index e2da2180f7..2c8f51cf38 100644 --- a/src/gallium/state_trackers/egl/egl_context.c +++ b/src/gallium/state_trackers/egl/egl_context.c @@ -148,7 +148,7 @@ drm_destroy_context(_EGLDriver *drv, EGLDisplay dpy, EGLContext context) { struct drm_context *c = lookup_drm_context(context); _eglUnlinkContext(&c->base); - if (!c->base.IsBound) { + if (!_eglIsContextBound(&c->base)) { st_destroy_context(c->st); c->pipe->destroy(c->pipe); free(c); diff --git a/src/gallium/state_trackers/egl/egl_surface.c b/src/gallium/state_trackers/egl/egl_surface.c index 86f2ea97e5..d4cd2d3c74 100644 --- a/src/gallium/state_trackers/egl/egl_surface.c +++ b/src/gallium/state_trackers/egl/egl_surface.c @@ -98,8 +98,8 @@ drm_create_texture(_EGLDriver *drv, goto err_buf; memset(&templat, 0, sizeof(templat)); - templat.tex_usage |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET; - templat.tex_usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET; + templat.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET; + templat.tex_usage |= PIPE_TEXTURE_USAGE_PRIMARY; templat.target = PIPE_TEXTURE_2D; templat.last_level = 0; templat.depth[0] = 1; @@ -366,7 +366,7 @@ drm_destroy_surface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface) struct drm_surface *surf = lookup_drm_surface(surface); _eglUnlinkSurface(&surf->base); - if (!surf->base.IsBound) { + if (!_eglIsSurfaceBound(&surf->base)) { if (surf->screen) drm_takedown_shown_screen(drv, surf->screen); st_unreference_framebuffer(surf->stfb); diff --git a/src/gallium/state_trackers/glx/xlib/Makefile b/src/gallium/state_trackers/glx/xlib/Makefile index 6d10b090aa..7b2adc62c3 100644 --- a/src/gallium/state_trackers/glx/xlib/Makefile +++ b/src/gallium/state_trackers/glx/xlib/Makefile @@ -5,13 +5,12 @@ LIBNAME = xlib LIBRARY_INCLUDES = \ -I$(TOP)/include \ - -I$(TOP)/src/mesa \ - -I$(TOP)/src/mesa/main + -I$(TOP)/src/mesa C_SOURCES = \ - glxapi.c \ - fakeglx.c \ - fakeglx_fonts.c \ + glx_api.c \ + glx_getproc.c \ + glx_usefont.c \ xm_api.c include ../../../Makefile.template diff --git a/src/gallium/state_trackers/glx/xlib/SConscript b/src/gallium/state_trackers/glx/xlib/SConscript index 0dbe341397..04a44c3067 100644 --- a/src/gallium/state_trackers/glx/xlib/SConscript +++ b/src/gallium/state_trackers/glx/xlib/SConscript @@ -18,9 +18,10 @@ if env['platform'] == 'linux' \ st_xlib = env.ConvenienceLibrary( target = 'st_xlib', - source = [ 'glxapi.c', - 'fakeglx.c', - 'fakeglx_fonts.c', + source = [ + 'glx_api.c', + 'glx_getproc.c', + 'glx_usefont.c', 'xm_api.c', ] ) diff --git a/src/gallium/state_trackers/glx/xlib/fakeglx.h b/src/gallium/state_trackers/glx/xlib/fakeglx.h deleted file mode 100644 index e5fd960072..0000000000 --- a/src/gallium/state_trackers/glx/xlib/fakeglx.h +++ /dev/null @@ -1,41 +0,0 @@ - -/* - * Mesa 3-D graphics library - * Version: 3.5 - * - * Copyright (C) 1999-2000 Brian Paul 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, 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 - * BRIAN PAUL 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 FAKEGLX_H -#define FAKEGLX_H - - -#include <X11/Xlib.h> - -struct _glxapi_table; - -extern struct _glxapi_table *_mesa_GetGLXDispatchTable(void); - -extern void Fake_glXUseXFont( Font font, int first, int count, int listbase ); - - -#endif - diff --git a/src/gallium/state_trackers/glx/xlib/fakeglx.c b/src/gallium/state_trackers/glx/xlib/glx_api.c index 23777c76f6..96490dbeda 100644 --- a/src/gallium/state_trackers/glx/xlib/fakeglx.c +++ b/src/gallium/state_trackers/glx/xlib/glx_api.c @@ -1,8 +1,9 @@ /* * Mesa 3-D graphics library - * Version: 7.1 + * Version: 7.6 * * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + * Copyright (C) 2009 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"), @@ -23,31 +24,21 @@ */ -/* - * This is an emulation of the GLX API which allows Mesa/GLX-based programs - * to run on X servers which do not have the real GLX extension. - * - * Thanks to the contributors: - * - * Initial version: Philip Brown (phil@bolthole.com) - * Better glXGetConfig() support: Armin Liebchen (liebchen@asylum.cs.utah.edu) - * Further visual-handling refinements: Wolfram Gloger - * (wmglo@Dent.MED.Uni-Muenchen.DE). - * - * Notes: - * Don't be fooled, stereo isn't supported yet. +/** + * "Fake" GLX API implemented in terms of the XMesa*() functions. */ -#include "glxapi.h" +#define GLX_GLXEXT_PROTOTYPES +#include "GL/glx.h" + #include "xm_api.h" -#include "context.h" -#include "config.h" -#include "macros.h" -#include "imports.h" -#include "version.h" -#include "fakeglx.h" +#include "main/context.h" +#include "main/config.h" +#include "main/macros.h" +#include "main/imports.h" +#include "main/version.h" #include "state_tracker/st_context.h" #include "state_tracker/st_public.h" @@ -80,24 +71,55 @@ "GLX_SGIX_fbconfig " \ "GLX_SGIX_pbuffer " -/* - * Our fake GLX context will contain a "real" GLX context and an XMesa context. - * - * Note that a pointer to a __GLXcontext is a pointer to a fake_glx_context, - * and vice versa. - * - * We really just need this structure in order to make the libGL functions - * glXGetCurrentContext(), glXGetCurrentDrawable() and glXGetCurrentDisplay() - * work correctly. +#define DEFAULT_DIRECT GL_TRUE + + + +/** + * The GLXContext typedef is defined as a pointer to this structure. */ -struct fake_glx_context { - __GLXcontext glxContext; /* this MUST be first! */ +struct __GLXcontextRec +{ + Display *currentDpy; + GLboolean isDirect; + GLXDrawable currentDrawable; + GLXDrawable currentReadable; + XID xid; + XMesaContext xmesaContext; }; -#define DEFAULT_DIRECT GL_TRUE +static pipe_tsd ContextTSD; + +/** Set current context for calling thread */ +static void +SetCurrentContext(GLXContext c) +{ + pipe_tsd_set(&ContextTSD, c); +} + +/** Get current context for calling thread */ +static GLXContext +GetCurrentContext(void) +{ + return pipe_tsd_get(&ContextTSD); +} + + + +/**********************************************************************/ +/*** Debug helper code ***/ +/**********************************************************************/ + +extern void _kw_ungrab_all( Display *dpy ); +void _kw_ungrab_all( Display *dpy ) +{ + XUngrabPointer( dpy, CurrentTime ); + XUngrabKeyboard( dpy, CurrentTime ); +} + /**********************************************************************/ @@ -366,10 +388,6 @@ find_glx_visual( Display *dpy, XVisualInfo *vinfo ) } - - - - /** * Try to get an X visual which matches the given arguments. */ @@ -418,7 +436,6 @@ get_visual( Display *dpy, int scr, unsigned int depth, int xclass ) } - /* * Retrieve the value of the given environment variable and find * the X visual which matches it. @@ -1002,8 +1019,8 @@ choose_visual( Display *dpy, int screen, const int *list, GLboolean fbConfig ) } -static XVisualInfo * -Fake_glXChooseVisual( Display *dpy, int screen, int *list ) +XVisualInfo * +glXChooseVisual( Display *dpy, int screen, int *list ) { XMesaVisual xmvis; @@ -1024,18 +1041,18 @@ Fake_glXChooseVisual( Display *dpy, int screen, int *list ) } -static GLXContext -Fake_glXCreateContext( Display *dpy, XVisualInfo *visinfo, - GLXContext share_list, Bool direct ) +GLXContext +glXCreateContext( Display *dpy, XVisualInfo *visinfo, + GLXContext share_list, Bool direct ) { XMesaVisual xmvis; - struct fake_glx_context *glxCtx; - struct fake_glx_context *shareCtx = (struct fake_glx_context *) share_list; + GLXContext glxCtx; + GLXContext shareCtx = share_list; if (!dpy || !visinfo) return 0; - glxCtx = CALLOC_STRUCT(fake_glx_context); + glxCtx = CALLOC_STRUCT(__GLXcontextRec); if (!glxCtx) return 0; @@ -1062,13 +1079,11 @@ Fake_glXCreateContext( Display *dpy, XVisualInfo *visinfo, return NULL; } - glxCtx->glxContext.isDirect = DEFAULT_DIRECT; - glxCtx->glxContext.currentDpy = dpy; - glxCtx->glxContext.xid = (XID) glxCtx; /* self pointer */ - - assert((void *) glxCtx == (void *) &(glxCtx->glxContext)); + glxCtx->isDirect = DEFAULT_DIRECT; + glxCtx->currentDpy = dpy; + glxCtx->xid = (XID) glxCtx; /* self pointer */ - return (GLXContext) glxCtx; + return glxCtx; } @@ -1081,11 +1096,11 @@ static XMesaBuffer MakeCurrent_PrevReadBuffer = 0; /* GLX 1.3 and later */ -static Bool -Fake_glXMakeContextCurrent( Display *dpy, GLXDrawable draw, - GLXDrawable read, GLXContext ctx ) +Bool +glXMakeContextCurrent( Display *dpy, GLXDrawable draw, + GLXDrawable read, GLXContext ctx ) { - struct fake_glx_context *glxCtx = (struct fake_glx_context *) ctx; + GLXContext glxCtx = ctx; static boolean firsttime = 1, no_rast = 0; if (firsttime) { @@ -1093,7 +1108,6 @@ Fake_glXMakeContextCurrent( Display *dpy, GLXDrawable draw, firsttime = 0; } - if (ctx && draw && read) { XMesaBuffer drawBuffer, readBuffer; XMesaContext xmctx = glxCtx->xmesaContext; @@ -1148,9 +1162,10 @@ Fake_glXMakeContextCurrent( Display *dpy, GLXDrawable draw, /* Now make current! */ if (XMesaMakeCurrent2(xmctx, drawBuffer, readBuffer)) { - ((__GLXcontext *) ctx)->currentDpy = dpy; - ((__GLXcontext *) ctx)->currentDrawable = draw; - ((__GLXcontext *) ctx)->currentReadable = read; + ctx->currentDpy = dpy; + ctx->currentDrawable = draw; + ctx->currentReadable = read; + SetCurrentContext(ctx); return True; } else { @@ -1165,6 +1180,7 @@ Fake_glXMakeContextCurrent( Display *dpy, GLXDrawable draw, MakeCurrent_PrevReadable = 0; MakeCurrent_PrevDrawBuffer = 0; MakeCurrent_PrevReadBuffer = 0; + SetCurrentContext(NULL); return True; } else { @@ -1176,15 +1192,61 @@ Fake_glXMakeContextCurrent( Display *dpy, GLXDrawable draw, } -static Bool -Fake_glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx ) +Bool +glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx ) { - return Fake_glXMakeContextCurrent( dpy, drawable, drawable, ctx ); + return glXMakeContextCurrent( dpy, drawable, drawable, ctx ); } -static GLXPixmap -Fake_glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo, Pixmap pixmap ) +GLXContext +glXGetCurrentContext(void) +{ + return GetCurrentContext(); +} + + +Display * +glXGetCurrentDisplay(void) +{ + GLXContext glxCtx = glXGetCurrentContext(); + + return glxCtx ? glxCtx->currentDpy : NULL; +} + + +Display * +glXGetCurrentDisplayEXT(void) +{ + return glXGetCurrentDisplay(); +} + + +GLXDrawable +glXGetCurrentDrawable(void) +{ + GLXContext gc = glXGetCurrentContext(); + return gc ? gc->currentDrawable : 0; +} + + +GLXDrawable +glXGetCurrentReadDrawable(void) +{ + GLXContext gc = glXGetCurrentContext(); + return gc ? gc->currentReadable : 0; +} + + +GLXDrawable +glXGetCurrentReadDrawableSGI(void) +{ + return glXGetCurrentReadDrawable(); +} + + +GLXPixmap +glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo, Pixmap pixmap ) { XMesaVisual v; XMesaBuffer b; @@ -1208,9 +1270,9 @@ Fake_glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo, Pixmap pixmap ) /*** GLX_MESA_pixmap_colormap ***/ -static GLXPixmap -Fake_glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo, - Pixmap pixmap, Colormap cmap ) +GLXPixmap +glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo, + Pixmap pixmap, Colormap cmap ) { XMesaVisual v; XMesaBuffer b; @@ -1232,8 +1294,8 @@ Fake_glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo, } -static void -Fake_glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap ) +void +glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap ) { XMesaBuffer b = XMesaFindBuffer(dpy, pixmap); if (b) { @@ -1245,12 +1307,12 @@ Fake_glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap ) } -static void -Fake_glXCopyContext( Display *dpy, GLXContext src, GLXContext dst, - unsigned long mask ) +void +glXCopyContext( Display *dpy, GLXContext src, GLXContext dst, + unsigned long mask ) { - struct fake_glx_context *fakeSrc = (struct fake_glx_context *) src; - struct fake_glx_context *fakeDst = (struct fake_glx_context *) dst; + GLXContext fakeSrc = src; + GLXContext fakeDst = dst; XMesaContext xm_src = fakeSrc->xmesaContext; XMesaContext xm_dst = fakeDst->xmesaContext; (void) dpy; @@ -1261,8 +1323,8 @@ Fake_glXCopyContext( Display *dpy, GLXContext src, GLXContext dst, } -static Bool -Fake_glXQueryExtension( Display *dpy, int *errorb, int *event ) +Bool +glXQueryExtension( Display *dpy, int *errorb, int *event ) { /* Mesa's GLX isn't really an X extension but we try to act like one. */ (void) dpy; @@ -1272,18 +1334,10 @@ Fake_glXQueryExtension( Display *dpy, int *errorb, int *event ) } -extern void _kw_ungrab_all( Display *dpy ); -void _kw_ungrab_all( Display *dpy ) -{ - XUngrabPointer( dpy, CurrentTime ); - XUngrabKeyboard( dpy, CurrentTime ); -} - - -static void -Fake_glXDestroyContext( Display *dpy, GLXContext ctx ) +void +glXDestroyContext( Display *dpy, GLXContext ctx ) { - struct fake_glx_context *glxCtx = (struct fake_glx_context *) ctx; + GLXContext glxCtx = ctx; (void) dpy; MakeCurrent_PrevContext = 0; MakeCurrent_PrevDrawable = 0; @@ -1296,18 +1350,18 @@ Fake_glXDestroyContext( Display *dpy, GLXContext ctx ) } -static Bool -Fake_glXIsDirect( Display *dpy, GLXContext ctx ) +Bool +glXIsDirect( Display *dpy, GLXContext ctx ) { - struct fake_glx_context *glxCtx = (struct fake_glx_context *) ctx; + GLXContext glxCtx = ctx; (void) ctx; - return glxCtx->glxContext.isDirect; + return glxCtx->isDirect; } -static void -Fake_glXSwapBuffers( Display *dpy, GLXDrawable drawable ) +void +glXSwapBuffers( Display *dpy, GLXDrawable drawable ) { XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable ); static boolean firsttime = 1, no_rast = 0; @@ -1333,8 +1387,8 @@ Fake_glXSwapBuffers( Display *dpy, GLXDrawable drawable ) /*** GLX_MESA_copy_sub_buffer ***/ -static void -Fake_glXCopySubBufferMESA( Display *dpy, GLXDrawable drawable, +void +glXCopySubBufferMESA( Display *dpy, GLXDrawable drawable, int x, int y, int width, int height ) { XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable ); @@ -1347,8 +1401,8 @@ Fake_glXCopySubBufferMESA( Display *dpy, GLXDrawable drawable, } -static Bool -Fake_glXQueryVersion( Display *dpy, int *maj, int *min ) +Bool +glXQueryVersion( Display *dpy, int *maj, int *min ) { (void) dpy; /* Return GLX version, not Mesa version */ @@ -1564,8 +1618,8 @@ get_config( XMesaVisual xmvis, int attrib, int *value, GLboolean fbconfig ) } -static int -Fake_glXGetConfig( Display *dpy, XVisualInfo *visinfo, +int +glXGetConfig( Display *dpy, XVisualInfo *visinfo, int attrib, int *value ) { XMesaVisual xmvis; @@ -1594,8 +1648,8 @@ Fake_glXGetConfig( Display *dpy, XVisualInfo *visinfo, } -static void -Fake_glXWaitGL( void ) +void +glXWaitGL( void ) { XMesaContext xmesa = XMesaGetCurrentContext(); XMesaFlush( xmesa ); @@ -1603,8 +1657,8 @@ Fake_glXWaitGL( void ) -static void -Fake_glXWaitX( void ) +void +glXWaitX( void ) { XMesaContext xmesa = XMesaGetCurrentContext(); XMesaFlush( xmesa ); @@ -1620,8 +1674,8 @@ get_extensions( void ) /* GLX 1.1 and later */ -static const char * -Fake_glXQueryExtensionsString( Display *dpy, int screen ) +const char * +glXQueryExtensionsString( Display *dpy, int screen ) { (void) dpy; (void) screen; @@ -1631,8 +1685,8 @@ Fake_glXQueryExtensionsString( Display *dpy, int screen ) /* GLX 1.1 and later */ -static const char * -Fake_glXQueryServerString( Display *dpy, int screen, int name ) +const char * +glXQueryServerString( Display *dpy, int screen, int name ) { static char version[1000]; _mesa_sprintf(version, "%d.%d %s", @@ -1656,8 +1710,8 @@ Fake_glXQueryServerString( Display *dpy, int screen, int name ) /* GLX 1.1 and later */ -static const char * -Fake_glXGetClientString( Display *dpy, int name ) +const char * +glXGetClientString( Display *dpy, int name ) { static char version[1000]; _mesa_sprintf(version, "%d.%d %s", CLIENT_MAJOR_VERSION, @@ -1684,8 +1738,8 @@ Fake_glXGetClientString( Display *dpy, int name ) */ -static int -Fake_glXGetFBConfigAttrib( Display *dpy, GLXFBConfig config, +int +glXGetFBConfigAttrib( Display *dpy, GLXFBConfig config, int attribute, int *value ) { XMesaVisual v = (XMesaVisual) config; @@ -1699,8 +1753,8 @@ Fake_glXGetFBConfigAttrib( Display *dpy, GLXFBConfig config, } -static GLXFBConfig * -Fake_glXGetFBConfigs( Display *dpy, int screen, int *nelements ) +GLXFBConfig * +glXGetFBConfigs( Display *dpy, int screen, int *nelements ) { XVisualInfo *visuals, visTemplate; const long visMask = VisualScreenMask; @@ -1725,15 +1779,15 @@ Fake_glXGetFBConfigs( Display *dpy, int screen, int *nelements ) } -static GLXFBConfig * -Fake_glXChooseFBConfig( Display *dpy, int screen, +GLXFBConfig * +glXChooseFBConfig( Display *dpy, int screen, const int *attribList, int *nitems ) { XMesaVisual xmvis; if (!attribList || !attribList[0]) { /* return list of all configs (per GLX_SGIX_fbconfig spec) */ - return Fake_glXGetFBConfigs(dpy, screen, nitems); + return glXGetFBConfigs(dpy, screen, nitems); } xmvis = choose_visual(dpy, screen, attribList, GL_TRUE); @@ -1754,8 +1808,8 @@ Fake_glXChooseFBConfig( Display *dpy, int screen, } -static XVisualInfo * -Fake_glXGetVisualFromFBConfig( Display *dpy, GLXFBConfig config ) +XVisualInfo * +glXGetVisualFromFBConfig( Display *dpy, GLXFBConfig config ) { if (dpy && config) { XMesaVisual xmvis = (XMesaVisual) config; @@ -1776,8 +1830,8 @@ Fake_glXGetVisualFromFBConfig( Display *dpy, GLXFBConfig config ) } -static GLXWindow -Fake_glXCreateWindow( Display *dpy, GLXFBConfig config, Window win, +GLXWindow +glXCreateWindow( Display *dpy, GLXFBConfig config, Window win, const int *attribList ) { XMesaVisual xmvis = (XMesaVisual) config; @@ -1796,8 +1850,8 @@ Fake_glXCreateWindow( Display *dpy, GLXFBConfig config, Window win, } -static void -Fake_glXDestroyWindow( Display *dpy, GLXWindow window ) +void +glXDestroyWindow( Display *dpy, GLXWindow window ) { XMesaBuffer b = XMesaFindBuffer(dpy, (Drawable) window); if (b) @@ -1807,8 +1861,8 @@ Fake_glXDestroyWindow( Display *dpy, GLXWindow window ) /* XXX untested */ -static GLXPixmap -Fake_glXCreatePixmap( Display *dpy, GLXFBConfig config, Pixmap pixmap, +GLXPixmap +glXCreatePixmap( Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attribList ) { XMesaVisual v = (XMesaVisual) config; @@ -1917,8 +1971,8 @@ Fake_glXCreatePixmap( Display *dpy, GLXFBConfig config, Pixmap pixmap, } -static void -Fake_glXDestroyPixmap( Display *dpy, GLXPixmap pixmap ) +void +glXDestroyPixmap( Display *dpy, GLXPixmap pixmap ) { XMesaBuffer b = XMesaFindBuffer(dpy, (Drawable)pixmap); if (b) @@ -1927,8 +1981,8 @@ Fake_glXDestroyPixmap( Display *dpy, GLXPixmap pixmap ) } -static GLXPbuffer -Fake_glXCreatePbuffer( Display *dpy, GLXFBConfig config, +GLXPbuffer +glXCreatePbuffer( Display *dpy, GLXFBConfig config, const int *attribList ) { XMesaVisual xmvis = (XMesaVisual) config; @@ -1980,8 +2034,8 @@ Fake_glXCreatePbuffer( Display *dpy, GLXFBConfig config, } -static void -Fake_glXDestroyPbuffer( Display *dpy, GLXPbuffer pbuf ) +void +glXDestroyPbuffer( Display *dpy, GLXPbuffer pbuf ) { XMesaBuffer b = XMesaFindBuffer(dpy, pbuf); if (b) { @@ -1990,8 +2044,8 @@ Fake_glXDestroyPbuffer( Display *dpy, GLXPbuffer pbuf ) } -static void -Fake_glXQueryDrawable( Display *dpy, GLXDrawable draw, int attribute, +void +glXQueryDrawable( Display *dpy, GLXDrawable draw, int attribute, unsigned int *value ) { XMesaBuffer xmbuf = XMesaFindBuffer(dpy, draw); @@ -2032,19 +2086,19 @@ Fake_glXQueryDrawable( Display *dpy, GLXDrawable draw, int attribute, } -static GLXContext -Fake_glXCreateNewContext( Display *dpy, GLXFBConfig config, +GLXContext +glXCreateNewContext( Display *dpy, GLXFBConfig config, int renderType, GLXContext shareList, Bool direct ) { - struct fake_glx_context *glxCtx; - struct fake_glx_context *shareCtx = (struct fake_glx_context *) shareList; + GLXContext glxCtx; + GLXContext shareCtx = shareList; XMesaVisual xmvis = (XMesaVisual) config; if (!dpy || !config || (renderType != GLX_RGBA_TYPE && renderType != GLX_COLOR_INDEX_TYPE)) return 0; - glxCtx = CALLOC_STRUCT(fake_glx_context); + glxCtx = CALLOC_STRUCT(__GLXcontextRec); if (!glxCtx) return 0; @@ -2058,20 +2112,18 @@ Fake_glXCreateNewContext( Display *dpy, GLXFBConfig config, return NULL; } - glxCtx->glxContext.isDirect = DEFAULT_DIRECT; - glxCtx->glxContext.currentDpy = dpy; - glxCtx->glxContext.xid = (XID) glxCtx; /* self pointer */ - - assert((void *) glxCtx == (void *) &(glxCtx->glxContext)); + glxCtx->isDirect = DEFAULT_DIRECT; + glxCtx->currentDpy = dpy; + glxCtx->xid = (XID) glxCtx; /* self pointer */ - return (GLXContext) glxCtx; + return glxCtx; } -static int -Fake_glXQueryContext( Display *dpy, GLXContext ctx, int attribute, int *value ) +int +glXQueryContext( Display *dpy, GLXContext ctx, int attribute, int *value ) { - struct fake_glx_context *glxCtx = (struct fake_glx_context *) ctx; + GLXContext glxCtx = ctx; XMesaContext xmctx = glxCtx->xmesaContext; (void) dpy; @@ -2097,8 +2149,8 @@ Fake_glXQueryContext( Display *dpy, GLXContext ctx, int attribute, int *value ) } -static void -Fake_glXSelectEvent( Display *dpy, GLXDrawable drawable, unsigned long mask ) +void +glXSelectEvent( Display *dpy, GLXDrawable drawable, unsigned long mask ) { XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); if (xmbuf) @@ -2106,8 +2158,8 @@ Fake_glXSelectEvent( Display *dpy, GLXDrawable drawable, unsigned long mask ) } -static void -Fake_glXGetSelectedEvent( Display *dpy, GLXDrawable drawable, +void +glXGetSelectedEvent( Display *dpy, GLXDrawable drawable, unsigned long *mask ) { XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); @@ -2121,8 +2173,8 @@ Fake_glXGetSelectedEvent( Display *dpy, GLXDrawable drawable, /*** GLX_SGI_swap_control ***/ -static int -Fake_glXSwapIntervalSGI(int interval) +int +glXSwapIntervalSGI(int interval) { (void) interval; return 0; @@ -2134,16 +2186,16 @@ Fake_glXSwapIntervalSGI(int interval) static unsigned int FrameCounter = 0; -static int -Fake_glXGetVideoSyncSGI(unsigned int *count) +int +glXGetVideoSyncSGI(unsigned int *count) { /* this is a bogus implementation */ *count = FrameCounter++; return 0; } -static int -Fake_glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count) +int +glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count) { if (divisor <= 0 || remainder < 0) return GLX_BAD_VALUE; @@ -2159,15 +2211,15 @@ Fake_glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count) /*** GLX_SGI_make_current_read ***/ -static Bool -Fake_glXMakeCurrentReadSGI(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx) +Bool +glXMakeCurrentReadSGI(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx) { - return Fake_glXMakeContextCurrent( dpy, draw, read, ctx ); + return glXMakeContextCurrent( dpy, draw, read, ctx ); } /* not used static GLXDrawable -Fake_glXGetCurrentReadDrawableSGI(void) +glXGetCurrentReadDrawableSGI(void) { return 0; } @@ -2177,8 +2229,8 @@ Fake_glXGetCurrentReadDrawableSGI(void) /*** GLX_SGIX_video_source ***/ #if defined(_VL_H) -static GLXVideoSourceSGIX -Fake_glXCreateGLXVideoSourceSGIX(Display *dpy, int screen, VLServer server, VLPath path, int nodeClass, VLNode drainNode) +GLXVideoSourceSGIX +glXCreateGLXVideoSourceSGIX(Display *dpy, int screen, VLServer server, VLPath path, int nodeClass, VLNode drainNode) { (void) dpy; (void) screen; @@ -2189,8 +2241,8 @@ Fake_glXCreateGLXVideoSourceSGIX(Display *dpy, int screen, VLServer server, VLPa return 0; } -static void -Fake_glXDestroyGLXVideoSourceSGIX(Display *dpy, GLXVideoSourceSGIX src) +void +glXDestroyGLXVideoSourceSGIX(Display *dpy, GLXVideoSourceSGIX src) { (void) dpy; (void) src; @@ -2201,30 +2253,30 @@ Fake_glXDestroyGLXVideoSourceSGIX(Display *dpy, GLXVideoSourceSGIX src) /*** GLX_EXT_import_context ***/ -static void -Fake_glXFreeContextEXT(Display *dpy, GLXContext context) +void +glXFreeContextEXT(Display *dpy, GLXContext context) { (void) dpy; (void) context; } -static GLXContextID -Fake_glXGetContextIDEXT(const GLXContext context) +GLXContextID +glXGetContextIDEXT(const GLXContext context) { (void) context; return 0; } -static GLXContext -Fake_glXImportContextEXT(Display *dpy, GLXContextID contextID) +GLXContext +glXImportContextEXT(Display *dpy, GLXContextID contextID) { (void) dpy; (void) contextID; return 0; } -static int -Fake_glXQueryContextInfoEXT(Display *dpy, GLXContext context, int attribute, int *value) +int +glXQueryContextInfoEXT(Display *dpy, GLXContext context, int attribute, int *value) { (void) dpy; (void) context; @@ -2237,21 +2289,21 @@ Fake_glXQueryContextInfoEXT(Display *dpy, GLXContext context, int attribute, int /*** GLX_SGIX_fbconfig ***/ -static int -Fake_glXGetFBConfigAttribSGIX(Display *dpy, GLXFBConfigSGIX config, int attribute, int *value) +int +glXGetFBConfigAttribSGIX(Display *dpy, GLXFBConfigSGIX config, int attribute, int *value) { - return Fake_glXGetFBConfigAttrib(dpy, config, attribute, value); + return glXGetFBConfigAttrib(dpy, config, attribute, value); } -static GLXFBConfigSGIX * -Fake_glXChooseFBConfigSGIX(Display *dpy, int screen, int *attrib_list, int *nelements) +GLXFBConfigSGIX * +glXChooseFBConfigSGIX(Display *dpy, int screen, int *attrib_list, int *nelements) { - return (GLXFBConfig *) Fake_glXChooseFBConfig(dpy, screen, attrib_list, nelements); + return (GLXFBConfig *) glXChooseFBConfig(dpy, screen, attrib_list, nelements); } -static GLXPixmap -Fake_glXCreateGLXPixmapWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, Pixmap pixmap) +GLXPixmap +glXCreateGLXPixmapWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, Pixmap pixmap) { XMesaVisual xmvis = (XMesaVisual) config; XMesaBuffer xmbuf = XMesaCreatePixmapBuffer(xmvis, pixmap, 0); @@ -2259,14 +2311,14 @@ Fake_glXCreateGLXPixmapWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, Pixm } -static GLXContext -Fake_glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct) +GLXContext +glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct) { XMesaVisual xmvis = (XMesaVisual) config; - struct fake_glx_context *glxCtx; - struct fake_glx_context *shareCtx = (struct fake_glx_context *) share_list; + GLXContext glxCtx; + GLXContext shareCtx = share_list; - glxCtx = CALLOC_STRUCT(fake_glx_context); + glxCtx = CALLOC_STRUCT(__GLXcontextRec); if (!glxCtx) return 0; @@ -2280,25 +2332,23 @@ Fake_glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, int re return NULL; } - glxCtx->glxContext.isDirect = DEFAULT_DIRECT; - glxCtx->glxContext.currentDpy = dpy; - glxCtx->glxContext.xid = (XID) glxCtx; /* self pointer */ - - assert((void *) glxCtx == (void *) &(glxCtx->glxContext)); + glxCtx->isDirect = DEFAULT_DIRECT; + glxCtx->currentDpy = dpy; + glxCtx->xid = (XID) glxCtx; /* self pointer */ - return (GLXContext) glxCtx; + return glxCtx; } -static XVisualInfo * -Fake_glXGetVisualFromFBConfigSGIX(Display *dpy, GLXFBConfigSGIX config) +XVisualInfo * +glXGetVisualFromFBConfigSGIX(Display *dpy, GLXFBConfigSGIX config) { - return Fake_glXGetVisualFromFBConfig(dpy, config); + return glXGetVisualFromFBConfig(dpy, config); } -static GLXFBConfigSGIX -Fake_glXGetFBConfigFromVisualSGIX(Display *dpy, XVisualInfo *vis) +GLXFBConfigSGIX +glXGetFBConfigFromVisualSGIX(Display *dpy, XVisualInfo *vis) { XMesaVisual xmvis = find_glx_visual(dpy, vis); if (!xmvis) { @@ -2313,8 +2363,8 @@ Fake_glXGetFBConfigFromVisualSGIX(Display *dpy, XVisualInfo *vis) /*** GLX_SGIX_pbuffer ***/ -static GLXPbufferSGIX -Fake_glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config, +GLXPbufferSGIX +glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config, unsigned int width, unsigned int height, int *attribList) { @@ -2352,8 +2402,8 @@ Fake_glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config, } -static void -Fake_glXDestroyGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf) +void +glXDestroyGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf) { XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf); if (xmbuf) { @@ -2362,8 +2412,8 @@ Fake_glXDestroyGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf) } -static int -Fake_glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf, int attribute, unsigned int *value) +int +glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf, int attribute, unsigned int *value) { const XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf); @@ -2395,8 +2445,8 @@ Fake_glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf, int attribute, un } -static void -Fake_glXSelectEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long mask) +void +glXSelectEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long mask) { XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); if (xmbuf) { @@ -2406,8 +2456,8 @@ Fake_glXSelectEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long mask) } -static void -Fake_glXGetSelectedEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long *mask) +void +glXGetSelectedEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long *mask) { XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); if (xmbuf) { @@ -2422,8 +2472,8 @@ Fake_glXGetSelectedEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long * /*** GLX_SGI_cushion ***/ -static void -Fake_glXCushionSGI(Display *dpy, Window win, float cushion) +void +glXCushionSGI(Display *dpy, Window win, float cushion) { (void) dpy; (void) win; @@ -2434,8 +2484,8 @@ Fake_glXCushionSGI(Display *dpy, Window win, float cushion) /*** GLX_SGIX_video_resize ***/ -static int -Fake_glXBindChannelToWindowSGIX(Display *dpy, int screen, int channel , Window window) +int +glXBindChannelToWindowSGIX(Display *dpy, int screen, int channel , Window window) { (void) dpy; (void) screen; @@ -2444,8 +2494,8 @@ Fake_glXBindChannelToWindowSGIX(Display *dpy, int screen, int channel , Window w return 0; } -static int -Fake_glXChannelRectSGIX(Display *dpy, int screen, int channel, int x, int y, int w, int h) +int +glXChannelRectSGIX(Display *dpy, int screen, int channel, int x, int y, int w, int h) { (void) dpy; (void) screen; @@ -2457,8 +2507,8 @@ Fake_glXChannelRectSGIX(Display *dpy, int screen, int channel, int x, int y, int return 0; } -static int -Fake_glXQueryChannelRectSGIX(Display *dpy, int screen, int channel, int *x, int *y, int *w, int *h) +int +glXQueryChannelRectSGIX(Display *dpy, int screen, int channel, int *x, int *y, int *w, int *h) { (void) dpy; (void) screen; @@ -2470,8 +2520,8 @@ Fake_glXQueryChannelRectSGIX(Display *dpy, int screen, int channel, int *x, int return 0; } -static int -Fake_glXQueryChannelDeltasSGIX(Display *dpy, int screen, int channel, int *dx, int *dy, int *dw, int *dh) +int +glXQueryChannelDeltasSGIX(Display *dpy, int screen, int channel, int *dx, int *dy, int *dw, int *dh) { (void) dpy; (void) screen; @@ -2483,8 +2533,8 @@ Fake_glXQueryChannelDeltasSGIX(Display *dpy, int screen, int channel, int *dx, i return 0; } -static int -Fake_glXChannelRectSyncSGIX(Display *dpy, int screen, int channel, GLenum synctype) +int +glXChannelRectSyncSGIX(Display *dpy, int screen, int channel, GLenum synctype) { (void) dpy; (void) screen; @@ -2498,8 +2548,8 @@ Fake_glXChannelRectSyncSGIX(Display *dpy, int screen, int channel, GLenum syncty /*** GLX_SGIX_dmbuffer **/ #if defined(_DM_BUFFER_H_) -static Bool -Fake_glXAssociateDMPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuffer, DMparams *params, DMbuffer dmbuffer) +Bool +glXAssociateDMPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuffer, DMparams *params, DMbuffer dmbuffer) { (void) dpy; (void) pbuffer; @@ -2512,8 +2562,8 @@ Fake_glXAssociateDMPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuffer, DMparams *p /*** GLX_SGIX_swap_group ***/ -static void -Fake_glXJoinSwapGroupSGIX(Display *dpy, GLXDrawable drawable, GLXDrawable member) +void +glXJoinSwapGroupSGIX(Display *dpy, GLXDrawable drawable, GLXDrawable member) { (void) dpy; (void) drawable; @@ -2524,16 +2574,16 @@ Fake_glXJoinSwapGroupSGIX(Display *dpy, GLXDrawable drawable, GLXDrawable member /*** GLX_SGIX_swap_barrier ***/ -static void -Fake_glXBindSwapBarrierSGIX(Display *dpy, GLXDrawable drawable, int barrier) +void +glXBindSwapBarrierSGIX(Display *dpy, GLXDrawable drawable, int barrier) { (void) dpy; (void) drawable; (void) barrier; } -static Bool -Fake_glXQueryMaxSwapBarriersSGIX(Display *dpy, int screen, int *max) +Bool +glXQueryMaxSwapBarriersSGIX(Display *dpy, int screen, int *max) { (void) dpy; (void) screen; @@ -2545,8 +2595,8 @@ Fake_glXQueryMaxSwapBarriersSGIX(Display *dpy, int screen, int *max) /*** GLX_SUN_get_transparent_index ***/ -static Status -Fake_glXGetTransparentIndexSUN(Display *dpy, Window overlay, Window underlay, long *pTransparent) +Status +glXGetTransparentIndexSUN(Display *dpy, Window overlay, Window underlay, long *pTransparent) { (void) dpy; (void) overlay; @@ -2563,8 +2613,8 @@ Fake_glXGetTransparentIndexSUN(Display *dpy, Window overlay, Window underlay, lo * Release the depth, stencil, accum buffers attached to a GLXDrawable * (a window or pixmap) prior to destroying the GLXDrawable. */ -static Bool -Fake_glXReleaseBuffersMESA( Display *dpy, GLXDrawable d ) +Bool +glXReleaseBuffersMESA( Display *dpy, GLXDrawable d ) { XMesaBuffer b = XMesaFindBuffer(dpy, d); if (b) { @@ -2576,8 +2626,8 @@ Fake_glXReleaseBuffersMESA( Display *dpy, GLXDrawable d ) /*** GLX_EXT_texture_from_pixmap ***/ -static void -Fake_glXBindTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer, +void +glXBindTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer, const int *attrib_list) { XMesaBuffer b = XMesaFindBuffer(dpy, drawable); @@ -2585,162 +2635,10 @@ Fake_glXBindTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer, XMesaBindTexImage(dpy, b, buffer, attrib_list); } -static void -Fake_glXReleaseTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer) +void +glXReleaseTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer) { XMesaBuffer b = XMesaFindBuffer(dpy, drawable); if (b) XMesaReleaseTexImage(dpy, b, buffer); } - - - -/** - * Create a new GLX API dispatch table with its function pointers - * initialized to point to Mesa's "fake" GLX API functions. - * - * Note: there used to be a similar function - * (_real_GetGLXDispatchTable) that returns a new dispatch table with - * all pointers initalized to point to "real" GLX functions (which - * understand GLX wire protocol, etc). - */ -struct _glxapi_table * -_mesa_GetGLXDispatchTable(void) -{ - static struct _glxapi_table glx; - - /* be sure our dispatch table size <= libGL's table */ - { - GLuint size = sizeof(struct _glxapi_table) / sizeof(void *); - (void) size; - assert(_glxapi_get_dispatch_table_size() >= size); - } - - /* initialize the whole table to no-ops */ - _glxapi_set_no_op_table(&glx); - - /* now initialize the table with the functions I implement */ - glx.ChooseVisual = Fake_glXChooseVisual; - glx.CopyContext = Fake_glXCopyContext; - glx.CreateContext = Fake_glXCreateContext; - glx.CreateGLXPixmap = Fake_glXCreateGLXPixmap; - glx.DestroyContext = Fake_glXDestroyContext; - glx.DestroyGLXPixmap = Fake_glXDestroyGLXPixmap; - glx.GetConfig = Fake_glXGetConfig; - /*glx.GetCurrentContext = Fake_glXGetCurrentContext;*/ - /*glx.GetCurrentDrawable = Fake_glXGetCurrentDrawable;*/ - glx.IsDirect = Fake_glXIsDirect; - glx.MakeCurrent = Fake_glXMakeCurrent; - glx.QueryExtension = Fake_glXQueryExtension; - glx.QueryVersion = Fake_glXQueryVersion; - glx.SwapBuffers = Fake_glXSwapBuffers; - glx.UseXFont = Fake_glXUseXFont; - glx.WaitGL = Fake_glXWaitGL; - glx.WaitX = Fake_glXWaitX; - - /*** GLX_VERSION_1_1 ***/ - glx.GetClientString = Fake_glXGetClientString; - glx.QueryExtensionsString = Fake_glXQueryExtensionsString; - glx.QueryServerString = Fake_glXQueryServerString; - - /*** GLX_VERSION_1_2 ***/ - /*glx.GetCurrentDisplay = Fake_glXGetCurrentDisplay;*/ - - /*** GLX_VERSION_1_3 ***/ - glx.ChooseFBConfig = Fake_glXChooseFBConfig; - glx.CreateNewContext = Fake_glXCreateNewContext; - glx.CreatePbuffer = Fake_glXCreatePbuffer; - glx.CreatePixmap = Fake_glXCreatePixmap; - glx.CreateWindow = Fake_glXCreateWindow; - glx.DestroyPbuffer = Fake_glXDestroyPbuffer; - glx.DestroyPixmap = Fake_glXDestroyPixmap; - glx.DestroyWindow = Fake_glXDestroyWindow; - /*glx.GetCurrentReadDrawable = Fake_glXGetCurrentReadDrawable;*/ - glx.GetFBConfigAttrib = Fake_glXGetFBConfigAttrib; - glx.GetFBConfigs = Fake_glXGetFBConfigs; - glx.GetSelectedEvent = Fake_glXGetSelectedEvent; - glx.GetVisualFromFBConfig = Fake_glXGetVisualFromFBConfig; - glx.MakeContextCurrent = Fake_glXMakeContextCurrent; - glx.QueryContext = Fake_glXQueryContext; - glx.QueryDrawable = Fake_glXQueryDrawable; - glx.SelectEvent = Fake_glXSelectEvent; - - /*** GLX_SGI_swap_control ***/ - glx.SwapIntervalSGI = Fake_glXSwapIntervalSGI; - - /*** GLX_SGI_video_sync ***/ - glx.GetVideoSyncSGI = Fake_glXGetVideoSyncSGI; - glx.WaitVideoSyncSGI = Fake_glXWaitVideoSyncSGI; - - /*** GLX_SGI_make_current_read ***/ - glx.MakeCurrentReadSGI = Fake_glXMakeCurrentReadSGI; - /*glx.GetCurrentReadDrawableSGI = Fake_glXGetCurrentReadDrawableSGI;*/ - -/*** GLX_SGIX_video_source ***/ -#if defined(_VL_H) - glx.CreateGLXVideoSourceSGIX = Fake_glXCreateGLXVideoSourceSGIX; - glx.DestroyGLXVideoSourceSGIX = Fake_glXDestroyGLXVideoSourceSGIX; -#endif - - /*** GLX_EXT_import_context ***/ - glx.FreeContextEXT = Fake_glXFreeContextEXT; - glx.GetContextIDEXT = Fake_glXGetContextIDEXT; - /*glx.GetCurrentDisplayEXT = Fake_glXGetCurrentDisplayEXT;*/ - glx.ImportContextEXT = Fake_glXImportContextEXT; - glx.QueryContextInfoEXT = Fake_glXQueryContextInfoEXT; - - /*** GLX_SGIX_fbconfig ***/ - glx.GetFBConfigAttribSGIX = Fake_glXGetFBConfigAttribSGIX; - glx.ChooseFBConfigSGIX = Fake_glXChooseFBConfigSGIX; - glx.CreateGLXPixmapWithConfigSGIX = Fake_glXCreateGLXPixmapWithConfigSGIX; - glx.CreateContextWithConfigSGIX = Fake_glXCreateContextWithConfigSGIX; - glx.GetVisualFromFBConfigSGIX = Fake_glXGetVisualFromFBConfigSGIX; - glx.GetFBConfigFromVisualSGIX = Fake_glXGetFBConfigFromVisualSGIX; - - /*** GLX_SGIX_pbuffer ***/ - glx.CreateGLXPbufferSGIX = Fake_glXCreateGLXPbufferSGIX; - glx.DestroyGLXPbufferSGIX = Fake_glXDestroyGLXPbufferSGIX; - glx.QueryGLXPbufferSGIX = Fake_glXQueryGLXPbufferSGIX; - glx.SelectEventSGIX = Fake_glXSelectEventSGIX; - glx.GetSelectedEventSGIX = Fake_glXGetSelectedEventSGIX; - - /*** GLX_SGI_cushion ***/ - glx.CushionSGI = Fake_glXCushionSGI; - - /*** GLX_SGIX_video_resize ***/ - glx.BindChannelToWindowSGIX = Fake_glXBindChannelToWindowSGIX; - glx.ChannelRectSGIX = Fake_glXChannelRectSGIX; - glx.QueryChannelRectSGIX = Fake_glXQueryChannelRectSGIX; - glx.QueryChannelDeltasSGIX = Fake_glXQueryChannelDeltasSGIX; - glx.ChannelRectSyncSGIX = Fake_glXChannelRectSyncSGIX; - - /*** GLX_SGIX_dmbuffer **/ -#if defined(_DM_BUFFER_H_) - glx.AssociateDMPbufferSGIX = NULL; -#endif - - /*** GLX_SGIX_swap_group ***/ - glx.JoinSwapGroupSGIX = Fake_glXJoinSwapGroupSGIX; - - /*** GLX_SGIX_swap_barrier ***/ - glx.BindSwapBarrierSGIX = Fake_glXBindSwapBarrierSGIX; - glx.QueryMaxSwapBarriersSGIX = Fake_glXQueryMaxSwapBarriersSGIX; - - /*** GLX_SUN_get_transparent_index ***/ - glx.GetTransparentIndexSUN = Fake_glXGetTransparentIndexSUN; - - /*** GLX_MESA_copy_sub_buffer ***/ - glx.CopySubBufferMESA = Fake_glXCopySubBufferMESA; - - /*** GLX_MESA_release_buffers ***/ - glx.ReleaseBuffersMESA = Fake_glXReleaseBuffersMESA; - - /*** GLX_MESA_pixmap_colormap ***/ - glx.CreateGLXPixmapMESA = Fake_glXCreateGLXPixmapMESA; - - /*** GLX_EXT_texture_from_pixmap ***/ - glx.BindTexImageEXT = Fake_glXBindTexImageEXT; - glx.ReleaseTexImageEXT = Fake_glXReleaseTexImageEXT; - - return &glx; -} diff --git a/src/gallium/state_trackers/glx/xlib/glx_getproc.c b/src/gallium/state_trackers/glx/xlib/glx_getproc.c new file mode 100644 index 0000000000..ca7d88c922 --- /dev/null +++ b/src/gallium/state_trackers/glx/xlib/glx_getproc.c @@ -0,0 +1,214 @@ +/* + * Mesa 3-D graphics library + * Version: 7.6 + * + * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. + * Copyright (C) 2009 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, 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 + * BRIAN PAUL 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. + */ + + +/** + * glXGetProcAddress() + */ + + +#define GLX_GLXEXT_PROTOTYPES + +#include <string.h> +#include "GL/glx.h" +#include "glapi/glapi.h" + + +struct name_address_pair { + const char *Name; + __GLXextFuncPtr Address; +}; + + +static struct name_address_pair GLX_functions[] = { + /*** GLX_VERSION_1_0 ***/ + { "glXChooseVisual", (__GLXextFuncPtr) glXChooseVisual }, + { "glXCopyContext", (__GLXextFuncPtr) glXCopyContext }, + { "glXCreateContext", (__GLXextFuncPtr) glXCreateContext }, + { "glXCreateGLXPixmap", (__GLXextFuncPtr) glXCreateGLXPixmap }, + { "glXDestroyContext", (__GLXextFuncPtr) glXDestroyContext }, + { "glXDestroyGLXPixmap", (__GLXextFuncPtr) glXDestroyGLXPixmap }, + { "glXGetConfig", (__GLXextFuncPtr) glXGetConfig }, + { "glXGetCurrentContext", (__GLXextFuncPtr) glXGetCurrentContext }, + { "glXGetCurrentDrawable", (__GLXextFuncPtr) glXGetCurrentDrawable }, + { "glXIsDirect", (__GLXextFuncPtr) glXIsDirect }, + { "glXMakeCurrent", (__GLXextFuncPtr) glXMakeCurrent }, + { "glXQueryExtension", (__GLXextFuncPtr) glXQueryExtension }, + { "glXQueryVersion", (__GLXextFuncPtr) glXQueryVersion }, + { "glXSwapBuffers", (__GLXextFuncPtr) glXSwapBuffers }, + { "glXUseXFont", (__GLXextFuncPtr) glXUseXFont }, + { "glXWaitGL", (__GLXextFuncPtr) glXWaitGL }, + { "glXWaitX", (__GLXextFuncPtr) glXWaitX }, + + /*** GLX_VERSION_1_1 ***/ + { "glXGetClientString", (__GLXextFuncPtr) glXGetClientString }, + { "glXQueryExtensionsString", (__GLXextFuncPtr) glXQueryExtensionsString }, + { "glXQueryServerString", (__GLXextFuncPtr) glXQueryServerString }, + + /*** GLX_VERSION_1_2 ***/ + { "glXGetCurrentDisplay", (__GLXextFuncPtr) glXGetCurrentDisplay }, + + /*** GLX_VERSION_1_3 ***/ + { "glXChooseFBConfig", (__GLXextFuncPtr) glXChooseFBConfig }, + { "glXCreateNewContext", (__GLXextFuncPtr) glXCreateNewContext }, + { "glXCreatePbuffer", (__GLXextFuncPtr) glXCreatePbuffer }, + { "glXCreatePixmap", (__GLXextFuncPtr) glXCreatePixmap }, + { "glXCreateWindow", (__GLXextFuncPtr) glXCreateWindow }, + { "glXDestroyPbuffer", (__GLXextFuncPtr) glXDestroyPbuffer }, + { "glXDestroyPixmap", (__GLXextFuncPtr) glXDestroyPixmap }, + { "glXDestroyWindow", (__GLXextFuncPtr) glXDestroyWindow }, + { "glXGetCurrentReadDrawable", (__GLXextFuncPtr) glXGetCurrentReadDrawable }, + { "glXGetFBConfigAttrib", (__GLXextFuncPtr) glXGetFBConfigAttrib }, + { "glXGetFBConfigs", (__GLXextFuncPtr) glXGetFBConfigs }, + { "glXGetSelectedEvent", (__GLXextFuncPtr) glXGetSelectedEvent }, + { "glXGetVisualFromFBConfig", (__GLXextFuncPtr) glXGetVisualFromFBConfig }, + { "glXMakeContextCurrent", (__GLXextFuncPtr) glXMakeContextCurrent }, + { "glXQueryContext", (__GLXextFuncPtr) glXQueryContext }, + { "glXQueryDrawable", (__GLXextFuncPtr) glXQueryDrawable }, + { "glXSelectEvent", (__GLXextFuncPtr) glXSelectEvent }, + + /*** GLX_VERSION_1_4 ***/ + { "glXGetProcAddress", (__GLXextFuncPtr) glXGetProcAddress }, + + /*** GLX_SGI_swap_control ***/ + { "glXSwapIntervalSGI", (__GLXextFuncPtr) glXSwapIntervalSGI }, + + /*** GLX_SGI_video_sync ***/ + { "glXGetVideoSyncSGI", (__GLXextFuncPtr) glXGetVideoSyncSGI }, + { "glXWaitVideoSyncSGI", (__GLXextFuncPtr) glXWaitVideoSyncSGI }, + + /*** GLX_SGI_make_current_read ***/ + { "glXMakeCurrentReadSGI", (__GLXextFuncPtr) glXMakeCurrentReadSGI }, + { "glXGetCurrentReadDrawableSGI", (__GLXextFuncPtr) glXGetCurrentReadDrawableSGI }, + + /*** GLX_SGIX_video_source ***/ +#if defined(_VL_H) + { "glXCreateGLXVideoSourceSGIX", (__GLXextFuncPtr) glXCreateGLXVideoSourceSGIX }, + { "glXDestroyGLXVideoSourceSGIX", (__GLXextFuncPtr) glXDestroyGLXVideoSourceSGIX }, +#endif + + /*** GLX_EXT_import_context ***/ + { "glXFreeContextEXT", (__GLXextFuncPtr) glXFreeContextEXT }, + { "glXGetContextIDEXT", (__GLXextFuncPtr) glXGetContextIDEXT }, + { "glXGetCurrentDisplayEXT", (__GLXextFuncPtr) glXGetCurrentDisplayEXT }, + { "glXImportContextEXT", (__GLXextFuncPtr) glXImportContextEXT }, + { "glXQueryContextInfoEXT", (__GLXextFuncPtr) glXQueryContextInfoEXT }, + + /*** GLX_SGIX_fbconfig ***/ + { "glXGetFBConfigAttribSGIX", (__GLXextFuncPtr) glXGetFBConfigAttribSGIX }, + { "glXChooseFBConfigSGIX", (__GLXextFuncPtr) glXChooseFBConfigSGIX }, + { "glXCreateGLXPixmapWithConfigSGIX", (__GLXextFuncPtr) glXCreateGLXPixmapWithConfigSGIX }, + { "glXCreateContextWithConfigSGIX", (__GLXextFuncPtr) glXCreateContextWithConfigSGIX }, + { "glXGetVisualFromFBConfigSGIX", (__GLXextFuncPtr) glXGetVisualFromFBConfigSGIX }, + { "glXGetFBConfigFromVisualSGIX", (__GLXextFuncPtr) glXGetFBConfigFromVisualSGIX }, + + /*** GLX_SGIX_pbuffer ***/ + { "glXCreateGLXPbufferSGIX", (__GLXextFuncPtr) glXCreateGLXPbufferSGIX }, + { "glXDestroyGLXPbufferSGIX", (__GLXextFuncPtr) glXDestroyGLXPbufferSGIX }, + { "glXQueryGLXPbufferSGIX", (__GLXextFuncPtr) glXQueryGLXPbufferSGIX }, + { "glXSelectEventSGIX", (__GLXextFuncPtr) glXSelectEventSGIX }, + { "glXGetSelectedEventSGIX", (__GLXextFuncPtr) glXGetSelectedEventSGIX }, + + /*** GLX_SGI_cushion ***/ + { "glXCushionSGI", (__GLXextFuncPtr) glXCushionSGI }, + + /*** GLX_SGIX_video_resize ***/ + { "glXBindChannelToWindowSGIX", (__GLXextFuncPtr) glXBindChannelToWindowSGIX }, + { "glXChannelRectSGIX", (__GLXextFuncPtr) glXChannelRectSGIX }, + { "glXQueryChannelRectSGIX", (__GLXextFuncPtr) glXQueryChannelRectSGIX }, + { "glXQueryChannelDeltasSGIX", (__GLXextFuncPtr) glXQueryChannelDeltasSGIX }, + { "glXChannelRectSyncSGIX", (__GLXextFuncPtr) glXChannelRectSyncSGIX }, + + /*** GLX_SGIX_dmbuffer **/ +#if defined(_DM_BUFFER_H_) + { "glXAssociateDMPbufferSGIX", (__GLXextFuncPtr) glXAssociateDMPbufferSGIX }, +#endif + + /*** GLX_SGIX_swap_group ***/ + { "glXJoinSwapGroupSGIX", (__GLXextFuncPtr) glXJoinSwapGroupSGIX }, + + /*** GLX_SGIX_swap_barrier ***/ + { "glXBindSwapBarrierSGIX", (__GLXextFuncPtr) glXBindSwapBarrierSGIX }, + { "glXQueryMaxSwapBarriersSGIX", (__GLXextFuncPtr) glXQueryMaxSwapBarriersSGIX }, + + /*** GLX_SUN_get_transparent_index ***/ + { "glXGetTransparentIndexSUN", (__GLXextFuncPtr) glXGetTransparentIndexSUN }, + + /*** GLX_MESA_copy_sub_buffer ***/ + { "glXCopySubBufferMESA", (__GLXextFuncPtr) glXCopySubBufferMESA }, + + /*** GLX_MESA_pixmap_colormap ***/ + { "glXCreateGLXPixmapMESA", (__GLXextFuncPtr) glXCreateGLXPixmapMESA }, + + /*** GLX_MESA_release_buffers ***/ + { "glXReleaseBuffersMESA", (__GLXextFuncPtr) glXReleaseBuffersMESA }, + + /*** GLX_ARB_get_proc_address ***/ + { "glXGetProcAddressARB", (__GLXextFuncPtr) glXGetProcAddressARB }, + + /*** GLX_EXT_texture_from_pixmap ***/ + { "glXBindTexImageEXT", (__GLXextFuncPtr) glXBindTexImageEXT }, + { "glXReleaseTexImageEXT", (__GLXextFuncPtr) glXReleaseTexImageEXT }, + + { NULL, NULL } /* end of list */ +}; + + + +/** + * Return address of named glX function, or NULL if not found. + */ +static __GLXextFuncPtr +_glxapi_get_proc_address(const char *funcName) +{ + GLuint i; + for (i = 0; GLX_functions[i].Name; i++) { + if (strcmp(GLX_functions[i].Name, funcName) == 0) + return GLX_functions[i].Address; + } + return NULL; +} + + +__GLXextFuncPtr +glXGetProcAddressARB(const GLubyte *procName) +{ + __GLXextFuncPtr f; + + f = _glxapi_get_proc_address((const char *) procName); + if (f) { + return f; + } + + f = (__GLXextFuncPtr) _glapi_get_proc_address((const char *) procName); + return f; +} + + +/* GLX 1.4 */ +void (*glXGetProcAddress(const GLubyte *procName))() +{ + return glXGetProcAddressARB(procName); +} diff --git a/src/gallium/state_trackers/glx/xlib/fakeglx_fonts.c b/src/gallium/state_trackers/glx/xlib/glx_usefont.c index e359046756..acc64df62b 100644 --- a/src/gallium/state_trackers/glx/xlib/fakeglx_fonts.c +++ b/src/gallium/state_trackers/glx/xlib/glx_usefont.c @@ -1,9 +1,10 @@ - /* * Mesa 3-D graphics library - * Version: 3.5 + * Version: 7.6 * - * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. + * Copyright (C) 1995 Thorsten.Ohl @ Physik.TH-Darmstadt.de + * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. + * Copyright (C) 2009 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"), @@ -24,13 +25,13 @@ */ -/* xfonts.c -- glXUseXFont() for Mesa written by - * Copyright (C) 1995 Thorsten.Ohl @ Physik.TH-Darmstadt.de +/** + * Fake implementation of glXUseXFont(). */ -#include "context.h" -#include "imports.h" -#include "fakeglx.h" + +#include "main/context.h" +#include "main/imports.h" #include <GL/glx.h> @@ -210,7 +211,7 @@ isvalid(XFontStruct * fs, unsigned int which) void -Fake_glXUseXFont(Font font, int first, int count, int listbase) +glXUseXFont(Font font, int first, int count, int listbase) { Display *dpy; Window win; @@ -228,7 +229,8 @@ Fake_glXUseXFont(Font font, int first, int count, int listbase) dpy = glXGetCurrentDisplay(); if (!dpy) return; /* I guess glXMakeCurrent wasn't called */ - win = RootWindow(dpy, DefaultScreen(dpy)); + i = DefaultScreen(dpy); + win = RootWindow(dpy, i); fs = XQueryFont(dpy, font); if (!fs) { diff --git a/src/gallium/state_trackers/glx/xlib/glxapi.c b/src/gallium/state_trackers/glx/xlib/glxapi.c deleted file mode 100644 index c2cb34d7cf..0000000000 --- a/src/gallium/state_trackers/glx/xlib/glxapi.c +++ /dev/null @@ -1,1254 +0,0 @@ -/* - * Mesa 3-D graphics library - * Version: 7.1 - * - * Copyright (C) 1999-2007 Brian Paul 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, 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 - * BRIAN PAUL 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 GLX API dispatcher. Calls to the glX* functions are - * either routed to the real GLX encoders or to Mesa's pseudo-GLX functions. - * See the glxapi.h file for more details. - */ - - -#include <assert.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include "glapi/glapi.h" -#include "glxapi.h" -#include "fakeglx.h" -#include "pipe/p_thread.h" - - -#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 303 -# define PUBLIC __attribute__((visibility("default"))) -# define USED __attribute__((used)) -#else -# define PUBLIC -# define USED -#endif - - -struct display_dispatch { - Display *Dpy; - struct _glxapi_table *Table; - struct display_dispatch *Next; -}; - -static struct display_dispatch *DispatchList = NULL; - - -/* Display -> Dispatch caching */ -static Display *prevDisplay = NULL; -static struct _glxapi_table *prevTable = NULL; - - -static struct _glxapi_table * -get_dispatch(Display *dpy) -{ - if (!dpy) - return NULL; - - /* search list of display/dispatch pairs for this display */ - { - const struct display_dispatch *d = DispatchList; - while (d) { - if (d->Dpy == dpy) { - prevDisplay = dpy; - prevTable = d->Table; - return d->Table; /* done! */ - } - d = d->Next; - } - } - - /* A new display, determine if we should use real GLX - * or Mesa's pseudo-GLX. - */ - { - struct _glxapi_table *t = _mesa_GetGLXDispatchTable(); - - if (t) { - struct display_dispatch *d; - d = (struct display_dispatch *) malloc(sizeof(struct display_dispatch)); - if (d) { - d->Dpy = dpy; - d->Table = t; - /* insert at head of list */ - d->Next = DispatchList; - DispatchList = d; - /* update cache */ - prevDisplay = dpy; - prevTable = t; - return t; - } - } - } - - /* If we get here that means we can't use real GLX on this display - * and the Mesa pseudo-GLX software renderer wasn't compiled in. - * Or, we ran out of memory! - */ - return NULL; -} - - -/* Don't use the GET_DISPATCH defined in glthread.h */ -#undef GET_DISPATCH - -#define GET_DISPATCH(DPY, TABLE) \ - if (DPY == prevDisplay) { \ - TABLE = prevTable; \ - } \ - else if (!DPY) { \ - TABLE = NULL; \ - } \ - else { \ - TABLE = get_dispatch(DPY); \ - } - - - - -/** - * GLX API current context. - */ -pipe_tsd ContextTSD; - - -static void -SetCurrentContext(GLXContext c) -{ - pipe_tsd_set(&ContextTSD, c); -} - - -/* - * GLX API entrypoints - */ - -/*** GLX_VERSION_1_0 ***/ - -XVisualInfo PUBLIC * -glXChooseVisual(Display *dpy, int screen, int *list) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return NULL; - return (t->ChooseVisual)(dpy, screen, list); -} - - -void PUBLIC -glXCopyContext(Display *dpy, GLXContext src, GLXContext dst, unsigned long mask) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return; - (t->CopyContext)(dpy, src, dst, mask); -} - - -GLXContext PUBLIC -glXCreateContext(Display *dpy, XVisualInfo *visinfo, GLXContext shareList, Bool direct) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return 0; - return (t->CreateContext)(dpy, visinfo, shareList, direct); -} - - -GLXPixmap PUBLIC -glXCreateGLXPixmap(Display *dpy, XVisualInfo *visinfo, Pixmap pixmap) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return 0; - return (t->CreateGLXPixmap)(dpy, visinfo, pixmap); -} - - -void PUBLIC -glXDestroyContext(Display *dpy, GLXContext ctx) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return; - if (glXGetCurrentContext() == ctx) - SetCurrentContext(NULL); - (t->DestroyContext)(dpy, ctx); -} - - -void PUBLIC -glXDestroyGLXPixmap(Display *dpy, GLXPixmap pixmap) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return; - (t->DestroyGLXPixmap)(dpy, pixmap); -} - - -int PUBLIC -glXGetConfig(Display *dpy, XVisualInfo *visinfo, int attrib, int *value) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return GLX_NO_EXTENSION; - return (t->GetConfig)(dpy, visinfo, attrib, value); -} - - -GLXContext PUBLIC -glXGetCurrentContext(void) -{ - return (GLXContext) pipe_tsd_get(&ContextTSD); -} - - -GLXDrawable PUBLIC -glXGetCurrentDrawable(void) -{ - __GLXcontext *gc = (__GLXcontext *) glXGetCurrentContext(); - return gc ? gc->currentDrawable : 0; -} - - -Bool PUBLIC -glXIsDirect(Display *dpy, GLXContext ctx) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return False; - return (t->IsDirect)(dpy, ctx); -} - - -Bool PUBLIC -glXMakeCurrent(Display *dpy, GLXDrawable drawable, GLXContext ctx) -{ - Bool b; - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) { - return False; - } - b = (*t->MakeCurrent)(dpy, drawable, ctx); - if (b) { - SetCurrentContext(ctx); - } - return b; -} - - -Bool PUBLIC -glXQueryExtension(Display *dpy, int *errorb, int *event) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return False; - return (t->QueryExtension)(dpy, errorb, event); -} - - -Bool PUBLIC -glXQueryVersion(Display *dpy, int *maj, int *min) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return False; - return (t->QueryVersion)(dpy, maj, min); -} - - -void PUBLIC -glXSwapBuffers(Display *dpy, GLXDrawable drawable) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return; - (t->SwapBuffers)(dpy, drawable); -} - - -void PUBLIC -glXUseXFont(Font font, int first, int count, int listBase) -{ - struct _glxapi_table *t; - Display *dpy = glXGetCurrentDisplay(); - GET_DISPATCH(dpy, t); - if (!t) - return; - (t->UseXFont)(font, first, count, listBase); -} - - -void PUBLIC -glXWaitGL(void) -{ - struct _glxapi_table *t; - Display *dpy = glXGetCurrentDisplay(); - GET_DISPATCH(dpy, t); - if (!t) - return; - (t->WaitGL)(); -} - - -void PUBLIC -glXWaitX(void) -{ - struct _glxapi_table *t; - Display *dpy = glXGetCurrentDisplay(); - GET_DISPATCH(dpy, t); - if (!t) - return; - (t->WaitX)(); -} - - - -/*** GLX_VERSION_1_1 ***/ - -const char PUBLIC * -glXGetClientString(Display *dpy, int name) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return NULL; - return (t->GetClientString)(dpy, name); -} - - -const char PUBLIC * -glXQueryExtensionsString(Display *dpy, int screen) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return NULL; - return (t->QueryExtensionsString)(dpy, screen); -} - - -const char PUBLIC * -glXQueryServerString(Display *dpy, int screen, int name) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return NULL; - return (t->QueryServerString)(dpy, screen, name); -} - - -/*** GLX_VERSION_1_2 ***/ - -Display PUBLIC * -glXGetCurrentDisplay(void) -{ - /* Same code as in libGL's glxext.c */ - __GLXcontext *gc = (__GLXcontext *) glXGetCurrentContext(); - if (NULL == gc) return NULL; - return gc->currentDpy; -} - - - -/*** GLX_VERSION_1_3 ***/ - -GLXFBConfig PUBLIC * -glXChooseFBConfig(Display *dpy, int screen, const int *attribList, int *nitems) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return 0; - return (t->ChooseFBConfig)(dpy, screen, attribList, nitems); -} - - -GLXContext PUBLIC -glXCreateNewContext(Display *dpy, GLXFBConfig config, int renderType, GLXContext shareList, Bool direct) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return 0; - return (t->CreateNewContext)(dpy, config, renderType, shareList, direct); -} - - -GLXPbuffer PUBLIC -glXCreatePbuffer(Display *dpy, GLXFBConfig config, const int *attribList) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return 0; - return (t->CreatePbuffer)(dpy, config, attribList); -} - - -GLXPixmap PUBLIC -glXCreatePixmap(Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attribList) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return 0; - return (t->CreatePixmap)(dpy, config, pixmap, attribList); -} - - -GLXWindow PUBLIC -glXCreateWindow(Display *dpy, GLXFBConfig config, Window win, const int *attribList) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return 0; - return (t->CreateWindow)(dpy, config, win, attribList); -} - - -void PUBLIC -glXDestroyPbuffer(Display *dpy, GLXPbuffer pbuf) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return; - (t->DestroyPbuffer)(dpy, pbuf); -} - - -void PUBLIC -glXDestroyPixmap(Display *dpy, GLXPixmap pixmap) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return; - (t->DestroyPixmap)(dpy, pixmap); -} - - -void PUBLIC -glXDestroyWindow(Display *dpy, GLXWindow window) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return; - (t->DestroyWindow)(dpy, window); -} - - -GLXDrawable PUBLIC -glXGetCurrentReadDrawable(void) -{ - __GLXcontext *gc = (__GLXcontext *) glXGetCurrentContext(); - return gc ? gc->currentReadable : 0; -} - - -int PUBLIC -glXGetFBConfigAttrib(Display *dpy, GLXFBConfig config, int attribute, int *value) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return GLX_NO_EXTENSION; - return (t->GetFBConfigAttrib)(dpy, config, attribute, value); -} - - -GLXFBConfig PUBLIC * -glXGetFBConfigs(Display *dpy, int screen, int *nelements) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return 0; - return (t->GetFBConfigs)(dpy, screen, nelements); -} - -void PUBLIC -glXGetSelectedEvent(Display *dpy, GLXDrawable drawable, unsigned long *mask) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return; - (t->GetSelectedEvent)(dpy, drawable, mask); -} - - -XVisualInfo PUBLIC * -glXGetVisualFromFBConfig(Display *dpy, GLXFBConfig config) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return NULL; - return (t->GetVisualFromFBConfig)(dpy, config); -} - - -Bool PUBLIC -glXMakeContextCurrent(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx) -{ - Bool b; - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return False; - b = (t->MakeContextCurrent)(dpy, draw, read, ctx); - if (b) { - SetCurrentContext(ctx); - } - return b; -} - - -int PUBLIC -glXQueryContext(Display *dpy, GLXContext ctx, int attribute, int *value) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - assert(t); - if (!t) - return 0; /* XXX correct? */ - return (t->QueryContext)(dpy, ctx, attribute, value); -} - - -void PUBLIC -glXQueryDrawable(Display *dpy, GLXDrawable draw, int attribute, unsigned int *value) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return; - (t->QueryDrawable)(dpy, draw, attribute, value); -} - - -void PUBLIC -glXSelectEvent(Display *dpy, GLXDrawable drawable, unsigned long mask) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return; - (t->SelectEvent)(dpy, drawable, mask); -} - - - -/*** GLX_SGI_swap_control ***/ - -int PUBLIC -glXSwapIntervalSGI(int interval) -{ - struct _glxapi_table *t; - Display *dpy = glXGetCurrentDisplay(); - GET_DISPATCH(dpy, t); - if (!t) - return 0; - return (t->SwapIntervalSGI)(interval); -} - - - -/*** GLX_SGI_video_sync ***/ - -int PUBLIC -glXGetVideoSyncSGI(unsigned int *count) -{ - struct _glxapi_table *t; - Display *dpy = glXGetCurrentDisplay(); - GET_DISPATCH(dpy, t); - if (!t || !glXGetCurrentContext()) - return GLX_BAD_CONTEXT; - return (t->GetVideoSyncSGI)(count); -} - -int PUBLIC -glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count) -{ - struct _glxapi_table *t; - Display *dpy = glXGetCurrentDisplay(); - GET_DISPATCH(dpy, t); - if (!t || !glXGetCurrentContext()) - return GLX_BAD_CONTEXT; - return (t->WaitVideoSyncSGI)(divisor, remainder, count); -} - - - -/*** GLX_SGI_make_current_read ***/ - -Bool PUBLIC -glXMakeCurrentReadSGI(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return False; - return (t->MakeCurrentReadSGI)(dpy, draw, read, ctx); -} - -GLXDrawable PUBLIC -glXGetCurrentReadDrawableSGI(void) -{ - return glXGetCurrentReadDrawable(); -} - - -#if defined(_VL_H) - -GLXVideoSourceSGIX PUBLIC -glXCreateGLXVideoSourceSGIX(Display *dpy, int screen, VLServer server, VLPath path, int nodeClass, VLNode drainNode) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return 0; - return (t->CreateGLXVideoSourceSGIX)(dpy, screen, server, path, nodeClass, drainNode); -} - -void PUBLIC -glXDestroyGLXVideoSourceSGIX(Display *dpy, GLXVideoSourceSGIX src) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return 0; - return (t->DestroyGLXVideoSourceSGIX)(dpy, src); -} - -#endif - - -/*** GLX_EXT_import_context ***/ - -void PUBLIC -glXFreeContextEXT(Display *dpy, GLXContext context) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return; - (t->FreeContextEXT)(dpy, context); -} - -GLXContextID PUBLIC -glXGetContextIDEXT(const GLXContext context) -{ - return ((__GLXcontext *) context)->xid; -} - -Display PUBLIC * -glXGetCurrentDisplayEXT(void) -{ - return glXGetCurrentDisplay(); -} - -GLXContext PUBLIC -glXImportContextEXT(Display *dpy, GLXContextID contextID) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return 0; - return (t->ImportContextEXT)(dpy, contextID); -} - -int PUBLIC -glXQueryContextInfoEXT(Display *dpy, GLXContext context, int attribute,int *value) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return 0; /* XXX ok? */ - return (t->QueryContextInfoEXT)(dpy, context, attribute, value); -} - - - -/*** GLX_SGIX_fbconfig ***/ - -int PUBLIC -glXGetFBConfigAttribSGIX(Display *dpy, GLXFBConfigSGIX config, int attribute, int *value) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return 0; - return (t->GetFBConfigAttribSGIX)(dpy, config, attribute, value); -} - -GLXFBConfigSGIX PUBLIC * -glXChooseFBConfigSGIX(Display *dpy, int screen, int *attrib_list, int *nelements) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return 0; - return (t->ChooseFBConfigSGIX)(dpy, screen, attrib_list, nelements); -} - -GLXPixmap PUBLIC -glXCreateGLXPixmapWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, Pixmap pixmap) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return 0; - return (t->CreateGLXPixmapWithConfigSGIX)(dpy, config, pixmap); -} - -GLXContext PUBLIC -glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return 0; - return (t->CreateContextWithConfigSGIX)(dpy, config, render_type, share_list, direct); -} - -XVisualInfo PUBLIC * -glXGetVisualFromFBConfigSGIX(Display *dpy, GLXFBConfigSGIX config) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return 0; - return (t->GetVisualFromFBConfigSGIX)(dpy, config); -} - -GLXFBConfigSGIX PUBLIC -glXGetFBConfigFromVisualSGIX(Display *dpy, XVisualInfo *vis) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return 0; - return (t->GetFBConfigFromVisualSGIX)(dpy, vis); -} - - - -/*** GLX_SGIX_pbuffer ***/ - -GLXPbufferSGIX PUBLIC -glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config, unsigned int width, unsigned int height, int *attrib_list) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return 0; - return (t->CreateGLXPbufferSGIX)(dpy, config, width, height, attrib_list); -} - -void PUBLIC -glXDestroyGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return; - (t->DestroyGLXPbufferSGIX)(dpy, pbuf); -} - -int PUBLIC -glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf, int attribute, unsigned int *value) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return 0; - return (t->QueryGLXPbufferSGIX)(dpy, pbuf, attribute, value); -} - -void PUBLIC -glXSelectEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long mask) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return; - (t->SelectEventSGIX)(dpy, drawable, mask); -} - -void PUBLIC -glXGetSelectedEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long *mask) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return; - (t->GetSelectedEventSGIX)(dpy, drawable, mask); -} - - - -/*** GLX_SGI_cushion ***/ - -void PUBLIC -glXCushionSGI(Display *dpy, Window win, float cushion) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return; - (t->CushionSGI)(dpy, win, cushion); -} - - - -/*** GLX_SGIX_video_resize ***/ - -int PUBLIC -glXBindChannelToWindowSGIX(Display *dpy, int screen, int channel , Window window) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return 0; - return (t->BindChannelToWindowSGIX)(dpy, screen, channel, window); -} - -int PUBLIC -glXChannelRectSGIX(Display *dpy, int screen, int channel, int x, int y, int w, int h) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return 0; - return (t->ChannelRectSGIX)(dpy, screen, channel, x, y, w, h); -} - -int PUBLIC -glXQueryChannelRectSGIX(Display *dpy, int screen, int channel, int *x, int *y, int *w, int *h) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return 0; - return (t->QueryChannelRectSGIX)(dpy, screen, channel, x, y, w, h); -} - -int PUBLIC -glXQueryChannelDeltasSGIX(Display *dpy, int screen, int channel, int *dx, int *dy, int *dw, int *dh) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return 0; - return (t->QueryChannelDeltasSGIX)(dpy, screen, channel, dx, dy, dw, dh); -} - -int PUBLIC -glXChannelRectSyncSGIX(Display *dpy, int screen, int channel, GLenum synctype) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return 0; - return (t->ChannelRectSyncSGIX)(dpy, screen, channel, synctype); -} - - - -#if defined(_DM_BUFFER_H_) - -Bool PUBLIC -glXAssociateDMPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuffer, DMparams *params, DMbuffer dmbuffer) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return False; - return (t->AssociateDMPbufferSGIX)(dpy, pbuffer, params, dmbuffer); -} - -#endif - - -/*** GLX_SGIX_swap_group ***/ - -void PUBLIC -glXJoinSwapGroupSGIX(Display *dpy, GLXDrawable drawable, GLXDrawable member) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return; - (*t->JoinSwapGroupSGIX)(dpy, drawable, member); -} - - -/*** GLX_SGIX_swap_barrier ***/ - -void PUBLIC -glXBindSwapBarrierSGIX(Display *dpy, GLXDrawable drawable, int barrier) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return; - (*t->BindSwapBarrierSGIX)(dpy, drawable, barrier); -} - -Bool PUBLIC -glXQueryMaxSwapBarriersSGIX(Display *dpy, int screen, int *max) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return False; - return (*t->QueryMaxSwapBarriersSGIX)(dpy, screen, max); -} - - - -/*** GLX_SUN_get_transparent_index ***/ - -Status PUBLIC -glXGetTransparentIndexSUN(Display *dpy, Window overlay, Window underlay, long *pTransparent) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return False; - return (*t->GetTransparentIndexSUN)(dpy, overlay, underlay, pTransparent); -} - - - -/*** GLX_MESA_copy_sub_buffer ***/ - -void PUBLIC -glXCopySubBufferMESA(Display *dpy, GLXDrawable drawable, int x, int y, int width, int height) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return; - (t->CopySubBufferMESA)(dpy, drawable, x, y, width, height); -} - - - -/*** GLX_MESA_release_buffers ***/ - -Bool PUBLIC -glXReleaseBuffersMESA(Display *dpy, Window w) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return False; - return (t->ReleaseBuffersMESA)(dpy, w); -} - - - -/*** GLX_MESA_pixmap_colormap ***/ - -GLXPixmap PUBLIC -glXCreateGLXPixmapMESA(Display *dpy, XVisualInfo *visinfo, Pixmap pixmap, Colormap cmap) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (!t) - return 0; - return (t->CreateGLXPixmapMESA)(dpy, visinfo, pixmap, cmap); -} - -/*** GLX_EXT_texture_from_pixmap */ - -void -glXBindTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer, - const int *attrib_list) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (t) - t->BindTexImageEXT(dpy, drawable, buffer, attrib_list); -} - -void -glXReleaseTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer) -{ - struct _glxapi_table *t; - GET_DISPATCH(dpy, t); - if (t) - t->ReleaseTexImageEXT(dpy, drawable, buffer); -} - - -/**********************************************************************/ -/* GLX API management functions */ -/**********************************************************************/ - - -const char * -_glxapi_get_version(void) -{ - return "1.3"; -} - - - -/* - * Return size of the GLX dispatch table, in entries, not bytes. - */ -GLuint -_glxapi_get_dispatch_table_size(void) -{ - return sizeof(struct _glxapi_table) / sizeof(void *); -} - - -static int -generic_no_op_func(void) -{ - return 0; -} - - -/* - * Initialize all functions in given dispatch table to be no-ops - */ -void -_glxapi_set_no_op_table(struct _glxapi_table *t) -{ - typedef int (*nop_func)(void); - nop_func *dispatch = (nop_func *) t; - GLuint n = _glxapi_get_dispatch_table_size(); - GLuint i; - for (i = 0; i < n; i++) { - dispatch[i] = generic_no_op_func; - } -} - - -struct name_address_pair { - const char *Name; - __GLXextFuncPtr Address; -}; - -static struct name_address_pair GLX_functions[] = { - /*** GLX_VERSION_1_0 ***/ - { "glXChooseVisual", (__GLXextFuncPtr) glXChooseVisual }, - { "glXCopyContext", (__GLXextFuncPtr) glXCopyContext }, - { "glXCreateContext", (__GLXextFuncPtr) glXCreateContext }, - { "glXCreateGLXPixmap", (__GLXextFuncPtr) glXCreateGLXPixmap }, - { "glXDestroyContext", (__GLXextFuncPtr) glXDestroyContext }, - { "glXDestroyGLXPixmap", (__GLXextFuncPtr) glXDestroyGLXPixmap }, - { "glXGetConfig", (__GLXextFuncPtr) glXGetConfig }, - { "glXGetCurrentContext", (__GLXextFuncPtr) glXGetCurrentContext }, - { "glXGetCurrentDrawable", (__GLXextFuncPtr) glXGetCurrentDrawable }, - { "glXIsDirect", (__GLXextFuncPtr) glXIsDirect }, - { "glXMakeCurrent", (__GLXextFuncPtr) glXMakeCurrent }, - { "glXQueryExtension", (__GLXextFuncPtr) glXQueryExtension }, - { "glXQueryVersion", (__GLXextFuncPtr) glXQueryVersion }, - { "glXSwapBuffers", (__GLXextFuncPtr) glXSwapBuffers }, - { "glXUseXFont", (__GLXextFuncPtr) glXUseXFont }, - { "glXWaitGL", (__GLXextFuncPtr) glXWaitGL }, - { "glXWaitX", (__GLXextFuncPtr) glXWaitX }, - - /*** GLX_VERSION_1_1 ***/ - { "glXGetClientString", (__GLXextFuncPtr) glXGetClientString }, - { "glXQueryExtensionsString", (__GLXextFuncPtr) glXQueryExtensionsString }, - { "glXQueryServerString", (__GLXextFuncPtr) glXQueryServerString }, - - /*** GLX_VERSION_1_2 ***/ - { "glXGetCurrentDisplay", (__GLXextFuncPtr) glXGetCurrentDisplay }, - - /*** GLX_VERSION_1_3 ***/ - { "glXChooseFBConfig", (__GLXextFuncPtr) glXChooseFBConfig }, - { "glXCreateNewContext", (__GLXextFuncPtr) glXCreateNewContext }, - { "glXCreatePbuffer", (__GLXextFuncPtr) glXCreatePbuffer }, - { "glXCreatePixmap", (__GLXextFuncPtr) glXCreatePixmap }, - { "glXCreateWindow", (__GLXextFuncPtr) glXCreateWindow }, - { "glXDestroyPbuffer", (__GLXextFuncPtr) glXDestroyPbuffer }, - { "glXDestroyPixmap", (__GLXextFuncPtr) glXDestroyPixmap }, - { "glXDestroyWindow", (__GLXextFuncPtr) glXDestroyWindow }, - { "glXGetCurrentReadDrawable", (__GLXextFuncPtr) glXGetCurrentReadDrawable }, - { "glXGetFBConfigAttrib", (__GLXextFuncPtr) glXGetFBConfigAttrib }, - { "glXGetFBConfigs", (__GLXextFuncPtr) glXGetFBConfigs }, - { "glXGetSelectedEvent", (__GLXextFuncPtr) glXGetSelectedEvent }, - { "glXGetVisualFromFBConfig", (__GLXextFuncPtr) glXGetVisualFromFBConfig }, - { "glXMakeContextCurrent", (__GLXextFuncPtr) glXMakeContextCurrent }, - { "glXQueryContext", (__GLXextFuncPtr) glXQueryContext }, - { "glXQueryDrawable", (__GLXextFuncPtr) glXQueryDrawable }, - { "glXSelectEvent", (__GLXextFuncPtr) glXSelectEvent }, - - /*** GLX_VERSION_1_4 ***/ - { "glXGetProcAddress", (__GLXextFuncPtr) glXGetProcAddress }, - - /*** GLX_SGI_swap_control ***/ - { "glXSwapIntervalSGI", (__GLXextFuncPtr) glXSwapIntervalSGI }, - - /*** GLX_SGI_video_sync ***/ - { "glXGetVideoSyncSGI", (__GLXextFuncPtr) glXGetVideoSyncSGI }, - { "glXWaitVideoSyncSGI", (__GLXextFuncPtr) glXWaitVideoSyncSGI }, - - /*** GLX_SGI_make_current_read ***/ - { "glXMakeCurrentReadSGI", (__GLXextFuncPtr) glXMakeCurrentReadSGI }, - { "glXGetCurrentReadDrawableSGI", (__GLXextFuncPtr) glXGetCurrentReadDrawableSGI }, - - /*** GLX_SGIX_video_source ***/ -#if defined(_VL_H) - { "glXCreateGLXVideoSourceSGIX", (__GLXextFuncPtr) glXCreateGLXVideoSourceSGIX }, - { "glXDestroyGLXVideoSourceSGIX", (__GLXextFuncPtr) glXDestroyGLXVideoSourceSGIX }, -#endif - - /*** GLX_EXT_import_context ***/ - { "glXFreeContextEXT", (__GLXextFuncPtr) glXFreeContextEXT }, - { "glXGetContextIDEXT", (__GLXextFuncPtr) glXGetContextIDEXT }, - { "glXGetCurrentDisplayEXT", (__GLXextFuncPtr) glXGetCurrentDisplayEXT }, - { "glXImportContextEXT", (__GLXextFuncPtr) glXImportContextEXT }, - { "glXQueryContextInfoEXT", (__GLXextFuncPtr) glXQueryContextInfoEXT }, - - /*** GLX_SGIX_fbconfig ***/ - { "glXGetFBConfigAttribSGIX", (__GLXextFuncPtr) glXGetFBConfigAttribSGIX }, - { "glXChooseFBConfigSGIX", (__GLXextFuncPtr) glXChooseFBConfigSGIX }, - { "glXCreateGLXPixmapWithConfigSGIX", (__GLXextFuncPtr) glXCreateGLXPixmapWithConfigSGIX }, - { "glXCreateContextWithConfigSGIX", (__GLXextFuncPtr) glXCreateContextWithConfigSGIX }, - { "glXGetVisualFromFBConfigSGIX", (__GLXextFuncPtr) glXGetVisualFromFBConfigSGIX }, - { "glXGetFBConfigFromVisualSGIX", (__GLXextFuncPtr) glXGetFBConfigFromVisualSGIX }, - - /*** GLX_SGIX_pbuffer ***/ - { "glXCreateGLXPbufferSGIX", (__GLXextFuncPtr) glXCreateGLXPbufferSGIX }, - { "glXDestroyGLXPbufferSGIX", (__GLXextFuncPtr) glXDestroyGLXPbufferSGIX }, - { "glXQueryGLXPbufferSGIX", (__GLXextFuncPtr) glXQueryGLXPbufferSGIX }, - { "glXSelectEventSGIX", (__GLXextFuncPtr) glXSelectEventSGIX }, - { "glXGetSelectedEventSGIX", (__GLXextFuncPtr) glXGetSelectedEventSGIX }, - - /*** GLX_SGI_cushion ***/ - { "glXCushionSGI", (__GLXextFuncPtr) glXCushionSGI }, - - /*** GLX_SGIX_video_resize ***/ - { "glXBindChannelToWindowSGIX", (__GLXextFuncPtr) glXBindChannelToWindowSGIX }, - { "glXChannelRectSGIX", (__GLXextFuncPtr) glXChannelRectSGIX }, - { "glXQueryChannelRectSGIX", (__GLXextFuncPtr) glXQueryChannelRectSGIX }, - { "glXQueryChannelDeltasSGIX", (__GLXextFuncPtr) glXQueryChannelDeltasSGIX }, - { "glXChannelRectSyncSGIX", (__GLXextFuncPtr) glXChannelRectSyncSGIX }, - - /*** GLX_SGIX_dmbuffer **/ -#if defined(_DM_BUFFER_H_) - { "glXAssociateDMPbufferSGIX", (__GLXextFuncPtr) glXAssociateDMPbufferSGIX }, -#endif - - /*** GLX_SGIX_swap_group ***/ - { "glXJoinSwapGroupSGIX", (__GLXextFuncPtr) glXJoinSwapGroupSGIX }, - - /*** GLX_SGIX_swap_barrier ***/ - { "glXBindSwapBarrierSGIX", (__GLXextFuncPtr) glXBindSwapBarrierSGIX }, - { "glXQueryMaxSwapBarriersSGIX", (__GLXextFuncPtr) glXQueryMaxSwapBarriersSGIX }, - - /*** GLX_SUN_get_transparent_index ***/ - { "glXGetTransparentIndexSUN", (__GLXextFuncPtr) glXGetTransparentIndexSUN }, - - /*** GLX_MESA_copy_sub_buffer ***/ - { "glXCopySubBufferMESA", (__GLXextFuncPtr) glXCopySubBufferMESA }, - - /*** GLX_MESA_pixmap_colormap ***/ - { "glXCreateGLXPixmapMESA", (__GLXextFuncPtr) glXCreateGLXPixmapMESA }, - - /*** GLX_MESA_release_buffers ***/ - { "glXReleaseBuffersMESA", (__GLXextFuncPtr) glXReleaseBuffersMESA }, - - /*** GLX_ARB_get_proc_address ***/ - { "glXGetProcAddressARB", (__GLXextFuncPtr) glXGetProcAddressARB }, - - /*** GLX_EXT_texture_from_pixmap ***/ - { "glXBindTexImageEXT", (__GLXextFuncPtr) glXBindTexImageEXT }, - { "glXReleaseTexImageEXT", (__GLXextFuncPtr) glXReleaseTexImageEXT }, - - { NULL, NULL } /* end of list */ -}; - - - -/* - * Return address of named glX function, or NULL if not found. - */ -__GLXextFuncPtr -_glxapi_get_proc_address(const char *funcName) -{ - GLuint i; - for (i = 0; GLX_functions[i].Name; i++) { - if (strcmp(GLX_functions[i].Name, funcName) == 0) - return GLX_functions[i].Address; - } - return NULL; -} - - - -/* - * This function does not get dispatched through the dispatch table - * since it's really a "meta" function. - */ -__GLXextFuncPtr -glXGetProcAddressARB(const GLubyte *procName) -{ - __GLXextFuncPtr f; - - f = _glxapi_get_proc_address((const char *) procName); - if (f) { - return f; - } - - f = (__GLXextFuncPtr) _glapi_get_proc_address((const char *) procName); - return f; -} - - -/* GLX 1.4 */ -void (*glXGetProcAddress(const GLubyte *procName))() -{ - return glXGetProcAddressARB(procName); -} diff --git a/src/gallium/state_trackers/glx/xlib/glxapi.h b/src/gallium/state_trackers/glx/xlib/glxapi.h deleted file mode 100644 index b4e12b4162..0000000000 --- a/src/gallium/state_trackers/glx/xlib/glxapi.h +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Mesa 3-D graphics library - * Version: 6.3 - * - * Copyright (C) 1999-2004 Brian Paul 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, 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 - * BRIAN PAUL 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 _glxapi_h_ -#define _glxapi_h_ - - -#define GLX_GLXEXT_PROTOTYPES -#include "GL/glx.h" - - -/* The GLX API dispatcher (i.e. this code) is being built into stand-alone - * Mesa. We don't know anything about XFree86 or real GLX so we define a - * minimal __GLXContextRec here so some of the functions in this file can - * work properly. - */ -typedef struct __GLXcontextRec { - Display *currentDpy; - GLboolean isDirect; - GLXDrawable currentDrawable; - GLXDrawable currentReadable; - XID xid; -} __GLXcontext; - - -/* - * Almost all the GLX API functions get routed through this dispatch table. - * The exceptions are the glXGetCurrentXXX() functions. - * - * This dispatch table allows multiple GLX client-side modules to coexist. - * Specifically, a real GLX library (like SGI's or the Utah GLX) and Mesa's - * pseudo-GLX can be present at the same time. The former being used on - * GLX-enabled X servers and the later on non-GLX X servers. - * - * Red Hat has been using this since Red Hat Linux 7.0 (I think). - * This'll be a standard feature in XFree86 4.3. It basically allows one - * libGL to do both DRI-rendering and "fake GLX" rendering to X displays - * that lack the GLX extension. - */ -struct _glxapi_table { - /*** GLX_VERSION_1_0 ***/ - XVisualInfo *(*ChooseVisual)(Display *dpy, int screen, int *list); - void (*CopyContext)(Display *dpy, GLXContext src, GLXContext dst, unsigned long mask); - GLXContext (*CreateContext)(Display *dpy, XVisualInfo *visinfo, GLXContext shareList, Bool direct); - GLXPixmap (*CreateGLXPixmap)(Display *dpy, XVisualInfo *visinfo, Pixmap pixmap); - void (*DestroyContext)(Display *dpy, GLXContext ctx); - void (*DestroyGLXPixmap)(Display *dpy, GLXPixmap pixmap); - int (*GetConfig)(Display *dpy, XVisualInfo *visinfo, int attrib, int *value); - /*GLXContext (*GetCurrentContext)(void);*/ - /*GLXDrawable (*GetCurrentDrawable)(void);*/ - Bool (*IsDirect)(Display *dpy, GLXContext ctx); - Bool (*MakeCurrent)(Display *dpy, GLXDrawable drawable, GLXContext ctx); - Bool (*QueryExtension)(Display *dpy, int *errorb, int *event); - Bool (*QueryVersion)(Display *dpy, int *maj, int *min); - void (*SwapBuffers)(Display *dpy, GLXDrawable drawable); - void (*UseXFont)(Font font, int first, int count, int listBase); - void (*WaitGL)(void); - void (*WaitX)(void); - - /*** GLX_VERSION_1_1 ***/ - const char *(*GetClientString)(Display *dpy, int name); - const char *(*QueryExtensionsString)(Display *dpy, int screen); - const char *(*QueryServerString)(Display *dpy, int screen, int name); - - /*** GLX_VERSION_1_2 ***/ - /*Display *(*GetCurrentDisplay)(void);*/ - - /*** GLX_VERSION_1_3 ***/ - GLXFBConfig *(*ChooseFBConfig)(Display *dpy, int screen, const int *attribList, int *nitems); - GLXContext (*CreateNewContext)(Display *dpy, GLXFBConfig config, int renderType, GLXContext shareList, Bool direct); - GLXPbuffer (*CreatePbuffer)(Display *dpy, GLXFBConfig config, const int *attribList); - GLXPixmap (*CreatePixmap)(Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attribList); - GLXWindow (*CreateWindow)(Display *dpy, GLXFBConfig config, Window win, const int *attribList); - void (*DestroyPbuffer)(Display *dpy, GLXPbuffer pbuf); - void (*DestroyPixmap)(Display *dpy, GLXPixmap pixmap); - void (*DestroyWindow)(Display *dpy, GLXWindow window); - /*GLXDrawable (*GetCurrentReadDrawable)(void);*/ - int (*GetFBConfigAttrib)(Display *dpy, GLXFBConfig config, int attribute, int *value); - GLXFBConfig *(*GetFBConfigs)(Display *dpy, int screen, int *nelements); - void (*GetSelectedEvent)(Display *dpy, GLXDrawable drawable, unsigned long *mask); - XVisualInfo *(*GetVisualFromFBConfig)(Display *dpy, GLXFBConfig config); - Bool (*MakeContextCurrent)(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx); - int (*QueryContext)(Display *dpy, GLXContext ctx, int attribute, int *value); - void (*QueryDrawable)(Display *dpy, GLXDrawable draw, int attribute, unsigned int *value); - void (*SelectEvent)(Display *dpy, GLXDrawable drawable, unsigned long mask); - - /*** GLX_SGI_swap_control ***/ - int (*SwapIntervalSGI)(int); - - /*** GLX_SGI_video_sync ***/ - int (*GetVideoSyncSGI)(unsigned int *count); - int (*WaitVideoSyncSGI)(int divisor, int remainder, unsigned int *count); - - /*** GLX_SGI_make_current_read ***/ - Bool (*MakeCurrentReadSGI)(Display *, GLXDrawable, GLXDrawable, GLXContext); - /*GLXDrawable (*GetCurrentReadDrawableSGI)(void);*/ - - /*** GLX_SGIX_video_source (needs video library) ***/ -#if defined(_VL_H_) - GLXVideoSourceSGIX (*CreateGLXVideoSourceSGIX)(Display *, int, VLServer, VLPath, int, VLNode); - void (*DestroyGLXVideoSourceSGIX)(Display *, GLXVideoSourceSGIX); -#else - void *CreateGLXVideoSourceSGIX; - void *DestroyGLXVideoSourceSGIX; -#endif - - /*** GLX_EXT_import_context ***/ - void (*FreeContextEXT)(Display *dpy, GLXContext context); - GLXContextID (*GetContextIDEXT)(const GLXContext context); - /*Display *(*GetCurrentDisplayEXT)(void);*/ - GLXContext (*ImportContextEXT)(Display *dpy, GLXContextID contextID); - int (*QueryContextInfoEXT)(Display *dpy, GLXContext context, int attribute,int *value); - - /*** GLX_SGIX_fbconfig ***/ - int (*GetFBConfigAttribSGIX)(Display *, GLXFBConfigSGIX, int, int *); - GLXFBConfigSGIX * (*ChooseFBConfigSGIX)(Display *, int, int *, int *); - GLXPixmap (*CreateGLXPixmapWithConfigSGIX)(Display *, GLXFBConfigSGIX, Pixmap); - GLXContext (*CreateContextWithConfigSGIX)(Display *, GLXFBConfigSGIX, int, GLXContext, Bool); - XVisualInfo * (*GetVisualFromFBConfigSGIX)(Display *, GLXFBConfigSGIX); - GLXFBConfigSGIX (*GetFBConfigFromVisualSGIX)(Display *, XVisualInfo *); - - /*** GLX_SGIX_pbuffer ***/ - GLXPbufferSGIX (*CreateGLXPbufferSGIX)(Display *, GLXFBConfigSGIX, unsigned int, unsigned int, int *); - void (*DestroyGLXPbufferSGIX)(Display *, GLXPbufferSGIX); - int (*QueryGLXPbufferSGIX)(Display *, GLXPbufferSGIX, int, unsigned int *); - void (*SelectEventSGIX)(Display *, GLXDrawable, unsigned long); - void (*GetSelectedEventSGIX)(Display *, GLXDrawable, unsigned long *); - - /*** GLX_SGI_cushion ***/ - void (*CushionSGI)(Display *, Window, float); - - /*** GLX_SGIX_video_resize ***/ - int (*BindChannelToWindowSGIX)(Display *, int, int, Window); - int (*ChannelRectSGIX)(Display *, int, int, int, int, int, int); - int (*QueryChannelRectSGIX)(Display *, int, int, int *, int *, int *, int *); - int (*QueryChannelDeltasSGIX)(Display *, int, int, int *, int *, int *, int *); - int (*ChannelRectSyncSGIX)(Display *, int, int, GLenum); - - /*** GLX_SGIX_dmbuffer (needs dmedia library) ***/ -#if defined (_DM_BUFFER_H_) - Bool (*AssociateDMPbufferSGIX)(Display *, GLXPbufferSGIX, DMparams *, DMbuffer); -#else - void *AssociciateDMPbufferSGIX; -#endif - - /*** GLX_SGIX_swap_group ***/ - void (*JoinSwapGroupSGIX)(Display *, GLXDrawable, GLXDrawable); - - /*** GLX_SGIX_swap_barrier ***/ - void (*BindSwapBarrierSGIX)(Display *, GLXDrawable, int); - Bool (*QueryMaxSwapBarriersSGIX)(Display *, int, int *); - - /*** GLX_SUN_get_transparent_index ***/ - Status (*GetTransparentIndexSUN)(Display *, Window, Window, long *); - - /*** GLX_MESA_copy_sub_buffer ***/ - void (*CopySubBufferMESA)(Display *dpy, GLXDrawable drawable, int x, int y, int width, int height); - - /*** GLX_MESA_release_buffers ***/ - Bool (*ReleaseBuffersMESA)(Display *dpy, Window w); - - /*** GLX_MESA_pixmap_colormap ***/ - GLXPixmap (*CreateGLXPixmapMESA)(Display *dpy, XVisualInfo *visinfo, Pixmap pixmap, Colormap cmap); - - /*** GLX_EXT_texture_from_pixmap ***/ - void (*BindTexImageEXT)(Display *dpy, GLXDrawable drawable, int buffer, - const int *attrib_list); - void (*ReleaseTexImageEXT)(Display *dpy, GLXDrawable drawable, int buffer); -}; - - - -extern const char * -_glxapi_get_version(void); - - - - -extern GLuint -_glxapi_get_dispatch_table_size(void); - - -extern void -_glxapi_set_no_op_table(struct _glxapi_table *t); - - -extern __GLXextFuncPtr -_glxapi_get_proc_address(const char *funcName); - - -#endif diff --git a/src/gallium/state_trackers/glx/xlib/xm_api.h b/src/gallium/state_trackers/glx/xlib/xm_api.h index bdd434cd36..ce97a3ec76 100644 --- a/src/gallium/state_trackers/glx/xlib/xm_api.h +++ b/src/gallium/state_trackers/glx/xlib/xm_api.h @@ -57,7 +57,7 @@ and create a window, you must do the following to use the X/Mesa interface: #define XMESA_H -#include "mtypes.h" +#include "main/mtypes.h" #include "state_tracker/st_context.h" #include "state_tracker/st_public.h" #include "pipe/p_thread.h" diff --git a/src/gallium/state_trackers/vega/vg_tracker.c b/src/gallium/state_trackers/vega/vg_tracker.c index c262ce08fa..56cc60aebe 100644 --- a/src/gallium/state_trackers/vega/vg_tracker.c +++ b/src/gallium/state_trackers/vega/vg_tracker.c @@ -367,6 +367,11 @@ void st_make_current(struct vg_context *st, } } +struct vg_context *st_get_current(void) +{ + return vg_current_context(); +} + void st_flush(struct vg_context *st, uint pipeFlushFlags, struct pipe_fence_handle **fence) { @@ -399,8 +404,13 @@ void st_notify_swapbuffers_complete(struct st_framebuffer *stfb) { } -int -st_set_teximage(struct pipe_texture *pt, int target) +int st_bind_texture_surface(struct pipe_surface *ps, int target, int level, + enum pipe_format format) +{ + return 0; +} + +int st_unbind_texture_surface(struct pipe_surface *ps, int target, int level) { return 0; } diff --git a/src/gallium/state_trackers/vega/vg_tracker.h b/src/gallium/state_trackers/vega/vg_tracker.h index 805c58ccc7..5457631106 100644 --- a/src/gallium/state_trackers/vega/vg_tracker.h +++ b/src/gallium/state_trackers/vega/vg_tracker.h @@ -70,7 +70,10 @@ void st_set_framebuffer_surface(struct st_framebuffer *stfb, void st_get_framebuffer_dimensions( struct st_framebuffer *stfb, uint *width, uint *height); -int st_set_teximage(struct pipe_texture *pt, int target); +int st_bind_texture_surface(struct pipe_surface *ps, int target, int level, + enum pipe_format format); + +int st_unbind_texture_surface(struct pipe_surface *ps, int target, int level); int st_get_framebuffer_surface(struct st_framebuffer *stfb, uint surfIndex, struct pipe_surface **surf); @@ -86,6 +89,8 @@ void st_make_current(struct vg_context *st, struct st_framebuffer *draw, struct st_framebuffer *read); +struct vg_context *st_get_current(void); + void st_flush(struct vg_context *st, uint pipeFlushFlags, struct pipe_fence_handle **fence); void st_finish(struct vg_context *st); diff --git a/src/gallium/state_trackers/xorg/xorg_dri2.c b/src/gallium/state_trackers/xorg/xorg_dri2.c index ae3338ffef..3fbab4dc51 100644 --- a/src/gallium/state_trackers/xorg/xorg_dri2.c +++ b/src/gallium/state_trackers/xorg/xorg_dri2.c @@ -39,10 +39,13 @@ #include "pipe/p_state.h" #include "pipe/p_inlines.h" +#include "util/u_rect.h" + typedef struct { PixmapPtr pPixmap; struct pipe_texture *tex; struct pipe_buffer *buf; + struct pipe_fence_handle *fence; } *BufferPrivatePtr; static DRI2BufferPtr @@ -83,7 +86,6 @@ driCreateBuffers(DrawablePtr pDraw, unsigned int *attachments, int count) pipe_texture_reference(&tex, depth); } else if (attachments[i] == DRI2BufferDepth) { struct pipe_texture template; - memset(&template, 0, sizeof(template)); template.target = PIPE_TEXTURE_2D; template.format = PIPE_FORMAT_S8Z24_UNORM; @@ -92,22 +94,20 @@ driCreateBuffers(DrawablePtr pDraw, unsigned int *attachments, int count) template.height[0] = pDraw->height; template.depth[0] = 1; template.last_level = 0; - template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET; + template.tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL; tex = ms->screen->texture_create(ms->screen, &template); + depth = tex; } else { - struct pipe_texture template; - memset(&template, 0, sizeof(template)); - template.target = PIPE_TEXTURE_2D; - template.format = PIPE_FORMAT_A8R8G8B8_UNORM; - pf_get_block(template.format, &template.block); - template.width[0] = pDraw->width; - template.height[0] = pDraw->height; - template.depth[0] = 1; - template.last_level = 0; - template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET; - tex = ms->screen->texture_create(ms->screen, &template); + pPixmap = (*pScreen->CreatePixmap)(pScreen, pDraw->width, + pDraw->height, + pDraw->depth, + 0); + tex = xorg_exa_get_texture(pPixmap); } + if (!tex) + FatalError("NO TEXTURE IN DRI2\n"); + ms->api->buffer_from_texture(ms->api, tex, &buf, &stride); ms->api->global_handle_from_buffer(ms->api, ms->screen, buf, &handle); @@ -138,15 +138,17 @@ driDestroyBuffers(DrawablePtr pDraw, DRI2BufferPtr buffers, int count) modesettingPtr ms = modesettingPTR(pScrn); BufferPrivatePtr private; int i; + (void)ms; for (i = 0; i < count; i++) { private = buffers[i].driverPrivate; - if (private->pPixmap) - (*pScreen->DestroyPixmap)(private->pPixmap); - pipe_texture_reference(&private->tex, NULL); pipe_buffer_reference(&private->buf, NULL); + ms->screen->fence_reference(ms->screen, &private->fence, NULL); + + if (private->pPixmap) + (*pScreen->DestroyPixmap)(private->pPixmap); } if (buffers) { @@ -164,19 +166,42 @@ driCopyRegion(DrawablePtr pDraw, RegionPtr pRegion, modesettingPtr ms = modesettingPTR(pScrn); BufferPrivatePtr dst_priv = pDestBuffer->driverPrivate; BufferPrivatePtr src_priv = pSrcBuffer->driverPrivate; + PixmapPtr src_pixmap; + PixmapPtr dst_pixmap; + GCPtr gc; + RegionPtr copy_clip; + + src_pixmap = src_priv->pPixmap; + dst_pixmap = dst_priv->pPixmap; + if (pSrcBuffer->attachment == DRI2BufferFrontLeft) + src_pixmap = (PixmapPtr)pDraw; + if (pDestBuffer->attachment == DRI2BufferFrontLeft) + dst_pixmap = (PixmapPtr)pDraw; + gc = GetScratchGC(pDraw->depth, pScreen); + copy_clip = REGION_CREATE(pScreen, NULL, 0); + REGION_COPY(pScreen, copy_clip, pRegion); + (*gc->funcs->ChangeClip) (gc, CT_REGION, copy_clip, 0); + ValidateGC(&dst_pixmap->drawable, gc); + + /* If this is a full buffer swap, throttle on the previous one */ + if (dst_priv->fence && REGION_NUM_RECTS(pRegion) == 1) { + BoxPtr extents = REGION_EXTENTS(pScreen, pRegion); + + if (extents->x1 == 0 && extents->y1 == 0 && + extents->x2 == pDraw->width && extents->y2 == pDraw->height) { + ms->screen->fence_finish(ms->screen, dst_priv->fence, 0); + ms->screen->fence_reference(ms->screen, &dst_priv->fence, NULL); + } + } - struct pipe_surface *dst_surf = - ms->screen->get_tex_surface(ms->screen, dst_priv->tex, 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_WRITE); - struct pipe_surface *src_surf = - ms->screen->get_tex_surface(ms->screen, src_priv->tex, 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_READ); + (*gc->ops->CopyArea)(&src_pixmap->drawable, &dst_pixmap->drawable, gc, + 0, 0, pDraw->width, pDraw->height, 0, 0); - ms->ctx->surface_copy(ms->ctx, dst_surf, 0, 0, src_surf, - 0, 0, pDraw->width, pDraw->height); + FreeScratchGC(gc); - pipe_surface_reference(&dst_surf, NULL); - pipe_surface_reference(&src_surf, NULL); + ms->ctx->flush(ms->ctx, PIPE_FLUSH_SWAPBUFFERS, + pDestBuffer->attachment == DRI2BufferFrontLeft ? + &dst_priv->fence : NULL); } Bool diff --git a/src/gallium/state_trackers/xorg/xorg_driver.c b/src/gallium/state_trackers/xorg/xorg_driver.c index e01e5294b1..53d1a33095 100644 --- a/src/gallium/state_trackers/xorg/xorg_driver.c +++ b/src/gallium/state_trackers/xorg/xorg_driver.c @@ -179,8 +179,10 @@ CreateFrontBuffer(ScrnInfoPtr pScrn) modesettingPtr ms = modesettingPTR(pScrn); ScreenPtr pScreen = pScrn->pScreen; PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen); + unsigned handle, stride; ms->noEvict = TRUE; + xorg_exa_set_displayed_usage(rootPixmap); pScreen->ModifyPixmapHeader(rootPixmap, pScrn->virtualX, pScrn->virtualY, pScrn->depth, pScrn->bitsPerPixel, @@ -188,13 +190,16 @@ CreateFrontBuffer(ScrnInfoPtr pScrn) NULL); ms->noEvict = FALSE; + handle = xorg_exa_get_pixmap_handle(rootPixmap, &stride); + drmModeAddFB(ms->fd, pScrn->virtualX, pScrn->virtualY, pScrn->depth, pScrn->bitsPerPixel, - pScrn->displayWidth * pScrn->bitsPerPixel / 8, - xorg_exa_get_pixmap_handle(rootPixmap), &ms->fb_id); + stride, + handle, + &ms->fb_id); pScrn->frameX0 = 0; pScrn->frameY0 = 0; @@ -426,6 +431,7 @@ CreateScreenResources(ScreenPtr pScreen) modesettingPtr ms = modesettingPTR(pScrn); PixmapPtr rootPixmap; Bool ret; + unsigned handle, stride; ms->noEvict = TRUE; @@ -435,18 +441,22 @@ CreateScreenResources(ScreenPtr pScreen) rootPixmap = pScreen->GetScreenPixmap(pScreen); + xorg_exa_set_displayed_usage(rootPixmap); if (!pScreen->ModifyPixmapHeader(rootPixmap, -1, -1, -1, -1, -1, NULL)) FatalError("Couldn't adjust screen pixmap\n"); ms->noEvict = FALSE; + handle = xorg_exa_get_pixmap_handle(rootPixmap, &stride); + drmModeAddFB(ms->fd, pScrn->virtualX, pScrn->virtualY, pScrn->depth, pScrn->bitsPerPixel, - pScrn->displayWidth * pScrn->bitsPerPixel / 8, - xorg_exa_get_pixmap_handle(rootPixmap), &ms->fb_id); + stride, + handle, + &ms->fb_id); AdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); @@ -623,6 +633,10 @@ LeaveVT(int scrnIndex, int flags) RestoreHWState(pScrn); + if (drmDropMaster(ms->fd)) + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "drmDropMaster failed: %s\n", strerror(errno)); + pScrn->vtSema = FALSE; } @@ -635,6 +649,17 @@ EnterVT(int scrnIndex, int flags) ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; modesettingPtr ms = modesettingPTR(pScrn); + if (drmSetMaster(ms->fd)) { + if (errno == EINVAL) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "drmSetMaster failed: 2.6.29 or newer kernel required for " + "multi-server DRI\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "drmSetMaster failed: %s\n", strerror(errno)); + } + } + /* * Only save state once per server generation since that's what most * drivers do. Could change this to save state at each VT enter. diff --git a/src/gallium/state_trackers/xorg/xorg_exa.c b/src/gallium/state_trackers/xorg/xorg_exa.c index 2c4291aa4e..f2dac73e90 100644 --- a/src/gallium/state_trackers/xorg/xorg_exa.c +++ b/src/gallium/state_trackers/xorg/xorg_exa.c @@ -359,8 +359,48 @@ ExaPixmapIsOffscreen(PixmapPtr pPixmap) return FALSE; } +int +xorg_exa_set_displayed_usage(PixmapPtr pPixmap) +{ + struct exa_pixmap_priv *priv; + priv = exaGetPixmapDriverPrivate(pPixmap); + + if (!priv) { + FatalError("NO PIXMAP PRIVATE\n"); + return 0; + } + + if (priv->flags & ~PIPE_TEXTURE_USAGE_PRIMARY) { + FatalError("BAD FLAGS\n"); + return 0; + } + priv->flags = PIPE_TEXTURE_USAGE_PRIMARY; + + return 0; +} + +int +xorg_exa_set_shared_usage(PixmapPtr pPixmap) +{ + struct exa_pixmap_priv *priv; + priv = exaGetPixmapDriverPrivate(pPixmap); + + if (!priv) { + FatalError("NO PIXMAP PRIVATE\n"); + return 0; + } + + if (priv->flags & ~PIPE_TEXTURE_USAGE_DISPLAY_TARGET) { + FatalError("BAD FLAGS\n"); + return 0; + } + priv->flags = PIPE_TEXTURE_USAGE_DISPLAY_TARGET; + + return 0; +} + unsigned -xorg_exa_get_pixmap_handle(PixmapPtr pPixmap) +xorg_exa_get_pixmap_handle(PixmapPtr pPixmap, unsigned *stride_out) { ScreenPtr pScreen = pPixmap->drawable.pScreen; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; @@ -385,6 +425,9 @@ xorg_exa_get_pixmap_handle(PixmapPtr pPixmap) ms->api->buffer_from_texture(ms->api, priv->tex, &buffer, &stride); ms->api->handle_from_buffer(ms->api, ms->screen, buffer, &handle); pipe_buffer_reference(&buffer, NULL); + if (stride_out) + *stride_out = stride; + return handle; } @@ -421,7 +464,9 @@ ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, bitsPerPixel, devKind, NULL); /* Deal with screen resize */ - if (priv->tex && (priv->tex->width[0] != width || priv->tex->height[0] != height)) { + if (priv->tex && (priv->tex->width[0] != width || + priv->tex->height[0] != height || + priv->tex_flags != priv->flags)) { pipe_texture_reference(&priv->tex, NULL); } @@ -436,7 +481,8 @@ ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, template.height[0] = height; template.depth[0] = 1; template.last_level = 0; - template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET; + template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET | priv->flags; + priv->tex_flags = priv->flags; priv->tex = exa->scrn->texture_create(exa->scrn, &template); } diff --git a/src/gallium/state_trackers/xorg/xorg_exa.h b/src/gallium/state_trackers/xorg/xorg_exa.h index 650997aec6..f0508eb2d5 100644 --- a/src/gallium/state_trackers/xorg/xorg_exa.h +++ b/src/gallium/state_trackers/xorg/xorg_exa.h @@ -14,6 +14,8 @@ struct exa_context struct exa_pixmap_priv { int flags; + int tex_flags; + struct pipe_texture *tex; unsigned int color; struct pipe_surface *src_surf; /* for copies */ diff --git a/src/gallium/state_trackers/xorg/xorg_tracker.h b/src/gallium/state_trackers/xorg/xorg_tracker.h index b4742bdbf5..910782dbc4 100644 --- a/src/gallium/state_trackers/xorg/xorg_tracker.h +++ b/src/gallium/state_trackers/xorg/xorg_tracker.h @@ -31,6 +31,7 @@ #ifndef _XORG_TRACKER_H_ #define _XORG_TRACKER_H_ +#include <stddef.h> #include <stdint.h> #include <errno.h> #include <drm.h> @@ -98,7 +99,13 @@ struct pipe_texture * xorg_exa_get_texture(PixmapPtr pPixmap); unsigned -xorg_exa_get_pixmap_handle(PixmapPtr pPixmap); +xorg_exa_get_pixmap_handle(PixmapPtr pPixmap, unsigned *stride); + +int +xorg_exa_set_displayed_usage(PixmapPtr pPixmap); + +int +xorg_exa_set_shared_usage(PixmapPtr pPixmap); void * xorg_exa_init(ScrnInfoPtr pScrn); diff --git a/src/gallium/winsys/drm/Makefile.template b/src/gallium/winsys/drm/Makefile.template index 985e5a861f..9635c3c50e 100644 --- a/src/gallium/winsys/drm/Makefile.template +++ b/src/gallium/winsys/drm/Makefile.template @@ -83,7 +83,9 @@ default: depend symlinks $(TOP)/$(LIB_DIR)/gallium/$(LIBNAME) $(LIBNAME): $(OBJECTS) $(MESA_MODULES) $(PIPE_DRIVERS) $(WINOBJ) Makefile $(TOP)/src/mesa/drivers/dri/Makefile.template $(MKLIB) -noprefix -o $@ \ - $(OBJECTS) $(PIPE_DRIVERS) $(MESA_MODULES) $(WINOBJ) $(DRI_LIB_DEPS) $(DRIVER_EXTRAS) + $(OBJECTS) $(PIPE_DRIVERS) \ + -Wl,--start-group $(MESA_MODULES) -Wl,--end-group \ + $(WINOBJ) $(DRI_LIB_DEPS) $(DRIVER_EXTRAS) $(LIBNAME_EGL): $(WINSYS_OBJECTS) $(LIBS) $(MKLIB) -o $(LIBNAME_EGL) \ diff --git a/src/gallium/winsys/drm/intel/dri/SConscript b/src/gallium/winsys/drm/intel/dri/SConscript index e14e96e32f..6c00861f51 100644 --- a/src/gallium/winsys/drm/intel/dri/SConscript +++ b/src/gallium/winsys/drm/intel/dri/SConscript @@ -2,11 +2,14 @@ Import('*') env = drienv.Clone() +env.ParseConfig('pkg-config --cflags --libs libdrm_intel') + drivers = [ + st_dri, + inteldrm, softpipe, i915simple, trace, - inteldrm ] env.SharedLibrary( diff --git a/src/gallium/winsys/drm/intel/egl/Makefile b/src/gallium/winsys/drm/intel/egl/Makefile index c5217ad2d6..490baded66 100644 --- a/src/gallium/winsys/drm/intel/egl/Makefile +++ b/src/gallium/winsys/drm/intel/egl/Makefile @@ -8,6 +8,7 @@ PIPE_DRIVERS = \ $(TOP)/src/gallium/state_trackers/egl/libegldrm.a \ $(GALLIUMDIR)/winsys/drm/intel/gem/libinteldrm.a \ $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ + $(TOP)/src/gallium/drivers/trace/libtrace.a \ $(TOP)/src/gallium/drivers/i915simple/libi915simple.a DRIVER_SOURCES = diff --git a/src/gallium/winsys/drm/intel/gem/intel_be_batchbuffer.c b/src/gallium/winsys/drm/intel/gem/intel_be_batchbuffer.c index d5e63c3bae..c4a79586e6 100644 --- a/src/gallium/winsys/drm/intel/gem/intel_be_batchbuffer.c +++ b/src/gallium/winsys/drm/intel/gem/intel_be_batchbuffer.c @@ -21,12 +21,10 @@ intel_be_batchbuffer_alloc(struct intel_be_context *intel) batch->base.size = 0; batch->base.actual_size = intel->device->max_batch_size; batch->base.relocs = 0; - batch->base.max_relocs = 500;/*INTEL_DEFAULT_RELOCS;*/ + batch->base.max_relocs = 100;/*INTEL_DEFAULT_RELOCS;*/ - batch->base.map = malloc(batch->base.actual_size); - memset(batch->base.map, 0, batch->base.actual_size); - - batch->base.ptr = batch->base.map; + batch->intel = intel; + batch->device = intel->device; intel_be_batchbuffer_reset(batch); @@ -41,16 +39,17 @@ intel_be_batchbuffer_reset(struct intel_be_batchbuffer *batch) if (batch->bo) drm_intel_bo_unreference(batch->bo); + batch->bo = drm_intel_bo_alloc(dev->pools.gem, + "gallium3d_batch_buffer", + batch->base.actual_size, + 4096); + drm_intel_bo_map(batch->bo, TRUE); + batch->base.map = batch->bo->virtual; memset(batch->base.map, 0, batch->base.actual_size); batch->base.ptr = batch->base.map; batch->base.size = batch->base.actual_size - BATCH_RESERVED; - batch->base.relocs = 0; - - batch->bo = drm_intel_bo_alloc(dev->pools.gem, - "gallium3d_batch_buffer", - batch->base.actual_size, 0); } int @@ -88,6 +87,7 @@ intel_be_batchbuffer_flush(struct intel_be_batchbuffer *batch, struct i915_batchbuffer *i915 = &batch->base; unsigned used = 0; int ret = 0; + int i; assert(i915_batchbuffer_space(i915) >= 0); @@ -105,11 +105,29 @@ intel_be_batchbuffer_flush(struct intel_be_batchbuffer *batch, used = batch->base.ptr - batch->base.map; - drm_intel_bo_subdata(batch->bo, 0, used, batch->base.map); - ret = drm_intel_bo_exec(batch->bo, used, NULL, 0, 0); + drm_intel_bo_unmap(batch->bo); + /* Do the sending to HW */ + ret = drm_intel_bo_exec(batch->bo, used, NULL, 0, 0); assert(ret == 0); + if (batch->device->dump_cmd) { + unsigned *ptr; + drm_intel_bo_map(batch->bo, FALSE); + ptr = (unsigned*)batch->bo->virtual; + + debug_printf("%s:\n", __func__); + for (i = 0; i < used / 4; i++, ptr++) { + debug_printf("\t%08x: %08x\n", i*4, *ptr); + } + + drm_intel_bo_unmap(batch->bo); + } else { + /* TODO figgure out why the gpu hangs if we don't run sync */ + drm_intel_bo_map(batch->bo, FALSE); + drm_intel_bo_unmap(batch->bo); + } + intel_be_batchbuffer_reset(batch); if (fence) { @@ -134,6 +152,5 @@ intel_be_batchbuffer_free(struct intel_be_batchbuffer *batch) if (batch->bo) drm_intel_bo_unreference(batch->bo); - free(batch->base.map); free(batch); } diff --git a/src/gallium/winsys/drm/intel/gem/intel_be_context.c b/src/gallium/winsys/drm/intel/gem/intel_be_context.c index db84f9af51..629987c6f9 100644 --- a/src/gallium/winsys/drm/intel/gem/intel_be_context.c +++ b/src/gallium/winsys/drm/intel/gem/intel_be_context.c @@ -36,7 +36,7 @@ intel_be_batch_reloc(struct i915_winsys *sws, } if (access_flags & I915_BUFFER_ACCESS_READ) { - read |= I915_GEM_DOMAIN_VERTEX; + read |= I915_GEM_DOMAIN_SAMPLER; } ret = intel_be_offset_relocation(intel->batch, diff --git a/src/gallium/winsys/drm/intel/gem/intel_be_device.c b/src/gallium/winsys/drm/intel/gem/intel_be_device.c index e3630f5d12..5312865a03 100644 --- a/src/gallium/winsys/drm/intel/gem/intel_be_device.c +++ b/src/gallium/winsys/drm/intel/gem/intel_be_device.c @@ -7,6 +7,7 @@ #include "pipe/p_inlines.h" #include "util/u_memory.h" #include "util/u_debug.h" +#include "util/u_math.h" #include "intel_be_fence.h" @@ -16,6 +17,8 @@ #include "intel_be_api.h" #include <stdio.h> +#define I915_TILING_X 1 + /* * Buffer */ @@ -25,9 +28,10 @@ intel_be_buffer_map(struct pipe_winsys *winsys, struct pipe_buffer *buf, unsigned flags) { + struct intel_be_buffer *buffer = intel_be_buffer(buf); drm_intel_bo *bo = intel_bo(buf); int write = 0; - int ret; + int ret = 0; if (flags & PIPE_BUFFER_USAGE_DONTBLOCK) { /* Remove this when drm_intel_bo_map supports DONTBLOCK @@ -38,19 +42,37 @@ intel_be_buffer_map(struct pipe_winsys *winsys, if (flags & PIPE_BUFFER_USAGE_CPU_WRITE) write = 1; - ret = drm_intel_bo_map(bo, write); + if (buffer->map_count) + goto out; + + if (buffer->map_gtt) + ret = drm_intel_gem_bo_map_gtt(bo); + else + ret = drm_intel_bo_map(bo, write); + + buffer->ptr = bo->virtual; +out: if (ret) return NULL; - return bo->virtual; + buffer->map_count++; + return buffer->ptr; } static void intel_be_buffer_unmap(struct pipe_winsys *winsys, struct pipe_buffer *buf) { - drm_intel_bo_unmap(intel_bo(buf)); + struct intel_be_buffer *buffer = intel_be_buffer(buf); + + if (--buffer->map_count) + return; + + if (buffer->map_gtt) + drm_intel_gem_bo_unmap_gtt(intel_bo(buf)); + else + drm_intel_bo_unmap(intel_bo(buf)); } static void @@ -80,8 +102,13 @@ intel_be_buffer_create(struct pipe_winsys *winsys, buffer->base.size = size; buffer->flinked = FALSE; buffer->flink = 0; + buffer->map_gtt = FALSE; - if (usage & (PIPE_BUFFER_USAGE_VERTEX | PIPE_BUFFER_USAGE_CONSTANT)) { + if (usage & I915_BUFFER_USAGE_SCANOUT) { + /* Scanout buffer */ + name = "gallium3d_scanout"; + pool = dev->pools.gem; + } else if (usage & (PIPE_BUFFER_USAGE_VERTEX | PIPE_BUFFER_USAGE_CONSTANT)) { /* Local buffer */ name = "gallium3d_local"; pool = dev->pools.gem; @@ -96,6 +123,12 @@ intel_be_buffer_create(struct pipe_winsys *winsys, } buffer->bo = drm_intel_bo_alloc(pool, name, size, alignment); + if (usage & I915_BUFFER_USAGE_SCANOUT) { + unsigned tiling = I915_TILING_X; + unsigned stride = 2048 * 4; /* TODO do something smarter here */ + drm_intel_bo_set_tiling(buffer->bo, &tiling, stride); + buffer->map_gtt = TRUE; + } if (!buffer->bo) goto err; @@ -142,6 +175,40 @@ err: return NULL; } +static struct pipe_buffer * +intel_be_surface_buffer_create(struct pipe_winsys *winsys, + unsigned width, unsigned height, + enum pipe_format format, + unsigned usage, + unsigned tex_usage, + unsigned *stride) +{ + struct pipe_format_block block; + unsigned buf_usage = 0; + unsigned buf_stride = 0; + unsigned buf_size = 0; + + pf_get_block(format, &block); + buf_stride = pf_get_stride(&block, width); + buf_stride = align(buf_stride, 64); + + if (tex_usage & PIPE_TEXTURE_USAGE_PRIMARY) { + /* TODO more checks */ + assert(buf_stride <= 2048*4); + assert(height % 8 == 0); + buf_stride = 2048 * 4; + buf_usage |= I915_BUFFER_USAGE_SCANOUT; + } + + buf_size = buf_stride * height; + *stride = buf_stride; + + return intel_be_buffer_create(winsys, + 0, + buf_usage, + buf_size); +} + boolean intel_be_get_texture_buffer(struct drm_api *api, struct pipe_texture *texture, @@ -225,6 +292,7 @@ intel_be_global_handle_from_buffer(struct drm_api *api, *handle = buf->flink; return TRUE; } + /* * Fence */ @@ -296,8 +364,8 @@ intel_be_init_device(struct intel_be_device *dev, int fd, unsigned id) dev->base.buffer_unmap = intel_be_buffer_unmap; dev->base.buffer_destroy = intel_be_buffer_destroy; - /* Not used anymore */ - dev->base.surface_buffer_create = NULL; + /* Used by softpipe */ + dev->base.surface_buffer_create = intel_be_surface_buffer_create; dev->base.fence_reference = intel_be_fence_refunref; dev->base.fence_signalled = intel_be_fence_signalled; @@ -308,6 +376,7 @@ intel_be_init_device(struct intel_be_device *dev, int fd, unsigned id) dev->pools.gem = drm_intel_bufmgr_gem_init(dev->fd, dev->max_batch_size); dev->softpipe = debug_get_bool_option("INTEL_SOFTPIPE", FALSE); + dev->dump_cmd = debug_get_bool_option("INTEL_DUMP_CMD", FALSE); return true; } diff --git a/src/gallium/winsys/drm/intel/gem/intel_be_device.h b/src/gallium/winsys/drm/intel/gem/intel_be_device.h index 56d95bd7fe..c397048f8c 100644 --- a/src/gallium/winsys/drm/intel/gem/intel_be_device.h +++ b/src/gallium/winsys/drm/intel/gem/intel_be_device.h @@ -19,6 +19,7 @@ struct intel_be_device struct pipe_winsys base; boolean softpipe; + boolean dump_cmd; int fd; /**< Drm file discriptor */ @@ -47,6 +48,10 @@ intel_be_init_device(struct intel_be_device *device, int fd, unsigned id); struct intel_be_buffer { struct pipe_buffer base; + void *ptr; + unsigned map_count; + boolean map_gtt; + drm_intel_bo *bo; boolean flinked; unsigned flink; diff --git a/src/gallium/winsys/drm/intel/xorg/Makefile b/src/gallium/winsys/drm/intel/xorg/Makefile index d51cca8d21..9e56853b02 100644 --- a/src/gallium/winsys/drm/intel/xorg/Makefile +++ b/src/gallium/winsys/drm/intel/xorg/Makefile @@ -19,6 +19,7 @@ LIBS = \ $(TOP)/src/gallium/state_trackers/xorg/libxorgtracker.a \ $(TOP)/src/gallium/winsys/drm/intel/gem/libinteldrm.a \ $(TOP)/src/gallium/drivers/i915simple/libi915simple.a \ + $(TOP)/src/gallium/drivers/trace/libtrace.a \ $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ $(GALLIUM_AUXILIARIES) diff --git a/src/gallium/winsys/egl_xlib/egl_xlib.c b/src/gallium/winsys/egl_xlib/egl_xlib.c index e1ddcae97b..f409a3fd6b 100644 --- a/src/gallium/winsys/egl_xlib/egl_xlib.c +++ b/src/gallium/winsys/egl_xlib/egl_xlib.c @@ -82,6 +82,7 @@ struct xlib_egl_surface { _EGLSurface Base; /**< base class */ + /* These are set for window surface */ Display *Dpy; /**< The X Display of the window */ Window Win; /**< The user-created window ID */ GC Gc; @@ -101,7 +102,7 @@ xlib_egl_driver(_EGLDriver *drv) } -static struct xlib_egl_surface * +static INLINE struct xlib_egl_surface * lookup_surface(EGLSurface surf) { _EGLSurface *surface = _eglLookupSurface(surf); @@ -109,10 +110,10 @@ lookup_surface(EGLSurface surf) } -static struct xlib_egl_context * -lookup_context(EGLContext surf) +static INLINE struct xlib_egl_context * +lookup_context(EGLContext ctx) { - _EGLContext *context = _eglLookupContext(surf); + _EGLContext *context = _eglLookupContext(ctx); return (struct xlib_egl_context *) context; } @@ -180,7 +181,9 @@ create_configs(_EGLDriver *drv, EGLDisplay dpy) SET_CONFIG_ATTRIB(config, EGL_NATIVE_RENDERABLE, EGL_FALSE); SET_CONFIG_ATTRIB(config, EGL_CONFORMANT, all_apis); SET_CONFIG_ATTRIB(config, EGL_RENDERABLE_TYPE, all_apis); - SET_CONFIG_ATTRIB(config, EGL_SURFACE_TYPE, EGL_WINDOW_BIT); + SET_CONFIG_ATTRIB(config, EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT); + SET_CONFIG_ATTRIB(config, EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE); + SET_CONFIG_ATTRIB(config, EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE); _eglAddConfig(disp, config); } @@ -264,7 +267,13 @@ static void check_and_update_buffer_size(struct xlib_egl_surface *surface) { uint width, height; - get_drawable_size(surface->Dpy, surface->Win, &width, &height); + if (surface->Base.Type == EGL_PBUFFER_BIT) { + width = surface->Base.Width; + height = surface->Base.Height; + } + else { + get_drawable_size(surface->Dpy, surface->Win, &width, &height); + } st_resize_framebuffer(surface->Framebuffer, width, height); surface->Base.Width = width; surface->Base.Height = height; @@ -281,6 +290,9 @@ display_surface(struct pipe_winsys *pws, XImage *ximage; void *data; + if (xsurf->Base.Type == EGL_PBUFFER_BIT) + return; + ximage = XCreateImage(xsurf->Dpy, xsurf->VisInfo.visual, xsurf->VisInfo.depth, @@ -382,7 +394,7 @@ xlib_eglDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx) struct xlib_egl_context *context = lookup_context(ctx); if (context) { _eglUnlinkContext(&context->Base); - if (!context->Base.IsBound) { + if (!_eglIsContextBound(&context->Base)) { /* API-dependent clean-up */ switch (context->Base.ClientAPI) { case EGL_OPENGL_ES_API: @@ -415,10 +427,14 @@ xlib_eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, struct xlib_egl_context *context = lookup_context(ctx); struct xlib_egl_surface *draw_surf = lookup_surface(draw); struct xlib_egl_surface *read_surf = lookup_surface(read); + struct st_context *oldctx = st_get_current(); if (!_eglMakeCurrent(drv, dpy, draw, read, context)) return EGL_FALSE; + /* Flush before switching context. Check client API? */ + if (oldctx) + st_flush(oldctx, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); st_make_current((context ? context->Context : NULL), (draw_surf ? draw_surf->Framebuffer : NULL), (read_surf ? read_surf->Framebuffer : NULL)); @@ -527,14 +543,92 @@ xlib_eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, } +static EGLSurface +xlib_eglCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, + const EGLint *attrib_list) +{ + struct xlib_egl_driver *xdrv = xlib_egl_driver(drv); + _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLConfig *conf = _eglLookupConfig(drv, dpy, config); + struct xlib_egl_surface *surf; + __GLcontextModes visual; + uint width, height; + EGLBoolean bind_texture; + + if (!disp) { + _eglError(EGL_BAD_DISPLAY, "eglCreatePbufferSurface"); + return EGL_NO_SURFACE; + } + if (!conf) { + _eglError(EGL_BAD_CONFIG, "eglCreatePbufferSurface"); + return EGL_NO_SURFACE; + } + + surf = CALLOC_STRUCT(xlib_egl_surface); + if (!surf) { + _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface"); + return EGL_NO_SURFACE; + } + + if (!_eglInitSurface(drv, &surf->Base, EGL_PBUFFER_BIT, + conf, attrib_list)) { + free(surf); + return EGL_NO_SURFACE; + } + if (surf->Base.Width < 0 || surf->Base.Height < 0) { + _eglError(EGL_BAD_PARAMETER, "eglCreatePbufferSurface"); + free(surf); + return EGL_NO_SURFACE; + } + + bind_texture = (surf->Base.TextureFormat != EGL_NO_TEXTURE); + width = (uint) surf->Base.Width; + height = (uint) surf->Base.Height; + if ((surf->Base.TextureTarget == EGL_NO_TEXTURE && bind_texture) || + (surf->Base.TextureTarget != EGL_NO_TEXTURE && !bind_texture)) { + _eglError(EGL_BAD_MATCH, "eglCreatePbufferSurface"); + free(surf); + return EGL_NO_SURFACE; + } + /* a framebuffer of zero width or height confuses st */ + if (width == 0 || height == 0) { + _eglError(EGL_BAD_MATCH, "eglCreatePbufferSurface"); + free(surf); + return EGL_NO_SURFACE; + } + /* no mipmap generation */ + if (surf->Base.MipmapTexture) { + _eglError(EGL_BAD_MATCH, "eglCreatePbufferSurface"); + free(surf); + return EGL_NO_SURFACE; + } + + surf->winsys = xdrv->winsys; + + _eglConfigToContextModesRec(conf, &visual); + + /* Create GL statetracker framebuffer */ + surf->Framebuffer = st_create_framebuffer(&visual, + choose_color_format(&visual), + choose_depth_format(&visual), + choose_stencil_format(&visual), + width, height, + (void *) surf); + st_resize_framebuffer(surf->Framebuffer, width, height); + + return _eglLinkSurface(&surf->Base, disp); +} + + static EGLBoolean xlib_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface) { struct xlib_egl_surface *surf = lookup_surface(surface); if (surf) { _eglUnlinkSurface(&surf->Base); - if (!surf->Base.IsBound) { - XFreeGC(surf->Dpy, surf->Gc); + if (!_eglIsSurfaceBound(&surf->Base)) { + if (surf->Base.Type != EGL_PBUFFER_BIT) + XFreeGC(surf->Dpy, surf->Gc); st_unreference_framebuffer(surf->Framebuffer); free(surf); } @@ -548,6 +642,86 @@ xlib_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface) static EGLBoolean +xlib_eglBindTexImage(_EGLDriver *drv, EGLDisplay dpy, + EGLSurface surface, EGLint buffer) +{ + struct xlib_egl_surface *xsurf = lookup_surface(surface); + struct xlib_egl_context *xctx; + struct pipe_surface *psurf; + enum pipe_format format; + int target; + + if (!xsurf || xsurf->Base.Type != EGL_PBUFFER_BIT) + return _eglError(EGL_BAD_SURFACE, "eglBindTexImage"); + if (buffer != EGL_BACK_BUFFER) + return _eglError(EGL_BAD_PARAMETER, "eglBindTexImage"); + if (xsurf->Base.BoundToTexture) + return _eglError(EGL_BAD_ACCESS, "eglBindTexImage"); + + /* this should be updated when choose_color_format is */ + switch (xsurf->Base.TextureFormat) { + case EGL_TEXTURE_RGB: + format = PIPE_FORMAT_R8G8B8_UNORM; + break; + case EGL_TEXTURE_RGBA: + format = PIPE_FORMAT_A8R8G8B8_UNORM; + break; + default: + return _eglError(EGL_BAD_MATCH, "eglBindTexImage"); + } + + switch (xsurf->Base.TextureTarget) { + case EGL_TEXTURE_2D: + target = ST_TEXTURE_2D; + break; + default: + return _eglError(EGL_BAD_MATCH, "eglBindTexImage"); + } + + /* flush properly */ + if (eglGetCurrentSurface(EGL_DRAW) == surface) { + xctx = lookup_context(eglGetCurrentContext()); + st_flush(xctx->Context, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, + NULL); + } + else if (_eglIsSurfaceBound(&xsurf->Base)) { + xctx = lookup_context(_eglGetContextHandle(xsurf->Base.Binding)); + if (xctx) + st_finish(xctx->Context); + } + + st_get_framebuffer_surface(xsurf->Framebuffer, ST_SURFACE_BACK_LEFT, + &psurf); + st_bind_texture_surface(psurf, target, xsurf->Base.MipmapLevel, format); + xsurf->Base.BoundToTexture = EGL_TRUE; + + return EGL_TRUE; +} + + +static EGLBoolean +xlib_eglReleaseTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, + EGLint buffer) +{ + struct xlib_egl_surface *xsurf = lookup_surface(surface); + struct pipe_surface *psurf; + + if (!xsurf || xsurf->Base.Type != EGL_PBUFFER_BIT || + !xsurf->Base.BoundToTexture) + return _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage"); + if (buffer != EGL_BACK_BUFFER) + return _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage"); + + st_get_framebuffer_surface(xsurf->Framebuffer, ST_SURFACE_BACK_LEFT, + &psurf); + st_unbind_texture_surface(psurf, ST_TEXTURE_2D, xsurf->Base.MipmapLevel); + xsurf->Base.BoundToTexture = EGL_FALSE; + + return EGL_TRUE; +} + + +static EGLBoolean xlib_eglSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw) { /* error checking step: */ @@ -631,7 +805,10 @@ _eglMain(_EGLDisplay *dpy, const char *args) xdrv->Base.API.CreateContext = xlib_eglCreateContext; xdrv->Base.API.DestroyContext = xlib_eglDestroyContext; xdrv->Base.API.CreateWindowSurface = xlib_eglCreateWindowSurface; + xdrv->Base.API.CreatePbufferSurface = xlib_eglCreatePbufferSurface; xdrv->Base.API.DestroySurface = xlib_eglDestroySurface; + xdrv->Base.API.BindTexImage = xlib_eglBindTexImage; + xdrv->Base.API.ReleaseTexImage = xlib_eglReleaseTexImage; xdrv->Base.API.MakeCurrent = xlib_eglMakeCurrent; xdrv->Base.API.SwapBuffers = xlib_eglSwapBuffers; diff --git a/src/gallium/winsys/egl_xlib/sw_winsys.c b/src/gallium/winsys/egl_xlib/sw_winsys.c index aa1bfa8e88..79ff2cc985 100644 --- a/src/gallium/winsys/egl_xlib/sw_winsys.c +++ b/src/gallium/winsys/egl_xlib/sw_winsys.c @@ -166,6 +166,7 @@ surface_buffer_create(struct pipe_winsys *winsys, unsigned width, unsigned height, enum pipe_format format, unsigned usage, + unsigned tex_usage, unsigned *stride) { const unsigned alignment = 64; diff --git a/src/gallium/winsys/xlib/xlib_brw_screen.c b/src/gallium/winsys/xlib/xlib_brw_screen.c index fe8dfff767..6f3861e2cd 100644 --- a/src/gallium/winsys/xlib/xlib_brw_screen.c +++ b/src/gallium/winsys/xlib/xlib_brw_screen.c @@ -249,6 +249,7 @@ aub_i915_surface_buffer_create(struct pipe_winsys *winsys, unsigned width, unsigned height, enum pipe_format format, unsigned usage, + unsigned tex_usage, unsigned *stride) { const unsigned alignment = 64; diff --git a/src/gallium/winsys/xlib/xlib_softpipe.c b/src/gallium/winsys/xlib/xlib_softpipe.c index 44b8464518..277e724d2a 100644 --- a/src/gallium/winsys/xlib/xlib_softpipe.c +++ b/src/gallium/winsys/xlib/xlib_softpipe.c @@ -375,6 +375,7 @@ xm_surface_buffer_create(struct pipe_winsys *winsys, unsigned width, unsigned height, enum pipe_format format, unsigned usage, + unsigned tex_usage, unsigned *stride) { const unsigned alignment = 64; diff --git a/src/glut/glx/win32_winproc.c b/src/glut/glx/win32_winproc.c index 4a9dc3781c..1b3a297828 100644 --- a/src/glut/glx/win32_winproc.c +++ b/src/glut/glx/win32_winproc.c @@ -548,8 +548,13 @@ __glutWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) window to be bigger than the screen, and smaller than 100x100 (although it doesn't seem to help the y minimum). */ minmax = (LPMINMAXINFO)lParam; +#if 0 + /* These two lines are disabled to fix incorrect handling of + * window maximization on Vista. See bug 23182. + */ minmax->ptMaxSize.x = __glutScreenWidth; minmax->ptMaxSize.y = __glutScreenHeight; +#endif minmax->ptMinTrackSize.x = 0; minmax->ptMinTrackSize.y = 0; minmax->ptMaxTrackSize.x = __glutScreenWidth + diff --git a/src/glx/x11/dri2.c b/src/glx/x11/dri2.c index ebb2985924..e144ed3e1f 100644 --- a/src/glx/x11/dri2.c +++ b/src/glx/x11/dri2.c @@ -52,320 +52,328 @@ static char dri2ExtensionName[] = DRI2_NAME; static XExtensionInfo *dri2Info; static XEXT_GENERATE_CLOSE_DISPLAY (DRI2CloseDisplay, dri2Info) + static /* const */ XExtensionHooks dri2ExtensionHooks = { - NULL, /* create_gc */ - NULL, /* copy_gc */ - NULL, /* flush_gc */ - NULL, /* free_gc */ - NULL, /* create_font */ - NULL, /* free_font */ - DRI2CloseDisplay, /* close_display */ - NULL, /* wire_to_event */ - NULL, /* event_to_wire */ - NULL, /* error */ - NULL, /* error_string */ + NULL, /* create_gc */ + NULL, /* copy_gc */ + NULL, /* flush_gc */ + NULL, /* free_gc */ + NULL, /* create_font */ + NULL, /* free_font */ + DRI2CloseDisplay, /* close_display */ + NULL, /* wire_to_event */ + NULL, /* event_to_wire */ + NULL, /* error */ + NULL, /* error_string */ }; -static XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay, dri2Info, - dri2ExtensionName, - &dri2ExtensionHooks, - 0, NULL) +static XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay, + dri2Info, + dri2ExtensionName, + &dri2ExtensionHooks, + 0, NULL) -Bool DRI2QueryExtension(Display *dpy, int *eventBase, int *errorBase) +Bool +DRI2QueryExtension(Display * dpy, int *eventBase, int *errorBase) { - XExtDisplayInfo *info = DRI2FindDisplay(dpy); + XExtDisplayInfo *info = DRI2FindDisplay(dpy); - if (XextHasExtension(info)) { - *eventBase = info->codes->first_event; - *errorBase = info->codes->first_error; - return True; - } + if (XextHasExtension(info)) { + *eventBase = info->codes->first_event; + *errorBase = info->codes->first_error; + return True; + } - return False; + return False; } -Bool DRI2QueryVersion(Display *dpy, int *major, int *minor) +Bool +DRI2QueryVersion(Display * dpy, int *major, int *minor) { - XExtDisplayInfo *info = DRI2FindDisplay (dpy); - xDRI2QueryVersionReply rep; - xDRI2QueryVersionReq *req; - - XextCheckExtension (dpy, info, dri2ExtensionName, False); - - LockDisplay(dpy); - GetReq(DRI2QueryVersion, req); - req->reqType = info->codes->major_opcode; - req->dri2ReqType = X_DRI2QueryVersion; - req->majorVersion = DRI2_MAJOR; - req->minorVersion = DRI2_MINOR; - if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { - UnlockDisplay(dpy); - SyncHandle(); - return False; - } - *major = rep.majorVersion; - *minor = rep.minorVersion; - UnlockDisplay(dpy); - SyncHandle(); - - return True; + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2QueryVersionReply rep; + xDRI2QueryVersionReq *req; + + XextCheckExtension(dpy, info, dri2ExtensionName, False); + + LockDisplay(dpy); + GetReq(DRI2QueryVersion, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2QueryVersion; + req->majorVersion = DRI2_MAJOR; + req->minorVersion = DRI2_MINOR; + if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + *major = rep.majorVersion; + *minor = rep.minorVersion; + UnlockDisplay(dpy); + SyncHandle(); + + return True; } -Bool DRI2Connect(Display *dpy, XID window, - char **driverName, char **deviceName) +Bool +DRI2Connect(Display * dpy, XID window, char **driverName, char **deviceName) { - XExtDisplayInfo *info = DRI2FindDisplay(dpy); - xDRI2ConnectReply rep; - xDRI2ConnectReq *req; - - XextCheckExtension (dpy, info, dri2ExtensionName, False); - - LockDisplay(dpy); - GetReq(DRI2Connect, req); - req->reqType = info->codes->major_opcode; - req->dri2ReqType = X_DRI2Connect; - req->window = window; - req->driverType = DRI2DriverDRI; - if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { - UnlockDisplay(dpy); - SyncHandle(); - return False; - } - - if (rep.driverNameLength == 0 && rep.deviceNameLength == 0) { - UnlockDisplay(dpy); - SyncHandle(); - return False; - } - - *driverName = Xmalloc(rep.driverNameLength + 1); - if (*driverName == NULL) { - _XEatData(dpy, - ((rep.driverNameLength + 3) & ~3) + - ((rep.deviceNameLength + 3) & ~3)); - UnlockDisplay(dpy); - SyncHandle(); - return False; - } - _XReadPad(dpy, *driverName, rep.driverNameLength); - (*driverName)[rep.driverNameLength] = '\0'; - - *deviceName = Xmalloc(rep.deviceNameLength + 1); - if (*deviceName == NULL) { - Xfree(*driverName); - _XEatData(dpy, ((rep.deviceNameLength + 3) & ~3)); - UnlockDisplay(dpy); - SyncHandle(); - return False; - } - _XReadPad(dpy, *deviceName, rep.deviceNameLength); - (*deviceName)[rep.deviceNameLength] = '\0'; - - UnlockDisplay(dpy); - SyncHandle(); - - return True; + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2ConnectReply rep; + xDRI2ConnectReq *req; + + XextCheckExtension(dpy, info, dri2ExtensionName, False); + + LockDisplay(dpy); + GetReq(DRI2Connect, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2Connect; + req->window = window; + req->driverType = DRI2DriverDRI; + if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + + if (rep.driverNameLength == 0 && rep.deviceNameLength == 0) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + + *driverName = Xmalloc(rep.driverNameLength + 1); + if (*driverName == NULL) { + _XEatData(dpy, + ((rep.driverNameLength + 3) & ~3) + + ((rep.deviceNameLength + 3) & ~3)); + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + _XReadPad(dpy, *driverName, rep.driverNameLength); + (*driverName)[rep.driverNameLength] = '\0'; + + *deviceName = Xmalloc(rep.deviceNameLength + 1); + if (*deviceName == NULL) { + Xfree(*driverName); + _XEatData(dpy, ((rep.deviceNameLength + 3) & ~3)); + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + _XReadPad(dpy, *deviceName, rep.deviceNameLength); + (*deviceName)[rep.deviceNameLength] = '\0'; + + UnlockDisplay(dpy); + SyncHandle(); + + return True; } -Bool DRI2Authenticate(Display *dpy, XID window, drm_magic_t magic) +Bool +DRI2Authenticate(Display * dpy, XID window, drm_magic_t magic) { - XExtDisplayInfo *info = DRI2FindDisplay(dpy); - xDRI2AuthenticateReq *req; - xDRI2AuthenticateReply rep; + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2AuthenticateReq *req; + xDRI2AuthenticateReply rep; - XextCheckExtension (dpy, info, dri2ExtensionName, False); + XextCheckExtension(dpy, info, dri2ExtensionName, False); - LockDisplay(dpy); - GetReq(DRI2Authenticate, req); - req->reqType = info->codes->major_opcode; - req->dri2ReqType = X_DRI2Authenticate; - req->window = window; - req->magic = magic; + LockDisplay(dpy); + GetReq(DRI2Authenticate, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2Authenticate; + req->window = window; + req->magic = magic; - if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { - UnlockDisplay(dpy); - SyncHandle(); - return False; - } + if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } - UnlockDisplay(dpy); - SyncHandle(); + UnlockDisplay(dpy); + SyncHandle(); - return rep.authenticated; + return rep.authenticated; } -void DRI2CreateDrawable(Display *dpy, XID drawable) +void +DRI2CreateDrawable(Display * dpy, XID drawable) { - XExtDisplayInfo *info = DRI2FindDisplay(dpy); - xDRI2CreateDrawableReq *req; - - XextSimpleCheckExtension (dpy, info, dri2ExtensionName); - - LockDisplay(dpy); - GetReq(DRI2CreateDrawable, req); - req->reqType = info->codes->major_opcode; - req->dri2ReqType = X_DRI2CreateDrawable; - req->drawable = drawable; - UnlockDisplay(dpy); - SyncHandle(); + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2CreateDrawableReq *req; + + XextSimpleCheckExtension(dpy, info, dri2ExtensionName); + + LockDisplay(dpy); + GetReq(DRI2CreateDrawable, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2CreateDrawable; + req->drawable = drawable; + UnlockDisplay(dpy); + SyncHandle(); } -void DRI2DestroyDrawable(Display *dpy, XID drawable) +void +DRI2DestroyDrawable(Display * dpy, XID drawable) { - XExtDisplayInfo *info = DRI2FindDisplay(dpy); - xDRI2DestroyDrawableReq *req; + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2DestroyDrawableReq *req; - XextSimpleCheckExtension (dpy, info, dri2ExtensionName); + XextSimpleCheckExtension(dpy, info, dri2ExtensionName); - XSync(dpy, False); + XSync(dpy, False); - LockDisplay(dpy); - GetReq(DRI2DestroyDrawable, req); - req->reqType = info->codes->major_opcode; - req->dri2ReqType = X_DRI2DestroyDrawable; - req->drawable = drawable; - UnlockDisplay(dpy); - SyncHandle(); + LockDisplay(dpy); + GetReq(DRI2DestroyDrawable, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2DestroyDrawable; + req->drawable = drawable; + UnlockDisplay(dpy); + SyncHandle(); } -DRI2Buffer *DRI2GetBuffers(Display *dpy, XID drawable, - int *width, int *height, - unsigned int *attachments, int count, - int *outCount) +DRI2Buffer * +DRI2GetBuffers(Display * dpy, XID drawable, + int *width, int *height, + unsigned int *attachments, int count, int *outCount) { - XExtDisplayInfo *info = DRI2FindDisplay(dpy); - xDRI2GetBuffersReply rep; - xDRI2GetBuffersReq *req; - DRI2Buffer *buffers; - xDRI2Buffer repBuffer; - CARD32 *p; - int i; - - XextCheckExtension (dpy, info, dri2ExtensionName, False); - - LockDisplay(dpy); - GetReqExtra(DRI2GetBuffers, count * 4, req); - req->reqType = info->codes->major_opcode; - req->dri2ReqType = X_DRI2GetBuffers; - req->drawable = drawable; - req->count = count; - p = (CARD32 *) &req[1]; - for (i = 0; i < count; i++) - p[i] = attachments[i]; - - if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { - UnlockDisplay(dpy); - SyncHandle(); - return NULL; - } - - *width = rep.width; - *height = rep.height; - *outCount = rep.count; - - buffers = Xmalloc(rep.count * sizeof buffers[0]); - if (buffers == NULL) { - _XEatData(dpy, rep.count * sizeof repBuffer); - UnlockDisplay(dpy); - SyncHandle(); - return NULL; - } - - for (i = 0; i < rep.count; i++) { - _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer); - buffers[i].attachment = repBuffer.attachment; - buffers[i].name = repBuffer.name; - buffers[i].pitch = repBuffer.pitch; - buffers[i].cpp = repBuffer.cpp; - buffers[i].flags = repBuffer.flags; - } - - UnlockDisplay(dpy); - SyncHandle(); - - return buffers; + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2GetBuffersReply rep; + xDRI2GetBuffersReq *req; + DRI2Buffer *buffers; + xDRI2Buffer repBuffer; + CARD32 *p; + int i; + + XextCheckExtension(dpy, info, dri2ExtensionName, False); + + LockDisplay(dpy); + GetReqExtra(DRI2GetBuffers, count * 4, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2GetBuffers; + req->drawable = drawable; + req->count = count; + p = (CARD32 *) & req[1]; + for (i = 0; i < count; i++) + p[i] = attachments[i]; + + if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return NULL; + } + + *width = rep.width; + *height = rep.height; + *outCount = rep.count; + + buffers = Xmalloc(rep.count * sizeof buffers[0]); + if (buffers == NULL) { + _XEatData(dpy, rep.count * sizeof repBuffer); + UnlockDisplay(dpy); + SyncHandle(); + return NULL; + } + + for (i = 0; i < rep.count; i++) { + _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer); + buffers[i].attachment = repBuffer.attachment; + buffers[i].name = repBuffer.name; + buffers[i].pitch = repBuffer.pitch; + buffers[i].cpp = repBuffer.cpp; + buffers[i].flags = repBuffer.flags; + } + + UnlockDisplay(dpy); + SyncHandle(); + + return buffers; } -DRI2Buffer *DRI2GetBuffersWithFormat(Display *dpy, XID drawable, - int *width, int *height, - unsigned int *attachments, int count, - int *outCount) +DRI2Buffer * +DRI2GetBuffersWithFormat(Display * dpy, XID drawable, + int *width, int *height, + unsigned int *attachments, int count, int *outCount) { - XExtDisplayInfo *info = DRI2FindDisplay(dpy); - xDRI2GetBuffersReply rep; - xDRI2GetBuffersReq *req; - DRI2Buffer *buffers; - xDRI2Buffer repBuffer; - CARD32 *p; - int i; - - XextCheckExtension (dpy, info, dri2ExtensionName, False); - - LockDisplay(dpy); - GetReqExtra(DRI2GetBuffers, count * (4 * 2), req); - req->reqType = info->codes->major_opcode; - req->dri2ReqType = X_DRI2GetBuffersWithFormat; - req->drawable = drawable; - req->count = count; - p = (CARD32 *) &req[1]; - for (i = 0; i < (count * 2); i++) - p[i] = attachments[i]; - - if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { - UnlockDisplay(dpy); - SyncHandle(); - return NULL; - } - - *width = rep.width; - *height = rep.height; - *outCount = rep.count; - - buffers = Xmalloc(rep.count * sizeof buffers[0]); - if (buffers == NULL) { - _XEatData(dpy, rep.count * sizeof repBuffer); - UnlockDisplay(dpy); - SyncHandle(); - return NULL; - } - - for (i = 0; i < rep.count; i++) { - _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer); - buffers[i].attachment = repBuffer.attachment; - buffers[i].name = repBuffer.name; - buffers[i].pitch = repBuffer.pitch; - buffers[i].cpp = repBuffer.cpp; - buffers[i].flags = repBuffer.flags; - } - - UnlockDisplay(dpy); - SyncHandle(); - - return buffers; + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2GetBuffersReply rep; + xDRI2GetBuffersReq *req; + DRI2Buffer *buffers; + xDRI2Buffer repBuffer; + CARD32 *p; + int i; + + XextCheckExtension(dpy, info, dri2ExtensionName, False); + + LockDisplay(dpy); + GetReqExtra(DRI2GetBuffers, count * (4 * 2), req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2GetBuffersWithFormat; + req->drawable = drawable; + req->count = count; + p = (CARD32 *) & req[1]; + for (i = 0; i < (count * 2); i++) + p[i] = attachments[i]; + + if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return NULL; + } + + *width = rep.width; + *height = rep.height; + *outCount = rep.count; + + buffers = Xmalloc(rep.count * sizeof buffers[0]); + if (buffers == NULL) { + _XEatData(dpy, rep.count * sizeof repBuffer); + UnlockDisplay(dpy); + SyncHandle(); + return NULL; + } + + for (i = 0; i < rep.count; i++) { + _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer); + buffers[i].attachment = repBuffer.attachment; + buffers[i].name = repBuffer.name; + buffers[i].pitch = repBuffer.pitch; + buffers[i].cpp = repBuffer.cpp; + buffers[i].flags = repBuffer.flags; + } + + UnlockDisplay(dpy); + SyncHandle(); + + return buffers; } -void DRI2CopyRegion(Display *dpy, XID drawable, XserverRegion region, - CARD32 dest, CARD32 src) +void +DRI2CopyRegion(Display * dpy, XID drawable, XserverRegion region, + CARD32 dest, CARD32 src) { - XExtDisplayInfo *info = DRI2FindDisplay(dpy); - xDRI2CopyRegionReq *req; - xDRI2CopyRegionReply rep; + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2CopyRegionReq *req; + xDRI2CopyRegionReply rep; - XextSimpleCheckExtension (dpy, info, dri2ExtensionName); + XextSimpleCheckExtension(dpy, info, dri2ExtensionName); - LockDisplay(dpy); - GetReq(DRI2CopyRegion, req); - req->reqType = info->codes->major_opcode; - req->dri2ReqType = X_DRI2CopyRegion; - req->drawable = drawable; - req->region = region; - req->dest = dest; - req->src = src; + LockDisplay(dpy); + GetReq(DRI2CopyRegion, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2CopyRegion; + req->drawable = drawable; + req->region = region; + req->dest = dest; + req->src = src; - _XReply(dpy, (xReply *)&rep, 0, xFalse); + _XReply(dpy, (xReply *) & rep, 0, xFalse); - UnlockDisplay(dpy); - SyncHandle(); + UnlockDisplay(dpy); + SyncHandle(); } diff --git a/src/glx/x11/dri2.h b/src/glx/x11/dri2.h index b0e61f80d7..a6fe66e136 100644 --- a/src/glx/x11/dri2.h +++ b/src/glx/x11/dri2.h @@ -36,45 +36,53 @@ #include <X11/extensions/Xfixes.h> #include <X11/extensions/dri2tokens.h> -typedef struct { - unsigned int attachment; - unsigned int name; - unsigned int pitch; - unsigned int cpp; - unsigned int flags; +typedef struct +{ + unsigned int attachment; + unsigned int name; + unsigned int pitch; + unsigned int cpp; + unsigned int flags; } DRI2Buffer; extern Bool -DRI2QueryExtension(Display *display, int *eventBase, int *errorBase); +DRI2QueryExtension(Display * display, int *eventBase, int *errorBase); + extern Bool -DRI2QueryVersion(Display *display, int *major, int *minor); +DRI2QueryVersion(Display * display, int *major, int *minor); + extern Bool -DRI2Connect(Display *display, XID window, - char **driverName, char **deviceName); +DRI2Connect(Display * display, XID window, + char **driverName, char **deviceName); + extern Bool -DRI2Authenticate(Display *display, XID window, drm_magic_t magic); +DRI2Authenticate(Display * display, XID window, drm_magic_t magic); + extern void -DRI2CreateDrawable(Display *display, XID drawable); +DRI2CreateDrawable(Display * display, XID drawable); + extern void -DRI2DestroyDrawable(Display *display, XID handle); -extern DRI2Buffer * -DRI2GetBuffers(Display *dpy, XID drawable, - int *width, int *height, - unsigned int *attachments, int count, - int *outCount); +DRI2DestroyDrawable(Display * display, XID handle); + +extern DRI2Buffer* +DRI2GetBuffers(Display * dpy, XID drawable, + int *width, int *height, + unsigned int *attachments, int count, + int *outCount); /** * \note * This function is only supported with DRI2 version 1.1 or later. */ -extern DRI2Buffer * -DRI2GetBuffersWithFormat(Display *dpy, XID drawable, - int *width, int *height, - unsigned int *attachments, int count, - int *outCount); +extern DRI2Buffer* +DRI2GetBuffersWithFormat(Display * dpy, XID drawable, + int *width, int *height, + unsigned int *attachments, + int count, int *outCount); extern void -DRI2CopyRegion(Display *dpy, XID drawable, XserverRegion region, - CARD32 dest, CARD32 src); +DRI2CopyRegion(Display * dpy, XID drawable, + XserverRegion region, + CARD32 dest, CARD32 src); #endif diff --git a/src/glx/x11/dri2_glx.c b/src/glx/x11/dri2_glx.c index 54add049ff..d5d5a07fee 100644 --- a/src/glx/x11/dri2_glx.c +++ b/src/glx/x11/dri2_glx.c @@ -54,249 +54,260 @@ typedef struct __GLXDRIdisplayPrivateRec __GLXDRIdisplayPrivate; typedef struct __GLXDRIcontextPrivateRec __GLXDRIcontextPrivate; typedef struct __GLXDRIdrawablePrivateRec __GLXDRIdrawablePrivate; -struct __GLXDRIdisplayPrivateRec { - __GLXDRIdisplay base; +struct __GLXDRIdisplayPrivateRec +{ + __GLXDRIdisplay base; - /* + /* ** XFree86-DRI version information */ - int driMajor; - int driMinor; - int driPatch; + int driMajor; + int driMinor; + int driPatch; }; -struct __GLXDRIcontextPrivateRec { - __GLXDRIcontext base; - __DRIcontext *driContext; - __GLXscreenConfigs *psc; +struct __GLXDRIcontextPrivateRec +{ + __GLXDRIcontext base; + __DRIcontext *driContext; + __GLXscreenConfigs *psc; }; -struct __GLXDRIdrawablePrivateRec { - __GLXDRIdrawable base; - __DRIbuffer buffers[5]; - int bufferCount; - int width, height; - int have_back; - int have_fake_front; +struct __GLXDRIdrawablePrivateRec +{ + __GLXDRIdrawable base; + __DRIbuffer buffers[5]; + int bufferCount; + int width, height; + int have_back; + int have_fake_front; }; -static void dri2WaitX(__GLXDRIdrawable *pdraw); +static void dri2WaitX(__GLXDRIdrawable * pdraw); -static void dri2DestroyContext(__GLXDRIcontext *context, - __GLXscreenConfigs *psc, Display *dpy) +static void +dri2DestroyContext(__GLXDRIcontext * context, + __GLXscreenConfigs * psc, Display * dpy) { - __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context; - const __DRIcoreExtension *core = pcp->psc->core; + __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context; + const __DRIcoreExtension *core = pcp->psc->core; - (*core->destroyContext)(pcp->driContext); + (*core->destroyContext) (pcp->driContext); - Xfree(pcp); + Xfree(pcp); } -static Bool dri2BindContext(__GLXDRIcontext *context, - __GLXDRIdrawable *draw, __GLXDRIdrawable *read) +static Bool +dri2BindContext(__GLXDRIcontext * context, + __GLXDRIdrawable * draw, __GLXDRIdrawable * read) { - __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context; - const __DRIcoreExtension *core = pcp->psc->core; + __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context; + const __DRIcoreExtension *core = pcp->psc->core; - return (*core->bindContext)(pcp->driContext, - draw->driDrawable, - read->driDrawable); + return (*core->bindContext) (pcp->driContext, + draw->driDrawable, read->driDrawable); } -static void dri2UnbindContext(__GLXDRIcontext *context) +static void +dri2UnbindContext(__GLXDRIcontext * context) { - __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context; - const __DRIcoreExtension *core = pcp->psc->core; + __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context; + const __DRIcoreExtension *core = pcp->psc->core; - (*core->unbindContext)(pcp->driContext); + (*core->unbindContext) (pcp->driContext); } -static __GLXDRIcontext *dri2CreateContext(__GLXscreenConfigs *psc, - const __GLcontextModes *mode, - GLXContext gc, - GLXContext shareList, int renderType) +static __GLXDRIcontext * +dri2CreateContext(__GLXscreenConfigs * psc, + const __GLcontextModes * mode, + GLXContext gc, GLXContext shareList, int renderType) { - __GLXDRIcontextPrivate *pcp, *pcp_shared; - __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) mode; - __DRIcontext *shared = NULL; - - if (shareList) { - pcp_shared = (__GLXDRIcontextPrivate *) shareList->driContext; - shared = pcp_shared->driContext; - } - - pcp = Xmalloc(sizeof *pcp); - if (pcp == NULL) - return NULL; - - pcp->psc = psc; - pcp->driContext = - (*psc->dri2->createNewContext)(psc->__driScreen, - config->driConfig, shared, pcp); - gc->__driContext = pcp->driContext; - - if (pcp->driContext == NULL) { - Xfree(pcp); - return NULL; - } - - pcp->base.destroyContext = dri2DestroyContext; - pcp->base.bindContext = dri2BindContext; - pcp->base.unbindContext = dri2UnbindContext; - - return &pcp->base; + __GLXDRIcontextPrivate *pcp, *pcp_shared; + __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) mode; + __DRIcontext *shared = NULL; + + if (shareList) { + pcp_shared = (__GLXDRIcontextPrivate *) shareList->driContext; + shared = pcp_shared->driContext; + } + + pcp = Xmalloc(sizeof *pcp); + if (pcp == NULL) + return NULL; + + pcp->psc = psc; + pcp->driContext = + (*psc->dri2->createNewContext) (psc->__driScreen, + config->driConfig, shared, pcp); + gc->__driContext = pcp->driContext; + + if (pcp->driContext == NULL) { + Xfree(pcp); + return NULL; + } + + pcp->base.destroyContext = dri2DestroyContext; + pcp->base.bindContext = dri2BindContext; + pcp->base.unbindContext = dri2UnbindContext; + + return &pcp->base; } -static void dri2DestroyDrawable(__GLXDRIdrawable *pdraw) +static void +dri2DestroyDrawable(__GLXDRIdrawable * pdraw) { - const __DRIcoreExtension *core = pdraw->psc->core; + const __DRIcoreExtension *core = pdraw->psc->core; - (*core->destroyDrawable)(pdraw->driDrawable); - DRI2DestroyDrawable(pdraw->psc->dpy, pdraw->drawable); - Xfree(pdraw); + (*core->destroyDrawable) (pdraw->driDrawable); + DRI2DestroyDrawable(pdraw->psc->dpy, pdraw->drawable); + Xfree(pdraw); } -static __GLXDRIdrawable *dri2CreateDrawable(__GLXscreenConfigs *psc, - XID xDrawable, - GLXDrawable drawable, - const __GLcontextModes *modes) +static __GLXDRIdrawable * +dri2CreateDrawable(__GLXscreenConfigs * psc, + XID xDrawable, + GLXDrawable drawable, const __GLcontextModes * modes) { - __GLXDRIdrawablePrivate *pdraw; - __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes; + __GLXDRIdrawablePrivate *pdraw; + __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes; - pdraw = Xmalloc(sizeof(*pdraw)); - if (!pdraw) - return NULL; + pdraw = Xmalloc(sizeof(*pdraw)); + if (!pdraw) + return NULL; - pdraw->base.destroyDrawable = dri2DestroyDrawable; - pdraw->base.xDrawable = xDrawable; - pdraw->base.drawable = drawable; - pdraw->base.psc = psc; - pdraw->bufferCount = 0; + pdraw->base.destroyDrawable = dri2DestroyDrawable; + pdraw->base.xDrawable = xDrawable; + pdraw->base.drawable = drawable; + pdraw->base.psc = psc; + pdraw->bufferCount = 0; - DRI2CreateDrawable(psc->dpy, xDrawable); + DRI2CreateDrawable(psc->dpy, xDrawable); - /* Create a new drawable */ - pdraw->base.driDrawable = - (*psc->dri2->createNewDrawable)(psc->__driScreen, - config->driConfig, pdraw); + /* Create a new drawable */ + pdraw->base.driDrawable = + (*psc->dri2->createNewDrawable) (psc->__driScreen, + config->driConfig, pdraw); - if (!pdraw->base.driDrawable) { - DRI2DestroyDrawable(psc->dpy, drawable); - Xfree(pdraw); - return NULL; - } + if (!pdraw->base.driDrawable) { + DRI2DestroyDrawable(psc->dpy, drawable); + Xfree(pdraw); + return NULL; + } - return &pdraw->base; + return &pdraw->base; } -static void dri2CopySubBuffer(__GLXDRIdrawable *pdraw, - int x, int y, int width, int height) +static void +dri2CopySubBuffer(__GLXDRIdrawable * pdraw, + int x, int y, int width, int height) { - __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; - XRectangle xrect; - XserverRegion region; + __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; + XRectangle xrect; + XserverRegion region; - /* Check we have the right attachments */ - if (!priv->have_back) - return; + /* Check we have the right attachments */ + if (!priv->have_back) + return; - xrect.x = x; - xrect.y = priv->height - y - height; - xrect.width = width; - xrect.height = height; + xrect.x = x; + xrect.y = priv->height - y - height; + xrect.width = width; + xrect.height = height; #ifdef __DRI2_FLUSH - if (pdraw->psc->f) - (*pdraw->psc->f->flush)(pdraw->driDrawable); + if (pdraw->psc->f) + (*pdraw->psc->f->flush) (pdraw->driDrawable); #endif - region = XFixesCreateRegion(pdraw->psc->dpy, &xrect, 1); - /* should get a fence ID back from here at some point */ - DRI2CopyRegion(pdraw->psc->dpy, pdraw->drawable, region, - DRI2BufferFrontLeft, DRI2BufferBackLeft); - XFixesDestroyRegion(pdraw->psc->dpy, region); + region = XFixesCreateRegion(pdraw->psc->dpy, &xrect, 1); + /* should get a fence ID back from here at some point */ + DRI2CopyRegion(pdraw->psc->dpy, pdraw->drawable, region, + DRI2BufferFrontLeft, DRI2BufferBackLeft); + XFixesDestroyRegion(pdraw->psc->dpy, region); - /* Refresh the fake front (if present) after we just damaged the real - * front. - */ - dri2WaitX(pdraw); + /* Refresh the fake front (if present) after we just damaged the real + * front. + */ + dri2WaitX(pdraw); } -static void dri2SwapBuffers(__GLXDRIdrawable *pdraw) +static void +dri2SwapBuffers(__GLXDRIdrawable * pdraw) { - __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; + __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; - dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height); + dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height); } -static void dri2WaitX(__GLXDRIdrawable *pdraw) +static void +dri2WaitX(__GLXDRIdrawable * pdraw) { - __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; - XRectangle xrect; - XserverRegion region; + __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; + XRectangle xrect; + XserverRegion region; - /* Check we have the right attachments */ - if (!priv->have_fake_front) - return; + /* Check we have the right attachments */ + if (!priv->have_fake_front) + return; - xrect.x = 0; - xrect.y = 0; - xrect.width = priv->width; - xrect.height = priv->height; + xrect.x = 0; + xrect.y = 0; + xrect.width = priv->width; + xrect.height = priv->height; #ifdef __DRI2_FLUSH - if (pdraw->psc->f) - (*pdraw->psc->f->flush)(pdraw->driDrawable); + if (pdraw->psc->f) + (*pdraw->psc->f->flush) (pdraw->driDrawable); #endif - region = XFixesCreateRegion(pdraw->psc->dpy, &xrect, 1); - DRI2CopyRegion(pdraw->psc->dpy, pdraw->drawable, region, - DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft); - XFixesDestroyRegion(pdraw->psc->dpy, region); + region = XFixesCreateRegion(pdraw->psc->dpy, &xrect, 1); + DRI2CopyRegion(pdraw->psc->dpy, pdraw->drawable, region, + DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft); + XFixesDestroyRegion(pdraw->psc->dpy, region); } -static void dri2WaitGL(__GLXDRIdrawable *pdraw) +static void +dri2WaitGL(__GLXDRIdrawable * pdraw) { - __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; - XRectangle xrect; - XserverRegion region; + __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; + XRectangle xrect; + XserverRegion region; - if (!priv->have_fake_front) - return; + if (!priv->have_fake_front) + return; - xrect.x = 0; - xrect.y = 0; - xrect.width = priv->width; - xrect.height = priv->height; + xrect.x = 0; + xrect.y = 0; + xrect.width = priv->width; + xrect.height = priv->height; #ifdef __DRI2_FLUSH - if (pdraw->psc->f) - (*pdraw->psc->f->flush)(pdraw->driDrawable); + if (pdraw->psc->f) + (*pdraw->psc->f->flush) (pdraw->driDrawable); #endif - region = XFixesCreateRegion(pdraw->psc->dpy, &xrect, 1); - DRI2CopyRegion(pdraw->psc->dpy, pdraw->drawable, region, - DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft); - XFixesDestroyRegion(pdraw->psc->dpy, region); + region = XFixesCreateRegion(pdraw->psc->dpy, &xrect, 1); + DRI2CopyRegion(pdraw->psc->dpy, pdraw->drawable, region, + DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft); + XFixesDestroyRegion(pdraw->psc->dpy, region); } -static void dri2FlushFrontBuffer(__DRIdrawable *driDrawable, - void *loaderPrivate) +static void +dri2FlushFrontBuffer(__DRIdrawable * driDrawable, void *loaderPrivate) { - (void) driDrawable; - dri2WaitGL((__GLXDRIdrawable *) loaderPrivate); + (void) driDrawable; + dri2WaitGL((__GLXDRIdrawable *) loaderPrivate); } -static void dri2DestroyScreen(__GLXscreenConfigs *psc) +static void +dri2DestroyScreen(__GLXscreenConfigs * psc) { - /* Free the direct rendering per screen data */ - (*psc->core->destroyScreen)(psc->__driScreen); - close(psc->fd); - psc->__driScreen = NULL; + /* Free the direct rendering per screen data */ + (*psc->core->destroyScreen) (psc->__driScreen); + close(psc->fd); + psc->__driScreen = NULL; } /** @@ -306,221 +317,222 @@ static void dri2DestroyScreen(__GLXscreenConfigs *psc) * \c DRI2GetBuffers or \c DRI2GetBuffersWithFormat. */ static void -process_buffers(__GLXDRIdrawablePrivate *pdraw, DRI2Buffer *buffers, - unsigned count) +process_buffers(__GLXDRIdrawablePrivate * pdraw, DRI2Buffer * buffers, + unsigned count) { - int i; - - pdraw->bufferCount = count; - pdraw->have_fake_front = 0; - pdraw->have_back = 0; - - /* This assumes the DRI2 buffer attachment tokens matches the - * __DRIbuffer tokens. */ - for (i = 0; i < count; i++) { - pdraw->buffers[i].attachment = buffers[i].attachment; - pdraw->buffers[i].name = buffers[i].name; - pdraw->buffers[i].pitch = buffers[i].pitch; - pdraw->buffers[i].cpp = buffers[i].cpp; - pdraw->buffers[i].flags = buffers[i].flags; - if (pdraw->buffers[i].attachment == __DRI_BUFFER_FAKE_FRONT_LEFT) - pdraw->have_fake_front = 1; - if (pdraw->buffers[i].attachment == __DRI_BUFFER_BACK_LEFT) - pdraw->have_back = 1; - } + int i; + + pdraw->bufferCount = count; + pdraw->have_fake_front = 0; + pdraw->have_back = 0; + + /* This assumes the DRI2 buffer attachment tokens matches the + * __DRIbuffer tokens. */ + for (i = 0; i < count; i++) { + pdraw->buffers[i].attachment = buffers[i].attachment; + pdraw->buffers[i].name = buffers[i].name; + pdraw->buffers[i].pitch = buffers[i].pitch; + pdraw->buffers[i].cpp = buffers[i].cpp; + pdraw->buffers[i].flags = buffers[i].flags; + if (pdraw->buffers[i].attachment == __DRI_BUFFER_FAKE_FRONT_LEFT) + pdraw->have_fake_front = 1; + if (pdraw->buffers[i].attachment == __DRI_BUFFER_BACK_LEFT) + pdraw->have_back = 1; + } } static __DRIbuffer * -dri2GetBuffers(__DRIdrawable *driDrawable, - int *width, int *height, - unsigned int *attachments, int count, - int *out_count, void *loaderPrivate) +dri2GetBuffers(__DRIdrawable * driDrawable, + int *width, int *height, + unsigned int *attachments, int count, + int *out_count, void *loaderPrivate) { - __GLXDRIdrawablePrivate *pdraw = loaderPrivate; - DRI2Buffer *buffers; + __GLXDRIdrawablePrivate *pdraw = loaderPrivate; + DRI2Buffer *buffers; - buffers = DRI2GetBuffers(pdraw->base.psc->dpy, pdraw->base.xDrawable, - width, height, attachments, count, out_count); - if (buffers == NULL) - return NULL; + buffers = DRI2GetBuffers(pdraw->base.psc->dpy, pdraw->base.xDrawable, + width, height, attachments, count, out_count); + if (buffers == NULL) + return NULL; - pdraw->width = *width; - pdraw->height = *height; - process_buffers(pdraw, buffers, *out_count); + pdraw->width = *width; + pdraw->height = *height; + process_buffers(pdraw, buffers, *out_count); - Xfree(buffers); + Xfree(buffers); - return pdraw->buffers; + return pdraw->buffers; } static __DRIbuffer * -dri2GetBuffersWithFormat(__DRIdrawable *driDrawable, - int *width, int *height, - unsigned int *attachments, int count, - int *out_count, void *loaderPrivate) +dri2GetBuffersWithFormat(__DRIdrawable * driDrawable, + int *width, int *height, + unsigned int *attachments, int count, + int *out_count, void *loaderPrivate) { - __GLXDRIdrawablePrivate *pdraw = loaderPrivate; - DRI2Buffer *buffers; + __GLXDRIdrawablePrivate *pdraw = loaderPrivate; + DRI2Buffer *buffers; - buffers = DRI2GetBuffersWithFormat(pdraw->base.psc->dpy, - pdraw->base.xDrawable, - width, height, attachments, - count, out_count); - if (buffers == NULL) - return NULL; + buffers = DRI2GetBuffersWithFormat(pdraw->base.psc->dpy, + pdraw->base.xDrawable, + width, height, attachments, + count, out_count); + if (buffers == NULL) + return NULL; - pdraw->width = *width; - pdraw->height = *height; - process_buffers(pdraw, buffers, *out_count); + pdraw->width = *width; + pdraw->height = *height; + process_buffers(pdraw, buffers, *out_count); - Xfree(buffers); + Xfree(buffers); - return pdraw->buffers; + return pdraw->buffers; } static const __DRIdri2LoaderExtension dri2LoaderExtension = { - { __DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION }, - dri2GetBuffers, - dri2FlushFrontBuffer, - dri2GetBuffersWithFormat, + {__DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION}, + dri2GetBuffers, + dri2FlushFrontBuffer, + dri2GetBuffersWithFormat, }; static const __DRIdri2LoaderExtension dri2LoaderExtension_old = { - { __DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION }, - dri2GetBuffers, - dri2FlushFrontBuffer, - NULL, + {__DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION}, + dri2GetBuffers, + dri2FlushFrontBuffer, + NULL, }; static const __DRIextension *loader_extensions[] = { - &dri2LoaderExtension.base, - &systemTimeExtension.base, - NULL + &dri2LoaderExtension.base, + &systemTimeExtension.base, + NULL }; static const __DRIextension *loader_extensions_old[] = { - &dri2LoaderExtension_old.base, - &systemTimeExtension.base, - NULL + &dri2LoaderExtension_old.base, + &systemTimeExtension.base, + NULL }; -static __GLXDRIscreen *dri2CreateScreen(__GLXscreenConfigs *psc, int screen, - __GLXdisplayPrivate *priv) +static __GLXDRIscreen * +dri2CreateScreen(__GLXscreenConfigs * psc, int screen, + __GLXdisplayPrivate * priv) { - const __DRIconfig **driver_configs; - const __DRIextension **extensions; - const __GLXDRIdisplayPrivate *const pdp = (__GLXDRIdisplayPrivate *) + const __DRIconfig **driver_configs; + const __DRIextension **extensions; + const __GLXDRIdisplayPrivate *const pdp = (__GLXDRIdisplayPrivate *) priv->dri2Display; - __GLXDRIscreen *psp; - char *driverName, *deviceName; - drm_magic_t magic; - int i; - - psp = Xmalloc(sizeof *psp); - if (psp == NULL) - return NULL; - - /* Initialize per screen dynamic client GLX extensions */ - psc->ext_list_first_time = GL_TRUE; - - if (!DRI2Connect(psc->dpy, RootWindow(psc->dpy, screen), - &driverName, &deviceName)) - return NULL; - - psc->driver = driOpenDriver(driverName); - if (psc->driver == NULL) { - ErrorMessageF("driver pointer missing\n"); - goto handle_error; - } - - extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS); - if (extensions == NULL) { - ErrorMessageF("driver exports no extensions (%s)\n", dlerror()); - goto handle_error; - } - - for (i = 0; extensions[i]; i++) { - if (strcmp(extensions[i]->name, __DRI_CORE) == 0) - psc->core = (__DRIcoreExtension *) extensions[i]; - if (strcmp(extensions[i]->name, __DRI_DRI2) == 0) - psc->dri2 = (__DRIdri2Extension *) extensions[i]; - } - - if (psc->core == NULL || psc->dri2 == NULL) { - ErrorMessageF("core dri or dri2 extension not found\n"); - goto handle_error; - } - - psc->fd = open(deviceName, O_RDWR); - if (psc->fd < 0) { - ErrorMessageF("failed to open drm device: %s\n", strerror(errno)); - return NULL; - } - - if (drmGetMagic(psc->fd, &magic)) { - ErrorMessageF("failed to get magic\n"); - return NULL; - } - - if (!DRI2Authenticate(psc->dpy, RootWindow(psc->dpy, screen), magic)) { - ErrorMessageF("failed to authenticate magic %d\n", magic); - return NULL; - } - - /* If the server does not support the protocol for - * DRI2GetBuffersWithFormat, don't supply that interface to the driver. - */ - psc->__driScreen = - psc->dri2->createNewScreen(screen, psc->fd, - ((pdp->driMinor < 1) - ? loader_extensions_old - : loader_extensions), - &driver_configs, psc); - - if (psc->__driScreen == NULL) { - ErrorMessageF("failed to create dri screen\n"); - return NULL; - } - - driBindExtensions(psc, 1); - - psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs); - psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs); - - psc->driver_configs = driver_configs; - - psp->destroyScreen = dri2DestroyScreen; - psp->createContext = dri2CreateContext; - psp->createDrawable = dri2CreateDrawable; - psp->swapBuffers = dri2SwapBuffers; - psp->waitGL = dri2WaitGL; - psp->waitX = dri2WaitX; - - /* DRI2 suports SubBuffer through DRI2CopyRegion, so it's always - * available.*/ - psp->copySubBuffer = dri2CopySubBuffer; - __glXEnableDirectExtension(psc, "GLX_MESA_copy_sub_buffer"); - - Xfree(driverName); - Xfree(deviceName); - - return psp; + __GLXDRIscreen *psp; + char *driverName, *deviceName; + drm_magic_t magic; + int i; + + psp = Xmalloc(sizeof *psp); + if (psp == NULL) + return NULL; + + /* Initialize per screen dynamic client GLX extensions */ + psc->ext_list_first_time = GL_TRUE; + + if (!DRI2Connect(psc->dpy, RootWindow(psc->dpy, screen), + &driverName, &deviceName)) + return NULL; + + psc->driver = driOpenDriver(driverName); + if (psc->driver == NULL) { + ErrorMessageF("driver pointer missing\n"); + goto handle_error; + } + + extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS); + if (extensions == NULL) { + ErrorMessageF("driver exports no extensions (%s)\n", dlerror()); + goto handle_error; + } + + for (i = 0; extensions[i]; i++) { + if (strcmp(extensions[i]->name, __DRI_CORE) == 0) + psc->core = (__DRIcoreExtension *) extensions[i]; + if (strcmp(extensions[i]->name, __DRI_DRI2) == 0) + psc->dri2 = (__DRIdri2Extension *) extensions[i]; + } + + if (psc->core == NULL || psc->dri2 == NULL) { + ErrorMessageF("core dri or dri2 extension not found\n"); + goto handle_error; + } + + psc->fd = open(deviceName, O_RDWR); + if (psc->fd < 0) { + ErrorMessageF("failed to open drm device: %s\n", strerror(errno)); + return NULL; + } + + if (drmGetMagic(psc->fd, &magic)) { + ErrorMessageF("failed to get magic\n"); + return NULL; + } + + if (!DRI2Authenticate(psc->dpy, RootWindow(psc->dpy, screen), magic)) { + ErrorMessageF("failed to authenticate magic %d\n", magic); + return NULL; + } + + /* If the server does not support the protocol for + * DRI2GetBuffersWithFormat, don't supply that interface to the driver. + */ + psc->__driScreen = + psc->dri2->createNewScreen(screen, psc->fd, ((pdp->driMinor < 1) + ? loader_extensions_old + : loader_extensions), + &driver_configs, psc); + + if (psc->__driScreen == NULL) { + ErrorMessageF("failed to create dri screen\n"); + return NULL; + } + + driBindExtensions(psc, 1); + + psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs); + psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs); + + psc->driver_configs = driver_configs; + + psp->destroyScreen = dri2DestroyScreen; + psp->createContext = dri2CreateContext; + psp->createDrawable = dri2CreateDrawable; + psp->swapBuffers = dri2SwapBuffers; + psp->waitGL = dri2WaitGL; + psp->waitX = dri2WaitX; + + /* DRI2 suports SubBuffer through DRI2CopyRegion, so it's always + * available.*/ + psp->copySubBuffer = dri2CopySubBuffer; + __glXEnableDirectExtension(psc, "GLX_MESA_copy_sub_buffer"); + + Xfree(driverName); + Xfree(deviceName); + + return psp; handle_error: - Xfree(driverName); - Xfree(deviceName); + Xfree(driverName); + Xfree(deviceName); - /* FIXME: clean up here */ + /* FIXME: clean up here */ - return NULL; + return NULL; } /* Called from __glXFreeDisplayPrivate. */ -static void dri2DestroyDisplay(__GLXDRIdisplay *dpy) +static void +dri2DestroyDisplay(__GLXDRIdisplay * dpy) { - Xfree(dpy); + Xfree(dpy); } /* @@ -528,29 +540,30 @@ static void dri2DestroyDisplay(__GLXDRIdisplay *dpy) * This is called from __glXInitialize() when we are given a new * display pointer. */ -_X_HIDDEN __GLXDRIdisplay *dri2CreateDisplay(Display *dpy) +_X_HIDDEN __GLXDRIdisplay * +dri2CreateDisplay(Display * dpy) { - __GLXDRIdisplayPrivate *pdp; - int eventBase, errorBase; + __GLXDRIdisplayPrivate *pdp; + int eventBase, errorBase; - if (!DRI2QueryExtension(dpy, &eventBase, &errorBase)) - return NULL; + if (!DRI2QueryExtension(dpy, &eventBase, &errorBase)) + return NULL; - pdp = Xmalloc(sizeof *pdp); - if (pdp == NULL) - return NULL; + pdp = Xmalloc(sizeof *pdp); + if (pdp == NULL) + return NULL; - if (!DRI2QueryVersion(dpy, &pdp->driMajor, &pdp->driMinor)) { - Xfree(pdp); - return NULL; - } + if (!DRI2QueryVersion(dpy, &pdp->driMajor, &pdp->driMinor)) { + Xfree(pdp); + return NULL; + } - pdp->driPatch = 0; + pdp->driPatch = 0; - pdp->base.destroyDisplay = dri2DestroyDisplay; - pdp->base.createScreen = dri2CreateScreen; + pdp->base.destroyDisplay = dri2DestroyDisplay; + pdp->base.createScreen = dri2CreateScreen; - return &pdp->base; + return &pdp->base; } #endif /* GLX_DIRECT_RENDERING */ diff --git a/src/glx/x11/dri_common.c b/src/glx/x11/dri_common.c index 6de4111113..9c825ad74a 100644 --- a/src/glx/x11/dri_common.c +++ b/src/glx/x11/dri_common.c @@ -49,33 +49,35 @@ #define RTLD_GLOBAL 0 #endif -_X_HIDDEN void InfoMessageF(const char *f, ...) +_X_HIDDEN void +InfoMessageF(const char *f, ...) { - va_list args; - const char *env; - - if ((env = getenv("LIBGL_DEBUG")) && strstr(env, "verbose")) { - fprintf(stderr, "libGL: "); - va_start(args, f); - vfprintf(stderr, f, args); - va_end(args); - } + va_list args; + const char *env; + + if ((env = getenv("LIBGL_DEBUG")) && strstr(env, "verbose")) { + fprintf(stderr, "libGL: "); + va_start(args, f); + vfprintf(stderr, f, args); + va_end(args); + } } /** * Print error to stderr, unless LIBGL_DEBUG=="quiet". */ -_X_HIDDEN void ErrorMessageF(const char *f, ...) +_X_HIDDEN void +ErrorMessageF(const char *f, ...) { - va_list args; - const char *env; - - if ((env = getenv("LIBGL_DEBUG")) && !strstr(env, "quiet")) { - fprintf(stderr, "libGL error: "); - va_start(args, f); - vfprintf(stderr, f, args); - va_end(args); - } + va_list args; + const char *env; + + if ((env = getenv("LIBGL_DEBUG")) && !strstr(env, "quiet")) { + fprintf(stderr, "libGL error: "); + va_start(args, f); + vfprintf(stderr, f, args); + va_end(args); + } } #ifndef DEFAULT_DRIVER_DIR @@ -95,7 +97,8 @@ _X_HIDDEN void ErrorMessageF(const char *f, ...) * \returns * A handle from \c dlopen, or \c NULL if driver file not found. */ -_X_HIDDEN void *driOpenDriver(const char *driverName) +_X_HIDDEN void * +driOpenDriver(const char *driverName) { void *glhandle, *handle; const char *libPaths, *p, *next; @@ -110,40 +113,41 @@ _X_HIDDEN void *driOpenDriver(const char *driverName) /* don't allow setuid apps to use LIBGL_DRIVERS_PATH */ libPaths = getenv("LIBGL_DRIVERS_PATH"); if (!libPaths) - libPaths = getenv("LIBGL_DRIVERS_DIR"); /* deprecated */ + libPaths = getenv("LIBGL_DRIVERS_DIR"); /* deprecated */ } if (libPaths == NULL) - libPaths = DEFAULT_DRIVER_DIR; + libPaths = DEFAULT_DRIVER_DIR; handle = NULL; for (p = libPaths; *p; p = next) { - next = strchr(p, ':'); - if (next == NULL) { - len = strlen(p); - next = p + len; - } else { - len = next - p; - next++; - } + next = strchr(p, ':'); + if (next == NULL) { + len = strlen(p); + next = p + len; + } + else { + len = next - p; + next++; + } #ifdef GLX_USE_TLS snprintf(realDriverName, sizeof realDriverName, - "%.*s/tls/%s_dri.so", len, p, driverName); + "%.*s/tls/%s_dri.so", len, p, driverName); InfoMessageF("OpenDriver: trying %s\n", realDriverName); handle = dlopen(realDriverName, RTLD_NOW | RTLD_GLOBAL); #endif - if ( handle == NULL ) { - snprintf(realDriverName, sizeof realDriverName, - "%.*s/%s_dri.so", len, p, driverName); - InfoMessageF("OpenDriver: trying %s\n", realDriverName); - handle = dlopen(realDriverName, RTLD_NOW | RTLD_GLOBAL); + if (handle == NULL) { + snprintf(realDriverName, sizeof realDriverName, + "%.*s/%s_dri.so", len, p, driverName); + InfoMessageF("OpenDriver: trying %s\n", realDriverName); + handle = dlopen(realDriverName, RTLD_NOW | RTLD_GLOBAL); } - if ( handle != NULL ) - break; + if (handle != NULL) + break; else - ErrorMessageF("dlopen %s failed (%s)\n", realDriverName, dlerror()); + ErrorMessageF("dlopen %s failed (%s)\n", realDriverName, dlerror()); } if (!handle) @@ -156,253 +160,258 @@ _X_HIDDEN void *driOpenDriver(const char *driverName) } _X_HIDDEN const __DRIsystemTimeExtension systemTimeExtension = { - { __DRI_SYSTEM_TIME, __DRI_SYSTEM_TIME_VERSION }, - __glXGetUST, - __driGetMscRateOML + {__DRI_SYSTEM_TIME, __DRI_SYSTEM_TIME_VERSION}, + __glXGetUST, + __driGetMscRateOML }; #define __ATTRIB(attrib, field) \ { attrib, offsetof(__GLcontextModes, field) } -static const struct { unsigned int attrib, offset; } attribMap[] = { - __ATTRIB(__DRI_ATTRIB_BUFFER_SIZE, rgbBits), - __ATTRIB(__DRI_ATTRIB_LEVEL, level), - __ATTRIB(__DRI_ATTRIB_RED_SIZE, redBits), - __ATTRIB(__DRI_ATTRIB_GREEN_SIZE, greenBits), - __ATTRIB(__DRI_ATTRIB_BLUE_SIZE, blueBits), - __ATTRIB(__DRI_ATTRIB_ALPHA_SIZE, alphaBits), - __ATTRIB(__DRI_ATTRIB_DEPTH_SIZE, depthBits), - __ATTRIB(__DRI_ATTRIB_STENCIL_SIZE, stencilBits), - __ATTRIB(__DRI_ATTRIB_ACCUM_RED_SIZE, accumRedBits), - __ATTRIB(__DRI_ATTRIB_ACCUM_GREEN_SIZE, accumGreenBits), - __ATTRIB(__DRI_ATTRIB_ACCUM_BLUE_SIZE, accumBlueBits), - __ATTRIB(__DRI_ATTRIB_ACCUM_ALPHA_SIZE, accumAlphaBits), - __ATTRIB(__DRI_ATTRIB_SAMPLE_BUFFERS, sampleBuffers), - __ATTRIB(__DRI_ATTRIB_SAMPLES, samples), - __ATTRIB(__DRI_ATTRIB_DOUBLE_BUFFER, doubleBufferMode), - __ATTRIB(__DRI_ATTRIB_STEREO, stereoMode), - __ATTRIB(__DRI_ATTRIB_AUX_BUFFERS, numAuxBuffers), +static const struct +{ + unsigned int attrib, offset; +} attribMap[] = { + __ATTRIB(__DRI_ATTRIB_BUFFER_SIZE, rgbBits), + __ATTRIB(__DRI_ATTRIB_LEVEL, level), + __ATTRIB(__DRI_ATTRIB_RED_SIZE, redBits), + __ATTRIB(__DRI_ATTRIB_GREEN_SIZE, greenBits), + __ATTRIB(__DRI_ATTRIB_BLUE_SIZE, blueBits), + __ATTRIB(__DRI_ATTRIB_ALPHA_SIZE, alphaBits), + __ATTRIB(__DRI_ATTRIB_DEPTH_SIZE, depthBits), + __ATTRIB(__DRI_ATTRIB_STENCIL_SIZE, stencilBits), + __ATTRIB(__DRI_ATTRIB_ACCUM_RED_SIZE, accumRedBits), + __ATTRIB(__DRI_ATTRIB_ACCUM_GREEN_SIZE, accumGreenBits), + __ATTRIB(__DRI_ATTRIB_ACCUM_BLUE_SIZE, accumBlueBits), + __ATTRIB(__DRI_ATTRIB_ACCUM_ALPHA_SIZE, accumAlphaBits), + __ATTRIB(__DRI_ATTRIB_SAMPLE_BUFFERS, sampleBuffers), + __ATTRIB(__DRI_ATTRIB_SAMPLES, samples), + __ATTRIB(__DRI_ATTRIB_DOUBLE_BUFFER, doubleBufferMode), + __ATTRIB(__DRI_ATTRIB_STEREO, stereoMode), + __ATTRIB(__DRI_ATTRIB_AUX_BUFFERS, numAuxBuffers), #if 0 - __ATTRIB(__DRI_ATTRIB_TRANSPARENT_TYPE, transparentPixel), - __ATTRIB(__DRI_ATTRIB_TRANSPARENT_INDEX_VALUE, transparentIndex), - __ATTRIB(__DRI_ATTRIB_TRANSPARENT_RED_VALUE, transparentRed), - __ATTRIB(__DRI_ATTRIB_TRANSPARENT_GREEN_VALUE, transparentGreen), - __ATTRIB(__DRI_ATTRIB_TRANSPARENT_BLUE_VALUE, transparentBlue), - __ATTRIB(__DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE, transparentAlpha), - __ATTRIB(__DRI_ATTRIB_RED_MASK, redMask), - __ATTRIB(__DRI_ATTRIB_GREEN_MASK, greenMask), - __ATTRIB(__DRI_ATTRIB_BLUE_MASK, blueMask), - __ATTRIB(__DRI_ATTRIB_ALPHA_MASK, alphaMask), + __ATTRIB(__DRI_ATTRIB_TRANSPARENT_TYPE, transparentPixel), + __ATTRIB(__DRI_ATTRIB_TRANSPARENT_INDEX_VALUE, transparentIndex), + __ATTRIB(__DRI_ATTRIB_TRANSPARENT_RED_VALUE, transparentRed), + __ATTRIB(__DRI_ATTRIB_TRANSPARENT_GREEN_VALUE, transparentGreen), + __ATTRIB(__DRI_ATTRIB_TRANSPARENT_BLUE_VALUE, transparentBlue), + __ATTRIB(__DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE, transparentAlpha), + __ATTRIB(__DRI_ATTRIB_RED_MASK, redMask), + __ATTRIB(__DRI_ATTRIB_GREEN_MASK, greenMask), + __ATTRIB(__DRI_ATTRIB_BLUE_MASK, blueMask), + __ATTRIB(__DRI_ATTRIB_ALPHA_MASK, alphaMask), #endif - __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_WIDTH, maxPbufferWidth), - __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_HEIGHT, maxPbufferHeight), - __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_PIXELS, maxPbufferPixels), - __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH, optimalPbufferWidth), - __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT, optimalPbufferHeight), + __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_WIDTH, maxPbufferWidth), + __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_HEIGHT, maxPbufferHeight), + __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_PIXELS, maxPbufferPixels), + __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH, optimalPbufferWidth), + __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT, optimalPbufferHeight), #if 0 - __ATTRIB(__DRI_ATTRIB_SWAP_METHOD, swapMethod), + __ATTRIB(__DRI_ATTRIB_SWAP_METHOD, swapMethod), #endif - __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGB, bindToTextureRgb), - __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGBA, bindToTextureRgba), - __ATTRIB(__DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE, bindToMipmapTexture), - __ATTRIB(__DRI_ATTRIB_YINVERTED, yInverted), -}; +__ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGB, bindToTextureRgb), + __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGBA, bindToTextureRgba), + __ATTRIB(__DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE, + bindToMipmapTexture), + __ATTRIB(__DRI_ATTRIB_YINVERTED, yInverted),}; #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0])) static int -scalarEqual(__GLcontextModes *mode, unsigned int attrib, unsigned int value) +scalarEqual(__GLcontextModes * mode, unsigned int attrib, unsigned int value) { - unsigned int glxValue; - int i; + unsigned int glxValue; + int i; - for (i = 0; i < ARRAY_SIZE(attribMap); i++) - if (attribMap[i].attrib == attrib) { - glxValue = *(unsigned int *) ((char *) mode + attribMap[i].offset); - return glxValue == GLX_DONT_CARE || glxValue == value; - } + for (i = 0; i < ARRAY_SIZE(attribMap); i++) + if (attribMap[i].attrib == attrib) { + glxValue = *(unsigned int *) ((char *) mode + attribMap[i].offset); + return glxValue == GLX_DONT_CARE || glxValue == value; + } - return GL_TRUE; /* Is a non-existing attribute equal to value? */ + return GL_TRUE; /* Is a non-existing attribute equal to value? */ } static int -driConfigEqual(const __DRIcoreExtension *core, - __GLcontextModes *modes, const __DRIconfig *driConfig) +driConfigEqual(const __DRIcoreExtension * core, + __GLcontextModes * modes, const __DRIconfig * driConfig) { - unsigned int attrib, value, glxValue; - int i; - - i = 0; - while (core->indexConfigAttrib(driConfig, i++, &attrib, &value)) { - switch (attrib) { - case __DRI_ATTRIB_RENDER_TYPE: - glxValue = 0; - if (value & __DRI_ATTRIB_RGBA_BIT) { - glxValue |= GLX_RGBA_BIT; - } else if (value & __DRI_ATTRIB_COLOR_INDEX_BIT) { - glxValue |= GLX_COLOR_INDEX_BIT; - } - if (glxValue != modes->renderType) - return GL_FALSE; - break; - - case __DRI_ATTRIB_CONFIG_CAVEAT: - if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG) - glxValue = GLX_NON_CONFORMANT_CONFIG; - else if (value & __DRI_ATTRIB_SLOW_BIT) - glxValue = GLX_SLOW_CONFIG; - else - glxValue = GLX_NONE; - if (glxValue != modes->visualRating) - return GL_FALSE; - break; - - case __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS: - glxValue = 0; - if (value & __DRI_ATTRIB_TEXTURE_1D_BIT) - glxValue |= GLX_TEXTURE_1D_BIT_EXT; - if (value & __DRI_ATTRIB_TEXTURE_2D_BIT) - glxValue |= GLX_TEXTURE_2D_BIT_EXT; - if (value & __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT) - glxValue |= GLX_TEXTURE_RECTANGLE_BIT_EXT; - if (modes->bindToTextureTargets != GLX_DONT_CARE && - glxValue != modes->bindToTextureTargets) - return GL_FALSE; - break; - - default: - if (!scalarEqual(modes, attrib, value)) - return GL_FALSE; - } - } - - return GL_TRUE; + unsigned int attrib, value, glxValue; + int i; + + i = 0; + while (core->indexConfigAttrib(driConfig, i++, &attrib, &value)) { + switch (attrib) { + case __DRI_ATTRIB_RENDER_TYPE: + glxValue = 0; + if (value & __DRI_ATTRIB_RGBA_BIT) { + glxValue |= GLX_RGBA_BIT; + } + else if (value & __DRI_ATTRIB_COLOR_INDEX_BIT) { + glxValue |= GLX_COLOR_INDEX_BIT; + } + if (glxValue != modes->renderType) + return GL_FALSE; + break; + + case __DRI_ATTRIB_CONFIG_CAVEAT: + if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG) + glxValue = GLX_NON_CONFORMANT_CONFIG; + else if (value & __DRI_ATTRIB_SLOW_BIT) + glxValue = GLX_SLOW_CONFIG; + else + glxValue = GLX_NONE; + if (glxValue != modes->visualRating) + return GL_FALSE; + break; + + case __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS: + glxValue = 0; + if (value & __DRI_ATTRIB_TEXTURE_1D_BIT) + glxValue |= GLX_TEXTURE_1D_BIT_EXT; + if (value & __DRI_ATTRIB_TEXTURE_2D_BIT) + glxValue |= GLX_TEXTURE_2D_BIT_EXT; + if (value & __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT) + glxValue |= GLX_TEXTURE_RECTANGLE_BIT_EXT; + if (modes->bindToTextureTargets != GLX_DONT_CARE && + glxValue != modes->bindToTextureTargets) + return GL_FALSE; + break; + + default: + if (!scalarEqual(modes, attrib, value)) + return GL_FALSE; + } + } + + return GL_TRUE; } static __GLcontextModes * -createDriMode(const __DRIcoreExtension *core, - __GLcontextModes *modes, const __DRIconfig **driConfigs) +createDriMode(const __DRIcoreExtension * core, + __GLcontextModes * modes, const __DRIconfig ** driConfigs) { - __GLXDRIconfigPrivate *config; - int i; + __GLXDRIconfigPrivate *config; + int i; - for (i = 0; driConfigs[i]; i++) { - if (driConfigEqual(core, modes, driConfigs[i])) - break; - } + for (i = 0; driConfigs[i]; i++) { + if (driConfigEqual(core, modes, driConfigs[i])) + break; + } - if (driConfigs[i] == NULL) - return NULL; + if (driConfigs[i] == NULL) + return NULL; - config = Xmalloc(sizeof *config); - if (config == NULL) - return NULL; + config = Xmalloc(sizeof *config); + if (config == NULL) + return NULL; - config->modes = *modes; - config->driConfig = driConfigs[i]; + config->modes = *modes; + config->driConfig = driConfigs[i]; - return &config->modes; + return &config->modes; } _X_HIDDEN __GLcontextModes * -driConvertConfigs(const __DRIcoreExtension *core, - __GLcontextModes *modes, const __DRIconfig **configs) +driConvertConfigs(const __DRIcoreExtension * core, + __GLcontextModes * modes, const __DRIconfig ** configs) { - __GLcontextModes head, *tail, *m; - - tail = &head; - head.next = NULL; - for (m = modes; m; m = m->next) { - tail->next = createDriMode(core, m, configs); - if (tail->next == NULL) { - /* no matching dri config for m */ - continue; - } + __GLcontextModes head, *tail, *m; + + tail = &head; + head.next = NULL; + for (m = modes; m; m = m->next) { + tail->next = createDriMode(core, m, configs); + if (tail->next == NULL) { + /* no matching dri config for m */ + continue; + } - tail = tail->next; - } + tail = tail->next; + } - _gl_context_modes_destroy(modes); + _gl_context_modes_destroy(modes); - return head.next; + return head.next; } _X_HIDDEN void -driBindExtensions(__GLXscreenConfigs *psc, int dri2) +driBindExtensions(__GLXscreenConfigs * psc, int dri2) { - const __DRIextension **extensions; - int i; + const __DRIextension **extensions; + int i; - extensions = psc->core->getExtensions(psc->__driScreen); + extensions = psc->core->getExtensions(psc->__driScreen); - for (i = 0; extensions[i]; i++) { + for (i = 0; extensions[i]; i++) { #ifdef __DRI_COPY_SUB_BUFFER - if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0) { - psc->driCopySubBuffer = (__DRIcopySubBufferExtension *) extensions[i]; - __glXEnableDirectExtension(psc, "GLX_MESA_copy_sub_buffer"); - } + if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0) { + psc->driCopySubBuffer = + (__DRIcopySubBufferExtension *) extensions[i]; + __glXEnableDirectExtension(psc, "GLX_MESA_copy_sub_buffer"); + } #endif #ifdef __DRI_SWAP_CONTROL - /* No DRI2 support for swap_control at the moment, since SwapBuffers - * is done by the X server */ - if (strcmp(extensions[i]->name, __DRI_SWAP_CONTROL) == 0 && !dri2) { - psc->swapControl = (__DRIswapControlExtension *) extensions[i]; - __glXEnableDirectExtension(psc, "GLX_SGI_swap_control"); - __glXEnableDirectExtension(psc, "GLX_MESA_swap_control"); - } + /* No DRI2 support for swap_control at the moment, since SwapBuffers + * is done by the X server */ + if (strcmp(extensions[i]->name, __DRI_SWAP_CONTROL) == 0 && !dri2) { + psc->swapControl = (__DRIswapControlExtension *) extensions[i]; + __glXEnableDirectExtension(psc, "GLX_SGI_swap_control"); + __glXEnableDirectExtension(psc, "GLX_MESA_swap_control"); + } #endif #ifdef __DRI_ALLOCATE - if (strcmp(extensions[i]->name, __DRI_ALLOCATE) == 0) { - psc->allocate = (__DRIallocateExtension *) extensions[i]; - __glXEnableDirectExtension(psc, "GLX_MESA_allocate_memory"); - } + if (strcmp(extensions[i]->name, __DRI_ALLOCATE) == 0) { + psc->allocate = (__DRIallocateExtension *) extensions[i]; + __glXEnableDirectExtension(psc, "GLX_MESA_allocate_memory"); + } #endif #ifdef __DRI_FRAME_TRACKING - if (strcmp(extensions[i]->name, __DRI_FRAME_TRACKING) == 0) { - psc->frameTracking = (__DRIframeTrackingExtension *) extensions[i]; - __glXEnableDirectExtension(psc, "GLX_MESA_swap_frame_usage"); - } + if (strcmp(extensions[i]->name, __DRI_FRAME_TRACKING) == 0) { + psc->frameTracking = (__DRIframeTrackingExtension *) extensions[i]; + __glXEnableDirectExtension(psc, "GLX_MESA_swap_frame_usage"); + } #endif #ifdef __DRI_MEDIA_STREAM_COUNTER - if (strcmp(extensions[i]->name, __DRI_MEDIA_STREAM_COUNTER) == 0) { - psc->msc = (__DRImediaStreamCounterExtension *) extensions[i]; - __glXEnableDirectExtension(psc, "GLX_SGI_video_sync"); - } + if (strcmp(extensions[i]->name, __DRI_MEDIA_STREAM_COUNTER) == 0) { + psc->msc = (__DRImediaStreamCounterExtension *) extensions[i]; + __glXEnableDirectExtension(psc, "GLX_SGI_video_sync"); + } #endif #ifdef __DRI_SWAP_BUFFER_COUNTER - /* No driver supports this at this time and the extension is - * not defined in dri_interface.h. Will enable - * GLX_OML_sync_control if implemented. */ + /* No driver supports this at this time and the extension is + * not defined in dri_interface.h. Will enable + * GLX_OML_sync_control if implemented. */ #endif #ifdef __DRI_READ_DRAWABLE - if (strcmp(extensions[i]->name, __DRI_READ_DRAWABLE) == 0) { - __glXEnableDirectExtension(psc, "GLX_SGI_make_current_read"); - } + if (strcmp(extensions[i]->name, __DRI_READ_DRAWABLE) == 0) { + __glXEnableDirectExtension(psc, "GLX_SGI_make_current_read"); + } #endif #ifdef __DRI_TEX_BUFFER - if ((strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0) && dri2) { - psc->texBuffer = (__DRItexBufferExtension *) extensions[i]; - __glXEnableDirectExtension(psc, "GLX_EXT_texture_from_pixmap"); - } + if ((strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0) && dri2) { + psc->texBuffer = (__DRItexBufferExtension *) extensions[i]; + __glXEnableDirectExtension(psc, "GLX_EXT_texture_from_pixmap"); + } #endif #ifdef __DRI2_FLUSH - if ((strcmp(extensions[i]->name, __DRI2_FLUSH) == 0) && dri2) { - psc->f = (__DRI2flushExtension *) extensions[i]; - /* internal driver extension, no GL extension exposed */ - } + if ((strcmp(extensions[i]->name, __DRI2_FLUSH) == 0) && dri2) { + psc->f = (__DRI2flushExtension *) extensions[i]; + /* internal driver extension, no GL extension exposed */ + } #endif - /* Ignore unknown extensions */ - } + /* Ignore unknown extensions */ + } } #endif /* GLX_DIRECT_RENDERING */ diff --git a/src/glx/x11/dri_glx.c b/src/glx/x11/dri_glx.c index d24471c436..ab24bd8ffe 100644 --- a/src/glx/x11/dri_glx.c +++ b/src/glx/x11/dri_glx.c @@ -51,22 +51,24 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. typedef struct __GLXDRIdisplayPrivateRec __GLXDRIdisplayPrivate; typedef struct __GLXDRIcontextPrivateRec __GLXDRIcontextPrivate; -struct __GLXDRIdisplayPrivateRec { - __GLXDRIdisplay base; +struct __GLXDRIdisplayPrivateRec +{ + __GLXDRIdisplay base; - /* + /* ** XFree86-DRI version information */ - int driMajor; - int driMinor; - int driPatch; + int driMajor; + int driMinor; + int driPatch; }; -struct __GLXDRIcontextPrivateRec { - __GLXDRIcontext base; - __DRIcontext *driContext; - XID hwContextID; - __GLXscreenConfigs *psc; +struct __GLXDRIcontextPrivateRec +{ + __GLXDRIcontext base; + __DRIcontext *driContext; + XID hwContextID; + __GLXscreenConfigs *psc; }; /* @@ -74,47 +76,51 @@ struct __GLXDRIcontextPrivateRec { * the DRI driver for the screen. (I.e. "r128", "tdfx", etc). * Return True for success, False for failure. */ -static Bool driGetDriverName(Display *dpy, int scrNum, char **driverName) +static Bool +driGetDriverName(Display * dpy, int scrNum, char **driverName) { - int directCapable; - Bool b; - int event, error; - int driverMajor, driverMinor, driverPatch; - - *driverName = NULL; - - if (XF86DRIQueryExtension(dpy, &event, &error)) { /* DRI1 */ - if (!XF86DRIQueryDirectRenderingCapable(dpy, scrNum, &directCapable)) { - ErrorMessageF("XF86DRIQueryDirectRenderingCapable failed\n"); - return False; - } - if (!directCapable) { - ErrorMessageF("XF86DRIQueryDirectRenderingCapable returned false\n"); - return False; - } - - b = XF86DRIGetClientDriverName(dpy, scrNum, &driverMajor, &driverMinor, - &driverPatch, driverName); - if (!b) { - ErrorMessageF("Cannot determine driver name for screen %d\n", scrNum); - return False; - } - - InfoMessageF("XF86DRIGetClientDriverName: %d.%d.%d %s (screen %d)\n", - driverMajor, driverMinor, driverPatch, *driverName, scrNum); - - return True; - } else if (DRI2QueryExtension(dpy, &event, &error)) { /* DRI2 */ - char *dev; - Bool ret = DRI2Connect(dpy, RootWindow(dpy, scrNum), driverName, &dev); - - if (ret) - Xfree(dev); - - return ret; - } - - return False; + int directCapable; + Bool b; + int event, error; + int driverMajor, driverMinor, driverPatch; + + *driverName = NULL; + + if (XF86DRIQueryExtension(dpy, &event, &error)) { /* DRI1 */ + if (!XF86DRIQueryDirectRenderingCapable(dpy, scrNum, &directCapable)) { + ErrorMessageF("XF86DRIQueryDirectRenderingCapable failed\n"); + return False; + } + if (!directCapable) { + ErrorMessageF("XF86DRIQueryDirectRenderingCapable returned false\n"); + return False; + } + + b = XF86DRIGetClientDriverName(dpy, scrNum, &driverMajor, &driverMinor, + &driverPatch, driverName); + if (!b) { + ErrorMessageF("Cannot determine driver name for screen %d\n", + scrNum); + return False; + } + + InfoMessageF("XF86DRIGetClientDriverName: %d.%d.%d %s (screen %d)\n", + driverMajor, driverMinor, driverPatch, *driverName, + scrNum); + + return True; + } + else if (DRI2QueryExtension(dpy, &event, &error)) { /* DRI2 */ + char *dev; + Bool ret = DRI2Connect(dpy, RootWindow(dpy, scrNum), driverName, &dev); + + if (ret) + Xfree(dev); + + return ret; + } + + return False; } /* @@ -123,17 +129,19 @@ static Bool driGetDriverName(Display *dpy, int scrNum, char **driverName) * The returned char pointer points to a static array that will be * overwritten by subsequent calls. */ -PUBLIC const char *glXGetScreenDriver (Display *dpy, int scrNum) { +PUBLIC const char * +glXGetScreenDriver(Display * dpy, int scrNum) +{ static char ret[32]; char *driverName; if (driGetDriverName(dpy, scrNum, &driverName)) { int len; if (!driverName) - return NULL; - len = strlen (driverName); + return NULL; + len = strlen(driverName); if (len >= 31) - return NULL; - memcpy (ret, driverName, len+1); + return NULL; + memcpy(ret, driverName, len + 1); Xfree(driverName); return ret; } @@ -151,121 +159,125 @@ PUBLIC const char *glXGetScreenDriver (Display *dpy, int scrNum) { * * Note: The driver remains opened after this function returns. */ -PUBLIC const char *glXGetDriverConfig (const char *driverName) +PUBLIC const char * +glXGetDriverConfig(const char *driverName) { - void *handle = driOpenDriver (driverName); + void *handle = driOpenDriver(driverName); if (handle) - return dlsym (handle, "__driConfigOptions"); + return dlsym(handle, "__driConfigOptions"); else return NULL; } #ifdef XDAMAGE_1_1_INTERFACE -static GLboolean has_damage_post(Display *dpy) +static GLboolean +has_damage_post(Display * dpy) { - static GLboolean inited = GL_FALSE; - static GLboolean has_damage; - - if (!inited) { - int major, minor; - - if (XDamageQueryVersion(dpy, &major, &minor) && - major == 1 && minor >= 1) - { - has_damage = GL_TRUE; - } else { - has_damage = GL_FALSE; - } - inited = GL_TRUE; - } - - return has_damage; + static GLboolean inited = GL_FALSE; + static GLboolean has_damage; + + if (!inited) { + int major, minor; + + if (XDamageQueryVersion(dpy, &major, &minor) && + major == 1 && minor >= 1) { + has_damage = GL_TRUE; + } + else { + has_damage = GL_FALSE; + } + inited = GL_TRUE; + } + + return has_damage; } -static void __glXReportDamage(__DRIdrawable *driDraw, - int x, int y, - drm_clip_rect_t *rects, int num_rects, - GLboolean front_buffer, - void *loaderPrivate) +static void +__glXReportDamage(__DRIdrawable * driDraw, + int x, int y, + drm_clip_rect_t * rects, int num_rects, + GLboolean front_buffer, void *loaderPrivate) { - XRectangle *xrects; - XserverRegion region; - int i; - int x_off, y_off; - __GLXDRIdrawable *glxDraw = loaderPrivate; - __GLXscreenConfigs *psc = glxDraw->psc; - Display *dpy = psc->dpy; - Drawable drawable; - - if (!has_damage_post(dpy)) - return; - - if (front_buffer) { - x_off = x; - y_off = y; - drawable = RootWindow(dpy, psc->scr); - } else{ - x_off = 0; - y_off = 0; - drawable = glxDraw->xDrawable; - } - - xrects = malloc(sizeof(XRectangle) * num_rects); - if (xrects == NULL) - return; - - for (i = 0; i < num_rects; i++) { - xrects[i].x = rects[i].x1 + x_off; - xrects[i].y = rects[i].y1 + y_off; - xrects[i].width = rects[i].x2 - rects[i].x1; - xrects[i].height = rects[i].y2 - rects[i].y1; - } - region = XFixesCreateRegion(dpy, xrects, num_rects); - free(xrects); - XDamageAdd(dpy, drawable, region); - XFixesDestroyRegion(dpy, region); + XRectangle *xrects; + XserverRegion region; + int i; + int x_off, y_off; + __GLXDRIdrawable *glxDraw = loaderPrivate; + __GLXscreenConfigs *psc = glxDraw->psc; + Display *dpy = psc->dpy; + Drawable drawable; + + if (!has_damage_post(dpy)) + return; + + if (front_buffer) { + x_off = x; + y_off = y; + drawable = RootWindow(dpy, psc->scr); + } + else { + x_off = 0; + y_off = 0; + drawable = glxDraw->xDrawable; + } + + xrects = malloc(sizeof(XRectangle) * num_rects); + if (xrects == NULL) + return; + + for (i = 0; i < num_rects; i++) { + xrects[i].x = rects[i].x1 + x_off; + xrects[i].y = rects[i].y1 + y_off; + xrects[i].width = rects[i].x2 - rects[i].x1; + xrects[i].height = rects[i].y2 - rects[i].y1; + } + region = XFixesCreateRegion(dpy, xrects, num_rects); + free(xrects); + XDamageAdd(dpy, drawable, region); + XFixesDestroyRegion(dpy, region); } static const __DRIdamageExtension damageExtension = { - { __DRI_DAMAGE, __DRI_DAMAGE_VERSION }, - __glXReportDamage, + {__DRI_DAMAGE, __DRI_DAMAGE_VERSION}, + __glXReportDamage, }; #endif static GLboolean -__glXDRIGetDrawableInfo(__DRIdrawable *drawable, - unsigned int *index, unsigned int *stamp, - int *X, int *Y, int *W, int *H, - int *numClipRects, drm_clip_rect_t ** pClipRects, - int *backX, int *backY, - int *numBackClipRects, drm_clip_rect_t **pBackClipRects, - void *loaderPrivate) +__glXDRIGetDrawableInfo(__DRIdrawable * drawable, + unsigned int *index, unsigned int *stamp, + int *X, int *Y, int *W, int *H, + int *numClipRects, drm_clip_rect_t ** pClipRects, + int *backX, int *backY, + int *numBackClipRects, + drm_clip_rect_t ** pBackClipRects, + void *loaderPrivate) { - __GLXDRIdrawable *glxDraw = loaderPrivate; - __GLXscreenConfigs *psc = glxDraw->psc; - Display *dpy = psc->dpy; - - return XF86DRIGetDrawableInfo(dpy, psc->scr, glxDraw->drawable, - index, stamp, X, Y, W, H, - numClipRects, pClipRects, - backX, backY, - numBackClipRects, pBackClipRects); + __GLXDRIdrawable *glxDraw = loaderPrivate; + __GLXscreenConfigs *psc = glxDraw->psc; + Display *dpy = psc->dpy; + + return XF86DRIGetDrawableInfo(dpy, psc->scr, glxDraw->drawable, + index, stamp, X, Y, W, H, + numClipRects, pClipRects, + backX, backY, + numBackClipRects, pBackClipRects); } static const __DRIgetDrawableInfoExtension getDrawableInfoExtension = { - { __DRI_GET_DRAWABLE_INFO, __DRI_GET_DRAWABLE_INFO_VERSION }, - __glXDRIGetDrawableInfo + {__DRI_GET_DRAWABLE_INFO, __DRI_GET_DRAWABLE_INFO_VERSION}, + __glXDRIGetDrawableInfo }; static const __DRIextension *loader_extensions[] = { - &systemTimeExtension.base, - &getDrawableInfoExtension.base, + &systemTimeExtension.base, + &getDrawableInfoExtension.base, #ifdef XDAMAGE_1_1_INTERFACE - &damageExtension.base, + &damageExtension.base, #endif - NULL + NULL }; #ifndef GLX_USE_APPLEGL @@ -284,427 +296,429 @@ static const __DRIextension *loader_extensions[] = { * the client-side driver on success, or \c NULL on failure. */ static void * -CallCreateNewScreen(Display *dpy, int scrn, __GLXscreenConfigs *psc, - __GLXDRIdisplayPrivate * driDpy) +CallCreateNewScreen(Display * dpy, int scrn, __GLXscreenConfigs * psc, + __GLXDRIdisplayPrivate * driDpy) { - void *psp = NULL; - drm_handle_t hSAREA; - drmAddress pSAREA = MAP_FAILED; - char *BusID; - __DRIversion ddx_version; - __DRIversion dri_version; - __DRIversion drm_version; - __DRIframebuffer framebuffer; - int fd = -1; - int status; - - drm_magic_t magic; - drmVersionPtr version; - int newlyopened; - char *driverName; - drm_handle_t hFB; - int junk; - const __DRIconfig **driver_configs; - __GLcontextModes *visual; - - /* DRI protocol version. */ - dri_version.major = driDpy->driMajor; - dri_version.minor = driDpy->driMinor; - dri_version.patch = driDpy->driPatch; - - framebuffer.base = MAP_FAILED; - framebuffer.dev_priv = NULL; - - if (!XF86DRIOpenConnection(dpy, scrn, &hSAREA, &BusID)) { - ErrorMessageF("XF86DRIOpenConnection failed\n"); - goto handle_error; - } - - fd = drmOpenOnce(NULL, BusID, &newlyopened); - - Xfree(BusID); /* No longer needed */ - - if (fd < 0) { - ErrorMessageF("drmOpenOnce failed (%s)\n", strerror(-fd)); - goto handle_error; - } - - if (drmGetMagic(fd, &magic)) { - ErrorMessageF("drmGetMagic failed\n"); - goto handle_error; - } - - version = drmGetVersion(fd); - if (version) { - drm_version.major = version->version_major; - drm_version.minor = version->version_minor; - drm_version.patch = version->version_patchlevel; - drmFreeVersion(version); - } - else { - drm_version.major = -1; - drm_version.minor = -1; - drm_version.patch = -1; - } - - if (newlyopened && !XF86DRIAuthConnection(dpy, scrn, magic)) { - ErrorMessageF("XF86DRIAuthConnection failed\n"); - goto handle_error; - } - - /* Get device name (like "tdfx") and the ddx version numbers. - * We'll check the version in each DRI driver's "createNewScreen" - * function. */ - if (!XF86DRIGetClientDriverName(dpy, scrn, - &ddx_version.major, - &ddx_version.minor, - &ddx_version.patch, - &driverName)) { - ErrorMessageF("XF86DRIGetClientDriverName failed\n"); - goto handle_error; - } - - Xfree(driverName); /* No longer needed. */ - - /* - * Get device-specific info. pDevPriv will point to a struct - * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h) that - * has information about the screen size, depth, pitch, ancilliary - * buffers, DRM mmap handles, etc. - */ - if (!XF86DRIGetDeviceInfo(dpy, scrn, &hFB, &junk, - &framebuffer.size, &framebuffer.stride, - &framebuffer.dev_priv_size, &framebuffer.dev_priv)) { - ErrorMessageF("XF86DRIGetDeviceInfo failed"); - goto handle_error; - } - - framebuffer.width = DisplayWidth(dpy, scrn); - framebuffer.height = DisplayHeight(dpy, scrn); - - /* Map the framebuffer region. */ - status = drmMap(fd, hFB, framebuffer.size, - (drmAddressPtr)&framebuffer.base); - if (status != 0) { - ErrorMessageF("drmMap of framebuffer failed (%s)", strerror(-status)); - goto handle_error; - } - - /* Map the SAREA region. Further mmap regions may be setup in - * each DRI driver's "createNewScreen" function. - */ - status = drmMap(fd, hSAREA, SAREA_MAX, &pSAREA); - if (status != 0) { - ErrorMessageF("drmMap of SAREA failed (%s)", strerror(-status)); - goto handle_error; - } - - psp = (*psc->legacy->createNewScreen)(scrn, - &ddx_version, - &dri_version, - &drm_version, - &framebuffer, - pSAREA, - fd, - loader_extensions, - &driver_configs, - psc); - - if (psp == NULL) { - ErrorMessageF("Calling driver entry point failed"); - goto handle_error; - } - - psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs); - psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs); - - psc->driver_configs = driver_configs; - - /* Visuals with depth != screen depth are subject to automatic compositing - * in the X server, so DRI1 can't render to them properly. Mark them as - * non-conformant to prevent apps from picking them up accidentally. - */ - for (visual = psc->visuals; visual; visual = visual->next) { - XVisualInfo template; - XVisualInfo *visuals; - int num_visuals; - long mask; - - template.visualid = visual->visualID; - mask = VisualIDMask; - visuals = XGetVisualInfo(dpy, mask, &template, &num_visuals); - - if (visuals) { - if (num_visuals > 0 && visuals->depth != DefaultDepth(dpy, scrn)) - visual->visualRating = GLX_NON_CONFORMANT_CONFIG; - - XFree(visuals); - } - } - - return psp; + void *psp = NULL; + drm_handle_t hSAREA; + drmAddress pSAREA = MAP_FAILED; + char *BusID; + __DRIversion ddx_version; + __DRIversion dri_version; + __DRIversion drm_version; + __DRIframebuffer framebuffer; + int fd = -1; + int status; + + drm_magic_t magic; + drmVersionPtr version; + int newlyopened; + char *driverName; + drm_handle_t hFB; + int junk; + const __DRIconfig **driver_configs; + __GLcontextModes *visual; + + /* DRI protocol version. */ + dri_version.major = driDpy->driMajor; + dri_version.minor = driDpy->driMinor; + dri_version.patch = driDpy->driPatch; + + framebuffer.base = MAP_FAILED; + framebuffer.dev_priv = NULL; + + if (!XF86DRIOpenConnection(dpy, scrn, &hSAREA, &BusID)) { + ErrorMessageF("XF86DRIOpenConnection failed\n"); + goto handle_error; + } + + fd = drmOpenOnce(NULL, BusID, &newlyopened); + + Xfree(BusID); /* No longer needed */ + + if (fd < 0) { + ErrorMessageF("drmOpenOnce failed (%s)\n", strerror(-fd)); + goto handle_error; + } + + if (drmGetMagic(fd, &magic)) { + ErrorMessageF("drmGetMagic failed\n"); + goto handle_error; + } + + version = drmGetVersion(fd); + if (version) { + drm_version.major = version->version_major; + drm_version.minor = version->version_minor; + drm_version.patch = version->version_patchlevel; + drmFreeVersion(version); + } + else { + drm_version.major = -1; + drm_version.minor = -1; + drm_version.patch = -1; + } + + if (newlyopened && !XF86DRIAuthConnection(dpy, scrn, magic)) { + ErrorMessageF("XF86DRIAuthConnection failed\n"); + goto handle_error; + } + + /* Get device name (like "tdfx") and the ddx version numbers. + * We'll check the version in each DRI driver's "createNewScreen" + * function. */ + if (!XF86DRIGetClientDriverName(dpy, scrn, + &ddx_version.major, + &ddx_version.minor, + &ddx_version.patch, &driverName)) { + ErrorMessageF("XF86DRIGetClientDriverName failed\n"); + goto handle_error; + } + + Xfree(driverName); /* No longer needed. */ + + /* + * Get device-specific info. pDevPriv will point to a struct + * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h) that + * has information about the screen size, depth, pitch, ancilliary + * buffers, DRM mmap handles, etc. + */ + if (!XF86DRIGetDeviceInfo(dpy, scrn, &hFB, &junk, + &framebuffer.size, &framebuffer.stride, + &framebuffer.dev_priv_size, + &framebuffer.dev_priv)) { + ErrorMessageF("XF86DRIGetDeviceInfo failed"); + goto handle_error; + } + + framebuffer.width = DisplayWidth(dpy, scrn); + framebuffer.height = DisplayHeight(dpy, scrn); + + /* Map the framebuffer region. */ + status = drmMap(fd, hFB, framebuffer.size, + (drmAddressPtr) & framebuffer.base); + if (status != 0) { + ErrorMessageF("drmMap of framebuffer failed (%s)", strerror(-status)); + goto handle_error; + } + + /* Map the SAREA region. Further mmap regions may be setup in + * each DRI driver's "createNewScreen" function. + */ + status = drmMap(fd, hSAREA, SAREA_MAX, &pSAREA); + if (status != 0) { + ErrorMessageF("drmMap of SAREA failed (%s)", strerror(-status)); + goto handle_error; + } + + psp = (*psc->legacy->createNewScreen) (scrn, + &ddx_version, + &dri_version, + &drm_version, + &framebuffer, + pSAREA, + fd, + loader_extensions, + &driver_configs, psc); + + if (psp == NULL) { + ErrorMessageF("Calling driver entry point failed"); + goto handle_error; + } + + psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs); + psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs); + + psc->driver_configs = driver_configs; + + /* Visuals with depth != screen depth are subject to automatic compositing + * in the X server, so DRI1 can't render to them properly. Mark them as + * non-conformant to prevent apps from picking them up accidentally. + */ + for (visual = psc->visuals; visual; visual = visual->next) { + XVisualInfo template; + XVisualInfo *visuals; + int num_visuals; + long mask; + + template.visualid = visual->visualID; + mask = VisualIDMask; + visuals = XGetVisualInfo(dpy, mask, &template, &num_visuals); + + if (visuals) { + if (num_visuals > 0 && visuals->depth != DefaultDepth(dpy, scrn)) + visual->visualRating = GLX_NON_CONFORMANT_CONFIG; + + XFree(visuals); + } + } + + return psp; handle_error: - if (pSAREA != MAP_FAILED) - drmUnmap(pSAREA, SAREA_MAX); + if (pSAREA != MAP_FAILED) + drmUnmap(pSAREA, SAREA_MAX); - if (framebuffer.base != MAP_FAILED) - drmUnmap((drmAddress)framebuffer.base, framebuffer.size); + if (framebuffer.base != MAP_FAILED) + drmUnmap((drmAddress) framebuffer.base, framebuffer.size); - if (framebuffer.dev_priv != NULL) - Xfree(framebuffer.dev_priv); + if (framebuffer.dev_priv != NULL) + Xfree(framebuffer.dev_priv); - if (fd >= 0) - drmCloseOnce(fd); + if (fd >= 0) + drmCloseOnce(fd); - XF86DRICloseConnection(dpy, scrn); + XF86DRICloseConnection(dpy, scrn); - ErrorMessageF("reverting to software direct rendering\n"); + ErrorMessageF("reverting to software direct rendering\n"); - return NULL; + return NULL; } #else /* !GLX_USE_APPLEGL */ static void * -CallCreateNewScreen(Display *dpy, int scrn, __GLXscreenConfigs *psc, - __GLXDRIdisplayPrivate * driDpy) +CallCreateNewScreen(Display * dpy, int scrn, __GLXscreenConfigs * psc, + __GLXDRIdisplayPrivate * driDpy) { - return NULL; + return NULL; } #endif /* !GLX_USE_APPLEGL */ -static void driDestroyContext(__GLXDRIcontext *context, - __GLXscreenConfigs *psc, Display *dpy) +static void +driDestroyContext(__GLXDRIcontext * context, + __GLXscreenConfigs * psc, Display * dpy) { - __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context; - - (*psc->core->destroyContext)(pcp->driContext); + __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context; - XF86DRIDestroyContext(psc->dpy, psc->scr, pcp->hwContextID); - Xfree(pcp); + (*psc->core->destroyContext) (pcp->driContext); + + XF86DRIDestroyContext(psc->dpy, psc->scr, pcp->hwContextID); + Xfree(pcp); } -static Bool driBindContext(__GLXDRIcontext *context, - __GLXDRIdrawable *draw, __GLXDRIdrawable *read) +static Bool +driBindContext(__GLXDRIcontext * context, + __GLXDRIdrawable * draw, __GLXDRIdrawable * read) { - __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context; - const __DRIcoreExtension *core = pcp->psc->core; + __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context; + const __DRIcoreExtension *core = pcp->psc->core; - return (*core->bindContext)(pcp->driContext, - draw->driDrawable, - read->driDrawable); + return (*core->bindContext) (pcp->driContext, + draw->driDrawable, read->driDrawable); } -static void driUnbindContext(__GLXDRIcontext *context) +static void +driUnbindContext(__GLXDRIcontext * context) { - __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context; - const __DRIcoreExtension *core = pcp->psc->core; + __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context; + const __DRIcoreExtension *core = pcp->psc->core; - (*core->unbindContext)(pcp->driContext); + (*core->unbindContext) (pcp->driContext); } -static __GLXDRIcontext *driCreateContext(__GLXscreenConfigs *psc, - const __GLcontextModes *mode, - GLXContext gc, - GLXContext shareList, int renderType) +static __GLXDRIcontext * +driCreateContext(__GLXscreenConfigs * psc, + const __GLcontextModes * mode, + GLXContext gc, GLXContext shareList, int renderType) { - __GLXDRIcontextPrivate *pcp, *pcp_shared; - drm_context_t hwContext; - __DRIcontext *shared = NULL; - __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) mode; - - if (!psc || !psc->driScreen) - return NULL; - - if (shareList) { - pcp_shared = (__GLXDRIcontextPrivate *) shareList->driContext; - shared = pcp_shared->driContext; - } - - pcp = Xmalloc(sizeof *pcp); - if (pcp == NULL) - return NULL; - - pcp->psc = psc; - if (!XF86DRICreateContextWithConfig(psc->dpy, psc->scr, - mode->visualID, - &pcp->hwContextID, &hwContext)) { - Xfree(pcp); - return NULL; - } - - pcp->driContext = - (*psc->legacy->createNewContext)(psc->__driScreen, - config->driConfig, - renderType, - shared, - hwContext, - pcp); - if (pcp->driContext == NULL) { - XF86DRIDestroyContext(psc->dpy, psc->scr, pcp->hwContextID); - Xfree(pcp); - return NULL; - } - - pcp->base.destroyContext = driDestroyContext; - pcp->base.bindContext = driBindContext; - pcp->base.unbindContext = driUnbindContext; - - return &pcp->base; + __GLXDRIcontextPrivate *pcp, *pcp_shared; + drm_context_t hwContext; + __DRIcontext *shared = NULL; + __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) mode; + + if (!psc || !psc->driScreen) + return NULL; + + if (shareList) { + pcp_shared = (__GLXDRIcontextPrivate *) shareList->driContext; + shared = pcp_shared->driContext; + } + + pcp = Xmalloc(sizeof *pcp); + if (pcp == NULL) + return NULL; + + pcp->psc = psc; + if (!XF86DRICreateContextWithConfig(psc->dpy, psc->scr, + mode->visualID, + &pcp->hwContextID, &hwContext)) { + Xfree(pcp); + return NULL; + } + + pcp->driContext = + (*psc->legacy->createNewContext) (psc->__driScreen, + config->driConfig, + renderType, shared, hwContext, pcp); + if (pcp->driContext == NULL) { + XF86DRIDestroyContext(psc->dpy, psc->scr, pcp->hwContextID); + Xfree(pcp); + return NULL; + } + + pcp->base.destroyContext = driDestroyContext; + pcp->base.bindContext = driBindContext; + pcp->base.unbindContext = driUnbindContext; + + return &pcp->base; } -static void driDestroyDrawable(__GLXDRIdrawable *pdraw) +static void +driDestroyDrawable(__GLXDRIdrawable * pdraw) { - __GLXscreenConfigs *psc = pdraw->psc; + __GLXscreenConfigs *psc = pdraw->psc; - (*psc->core->destroyDrawable)(pdraw->driDrawable); - XF86DRIDestroyDrawable(psc->dpy, psc->scr, pdraw->drawable); - Xfree(pdraw); + (*psc->core->destroyDrawable) (pdraw->driDrawable); + XF86DRIDestroyDrawable(psc->dpy, psc->scr, pdraw->drawable); + Xfree(pdraw); } -static __GLXDRIdrawable *driCreateDrawable(__GLXscreenConfigs *psc, - XID xDrawable, - GLXDrawable drawable, - const __GLcontextModes *modes) +static __GLXDRIdrawable * +driCreateDrawable(__GLXscreenConfigs * psc, + XID xDrawable, + GLXDrawable drawable, const __GLcontextModes * modes) { - __GLXDRIdrawable *pdraw; - drm_drawable_t hwDrawable; - void *empty_attribute_list = NULL; - __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes; - - /* Old dri can't handle GLX 1.3+ drawable constructors. */ - if (xDrawable != drawable) - return NULL; - - pdraw = Xmalloc(sizeof(*pdraw)); - if (!pdraw) - return NULL; - - pdraw->drawable = drawable; - pdraw->psc = psc; - - if (!XF86DRICreateDrawable(psc->dpy, psc->scr, drawable, &hwDrawable)) - return NULL; - - /* Create a new drawable */ - pdraw->driDrawable = - (*psc->legacy->createNewDrawable)(psc->__driScreen, - config->driConfig, - hwDrawable, - GLX_WINDOW_BIT, - empty_attribute_list, - pdraw); - - if (!pdraw->driDrawable) { - XF86DRIDestroyDrawable(psc->dpy, psc->scr, drawable); - Xfree(pdraw); - return NULL; - } - - pdraw->destroyDrawable = driDestroyDrawable; - - return pdraw; + __GLXDRIdrawable *pdraw; + drm_drawable_t hwDrawable; + void *empty_attribute_list = NULL; + __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes; + + /* Old dri can't handle GLX 1.3+ drawable constructors. */ + if (xDrawable != drawable) + return NULL; + + pdraw = Xmalloc(sizeof(*pdraw)); + if (!pdraw) + return NULL; + + pdraw->drawable = drawable; + pdraw->psc = psc; + + if (!XF86DRICreateDrawable(psc->dpy, psc->scr, drawable, &hwDrawable)) + return NULL; + + /* Create a new drawable */ + pdraw->driDrawable = + (*psc->legacy->createNewDrawable) (psc->__driScreen, + config->driConfig, + hwDrawable, + GLX_WINDOW_BIT, + empty_attribute_list, pdraw); + + if (!pdraw->driDrawable) { + XF86DRIDestroyDrawable(psc->dpy, psc->scr, drawable); + Xfree(pdraw); + return NULL; + } + + pdraw->destroyDrawable = driDestroyDrawable; + + return pdraw; } -static void driSwapBuffers(__GLXDRIdrawable *pdraw) +static void +driSwapBuffers(__GLXDRIdrawable * pdraw) { - (*pdraw->psc->core->swapBuffers)(pdraw->driDrawable); + (*pdraw->psc->core->swapBuffers) (pdraw->driDrawable); } -static void driCopySubBuffer(__GLXDRIdrawable *pdraw, - int x, int y, int width, int height) +static void +driCopySubBuffer(__GLXDRIdrawable * pdraw, + int x, int y, int width, int height) { - (*pdraw->psc->driCopySubBuffer->copySubBuffer)(pdraw->driDrawable, - x, y, width, height); + (*pdraw->psc->driCopySubBuffer->copySubBuffer) (pdraw->driDrawable, + x, y, width, height); } -static void driDestroyScreen(__GLXscreenConfigs *psc) +static void +driDestroyScreen(__GLXscreenConfigs * psc) { - /* Free the direct rendering per screen data */ - if (psc->__driScreen) - (*psc->core->destroyScreen)(psc->__driScreen); - psc->__driScreen = NULL; - if (psc->driver) - dlclose(psc->driver); + /* Free the direct rendering per screen data */ + if (psc->__driScreen) + (*psc->core->destroyScreen) (psc->__driScreen); + psc->__driScreen = NULL; + if (psc->driver) + dlclose(psc->driver); } -static __GLXDRIscreen *driCreateScreen(__GLXscreenConfigs *psc, int screen, - __GLXdisplayPrivate *priv) +static __GLXDRIscreen * +driCreateScreen(__GLXscreenConfigs * psc, int screen, + __GLXdisplayPrivate * priv) { - __GLXDRIdisplayPrivate *pdp; - __GLXDRIscreen *psp; - const __DRIextension **extensions; - char *driverName; - int i; - - psp = Xcalloc(1, sizeof *psp); - if (psp == NULL) - return NULL; - - /* Initialize per screen dynamic client GLX extensions */ - psc->ext_list_first_time = GL_TRUE; - - if (!driGetDriverName(priv->dpy, screen, &driverName)) { - Xfree(psp); - return NULL; - } - - psc->driver = driOpenDriver(driverName); - Xfree(driverName); - if (psc->driver == NULL) { - Xfree(psp); - return NULL; - } - - extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS); - if (extensions == NULL) { - ErrorMessageF("driver exports no extensions (%s)\n", dlerror()); - Xfree(psp); - return NULL; - } - - for (i = 0; extensions[i]; i++) { - if (strcmp(extensions[i]->name, __DRI_CORE) == 0) - psc->core = (__DRIcoreExtension *) extensions[i]; - if (strcmp(extensions[i]->name, __DRI_LEGACY) == 0) - psc->legacy = (__DRIlegacyExtension *) extensions[i]; - } - - if (psc->core == NULL || psc->legacy == NULL) { - Xfree(psp); - return NULL; - } - - pdp = (__GLXDRIdisplayPrivate *) priv->driDisplay; - psc->__driScreen = - CallCreateNewScreen(psc->dpy, screen, psc, pdp); - if (psc->__driScreen == NULL) { - dlclose(psc->driver); - Xfree(psp); - return NULL; - } - - driBindExtensions(psc, 0); - if (psc->driCopySubBuffer) - psp->copySubBuffer = driCopySubBuffer; - - psp->destroyScreen = driDestroyScreen; - psp->createContext = driCreateContext; - psp->createDrawable = driCreateDrawable; - psp->swapBuffers = driSwapBuffers; - psp->waitX = NULL; - psp->waitGL = NULL; - - return psp; + __GLXDRIdisplayPrivate *pdp; + __GLXDRIscreen *psp; + const __DRIextension **extensions; + char *driverName; + int i; + + psp = Xcalloc(1, sizeof *psp); + if (psp == NULL) + return NULL; + + /* Initialize per screen dynamic client GLX extensions */ + psc->ext_list_first_time = GL_TRUE; + + if (!driGetDriverName(priv->dpy, screen, &driverName)) { + Xfree(psp); + return NULL; + } + + psc->driver = driOpenDriver(driverName); + Xfree(driverName); + if (psc->driver == NULL) { + Xfree(psp); + return NULL; + } + + extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS); + if (extensions == NULL) { + ErrorMessageF("driver exports no extensions (%s)\n", dlerror()); + Xfree(psp); + return NULL; + } + + for (i = 0; extensions[i]; i++) { + if (strcmp(extensions[i]->name, __DRI_CORE) == 0) + psc->core = (__DRIcoreExtension *) extensions[i]; + if (strcmp(extensions[i]->name, __DRI_LEGACY) == 0) + psc->legacy = (__DRIlegacyExtension *) extensions[i]; + } + + if (psc->core == NULL || psc->legacy == NULL) { + Xfree(psp); + return NULL; + } + + pdp = (__GLXDRIdisplayPrivate *) priv->driDisplay; + psc->__driScreen = CallCreateNewScreen(psc->dpy, screen, psc, pdp); + if (psc->__driScreen == NULL) { + dlclose(psc->driver); + Xfree(psp); + return NULL; + } + + driBindExtensions(psc, 0); + if (psc->driCopySubBuffer) + psp->copySubBuffer = driCopySubBuffer; + + psp->destroyScreen = driDestroyScreen; + psp->createContext = driCreateContext; + psp->createDrawable = driCreateDrawable; + psp->swapBuffers = driSwapBuffers; + psp->waitX = NULL; + psp->waitGL = NULL; + + return psp; } /* Called from __glXFreeDisplayPrivate. */ -static void driDestroyDisplay(__GLXDRIdisplay *dpy) +static void +driDestroyDisplay(__GLXDRIdisplay * dpy) { - Xfree(dpy); + Xfree(dpy); } /* @@ -712,33 +726,34 @@ static void driDestroyDisplay(__GLXDRIdisplay *dpy) * This is called from __glXInitialize() when we are given a new * display pointer. */ -_X_HIDDEN __GLXDRIdisplay *driCreateDisplay(Display *dpy) +_X_HIDDEN __GLXDRIdisplay * +driCreateDisplay(Display * dpy) { - __GLXDRIdisplayPrivate *pdpyp; - int eventBase, errorBase; - int major, minor, patch; + __GLXDRIdisplayPrivate *pdpyp; + int eventBase, errorBase; + int major, minor, patch; - if (!XF86DRIQueryExtension(dpy, &eventBase, &errorBase)) { - return NULL; - } + if (!XF86DRIQueryExtension(dpy, &eventBase, &errorBase)) { + return NULL; + } - if (!XF86DRIQueryVersion(dpy, &major, &minor, &patch)) { - return NULL; - } + if (!XF86DRIQueryVersion(dpy, &major, &minor, &patch)) { + return NULL; + } - pdpyp = Xmalloc(sizeof *pdpyp); - if (!pdpyp) { - return NULL; - } + pdpyp = Xmalloc(sizeof *pdpyp); + if (!pdpyp) { + return NULL; + } - pdpyp->driMajor = major; - pdpyp->driMinor = minor; - pdpyp->driPatch = patch; + pdpyp->driMajor = major; + pdpyp->driMinor = minor; + pdpyp->driPatch = patch; - pdpyp->base.destroyDisplay = driDestroyDisplay; - pdpyp->base.createScreen = driCreateScreen; + pdpyp->base.destroyDisplay = driDestroyDisplay; + pdpyp->base.createScreen = driCreateScreen; - return &pdpyp->base; + return &pdpyp->base; } #endif /* GLX_DIRECT_RENDERING */ diff --git a/src/glx/x11/glx_pbuffer.c b/src/glx/x11/glx_pbuffer.c index a06331fd7f..88a17df6f8 100644 --- a/src/glx/x11/glx_pbuffer.c +++ b/src/glx/x11/glx_pbuffer.c @@ -25,7 +25,7 @@ /** * \file glx_pbuffer.c * Implementation of pbuffer related functions. - * + * * \author Ian Romanick <idr@us.ibm.com> */ @@ -114,7 +114,7 @@ ChangeDrawableAttribute(Display * dpy, GLXDrawable drawable, * \note * This function dynamically determines whether to use the SGIX_pbuffer * version of the protocol or the GLX 1.3 version of the protocol. - * + * * \todo * This function needs to be modified to work with direct-rendering drivers. */ @@ -198,7 +198,7 @@ determineTextureFormat(const int *attribs, int numAttribs) for (i = 0; i < numAttribs; i++) { if (attribs[2 * i] == GLX_TEXTURE_FORMAT_EXT) - return attribs[2 * i + 1]; + return attribs[2 * i + 1]; } return 0; @@ -681,8 +681,7 @@ GLX_ALIAS_VOID(glXDestroyGLXPbufferSGIX, PUBLIC GLX_ALIAS_VOID(glXSelectEventSGIX, (Display * dpy, GLXDrawable drawable, - unsigned long mask), (dpy, drawable, mask), - glXSelectEvent) + unsigned long mask), (dpy, drawable, mask), glXSelectEvent) PUBLIC GLX_ALIAS_VOID(glXGetSelectedEventSGIX, diff --git a/src/glx/x11/glx_query.c b/src/glx/x11/glx_query.c index 2789b841b1..efad13d376 100644 --- a/src/glx/x11/glx_query.c +++ b/src/glx/x11/glx_query.c @@ -25,7 +25,7 @@ /** * \file glx_query.c * Generic utility functions to query internal data from the server. - * + * * \author Ian Romanick <idr@us.ibm.com> */ @@ -43,13 +43,10 @@ * Exchange a protocol request for glXQueryServerString. */ char * -__glXQueryServerString(Display* dpy, - int opcode, - CARD32 screen, - CARD32 name) +__glXQueryServerString(Display * dpy, int opcode, CARD32 screen, CARD32 name) { xcb_connection_t *c = XGetXCBConnection(dpy); - xcb_glx_query_server_string_reply_t* reply = + xcb_glx_query_server_string_reply_t *reply = xcb_glx_query_server_string_reply(c, xcb_glx_query_server_string(c, screen, @@ -59,7 +56,7 @@ __glXQueryServerString(Display* dpy, /* The spec doesn't mention this, but the Xorg server replies with * a string already terminated with '\0'. */ uint32_t len = xcb_glx_query_server_string_string_length(reply); - char* buf = Xmalloc(len); + char *buf = Xmalloc(len); memcpy(buf, xcb_glx_query_server_string_string(reply), len); free(reply); @@ -70,23 +67,20 @@ __glXQueryServerString(Display* dpy, * Exchange a protocol request for glGetString. */ char * -__glXGetString(Display* dpy, - int opcode, - CARD32 contextTag, - CARD32 name) +__glXGetString(Display * dpy, int opcode, CARD32 contextTag, CARD32 name) { xcb_connection_t *c = XGetXCBConnection(dpy); - xcb_glx_get_string_reply_t* reply = - xcb_glx_get_string_reply(c, - xcb_glx_get_string(c, - contextTag, - name), - NULL); + xcb_glx_get_string_reply_t *reply = xcb_glx_get_string_reply(c, + xcb_glx_get_string + (c, + contextTag, + name), + NULL); /* The spec doesn't mention this, but the Xorg server replies with * a string already terminated with '\0'. */ uint32_t len = xcb_glx_get_string_string_length(reply); - char* buf = Xmalloc(len); + char *buf = Xmalloc(len); memcpy(buf, xcb_glx_get_string_string(reply), len); free(reply); @@ -97,7 +91,7 @@ __glXGetString(Display* dpy, /** * GLX protocol structure for the ficticious "GXLGenericGetString" request. - * + * * This is a non-existant protocol packet. It just so happens that all of * the real protocol packets used to request a string from the server have * an identical binary layout. The only difference between them is the @@ -167,25 +161,17 @@ __glXGetStringFromServer(Display * dpy, int opcode, CARD32 glxCode, } char * -__glXQueryServerString(Display* dpy, - int opcode, - CARD32 screen, - CARD32 name) +__glXQueryServerString(Display * dpy, int opcode, CARD32 screen, CARD32 name) { return __glXGetStringFromServer(dpy, opcode, - X_GLXQueryServerString, - screen, name); + X_GLXQueryServerString, screen, name); } char * -__glXGetString(Display* dpy, - int opcode, - CARD32 contextTag, - CARD32 name) +__glXGetString(Display * dpy, int opcode, CARD32 contextTag, CARD32 name) { return __glXGetStringFromServer(dpy, opcode, X_GLsop_GetString, contextTag, name); } #endif /* USE_XCB */ - diff --git a/src/glx/x11/glxclient.h b/src/glx/x11/glxclient.h index 09db8ea6a6..00ee14fb05 100644 --- a/src/glx/x11/glxclient.h +++ b/src/glx/x11/glxclient.h @@ -65,7 +65,7 @@ /* If we build the library with gcc's -fvisibility=hidden flag, we'll * use the PUBLIC macro to mark functions that are to be exported. * - * We also need to define a USED attribute, so the optimizer doesn't + * We also need to define a USED attribute, so the optimizer doesn't * inline a static function that we later use in an alias. - ajax */ #if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 303 @@ -78,8 +78,8 @@ -#define GLX_MAJOR_VERSION 1 /* current version numbers */ -#define GLX_MINOR_VERSION 4 +#define GLX_MAJOR_VERSION 1 /* current version numbers */ +#define GLX_MINOR_VERSION 4 #define __GLX_MAX_TEXTURE_UNITS 32 @@ -93,7 +93,7 @@ typedef struct _glapi_table __GLapi; #ifdef GLX_DIRECT_RENDERING -#define containerOf(ptr, type, member) \ +#define containerOf(ptr, type, member) \ (type *)( (char *)ptr - offsetof(type,member) ) #include <GL/internal/dri_interface.h> @@ -110,75 +110,78 @@ typedef struct __GLXDRIcontextRec __GLXDRIcontext; #include "glxextensions.h" -struct __GLXDRIdisplayRec { +struct __GLXDRIdisplayRec +{ /** * Method to destroy the private DRI display data. */ - void (*destroyDisplay)(__GLXDRIdisplay *display); + void (*destroyDisplay) (__GLXDRIdisplay * display); - __GLXDRIscreen *(*createScreen)(__GLXscreenConfigs *psc, int screen, - __GLXdisplayPrivate *priv); + __GLXDRIscreen *(*createScreen) (__GLXscreenConfigs * psc, int screen, + __GLXdisplayPrivate * priv); }; -struct __GLXDRIscreenRec { - - void (*destroyScreen)(__GLXscreenConfigs *psc); - - __GLXDRIcontext *(*createContext)(__GLXscreenConfigs *psc, - const __GLcontextModes *mode, - GLXContext gc, - GLXContext shareList, int renderType); - - __GLXDRIdrawable *(*createDrawable)(__GLXscreenConfigs *psc, - XID drawable, - GLXDrawable glxDrawable, - const __GLcontextModes *modes); - - void (*swapBuffers)(__GLXDRIdrawable *pdraw); - void (*copySubBuffer)(__GLXDRIdrawable *pdraw, - int x, int y, int width, int height); - void (*waitX)(__GLXDRIdrawable *pdraw); - void (*waitGL)(__GLXDRIdrawable *pdraw); +struct __GLXDRIscreenRec +{ + + void (*destroyScreen) (__GLXscreenConfigs * psc); + + __GLXDRIcontext *(*createContext) (__GLXscreenConfigs * psc, + const __GLcontextModes * mode, + GLXContext gc, + GLXContext shareList, int renderType); + + __GLXDRIdrawable *(*createDrawable) (__GLXscreenConfigs * psc, + XID drawable, + GLXDrawable glxDrawable, + const __GLcontextModes * modes); + + void (*swapBuffers) (__GLXDRIdrawable * pdraw); + void (*copySubBuffer) (__GLXDRIdrawable * pdraw, + int x, int y, int width, int height); + void (*waitX) (__GLXDRIdrawable * pdraw); + void (*waitGL) (__GLXDRIdrawable * pdraw); }; -struct __GLXDRIcontextRec { - void (*destroyContext)(__GLXDRIcontext *context, __GLXscreenConfigs *psc, - Display *dpy); - Bool (*bindContext)(__GLXDRIcontext *context, - __GLXDRIdrawable *pdraw, - __GLXDRIdrawable *pread); - - void (*unbindContext)(__GLXDRIcontext *context); +struct __GLXDRIcontextRec +{ + void (*destroyContext) (__GLXDRIcontext * context, + __GLXscreenConfigs * psc, Display * dpy); + Bool(*bindContext) (__GLXDRIcontext * context, __GLXDRIdrawable * pdraw, + __GLXDRIdrawable * pread); + + void (*unbindContext) (__GLXDRIcontext * context); }; -struct __GLXDRIdrawableRec { - void (*destroyDrawable)(__GLXDRIdrawable *drawable); +struct __GLXDRIdrawableRec +{ + void (*destroyDrawable) (__GLXDRIdrawable * drawable); - XID xDrawable; - XID drawable; - __GLXscreenConfigs *psc; - GLenum textureTarget; - __DRIdrawable *driDrawable; - GLenum textureFormat; /* EXT_texture_from_pixmap support */ + XID xDrawable; + XID drawable; + __GLXscreenConfigs *psc; + GLenum textureTarget; + __DRIdrawable *driDrawable; + GLenum textureFormat; /* EXT_texture_from_pixmap support */ }; /* ** Function to create and DRI display data and initialize the display ** dependent methods. */ -extern __GLXDRIdisplay *driswCreateDisplay(Display *dpy); -extern __GLXDRIdisplay *driCreateDisplay(Display *dpy); -extern __GLXDRIdisplay *dri2CreateDisplay(Display *dpy); +extern __GLXDRIdisplay *driswCreateDisplay(Display * dpy); +extern __GLXDRIdisplay *driCreateDisplay(Display * dpy); +extern __GLXDRIdisplay *dri2CreateDisplay(Display * dpy); -extern void DRI_glXUseXFont( Font font, int first, int count, int listbase ); +extern void DRI_glXUseXFont(Font font, int first, int count, int listbase); /* ** Functions to obtain driver configuration information from a direct ** rendering client application */ -extern const char *glXGetScreenDriver (Display *dpy, int scrNum); +extern const char *glXGetScreenDriver(Display * dpy, int scrNum); -extern const char *glXGetDriverConfig (const char *driverName); +extern const char *glXGetDriverConfig(const char *driverName); #endif @@ -186,53 +189,57 @@ extern const char *glXGetDriverConfig (const char *driverName); #define __GL_CLIENT_ATTRIB_STACK_DEPTH 16 -typedef struct __GLXpixelStoreModeRec { - GLboolean swapEndian; - GLboolean lsbFirst; - GLuint rowLength; - GLuint imageHeight; - GLuint imageDepth; - GLuint skipRows; - GLuint skipPixels; - GLuint skipImages; - GLuint alignment; +typedef struct __GLXpixelStoreModeRec +{ + GLboolean swapEndian; + GLboolean lsbFirst; + GLuint rowLength; + GLuint imageHeight; + GLuint imageDepth; + GLuint skipRows; + GLuint skipPixels; + GLuint skipImages; + GLuint alignment; } __GLXpixelStoreMode; -typedef struct __GLXattributeRec { - GLuint mask; +typedef struct __GLXattributeRec +{ + GLuint mask; /** * Pixel storage state. Most of the pixel store mode state is kept * here and used by the client code to manage the packing and * unpacking of data sent to/received from the server. */ - __GLXpixelStoreMode storePack, storeUnpack; + __GLXpixelStoreMode storePack, storeUnpack; /** * Is EXT_vertex_array / GL 1.1 DrawArrays protocol specifically * disabled? */ - GLboolean NoDrawArraysProtocol; - + GLboolean NoDrawArraysProtocol; + /** * Vertex Array storage state. The vertex array component * state is stored here and is used to manage the packing of * DrawArrays data sent to the server. */ - struct array_state_vector * array_state; + struct array_state_vector *array_state; } __GLXattribute; -typedef struct __GLXattributeMachineRec { - __GLXattribute *stack[__GL_CLIENT_ATTRIB_STACK_DEPTH]; - __GLXattribute **stackPointer; +typedef struct __GLXattributeMachineRec +{ + __GLXattribute *stack[__GL_CLIENT_ATTRIB_STACK_DEPTH]; + __GLXattribute **stackPointer; } __GLXattributeMachine; /** * GLX state that needs to be kept on the client. One of these records * exist for each context that has been made current by this client. */ -struct __GLXcontextRec { +struct __GLXcontextRec +{ /** * \name Drawing command buffer. * @@ -249,13 +256,13 @@ struct __GLXcontextRec { * These must be the first 6 fields since they are static initialized * in the dummy context in glxext.c */ - /*@{*/ - GLubyte *buf; - GLubyte *pc; - GLubyte *limit; - GLubyte *bufEnd; - GLint bufSize; - /*@}*/ + /*@{ */ + GLubyte *buf; + GLubyte *pc; + GLubyte *limit; + GLubyte *bufEnd; + GLint bufSize; + /*@} */ /** * The XID of this rendering context. When the context is created a @@ -263,24 +270,24 @@ struct __GLXcontextRec { * destroyed but is still current to some thread. In this case the * context will be freed on next MakeCurrent. */ - XID xid; + XID xid; /** * The XID of the \c shareList context. */ - XID share_xid; + XID share_xid; /** * Screen number. */ - GLint screen; - __GLXscreenConfigs *psc; + GLint screen; + __GLXscreenConfigs *psc; /** * \c GL_TRUE if the context was created with ImportContext, which * means the server-side context was created by another X client. */ - GLboolean imported; + GLboolean imported; /** * The context tag returned by MakeCurrent when this context is made @@ -290,7 +297,7 @@ struct __GLXcontextRec { * \c WaitX, \c WaitGL, \c UseXFont, and \c MakeCurrent (for the old * context)). */ - GLXContextTag currentContextTag; + GLXContextTag currentContextTag; /** * \name Rendering mode @@ -299,11 +306,11 @@ struct __GLXcontextRec { * When \c glRenderMode is called, the buffer associated with the * previous rendering mode (feedback or select) is filled. */ - /*@{*/ - GLenum renderMode; - GLfloat *feedbackBuf; - GLuint *selectBuf; - /*@}*/ + /*@{ */ + GLenum renderMode; + GLfloat *feedbackBuf; + GLuint *selectBuf; + /*@} */ /** * This is \c GL_TRUE if the pixel unpack modes are such that an image @@ -311,43 +318,43 @@ struct __GLXcontextRec { * still be true that the server will have to do some work. This * just promises that a straight copy will fetch the correct bytes. */ - GLboolean fastImageUnpack; + GLboolean fastImageUnpack; /** * Fill newImage with the unpacked form of \c oldImage getting it * ready for transport to the server. */ - void (*fillImage)(__GLXcontext*, GLint, GLint, GLint, GLint, GLenum, - GLenum, const GLvoid*, GLubyte*, GLubyte*); + void (*fillImage) (__GLXcontext *, GLint, GLint, GLint, GLint, GLenum, + GLenum, const GLvoid *, GLubyte *, GLubyte *); /** * Client side attribs. */ - __GLXattributeMachine attributes; + __GLXattributeMachine attributes; /** * Client side error code. This is set when client side gl API * routines need to set an error because of a bad enumerant or * running out of memory, etc. */ - GLenum error; + GLenum error; /** * Whether this context does direct rendering. */ - Bool isDirect; + Bool isDirect; /** * \c dpy of current display for this context. Will be \c NULL if not * current to any display, or if this is the "dummy context". */ - Display *currentDpy; + Display *currentDpy; /** * The current drawable for this context. Will be None if this * context is not current to any drawable. currentReadable is below. */ - GLXDrawable currentDrawable; + GLXDrawable currentDrawable; /** * \name GL Constant Strings @@ -356,38 +363,38 @@ struct __GLXcontextRec { * These pertain to GL attributes, not to be confused with * GLX versioning attributes. */ - /*@{*/ - GLubyte *vendor; - GLubyte *renderer; - GLubyte *version; - GLubyte *extensions; - /*@}*/ + /*@{ */ + GLubyte *vendor; + GLubyte *renderer; + GLubyte *version; + GLubyte *extensions; + /*@} */ /** * Record the dpy this context was created on for later freeing */ - Display *createDpy; + Display *createDpy; /** * Maximum small render command size. This is the smaller of 64k and * the size of the above buffer. */ - GLint maxSmallRenderCommandSize; + GLint maxSmallRenderCommandSize; /** * Major opcode for the extension. Copied here so a lookup isn't * needed. */ - GLint majorOpcode; + GLint majorOpcode; /** * Pointer to the mode used to create this context. */ - const __GLcontextModes * mode; + const __GLcontextModes *mode; #ifdef GLX_DIRECT_RENDERING - __GLXDRIcontext *driContext; - __DRIcontext *__driContext; + __GLXDRIcontext *driContext; + __DRIcontext *__driContext; #endif /** @@ -396,22 +403,22 @@ struct __GLXcontextRec { * * \since Internal API version 20030606. */ - GLXDrawable currentReadable; + GLXDrawable currentReadable; - /** + /** * Pointer to client-state data that is private to libGL. This is only * used for indirect rendering contexts. * * No internal API version change was made for this change. Client-side * drivers should NEVER use this data or even care that it exists. */ - void * client_state_private; + void *client_state_private; /** * Stored value for \c glXQueryContext attribute \c GLX_RENDER_TYPE. */ int renderType; - + /** * \name Raw server GL version * @@ -419,23 +426,23 @@ struct __GLXcontextRec { * returned by the server, and it may not reflect what is actually * supported (or reported) by the client-side library. */ - /*@{*/ + /*@{ */ int server_major; /**< Major version number. */ int server_minor; /**< Minor version number. */ - /*@}*/ + /*@} */ /** * Thread ID we're currently current in. Zero if none. */ unsigned long thread_id; - char gl_extension_bits[ __GL_EXT_BYTES ]; + char gl_extension_bits[__GL_EXT_BYTES]; }; -#define __glXSetError(gc,code) \ - if (!(gc)->error) { \ - (gc)->error = code; \ - } +#define __glXSetError(gc,code) \ + if (!(gc)->error) { \ + (gc)->error = code; \ + } extern void __glFreeAttributeState(__GLXcontext *); @@ -446,7 +453,7 @@ extern void __glFreeAttributeState(__GLXcontext *); * that will use the GLXRender GLX command. In this case it is * \c glPolygonStipple. */ -#define __GLX_MAX_SMALL_RENDER_CMD_SIZE 156 +#define __GLX_MAX_SMALL_RENDER_CMD_SIZE 156 /** * To keep the implementation fast, the code uses a "limit" pointer @@ -458,75 +465,76 @@ extern void __glFreeAttributeState(__GLXcontext *); * efficacy of the buffer. The "+32" is just to keep the code working * in case somebody counts wrong. */ -#define __GLX_BUFFER_LIMIT_SIZE (__GLX_MAX_SMALL_RENDER_CMD_SIZE + 32) +#define __GLX_BUFFER_LIMIT_SIZE (__GLX_MAX_SMALL_RENDER_CMD_SIZE + 32) /** * This implementation uses a smaller threshold for switching * to the RenderLarge protocol than the protcol requires so that * large copies don't occur. */ -#define __GLX_RENDER_CMD_SIZE_LIMIT 4096 +#define __GLX_RENDER_CMD_SIZE_LIMIT 4096 /** * One of these records exists per screen of the display. It contains * a pointer to the config data for that screen (if the screen supports GL). */ -struct __GLXscreenConfigsRec { +struct __GLXscreenConfigsRec +{ /** * GLX extension string reported by the X-server. */ - const char *serverGLXexts; + const char *serverGLXexts; /** * GLX extension string to be reported to applications. This is the * set of extensions that the application can actually use. */ - char *effectiveGLXexts; + char *effectiveGLXexts; #ifdef GLX_DIRECT_RENDERING /** * Per screen direct rendering interface functions and data. */ - __DRIscreen *__driScreen; - const __DRIcoreExtension *core; - const __DRIlegacyExtension *legacy; - const __DRIswrastExtension *swrast; - const __DRIdri2Extension *dri2; - __glxHashTable *drawHash; - Display *dpy; - int scr, fd; - void *driver; + __DRIscreen *__driScreen; + const __DRIcoreExtension *core; + const __DRIlegacyExtension *legacy; + const __DRIswrastExtension *swrast; + const __DRIdri2Extension *dri2; + __glxHashTable *drawHash; + Display *dpy; + int scr, fd; + void *driver; - __GLXDRIscreen *driScreen; + __GLXDRIscreen *driScreen; - const __DRIconfig** driver_configs; + const __DRIconfig **driver_configs; #ifdef __DRI_COPY_SUB_BUFFER - const __DRIcopySubBufferExtension *driCopySubBuffer; + const __DRIcopySubBufferExtension *driCopySubBuffer; #endif #ifdef __DRI_SWAP_CONTROL - const __DRIswapControlExtension *swapControl; + const __DRIswapControlExtension *swapControl; #endif #ifdef __DRI_ALLOCATE - const __DRIallocateExtension *allocate; + const __DRIallocateExtension *allocate; #endif #ifdef __DRI_FRAME_TRACKING - const __DRIframeTrackingExtension *frameTracking; + const __DRIframeTrackingExtension *frameTracking; #endif #ifdef __DRI_MEDIA_STREAM_COUNTER - const __DRImediaStreamCounterExtension *msc; + const __DRImediaStreamCounterExtension *msc; #endif #ifdef __DRI_TEX_BUFFER - const __DRItexBufferExtension *texBuffer; + const __DRItexBufferExtension *texBuffer; #endif #ifdef __DRI2_FLUSH - const __DRI2flushExtension *f; + const __DRI2flushExtension *f; #endif #endif @@ -534,7 +542,7 @@ struct __GLXscreenConfigsRec { /** * Linked list of glx visuals and fbconfigs for this screen. */ - __GLcontextModes *visuals, *configs; + __GLcontextModes *visuals, *configs; /** * Per-screen dynamic GLX extension tracking. The \c direct_support @@ -543,10 +551,10 @@ struct __GLXscreenConfigsRec { * this field. The \c __GLXscreenConfigs structure is not used outside * libGL. */ - /*@{*/ - unsigned char direct_support[8]; - GLboolean ext_list_first_time; - /*@}*/ + /*@{ */ + unsigned char direct_support[8]; + GLboolean ext_list_first_time; + /*@} */ }; @@ -554,67 +562,68 @@ struct __GLXscreenConfigsRec { * Per display private data. One of these records exists for each display * that is using the OpenGL (GLX) extension. */ -struct __GLXdisplayPrivateRec { +struct __GLXdisplayPrivateRec +{ /** * Back pointer to the display */ - Display *dpy; + Display *dpy; /** * The \c majorOpcode is common to all connections to the same server. * It is also copied into the context structure. */ - int majorOpcode; + int majorOpcode; /** * \name Server Version * * Major and minor version returned by the server during initialization. */ - /*@{*/ - int majorVersion, minorVersion; - /*@}*/ + /*@{ */ + int majorVersion, minorVersion; + /*@} */ /** * \name Storage for the servers GLX vendor and versions strings. - * + * * These are the same for all screens on this display. These fields will * be filled in on demand. */ - /*@{*/ - const char *serverGLXvendor; - const char *serverGLXversion; - /*@}*/ + /*@{ */ + const char *serverGLXvendor; + const char *serverGLXversion; + /*@} */ /** * Configurations of visuals for all screens on this display. * Also, per screen data which now includes the server \c GLX_EXTENSION * string. */ - __GLXscreenConfigs *screenConfigs; + __GLXscreenConfigs *screenConfigs; #ifdef GLX_DIRECT_RENDERING /** * Per display direct rendering interface functions and data. */ - __GLXDRIdisplay *driswDisplay; - __GLXDRIdisplay *driDisplay; - __GLXDRIdisplay *dri2Display; + __GLXDRIdisplay *driswDisplay; + __GLXDRIdisplay *driDisplay; + __GLXDRIdisplay *dri2Display; #endif }; -extern GLubyte *__glXFlushRenderBuffer(__GLXcontext*, GLubyte*); +extern GLubyte *__glXFlushRenderBuffer(__GLXcontext *, GLubyte *); -extern void __glXSendLargeChunk(__GLXcontext *gc, GLint requestNumber, - GLint totalRequests, - const GLvoid * data, GLint dataLen); +extern void __glXSendLargeChunk(__GLXcontext * gc, GLint requestNumber, + GLint totalRequests, + const GLvoid * data, GLint dataLen); extern void __glXSendLargeCommand(__GLXcontext *, const GLvoid *, GLint, - const GLvoid *, GLint); + const GLvoid *, GLint); /* Initialize the GLX extension for dpy */ -extern __GLXdisplayPrivate *__glXInitialize(Display*); +extern __GLXdisplayPrivate *__glXInitialize(Display *); extern void __glXPreferEGL(int state); @@ -625,14 +634,14 @@ extern int __glXDebug; /* This is per-thread storage in an MT environment */ #if defined( PTHREADS ) -extern void __glXSetCurrentContext(__GLXcontext *c); +extern void __glXSetCurrentContext(__GLXcontext * c); # if defined( GLX_USE_TLS ) -extern __thread void * __glX_tls_Context - __attribute__((tls_model("initial-exec"))); +extern __thread void *__glX_tls_Context + __attribute__ ((tls_model("initial-exec"))); -# define __glXGetCurrentContext() __glX_tls_Context +# define __glXGetCurrentContext() __glX_tls_Context # else @@ -643,14 +652,14 @@ extern __GLXcontext *__glXGetCurrentContext(void); #else extern __GLXcontext *__glXcurrentContext; -#define __glXGetCurrentContext() __glXcurrentContext -#define __glXSetCurrentContext(gc) __glXcurrentContext = gc +#define __glXGetCurrentContext() __glXcurrentContext +#define __glXSetCurrentContext(gc) __glXcurrentContext = gc #endif /* defined( PTHREADS ) */ extern void __glXSetCurrentContextNull(void); -extern void __glXFreeContext(__GLXcontext*); +extern void __glXFreeContext(__GLXcontext *); /* @@ -669,7 +678,7 @@ extern pthread_mutex_t __glXmutex; /* ** Setup for a command. Initialize the extension for dpy if necessary. */ -extern CARD8 __glXSetupForCommand(Display *dpy); +extern CARD8 __glXSetupForCommand(Display * dpy); /************************************************************************/ @@ -680,9 +689,11 @@ extern CARD8 __glXSetupForCommand(Display *dpy); extern const GLuint __glXDefaultPixelStore[9]; /* Send an image to the server using RenderLarge. */ -extern void __glXSendLargeImage(__GLXcontext *gc, GLint compsize, GLint dim, - GLint width, GLint height, GLint depth, GLenum format, GLenum type, - const GLvoid *src, GLubyte *pc, GLubyte *modes); +extern void __glXSendLargeImage(__GLXcontext * gc, GLint compsize, GLint dim, + GLint width, GLint height, GLint depth, + GLenum format, GLenum type, + const GLvoid * src, GLubyte * pc, + GLubyte * modes); /* Return the size, in bytes, of some pixel data */ extern GLint __glImageSize(GLint, GLint, GLint, GLenum, GLenum, GLenum); @@ -702,23 +713,23 @@ extern GLint __glBytesPerElement(GLenum type); ** updated to contain the modes needed by the server to decode the ** sent data. */ -extern void __glFillImage(__GLXcontext*, GLint, GLint, GLint, GLint, GLenum, - GLenum, const GLvoid*, GLubyte*, GLubyte*); +extern void __glFillImage(__GLXcontext *, GLint, GLint, GLint, GLint, GLenum, + GLenum, const GLvoid *, GLubyte *, GLubyte *); /* Copy map data with a stride into a packed buffer */ extern void __glFillMap1f(GLint, GLint, GLint, const GLfloat *, GLubyte *); extern void __glFillMap1d(GLint, GLint, GLint, const GLdouble *, GLubyte *); extern void __glFillMap2f(GLint, GLint, GLint, GLint, GLint, - const GLfloat *, GLfloat *); + const GLfloat *, GLfloat *); extern void __glFillMap2d(GLint, GLint, GLint, GLint, GLint, - const GLdouble *, GLdouble *); + const GLdouble *, GLdouble *); /* ** Empty an image out of the reply buffer into the clients memory applying ** the pack modes to pack back into the clients requested format. */ -extern void __glEmptyImage(__GLXcontext*, GLint, GLint, GLint, GLint, GLenum, - GLenum, const GLubyte *, GLvoid *); +extern void __glEmptyImage(__GLXcontext *, GLint, GLint, GLint, GLint, GLenum, + GLenum, const GLubyte *, GLvoid *); /* @@ -731,7 +742,7 @@ extern void __glXFreeVertexArrayState(__GLXcontext *); ** Inform the Server of the major and minor numbers and of the client ** libraries extension string. */ -extern void __glXClientInfo ( Display *dpy, int opcode ); +extern void __glXClientInfo(Display * dpy, int opcode); /************************************************************************/ @@ -739,20 +750,22 @@ extern void __glXClientInfo ( Display *dpy, int opcode ); ** Declarations that should be in Xlib */ #ifdef __GL_USE_OUR_PROTOTYPES -extern void _XFlush(Display*); -extern Status _XReply(Display*, xReply*, int, Bool); -extern void _XRead(Display*, void*, long); -extern void _XSend(Display*, const void*, long); +extern void _XFlush(Display *); +extern Status _XReply(Display *, xReply *, int, Bool); +extern void _XRead(Display *, void *, long); +extern void _XSend(Display *, const void *, long); #endif -extern void __glXInitializeVisualConfigFromTags( __GLcontextModes *config, - int count, const INT32 *bp, Bool tagged_only, Bool fbconfig_style_tags ); +extern void __glXInitializeVisualConfigFromTags(__GLcontextModes * config, + int count, const INT32 * bp, + Bool tagged_only, + Bool fbconfig_style_tags); -extern char * __glXQueryServerString(Display* dpy, int opcode, - CARD32 screen, CARD32 name); -extern char * __glXGetString(Display* dpy, int opcode, - CARD32 screen, CARD32 name); +extern char *__glXQueryServerString(Display * dpy, int opcode, + CARD32 screen, CARD32 name); +extern char *__glXGetString(Display * dpy, int opcode, + CARD32 screen, CARD32 name); extern char *__glXstrdup(const char *str); @@ -761,15 +774,16 @@ extern const char __glXGLClientVersion[]; extern const char __glXGLClientExtensions[]; /* Get the unadjusted system time */ -extern int __glXGetUST( int64_t * ust ); +extern int __glXGetUST(int64_t * ust); extern GLboolean __glXGetMscRateOML(Display * dpy, GLXDrawable drawable, - int32_t * numerator, int32_t * denominator); + int32_t * numerator, + int32_t * denominator); #ifdef GLX_DIRECT_RENDERING GLboolean -__driGetMscRateOML(__DRIdrawable *draw, - int32_t *numerator, int32_t *denominator, void *private); +__driGetMscRateOML(__DRIdrawable * draw, + int32_t * numerator, int32_t * denominator, void *private); #endif #endif /* !__GLX_client_h__ */ diff --git a/src/glx/x11/glxcmds.c b/src/glx/x11/glxcmds.c index 820d8b9868..7eb23dbaca 100644 --- a/src/glx/x11/glxcmds.c +++ b/src/glx/x11/glxcmds.c @@ -59,56 +59,59 @@ static const char __glXGLXClientVersion[] = "1.4"; #ifdef GLX_DIRECT_RENDERING static Bool windowExistsFlag; -static int windowExistsErrorHandler(Display *dpy, XErrorEvent *xerr) +static int +windowExistsErrorHandler(Display * dpy, XErrorEvent * xerr) { - if (xerr->error_code == BadWindow) { - windowExistsFlag = GL_FALSE; - } - return 0; + if (xerr->error_code == BadWindow) { + windowExistsFlag = GL_FALSE; + } + return 0; } /** * Find drawables in the local hash that have been destroyed on the * server. - * + * * \param dpy Display to destroy drawables for * \param screen Screen number to destroy drawables for */ -static void GarbageCollectDRIDrawables(Display *dpy, __GLXscreenConfigs *sc) -{ - XID draw; - __GLXDRIdrawable *pdraw; - XWindowAttributes xwa; - int (*oldXErrorHandler)(Display *, XErrorEvent *); - - /* Set no-op error handler so Xlib doesn't bail out if the windows - * has alreay been destroyed on the server. */ - XSync(dpy, GL_FALSE); - oldXErrorHandler = XSetErrorHandler(windowExistsErrorHandler); - - if (__glxHashFirst(sc->drawHash, &draw, (void *)&pdraw) == 1) { - do { - windowExistsFlag = GL_TRUE; - XGetWindowAttributes(dpy, draw, &xwa); /* dummy request */ - if (!windowExistsFlag) { - /* Destroy the local drawable data, if the drawable no - longer exists in the Xserver */ - (*pdraw->destroyDrawable)(pdraw); - __glxHashDelete(sc->drawHash, draw); - } - } while (__glxHashNext(sc->drawHash, &draw, (void *)&pdraw) == 1); - } - - XSync(dpy, GL_FALSE); - XSetErrorHandler(oldXErrorHandler); -} - -extern __GLXDRIdrawable * -GetGLXDRIDrawable(Display *dpy, GLXDrawable drawable, int * const scrn_num); +static void +GarbageCollectDRIDrawables(Display * dpy, __GLXscreenConfigs * sc) +{ + XID draw; + __GLXDRIdrawable *pdraw; + XWindowAttributes xwa; + int (*oldXErrorHandler) (Display *, XErrorEvent *); + + /* Set no-op error handler so Xlib doesn't bail out if the windows + * has alreay been destroyed on the server. */ + XSync(dpy, GL_FALSE); + oldXErrorHandler = XSetErrorHandler(windowExistsErrorHandler); + + if (__glxHashFirst(sc->drawHash, &draw, (void *) &pdraw) == 1) { + do { + windowExistsFlag = GL_TRUE; + XGetWindowAttributes(dpy, draw, &xwa); /* dummy request */ + if (!windowExistsFlag) { + /* Destroy the local drawable data, if the drawable no + longer exists in the Xserver */ + (*pdraw->destroyDrawable) (pdraw); + __glxHashDelete(sc->drawHash, draw); + } + } while (__glxHashNext(sc->drawHash, &draw, (void *) &pdraw) == 1); + } + + XSync(dpy, GL_FALSE); + XSetErrorHandler(oldXErrorHandler); +} + +extern __GLXDRIdrawable *GetGLXDRIDrawable(Display * dpy, + GLXDrawable drawable, + int *const scrn_num); /** * Get the __DRIdrawable for the drawable associated with a GLXContext - * + * * \param dpy The display associated with \c drawable. * \param drawable GLXDrawable whose __DRIdrawable part is to be retrieved. * \param scrn_num If non-NULL, the drawables screen is stored there @@ -116,30 +119,30 @@ GetGLXDRIDrawable(Display *dpy, GLXDrawable drawable, int * const scrn_num); * the drawable is not associated with a direct-rendering context. */ _X_HIDDEN __GLXDRIdrawable * -GetGLXDRIDrawable(Display *dpy, GLXDrawable drawable, int * const scrn_num) +GetGLXDRIDrawable(Display * dpy, GLXDrawable drawable, int *const scrn_num) { - __GLXdisplayPrivate *priv = __glXInitialize(dpy); - __GLXDRIdrawable *pdraw; - const unsigned screen_count = ScreenCount(dpy); - unsigned i; - __GLXscreenConfigs *psc; + __GLXdisplayPrivate *priv = __glXInitialize(dpy); + __GLXDRIdrawable *pdraw; + const unsigned screen_count = ScreenCount(dpy); + unsigned i; + __GLXscreenConfigs *psc; - if (priv == NULL) - return NULL; - - for (i = 0; i < screen_count; i++) { - psc = &priv->screenConfigs[i]; - if (psc->drawHash == NULL) - continue; + if (priv == NULL) + return NULL; - if (__glxHashLookup(psc->drawHash, drawable, (void *) &pdraw) == 0) { - if (scrn_num != NULL) - *scrn_num = i; - return pdraw; - } - } + for (i = 0; i < screen_count; i++) { + psc = &priv->screenConfigs[i]; + if (psc->drawHash == NULL) + continue; + + if (__glxHashLookup(psc->drawHash, drawable, (void *) &pdraw) == 0) { + if (scrn_num != NULL) + *scrn_num = i; + return pdraw; + } + } - return NULL; + return NULL; } #endif @@ -147,57 +150,59 @@ GetGLXDRIDrawable(Display *dpy, GLXDrawable drawable, int * const scrn_num) /** * Get the GLX per-screen data structure associated with a GLX context. - * + * * \param dpy Display for which the GLX per-screen information is to be * retrieved. * \param scrn Screen on \c dpy for which the GLX per-screen information is * to be retrieved. * \returns A pointer to the GLX per-screen data if \c dpy and \c scrn * specify a valid GLX screen, or NULL otherwise. - * + * * \todo Should this function validate that \c scrn is within the screen * number range for \c dpy? */ static __GLXscreenConfigs * -GetGLXScreenConfigs(Display *dpy, int scrn) +GetGLXScreenConfigs(Display * dpy, int scrn) { - __GLXdisplayPrivate * const priv = __glXInitialize(dpy); + __GLXdisplayPrivate *const priv = __glXInitialize(dpy); - return (priv && priv->screenConfigs != NULL) ? &priv->screenConfigs[scrn] : NULL; + return (priv + && priv->screenConfigs != + NULL) ? &priv->screenConfigs[scrn] : NULL; } static int -GetGLXPrivScreenConfig( Display *dpy, int scrn, __GLXdisplayPrivate ** ppriv, - __GLXscreenConfigs ** ppsc ) +GetGLXPrivScreenConfig(Display * dpy, int scrn, __GLXdisplayPrivate ** ppriv, + __GLXscreenConfigs ** ppsc) { - /* Initialize the extension, if needed . This has the added value - * of initializing/allocating the display private - */ - - if ( dpy == NULL ) { - return GLX_NO_EXTENSION; - } + /* Initialize the extension, if needed . This has the added value + * of initializing/allocating the display private + */ - *ppriv = __glXInitialize(dpy); - if ( *ppriv == NULL ) { - return GLX_NO_EXTENSION; - } + if (dpy == NULL) { + return GLX_NO_EXTENSION; + } - /* Check screen number to see if its valid */ - if ((scrn < 0) || (scrn >= ScreenCount(dpy))) { - return GLX_BAD_SCREEN; - } + *ppriv = __glXInitialize(dpy); + if (*ppriv == NULL) { + return GLX_NO_EXTENSION; + } - /* Check to see if the GL is supported on this screen */ - *ppsc = &((*ppriv)->screenConfigs[scrn]); - if ( (*ppsc)->configs == NULL ) { - /* No support for GL on this screen regardless of visual */ - return GLX_BAD_VISUAL; - } + /* Check screen number to see if its valid */ + if ((scrn < 0) || (scrn >= ScreenCount(dpy))) { + return GLX_BAD_SCREEN; + } - return Success; + /* Check to see if the GL is supported on this screen */ + *ppsc = &((*ppriv)->screenConfigs[scrn]); + if ((*ppsc)->configs == NULL) { + /* No support for GL on this screen regardless of visual */ + return GLX_BAD_VISUAL; + } + + return Success; } @@ -212,27 +217,26 @@ GetGLXPrivScreenConfig( Display *dpy, int scrn, __GLXdisplayPrivate ** ppriv, * is returned. */ static __GLcontextModes * -ValidateGLXFBConfig( Display * dpy, GLXFBConfig config ) -{ - __GLXdisplayPrivate * const priv = __glXInitialize(dpy); - const unsigned num_screens = ScreenCount(dpy); - unsigned i; - const __GLcontextModes * modes; - - - if ( priv != NULL ) { - for ( i = 0 ; i < num_screens ; i++ ) { - for ( modes = priv->screenConfigs[i].configs - ; modes != NULL - ; modes = modes->next ) { - if ( modes == (__GLcontextModes *) config ) { - return (__GLcontextModes *) config; - } - } - } - } +ValidateGLXFBConfig(Display * dpy, GLXFBConfig config) +{ + __GLXdisplayPrivate *const priv = __glXInitialize(dpy); + const unsigned num_screens = ScreenCount(dpy); + unsigned i; + const __GLcontextModes *modes; + + + if (priv != NULL) { + for (i = 0; i < num_screens; i++) { + for (modes = priv->screenConfigs[i].configs; modes != NULL; + modes = modes->next) { + if (modes == (__GLcontextModes *) config) { + return (__GLcontextModes *) config; + } + } + } + } - return NULL; + return NULL; } @@ -241,471 +245,497 @@ ValidateGLXFBConfig( Display * dpy, GLXFBConfig config ) * later in the function for direct-rendering contexts. Direct-rendering * contexts don't need to track client state, so they don't need that memory * at all. - * + * * \todo Eliminate \c __glXInitVertexArrayState. Replace it with a new * function called \c __glXAllocateClientState that allocates the memory and * does all the initialization (including the pixel pack / unpack). */ -static -GLXContext AllocateGLXContext( Display *dpy ) -{ - GLXContext gc; - int bufSize; - CARD8 opcode; - __GLXattribute *state; - - if (!dpy) - return NULL; - - opcode = __glXSetupForCommand(dpy); - if (!opcode) { - return NULL; - } - - /* Allocate our context record */ - gc = (GLXContext) Xmalloc(sizeof(struct __GLXcontextRec)); - if (!gc) { - /* Out of memory */ - return NULL; - } - memset(gc, 0, sizeof(struct __GLXcontextRec)); - - state = Xmalloc(sizeof(struct __GLXattributeRec)); - if (state == NULL) { - /* Out of memory */ - Xfree(gc); - return NULL; - } - gc->client_state_private = state; - memset(gc->client_state_private, 0, sizeof(struct __GLXattributeRec)); - state->NoDrawArraysProtocol = (getenv("LIBGL_NO_DRAWARRAYS") != NULL); - - /* +static GLXContext +AllocateGLXContext(Display * dpy) +{ + GLXContext gc; + int bufSize; + CARD8 opcode; + __GLXattribute *state; + + if (!dpy) + return NULL; + + opcode = __glXSetupForCommand(dpy); + if (!opcode) { + return NULL; + } + + /* Allocate our context record */ + gc = (GLXContext) Xmalloc(sizeof(struct __GLXcontextRec)); + if (!gc) { + /* Out of memory */ + return NULL; + } + memset(gc, 0, sizeof(struct __GLXcontextRec)); + + state = Xmalloc(sizeof(struct __GLXattributeRec)); + if (state == NULL) { + /* Out of memory */ + Xfree(gc); + return NULL; + } + gc->client_state_private = state; + memset(gc->client_state_private, 0, sizeof(struct __GLXattributeRec)); + state->NoDrawArraysProtocol = (getenv("LIBGL_NO_DRAWARRAYS") != NULL); + + /* ** Create a temporary buffer to hold GLX rendering commands. The size ** of the buffer is selected so that the maximum number of GLX rendering ** commands can fit in a single X packet and still have room in the X ** packet for the GLXRenderReq header. */ - bufSize = (XMaxRequestSize(dpy) * 4) - sz_xGLXRenderReq; - gc->buf = (GLubyte *) Xmalloc(bufSize); - if (!gc->buf) { - Xfree(gc->client_state_private); - Xfree(gc); - return NULL; - } - gc->bufSize = bufSize; + bufSize = (XMaxRequestSize(dpy) * 4) - sz_xGLXRenderReq; + gc->buf = (GLubyte *) Xmalloc(bufSize); + if (!gc->buf) { + Xfree(gc->client_state_private); + Xfree(gc); + return NULL; + } + gc->bufSize = bufSize; - /* Fill in the new context */ - gc->renderMode = GL_RENDER; + /* Fill in the new context */ + gc->renderMode = GL_RENDER; - state->storePack.alignment = 4; - state->storeUnpack.alignment = 4; + state->storePack.alignment = 4; + state->storeUnpack.alignment = 4; - gc->attributes.stackPointer = &gc->attributes.stack[0]; + gc->attributes.stackPointer = &gc->attributes.stack[0]; - /* + /* ** PERFORMANCE NOTE: A mode dependent fill image can speed things up. ** Other code uses the fastImageUnpack bit, but it is never set ** to GL_TRUE. */ - gc->fastImageUnpack = GL_FALSE; - gc->fillImage = __glFillImage; - gc->pc = gc->buf; - gc->bufEnd = gc->buf + bufSize; - gc->isDirect = GL_FALSE; - if (__glXDebug) { - /* - ** Set limit register so that there will be one command per packet - */ - gc->limit = gc->buf; - } else { - gc->limit = gc->buf + bufSize - __GLX_BUFFER_LIMIT_SIZE; - } - gc->createDpy = dpy; - gc->majorOpcode = opcode; - - /* + gc->fastImageUnpack = GL_FALSE; + gc->fillImage = __glFillImage; + gc->pc = gc->buf; + gc->bufEnd = gc->buf + bufSize; + gc->isDirect = GL_FALSE; + if (__glXDebug) { + /* + ** Set limit register so that there will be one command per packet + */ + gc->limit = gc->buf; + } + else { + gc->limit = gc->buf + bufSize - __GLX_BUFFER_LIMIT_SIZE; + } + gc->createDpy = dpy; + gc->majorOpcode = opcode; + + /* ** Constrain the maximum drawing command size allowed to be ** transfered using the X_GLXRender protocol request. First ** constrain by a software limit, then constrain by the protocl ** limit. */ - if (bufSize > __GLX_RENDER_CMD_SIZE_LIMIT) { - bufSize = __GLX_RENDER_CMD_SIZE_LIMIT; - } - if (bufSize > __GLX_MAX_RENDER_CMD_SIZE) { - bufSize = __GLX_MAX_RENDER_CMD_SIZE; - } - gc->maxSmallRenderCommandSize = bufSize; - return gc; + if (bufSize > __GLX_RENDER_CMD_SIZE_LIMIT) { + bufSize = __GLX_RENDER_CMD_SIZE_LIMIT; + } + if (bufSize > __GLX_MAX_RENDER_CMD_SIZE) { + bufSize = __GLX_MAX_RENDER_CMD_SIZE; + } + gc->maxSmallRenderCommandSize = bufSize; + return gc; } /** * Create a new context. Exactly one of \c vis and \c fbconfig should be * non-NULL. - * + * * \param use_glx_1_3 For FBConfigs, should GLX 1.3 protocol or * SGIX_fbconfig protocol be used? * \param renderType For FBConfigs, what is the rendering type? */ static GLXContext -CreateContext(Display *dpy, XVisualInfo *vis, - const __GLcontextModes * const fbconfig, - GLXContext shareList, - Bool allowDirect, GLXContextID contextID, - Bool use_glx_1_3, int renderType) +CreateContext(Display * dpy, XVisualInfo * vis, + const __GLcontextModes * const fbconfig, + GLXContext shareList, + Bool allowDirect, GLXContextID contextID, + Bool use_glx_1_3, int renderType) { - GLXContext gc; + GLXContext gc; #ifdef GLX_DIRECT_RENDERING - int screen = (fbconfig == NULL) ? vis->screen : fbconfig->screen; - __GLXscreenConfigs * const psc = GetGLXScreenConfigs(dpy, screen); + int screen = (fbconfig == NULL) ? vis->screen : fbconfig->screen; + __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); #endif - if ( dpy == NULL ) - return NULL; + if (dpy == NULL) + return NULL; - gc = AllocateGLXContext(dpy); - if (!gc) - return NULL; + gc = AllocateGLXContext(dpy); + if (!gc) + return NULL; - if (None == contextID) { - if ( (vis == NULL) && (fbconfig == NULL) ) - return NULL; + if (None == contextID) { + if ((vis == NULL) && (fbconfig == NULL)) + return NULL; #ifdef GLX_DIRECT_RENDERING - if (allowDirect && psc->driScreen) { - const __GLcontextModes * mode; - - if (fbconfig == NULL) { - mode = _gl_context_modes_find_visual(psc->visuals, vis->visualid); - if (mode == NULL) { - xError error; - - error.errorCode = BadValue; - error.resourceID = vis->visualid; - error.sequenceNumber = dpy->request; - error.type = X_Error; - error.majorCode = gc->majorOpcode; - error.minorCode = X_GLXCreateContext; - _XError(dpy, &error); - return None; - } - } - else { - mode = fbconfig; - } - - gc->driContext = psc->driScreen->createContext(psc, mode, gc, - shareList, - renderType); - if (gc->driContext != NULL) { - gc->screen = mode->screen; - gc->psc = psc; - gc->mode = mode; - gc->isDirect = GL_TRUE; - } - } + if (allowDirect && psc->driScreen) { + const __GLcontextModes *mode; + + if (fbconfig == NULL) { + mode = _gl_context_modes_find_visual(psc->visuals, vis->visualid); + if (mode == NULL) { + xError error; + + error.errorCode = BadValue; + error.resourceID = vis->visualid; + error.sequenceNumber = dpy->request; + error.type = X_Error; + error.majorCode = gc->majorOpcode; + error.minorCode = X_GLXCreateContext; + _XError(dpy, &error); + return None; + } + } + else { + mode = fbconfig; + } + + gc->driContext = psc->driScreen->createContext(psc, mode, gc, + shareList, + renderType); + if (gc->driContext != NULL) { + gc->screen = mode->screen; + gc->psc = psc; + gc->mode = mode; + gc->isDirect = GL_TRUE; + } + } #endif - LockDisplay(dpy); - if ( fbconfig == NULL ) { - xGLXCreateContextReq *req; - - /* Send the glXCreateContext request */ - GetReq(GLXCreateContext,req); - req->reqType = gc->majorOpcode; - req->glxCode = X_GLXCreateContext; - req->context = gc->xid = XAllocID(dpy); - req->visual = vis->visualid; - req->screen = vis->screen; - req->shareList = shareList ? shareList->xid : None; + LockDisplay(dpy); + if (fbconfig == NULL) { + xGLXCreateContextReq *req; + + /* Send the glXCreateContext request */ + GetReq(GLXCreateContext, req); + req->reqType = gc->majorOpcode; + req->glxCode = X_GLXCreateContext; + req->context = gc->xid = XAllocID(dpy); + req->visual = vis->visualid; + req->screen = vis->screen; + req->shareList = shareList ? shareList->xid : None; #ifdef GLX_DIRECT_RENDERING - req->isDirect = gc->driContext != NULL; + req->isDirect = gc->driContext != NULL; #else - req->isDirect = 0; + req->isDirect = 0; #endif - } - else if ( use_glx_1_3 ) { - xGLXCreateNewContextReq *req; - - /* Send the glXCreateNewContext request */ - GetReq(GLXCreateNewContext,req); - req->reqType = gc->majorOpcode; - req->glxCode = X_GLXCreateNewContext; - req->context = gc->xid = XAllocID(dpy); - req->fbconfig = fbconfig->fbconfigID; - req->screen = fbconfig->screen; - req->renderType = renderType; - req->shareList = shareList ? shareList->xid : None; + } + else if (use_glx_1_3) { + xGLXCreateNewContextReq *req; + + /* Send the glXCreateNewContext request */ + GetReq(GLXCreateNewContext, req); + req->reqType = gc->majorOpcode; + req->glxCode = X_GLXCreateNewContext; + req->context = gc->xid = XAllocID(dpy); + req->fbconfig = fbconfig->fbconfigID; + req->screen = fbconfig->screen; + req->renderType = renderType; + req->shareList = shareList ? shareList->xid : None; #ifdef GLX_DIRECT_RENDERING - req->isDirect = gc->driContext != NULL; + req->isDirect = gc->driContext != NULL; #else - req->isDirect = 0; + req->isDirect = 0; #endif - } - else { - xGLXVendorPrivateWithReplyReq *vpreq; - xGLXCreateContextWithConfigSGIXReq *req; - - /* Send the glXCreateNewContext request */ - GetReqExtra(GLXVendorPrivateWithReply, - sz_xGLXCreateContextWithConfigSGIXReq-sz_xGLXVendorPrivateWithReplyReq,vpreq); - req = (xGLXCreateContextWithConfigSGIXReq *)vpreq; - req->reqType = gc->majorOpcode; - req->glxCode = X_GLXVendorPrivateWithReply; - req->vendorCode = X_GLXvop_CreateContextWithConfigSGIX; - req->context = gc->xid = XAllocID(dpy); - req->fbconfig = fbconfig->fbconfigID; - req->screen = fbconfig->screen; - req->renderType = renderType; - req->shareList = shareList ? shareList->xid : None; + } + else { + xGLXVendorPrivateWithReplyReq *vpreq; + xGLXCreateContextWithConfigSGIXReq *req; + + /* Send the glXCreateNewContext request */ + GetReqExtra(GLXVendorPrivateWithReply, + sz_xGLXCreateContextWithConfigSGIXReq - + sz_xGLXVendorPrivateWithReplyReq, vpreq); + req = (xGLXCreateContextWithConfigSGIXReq *) vpreq; + req->reqType = gc->majorOpcode; + req->glxCode = X_GLXVendorPrivateWithReply; + req->vendorCode = X_GLXvop_CreateContextWithConfigSGIX; + req->context = gc->xid = XAllocID(dpy); + req->fbconfig = fbconfig->fbconfigID; + req->screen = fbconfig->screen; + req->renderType = renderType; + req->shareList = shareList ? shareList->xid : None; #ifdef GLX_DIRECT_RENDERING - req->isDirect = gc->driContext != NULL; + req->isDirect = gc->driContext != NULL; #else - req->isDirect = 0; + req->isDirect = 0; #endif - } + } - UnlockDisplay(dpy); - SyncHandle(); - gc->imported = GL_FALSE; - } - else { - gc->xid = contextID; - gc->imported = GL_TRUE; - } + UnlockDisplay(dpy); + SyncHandle(); + gc->imported = GL_FALSE; + } + else { + gc->xid = contextID; + gc->imported = GL_TRUE; + } - return gc; + return gc; } -PUBLIC GLXContext glXCreateContext(Display *dpy, XVisualInfo *vis, - GLXContext shareList, Bool allowDirect) +PUBLIC GLXContext +glXCreateContext(Display * dpy, XVisualInfo * vis, + GLXContext shareList, Bool allowDirect) { return CreateContext(dpy, vis, NULL, shareList, allowDirect, None, - False, 0); + False, 0); } -_X_HIDDEN void __glXFreeContext(__GLXcontext *gc) +_X_HIDDEN void +__glXFreeContext(__GLXcontext * gc) { - if (gc->vendor) XFree((char *) gc->vendor); - if (gc->renderer) XFree((char *) gc->renderer); - if (gc->version) XFree((char *) gc->version); - if (gc->extensions) XFree((char *) gc->extensions); - __glFreeAttributeState(gc); - XFree((char *) gc->buf); - Xfree((char *) gc->client_state_private); - XFree((char *) gc); - + if (gc->vendor) + XFree((char *) gc->vendor); + if (gc->renderer) + XFree((char *) gc->renderer); + if (gc->version) + XFree((char *) gc->version); + if (gc->extensions) + XFree((char *) gc->extensions); + __glFreeAttributeState(gc); + XFree((char *) gc->buf); + Xfree((char *) gc->client_state_private); + XFree((char *) gc); + } /* ** Destroy the named context */ -static void -DestroyContext(Display *dpy, GLXContext gc) +static void +DestroyContext(Display * dpy, GLXContext gc) { - xGLXDestroyContextReq *req; - GLXContextID xid; - CARD8 opcode; - GLboolean imported; + xGLXDestroyContextReq *req; + GLXContextID xid; + CARD8 opcode; + GLboolean imported; - opcode = __glXSetupForCommand(dpy); - if (!opcode || !gc) { - return; - } + opcode = __glXSetupForCommand(dpy); + if (!opcode || !gc) { + return; + } - __glXLock(); - xid = gc->xid; - imported = gc->imported; - gc->xid = None; + __glXLock(); + xid = gc->xid; + imported = gc->imported; + gc->xid = None; #ifdef GLX_DIRECT_RENDERING - /* Destroy the direct rendering context */ - if (gc->driContext) { - (*gc->driContext->destroyContext)(gc->driContext, gc->psc, dpy); - gc->driContext = NULL; - GarbageCollectDRIDrawables(dpy, gc->psc); - } + /* Destroy the direct rendering context */ + if (gc->driContext) { + (*gc->driContext->destroyContext) (gc->driContext, gc->psc, dpy); + gc->driContext = NULL; + GarbageCollectDRIDrawables(dpy, gc->psc); + } #endif - __glXFreeVertexArrayState(gc); + __glXFreeVertexArrayState(gc); - if (gc->currentDpy) { - /* Have to free later cuz it's in use now */ - __glXUnlock(); - } else { - /* Destroy the handle if not current to anybody */ - __glXUnlock(); - __glXFreeContext(gc); - } + if (gc->currentDpy) { + /* Have to free later cuz it's in use now */ + __glXUnlock(); + } + else { + /* Destroy the handle if not current to anybody */ + __glXUnlock(); + __glXFreeContext(gc); + } - if (!imported) { - /* - ** This dpy also created the server side part of the context. - ** Send the glXDestroyContext request. - */ - LockDisplay(dpy); - GetReq(GLXDestroyContext,req); - req->reqType = opcode; - req->glxCode = X_GLXDestroyContext; - req->context = xid; - UnlockDisplay(dpy); - SyncHandle(); - } + if (!imported) { + /* + ** This dpy also created the server side part of the context. + ** Send the glXDestroyContext request. + */ + LockDisplay(dpy); + GetReq(GLXDestroyContext, req); + req->reqType = opcode; + req->glxCode = X_GLXDestroyContext; + req->context = xid; + UnlockDisplay(dpy); + SyncHandle(); + } } -PUBLIC void glXDestroyContext(Display *dpy, GLXContext gc) +PUBLIC void +glXDestroyContext(Display * dpy, GLXContext gc) { - DestroyContext(dpy, gc); + DestroyContext(dpy, gc); } /* ** Return the major and minor version #s for the GLX extension */ -PUBLIC Bool glXQueryVersion(Display *dpy, int *major, int *minor) +PUBLIC Bool +glXQueryVersion(Display * dpy, int *major, int *minor) { - __GLXdisplayPrivate *priv; + __GLXdisplayPrivate *priv; - /* Init the extension. This fetches the major and minor version. */ - priv = __glXInitialize(dpy); - if (!priv) return GL_FALSE; + /* Init the extension. This fetches the major and minor version. */ + priv = __glXInitialize(dpy); + if (!priv) + return GL_FALSE; - if (major) *major = priv->majorVersion; - if (minor) *minor = priv->minorVersion; - return GL_TRUE; + if (major) + *major = priv->majorVersion; + if (minor) + *minor = priv->minorVersion; + return GL_TRUE; } /* ** Query the existance of the GLX extension */ -PUBLIC Bool glXQueryExtension(Display *dpy, int *errorBase, int *eventBase) -{ - int major_op, erb, evb; - Bool rv; - - rv = XQueryExtension(dpy, GLX_EXTENSION_NAME, &major_op, &evb, &erb); - if (rv) { - if (errorBase) *errorBase = erb; - if (eventBase) *eventBase = evb; - } - return rv; +PUBLIC Bool +glXQueryExtension(Display * dpy, int *errorBase, int *eventBase) +{ + int major_op, erb, evb; + Bool rv; + + rv = XQueryExtension(dpy, GLX_EXTENSION_NAME, &major_op, &evb, &erb); + if (rv) { + if (errorBase) + *errorBase = erb; + if (eventBase) + *eventBase = evb; + } + return rv; } /* ** Put a barrier in the token stream that forces the GL to finish its ** work before X can proceed. */ -PUBLIC void glXWaitGL(void) +PUBLIC void +glXWaitGL(void) { - xGLXWaitGLReq *req; - GLXContext gc = __glXGetCurrentContext(); - Display *dpy = gc->currentDpy; + xGLXWaitGLReq *req; + GLXContext gc = __glXGetCurrentContext(); + Display *dpy = gc->currentDpy; - if (!dpy) return; + if (!dpy) + return; - /* Flush any pending commands out */ - __glXFlushRenderBuffer(gc, gc->pc); + /* Flush any pending commands out */ + __glXFlushRenderBuffer(gc, gc->pc); #ifdef GLX_DIRECT_RENDERING - if (gc->driContext) { - int screen; - __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, gc->currentDrawable, &screen); - - if ( pdraw != NULL ) { - __GLXscreenConfigs * const psc = GetGLXScreenConfigs(dpy, screen); - glFlush(); - if (psc->driScreen->waitGL != NULL) - (*psc->driScreen->waitGL)(pdraw); - } - return; - } + if (gc->driContext) { + int screen; + __GLXDRIdrawable *pdraw = + GetGLXDRIDrawable(dpy, gc->currentDrawable, &screen); + + if (pdraw != NULL) { + __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); + glFlush(); + if (psc->driScreen->waitGL != NULL) + (*psc->driScreen->waitGL) (pdraw); + } + return; + } #endif - /* Send the glXWaitGL request */ - LockDisplay(dpy); - GetReq(GLXWaitGL,req); - req->reqType = gc->majorOpcode; - req->glxCode = X_GLXWaitGL; - req->contextTag = gc->currentContextTag; - UnlockDisplay(dpy); - SyncHandle(); + /* Send the glXWaitGL request */ + LockDisplay(dpy); + GetReq(GLXWaitGL, req); + req->reqType = gc->majorOpcode; + req->glxCode = X_GLXWaitGL; + req->contextTag = gc->currentContextTag; + UnlockDisplay(dpy); + SyncHandle(); } /* ** Put a barrier in the token stream that forces X to finish its ** work before GL can proceed. */ -PUBLIC void glXWaitX(void) +PUBLIC void +glXWaitX(void) { - xGLXWaitXReq *req; - GLXContext gc = __glXGetCurrentContext(); - Display *dpy = gc->currentDpy; + xGLXWaitXReq *req; + GLXContext gc = __glXGetCurrentContext(); + Display *dpy = gc->currentDpy; - if (!dpy) return; + if (!dpy) + return; - /* Flush any pending commands out */ - __glXFlushRenderBuffer(gc, gc->pc); + /* Flush any pending commands out */ + __glXFlushRenderBuffer(gc, gc->pc); #ifdef GLX_DIRECT_RENDERING - if (gc->driContext) { - int screen; - __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, gc->currentDrawable, &screen); - - if ( pdraw != NULL ) { - __GLXscreenConfigs * const psc = GetGLXScreenConfigs(dpy, screen); - if (psc->driScreen->waitX != NULL) - (*psc->driScreen->waitX)(pdraw); - } else - XSync(dpy, False); - return; - } + if (gc->driContext) { + int screen; + __GLXDRIdrawable *pdraw = + GetGLXDRIDrawable(dpy, gc->currentDrawable, &screen); + + if (pdraw != NULL) { + __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); + if (psc->driScreen->waitX != NULL) + (*psc->driScreen->waitX) (pdraw); + } + else + XSync(dpy, False); + return; + } #endif - /* + /* ** Send the glXWaitX request. */ - LockDisplay(dpy); - GetReq(GLXWaitX,req); - req->reqType = gc->majorOpcode; - req->glxCode = X_GLXWaitX; - req->contextTag = gc->currentContextTag; - UnlockDisplay(dpy); - SyncHandle(); + LockDisplay(dpy); + GetReq(GLXWaitX, req); + req->reqType = gc->majorOpcode; + req->glxCode = X_GLXWaitX; + req->contextTag = gc->currentContextTag; + UnlockDisplay(dpy); + SyncHandle(); } -PUBLIC void glXUseXFont(Font font, int first, int count, int listBase) +PUBLIC void +glXUseXFont(Font font, int first, int count, int listBase) { - xGLXUseXFontReq *req; - GLXContext gc = __glXGetCurrentContext(); - Display *dpy = gc->currentDpy; + xGLXUseXFontReq *req; + GLXContext gc = __glXGetCurrentContext(); + Display *dpy = gc->currentDpy; - if (!dpy) return; + if (!dpy) + return; - /* Flush any pending commands out */ - (void) __glXFlushRenderBuffer(gc, gc->pc); + /* Flush any pending commands out */ + (void) __glXFlushRenderBuffer(gc, gc->pc); #ifdef GLX_DIRECT_RENDERING - if (gc->driContext) { + if (gc->driContext) { DRI_glXUseXFont(font, first, count, listBase); return; - } + } #endif - /* Send the glXUseFont request */ - LockDisplay(dpy); - GetReq(GLXUseXFont,req); - req->reqType = gc->majorOpcode; - req->glxCode = X_GLXUseXFont; - req->contextTag = gc->currentContextTag; - req->font = font; - req->first = first; - req->count = count; - req->listBase = listBase; - UnlockDisplay(dpy); - SyncHandle(); + /* Send the glXUseFont request */ + LockDisplay(dpy); + GetReq(GLXUseXFont, req); + req->reqType = gc->majorOpcode; + req->glxCode = X_GLXUseXFont; + req->contextTag = gc->currentContextTag; + req->font = font; + req->first = first; + req->count = count; + req->listBase = listBase; + UnlockDisplay(dpy); + SyncHandle(); } /************************************************************************/ @@ -714,46 +744,48 @@ PUBLIC void glXUseXFont(Font font, int first, int count, int listBase) ** Copy the source context to the destination context using the ** attribute "mask". */ -PUBLIC void glXCopyContext(Display *dpy, GLXContext source, - GLXContext dest, unsigned long mask) +PUBLIC void +glXCopyContext(Display * dpy, GLXContext source, + GLXContext dest, unsigned long mask) { - xGLXCopyContextReq *req; - GLXContext gc = __glXGetCurrentContext(); - GLXContextTag tag; - CARD8 opcode; + xGLXCopyContextReq *req; + GLXContext gc = __glXGetCurrentContext(); + GLXContextTag tag; + CARD8 opcode; - opcode = __glXSetupForCommand(dpy); - if (!opcode) { - return; - } + opcode = __glXSetupForCommand(dpy); + if (!opcode) { + return; + } #ifdef GLX_DIRECT_RENDERING - if (gc->driContext) { - /* NOT_DONE: This does not work yet */ - } + if (gc->driContext) { + /* NOT_DONE: This does not work yet */ + } #endif - /* + /* ** If the source is the current context, send its tag so that the context ** can be flushed before the copy. */ - if (source == gc && dpy == gc->currentDpy) { - tag = gc->currentContextTag; - } else { - tag = 0; - } - - /* Send the glXCopyContext request */ - LockDisplay(dpy); - GetReq(GLXCopyContext,req); - req->reqType = opcode; - req->glxCode = X_GLXCopyContext; - req->source = source ? source->xid : None; - req->dest = dest ? dest->xid : None; - req->mask = mask; - req->contextTag = tag; - UnlockDisplay(dpy); - SyncHandle(); + if (source == gc && dpy == gc->currentDpy) { + tag = gc->currentContextTag; + } + else { + tag = 0; + } + + /* Send the glXCopyContext request */ + LockDisplay(dpy); + GetReq(GLXCopyContext, req); + req->reqType = opcode; + req->glxCode = X_GLXCopyContext; + req->source = source ? source->xid : None; + req->dest = dest ? dest->xid : None; + req->mask = mask; + req->contextTag = tag; + UnlockDisplay(dpy); + SyncHandle(); } @@ -765,42 +797,43 @@ PUBLIC void glXCopyContext(Display *dpy, GLXContext source, * * \returns \c GL_TRUE if the context is direct rendering or not. */ -static Bool __glXIsDirect(Display *dpy, GLXContextID contextID) +static Bool +__glXIsDirect(Display * dpy, GLXContextID contextID) { #if !defined(USE_XCB) - xGLXIsDirectReq *req; - xGLXIsDirectReply reply; + xGLXIsDirectReq *req; + xGLXIsDirectReply reply; #endif - CARD8 opcode; + CARD8 opcode; - opcode = __glXSetupForCommand(dpy); - if (!opcode) { - return GL_FALSE; - } + opcode = __glXSetupForCommand(dpy); + if (!opcode) { + return GL_FALSE; + } #ifdef USE_XCB - xcb_connection_t* c = XGetXCBConnection(dpy); - xcb_glx_is_direct_reply_t* reply = - xcb_glx_is_direct_reply(c, - xcb_glx_is_direct(c, contextID), - NULL); + xcb_connection_t *c = XGetXCBConnection(dpy); + xcb_glx_is_direct_reply_t *reply = xcb_glx_is_direct_reply(c, + xcb_glx_is_direct + (c, contextID), + NULL); const Bool is_direct = reply->is_direct ? True : False; free(reply); return is_direct; #else - /* Send the glXIsDirect request */ - LockDisplay(dpy); - GetReq(GLXIsDirect,req); - req->reqType = opcode; - req->glxCode = X_GLXIsDirect; - req->context = contextID; - _XReply(dpy, (xReply*) &reply, 0, False); - UnlockDisplay(dpy); - SyncHandle(); - - return reply.isDirect; + /* Send the glXIsDirect request */ + LockDisplay(dpy); + GetReq(GLXIsDirect, req); + req->reqType = opcode; + req->glxCode = X_GLXIsDirect; + req->context = contextID; + _XReply(dpy, (xReply *) & reply, 0, False); + UnlockDisplay(dpy); + SyncHandle(); + + return reply.isDirect; #endif /* USE_XCB */ } @@ -810,134 +843,140 @@ static Bool __glXIsDirect(Display *dpy, GLXContextID contextID) * \c GLX_DIRECT_RENDERING is not defined? Do we really need to bother with * the GLX protocol here at all? */ -PUBLIC Bool glXIsDirect(Display *dpy, GLXContext gc) +PUBLIC Bool +glXIsDirect(Display * dpy, GLXContext gc) { - if (!gc) { - return GL_FALSE; + if (!gc) { + return GL_FALSE; #ifdef GLX_DIRECT_RENDERING - } else if (gc->driContext) { - return GL_TRUE; + } + else if (gc->driContext) { + return GL_TRUE; #endif - } - return __glXIsDirect(dpy, gc->xid); + } + return __glXIsDirect(dpy, gc->xid); } -PUBLIC GLXPixmap glXCreateGLXPixmap(Display *dpy, XVisualInfo *vis, - Pixmap pixmap) +PUBLIC GLXPixmap +glXCreateGLXPixmap(Display * dpy, XVisualInfo * vis, Pixmap pixmap) { - xGLXCreateGLXPixmapReq *req; - GLXPixmap xid; - CARD8 opcode; + xGLXCreateGLXPixmapReq *req; + GLXPixmap xid; + CARD8 opcode; - opcode = __glXSetupForCommand(dpy); - if (!opcode) { - return None; - } + opcode = __glXSetupForCommand(dpy); + if (!opcode) { + return None; + } - /* Send the glXCreateGLXPixmap request */ - LockDisplay(dpy); - GetReq(GLXCreateGLXPixmap,req); - req->reqType = opcode; - req->glxCode = X_GLXCreateGLXPixmap; - req->screen = vis->screen; - req->visual = vis->visualid; - req->pixmap = pixmap; - req->glxpixmap = xid = XAllocID(dpy); - UnlockDisplay(dpy); - SyncHandle(); - return xid; + /* Send the glXCreateGLXPixmap request */ + LockDisplay(dpy); + GetReq(GLXCreateGLXPixmap, req); + req->reqType = opcode; + req->glxCode = X_GLXCreateGLXPixmap; + req->screen = vis->screen; + req->visual = vis->visualid; + req->pixmap = pixmap; + req->glxpixmap = xid = XAllocID(dpy); + UnlockDisplay(dpy); + SyncHandle(); + return xid; } /* ** Destroy the named pixmap */ -PUBLIC void glXDestroyGLXPixmap(Display *dpy, GLXPixmap glxpixmap) -{ - xGLXDestroyGLXPixmapReq *req; - CARD8 opcode; - - opcode = __glXSetupForCommand(dpy); - if (!opcode) { - return; - } - - /* Send the glXDestroyGLXPixmap request */ - LockDisplay(dpy); - GetReq(GLXDestroyGLXPixmap,req); - req->reqType = opcode; - req->glxCode = X_GLXDestroyGLXPixmap; - req->glxpixmap = glxpixmap; - UnlockDisplay(dpy); - SyncHandle(); +PUBLIC void +glXDestroyGLXPixmap(Display * dpy, GLXPixmap glxpixmap) +{ + xGLXDestroyGLXPixmapReq *req; + CARD8 opcode; + + opcode = __glXSetupForCommand(dpy); + if (!opcode) { + return; + } + + /* Send the glXDestroyGLXPixmap request */ + LockDisplay(dpy); + GetReq(GLXDestroyGLXPixmap, req); + req->reqType = opcode; + req->glxCode = X_GLXDestroyGLXPixmap; + req->glxpixmap = glxpixmap; + UnlockDisplay(dpy); + SyncHandle(); #ifdef GLX_DIRECT_RENDERING - { - int screen; - __GLXdisplayPrivate *const priv = __glXInitialize(dpy); - __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, glxpixmap, &screen); - __GLXscreenConfigs *psc = &priv->screenConfigs[screen]; - - if (pdraw != NULL) { - (*pdraw->destroyDrawable) (pdraw); - __glxHashDelete(psc->drawHash, glxpixmap); - } - } + { + int screen; + __GLXdisplayPrivate *const priv = __glXInitialize(dpy); + __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, glxpixmap, &screen); + __GLXscreenConfigs *psc = &priv->screenConfigs[screen]; + + if (pdraw != NULL) { + (*pdraw->destroyDrawable) (pdraw); + __glxHashDelete(psc->drawHash, glxpixmap); + } + } #endif } -PUBLIC void glXSwapBuffers(Display *dpy, GLXDrawable drawable) +PUBLIC void +glXSwapBuffers(Display * dpy, GLXDrawable drawable) { - GLXContext gc; - GLXContextTag tag; - CARD8 opcode; + GLXContext gc; + GLXContextTag tag; + CARD8 opcode; #ifdef USE_XCB - xcb_connection_t *c; + xcb_connection_t *c; #else - xGLXSwapBuffersReq *req; + xGLXSwapBuffersReq *req; #endif #ifdef GLX_DIRECT_RENDERING - __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL); + __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL); - if (pdraw != NULL) { - glFlush(); - (*pdraw->psc->driScreen->swapBuffers)(pdraw); - return; - } + if (pdraw != NULL) { + glFlush(); + (*pdraw->psc->driScreen->swapBuffers) (pdraw); + return; + } #endif - opcode = __glXSetupForCommand(dpy); - if (!opcode) { - return; - } + opcode = __glXSetupForCommand(dpy); + if (!opcode) { + return; + } - /* + /* ** The calling thread may or may not have a current context. If it ** does, send the context tag so the server can do a flush. */ - gc = __glXGetCurrentContext(); - if ((gc != NULL) && (dpy == gc->currentDpy) && - ((drawable == gc->currentDrawable) || (drawable == gc->currentReadable)) ) { - tag = gc->currentContextTag; - } else { - tag = 0; - } + gc = __glXGetCurrentContext(); + if ((gc != NULL) && (dpy == gc->currentDpy) && + ((drawable == gc->currentDrawable) + || (drawable == gc->currentReadable))) { + tag = gc->currentContextTag; + } + else { + tag = 0; + } #ifdef USE_XCB - c = XGetXCBConnection(dpy); - xcb_glx_swap_buffers(c, tag, drawable); - xcb_flush(c); + c = XGetXCBConnection(dpy); + xcb_glx_swap_buffers(c, tag, drawable); + xcb_flush(c); #else - /* Send the glXSwapBuffers request */ - LockDisplay(dpy); - GetReq(GLXSwapBuffers,req); - req->reqType = opcode; - req->glxCode = X_GLXSwapBuffers; - req->drawable = drawable; - req->contextTag = tag; - UnlockDisplay(dpy); - SyncHandle(); - XFlush(dpy); + /* Send the glXSwapBuffers request */ + LockDisplay(dpy); + GetReq(GLXSwapBuffers, req); + req->reqType = opcode; + req->glxCode = X_GLXSwapBuffers; + req->drawable = drawable; + req->contextTag = tag; + UnlockDisplay(dpy); + SyncHandle(); + XFlush(dpy); #endif /* USE_XCB */ } @@ -946,94 +985,96 @@ PUBLIC void glXSwapBuffers(Display *dpy, GLXDrawable drawable) ** Return configuration information for the given display, screen and ** visual combination. */ -PUBLIC int glXGetConfig(Display *dpy, XVisualInfo *vis, int attribute, - int *value_return) -{ - __GLXdisplayPrivate *priv; - __GLXscreenConfigs *psc; - __GLcontextModes *modes; - int status; - - status = GetGLXPrivScreenConfig( dpy, vis->screen, & priv, & psc ); - if ( status == Success ) { - modes = _gl_context_modes_find_visual(psc->visuals, vis->visualid); - - /* Lookup attribute after first finding a match on the visual */ - if ( modes != NULL ) { - return _gl_get_context_mode_data( modes, attribute, value_return ); - } - - status = GLX_BAD_VISUAL; - } - - /* +PUBLIC int +glXGetConfig(Display * dpy, XVisualInfo * vis, int attribute, + int *value_return) +{ + __GLXdisplayPrivate *priv; + __GLXscreenConfigs *psc; + __GLcontextModes *modes; + int status; + + status = GetGLXPrivScreenConfig(dpy, vis->screen, &priv, &psc); + if (status == Success) { + modes = _gl_context_modes_find_visual(psc->visuals, vis->visualid); + + /* Lookup attribute after first finding a match on the visual */ + if (modes != NULL) { + return _gl_get_context_mode_data(modes, attribute, value_return); + } + + status = GLX_BAD_VISUAL; + } + + /* ** If we can't find the config for this visual, this visual is not ** supported by the OpenGL implementation on the server. */ - if ( (status == GLX_BAD_VISUAL) && (attribute == GLX_USE_GL) ) { - *value_return = GL_FALSE; - status = Success; - } + if ((status == GLX_BAD_VISUAL) && (attribute == GLX_USE_GL)) { + *value_return = GL_FALSE; + status = Success; + } - return status; + return status; } /************************************************************************/ static void -init_fbconfig_for_chooser( __GLcontextModes * config, - GLboolean fbconfig_style_tags ) -{ - memset( config, 0, sizeof( __GLcontextModes ) ); - config->visualID = (XID) GLX_DONT_CARE; - config->visualType = GLX_DONT_CARE; - - /* glXChooseFBConfig specifies different defaults for these two than - * glXChooseVisual. - */ - if ( fbconfig_style_tags ) { - config->rgbMode = GL_TRUE; - config->doubleBufferMode = GLX_DONT_CARE; - } - - config->visualRating = GLX_DONT_CARE; - config->transparentPixel = GLX_NONE; - config->transparentRed = GLX_DONT_CARE; - config->transparentGreen = GLX_DONT_CARE; - config->transparentBlue = GLX_DONT_CARE; - config->transparentAlpha = GLX_DONT_CARE; - config->transparentIndex = GLX_DONT_CARE; - - config->drawableType = GLX_WINDOW_BIT; - config->renderType = (config->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT; - config->xRenderable = GLX_DONT_CARE; - config->fbconfigID = (GLXFBConfigID)(GLX_DONT_CARE); - - config->swapMethod = GLX_DONT_CARE; -} - -#define MATCH_DONT_CARE( param ) \ - do { \ - if ( (a-> param != GLX_DONT_CARE) \ - && (a-> param != b-> param) ) { \ - return False; \ - } \ - } while ( 0 ) - -#define MATCH_MINIMUM( param ) \ - do { \ - if ( (a-> param != GLX_DONT_CARE) \ - && (a-> param > b-> param) ) { \ - return False; \ - } \ - } while ( 0 ) - -#define MATCH_EXACT( param ) \ - do { \ - if ( a-> param != b-> param) { \ - return False; \ - } \ - } while ( 0 ) +init_fbconfig_for_chooser(__GLcontextModes * config, + GLboolean fbconfig_style_tags) +{ + memset(config, 0, sizeof(__GLcontextModes)); + config->visualID = (XID) GLX_DONT_CARE; + config->visualType = GLX_DONT_CARE; + + /* glXChooseFBConfig specifies different defaults for these two than + * glXChooseVisual. + */ + if (fbconfig_style_tags) { + config->rgbMode = GL_TRUE; + config->doubleBufferMode = GLX_DONT_CARE; + } + + config->visualRating = GLX_DONT_CARE; + config->transparentPixel = GLX_NONE; + config->transparentRed = GLX_DONT_CARE; + config->transparentGreen = GLX_DONT_CARE; + config->transparentBlue = GLX_DONT_CARE; + config->transparentAlpha = GLX_DONT_CARE; + config->transparentIndex = GLX_DONT_CARE; + + config->drawableType = GLX_WINDOW_BIT; + config->renderType = + (config->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT; + config->xRenderable = GLX_DONT_CARE; + config->fbconfigID = (GLXFBConfigID) (GLX_DONT_CARE); + + config->swapMethod = GLX_DONT_CARE; +} + +#define MATCH_DONT_CARE( param ) \ + do { \ + if ( (a-> param != GLX_DONT_CARE) \ + && (a-> param != b-> param) ) { \ + return False; \ + } \ + } while ( 0 ) + +#define MATCH_MINIMUM( param ) \ + do { \ + if ( (a-> param != GLX_DONT_CARE) \ + && (a-> param > b-> param) ) { \ + return False; \ + } \ + } while ( 0 ) + +#define MATCH_EXACT( param ) \ + do { \ + if ( a-> param != b-> param) { \ + return False; \ + } \ + } while ( 0 ) /** * Determine if two GLXFBConfigs are compatible. @@ -1042,80 +1083,80 @@ init_fbconfig_for_chooser( __GLcontextModes * config, * \param b Server specified config to test against \c a. */ static Bool -fbconfigs_compatible( const __GLcontextModes * const a, - const __GLcontextModes * const b ) -{ - MATCH_DONT_CARE( doubleBufferMode ); - MATCH_DONT_CARE( visualType ); - MATCH_DONT_CARE( visualRating ); - MATCH_DONT_CARE( xRenderable ); - MATCH_DONT_CARE( fbconfigID ); - MATCH_DONT_CARE( swapMethod ); - - MATCH_MINIMUM( rgbBits ); - MATCH_MINIMUM( numAuxBuffers ); - MATCH_MINIMUM( redBits ); - MATCH_MINIMUM( greenBits ); - MATCH_MINIMUM( blueBits ); - MATCH_MINIMUM( alphaBits ); - MATCH_MINIMUM( depthBits ); - MATCH_MINIMUM( stencilBits ); - MATCH_MINIMUM( accumRedBits ); - MATCH_MINIMUM( accumGreenBits ); - MATCH_MINIMUM( accumBlueBits ); - MATCH_MINIMUM( accumAlphaBits ); - MATCH_MINIMUM( sampleBuffers ); - MATCH_MINIMUM( maxPbufferWidth ); - MATCH_MINIMUM( maxPbufferHeight ); - MATCH_MINIMUM( maxPbufferPixels ); - MATCH_MINIMUM( samples ); - - MATCH_DONT_CARE( stereoMode ); - MATCH_EXACT( level ); - - if ( ((a->drawableType & b->drawableType) == 0) - || ((a->renderType & b->renderType) == 0) ) { - return False; - } - - - /* There is a bug in a few of the XFree86 DDX drivers. They contain - * visuals with a "transparent type" of 0 when they really mean GLX_NONE. - * Technically speaking, it is a bug in the DDX driver, but there is - * enough of an installed base to work around the problem here. In any - * case, 0 is not a valid value of the transparent type, so we'll treat 0 - * from the app as GLX_DONT_CARE. We'll consider GLX_NONE from the app and - * 0 from the server to be a match to maintain backward compatibility with - * the (broken) drivers. - */ - - if ( a->transparentPixel != GLX_DONT_CARE - && a->transparentPixel != 0 ) { - if ( a->transparentPixel == GLX_NONE ) { - if ( b->transparentPixel != GLX_NONE && b->transparentPixel != 0 ) - return False; - } else { - MATCH_EXACT( transparentPixel ); - } - - switch ( a->transparentPixel ) { - case GLX_TRANSPARENT_RGB: - MATCH_DONT_CARE( transparentRed ); - MATCH_DONT_CARE( transparentGreen ); - MATCH_DONT_CARE( transparentBlue ); - MATCH_DONT_CARE( transparentAlpha ); - break; - - case GLX_TRANSPARENT_INDEX: - MATCH_DONT_CARE( transparentIndex ); - break; - - default: - break; - } - } - - return True; +fbconfigs_compatible(const __GLcontextModes * const a, + const __GLcontextModes * const b) +{ + MATCH_DONT_CARE(doubleBufferMode); + MATCH_DONT_CARE(visualType); + MATCH_DONT_CARE(visualRating); + MATCH_DONT_CARE(xRenderable); + MATCH_DONT_CARE(fbconfigID); + MATCH_DONT_CARE(swapMethod); + + MATCH_MINIMUM(rgbBits); + MATCH_MINIMUM(numAuxBuffers); + MATCH_MINIMUM(redBits); + MATCH_MINIMUM(greenBits); + MATCH_MINIMUM(blueBits); + MATCH_MINIMUM(alphaBits); + MATCH_MINIMUM(depthBits); + MATCH_MINIMUM(stencilBits); + MATCH_MINIMUM(accumRedBits); + MATCH_MINIMUM(accumGreenBits); + MATCH_MINIMUM(accumBlueBits); + MATCH_MINIMUM(accumAlphaBits); + MATCH_MINIMUM(sampleBuffers); + MATCH_MINIMUM(maxPbufferWidth); + MATCH_MINIMUM(maxPbufferHeight); + MATCH_MINIMUM(maxPbufferPixels); + MATCH_MINIMUM(samples); + + MATCH_DONT_CARE(stereoMode); + MATCH_EXACT(level); + + if (((a->drawableType & b->drawableType) == 0) + || ((a->renderType & b->renderType) == 0)) { + return False; + } + + + /* There is a bug in a few of the XFree86 DDX drivers. They contain + * visuals with a "transparent type" of 0 when they really mean GLX_NONE. + * Technically speaking, it is a bug in the DDX driver, but there is + * enough of an installed base to work around the problem here. In any + * case, 0 is not a valid value of the transparent type, so we'll treat 0 + * from the app as GLX_DONT_CARE. We'll consider GLX_NONE from the app and + * 0 from the server to be a match to maintain backward compatibility with + * the (broken) drivers. + */ + + if (a->transparentPixel != GLX_DONT_CARE && a->transparentPixel != 0) { + if (a->transparentPixel == GLX_NONE) { + if (b->transparentPixel != GLX_NONE && b->transparentPixel != 0) + return False; + } + else { + MATCH_EXACT(transparentPixel); + } + + switch (a->transparentPixel) { + case GLX_TRANSPARENT_RGB: + MATCH_DONT_CARE(transparentRed); + MATCH_DONT_CARE(transparentGreen); + MATCH_DONT_CARE(transparentBlue); + MATCH_DONT_CARE(transparentAlpha); + break; + + case GLX_TRANSPARENT_INDEX: + MATCH_DONT_CARE(transparentIndex); + break; + + default: + break; + } + } + + return True; } @@ -1125,39 +1166,39 @@ fbconfigs_compatible( const __GLcontextModes * const a, * Well, that's really hard to do with the code as-is. This behavior is * closer to correct, but still not technically right. */ -#define PREFER_LARGER_OR_ZERO(comp) \ - do { \ - if ( ((*a)-> comp) != ((*b)-> comp) ) { \ - if ( ((*a)-> comp) == 0 ) { \ - return -1; \ - } \ - else if ( ((*b)-> comp) == 0 ) { \ - return 1; \ - } \ - else { \ - return ((*b)-> comp) - ((*a)-> comp) ; \ - } \ - } \ - } while( 0 ) - -#define PREFER_LARGER(comp) \ - do { \ - if ( ((*a)-> comp) != ((*b)-> comp) ) { \ - return ((*b)-> comp) - ((*a)-> comp) ; \ - } \ - } while( 0 ) - -#define PREFER_SMALLER(comp) \ - do { \ - if ( ((*a)-> comp) != ((*b)-> comp) ) { \ - return ((*a)-> comp) - ((*b)-> comp) ; \ - } \ - } while( 0 ) +#define PREFER_LARGER_OR_ZERO(comp) \ + do { \ + if ( ((*a)-> comp) != ((*b)-> comp) ) { \ + if ( ((*a)-> comp) == 0 ) { \ + return -1; \ + } \ + else if ( ((*b)-> comp) == 0 ) { \ + return 1; \ + } \ + else { \ + return ((*b)-> comp) - ((*a)-> comp) ; \ + } \ + } \ + } while( 0 ) + +#define PREFER_LARGER(comp) \ + do { \ + if ( ((*a)-> comp) != ((*b)-> comp) ) { \ + return ((*b)-> comp) - ((*a)-> comp) ; \ + } \ + } while( 0 ) + +#define PREFER_SMALLER(comp) \ + do { \ + if ( ((*a)-> comp) != ((*b)-> comp) ) { \ + return ((*a)-> comp) - ((*b)-> comp) ; \ + } \ + } while( 0 ) /** * Compare two GLXFBConfigs. This function is intended to be used as the * compare function passed in to qsort. - * + * * \returns If \c a is a "better" config, according to the specification of * SGIX_fbconfig, a number less than zero is returned. If \c b is * better, then a number greater than zero is return. If both are @@ -1165,66 +1206,66 @@ fbconfigs_compatible( const __GLcontextModes * const a, * \sa qsort, glXChooseVisual, glXChooseFBConfig, glXChooseFBConfigSGIX */ static int -fbconfig_compare( const __GLcontextModes * const * const a, - const __GLcontextModes * const * const b ) +fbconfig_compare(const __GLcontextModes * const *const a, + const __GLcontextModes * const *const b) { - /* The order of these comparisons must NOT change. It is defined by - * the GLX 1.3 spec and ARB_multisample. - */ + /* The order of these comparisons must NOT change. It is defined by + * the GLX 1.3 spec and ARB_multisample. + */ - PREFER_SMALLER( visualSelectGroup ); + PREFER_SMALLER(visualSelectGroup); - /* The sort order for the visualRating is GLX_NONE, GLX_SLOW, and - * GLX_NON_CONFORMANT_CONFIG. It just so happens that this is the - * numerical sort order of the enums (0x8000, 0x8001, and 0x800D). - */ - PREFER_SMALLER( visualRating ); + /* The sort order for the visualRating is GLX_NONE, GLX_SLOW, and + * GLX_NON_CONFORMANT_CONFIG. It just so happens that this is the + * numerical sort order of the enums (0x8000, 0x8001, and 0x800D). + */ + PREFER_SMALLER(visualRating); - /* This isn't quite right. It is supposed to compare the sum of the - * components the user specifically set minimums for. - */ - PREFER_LARGER_OR_ZERO( redBits ); - PREFER_LARGER_OR_ZERO( greenBits ); - PREFER_LARGER_OR_ZERO( blueBits ); - PREFER_LARGER_OR_ZERO( alphaBits ); + /* This isn't quite right. It is supposed to compare the sum of the + * components the user specifically set minimums for. + */ + PREFER_LARGER_OR_ZERO(redBits); + PREFER_LARGER_OR_ZERO(greenBits); + PREFER_LARGER_OR_ZERO(blueBits); + PREFER_LARGER_OR_ZERO(alphaBits); - PREFER_SMALLER( rgbBits ); + PREFER_SMALLER(rgbBits); - if ( ((*a)->doubleBufferMode != (*b)->doubleBufferMode) ) { - /* Prefer single-buffer. - */ - return ( !(*a)->doubleBufferMode ) ? -1 : 1; - } + if (((*a)->doubleBufferMode != (*b)->doubleBufferMode)) { + /* Prefer single-buffer. + */ + return (!(*a)->doubleBufferMode) ? -1 : 1; + } - PREFER_SMALLER( numAuxBuffers ); + PREFER_SMALLER(numAuxBuffers); - PREFER_LARGER_OR_ZERO( depthBits ); - PREFER_SMALLER( stencilBits ); + PREFER_LARGER_OR_ZERO(depthBits); + PREFER_SMALLER(stencilBits); - /* This isn't quite right. It is supposed to compare the sum of the - * components the user specifically set minimums for. - */ - PREFER_LARGER_OR_ZERO( accumRedBits ); - PREFER_LARGER_OR_ZERO( accumGreenBits ); - PREFER_LARGER_OR_ZERO( accumBlueBits ); - PREFER_LARGER_OR_ZERO( accumAlphaBits ); + /* This isn't quite right. It is supposed to compare the sum of the + * components the user specifically set minimums for. + */ + PREFER_LARGER_OR_ZERO(accumRedBits); + PREFER_LARGER_OR_ZERO(accumGreenBits); + PREFER_LARGER_OR_ZERO(accumBlueBits); + PREFER_LARGER_OR_ZERO(accumAlphaBits); - PREFER_SMALLER( visualType ); + PREFER_SMALLER(visualType); - /* None of the multisample specs say where this comparison should happen, - * so I put it near the end. - */ - PREFER_SMALLER( sampleBuffers ); - PREFER_SMALLER( samples ); + /* None of the multisample specs say where this comparison should happen, + * so I put it near the end. + */ + PREFER_SMALLER(sampleBuffers); + PREFER_SMALLER(samples); - /* None of the pbuffer or fbconfig specs say that this comparison needs - * to happen at all, but it seems like it should. - */ - PREFER_LARGER( maxPbufferWidth ); - PREFER_LARGER( maxPbufferHeight ); - PREFER_LARGER( maxPbufferPixels ); + /* None of the pbuffer or fbconfig specs say that this comparison needs + * to happen at all, but it seems like it should. + */ + PREFER_LARGER(maxPbufferWidth); + PREFER_LARGER(maxPbufferHeight); + PREFER_LARGER(maxPbufferPixels); - return 0; + return 0; } @@ -1232,7 +1273,7 @@ fbconfig_compare( const __GLcontextModes * const * const a, * Selects and sorts a subset of the supplied configs based on the attributes. * This function forms to basis of \c glXChooseVisual, \c glXChooseFBConfig, * and \c glXChooseFBConfigSGIX. - * + * * \param configs Array of pointers to possible configs. The elements of * this array that do not meet the criteria will be set to * NULL. The remaining elements will be sorted according to @@ -1247,53 +1288,52 @@ fbconfig_compare( const __GLcontextModes * const * const a, * \c glXChooseVisual style or * \c glXChooseFBConfig style. * \returns The number of valid elements left in \c configs. - * + * * \sa glXChooseVisual, glXChooseFBConfig, glXChooseFBConfigSGIX */ static int -choose_visual( __GLcontextModes ** configs, int num_configs, - const int *attribList, GLboolean fbconfig_style_tags ) -{ - __GLcontextModes test_config; - int base; - int i; - - /* This is a fairly direct implementation of the selection method - * described by GLX_SGIX_fbconfig. Start by culling out all the - * configs that are not compatible with the selected parameter - * list. - */ - - init_fbconfig_for_chooser( & test_config, fbconfig_style_tags ); - __glXInitializeVisualConfigFromTags( & test_config, 512, - (const INT32 *) attribList, - GL_TRUE, fbconfig_style_tags ); - - base = 0; - for ( i = 0 ; i < num_configs ; i++ ) { - if ( fbconfigs_compatible( & test_config, configs[i] ) ) { - configs[ base ] = configs[ i ]; - base++; - } - } - - if ( base == 0 ) { - return 0; - } - - if ( base < num_configs ) { - (void) memset( & configs[ base ], 0, - sizeof( void * ) * (num_configs - base) ); - } - - /* After the incompatible configs are removed, the resulting - * list is sorted according to the rules set out in the various - * specifications. - */ - - qsort( configs, base, sizeof( __GLcontextModes * ), - (int (*)(const void*, const void*)) fbconfig_compare ); - return base; +choose_visual(__GLcontextModes ** configs, int num_configs, + const int *attribList, GLboolean fbconfig_style_tags) +{ + __GLcontextModes test_config; + int base; + int i; + + /* This is a fairly direct implementation of the selection method + * described by GLX_SGIX_fbconfig. Start by culling out all the + * configs that are not compatible with the selected parameter + * list. + */ + + init_fbconfig_for_chooser(&test_config, fbconfig_style_tags); + __glXInitializeVisualConfigFromTags(&test_config, 512, + (const INT32 *) attribList, + GL_TRUE, fbconfig_style_tags); + + base = 0; + for (i = 0; i < num_configs; i++) { + if (fbconfigs_compatible(&test_config, configs[i])) { + configs[base] = configs[i]; + base++; + } + } + + if (base == 0) { + return 0; + } + + if (base < num_configs) { + (void) memset(&configs[base], 0, sizeof(void *) * (num_configs - base)); + } + + /* After the incompatible configs are removed, the resulting + * list is sorted according to the rules set out in the various + * specifications. + */ + + qsort(configs, base, sizeof(__GLcontextModes *), + (int (*)(const void *, const void *)) fbconfig_compare); + return base; } @@ -1303,33 +1343,34 @@ choose_visual( __GLcontextModes ** configs, int num_configs, ** Return the visual that best matches the template. Return None if no ** visual matches the template. */ -PUBLIC XVisualInfo *glXChooseVisual(Display *dpy, int screen, int *attribList) +PUBLIC XVisualInfo * +glXChooseVisual(Display * dpy, int screen, int *attribList) { - XVisualInfo *visualList = NULL; - __GLXdisplayPrivate *priv; - __GLXscreenConfigs *psc; - __GLcontextModes test_config; - __GLcontextModes *modes; - const __GLcontextModes *best_config = NULL; + XVisualInfo *visualList = NULL; + __GLXdisplayPrivate *priv; + __GLXscreenConfigs *psc; + __GLcontextModes test_config; + __GLcontextModes *modes; + const __GLcontextModes *best_config = NULL; - /* + /* ** Get a list of all visuals, return if list is empty */ - if ( GetGLXPrivScreenConfig( dpy, screen, & priv, & psc ) != Success ) { - return None; - } - + if (GetGLXPrivScreenConfig(dpy, screen, &priv, &psc) != Success) { + return None; + } - /* + + /* ** Build a template from the defaults and the attribute list ** Free visual list and return if an unexpected token is encountered */ - init_fbconfig_for_chooser( & test_config, GL_FALSE ); - __glXInitializeVisualConfigFromTags( & test_config, 512, - (const INT32 *) attribList, - GL_TRUE, GL_FALSE ); + init_fbconfig_for_chooser(&test_config, GL_FALSE); + __glXInitializeVisualConfigFromTags(&test_config, 512, + (const INT32 *) attribList, + GL_TRUE, GL_FALSE); - /* + /* ** Eliminate visuals that don't meet minimum requirements ** Compute a score for those that do ** Remember which visual, if any, got the highest score @@ -1337,136 +1378,141 @@ PUBLIC XVisualInfo *glXChooseVisual(Display *dpy, int screen, int *attribList) ** Otherwise, create an XVisualInfo list with just the selected X visual ** and return this. */ - for ( modes = psc->visuals ; modes != NULL ; modes = modes->next ) { - if ( fbconfigs_compatible( & test_config, modes ) - && ((best_config == NULL) - || (fbconfig_compare( (const __GLcontextModes * const * const)&modes, &best_config ) < 0)) ) { - XVisualInfo visualTemplate; - XVisualInfo *newList; - int i; - - visualTemplate.screen = screen; - visualTemplate.visualid = modes->visualID; - newList = XGetVisualInfo( dpy, VisualScreenMask|VisualIDMask, - &visualTemplate, &i ); - - if (newList) { - Xfree(visualList); - visualList = newList; - best_config = modes; - } - } - } + for (modes = psc->visuals; modes != NULL; modes = modes->next) { + if (fbconfigs_compatible(&test_config, modes) + && ((best_config == NULL) + || + (fbconfig_compare + ((const __GLcontextModes * const *const) &modes, + &best_config) < 0))) { + XVisualInfo visualTemplate; + XVisualInfo *newList; + int i; + + visualTemplate.screen = screen; + visualTemplate.visualid = modes->visualID; + newList = XGetVisualInfo(dpy, VisualScreenMask | VisualIDMask, + &visualTemplate, &i); + + if (newList) { + Xfree(visualList); + visualList = newList; + best_config = modes; + } + } + } - return visualList; + return visualList; } -PUBLIC const char *glXQueryExtensionsString( Display *dpy, int screen ) +PUBLIC const char * +glXQueryExtensionsString(Display * dpy, int screen) { - __GLXscreenConfigs *psc; - __GLXdisplayPrivate *priv; + __GLXscreenConfigs *psc; + __GLXdisplayPrivate *priv; - if ( GetGLXPrivScreenConfig( dpy, screen, & priv, & psc ) != Success ) { - return NULL; - } + if (GetGLXPrivScreenConfig(dpy, screen, &priv, &psc) != Success) { + return NULL; + } - if (!psc->effectiveGLXexts) { - if (!psc->serverGLXexts) { - psc->serverGLXexts = - __glXQueryServerString(dpy, priv->majorOpcode, screen, GLX_EXTENSIONS); - } + if (!psc->effectiveGLXexts) { + if (!psc->serverGLXexts) { + psc->serverGLXexts = + __glXQueryServerString(dpy, priv->majorOpcode, screen, + GLX_EXTENSIONS); + } - __glXCalculateUsableExtensions(psc, + __glXCalculateUsableExtensions(psc, #ifdef GLX_DIRECT_RENDERING - (psc->driScreen != NULL), + (psc->driScreen != NULL), #else - GL_FALSE, + GL_FALSE, #endif - priv->minorVersion); - } + priv->minorVersion); + } - return psc->effectiveGLXexts; + return psc->effectiveGLXexts; } -PUBLIC const char *glXGetClientString( Display *dpy, int name ) +PUBLIC const char * +glXGetClientString(Display * dpy, int name) { - switch(name) { - case GLX_VENDOR: - return (__glXGLXClientVendorName); - case GLX_VERSION: - return (__glXGLXClientVersion); - case GLX_EXTENSIONS: - return (__glXGetClientExtensions()); - default: - return NULL; - } + switch (name) { + case GLX_VENDOR: + return (__glXGLXClientVendorName); + case GLX_VERSION: + return (__glXGLXClientVersion); + case GLX_EXTENSIONS: + return (__glXGetClientExtensions()); + default: + return NULL; + } } -PUBLIC const char *glXQueryServerString( Display *dpy, int screen, int name ) +PUBLIC const char * +glXQueryServerString(Display * dpy, int screen, int name) { - __GLXscreenConfigs *psc; - __GLXdisplayPrivate *priv; - const char ** str; + __GLXscreenConfigs *psc; + __GLXdisplayPrivate *priv; + const char **str; - if ( GetGLXPrivScreenConfig( dpy, screen, & priv, & psc ) != Success ) { - return NULL; - } + if (GetGLXPrivScreenConfig(dpy, screen, &priv, &psc) != Success) { + return NULL; + } - switch(name) { - case GLX_VENDOR: - str = & priv->serverGLXvendor; - break; - case GLX_VERSION: - str = & priv->serverGLXversion; - break; - case GLX_EXTENSIONS: - str = & psc->serverGLXexts; - break; - default: - return NULL; - } + switch (name) { + case GLX_VENDOR: + str = &priv->serverGLXvendor; + break; + case GLX_VERSION: + str = &priv->serverGLXversion; + break; + case GLX_EXTENSIONS: + str = &psc->serverGLXexts; + break; + default: + return NULL; + } - if ( *str == NULL ) { - *str = __glXQueryServerString(dpy, priv->majorOpcode, screen, name); - } - - return *str; + if (*str == NULL) { + *str = __glXQueryServerString(dpy, priv->majorOpcode, screen, name); + } + + return *str; } -void __glXClientInfo ( Display *dpy, int opcode ) +void +__glXClientInfo(Display * dpy, int opcode) { - char * ext_str = __glXGetClientGLExtensionString(); - int size = strlen( ext_str ) + 1; + char *ext_str = __glXGetClientGLExtensionString(); + int size = strlen(ext_str) + 1; #ifdef USE_XCB xcb_connection_t *c = XGetXCBConnection(dpy); xcb_glx_client_info(c, - GLX_MAJOR_VERSION, - GLX_MINOR_VERSION, - size, - (const uint8_t *)ext_str); + GLX_MAJOR_VERSION, GLX_MINOR_VERSION, size, ext_str); #else - xGLXClientInfoReq *req; - - /* Send the glXClientInfo request */ - LockDisplay(dpy); - GetReq(GLXClientInfo,req); - req->reqType = opcode; - req->glxCode = X_GLXClientInfo; - req->major = GLX_MAJOR_VERSION; - req->minor = GLX_MINOR_VERSION; - - req->length += (size + 3) >> 2; - req->numbytes = size; - Data(dpy, ext_str, size); - - UnlockDisplay(dpy); - SyncHandle(); + xGLXClientInfoReq *req; + + /* Send the glXClientInfo request */ + LockDisplay(dpy); + GetReq(GLXClientInfo, req); + req->reqType = opcode; + req->glxCode = X_GLXClientInfo; + req->major = GLX_MAJOR_VERSION; + req->minor = GLX_MINOR_VERSION; + + req->length += (size + 3) >> 2; + req->numbytes = size; + Data(dpy, ext_str, size); + + UnlockDisplay(dpy); + SyncHandle(); #endif /* USE_XCB */ - Xfree( ext_str ); + Xfree(ext_str); } @@ -1474,194 +1520,201 @@ void __glXClientInfo ( Display *dpy, int opcode ) ** EXT_import_context */ -PUBLIC Display *glXGetCurrentDisplay(void) +PUBLIC Display * +glXGetCurrentDisplay(void) { - GLXContext gc = __glXGetCurrentContext(); - if (NULL == gc) return NULL; - return gc->currentDpy; + GLXContext gc = __glXGetCurrentContext(); + if (NULL == gc) + return NULL; + return gc->currentDpy; } -PUBLIC GLX_ALIAS(Display *, glXGetCurrentDisplayEXT, (void), (), - glXGetCurrentDisplay) +PUBLIC +GLX_ALIAS(Display *, glXGetCurrentDisplayEXT, (void), (), + glXGetCurrentDisplay) /** * Used internally by libGL to send \c xGLXQueryContextinfoExtReq requests * to the X-server. - * + * * \param dpy Display where \c ctx was created. * \param ctx Context to query. * \returns \c Success on success. \c GLX_BAD_CONTEXT if \c ctx is invalid, * or zero if the request failed due to internal problems (i.e., * unable to allocate temporary memory, etc.) - * + * * \note * This function dynamically determines whether to use the EXT_import_context * version of the protocol or the GLX 1.3 version of the protocol. */ -static int __glXQueryContextInfo(Display *dpy, GLXContext ctx) -{ - __GLXdisplayPrivate *priv = __glXInitialize(dpy); - xGLXQueryContextReply reply; - CARD8 opcode; - GLuint numValues; - int retval; - - if (ctx == NULL) { - return GLX_BAD_CONTEXT; - } - opcode = __glXSetupForCommand(dpy); - if (!opcode) { - return 0; - } - - /* Send the glXQueryContextInfoEXT request */ - LockDisplay(dpy); - - if ( (priv->majorVersion > 1) || (priv->minorVersion >= 3) ) { - xGLXQueryContextReq *req; - - GetReq(GLXQueryContext, req); - - req->reqType = opcode; - req->glxCode = X_GLXQueryContext; - req->context = (unsigned int)(ctx->xid); - } - else { - xGLXVendorPrivateReq *vpreq; - xGLXQueryContextInfoEXTReq *req; - - GetReqExtra( GLXVendorPrivate, - sz_xGLXQueryContextInfoEXTReq - sz_xGLXVendorPrivateReq, - vpreq ); - req = (xGLXQueryContextInfoEXTReq *)vpreq; - req->reqType = opcode; - req->glxCode = X_GLXVendorPrivateWithReply; - req->vendorCode = X_GLXvop_QueryContextInfoEXT; - req->context = (unsigned int)(ctx->xid); - } - - _XReply(dpy, (xReply*) &reply, 0, False); - - numValues = reply.n; - if (numValues == 0) - retval = Success; - else if (numValues > __GLX_MAX_CONTEXT_PROPS) - retval = 0; - else - { - int *propList, *pProp; - int nPropListBytes; - int i; - - nPropListBytes = numValues << 3; - propList = (int *) Xmalloc(nPropListBytes); - if (NULL == propList) { - retval = 0; - } else { - _XRead(dpy, (char *)propList, nPropListBytes); - pProp = propList; - for (i=0; i < numValues; i++) { - switch (*pProp++) { - case GLX_SHARE_CONTEXT_EXT: - ctx->share_xid = *pProp++; - break; - case GLX_VISUAL_ID_EXT: - ctx->mode = - _gl_context_modes_find_visual(ctx->psc->visuals, *pProp++); - break; - case GLX_SCREEN: - ctx->screen = *pProp++; - break; - case GLX_FBCONFIG_ID: - ctx->mode = - _gl_context_modes_find_fbconfig(ctx->psc->configs, *pProp++); - break; - case GLX_RENDER_TYPE: - ctx->renderType = *pProp++; - break; - default: - pProp++; - continue; - } - } - Xfree((char *)propList); - retval = Success; - } - } - UnlockDisplay(dpy); - SyncHandle(); - return retval; + static int __glXQueryContextInfo(Display * dpy, GLXContext ctx) +{ + __GLXdisplayPrivate *priv = __glXInitialize(dpy); + xGLXQueryContextReply reply; + CARD8 opcode; + GLuint numValues; + int retval; + + if (ctx == NULL) { + return GLX_BAD_CONTEXT; + } + opcode = __glXSetupForCommand(dpy); + if (!opcode) { + return 0; + } + + /* Send the glXQueryContextInfoEXT request */ + LockDisplay(dpy); + + if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) { + xGLXQueryContextReq *req; + + GetReq(GLXQueryContext, req); + + req->reqType = opcode; + req->glxCode = X_GLXQueryContext; + req->context = (unsigned int) (ctx->xid); + } + else { + xGLXVendorPrivateReq *vpreq; + xGLXQueryContextInfoEXTReq *req; + + GetReqExtra(GLXVendorPrivate, + sz_xGLXQueryContextInfoEXTReq - sz_xGLXVendorPrivateReq, + vpreq); + req = (xGLXQueryContextInfoEXTReq *) vpreq; + req->reqType = opcode; + req->glxCode = X_GLXVendorPrivateWithReply; + req->vendorCode = X_GLXvop_QueryContextInfoEXT; + req->context = (unsigned int) (ctx->xid); + } + + _XReply(dpy, (xReply *) & reply, 0, False); + + numValues = reply.n; + if (numValues == 0) + retval = Success; + else if (numValues > __GLX_MAX_CONTEXT_PROPS) + retval = 0; + else { + int *propList, *pProp; + int nPropListBytes; + int i; + + nPropListBytes = numValues << 3; + propList = (int *) Xmalloc(nPropListBytes); + if (NULL == propList) { + retval = 0; + } + else { + _XRead(dpy, (char *) propList, nPropListBytes); + pProp = propList; + for (i = 0; i < numValues; i++) { + switch (*pProp++) { + case GLX_SHARE_CONTEXT_EXT: + ctx->share_xid = *pProp++; + break; + case GLX_VISUAL_ID_EXT: + ctx->mode = + _gl_context_modes_find_visual(ctx->psc->visuals, *pProp++); + break; + case GLX_SCREEN: + ctx->screen = *pProp++; + break; + case GLX_FBCONFIG_ID: + ctx->mode = + _gl_context_modes_find_fbconfig(ctx->psc->configs, + *pProp++); + break; + case GLX_RENDER_TYPE: + ctx->renderType = *pProp++; + break; + default: + pProp++; + continue; + } + } + Xfree((char *) propList); + retval = Success; + } + } + UnlockDisplay(dpy); + SyncHandle(); + return retval; } PUBLIC int -glXQueryContext(Display *dpy, GLXContext ctx, int attribute, int *value) +glXQueryContext(Display * dpy, GLXContext ctx, int attribute, int *value) { - int retVal; + int retVal; - /* get the information from the server if we don't have it already */ + /* get the information from the server if we don't have it already */ #ifdef GLX_DIRECT_RENDERING - if (!ctx->driContext && (ctx->mode == NULL)) { + if (!ctx->driContext && (ctx->mode == NULL)) { #else - if (ctx->mode == NULL) { + if (ctx->mode == NULL) { #endif - retVal = __glXQueryContextInfo(dpy, ctx); - if (Success != retVal) return retVal; - } - switch (attribute) { - case GLX_SHARE_CONTEXT_EXT: - *value = (int)(ctx->share_xid); - break; - case GLX_VISUAL_ID_EXT: - *value = ctx->mode ? ctx->mode->visualID : None; - break; - case GLX_SCREEN: - *value = (int)(ctx->screen); - break; - case GLX_FBCONFIG_ID: - *value = ctx->mode ? ctx->mode->fbconfigID : None; - break; - case GLX_RENDER_TYPE: - *value = (int)(ctx->renderType); - break; - default: - return GLX_BAD_ATTRIBUTE; - } - return Success; + retVal = __glXQueryContextInfo(dpy, ctx); + if (Success != retVal) + return retVal; + } + switch (attribute) { + case GLX_SHARE_CONTEXT_EXT: + *value = (int) (ctx->share_xid); + break; + case GLX_VISUAL_ID_EXT: + *value = ctx->mode ? ctx->mode->visualID : None; + break; + case GLX_SCREEN: + *value = (int) (ctx->screen); + break; + case GLX_FBCONFIG_ID: + *value = ctx->mode ? ctx->mode->fbconfigID : None; + break; + case GLX_RENDER_TYPE: + *value = (int) (ctx->renderType); + break; + default: + return GLX_BAD_ATTRIBUTE; + } + return Success; } -PUBLIC GLX_ALIAS( int, glXQueryContextInfoEXT, - (Display *dpy, GLXContext ctx, int attribute, int *value), - (dpy, ctx, attribute, value), - glXQueryContext ) +PUBLIC +GLX_ALIAS(int, glXQueryContextInfoEXT, + (Display * dpy, GLXContext ctx, int attribute, int *value), + (dpy, ctx, attribute, value), glXQueryContext) -PUBLIC GLXContextID glXGetContextIDEXT(const GLXContext ctx) + PUBLIC GLXContextID glXGetContextIDEXT(const GLXContext ctx) { - return ctx->xid; + return ctx->xid; } -PUBLIC GLXContext glXImportContextEXT(Display *dpy, GLXContextID contextID) +PUBLIC GLXContext +glXImportContextEXT(Display * dpy, GLXContextID contextID) { - GLXContext ctx; + GLXContext ctx; - if (contextID == None) { - return NULL; - } - if (__glXIsDirect(dpy, contextID)) { - return NULL; - } + if (contextID == None) { + return NULL; + } + if (__glXIsDirect(dpy, contextID)) { + return NULL; + } - ctx = CreateContext(dpy, NULL, NULL, NULL, False, contextID, False, 0); - if (NULL != ctx) { - if (Success != __glXQueryContextInfo(dpy, ctx)) { - return NULL; - } - } - return ctx; + ctx = CreateContext(dpy, NULL, NULL, NULL, False, contextID, False, 0); + if (NULL != ctx) { + if (Success != __glXQueryContextInfo(dpy, ctx)) { + return NULL; + } + } + return ctx; } -PUBLIC void glXFreeContextEXT(Display *dpy, GLXContext ctx) +PUBLIC void +glXFreeContextEXT(Display * dpy, GLXContext ctx) { - DestroyContext(dpy, ctx); + DestroyContext(dpy, ctx); } @@ -1670,147 +1723,149 @@ PUBLIC void glXFreeContextEXT(Display *dpy, GLXContext ctx) * GLX 1.3 functions - these are just stubs for now! */ -PUBLIC GLXFBConfig *glXChooseFBConfig(Display *dpy, int screen, - const int *attribList, int *nitems) +PUBLIC GLXFBConfig * +glXChooseFBConfig(Display * dpy, int screen, + const int *attribList, int *nitems) { - __GLcontextModes ** config_list; - int list_size; + __GLcontextModes **config_list; + int list_size; - config_list = (__GLcontextModes **) - glXGetFBConfigs( dpy, screen, & list_size ); + config_list = (__GLcontextModes **) + glXGetFBConfigs(dpy, screen, &list_size); - if ( (config_list != NULL) && (list_size > 0) && (attribList != NULL) ) { - list_size = choose_visual( config_list, list_size, attribList, - GL_TRUE ); - if ( list_size == 0 ) { - XFree( config_list ); - config_list = NULL; - } - } + if ((config_list != NULL) && (list_size > 0) && (attribList != NULL)) { + list_size = choose_visual(config_list, list_size, attribList, GL_TRUE); + if (list_size == 0) { + XFree(config_list); + config_list = NULL; + } + } - *nitems = list_size; - return (GLXFBConfig *) config_list; + *nitems = list_size; + return (GLXFBConfig *) config_list; } -PUBLIC GLXContext glXCreateNewContext(Display *dpy, GLXFBConfig config, - int renderType, GLXContext shareList, - Bool allowDirect) +PUBLIC GLXContext +glXCreateNewContext(Display * dpy, GLXFBConfig config, + int renderType, GLXContext shareList, Bool allowDirect) { - return CreateContext( dpy, NULL, (__GLcontextModes *) config, shareList, - allowDirect, None, True, renderType ); + return CreateContext(dpy, NULL, (__GLcontextModes *) config, shareList, + allowDirect, None, True, renderType); } -PUBLIC GLXDrawable glXGetCurrentReadDrawable(void) +PUBLIC GLXDrawable +glXGetCurrentReadDrawable(void) { - GLXContext gc = __glXGetCurrentContext(); - return gc->currentReadable; + GLXContext gc = __glXGetCurrentContext(); + return gc->currentReadable; } -PUBLIC GLXFBConfig *glXGetFBConfigs(Display *dpy, int screen, int *nelements) +PUBLIC GLXFBConfig * +glXGetFBConfigs(Display * dpy, int screen, int *nelements) { - __GLXdisplayPrivate *priv = __glXInitialize(dpy); - __GLcontextModes ** config = NULL; - int i; + __GLXdisplayPrivate *priv = __glXInitialize(dpy); + __GLcontextModes **config = NULL; + int i; - *nelements = 0; - if ( priv - && (priv->screenConfigs != NULL) - && (screen >= 0) && (screen <= ScreenCount(dpy)) - && (priv->screenConfigs[screen].configs != NULL) - && (priv->screenConfigs[screen].configs->fbconfigID != GLX_DONT_CARE) ) { - unsigned num_configs = 0; - __GLcontextModes * modes; + *nelements = 0; + if (priv && (priv->screenConfigs != NULL) + && (screen >= 0) && (screen <= ScreenCount(dpy)) + && (priv->screenConfigs[screen].configs != NULL) + && (priv->screenConfigs[screen].configs->fbconfigID != GLX_DONT_CARE)) { + unsigned num_configs = 0; + __GLcontextModes *modes; - for ( modes = priv->screenConfigs[screen].configs - ; modes != NULL - ; modes = modes->next ) { - if ( modes->fbconfigID != GLX_DONT_CARE ) { - num_configs++; - } - } + for (modes = priv->screenConfigs[screen].configs; modes != NULL; + modes = modes->next) { + if (modes->fbconfigID != GLX_DONT_CARE) { + num_configs++; + } + } - config = (__GLcontextModes **) Xmalloc( sizeof(__GLcontextModes *) - * num_configs ); - if ( config != NULL ) { - *nelements = num_configs; - i = 0; - for ( modes = priv->screenConfigs[screen].configs - ; modes != NULL - ; modes = modes->next ) { - if ( modes->fbconfigID != GLX_DONT_CARE ) { - config[i] = modes; - i++; - } - } - } - } - return (GLXFBConfig *) config; + config = (__GLcontextModes **) Xmalloc(sizeof(__GLcontextModes *) + * num_configs); + if (config != NULL) { + *nelements = num_configs; + i = 0; + for (modes = priv->screenConfigs[screen].configs; modes != NULL; + modes = modes->next) { + if (modes->fbconfigID != GLX_DONT_CARE) { + config[i] = modes; + i++; + } + } + } + } + return (GLXFBConfig *) config; } -PUBLIC int glXGetFBConfigAttrib(Display *dpy, GLXFBConfig config, - int attribute, int *value) +PUBLIC int +glXGetFBConfigAttrib(Display * dpy, GLXFBConfig config, + int attribute, int *value) { - __GLcontextModes * const modes = ValidateGLXFBConfig( dpy, config ); + __GLcontextModes *const modes = ValidateGLXFBConfig(dpy, config); - return (modes != NULL) - ? _gl_get_context_mode_data( modes, attribute, value ) - : GLXBadFBConfig; + return (modes != NULL) + ? _gl_get_context_mode_data(modes, attribute, value) + : GLXBadFBConfig; } -PUBLIC XVisualInfo *glXGetVisualFromFBConfig(Display *dpy, GLXFBConfig config) +PUBLIC XVisualInfo * +glXGetVisualFromFBConfig(Display * dpy, GLXFBConfig config) { - XVisualInfo visualTemplate; - __GLcontextModes * fbconfig = (__GLcontextModes *) config; - int count; + XVisualInfo visualTemplate; + __GLcontextModes *fbconfig = (__GLcontextModes *) config; + int count; - /* + /* ** Get a list of all visuals, return if list is empty */ - visualTemplate.visualid = fbconfig->visualID; - return XGetVisualInfo(dpy,VisualIDMask,&visualTemplate,&count); + visualTemplate.visualid = fbconfig->visualID; + return XGetVisualInfo(dpy, VisualIDMask, &visualTemplate, &count); } /* ** GLX_SGI_swap_control */ -static int __glXSwapIntervalSGI(int interval) +static int +__glXSwapIntervalSGI(int interval) { xGLXVendorPrivateReq *req; GLXContext gc = __glXGetCurrentContext(); - Display * dpy; - CARD32 * interval_ptr; + Display *dpy; + CARD32 *interval_ptr; CARD8 opcode; - if ( gc == NULL ) { + if (gc == NULL) { return GLX_BAD_CONTEXT; } - - if ( interval <= 0 ) { + + if (interval <= 0) { return GLX_BAD_VALUE; } #ifdef __DRI_SWAP_CONTROL if (gc->driContext) { - __GLXscreenConfigs * const psc = GetGLXScreenConfigs( gc->currentDpy, - gc->screen ); - __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(gc->currentDpy, - gc->currentDrawable, - NULL); - if (psc->swapControl != NULL && pdraw != NULL) { - psc->swapControl->setSwapInterval(pdraw->driDrawable, interval); - return 0; - } - else { - return GLX_BAD_CONTEXT; - } + __GLXscreenConfigs *const psc = GetGLXScreenConfigs(gc->currentDpy, + gc->screen); + __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(gc->currentDpy, + gc->currentDrawable, + NULL); + if (psc->swapControl != NULL && pdraw != NULL) { + psc->swapControl->setSwapInterval(pdraw->driDrawable, interval); + return 0; + } + else { + return GLX_BAD_CONTEXT; + } } #endif dpy = gc->currentDpy; @@ -1821,7 +1876,7 @@ static int __glXSwapIntervalSGI(int interval) /* Send the glXSwapIntervalSGI request */ LockDisplay(dpy); - GetReqExtra(GLXVendorPrivate,sizeof(CARD32),req); + GetReqExtra(GLXVendorPrivate, sizeof(CARD32), req); req->reqType = opcode; req->glxCode = X_GLXVendorPrivate; req->vendorCode = X_GLXvop_SwapIntervalSGI; @@ -1841,26 +1896,27 @@ static int __glXSwapIntervalSGI(int interval) /* ** GLX_MESA_swap_control */ -static int __glXSwapIntervalMESA(unsigned int interval) +static int +__glXSwapIntervalMESA(unsigned int interval) { #ifdef __DRI_SWAP_CONTROL GLXContext gc = __glXGetCurrentContext(); - if ( interval < 0 ) { + if (interval < 0) { return GLX_BAD_VALUE; } if (gc != NULL && gc->driContext) { - __GLXscreenConfigs * const psc = GetGLXScreenConfigs( gc->currentDpy, - gc->screen ); - - if ( (psc != NULL) && (psc->driScreen != NULL) ) { - __GLXDRIdrawable *pdraw = - GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); - if (psc->swapControl != NULL && pdraw != NULL) { - psc->swapControl->setSwapInterval(pdraw->driDrawable, interval); - return 0; - } + __GLXscreenConfigs *const psc = GetGLXScreenConfigs(gc->currentDpy, + gc->screen); + + if ((psc != NULL) && (psc->driScreen != NULL)) { + __GLXDRIdrawable *pdraw = + GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); + if (psc->swapControl != NULL && pdraw != NULL) { + psc->swapControl->setSwapInterval(pdraw->driDrawable, interval); + return 0; + } } } #else @@ -1869,23 +1925,24 @@ static int __glXSwapIntervalMESA(unsigned int interval) return GLX_BAD_CONTEXT; } - -static int __glXGetSwapIntervalMESA(void) + +static int +__glXGetSwapIntervalMESA(void) { #ifdef __DRI_SWAP_CONTROL GLXContext gc = __glXGetCurrentContext(); if (gc != NULL && gc->driContext) { - __GLXscreenConfigs * const psc = GetGLXScreenConfigs( gc->currentDpy, - gc->screen ); - - if ( (psc != NULL) && (psc->driScreen != NULL) ) { - __GLXDRIdrawable *pdraw = - GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); - if (psc->swapControl != NULL && pdraw != NULL) { - return psc->swapControl->getSwapInterval(pdraw->driDrawable); - } + __GLXscreenConfigs *const psc = GetGLXScreenConfigs(gc->currentDpy, + gc->screen); + + if ((psc != NULL) && (psc->driScreen != NULL)) { + __GLXDRIdrawable *pdraw = + GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); + if (psc->swapControl != NULL && pdraw != NULL) { + return psc->swapControl->getSwapInterval(pdraw->driDrawable); + } } } #endif @@ -1898,16 +1955,17 @@ static int __glXGetSwapIntervalMESA(void) ** GLX_MESA_swap_frame_usage */ -static GLint __glXBeginFrameTrackingMESA(Display *dpy, GLXDrawable drawable) +static GLint +__glXBeginFrameTrackingMESA(Display * dpy, GLXDrawable drawable) { - int status = GLX_BAD_CONTEXT; + int status = GLX_BAD_CONTEXT; #ifdef __DRI_FRAME_TRACKING int screen; __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); - __GLXscreenConfigs * const psc = GetGLXScreenConfigs(dpy, screen); + __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); if (pdraw != NULL && psc->frameTracking != NULL) - status = psc->frameTracking->frameTracking(pdraw->driDrawable, GL_TRUE); + status = psc->frameTracking->frameTracking(pdraw->driDrawable, GL_TRUE); #else (void) dpy; (void) drawable; @@ -1915,18 +1973,19 @@ static GLint __glXBeginFrameTrackingMESA(Display *dpy, GLXDrawable drawable) return status; } - -static GLint __glXEndFrameTrackingMESA(Display *dpy, GLXDrawable drawable) + +static GLint +__glXEndFrameTrackingMESA(Display * dpy, GLXDrawable drawable) { - int status = GLX_BAD_CONTEXT; + int status = GLX_BAD_CONTEXT; #ifdef __DRI_FRAME_TRACKING int screen; - __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, & screen); + __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); __GLXscreenConfigs *psc = GetGLXScreenConfigs(dpy, screen); if (pdraw != NULL && psc->frameTracking != NULL) - status = psc->frameTracking->frameTracking(pdraw->driDrawable, - GL_FALSE); + status = psc->frameTracking->frameTracking(pdraw->driDrawable, + GL_FALSE); #else (void) dpy; (void) drawable; @@ -1935,24 +1994,24 @@ static GLint __glXEndFrameTrackingMESA(Display *dpy, GLXDrawable drawable) } -static GLint __glXGetFrameUsageMESA(Display *dpy, GLXDrawable drawable, - GLfloat *usage) +static GLint +__glXGetFrameUsageMESA(Display * dpy, GLXDrawable drawable, GLfloat * usage) { - int status = GLX_BAD_CONTEXT; + int status = GLX_BAD_CONTEXT; #ifdef __DRI_FRAME_TRACKING int screen; - __GLXDRIdrawable * const pdraw = GetGLXDRIDrawable(dpy, drawable, & screen); - __GLXscreenConfigs * const psc = GetGLXScreenConfigs(dpy, screen); + __GLXDRIdrawable *const pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); + __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); if (pdraw != NULL && psc->frameTracking != NULL) { - int64_t sbc, missedFrames; - float lastMissedUsage; + int64_t sbc, missedFrames; + float lastMissedUsage; - status = psc->frameTracking->queryFrameTracking(pdraw->driDrawable, - &sbc, - &missedFrames, - &lastMissedUsage, - usage); + status = psc->frameTracking->queryFrameTracking(pdraw->driDrawable, + &sbc, + &missedFrames, + &lastMissedUsage, + usage); } #else (void) dpy; @@ -1963,22 +2022,24 @@ static GLint __glXGetFrameUsageMESA(Display *dpy, GLXDrawable drawable, } -static GLint __glXQueryFrameTrackingMESA(Display *dpy, GLXDrawable drawable, - int64_t *sbc, int64_t *missedFrames, - GLfloat *lastMissedUsage) +static GLint +__glXQueryFrameTrackingMESA(Display * dpy, GLXDrawable drawable, + int64_t * sbc, int64_t * missedFrames, + GLfloat * lastMissedUsage) { - int status = GLX_BAD_CONTEXT; + int status = GLX_BAD_CONTEXT; #ifdef __DRI_FRAME_TRACKING int screen; - __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, & screen); - __GLXscreenConfigs * const psc = GetGLXScreenConfigs(dpy, screen); + __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); + __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); if (pdraw != NULL && psc->frameTracking != NULL) { - float usage; + float usage; status = psc->frameTracking->queryFrameTracking(pdraw->driDrawable, - sbc, missedFrames, - lastMissedUsage, &usage); + sbc, missedFrames, + lastMissedUsage, + &usage); } #else (void) dpy; @@ -1994,7 +2055,8 @@ static GLint __glXQueryFrameTrackingMESA(Display *dpy, GLXDrawable drawable, /* ** GLX_SGI_video_sync */ -static int __glXGetVideoSyncSGI(unsigned int *count) +static int +__glXGetVideoSyncSGI(unsigned int *count) { /* FIXME: Looking at the GLX_SGI_video_sync spec in the extension registry, * FIXME: there should be a GLX encoding for this call. I can find no @@ -2005,49 +2067,50 @@ static int __glXGetVideoSyncSGI(unsigned int *count) if (gc != NULL && gc->driContext) { - __GLXscreenConfigs * const psc = GetGLXScreenConfigs( gc->currentDpy, - gc->screen ); - if ( psc->msc && psc->driScreen ) { - __GLXDRIdrawable *pdraw = - GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); - int64_t temp; - int ret; - - ret = (*psc->msc->getDrawableMSC)(psc->__driScreen, - pdraw->driDrawable, &temp); - *count = (unsigned) temp; - - return (ret == 0) ? 0 : GLX_BAD_CONTEXT; + __GLXscreenConfigs *const psc = GetGLXScreenConfigs(gc->currentDpy, + gc->screen); + if (psc->msc && psc->driScreen) { + __GLXDRIdrawable *pdraw = + GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); + int64_t temp; + int ret; + + ret = (*psc->msc->getDrawableMSC) (psc->__driScreen, + pdraw->driDrawable, &temp); + *count = (unsigned) temp; + + return (ret == 0) ? 0 : GLX_BAD_CONTEXT; } } #else - (void) count; + (void) count; #endif return GLX_BAD_CONTEXT; } -static int __glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count) +static int +__glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count) { #ifdef __DRI_MEDIA_STREAM_COUNTER GLXContext gc = __glXGetCurrentContext(); - if ( divisor <= 0 || remainder < 0 ) - return GLX_BAD_VALUE; + if (divisor <= 0 || remainder < 0) + return GLX_BAD_VALUE; if (gc != NULL && gc->driContext) { - __GLXscreenConfigs * const psc = GetGLXScreenConfigs( gc->currentDpy, - gc->screen ); - if (psc->msc != NULL && psc->driScreen ) { - __GLXDRIdrawable *pdraw = - GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); - int ret; - int64_t msc; - int64_t sbc; - - ret = (*psc->msc->waitForMSC)(pdraw->driDrawable, 0, - divisor, remainder, &msc, &sbc); - *count = (unsigned) msc; - return (ret == 0) ? 0 : GLX_BAD_CONTEXT; + __GLXscreenConfigs *const psc = GetGLXScreenConfigs(gc->currentDpy, + gc->screen); + if (psc->msc != NULL && psc->driScreen) { + __GLXDRIdrawable *pdraw = + GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL); + int ret; + int64_t msc; + int64_t sbc; + + ret = (*psc->msc->waitForMSC) (pdraw->driDrawable, 0, + divisor, remainder, &msc, &sbc); + *count = (unsigned) msc; + return (ret == 0) ? 0 : GLX_BAD_CONTEXT; } } #else @@ -2063,109 +2126,112 @@ static int __glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count ** GLX_functions table. */ -PUBLIC GLX_ALIAS(int, glXGetFBConfigAttribSGIX, - (Display *dpy, GLXFBConfigSGIX config, int attribute, int *value), - (dpy, config, attribute, value), - glXGetFBConfigAttrib) +PUBLIC +GLX_ALIAS(int, glXGetFBConfigAttribSGIX, + (Display * dpy, GLXFBConfigSGIX config, int attribute, int *value), + (dpy, config, attribute, value), glXGetFBConfigAttrib) -PUBLIC GLX_ALIAS(GLXFBConfigSGIX *, glXChooseFBConfigSGIX, - (Display *dpy, int screen, int *attrib_list, int *nelements), - (dpy, screen, attrib_list, nelements), - glXChooseFBConfig) + PUBLIC GLX_ALIAS(GLXFBConfigSGIX *, glXChooseFBConfigSGIX, + (Display * dpy, int screen, int *attrib_list, + int *nelements), (dpy, screen, attrib_list, nelements), + glXChooseFBConfig) -PUBLIC GLX_ALIAS(XVisualInfo *, glXGetVisualFromFBConfigSGIX, - (Display * dpy, GLXFBConfigSGIX config), - (dpy, config), - glXGetVisualFromFBConfig) + PUBLIC GLX_ALIAS(XVisualInfo *, glXGetVisualFromFBConfigSGIX, + (Display * dpy, GLXFBConfigSGIX config), + (dpy, config), glXGetVisualFromFBConfig) -PUBLIC GLXPixmap glXCreateGLXPixmapWithConfigSGIX(Display *dpy, - GLXFBConfigSGIX config, Pixmap pixmap) + PUBLIC GLXPixmap glXCreateGLXPixmapWithConfigSGIX(Display * dpy, + GLXFBConfigSGIX config, + Pixmap pixmap) { - xGLXVendorPrivateWithReplyReq *vpreq; - xGLXCreateGLXPixmapWithConfigSGIXReq *req; - GLXPixmap xid = None; - CARD8 opcode; - const __GLcontextModes * const fbconfig = (__GLcontextModes *) config; - __GLXscreenConfigs * psc; + xGLXVendorPrivateWithReplyReq *vpreq; + xGLXCreateGLXPixmapWithConfigSGIXReq *req; + GLXPixmap xid = None; + CARD8 opcode; + const __GLcontextModes *const fbconfig = (__GLcontextModes *) config; + __GLXscreenConfigs *psc; - if ( (dpy == NULL) || (config == NULL) ) { - return None; - } + if ((dpy == NULL) || (config == NULL)) { + return None; + } - psc = GetGLXScreenConfigs( dpy, fbconfig->screen ); - if ( (psc != NULL) - && __glXExtensionBitIsEnabled( psc, SGIX_fbconfig_bit ) ) { - opcode = __glXSetupForCommand(dpy); - if (!opcode) { - return None; - } + psc = GetGLXScreenConfigs(dpy, fbconfig->screen); + if ((psc != NULL) + && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)) { + opcode = __glXSetupForCommand(dpy); + if (!opcode) { + return None; + } - /* Send the glXCreateGLXPixmapWithConfigSGIX request */ - LockDisplay(dpy); - GetReqExtra(GLXVendorPrivateWithReply, - sz_xGLXCreateGLXPixmapWithConfigSGIXReq-sz_xGLXVendorPrivateWithReplyReq,vpreq); - req = (xGLXCreateGLXPixmapWithConfigSGIXReq *)vpreq; - req->reqType = opcode; - req->glxCode = X_GLXVendorPrivateWithReply; - req->vendorCode = X_GLXvop_CreateGLXPixmapWithConfigSGIX; - req->screen = fbconfig->screen; - req->fbconfig = fbconfig->fbconfigID; - req->pixmap = pixmap; - req->glxpixmap = xid = XAllocID(dpy); - UnlockDisplay(dpy); - SyncHandle(); - } + /* Send the glXCreateGLXPixmapWithConfigSGIX request */ + LockDisplay(dpy); + GetReqExtra(GLXVendorPrivateWithReply, + sz_xGLXCreateGLXPixmapWithConfigSGIXReq - + sz_xGLXVendorPrivateWithReplyReq, vpreq); + req = (xGLXCreateGLXPixmapWithConfigSGIXReq *) vpreq; + req->reqType = opcode; + req->glxCode = X_GLXVendorPrivateWithReply; + req->vendorCode = X_GLXvop_CreateGLXPixmapWithConfigSGIX; + req->screen = fbconfig->screen; + req->fbconfig = fbconfig->fbconfigID; + req->pixmap = pixmap; + req->glxpixmap = xid = XAllocID(dpy); + UnlockDisplay(dpy); + SyncHandle(); + } - return xid; + return xid; } -PUBLIC GLXContext glXCreateContextWithConfigSGIX(Display *dpy, - GLXFBConfigSGIX config, int renderType, - GLXContext shareList, Bool allowDirect) +PUBLIC GLXContext +glXCreateContextWithConfigSGIX(Display * dpy, + GLXFBConfigSGIX config, int renderType, + GLXContext shareList, Bool allowDirect) { - GLXContext gc = NULL; - const __GLcontextModes * const fbconfig = (__GLcontextModes *) config; - __GLXscreenConfigs * psc; + GLXContext gc = NULL; + const __GLcontextModes *const fbconfig = (__GLcontextModes *) config; + __GLXscreenConfigs *psc; - if ( (dpy == NULL) || (config == NULL) ) { - return None; - } + if ((dpy == NULL) || (config == NULL)) { + return None; + } - psc = GetGLXScreenConfigs( dpy, fbconfig->screen ); - if ( (psc != NULL) - && __glXExtensionBitIsEnabled( psc, SGIX_fbconfig_bit ) ) { - gc = CreateContext( dpy, NULL, (__GLcontextModes *) config, shareList, - allowDirect, None, False, renderType ); - } + psc = GetGLXScreenConfigs(dpy, fbconfig->screen); + if ((psc != NULL) + && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)) { + gc = CreateContext(dpy, NULL, (__GLcontextModes *) config, shareList, + allowDirect, None, False, renderType); + } - return gc; + return gc; } -PUBLIC GLXFBConfigSGIX glXGetFBConfigFromVisualSGIX(Display *dpy, - XVisualInfo *vis) +PUBLIC GLXFBConfigSGIX +glXGetFBConfigFromVisualSGIX(Display * dpy, XVisualInfo * vis) { - __GLXdisplayPrivate *priv; - __GLXscreenConfigs *psc; + __GLXdisplayPrivate *priv; + __GLXscreenConfigs *psc; - if ( (GetGLXPrivScreenConfig( dpy, vis->screen, & priv, & psc ) != Success) - && __glXExtensionBitIsEnabled( psc, SGIX_fbconfig_bit ) - && (psc->configs->fbconfigID != GLX_DONT_CARE) ) { - return (GLXFBConfigSGIX) _gl_context_modes_find_visual( psc->configs, - vis->visualid ); - } + if ((GetGLXPrivScreenConfig(dpy, vis->screen, &priv, &psc) != Success) + && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit) + && (psc->configs->fbconfigID != GLX_DONT_CARE)) { + return (GLXFBConfigSGIX) _gl_context_modes_find_visual(psc->configs, + vis->visualid); + } - return NULL; + return NULL; } /* ** GLX_SGIX_swap_group */ -static void __glXJoinSwapGroupSGIX(Display *dpy, GLXDrawable drawable, - GLXDrawable member) +static void +__glXJoinSwapGroupSGIX(Display * dpy, GLXDrawable drawable, + GLXDrawable member) { (void) dpy; (void) drawable; @@ -2176,15 +2242,16 @@ static void __glXJoinSwapGroupSGIX(Display *dpy, GLXDrawable drawable, /* ** GLX_SGIX_swap_barrier */ -static void __glXBindSwapBarrierSGIX(Display *dpy, GLXDrawable drawable, - int barrier) +static void +__glXBindSwapBarrierSGIX(Display * dpy, GLXDrawable drawable, int barrier) { (void) dpy; (void) drawable; (void) barrier; } -static Bool __glXQueryMaxSwapBarriersSGIX(Display *dpy, int screen, int *max) +static Bool +__glXQueryMaxSwapBarriersSGIX(Display * dpy, int screen, int *max) { (void) dpy; (void) screen; @@ -2196,23 +2263,24 @@ static Bool __glXQueryMaxSwapBarriersSGIX(Display *dpy, int screen, int *max) /* ** GLX_OML_sync_control */ -static Bool __glXGetSyncValuesOML(Display *dpy, GLXDrawable drawable, - int64_t *ust, int64_t *msc, int64_t *sbc) +static Bool +__glXGetSyncValuesOML(Display * dpy, GLXDrawable drawable, + int64_t * ust, int64_t * msc, int64_t * sbc) { #if defined(__DRI_SWAP_BUFFER_COUNTER) && defined(__DRI_MEDIA_STREAM_COUNTER) - __GLXdisplayPrivate * const priv = __glXInitialize(dpy); - - if ( priv != NULL ) { - int i; - __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &i); - __GLXscreenConfigs * const psc = &priv->screenConfigs[i]; - - assert( (pdraw == NULL) || (i != -1) ); - return ( (pdraw && psc->sbc && psc->msc) - && ((*psc->msc->getMSC)(psc->driScreen, msc) == 0) - && ((*psc->sbc->getSBC)(pdraw->driDrawable, sbc) == 0) - && (__glXGetUST(ust) == 0) ); - } + __GLXdisplayPrivate *const priv = __glXInitialize(dpy); + + if (priv != NULL) { + int i; + __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &i); + __GLXscreenConfigs *const psc = &priv->screenConfigs[i]; + + assert((pdraw == NULL) || (i != -1)); + return ((pdraw && psc->sbc && psc->msc) + && ((*psc->msc->getMSC) (psc->driScreen, msc) == 0) + && ((*psc->sbc->getSBC) (pdraw->driDrawable, sbc) == 0) + && (__glXGetUST(ust) == 0)); + } #else (void) dpy; (void) drawable; @@ -2225,94 +2293,94 @@ static Bool __glXGetSyncValuesOML(Display *dpy, GLXDrawable drawable, #ifdef GLX_DIRECT_RENDERING _X_HIDDEN GLboolean -__driGetMscRateOML(__DRIdrawable *draw, - int32_t *numerator, int32_t *denominator, void *private) +__driGetMscRateOML(__DRIdrawable * draw, + int32_t * numerator, int32_t * denominator, void *private) { #ifdef XF86VIDMODE - __GLXscreenConfigs *psc; - XF86VidModeModeLine mode_line; - int dot_clock; - int i; - __GLXDRIdrawable *glxDraw = private; - - psc = glxDraw->psc; - if (XF86VidModeQueryVersion(psc->dpy, &i, &i) && - XF86VidModeGetModeLine(psc->dpy, psc->scr, &dot_clock, &mode_line) ) { - unsigned n = dot_clock * 1000; - unsigned d = mode_line.vtotal * mode_line.htotal; - + __GLXscreenConfigs *psc; + XF86VidModeModeLine mode_line; + int dot_clock; + int i; + __GLXDRIdrawable *glxDraw = private; + + psc = glxDraw->psc; + if (XF86VidModeQueryVersion(psc->dpy, &i, &i) && + XF86VidModeGetModeLine(psc->dpy, psc->scr, &dot_clock, &mode_line)) { + unsigned n = dot_clock * 1000; + unsigned d = mode_line.vtotal * mode_line.htotal; + # define V_INTERLACE 0x010 # define V_DBLSCAN 0x020 - if (mode_line.flags & V_INTERLACE) - n *= 2; - else if (mode_line.flags & V_DBLSCAN) - d *= 2; - - /* The OML_sync_control spec requires that if the refresh rate is a - * whole number, that the returned numerator be equal to the refresh - * rate and the denominator be 1. - */ - - if (n % d == 0) { - n /= d; - d = 1; - } - else { - static const unsigned f[] = { 13, 11, 7, 5, 3, 2, 0 }; - - /* This is a poor man's way to reduce a fraction. It's far from - * perfect, but it will work well enough for this situation. - */ - - for (i = 0; f[i] != 0; i++) { - while (n % f[i] == 0 && d % f[i] == 0) { - d /= f[i]; - n /= f[i]; - } - } - } - - *numerator = n; - *denominator = d; - - return True; - } - else - return False; + if (mode_line.flags & V_INTERLACE) + n *= 2; + else if (mode_line.flags & V_DBLSCAN) + d *= 2; + + /* The OML_sync_control spec requires that if the refresh rate is a + * whole number, that the returned numerator be equal to the refresh + * rate and the denominator be 1. + */ + + if (n % d == 0) { + n /= d; + d = 1; + } + else { + static const unsigned f[] = { 13, 11, 7, 5, 3, 2, 0 }; + + /* This is a poor man's way to reduce a fraction. It's far from + * perfect, but it will work well enough for this situation. + */ + + for (i = 0; f[i] != 0; i++) { + while (n % f[i] == 0 && d % f[i] == 0) { + d /= f[i]; + n /= f[i]; + } + } + } + + *numerator = n; + *denominator = d; + + return True; + } + else + return False; #else - return False; + return False; #endif } #endif /** * Determine the refresh rate of the specified drawable and display. - * + * * \param dpy Display whose refresh rate is to be determined. * \param drawable Drawable whose refresh rate is to be determined. * \param numerator Numerator of the refresh rate. * \param demoninator Denominator of the refresh rate. * \return If the refresh rate for the specified display and drawable could * be calculated, True is returned. Otherwise False is returned. - * + * * \note This function is implemented entirely client-side. A lot of other * functionality is required to export GLX_OML_sync_control, so on * XFree86 this function can be called for direct-rendering contexts * when GLX_OML_sync_control appears in the client extension string. */ -_X_HIDDEN GLboolean __glXGetMscRateOML(Display * dpy, GLXDrawable drawable, - int32_t * numerator, - int32_t * denominator) +_X_HIDDEN GLboolean +__glXGetMscRateOML(Display * dpy, GLXDrawable drawable, + int32_t * numerator, int32_t * denominator) { #if defined( GLX_DIRECT_RENDERING ) && defined( XF86VIDMODE ) - __GLXDRIdrawable *draw = GetGLXDRIDrawable(dpy, drawable, NULL); + __GLXDRIdrawable *draw = GetGLXDRIDrawable(dpy, drawable, NULL); - if (draw == NULL) - return False; + if (draw == NULL) + return False; - return __driGetMscRateOML(draw->driDrawable, numerator, denominator, draw); + return __driGetMscRateOML(draw->driDrawable, numerator, denominator, draw); #else (void) dpy; (void) drawable; @@ -2323,28 +2391,28 @@ _X_HIDDEN GLboolean __glXGetMscRateOML(Display * dpy, GLXDrawable drawable, } -static int64_t __glXSwapBuffersMscOML(Display *dpy, GLXDrawable drawable, - int64_t target_msc, int64_t divisor, - int64_t remainder) +static int64_t +__glXSwapBuffersMscOML(Display * dpy, GLXDrawable drawable, + int64_t target_msc, int64_t divisor, int64_t remainder) { #ifdef __DRI_SWAP_BUFFER_COUNTER int screen; __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); - __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, screen ); + __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); /* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE * error", but it also says "It [glXSwapBuffersMscOML] will return a value * of -1 if the function failed because of errors detected in the input * parameters" */ - if ( divisor < 0 || remainder < 0 || target_msc < 0 ) + if (divisor < 0 || remainder < 0 || target_msc < 0) return -1; - if ( divisor > 0 && remainder >= divisor ) + if (divisor > 0 && remainder >= divisor) return -1; if (pdraw != NULL && psc->counters != NULL) - return (*psc->sbc->swapBuffersMSC)(pdraw->driDrawable, target_msc, - divisor, remainder); + return (*psc->sbc->swapBuffersMSC) (pdraw->driDrawable, target_msc, + divisor, remainder); #else (void) dpy; @@ -2357,33 +2425,34 @@ static int64_t __glXSwapBuffersMscOML(Display *dpy, GLXDrawable drawable, } -static Bool __glXWaitForMscOML(Display * dpy, GLXDrawable drawable, - int64_t target_msc, int64_t divisor, - int64_t remainder, int64_t *ust, - int64_t *msc, int64_t *sbc) +static Bool +__glXWaitForMscOML(Display * dpy, GLXDrawable drawable, + int64_t target_msc, int64_t divisor, + int64_t remainder, int64_t * ust, + int64_t * msc, int64_t * sbc) { #ifdef __DRI_MEDIA_STREAM_COUNTER int screen; __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); - __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, screen ); - int ret; + __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); + int ret; /* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE * error", but the return type in the spec is Bool. */ - if ( divisor < 0 || remainder < 0 || target_msc < 0 ) + if (divisor < 0 || remainder < 0 || target_msc < 0) return False; - if ( divisor > 0 && remainder >= divisor ) + if (divisor > 0 && remainder >= divisor) return False; if (pdraw != NULL && psc->msc != NULL) { - ret = (*psc->msc->waitForMSC)(pdraw->driDrawable, target_msc, - divisor, remainder, msc, sbc); + ret = (*psc->msc->waitForMSC) (pdraw->driDrawable, target_msc, + divisor, remainder, msc, sbc); /* __glXGetUST returns zero on success and non-zero on failure. * This function returns True on success and False on failure. */ - return ( (ret == 0) && (__glXGetUST( ust ) == 0) ); + return ((ret == 0) && (__glXGetUST(ust) == 0)); } #else (void) dpy; @@ -2399,29 +2468,31 @@ static Bool __glXWaitForMscOML(Display * dpy, GLXDrawable drawable, } -static Bool __glXWaitForSbcOML(Display * dpy, GLXDrawable drawable, - int64_t target_sbc, int64_t *ust, - int64_t *msc, int64_t *sbc ) +static Bool +__glXWaitForSbcOML(Display * dpy, GLXDrawable drawable, + int64_t target_sbc, int64_t * ust, + int64_t * msc, int64_t * sbc) { #ifdef __DRI_SWAP_BUFFER_COUNTER int screen; __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); - __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, screen ); - int ret; + __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); + int ret; /* The OML_sync_control spec says this should "generate a GLX_BAD_VALUE * error", but the return type in the spec is Bool. */ - if ( target_sbc < 0 ) + if (target_sbc < 0) return False; if (pdraw != NULL && psc->sbc != NULL) { - ret = (*psc->sbc->waitForSBC)(pdraw->driDrawable, target_sbc, msc, sbc); + ret = + (*psc->sbc->waitForSBC) (pdraw->driDrawable, target_sbc, msc, sbc); /* __glXGetUST returns zero on success and non-zero on failure. * This function returns True on success and False on failure. */ - return( (ret == 0) && (__glXGetUST( ust ) == 0) ); + return ((ret == 0) && (__glXGetUST(ust) == 0)); } #else (void) dpy; @@ -2440,16 +2511,17 @@ static Bool __glXWaitForSbcOML(Display * dpy, GLXDrawable drawable, */ /*@{*/ -PUBLIC void *glXAllocateMemoryMESA(Display *dpy, int scrn, - size_t size, float readFreq, - float writeFreq, float priority) +PUBLIC void * +glXAllocateMemoryMESA(Display * dpy, int scrn, + size_t size, float readFreq, + float writeFreq, float priority) { #ifdef __DRI_ALLOCATE - __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, scrn ); + __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, scrn); if (psc && psc->allocate) - return (*psc->allocate->allocateMemory)(psc->__driScreen, size, - readFreq, writeFreq, priority); + return (*psc->allocate->allocateMemory) (psc->__driScreen, size, + readFreq, writeFreq, priority); #else (void) dpy; @@ -2464,13 +2536,14 @@ PUBLIC void *glXAllocateMemoryMESA(Display *dpy, int scrn, } -PUBLIC void glXFreeMemoryMESA(Display *dpy, int scrn, void *pointer) +PUBLIC void +glXFreeMemoryMESA(Display * dpy, int scrn, void *pointer) { #ifdef __DRI_ALLOCATE - __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, scrn ); + __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, scrn); if (psc && psc->allocate) - (*psc->allocate->freeMemory)(psc->__driScreen, pointer); + (*psc->allocate->freeMemory) (psc->__driScreen, pointer); #else (void) dpy; @@ -2480,14 +2553,14 @@ PUBLIC void glXFreeMemoryMESA(Display *dpy, int scrn, void *pointer) } -PUBLIC GLuint glXGetMemoryOffsetMESA( Display *dpy, int scrn, - const void *pointer ) +PUBLIC GLuint +glXGetMemoryOffsetMESA(Display * dpy, int scrn, const void *pointer) { #ifdef __DRI_ALLOCATE - __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, scrn ); + __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, scrn); if (psc && psc->allocate) - return (*psc->allocate->memoryOffset)(psc->__driScreen, pointer); + return (*psc->allocate->memoryOffset) (psc->__driScreen, pointer); #else (void) dpy; @@ -2497,6 +2570,7 @@ PUBLIC GLuint glXGetMemoryOffsetMESA( Display *dpy, int scrn, return ~0L; } + /*@}*/ @@ -2527,7 +2601,8 @@ PUBLIC GLuint glXGetMemoryOffsetMESA( Display *dpy, int scrn, * glXDestroyPbuffer glXDestroyPixmap glXDestroyWindow * glXDestroyGLXPbufferSGIX glXDestroyGLXVideoSourceSGIX */ -static Bool __glXReleaseBuffersMESA( Display *dpy, GLXDrawable d ) +static Bool +__glXReleaseBuffersMESA(Display * dpy, GLXDrawable d) { (void) dpy; (void) d; @@ -2535,8 +2610,9 @@ static Bool __glXReleaseBuffersMESA( Display *dpy, GLXDrawable d ) } -PUBLIC GLXPixmap glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visual, - Pixmap pixmap, Colormap cmap ) +PUBLIC GLXPixmap +glXCreateGLXPixmapMESA(Display * dpy, XVisualInfo * visual, + Pixmap pixmap, Colormap cmap) { (void) dpy; (void) visual; @@ -2544,6 +2620,7 @@ PUBLIC GLXPixmap glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visual, (void) cmap; return 0; } + /*@}*/ @@ -2551,68 +2628,70 @@ PUBLIC GLXPixmap glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visual, * GLX_MESA_copy_sub_buffer */ #define X_GLXvop_CopySubBufferMESA 5154 /* temporary */ -static void __glXCopySubBufferMESA(Display *dpy, GLXDrawable drawable, - int x, int y, int width, int height) +static void +__glXCopySubBufferMESA(Display * dpy, GLXDrawable drawable, + int x, int y, int width, int height) { - xGLXVendorPrivateReq *req; - GLXContext gc; - GLXContextTag tag; - CARD32 *drawable_ptr; - INT32 *x_ptr, *y_ptr, *w_ptr, *h_ptr; - CARD8 opcode; + xGLXVendorPrivateReq *req; + GLXContext gc; + GLXContextTag tag; + CARD32 *drawable_ptr; + INT32 *x_ptr, *y_ptr, *w_ptr, *h_ptr; + CARD8 opcode; #ifdef __DRI_COPY_SUB_BUFFER - int screen; - __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); - if ( pdraw != NULL ) { - __GLXscreenConfigs * const psc = GetGLXScreenConfigs(dpy, screen); - if (psc->driScreen->copySubBuffer != NULL) { - glFlush(); - (*psc->driScreen->copySubBuffer)(pdraw, x, y, width, height); - } - - return; - } + int screen; + __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); + if (pdraw != NULL) { + __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen); + if (psc->driScreen->copySubBuffer != NULL) { + glFlush(); + (*psc->driScreen->copySubBuffer) (pdraw, x, y, width, height); + } + + return; + } #endif - opcode = __glXSetupForCommand(dpy); - if (!opcode) - return; + opcode = __glXSetupForCommand(dpy); + if (!opcode) + return; - /* + /* ** The calling thread may or may not have a current context. If it ** does, send the context tag so the server can do a flush. */ - gc = __glXGetCurrentContext(); - if ((gc != NULL) && (dpy == gc->currentDpy) && - ((drawable == gc->currentDrawable) || - (drawable == gc->currentReadable)) ) { - tag = gc->currentContextTag; - } else { - tag = 0; - } - - LockDisplay(dpy); - GetReqExtra(GLXVendorPrivate, sizeof(CARD32) + sizeof(INT32) * 4,req); - req->reqType = opcode; - req->glxCode = X_GLXVendorPrivate; - req->vendorCode = X_GLXvop_CopySubBufferMESA; - req->contextTag = tag; - - drawable_ptr = (CARD32 *) (req + 1); - x_ptr = (INT32 *) (drawable_ptr + 1); - y_ptr = (INT32 *) (drawable_ptr + 2); - w_ptr = (INT32 *) (drawable_ptr + 3); - h_ptr = (INT32 *) (drawable_ptr + 4); - - *drawable_ptr = drawable; - *x_ptr = x; - *y_ptr = y; - *w_ptr = width; - *h_ptr = height; - - UnlockDisplay(dpy); - SyncHandle(); + gc = __glXGetCurrentContext(); + if ((gc != NULL) && (dpy == gc->currentDpy) && + ((drawable == gc->currentDrawable) || + (drawable == gc->currentReadable))) { + tag = gc->currentContextTag; + } + else { + tag = 0; + } + + LockDisplay(dpy); + GetReqExtra(GLXVendorPrivate, sizeof(CARD32) + sizeof(INT32) * 4, req); + req->reqType = opcode; + req->glxCode = X_GLXVendorPrivate; + req->vendorCode = X_GLXvop_CopySubBufferMESA; + req->contextTag = tag; + + drawable_ptr = (CARD32 *) (req + 1); + x_ptr = (INT32 *) (drawable_ptr + 1); + y_ptr = (INT32 *) (drawable_ptr + 2); + w_ptr = (INT32 *) (drawable_ptr + 3); + h_ptr = (INT32 *) (drawable_ptr + 4); + + *drawable_ptr = drawable; + *x_ptr = x; + *y_ptr = y; + *w_ptr = width; + *h_ptr = height; + + UnlockDisplay(dpy); + SyncHandle(); } @@ -2620,128 +2699,127 @@ static void __glXCopySubBufferMESA(Display *dpy, GLXDrawable drawable, * GLX_EXT_texture_from_pixmap */ /*@{*/ -static void __glXBindTexImageEXT(Display *dpy, - GLXDrawable drawable, - int buffer, - const int *attrib_list) -{ - xGLXVendorPrivateReq *req; - GLXContext gc = __glXGetCurrentContext(); - CARD32 *drawable_ptr; - INT32 *buffer_ptr; - CARD32 *num_attrib_ptr; - CARD32 *attrib_ptr; - CARD8 opcode; - unsigned int i; - - if (gc == NULL) - return; - - i = 0; - if (attrib_list) { - while (attrib_list[i * 2] != None) - i++; - } - +static void +__glXBindTexImageEXT(Display * dpy, + GLXDrawable drawable, int buffer, const int *attrib_list) +{ + xGLXVendorPrivateReq *req; + GLXContext gc = __glXGetCurrentContext(); + CARD32 *drawable_ptr; + INT32 *buffer_ptr; + CARD32 *num_attrib_ptr; + CARD32 *attrib_ptr; + CARD8 opcode; + unsigned int i; + + if (gc == NULL) + return; + + i = 0; + if (attrib_list) { + while (attrib_list[i * 2] != None) + i++; + } + #ifdef GLX_DIRECT_RENDERING - if (gc->driContext) { - __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL); - - if (pdraw != NULL) { - if (pdraw->psc->texBuffer->base.version >= 2 && - pdraw->psc->texBuffer->setTexBuffer2 != NULL) { - (*pdraw->psc->texBuffer->setTexBuffer2)(gc->__driContext, - pdraw->textureTarget, - pdraw->textureFormat, - pdraw->driDrawable); - } else { - (*pdraw->psc->texBuffer->setTexBuffer)(gc->__driContext, - pdraw->textureTarget, - pdraw->driDrawable); - } - } - return; - } + if (gc->driContext) { + __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL); + + if (pdraw != NULL) { + if (pdraw->psc->texBuffer->base.version >= 2 && + pdraw->psc->texBuffer->setTexBuffer2 != NULL) { + (*pdraw->psc->texBuffer->setTexBuffer2) (gc->__driContext, + pdraw->textureTarget, + pdraw->textureFormat, + pdraw->driDrawable); + } + else { + (*pdraw->psc->texBuffer->setTexBuffer) (gc->__driContext, + pdraw->textureTarget, + pdraw->driDrawable); + } + } + return; + } #endif - opcode = __glXSetupForCommand(dpy); - if (!opcode) - return; - - LockDisplay(dpy); - GetReqExtra(GLXVendorPrivate, 12 + 8 * i,req); - req->reqType = opcode; - req->glxCode = X_GLXVendorPrivate; - req->vendorCode = X_GLXvop_BindTexImageEXT; - req->contextTag = gc->currentContextTag; - - drawable_ptr = (CARD32 *) (req + 1); - buffer_ptr = (INT32 *) (drawable_ptr + 1); - num_attrib_ptr = (CARD32 *) (buffer_ptr + 1); - attrib_ptr = (CARD32 *) (num_attrib_ptr + 1); - - *drawable_ptr = drawable; - *buffer_ptr = buffer; - *num_attrib_ptr = (CARD32) i; - - i = 0; - if (attrib_list) { - while (attrib_list[i * 2] != None) - { - *attrib_ptr++ = (CARD32) attrib_list[i * 2 + 0]; - *attrib_ptr++ = (CARD32) attrib_list[i * 2 + 1]; - i++; - } - } - - UnlockDisplay(dpy); - SyncHandle(); -} - -static void __glXReleaseTexImageEXT(Display *dpy, - GLXDrawable drawable, - int buffer) -{ - xGLXVendorPrivateReq *req; - GLXContext gc = __glXGetCurrentContext(); - CARD32 *drawable_ptr; - INT32 *buffer_ptr; - CARD8 opcode; - - if (gc == NULL) - return; + opcode = __glXSetupForCommand(dpy); + if (!opcode) + return; + + LockDisplay(dpy); + GetReqExtra(GLXVendorPrivate, 12 + 8 * i, req); + req->reqType = opcode; + req->glxCode = X_GLXVendorPrivate; + req->vendorCode = X_GLXvop_BindTexImageEXT; + req->contextTag = gc->currentContextTag; + + drawable_ptr = (CARD32 *) (req + 1); + buffer_ptr = (INT32 *) (drawable_ptr + 1); + num_attrib_ptr = (CARD32 *) (buffer_ptr + 1); + attrib_ptr = (CARD32 *) (num_attrib_ptr + 1); + + *drawable_ptr = drawable; + *buffer_ptr = buffer; + *num_attrib_ptr = (CARD32) i; + + i = 0; + if (attrib_list) { + while (attrib_list[i * 2] != None) { + *attrib_ptr++ = (CARD32) attrib_list[i * 2 + 0]; + *attrib_ptr++ = (CARD32) attrib_list[i * 2 + 1]; + i++; + } + } + + UnlockDisplay(dpy); + SyncHandle(); +} + +static void +__glXReleaseTexImageEXT(Display * dpy, GLXDrawable drawable, int buffer) +{ + xGLXVendorPrivateReq *req; + GLXContext gc = __glXGetCurrentContext(); + CARD32 *drawable_ptr; + INT32 *buffer_ptr; + CARD8 opcode; + + if (gc == NULL) + return; #ifdef GLX_DIRECT_RENDERING - if (gc->driContext) - return; + if (gc->driContext) + return; #endif - opcode = __glXSetupForCommand(dpy); - if (!opcode) - return; + opcode = __glXSetupForCommand(dpy); + if (!opcode) + return; - LockDisplay(dpy); - GetReqExtra(GLXVendorPrivate, sizeof(CARD32)+sizeof(INT32),req); - req->reqType = opcode; - req->glxCode = X_GLXVendorPrivate; - req->vendorCode = X_GLXvop_ReleaseTexImageEXT; - req->contextTag = gc->currentContextTag; + LockDisplay(dpy); + GetReqExtra(GLXVendorPrivate, sizeof(CARD32) + sizeof(INT32), req); + req->reqType = opcode; + req->glxCode = X_GLXVendorPrivate; + req->vendorCode = X_GLXvop_ReleaseTexImageEXT; + req->contextTag = gc->currentContextTag; - drawable_ptr = (CARD32 *) (req + 1); - buffer_ptr = (INT32 *) (drawable_ptr + 1); + drawable_ptr = (CARD32 *) (req + 1); + buffer_ptr = (INT32 *) (drawable_ptr + 1); - *drawable_ptr = drawable; - *buffer_ptr = buffer; + *drawable_ptr = drawable; + *buffer_ptr = buffer; - UnlockDisplay(dpy); - SyncHandle(); + UnlockDisplay(dpy); + SyncHandle(); } + /*@}*/ /** * \c strdup is actually not a standard ANSI C or POSIX routine. * Irix will not define it if ANSI mode is in effect. - * + * * \sa strdup */ _X_HIDDEN char * @@ -2759,7 +2837,8 @@ __glXstrdup(const char *str) ** glXGetProcAddress support */ -struct name_address_pair { +struct name_address_pair +{ const char *Name; GLvoid *Address; }; @@ -2769,139 +2848,139 @@ struct name_address_pair { static const struct name_address_pair GLX_functions[] = { /*** GLX_VERSION_1_0 ***/ - GLX_FUNCTION( glXChooseVisual ), - GLX_FUNCTION( glXCopyContext ), - GLX_FUNCTION( glXCreateContext ), - GLX_FUNCTION( glXCreateGLXPixmap ), - GLX_FUNCTION( glXDestroyContext ), - GLX_FUNCTION( glXDestroyGLXPixmap ), - GLX_FUNCTION( glXGetConfig ), - GLX_FUNCTION( glXGetCurrentContext ), - GLX_FUNCTION( glXGetCurrentDrawable ), - GLX_FUNCTION( glXIsDirect ), - GLX_FUNCTION( glXMakeCurrent ), - GLX_FUNCTION( glXQueryExtension ), - GLX_FUNCTION( glXQueryVersion ), - GLX_FUNCTION( glXSwapBuffers ), - GLX_FUNCTION( glXUseXFont ), - GLX_FUNCTION( glXWaitGL ), - GLX_FUNCTION( glXWaitX ), + GLX_FUNCTION(glXChooseVisual), + GLX_FUNCTION(glXCopyContext), + GLX_FUNCTION(glXCreateContext), + GLX_FUNCTION(glXCreateGLXPixmap), + GLX_FUNCTION(glXDestroyContext), + GLX_FUNCTION(glXDestroyGLXPixmap), + GLX_FUNCTION(glXGetConfig), + GLX_FUNCTION(glXGetCurrentContext), + GLX_FUNCTION(glXGetCurrentDrawable), + GLX_FUNCTION(glXIsDirect), + GLX_FUNCTION(glXMakeCurrent), + GLX_FUNCTION(glXQueryExtension), + GLX_FUNCTION(glXQueryVersion), + GLX_FUNCTION(glXSwapBuffers), + GLX_FUNCTION(glXUseXFont), + GLX_FUNCTION(glXWaitGL), + GLX_FUNCTION(glXWaitX), /*** GLX_VERSION_1_1 ***/ - GLX_FUNCTION( glXGetClientString ), - GLX_FUNCTION( glXQueryExtensionsString ), - GLX_FUNCTION( glXQueryServerString ), + GLX_FUNCTION(glXGetClientString), + GLX_FUNCTION(glXQueryExtensionsString), + GLX_FUNCTION(glXQueryServerString), /*** GLX_VERSION_1_2 ***/ - GLX_FUNCTION( glXGetCurrentDisplay ), + GLX_FUNCTION(glXGetCurrentDisplay), /*** GLX_VERSION_1_3 ***/ - GLX_FUNCTION( glXChooseFBConfig ), - GLX_FUNCTION( glXCreateNewContext ), - GLX_FUNCTION( glXCreatePbuffer ), - GLX_FUNCTION( glXCreatePixmap ), - GLX_FUNCTION( glXCreateWindow ), - GLX_FUNCTION( glXDestroyPbuffer ), - GLX_FUNCTION( glXDestroyPixmap ), - GLX_FUNCTION( glXDestroyWindow ), - GLX_FUNCTION( glXGetCurrentReadDrawable ), - GLX_FUNCTION( glXGetFBConfigAttrib ), - GLX_FUNCTION( glXGetFBConfigs ), - GLX_FUNCTION( glXGetSelectedEvent ), - GLX_FUNCTION( glXGetVisualFromFBConfig ), - GLX_FUNCTION( glXMakeContextCurrent ), - GLX_FUNCTION( glXQueryContext ), - GLX_FUNCTION( glXQueryDrawable ), - GLX_FUNCTION( glXSelectEvent ), + GLX_FUNCTION(glXChooseFBConfig), + GLX_FUNCTION(glXCreateNewContext), + GLX_FUNCTION(glXCreatePbuffer), + GLX_FUNCTION(glXCreatePixmap), + GLX_FUNCTION(glXCreateWindow), + GLX_FUNCTION(glXDestroyPbuffer), + GLX_FUNCTION(glXDestroyPixmap), + GLX_FUNCTION(glXDestroyWindow), + GLX_FUNCTION(glXGetCurrentReadDrawable), + GLX_FUNCTION(glXGetFBConfigAttrib), + GLX_FUNCTION(glXGetFBConfigs), + GLX_FUNCTION(glXGetSelectedEvent), + GLX_FUNCTION(glXGetVisualFromFBConfig), + GLX_FUNCTION(glXMakeContextCurrent), + GLX_FUNCTION(glXQueryContext), + GLX_FUNCTION(glXQueryDrawable), + GLX_FUNCTION(glXSelectEvent), /*** GLX_SGI_swap_control ***/ - GLX_FUNCTION2( glXSwapIntervalSGI, __glXSwapIntervalSGI ), + GLX_FUNCTION2(glXSwapIntervalSGI, __glXSwapIntervalSGI), /*** GLX_SGI_video_sync ***/ - GLX_FUNCTION2( glXGetVideoSyncSGI, __glXGetVideoSyncSGI ), - GLX_FUNCTION2( glXWaitVideoSyncSGI, __glXWaitVideoSyncSGI ), + GLX_FUNCTION2(glXGetVideoSyncSGI, __glXGetVideoSyncSGI), + GLX_FUNCTION2(glXWaitVideoSyncSGI, __glXWaitVideoSyncSGI), /*** GLX_SGI_make_current_read ***/ - GLX_FUNCTION2( glXMakeCurrentReadSGI, glXMakeContextCurrent ), - GLX_FUNCTION2( glXGetCurrentReadDrawableSGI, glXGetCurrentReadDrawable ), + GLX_FUNCTION2(glXMakeCurrentReadSGI, glXMakeContextCurrent), + GLX_FUNCTION2(glXGetCurrentReadDrawableSGI, glXGetCurrentReadDrawable), /*** GLX_EXT_import_context ***/ - GLX_FUNCTION( glXFreeContextEXT ), - GLX_FUNCTION( glXGetContextIDEXT ), - GLX_FUNCTION2( glXGetCurrentDisplayEXT, glXGetCurrentDisplay ), - GLX_FUNCTION( glXImportContextEXT ), - GLX_FUNCTION2( glXQueryContextInfoEXT, glXQueryContext ), + GLX_FUNCTION(glXFreeContextEXT), + GLX_FUNCTION(glXGetContextIDEXT), + GLX_FUNCTION2(glXGetCurrentDisplayEXT, glXGetCurrentDisplay), + GLX_FUNCTION(glXImportContextEXT), + GLX_FUNCTION2(glXQueryContextInfoEXT, glXQueryContext), /*** GLX_SGIX_fbconfig ***/ - GLX_FUNCTION2( glXGetFBConfigAttribSGIX, glXGetFBConfigAttrib ), - GLX_FUNCTION2( glXChooseFBConfigSGIX, glXChooseFBConfig ), - GLX_FUNCTION( glXCreateGLXPixmapWithConfigSGIX ), - GLX_FUNCTION( glXCreateContextWithConfigSGIX ), - GLX_FUNCTION2( glXGetVisualFromFBConfigSGIX, glXGetVisualFromFBConfig ), - GLX_FUNCTION( glXGetFBConfigFromVisualSGIX ), + GLX_FUNCTION2(glXGetFBConfigAttribSGIX, glXGetFBConfigAttrib), + GLX_FUNCTION2(glXChooseFBConfigSGIX, glXChooseFBConfig), + GLX_FUNCTION(glXCreateGLXPixmapWithConfigSGIX), + GLX_FUNCTION(glXCreateContextWithConfigSGIX), + GLX_FUNCTION2(glXGetVisualFromFBConfigSGIX, glXGetVisualFromFBConfig), + GLX_FUNCTION(glXGetFBConfigFromVisualSGIX), /*** GLX_SGIX_pbuffer ***/ - GLX_FUNCTION( glXCreateGLXPbufferSGIX ), - GLX_FUNCTION( glXDestroyGLXPbufferSGIX ), - GLX_FUNCTION( glXQueryGLXPbufferSGIX ), - GLX_FUNCTION( glXSelectEventSGIX ), - GLX_FUNCTION( glXGetSelectedEventSGIX ), + GLX_FUNCTION(glXCreateGLXPbufferSGIX), + GLX_FUNCTION(glXDestroyGLXPbufferSGIX), + GLX_FUNCTION(glXQueryGLXPbufferSGIX), + GLX_FUNCTION(glXSelectEventSGIX), + GLX_FUNCTION(glXGetSelectedEventSGIX), /*** GLX_SGIX_swap_group ***/ - GLX_FUNCTION2( glXJoinSwapGroupSGIX, __glXJoinSwapGroupSGIX ), + GLX_FUNCTION2(glXJoinSwapGroupSGIX, __glXJoinSwapGroupSGIX), /*** GLX_SGIX_swap_barrier ***/ - GLX_FUNCTION2( glXBindSwapBarrierSGIX, __glXBindSwapBarrierSGIX ), - GLX_FUNCTION2( glXQueryMaxSwapBarriersSGIX, __glXQueryMaxSwapBarriersSGIX ), + GLX_FUNCTION2(glXBindSwapBarrierSGIX, __glXBindSwapBarrierSGIX), + GLX_FUNCTION2(glXQueryMaxSwapBarriersSGIX, __glXQueryMaxSwapBarriersSGIX), /*** GLX_MESA_allocate_memory ***/ - GLX_FUNCTION( glXAllocateMemoryMESA ), - GLX_FUNCTION( glXFreeMemoryMESA ), - GLX_FUNCTION( glXGetMemoryOffsetMESA ), + GLX_FUNCTION(glXAllocateMemoryMESA), + GLX_FUNCTION(glXFreeMemoryMESA), + GLX_FUNCTION(glXGetMemoryOffsetMESA), /*** GLX_MESA_copy_sub_buffer ***/ - GLX_FUNCTION2( glXCopySubBufferMESA, __glXCopySubBufferMESA ), + GLX_FUNCTION2(glXCopySubBufferMESA, __glXCopySubBufferMESA), /*** GLX_MESA_pixmap_colormap ***/ - GLX_FUNCTION( glXCreateGLXPixmapMESA ), + GLX_FUNCTION(glXCreateGLXPixmapMESA), /*** GLX_MESA_release_buffers ***/ - GLX_FUNCTION2( glXReleaseBuffersMESA, __glXReleaseBuffersMESA ), + GLX_FUNCTION2(glXReleaseBuffersMESA, __glXReleaseBuffersMESA), /*** GLX_MESA_swap_control ***/ - GLX_FUNCTION2( glXSwapIntervalMESA, __glXSwapIntervalMESA ), - GLX_FUNCTION2( glXGetSwapIntervalMESA, __glXGetSwapIntervalMESA ), + GLX_FUNCTION2(glXSwapIntervalMESA, __glXSwapIntervalMESA), + GLX_FUNCTION2(glXGetSwapIntervalMESA, __glXGetSwapIntervalMESA), /*** GLX_MESA_swap_frame_usage ***/ - GLX_FUNCTION2( glXBeginFrameTrackingMESA, __glXBeginFrameTrackingMESA ), - GLX_FUNCTION2( glXEndFrameTrackingMESA, __glXEndFrameTrackingMESA ), - GLX_FUNCTION2( glXGetFrameUsageMESA, __glXGetFrameUsageMESA ), - GLX_FUNCTION2( glXQueryFrameTrackingMESA, __glXQueryFrameTrackingMESA ), + GLX_FUNCTION2(glXBeginFrameTrackingMESA, __glXBeginFrameTrackingMESA), + GLX_FUNCTION2(glXEndFrameTrackingMESA, __glXEndFrameTrackingMESA), + GLX_FUNCTION2(glXGetFrameUsageMESA, __glXGetFrameUsageMESA), + GLX_FUNCTION2(glXQueryFrameTrackingMESA, __glXQueryFrameTrackingMESA), /*** GLX_ARB_get_proc_address ***/ - GLX_FUNCTION( glXGetProcAddressARB ), + GLX_FUNCTION(glXGetProcAddressARB), /*** GLX 1.4 ***/ - GLX_FUNCTION2( glXGetProcAddress, glXGetProcAddressARB ), + GLX_FUNCTION2(glXGetProcAddress, glXGetProcAddressARB), /*** GLX_OML_sync_control ***/ - GLX_FUNCTION2( glXWaitForSbcOML, __glXWaitForSbcOML ), - GLX_FUNCTION2( glXWaitForMscOML, __glXWaitForMscOML ), - GLX_FUNCTION2( glXSwapBuffersMscOML, __glXSwapBuffersMscOML ), - GLX_FUNCTION2( glXGetMscRateOML, __glXGetMscRateOML ), - GLX_FUNCTION2( glXGetSyncValuesOML, __glXGetSyncValuesOML ), + GLX_FUNCTION2(glXWaitForSbcOML, __glXWaitForSbcOML), + GLX_FUNCTION2(glXWaitForMscOML, __glXWaitForMscOML), + GLX_FUNCTION2(glXSwapBuffersMscOML, __glXSwapBuffersMscOML), + GLX_FUNCTION2(glXGetMscRateOML, __glXGetMscRateOML), + GLX_FUNCTION2(glXGetSyncValuesOML, __glXGetSyncValuesOML), /*** GLX_EXT_texture_from_pixmap ***/ - GLX_FUNCTION2( glXBindTexImageEXT, __glXBindTexImageEXT ), - GLX_FUNCTION2( glXReleaseTexImageEXT, __glXReleaseTexImageEXT ), + GLX_FUNCTION2(glXBindTexImageEXT, __glXBindTexImageEXT), + GLX_FUNCTION2(glXReleaseTexImageEXT, __glXReleaseTexImageEXT), #ifdef GLX_DIRECT_RENDERING /*** DRI configuration ***/ - GLX_FUNCTION( glXGetScreenDriver ), - GLX_FUNCTION( glXGetDriverConfig ), + GLX_FUNCTION(glXGetScreenDriver), + GLX_FUNCTION(glXGetDriverConfig), #endif - { NULL, NULL } /* end of list */ + {NULL, NULL} /* end of list */ }; @@ -2913,7 +2992,7 @@ get_glx_proc_address(const char *funcName) /* try static functions */ for (i = 0; GLX_functions[i].Name; i++) { if (strcmp(GLX_functions[i].Name, funcName) == 0) - return GLX_functions[i].Address; + return GLX_functions[i].Address; } return NULL; @@ -2929,9 +3008,9 @@ get_glx_proc_address(const char *funcName) * * \sa glXGetProcAddress */ -PUBLIC void (*glXGetProcAddressARB(const GLubyte *procName))( void ) +PUBLIC void (*glXGetProcAddressARB(const GLubyte * procName)) (void) { - typedef void (*gl_function)( void ); + typedef void (*gl_function) (void); gl_function f; @@ -2943,8 +3022,8 @@ PUBLIC void (*glXGetProcAddressARB(const GLubyte *procName))( void ) */ f = (gl_function) get_glx_proc_address((const char *) procName); - if ( (f == NULL) && (procName[0] == 'g') && (procName[1] == 'l') - && (procName[2] != 'X') ) { + if ((f == NULL) && (procName[0] == 'g') && (procName[1] == 'l') + && (procName[2] != 'X')) { f = (gl_function) _glapi_get_proc_address((const char *) procName); } @@ -2960,9 +3039,9 @@ PUBLIC void (*glXGetProcAddressARB(const GLubyte *procName))( void ) * * \sa glXGetProcAddressARB */ -PUBLIC void (*glXGetProcAddress(const GLubyte *procName))( void ) +PUBLIC void (*glXGetProcAddress(const GLubyte * procName)) (void) #if defined(__GNUC__) && !defined(GLX_ALIAS_UNSUPPORTED) - __attribute__ ((alias ("glXGetProcAddressARB"))); + __attribute__ ((alias("glXGetProcAddressARB"))); #else { return glXGetProcAddressARB(procName); @@ -2980,24 +3059,26 @@ PUBLIC void (*glXGetProcAddress(const GLubyte *procName))( void ) * * \param ust Location to store the 64-bit UST * \returns Zero on success or a negative errno value on failure. - * + * * \sa glXGetProcAddress, PFNGLXGETUSTPROC * * \since Internal API version 20030317. */ -_X_HIDDEN int __glXGetUST( int64_t * ust ) -{ - struct timeval tv; - - if ( ust == NULL ) { - return -EFAULT; - } - - if ( gettimeofday( & tv, NULL ) == 0 ) { - ust[0] = (tv.tv_sec * 1000000) + tv.tv_usec; - return 0; - } else { - return -errno; - } +_X_HIDDEN int +__glXGetUST(int64_t * ust) +{ + struct timeval tv; + + if (ust == NULL) { + return -EFAULT; + } + + if (gettimeofday(&tv, NULL) == 0) { + ust[0] = (tv.tv_sec * 1000000) + tv.tv_usec; + return 0; + } + else { + return -errno; + } } #endif /* GLX_DIRECT_RENDERING */ diff --git a/src/glx/x11/glxcurrent.c b/src/glx/x11/glxcurrent.c index ce037e0ef4..f1e3e161be 100644 --- a/src/glx/x11/glxcurrent.c +++ b/src/glx/x11/glxcurrent.c @@ -81,7 +81,7 @@ _X_HIDDEN pthread_mutex_t __glXmutex = PTHREAD_MUTEX_INITIALIZER; /** * Per-thread GLX context pointer. - * + * * \c __glXSetCurrentContext is written is such a way that this pointer can * \b never be \c NULL. This is important! Because of this * \c __glXGetCurrentContext can be implemented as trivial macro. @@ -101,7 +101,7 @@ static pthread_once_t once_control = PTHREAD_ONCE_INIT; /** * Per-thread data key. - * + * * Once \c init_thread_data has been called, the per-thread data key will * take a value of \c NULL. As each new thread is created the default * value, in that thread, will be \c NULL. @@ -110,7 +110,7 @@ static pthread_key_t ContextTSD; /** * Initialize the per-thread data key. - * + * * This function is called \b exactly once per-process (not per-thread!) to * initialize the per-thread data key. This is ideally done using the * \c pthread_once mechanism. @@ -302,8 +302,8 @@ FetchDRIDrawable(Display * dpy, GLXDrawable glxDrawable, GLXContext gc) #endif /* GLX_DIRECT_RENDERING */ static void -__glXGenerateError(Display *dpy, GLXContext gc, XID resource, - BYTE errorCode, CARD16 minorCode) +__glXGenerateError(Display * dpy, GLXContext gc, XID resource, + BYTE errorCode, CARD16 minorCode) { xError error; @@ -318,7 +318,7 @@ __glXGenerateError(Display *dpy, GLXContext gc, XID resource, /** * Make a particular context current. - * + * * \note This is in this file so that it can access dummyContext. */ static Bool @@ -347,21 +347,19 @@ MakeContextCurrent(Display * dpy, GLXDrawable draw, if (gc == NULL && (draw != None || read != None)) { __glXGenerateError(dpy, gc, (draw != None) ? draw : read, - BadMatch, X_GLXMakeContextCurrent); + BadMatch, X_GLXMakeContextCurrent); return False; } if (gc != NULL && (draw == None || read == None)) { - __glXGenerateError(dpy, gc, None, - BadMatch, X_GLXMakeContextCurrent); + __glXGenerateError(dpy, gc, None, BadMatch, X_GLXMakeContextCurrent); return False; } _glapi_check_multithread(); - if (gc != NULL && gc->thread_id != 0 && - gc->thread_id != _glthread_GetID()) { + if (gc != NULL && gc->thread_id != 0 && gc->thread_id != _glthread_GetID()) { __glXGenerateError(dpy, gc, gc->xid, - BadAccess, X_GLXMakeContextCurrent); + BadAccess, X_GLXMakeContextCurrent); return False; } @@ -373,7 +371,7 @@ MakeContextCurrent(Display * dpy, GLXDrawable draw, if ((pdraw == NULL) || (pread == NULL)) { __glXGenerateError(dpy, gc, (pdraw == NULL) ? draw : read, - GLXBadDrawable, X_GLXMakeContextCurrent); + GLXBadDrawable, X_GLXMakeContextCurrent); return False; } @@ -521,6 +519,5 @@ GLX_ALIAS(Bool, glXMakeCurrentReadSGI, PUBLIC GLX_ALIAS(Bool, glXMakeContextCurrent, - (Display * dpy, GLXDrawable d, GLXDrawable r, - GLXContext ctx), (dpy, d, r, ctx), - MakeContextCurrent) + (Display * dpy, GLXDrawable d, GLXDrawable r, + GLXContext ctx), (dpy, d, r, ctx), MakeContextCurrent) diff --git a/src/glx/x11/glxext.c b/src/glx/x11/glxext.c index c6ab4b5890..e5553cbf76 100644 --- a/src/glx/x11/glxext.c +++ b/src/glx/x11/glxext.c @@ -102,19 +102,19 @@ static XEXT_GENERATE_ERROR_STRING(__glXErrorString, __glXExtensionName, __GLX_NUMBER_ERRORS, error_list) - static /* const */ XExtensionHooks __glXExtensionHooks = { - NULL, /* create_gc */ - NULL, /* copy_gc */ - NULL, /* flush_gc */ - NULL, /* free_gc */ - NULL, /* create_font */ - NULL, /* free_font */ - __glXCloseDisplay, /* close_display */ - NULL, /* wire_to_event */ - NULL, /* event_to_wire */ - NULL, /* error */ - __glXErrorString, /* error_string */ - }; +static /* const */ XExtensionHooks __glXExtensionHooks = { + NULL, /* create_gc */ + NULL, /* copy_gc */ + NULL, /* flush_gc */ + NULL, /* free_gc */ + NULL, /* create_font */ + NULL, /* free_font */ + __glXCloseDisplay, /* close_display */ + NULL, /* wire_to_event */ + NULL, /* event_to_wire */ + NULL, /* error */ + __glXErrorString, /* error_string */ +}; static XEXT_GENERATE_FIND_DISPLAY(__glXFindDisplay, __glXExtensionInfo, @@ -150,8 +150,8 @@ FreeScreenConfigs(__GLXdisplayPrivate * priv) #ifdef GLX_DIRECT_RENDERING if (psc->driver_configs) { - for(unsigned int i = 0; psc->driver_configs[i]; i++) - free((__DRIconfig*)psc->driver_configs[i]); + for (unsigned int i = 0; psc->driver_configs[i]; i++) + free((__DRIconfig *) psc->driver_configs[i]); free(psc->driver_configs); psc->driver_configs = NULL; } @@ -217,15 +217,14 @@ QueryVersion(Display * dpy, int opcode, int *major, int *minor) { #ifdef USE_XCB xcb_connection_t *c = XGetXCBConnection(dpy); - xcb_glx_query_version_reply_t* reply = - xcb_glx_query_version_reply(c, - xcb_glx_query_version(c, - GLX_MAJOR_VERSION, - GLX_MINOR_VERSION), - NULL); - - if(reply->major_version != GLX_MAJOR_VERSION) - { + xcb_glx_query_version_reply_t *reply = xcb_glx_query_version_reply(c, + xcb_glx_query_version + (c, + GLX_MAJOR_VERSION, + GLX_MINOR_VERSION), + NULL); + + if (reply->major_version != GLX_MAJOR_VERSION) { free(reply); return GL_FALSE; } @@ -543,7 +542,8 @@ getFBConfigs(Display * dpy, __GLXdisplayPrivate * priv, int screen) __GLXscreenConfigs *psc; psc = priv->screenConfigs + screen; - psc->serverGLXexts = __glXQueryServerString(dpy, priv->majorOpcode, screen, GLX_EXTENSIONS); + psc->serverGLXexts = + __glXQueryServerString(dpy, priv->majorOpcode, screen, GLX_EXTENSIONS); LockDisplay(dpy); @@ -601,7 +601,8 @@ AllocAndFetchScreenConfigs(Display * dpy, __GLXdisplayPrivate * priv) memset(psc, 0, screens * sizeof(__GLXscreenConfigs)); priv->screenConfigs = psc; - priv->serverGLXversion = __glXQueryServerString(dpy, priv->majorOpcode, 0, GLX_VERSION); + priv->serverGLXversion = + __glXQueryServerString(dpy, priv->majorOpcode, 0, GLX_VERSION); if (priv->serverGLXversion == NULL) { FreeScreenConfigs(priv); return GL_FALSE; @@ -786,10 +787,10 @@ __glXSetupForCommand(Display * dpy) /** * Flush the drawing command transport buffer. - * + * * \param ctx Context whose transport buffer is to be flushed. * \param pc Pointer to first unused buffer location. - * + * * \todo * Modify this function to use \c ctx->pc instead of the explicit * \c pc parameter. @@ -881,11 +882,11 @@ __glXSendLargeChunk(__GLXcontext * gc, GLint requestNumber, /** * Send a command that is too large for the GLXRender protocol request. - * + * * Send a large command, one that is too large for some reason to * send using the GLXRender protocol request. One reason to send * a large command is to avoid copying the data. - * + * * \param ctx GLX context * \param header Header data. * \param headerLen Size, in bytes, of the header data. It is assumed that diff --git a/src/glx/x11/glxextensions.c b/src/glx/x11/glxextensions.c index 051433a006..473f46d1e5 100644 --- a/src/glx/x11/glxextensions.c +++ b/src/glx/x11/glxextensions.c @@ -315,10 +315,10 @@ set_glx_extension(const struct extension_info *ext, /** * Convert the server's extension string to a bit-field. - * + * * \param server_string GLX extension string from the server. * \param server_support Bit-field of supported extensions. - * + * * \note * This function is used to process both GLX and GL extension strings. The * bit-fields used to track each of these have different sizes. Therefore, @@ -336,8 +336,7 @@ __glXProcessServerString(const struct extension_info *ext, /* Determine the length of the next extension name. */ for (len = 0; (server_string[base + len] != SEPARATOR) - && (server_string[base + len] != NUL); - len++) { + && (server_string[base + len] != NUL); len++) { /* empty */ } @@ -351,8 +350,7 @@ __glXProcessServerString(const struct extension_info *ext, * over the previous string and any trialing white-space. */ for (base += len; (server_string[base] == SEPARATOR) - && (server_string[base] != NUL); - base++) { + && (server_string[base] != NUL); base++) { /* empty */ } } @@ -549,7 +547,7 @@ __glXGetClientExtensions(void) /** * Calculate the list of application usable extensions. The resulting * string is stored in \c psc->effectiveGLXexts. - * + * * \param psc Pointer to GLX per-screen record. * \param display_is_direct_capable True if the display is capable of * direct rendering. @@ -600,7 +598,7 @@ __glXCalculateUsableExtensions(__GLXscreenConfigs * psc, * it and the "server" supports it. In this case that means that either * the true server supports it or it is only for direct-rendering and * the direct rendering driver supports it. - * + * * If the display is not capable of direct rendering, then the extension * is enabled if and only if the client-side library and the server * support it. @@ -609,10 +607,10 @@ __glXCalculateUsableExtensions(__GLXscreenConfigs * psc, if (display_is_direct_capable) { for (i = 0; i < 8; i++) { usable[i] = (client_glx_support[i] & client_glx_only[i]) - | (client_glx_support[i] & psc-> - direct_support[i] & server_support[i]) - | (client_glx_support[i] & psc-> - direct_support[i] & direct_glx_only[i]); + | (client_glx_support[i] & psc->direct_support[i] & + server_support[i]) + | (client_glx_support[i] & psc->direct_support[i] & + direct_glx_only[i]); } } else { @@ -630,7 +628,7 @@ __glXCalculateUsableExtensions(__GLXscreenConfigs * psc, /** * Calculate the list of application usable extensions. The resulting * string is stored in \c gc->extensions. - * + * * \param gc Pointer to GLX context. * \param server_string Extension string from the server. * \param major_version GL major version from the server. diff --git a/src/glx/x11/indirect_size.c b/src/glx/x11/indirect_size.c index 54c039dd6c..cdaf02ffe6 100644 --- a/src/glx/x11/indirect_size.c +++ b/src/glx/x11/indirect_size.c @@ -192,6 +192,10 @@ __glTexParameterfv_size(GLenum e) case GL_TEXTURE_MAX_ANISOTROPY_EXT: case GL_TEXTURE_LOD_BIAS: /* case GL_TEXTURE_LOD_BIAS_EXT:*/ + case GL_TEXTURE_STORAGE_HINT_APPLE: + case GL_STORAGE_PRIVATE_APPLE: + case GL_STORAGE_CACHED_APPLE: + case GL_STORAGE_SHARED_APPLE: case GL_DEPTH_TEXTURE_MODE: /* case GL_DEPTH_TEXTURE_MODE_ARB:*/ case GL_TEXTURE_COMPARE_MODE: diff --git a/src/glx/x11/indirect_vertex_array.c b/src/glx/x11/indirect_vertex_array.c index bb5232f618..ad9882528f 100644 --- a/src/glx/x11/indirect_vertex_array.c +++ b/src/glx/x11/indirect_vertex_array.c @@ -1,18 +1,18 @@ /* * (C) Copyright IBM Corporation 2004, 2005 * 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 @@ -39,7 +39,7 @@ /** * \file indirect_vertex_array.c * Implement GLX protocol for vertex arrays and vertex buffer objects. - * + * * The most important function in this fill is \c fill_array_info_cache. * The \c array_state_vector contains a cache of the ARRAY_INFO data sent * in the DrawArrays protocol. Certain operations, such as enabling or @@ -47,7 +47,7 @@ * fills-in this data. Additionally, it examines the enabled state and * other factors to determine what "version" of DrawArrays protocoal can be * used. - * + * * Current, only two versions of DrawArrays protocol are implemented. The * first version is the "none" protocol. This is the fallback when the * server does not support GL 1.1 / EXT_vertex_arrays. It is implemented @@ -90,11 +90,11 @@ static GLboolean validate_type(__GLXcontext * gc, GLenum type); /** - * Table of sizes, in bytes, of a GL types. All of the type enums are be in + * Table of sizes, in bytes, of a GL types. All of the type enums are be in * the range 0x1400 - 0x140F. That includes types added by extensions (i.e., * \c GL_HALF_FLOAT_NV). This elements of this table correspond to the * type enums masked with 0x0f. - * + * * \notes * \c GL_HALF_FLOAT_NV is not included. Neither are \c GL_2_BYTES, * \c GL_3_BYTES, or \c GL_4_BYTES. @@ -131,15 +131,15 @@ __glXFreeVertexArrayState(__GLXcontext * gc) /** * Initialize vertex array state of a GLX context. - * + * * \param gc GLX context whose vertex array state is to be initialized. - * + * * \warning * This function may only be called after __GLXcontext::gl_extension_bits, * __GLXcontext::server_minor, and __GLXcontext::server_major have been * initialized. These values are used to determine what vertex arrays are * supported. - * + * * \bug * Return values from malloc are not properly tested. */ @@ -171,7 +171,7 @@ __glXInitVertexArrayState(__GLXcontext * gc) * are supported by the server are create. For example, if the server * supports only 2 texture units, then only 2 texture coordinate arrays * are created. - * + * * At the very least, GL_VERTEX_ARRAY, GL_NORMAL_ARRAY, * GL_COLOR_ARRAY, GL_INDEX_ARRAY, GL_TEXTURE_COORD_ARRAY, and * GL_EDGE_FLAG_ARRAY are supported. @@ -532,7 +532,7 @@ emit_DrawArrays_none(GLenum mode, GLint first, GLsizei count) /** * Emit the header data for the GL 1.1 / EXT_vertex_arrays DrawArrays * protocol. - * + * * \param gc GLX context. * \param arrays Array state. * \param elements_per_request Location to store the number of elements that @@ -543,7 +543,7 @@ emit_DrawArrays_none(GLenum mode, GLint first, GLsizei count) * will be zero. * \param mode Drawing mode. * \param count Number of vertices. - * + * * \returns * A pointer to the buffer for array data. */ @@ -594,7 +594,7 @@ emit_DrawArrays_header_old(__GLXcontext * gc, /* Calculate the number of data packets that will be required to send * the whole command. To do this, the number of verticies that * will fit in a single buffer must be calculated. - * + * * The important value here is elements_per_request. This is the * number of complete array elements that will fit in a single * buffer. There may be some wasted space at the end of the buffer, @@ -869,7 +869,7 @@ emit_DrawElements_old(GLenum mode, GLsizei count, GLenum type, /** * Validate that the \c mode parameter to \c glDrawArrays, et. al. is valid. * If it is not valid, then an error code is set in the GLX context. - * + * * \returns * \c GL_TRUE if the argument is valid, \c GL_FALSE if is not. */ @@ -902,7 +902,7 @@ validate_mode(__GLXcontext * gc, GLenum mode) * A value less than zero is invalid and will result in \c GL_INVALID_VALUE * being set. A value of zero will not result in an error being set, but * will result in \c GL_FALSE being returned. - * + * * \returns * \c GL_TRUE if the argument is valid, \c GL_FALSE if it is not. */ @@ -1084,21 +1084,21 @@ __indirect_glMultiDrawElementsEXT(GLenum mode, const GLsizei * count, #define COMMON_ARRAY_DATA_INIT(a, PTR, TYPE, STRIDE, COUNT, NORMALIZED, HDR_SIZE, OPCODE) \ - do { \ - (a)->data = PTR; \ - (a)->data_type = TYPE; \ - (a)->user_stride = STRIDE; \ - (a)->count = COUNT; \ - (a)->normalized = NORMALIZED; \ - \ - (a)->element_size = __glXTypeSize( TYPE ) * COUNT; \ - (a)->true_stride = (STRIDE == 0) \ - ? (a)->element_size : STRIDE; \ - \ - (a)->header_size = HDR_SIZE; \ - ((uint16_t *) (a)->header)[0] = __GLX_PAD((a)->header_size + (a)->element_size); \ - ((uint16_t *) (a)->header)[1] = OPCODE; \ - } while(0) + do { \ + (a)->data = PTR; \ + (a)->data_type = TYPE; \ + (a)->user_stride = STRIDE; \ + (a)->count = COUNT; \ + (a)->normalized = NORMALIZED; \ + \ + (a)->element_size = __glXTypeSize( TYPE ) * COUNT; \ + (a)->true_stride = (STRIDE == 0) \ + ? (a)->element_size : STRIDE; \ + \ + (a)->header_size = HDR_SIZE; \ + ((uint16_t *) (a)->header)[0] = __GLX_PAD((a)->header_size + (a)->element_size); \ + ((uint16_t *) (a)->header)[1] = OPCODE; \ + } while(0) void @@ -1363,36 +1363,36 @@ __indirect_glTexCoordPointer(GLint size, GLenum type, GLsizei stride, { static const uint16_t short_ops[5] = { 0, X_GLrop_TexCoord1sv, X_GLrop_TexCoord2sv, X_GLrop_TexCoord3sv, - X_GLrop_TexCoord4sv + X_GLrop_TexCoord4sv }; static const uint16_t int_ops[5] = { 0, X_GLrop_TexCoord1iv, X_GLrop_TexCoord2iv, X_GLrop_TexCoord3iv, - X_GLrop_TexCoord4iv + X_GLrop_TexCoord4iv }; static const uint16_t float_ops[5] = { 0, X_GLrop_TexCoord1dv, X_GLrop_TexCoord2fv, X_GLrop_TexCoord3fv, - X_GLrop_TexCoord4fv + X_GLrop_TexCoord4fv }; static const uint16_t double_ops[5] = { 0, X_GLrop_TexCoord1dv, X_GLrop_TexCoord2dv, X_GLrop_TexCoord3dv, - X_GLrop_TexCoord4dv + X_GLrop_TexCoord4dv }; static const uint16_t mshort_ops[5] = { 0, X_GLrop_MultiTexCoord1svARB, X_GLrop_MultiTexCoord2svARB, - X_GLrop_MultiTexCoord3svARB, X_GLrop_MultiTexCoord4svARB + X_GLrop_MultiTexCoord3svARB, X_GLrop_MultiTexCoord4svARB }; static const uint16_t mint_ops[5] = { 0, X_GLrop_MultiTexCoord1ivARB, X_GLrop_MultiTexCoord2ivARB, - X_GLrop_MultiTexCoord3ivARB, X_GLrop_MultiTexCoord4ivARB + X_GLrop_MultiTexCoord3ivARB, X_GLrop_MultiTexCoord4ivARB }; static const uint16_t mfloat_ops[5] = { 0, X_GLrop_MultiTexCoord1dvARB, X_GLrop_MultiTexCoord2fvARB, - X_GLrop_MultiTexCoord3fvARB, X_GLrop_MultiTexCoord4fvARB + X_GLrop_MultiTexCoord3fvARB, X_GLrop_MultiTexCoord4fvARB }; static const uint16_t mdouble_ops[5] = { 0, X_GLrop_MultiTexCoord1dvARB, X_GLrop_MultiTexCoord2dvARB, - X_GLrop_MultiTexCoord3dvARB, X_GLrop_MultiTexCoord4dvARB + X_GLrop_MultiTexCoord3dvARB, X_GLrop_MultiTexCoord4dvARB }; uint16_t opcode; diff --git a/src/glx/x11/single2.c b/src/glx/x11/single2.c index 0b2d5113cc..d128ba2053 100644 --- a/src/glx/x11/single2.c +++ b/src/glx/x11/single2.c @@ -147,7 +147,7 @@ __indirect_glGetError(void) /** * Get the selected attribute from the client state. - * + * * \returns * On success \c GL_TRUE is returned. Otherwise, \c GL_FALSE is returned. */ @@ -679,7 +679,8 @@ __indirect_glGetString(GLenum name) */ (void) __glXFlushRenderBuffer(gc, gc->pc); - s = (GLubyte *) __glXGetString(dpy, gc->majorOpcode, gc->currentContextTag, name); + s = (GLubyte *) __glXGetString(dpy, gc->majorOpcode, gc->currentContextTag, + name); if (!s) { /* Throw data on the floor */ __glXSetError(gc, GL_OUT_OF_MEMORY); @@ -753,7 +754,7 @@ __indirect_glGetString(GLenum name) * hardware accelerated. For example, a TNT will show core * version 1.5, but most of the post-1.2 functionality is a * software fallback. - * + * * I don't want to break applications that rely on this odd * behavior. At the same time, the code is written and tested, * so I didn't want to throw it away. Therefore, the code is here @@ -766,7 +767,7 @@ __indirect_glGetString(GLenum name) * gc->server_minor are set. This version may be higher than we * can completely support, but it may imply support for some * extensions that we can support. - * + * * For example, at the time of this writing, the client-side * library only supports upto core GL version 1.2. However, cubic * textures, multitexture, multisampling, and some other 1.3 @@ -880,50 +881,50 @@ GLboolean __indirect_glAreTexturesResident(GLsizei n, const GLuint * textures, GLboolean * residences) { - __GLXcontext *const gc = __glXGetCurrentContext(); - Display *const dpy = gc->currentDpy; - GLboolean retval = (GLboolean) 0; - const GLuint cmdlen = 4 + __GLX_PAD((n * 4)); - if (__builtin_expect((n >= 0) && (dpy != NULL), 1)) { + __GLXcontext *const gc = __glXGetCurrentContext(); + Display *const dpy = gc->currentDpy; + GLboolean retval = (GLboolean) 0; + const GLuint cmdlen = 4 + __GLX_PAD((n * 4)); + if (__builtin_expect((n >= 0) && (dpy != NULL), 1)) { #ifdef USE_XCB - xcb_connection_t *c = XGetXCBConnection(dpy); - (void) __glXFlushRenderBuffer(gc, gc->pc); - xcb_glx_are_textures_resident_reply_t *reply = - xcb_glx_are_textures_resident_reply(c, - xcb_glx_are_textures_resident - (c, gc->currentContextTag, n, - textures), NULL); - (void) memcpy(residences, xcb_glx_are_textures_resident_data(reply), - xcb_glx_are_textures_resident_data_length(reply) * - sizeof(GLboolean)); - retval = reply->ret_val; - free(reply); + xcb_connection_t *c = XGetXCBConnection(dpy); + (void) __glXFlushRenderBuffer(gc, gc->pc); + xcb_glx_are_textures_resident_reply_t *reply = + xcb_glx_are_textures_resident_reply(c, + xcb_glx_are_textures_resident + (c, gc->currentContextTag, n, + textures), NULL); + (void) memcpy(residences, xcb_glx_are_textures_resident_data(reply), + xcb_glx_are_textures_resident_data_length(reply) * + sizeof(GLboolean)); + retval = reply->ret_val; + free(reply); #else - GLubyte const *pc = - __glXSetupSingleRequest(gc, X_GLsop_AreTexturesResident, cmdlen); - (void) memcpy((void *) (pc + 0), (void *) (&n), 4); - (void) memcpy((void *) (pc + 4), (void *) (textures), (n * 4)); - if (n & 3) { - /* n is not a multiple of four. - * When reply_is_always_array is TRUE, __glXReadReply() will - * put a multiple of four bytes into the dest buffer. If the - * caller's buffer is not a multiple of four in size, we'll write - * out of bounds. So use a temporary buffer that's a few bytes - * larger. - */ - GLboolean *res4 = malloc((n + 3) & ~3); - retval = (GLboolean) __glXReadReply(dpy, 1, res4, GL_TRUE); - memcpy(residences, res4, n); - free(res4); - } - else { - retval = (GLboolean) __glXReadReply(dpy, 1, residences, GL_TRUE); - } - UnlockDisplay(dpy); - SyncHandle(); + GLubyte const *pc = + __glXSetupSingleRequest(gc, X_GLsop_AreTexturesResident, cmdlen); + (void) memcpy((void *) (pc + 0), (void *) (&n), 4); + (void) memcpy((void *) (pc + 4), (void *) (textures), (n * 4)); + if (n & 3) { + /* n is not a multiple of four. + * When reply_is_always_array is TRUE, __glXReadReply() will + * put a multiple of four bytes into the dest buffer. If the + * caller's buffer is not a multiple of four in size, we'll write + * out of bounds. So use a temporary buffer that's a few bytes + * larger. + */ + GLboolean *res4 = malloc((n + 3) & ~3); + retval = (GLboolean) __glXReadReply(dpy, 1, res4, GL_TRUE); + memcpy(residences, res4, n); + free(res4); + } + else { + retval = (GLboolean) __glXReadReply(dpy, 1, residences, GL_TRUE); + } + UnlockDisplay(dpy); + SyncHandle(); #endif /* USE_XCB */ - } - return retval; + } + return retval; } @@ -936,36 +937,37 @@ GLboolean glAreTexturesResidentEXT(GLsizei n, const GLuint * textures, GLboolean * residences) { - __GLXcontext *const gc = __glXGetCurrentContext(); - - if (gc->isDirect) { - return CALL_AreTexturesResident(GET_DISPATCH(), - (n, textures, residences)); - } else { - __GLXcontext *const gc = __glXGetCurrentContext(); - Display *const dpy = gc->currentDpy; - GLboolean retval = (GLboolean) 0; - const GLuint cmdlen = 4 + __GLX_PAD((n * 4)); - if (__builtin_expect((n >= 0) && (dpy != NULL), 1)) { - GLubyte const *pc = - __glXSetupVendorRequest(gc, X_GLXVendorPrivateWithReply, - X_GLvop_AreTexturesResidentEXT, - cmdlen); - (void) memcpy((void *) (pc + 0), (void *) (&n), 4); - (void) memcpy((void *) (pc + 4), (void *) (textures), (n * 4)); - if (n & 3) { - /* see comments in __indirect_glAreTexturesResident() */ - GLboolean *res4 = malloc((n + 3) & ~3); - retval = (GLboolean) __glXReadReply(dpy, 1, res4, GL_TRUE); - memcpy(residences, res4, n); - free(res4); - } - else { - retval = (GLboolean) __glXReadReply(dpy, 1, residences, GL_TRUE); - } - UnlockDisplay(dpy); - SyncHandle(); - } - return retval; - } + __GLXcontext *const gc = __glXGetCurrentContext(); + + if (gc->isDirect) { + return CALL_AreTexturesResident(GET_DISPATCH(), + (n, textures, residences)); + } + else { + __GLXcontext *const gc = __glXGetCurrentContext(); + Display *const dpy = gc->currentDpy; + GLboolean retval = (GLboolean) 0; + const GLuint cmdlen = 4 + __GLX_PAD((n * 4)); + if (__builtin_expect((n >= 0) && (dpy != NULL), 1)) { + GLubyte const *pc = + __glXSetupVendorRequest(gc, X_GLXVendorPrivateWithReply, + X_GLvop_AreTexturesResidentEXT, + cmdlen); + (void) memcpy((void *) (pc + 0), (void *) (&n), 4); + (void) memcpy((void *) (pc + 4), (void *) (textures), (n * 4)); + if (n & 3) { + /* see comments in __indirect_glAreTexturesResident() */ + GLboolean *res4 = malloc((n + 3) & ~3); + retval = (GLboolean) __glXReadReply(dpy, 1, res4, GL_TRUE); + memcpy(residences, res4, n); + free(res4); + } + else { + retval = (GLboolean) __glXReadReply(dpy, 1, residences, GL_TRUE); + } + UnlockDisplay(dpy); + SyncHandle(); + } + return retval; + } } diff --git a/src/mesa/drivers/common/meta.c b/src/mesa/drivers/common/meta.c new file mode 100644 index 0000000000..e42beabc9b --- /dev/null +++ b/src/mesa/drivers/common/meta.c @@ -0,0 +1,1249 @@ +/* + * Mesa 3-D graphics library + * Version: 7.6 + * + * Copyright (C) 2009 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, 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 + * BRIAN PAUL 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. + */ + +/** + * Meta operations. Some GL operations can be expressed in terms of + * other GL operations. For example, glBlitFramebuffer() can be done + * with texture mapping and glClear() can be done with polygon rendering. + * + * \author Brian Paul + */ + + +#include "main/glheader.h" +#include "main/mtypes.h" +#include "main/imports.h" +#include "main/arrayobj.h" +#include "main/blend.h" +#include "main/bufferobj.h" +#include "main/depth.h" +#include "main/enable.h" +#include "main/image.h" +#include "main/macros.h" +#include "main/matrix.h" +#include "main/polygon.h" +#include "main/scissor.h" +#include "main/shaders.h" +#include "main/stencil.h" +#include "main/texobj.h" +#include "main/texenv.h" +#include "main/teximage.h" +#include "main/texparam.h" +#include "main/texstate.h" +#include "main/varray.h" +#include "main/viewport.h" +#include "shader/program.h" +#include "swrast/swrast.h" +#include "drivers/common/meta.h" + + +/** + * State which we may save/restore across meta ops. + * XXX this may be incomplete... + */ +struct save_state +{ + GLbitfield SavedState; /**< bitmask of META_* flags */ + + /** META_ALPHA_TEST */ + GLboolean AlphaEnabled; + + /** META_BLEND */ + GLboolean BlendEnabled; + GLboolean ColorLogicOpEnabled; + + /** META_COLOR_MASK */ + GLubyte ColorMask[4]; + + /** META_DEPTH_TEST */ + struct gl_depthbuffer_attrib Depth; + + /** META_FOG */ + GLboolean Fog; + + /** META_PIXELSTORE */ + /* XXX / TO-DO */ + + /** META_RASTERIZATION */ + GLenum FrontPolygonMode, BackPolygonMode; + GLboolean PolygonOffset; + GLboolean PolygonSmooth; + GLboolean PolygonStipple; + GLboolean PolygonCull; + + /** META_SCISSOR */ + struct gl_scissor_attrib Scissor; + + /** META_SHADER */ + GLboolean VertexProgramEnabled; + struct gl_vertex_program *VertexProgram; + GLboolean FragmentProgramEnabled; + struct gl_fragment_program *FragmentProgram; + GLuint Shader; + + /** META_STENCIL_TEST */ + struct gl_stencil_attrib Stencil; + + /** META_TRANSFORM */ + GLenum MatrixMode; + GLfloat ModelviewMatrix[16]; + GLfloat ProjectionMatrix[16]; + GLfloat TextureMatrix[16]; + GLbitfield ClipPlanesEnabled; + + /** META_TEXTURE */ + GLuint ActiveUnit; + GLuint ClientActiveUnit; + /** for unit[0] only */ + struct gl_texture_object *CurrentTexture[NUM_TEXTURE_TARGETS]; + /** mask of TEXTURE_2D_BIT, etc */ + GLbitfield TexEnabled[MAX_TEXTURE_UNITS]; + GLbitfield TexGenEnabled[MAX_TEXTURE_UNITS]; + GLuint EnvMode; /* unit[0] only */ + + /** META_VERTEX */ + struct gl_array_object *ArrayObj; + struct gl_buffer_object *ArrayBufferObj; + + /** META_VIEWPORT */ + GLint ViewportX, ViewportY, ViewportW, ViewportH; + GLclampd DepthNear, DepthFar; + + /** Miscellaneous (always disabled) */ + GLboolean Lighting; +}; + + +/** + * State for glBlitFramebufer() + */ +struct blit_state +{ + GLuint TexObj; + GLsizei TexWidth, TexHeight; + GLenum TexType; + GLuint ArrayObj; + GLuint VBO; + GLfloat verts[4][4]; /** four verts of X,Y,S,T */ +}; + + +/** + * State for glClear() + */ +struct clear_state +{ + GLuint ArrayObj; + GLuint VBO; + GLfloat verts[4][7]; /** four verts of X,Y,Z,R,G,B,A */ +}; + + +/** + * State for glCopyPixels() + */ +struct copypix_state +{ + GLuint TexObj; + GLsizei TexWidth, TexHeight; + GLenum TexType; + GLuint ArrayObj; + GLuint VBO; + GLfloat verts[4][5]; /** four verts of X,Y,Z,S,T */ +}; + + +/** + * State for glDrawPixels() + */ +struct drawpix_state +{ + GLuint TexObj; + GLsizei TexWidth, TexHeight; + GLenum TexIntFormat; + GLuint ArrayObj; + GLuint VBO; + GLfloat verts[4][5]; /** four verts of X,Y,Z,S,T */ +}; + + + +/** + * All per-context meta state. + */ +struct gl_meta_state +{ + struct save_state Save; /**< state saved during meta-ops */ + + struct blit_state Blit; /**< For _mesa_meta_blit_framebuffer() */ + struct clear_state Clear; /**< For _mesa_meta_clear() */ + struct copypix_state CopyPix; /**< For _mesa_meta_copy_pixels() */ + struct drawpix_state DrawPix; /**< For _mesa_meta_draw_pixels() */ + + /* other possible meta-ops: + * glDrawPixels() + * glBitmap() + * glGenerateMipmap() + */ +}; + + +/** + * Initialize meta-ops for a context. + * To be called once during context creation. + */ +void +_mesa_meta_init(GLcontext *ctx) +{ + ASSERT(!ctx->Meta); + + ctx->Meta = CALLOC_STRUCT(gl_meta_state); +} + + +/** + * Free context meta-op state. + * To be called once during context destruction. + */ +void +_mesa_meta_free(GLcontext *ctx) +{ + struct gl_meta_state *meta = ctx->Meta; + + if (meta->Blit.TexObj) { + _mesa_DeleteTextures(1, &meta->Blit.TexObj); + _mesa_DeleteBuffersARB(1, & meta->Blit.VBO); + _mesa_DeleteVertexArraysAPPLE(1, &meta->Blit.ArrayObj); + } + + if (meta->Clear.VBO) { + _mesa_DeleteBuffersARB(1, & meta->Clear.VBO); + _mesa_DeleteVertexArraysAPPLE(1, &meta->Clear.ArrayObj); + } + + if (meta->CopyPix.TexObj) { + _mesa_DeleteTextures(1, &meta->CopyPix.TexObj); + _mesa_DeleteBuffersARB(1, & meta->CopyPix.VBO); + _mesa_DeleteVertexArraysAPPLE(1, &meta->CopyPix.ArrayObj); + } + + if (meta->DrawPix.TexObj) { + _mesa_DeleteTextures(1, &meta->DrawPix.TexObj); + _mesa_DeleteBuffersARB(1, & meta->DrawPix.VBO); + _mesa_DeleteVertexArraysAPPLE(1, &meta->DrawPix.ArrayObj); + } + + _mesa_free(ctx->Meta); + ctx->Meta = NULL; +} + + +/** + * Enter meta state. This is like a light-weight version of glPushAttrib + * but it also resets most GL state back to default values. + * + * \param state bitmask of META_* flags indicating which attribute groups + * to save and reset to their defaults + */ +static void +_mesa_meta_begin(GLcontext *ctx, GLbitfield state) +{ + struct save_state *save = &ctx->Meta->Save; + + save->SavedState = state; + + if (state & META_ALPHA_TEST) { + save->AlphaEnabled = ctx->Color.AlphaEnabled; + if (ctx->Color.AlphaEnabled) + _mesa_Disable(GL_ALPHA_TEST); + } + + if (state & META_BLEND) { + save->BlendEnabled = ctx->Color.BlendEnabled; + if (ctx->Color.BlendEnabled) + _mesa_Disable(GL_BLEND); + save->ColorLogicOpEnabled = ctx->Color.ColorLogicOpEnabled; + if (ctx->Color.ColorLogicOpEnabled) + _mesa_Disable(GL_COLOR_LOGIC_OP); + } + + if (state & META_COLOR_MASK) { + COPY_4V(save->ColorMask, ctx->Color.ColorMask); + if (!ctx->Color.ColorMask[0] || + !ctx->Color.ColorMask[1] || + !ctx->Color.ColorMask[2] || + !ctx->Color.ColorMask[3]) + _mesa_ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + } + + if (state & META_DEPTH_TEST) { + save->Depth = ctx->Depth; /* struct copy */ + if (ctx->Depth.Test) + _mesa_Disable(GL_DEPTH_TEST); + } + + if (state & META_FOG) { + save->Fog = ctx->Fog.Enabled; + if (ctx->Fog.Enabled) + _mesa_set_enable(ctx, GL_FOG, GL_FALSE); + } + + if (state & META_RASTERIZATION) { + save->FrontPolygonMode = ctx->Polygon.FrontMode; + save->BackPolygonMode = ctx->Polygon.BackMode; + save->PolygonOffset = ctx->Polygon.OffsetFill; + save->PolygonSmooth = ctx->Polygon.SmoothFlag; + save->PolygonStipple = ctx->Polygon.StippleFlag; + save->PolygonCull = ctx->Polygon.CullFlag; + _mesa_PolygonMode(GL_FRONT_AND_BACK, GL_FILL); + _mesa_set_enable(ctx, GL_POLYGON_OFFSET_FILL, GL_FALSE); + _mesa_set_enable(ctx, GL_POLYGON_SMOOTH, GL_FALSE); + _mesa_set_enable(ctx, GL_POLYGON_STIPPLE, GL_FALSE); + _mesa_set_enable(ctx, GL_CULL_FACE, GL_FALSE); + } + + if (state & META_SCISSOR) { + save->Scissor = ctx->Scissor; /* struct copy */ + } + + if (state & META_SHADER) { + if (ctx->Extensions.ARB_vertex_program) { + save->VertexProgramEnabled = ctx->VertexProgram.Enabled; + save->VertexProgram = ctx->VertexProgram.Current; + _mesa_set_enable(ctx, GL_VERTEX_PROGRAM_ARB, GL_FALSE); + } + + if (ctx->Extensions.ARB_fragment_program) { + save->FragmentProgramEnabled = ctx->FragmentProgram.Enabled; + save->FragmentProgram = ctx->FragmentProgram.Current; + _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_FALSE); + } + + if (ctx->Extensions.ARB_shader_objects) { + save->Shader = ctx->Shader.CurrentProgram ? + ctx->Shader.CurrentProgram->Name : 0; + _mesa_UseProgramObjectARB(0); + } + } + + if (state & META_STENCIL_TEST) { + save->Stencil = ctx->Stencil; /* struct copy */ + if (ctx->Stencil.Enabled) + _mesa_Disable(GL_STENCIL_TEST); + /* NOTE: other stencil state not reset */ + } + + if (state & META_TEXTURE) { + GLuint u, tgt; + + save->ActiveUnit = ctx->Texture.CurrentUnit; + save->ClientActiveUnit = ctx->Array.ActiveTexture; + save->EnvMode = ctx->Texture.Unit[0].EnvMode; + + /* Disable all texture units */ + for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { + save->TexEnabled[u] = ctx->Texture.Unit[u].Enabled; + save->TexGenEnabled[u] = ctx->Texture.Unit[u].TexGenEnabled; + if (ctx->Texture.Unit[u].Enabled || + ctx->Texture.Unit[u].TexGenEnabled) { + _mesa_ActiveTextureARB(GL_TEXTURE0 + u); + _mesa_set_enable(ctx, GL_TEXTURE_1D, GL_FALSE); + _mesa_set_enable(ctx, GL_TEXTURE_2D, GL_FALSE); + _mesa_set_enable(ctx, GL_TEXTURE_3D, GL_FALSE); + _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE); + _mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE, GL_FALSE); + _mesa_set_enable(ctx, GL_TEXTURE_GEN_S, GL_FALSE); + _mesa_set_enable(ctx, GL_TEXTURE_GEN_T, GL_FALSE); + _mesa_set_enable(ctx, GL_TEXTURE_GEN_R, GL_FALSE); + _mesa_set_enable(ctx, GL_TEXTURE_GEN_Q, GL_FALSE); + } + } + + /* save current texture objects for unit[0] only */ + for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) { + _mesa_reference_texobj(&save->CurrentTexture[tgt], + ctx->Texture.Unit[0].CurrentTex[tgt]); + } + + /* set defaults for unit[0] */ + _mesa_ActiveTextureARB(GL_TEXTURE0); + _mesa_ClientActiveTextureARB(GL_TEXTURE0); + _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + } + + if (state & META_TRANSFORM) { + GLuint activeTexture = ctx->Texture.CurrentUnit; + _mesa_memcpy(save->ModelviewMatrix, ctx->ModelviewMatrixStack.Top->m, + 16 * sizeof(GLfloat)); + _mesa_memcpy(save->ProjectionMatrix, ctx->ProjectionMatrixStack.Top->m, + 16 * sizeof(GLfloat)); + _mesa_memcpy(save->TextureMatrix, ctx->TextureMatrixStack[0].Top->m, + 16 * sizeof(GLfloat)); + save->MatrixMode = ctx->Transform.MatrixMode; + /* set 1:1 vertex:pixel coordinate transform */ + _mesa_ActiveTextureARB(GL_TEXTURE0); + _mesa_MatrixMode(GL_TEXTURE); + _mesa_LoadIdentity(); + _mesa_ActiveTextureARB(GL_TEXTURE0 + activeTexture); + _mesa_MatrixMode(GL_MODELVIEW); + _mesa_LoadIdentity(); + _mesa_MatrixMode(GL_PROJECTION); + _mesa_LoadIdentity(); + _mesa_Ortho(0.0F, ctx->DrawBuffer->Width, + 0.0F, ctx->DrawBuffer->Height, + -1.0F, 1.0F); + save->ClipPlanesEnabled = ctx->Transform.ClipPlanesEnabled; + if (ctx->Transform.ClipPlanesEnabled) { + GLuint i; + for (i = 0; i < ctx->Const.MaxClipPlanes; i++) { + _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_FALSE); + } + } + } + + if (state & META_VERTEX) { + /* save vertex array object state */ + _mesa_reference_array_object(ctx, &save->ArrayObj, + ctx->Array.ArrayObj); + _mesa_reference_buffer_object(ctx, &save->ArrayBufferObj, + ctx->Array.ArrayBufferObj); + /* set some default state? */ + } + + if (state & META_VIEWPORT) { + save->ViewportX = ctx->Viewport.X; + save->ViewportY = ctx->Viewport.Y; + save->ViewportW = ctx->Viewport.Width; + save->ViewportH = ctx->Viewport.Height; + _mesa_Viewport(0, 0, ctx->DrawBuffer->Width, ctx->DrawBuffer->Height); + save->DepthNear = ctx->Viewport.Near; + save->DepthFar = ctx->Viewport.Far; + _mesa_DepthRange(0.0, 1.0); + } + + /* misc */ + { + save->Lighting = ctx->Light.Enabled; + if (ctx->Light.Enabled) + _mesa_set_enable(ctx, GL_LIGHTING, GL_FALSE); + } +} + + +/** + * Leave meta state. This is like a light-weight version of glPopAttrib(). + */ +static void +_mesa_meta_end(GLcontext *ctx) +{ + struct save_state *save = &ctx->Meta->Save; + const GLbitfield state = save->SavedState; + + if (state & META_ALPHA_TEST) { + if (ctx->Color.AlphaEnabled != save->AlphaEnabled) + _mesa_set_enable(ctx, GL_ALPHA_TEST, save->AlphaEnabled); + } + + if (state & META_BLEND) { + if (ctx->Color.BlendEnabled != save->BlendEnabled) + _mesa_set_enable(ctx, GL_BLEND, save->BlendEnabled); + if (ctx->Color.ColorLogicOpEnabled != save->ColorLogicOpEnabled) + _mesa_set_enable(ctx, GL_COLOR_LOGIC_OP, save->ColorLogicOpEnabled); + } + + if (state & META_COLOR_MASK) { + if (!TEST_EQ_4V(ctx->Color.ColorMask, save->ColorMask)) + _mesa_ColorMask(save->ColorMask[0], save->ColorMask[1], + save->ColorMask[2], save->ColorMask[3]); + } + + if (state & META_DEPTH_TEST) { + if (ctx->Depth.Test != save->Depth.Test) + _mesa_set_enable(ctx, GL_DEPTH_TEST, save->Depth.Test); + _mesa_DepthFunc(save->Depth.Func); + _mesa_DepthMask(save->Depth.Mask); + } + + if (state & META_FOG) { + _mesa_set_enable(ctx, GL_FOG, save->Fog); + } + + if (state & META_RASTERIZATION) { + _mesa_PolygonMode(GL_FRONT, save->FrontPolygonMode); + _mesa_PolygonMode(GL_BACK, save->BackPolygonMode); + _mesa_set_enable(ctx, GL_POLYGON_STIPPLE, save->PolygonStipple); + _mesa_set_enable(ctx, GL_POLYGON_OFFSET_FILL, save->PolygonOffset); + _mesa_set_enable(ctx, GL_POLYGON_SMOOTH, save->PolygonSmooth); + _mesa_set_enable(ctx, GL_CULL_FACE, save->PolygonCull); + } + + if (state & META_SCISSOR) { + _mesa_set_enable(ctx, GL_SCISSOR_TEST, save->Scissor.Enabled); + _mesa_Scissor(save->Scissor.X, save->Scissor.Y, + save->Scissor.Width, save->Scissor.Height); + } + + if (state & META_SHADER) { + if (ctx->Extensions.ARB_vertex_program) { + _mesa_set_enable(ctx, GL_VERTEX_PROGRAM_ARB, + save->VertexProgramEnabled); + _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, + save->VertexProgram); + } + + if (ctx->Extensions.ARB_fragment_program) { + _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, + save->FragmentProgramEnabled); + _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, + save->FragmentProgram); + } + + if (ctx->Extensions.ARB_shader_objects) { + _mesa_UseProgramObjectARB(save->Shader); + } + } + + if (state & META_STENCIL_TEST) { + const struct gl_stencil_attrib *stencil = &save->Stencil; + + _mesa_set_enable(ctx, GL_STENCIL_TEST, stencil->Enabled); + _mesa_ClearStencil(stencil->Clear); + if (ctx->Extensions.EXT_stencil_two_side) { + _mesa_set_enable(ctx, GL_STENCIL_TEST_TWO_SIDE_EXT, + stencil->TestTwoSide); + _mesa_ActiveStencilFaceEXT(stencil->ActiveFace + ? GL_BACK : GL_FRONT); + } + /* front state */ + _mesa_StencilFuncSeparate(GL_FRONT, + stencil->Function[0], + stencil->Ref[0], + stencil->ValueMask[0]); + _mesa_StencilMaskSeparate(GL_FRONT, stencil->WriteMask[0]); + _mesa_StencilOpSeparate(GL_FRONT, stencil->FailFunc[0], + stencil->ZFailFunc[0], + stencil->ZPassFunc[0]); + /* back state */ + _mesa_StencilFuncSeparate(GL_BACK, + stencil->Function[1], + stencil->Ref[1], + stencil->ValueMask[1]); + _mesa_StencilMaskSeparate(GL_BACK, stencil->WriteMask[1]); + _mesa_StencilOpSeparate(GL_BACK, stencil->FailFunc[1], + stencil->ZFailFunc[1], + stencil->ZPassFunc[1]); + } + + if (state & META_TEXTURE) { + GLuint u, tgt; + + ASSERT(ctx->Texture.CurrentUnit == 0); + + /* restore texenv for unit[0] */ + _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, save->EnvMode); + + /* restore texture objects for unit[0] only */ + for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) { + _mesa_reference_texobj(&ctx->Texture.Unit[0].CurrentTex[tgt], + save->CurrentTexture[tgt]); + } + + /* Re-enable textures, texgen */ + for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { + if (save->TexEnabled[u]) { + _mesa_ActiveTextureARB(GL_TEXTURE0 + u); + + if (save->TexEnabled[u] & TEXTURE_1D_BIT) + _mesa_set_enable(ctx, GL_TEXTURE_1D, GL_TRUE); + if (save->TexEnabled[u] & TEXTURE_2D_BIT) + _mesa_set_enable(ctx, GL_TEXTURE_2D, GL_TRUE); + if (save->TexEnabled[u] & TEXTURE_3D_BIT) + _mesa_set_enable(ctx, GL_TEXTURE_3D, GL_TRUE); + if (save->TexEnabled[u] & TEXTURE_CUBE_BIT) + _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP, GL_TRUE); + if (save->TexEnabled[u] & TEXTURE_RECT_BIT) + _mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE, GL_TRUE); + } + + if (save->TexGenEnabled[u]) { + _mesa_ActiveTextureARB(GL_TEXTURE0 + u); + + if (save->TexGenEnabled[u] & S_BIT) + _mesa_set_enable(ctx, GL_TEXTURE_GEN_S, GL_TRUE); + if (save->TexGenEnabled[u] & T_BIT) + _mesa_set_enable(ctx, GL_TEXTURE_GEN_T, GL_TRUE); + if (save->TexGenEnabled[u] & R_BIT) + _mesa_set_enable(ctx, GL_TEXTURE_GEN_R, GL_TRUE); + if (save->TexGenEnabled[u] & Q_BIT) + _mesa_set_enable(ctx, GL_TEXTURE_GEN_Q, GL_TRUE); + } + } + + /* restore current unit state */ + _mesa_ActiveTextureARB(GL_TEXTURE0 + save->ActiveUnit); + _mesa_ClientActiveTextureARB(GL_TEXTURE0 + save->ClientActiveUnit); + } + + if (state & META_TRANSFORM) { + GLuint activeTexture = ctx->Texture.CurrentUnit; + _mesa_ActiveTextureARB(GL_TEXTURE0); + _mesa_MatrixMode(GL_TEXTURE); + _mesa_LoadMatrixf(save->TextureMatrix); + _mesa_ActiveTextureARB(GL_TEXTURE0 + activeTexture); + + _mesa_MatrixMode(GL_MODELVIEW); + _mesa_LoadMatrixf(save->ModelviewMatrix); + + _mesa_MatrixMode(GL_PROJECTION); + _mesa_LoadMatrixf(save->ProjectionMatrix); + + _mesa_MatrixMode(save->MatrixMode); + + save->ClipPlanesEnabled = ctx->Transform.ClipPlanesEnabled; + if (save->ClipPlanesEnabled) { + GLuint i; + for (i = 0; i < ctx->Const.MaxClipPlanes; i++) { + if (save->ClipPlanesEnabled & (1 << i)) { + _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_TRUE); + } + } + } + } + + if (state & META_VERTEX) { + /* restore vertex buffer object */ + _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, save->ArrayBufferObj->Name); + _mesa_reference_buffer_object(ctx, &save->ArrayBufferObj, NULL); + + /* restore vertex array object */ + _mesa_BindVertexArray(save->ArrayObj->Name); + _mesa_reference_array_object(ctx, &save->ArrayObj, NULL); + } + + if (state & META_VIEWPORT) { + _mesa_Viewport(save->ViewportX, save->ViewportY, + save->ViewportW, save->ViewportH); + _mesa_DepthRange(save->DepthNear, save->DepthFar); + } + + /* misc */ + if (save->Lighting) { + _mesa_set_enable(ctx, GL_LIGHTING, GL_TRUE); + } + if (save->Fog) { + _mesa_set_enable(ctx, GL_FOG, GL_TRUE); + } +} + + +/** + * Meta implementation of ctx->Driver.BlitFramebuffer() in terms + * of texture mapping and polygon rendering. + * Note: this function requires GL_ARB_texture_rectangle support. + */ +void +_mesa_meta_blit_framebuffer(GLcontext *ctx, + GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, + GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, + GLbitfield mask, GLenum filter) +{ + struct blit_state *blit = &ctx->Meta->Blit; + const GLint srcX = MIN2(srcX0, srcX1); + const GLint srcY = MIN2(srcY0, srcY1); + const GLint srcW = abs(srcX1 - srcX0); + const GLint srcH = abs(srcY1 - srcY0); + GLboolean srcFlipX = srcX1 < srcX0; + GLboolean srcFlipY = srcY1 < srcY0; + + ASSERT(ctx->Extensions.NV_texture_rectangle); + + if (srcW > ctx->Const.MaxTextureRectSize || + srcH > ctx->Const.MaxTextureRectSize) { + /* XXX avoid this fallback */ + _swrast_BlitFramebuffer(ctx, srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, mask, filter); + return; + } + + + if (srcFlipX) { + GLint tmp = dstX0; + dstX0 = dstX1; + dstX1 = tmp; + } + + if (srcFlipY) { + GLint tmp = dstY0; + dstY0 = dstY1; + dstY1 = tmp; + } + + /* only scissor effects blit so save/clear all other relevant state */ + _mesa_meta_begin(ctx, ~META_SCISSOR); + + if (blit->TexObj == 0) { + /* one-time setup */ + + /* create texture object */ + _mesa_GenTextures(1, &blit->TexObj); + _mesa_BindTexture(GL_TEXTURE_RECTANGLE, blit->TexObj); + _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + } + else { + _mesa_BindTexture(GL_TEXTURE_RECTANGLE, blit->TexObj); + } + + _mesa_TexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, filter); + _mesa_TexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, filter); + + if (blit->ArrayObj == 0) { + /* one-time setup */ + + /* create vertex array object */ + _mesa_GenVertexArrays(1, &blit->ArrayObj); + _mesa_BindVertexArray(blit->ArrayObj); + + /* create vertex array buffer */ + _mesa_GenBuffersARB(1, &blit->VBO); + _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, blit->VBO); + _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(blit->verts), + blit->verts, GL_STREAM_DRAW_ARB); + + /* setup vertex arrays */ + _mesa_VertexPointer(2, GL_FLOAT, 4 * sizeof(GLfloat), + (void*) (0 * sizeof(GLfloat))); + _mesa_TexCoordPointer(2, GL_FLOAT, 4 * sizeof(GLfloat), + (void *) (2 * sizeof(GLfloat))); + _mesa_EnableClientState(GL_VERTEX_ARRAY); + _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY); + } + else { + _mesa_BindVertexArray(blit->ArrayObj); + _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, blit->VBO); + } + + /* vertex positions */ + blit->verts[0][0] = (GLfloat) dstX0; + blit->verts[0][1] = (GLfloat) dstY0; + blit->verts[1][0] = (GLfloat) dstX1; + blit->verts[1][1] = (GLfloat) dstY0; + blit->verts[2][0] = (GLfloat) dstX1; + blit->verts[2][1] = (GLfloat) dstY1; + blit->verts[3][0] = (GLfloat) dstX0; + blit->verts[3][1] = (GLfloat) dstY1; + + /* texcoords */ + blit->verts[0][2] = 0.0F; + blit->verts[0][3] = 0.0F; + blit->verts[1][2] = (GLfloat) srcW; + blit->verts[1][3] = 0.0F; + blit->verts[2][2] = (GLfloat) srcW; + blit->verts[2][3] = (GLfloat) srcH; + blit->verts[3][2] = 0.0F; + blit->verts[3][3] = (GLfloat) srcH; + + /* upload new vertex data */ + _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, + sizeof(blit->verts), blit->verts); + + /* copy framebuffer image to texture */ + if (mask & GL_COLOR_BUFFER_BIT) { + if (blit->TexWidth == srcW && + blit->TexHeight == srcH && + blit->TexType == GL_RGBA) { + /* replace existing tex image */ + _mesa_CopyTexSubImage2D(GL_TEXTURE_RECTANGLE, 0, + 0, 0, srcX, srcY, srcW, srcH); + } + else { + /* create new tex image */ + _mesa_CopyTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA, + srcX, srcY, srcW, srcH, 0); + blit->TexWidth = srcW; + blit->TexHeight = srcH; + blit->TexType = GL_RGBA; + } + + mask &= ~GL_COLOR_BUFFER_BIT; + } + + _mesa_Enable(GL_TEXTURE_RECTANGLE); + + /* draw textured quad */ + _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); + + _mesa_Disable(GL_TEXTURE_RECTANGLE); + + _mesa_meta_end(ctx); + + /* XXX, TO-DO: try to handle these cases above! */ + if (mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) { + _swrast_BlitFramebuffer(ctx, srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, mask, filter); + } +} + + +/** + * Meta implementation of ctx->Driver.Clear() in terms of polygon rendering. + */ +void +_mesa_meta_clear(GLcontext *ctx, GLbitfield buffers) +{ + struct clear_state *clear = &ctx->Meta->Clear; + GLfloat z = 1.0 - 2.0 * ctx->Depth.Clear; + GLuint i; + + /* only scissor and color mask effects clearing */ + _mesa_meta_begin(ctx, ~(META_SCISSOR | META_COLOR_MASK)); + + if (clear->ArrayObj == 0) { + /* one-time setup */ + + /* create vertex array object */ + _mesa_GenVertexArrays(1, &clear->ArrayObj); + _mesa_BindVertexArray(clear->ArrayObj); + + /* create vertex array buffer */ + _mesa_GenBuffersARB(1, &clear->VBO); + _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, clear->VBO); + _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(clear->verts), + clear->verts, GL_STREAM_DRAW_ARB); + + /* setup vertex arrays */ + _mesa_VertexPointer(3, GL_FLOAT, 7 * sizeof(GLfloat), (void *) 0); + _mesa_ColorPointer(4, GL_FLOAT, 7 * sizeof(GLfloat), + (void *) (3 * sizeof(GLfloat))); + _mesa_EnableClientState(GL_VERTEX_ARRAY); + _mesa_EnableClientState(GL_COLOR_ARRAY); + } + else { + _mesa_BindVertexArray(clear->ArrayObj); + _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, clear->VBO); + } + + /* GL_COLOR_BUFFER_BIT */ + if (buffers & BUFFER_BITS_COLOR) { + /* leave colormask, glDrawBuffer state as-is */ + } + else { + _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + } + + /* GL_DEPTH_BUFFER_BIT */ + if (buffers & BUFFER_BIT_DEPTH) { + _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_TRUE); + _mesa_DepthFunc(GL_ALWAYS); + _mesa_DepthMask(GL_TRUE); + } + else { + assert(!ctx->Depth.Test); + } + + /* GL_STENCIL_BUFFER_BIT */ + if (buffers & BUFFER_BIT_STENCIL) { + _mesa_set_enable(ctx, GL_STENCIL_TEST, GL_TRUE); + _mesa_StencilOpSeparate(GL_FRONT_AND_BACK, + GL_REPLACE, GL_REPLACE, GL_REPLACE); + _mesa_StencilFuncSeparate(GL_FRONT_AND_BACK, GL_ALWAYS, + ctx->Stencil.Clear & 0x7fffffff, + ctx->Stencil.WriteMask[0]); + } + else { + assert(!ctx->Stencil.Enabled); + } + + /* vertex positions */ + clear->verts[0][0] = (GLfloat) ctx->DrawBuffer->_Xmin; + clear->verts[0][1] = (GLfloat) ctx->DrawBuffer->_Ymin; + clear->verts[0][2] = z; + clear->verts[1][0] = (GLfloat) ctx->DrawBuffer->_Xmax; + clear->verts[1][1] = (GLfloat) ctx->DrawBuffer->_Ymin; + clear->verts[1][2] = z; + clear->verts[2][0] = (GLfloat) ctx->DrawBuffer->_Xmax; + clear->verts[2][1] = (GLfloat) ctx->DrawBuffer->_Ymax; + clear->verts[2][2] = z; + clear->verts[3][0] = (GLfloat) ctx->DrawBuffer->_Xmin; + clear->verts[3][1] = (GLfloat) ctx->DrawBuffer->_Ymax; + clear->verts[3][2] = z; + + /* vertex colors */ + for (i = 0; i < 4; i++) { + COPY_4FV(&clear->verts[i][3], ctx->Color.ClearColor); + } + + /* upload new vertex data */ + _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, + sizeof(clear->verts), clear->verts); + + /* draw quad */ + _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); + + _mesa_meta_end(ctx); +} + + +/** + * Meta implementation of ctx->Driver.CopyPixels() in terms + * of texture mapping and polygon rendering. + * Note: this function requires GL_ARB_texture_rectangle support. + */ +void +_mesa_meta_copy_pixels(GLcontext *ctx, GLint srcX, GLint srcY, + GLsizei width, GLsizei height, + GLint dstX, GLint dstY, GLenum type) +{ + const GLenum filter = GL_NEAREST; + struct copypix_state *copypix = &ctx->Meta->CopyPix; + const GLfloat z = ctx->Current.RasterPos[2]; + const GLfloat dstX1 = dstX + width * ctx->Pixel.ZoomX; + const GLfloat dstY1 = dstY + height * ctx->Pixel.ZoomY; + + ASSERT(ctx->Extensions.NV_texture_rectangle); + + if (type != GL_COLOR || + ctx->_ImageTransferState || + ctx->Fog.Enabled || + width > ctx->Const.MaxTextureRectSize || + height > ctx->Const.MaxTextureRectSize) { + /* XXX avoid this fallback */ + _swrast_CopyPixels(ctx, srcX, srcY, width, height, dstX, dstY, type); + return; + } + + /* Most GL state applies to glCopyPixels, but a there's a few things + * we need to override: + */ + _mesa_meta_begin(ctx, (META_RASTERIZATION | + META_SHADER | + META_TEXTURE | + META_TRANSFORM | + META_VERTEX | + META_VIEWPORT)); + + if (copypix->TexObj == 0) { + /* one-time setup */ + + /* create texture object */ + _mesa_GenTextures(1, ©pix->TexObj); + _mesa_BindTexture(GL_TEXTURE_RECTANGLE, copypix->TexObj); + _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + _mesa_TexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, filter); + _mesa_TexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, filter); + } + else { + _mesa_BindTexture(GL_TEXTURE_RECTANGLE, copypix->TexObj); + } + + if (copypix->ArrayObj == 0) { + /* one-time setup */ + + /* create vertex array object */ + _mesa_GenVertexArrays(1, ©pix->ArrayObj); + _mesa_BindVertexArray(copypix->ArrayObj); + + /* create vertex array buffer */ + _mesa_GenBuffersARB(1, ©pix->VBO); + _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, copypix->VBO); + _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(copypix->verts), + copypix->verts, GL_STREAM_DRAW_ARB); + + /* setup vertex arrays */ + _mesa_VertexPointer(3, GL_FLOAT, sizeof(copypix->verts[0]), + (void*) (0 * sizeof(GLfloat))); + _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(copypix->verts[0]), + (void *) (3 * sizeof(GLfloat))); + _mesa_EnableClientState(GL_VERTEX_ARRAY); + _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY); + } + else { + _mesa_BindVertexArray(copypix->ArrayObj); + _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, copypix->VBO); + } + + /* vertex positions, texcoords */ + copypix->verts[0][0] = (GLfloat) dstX; + copypix->verts[0][1] = (GLfloat) dstY; + copypix->verts[0][2] = z; + copypix->verts[0][3] = 0.0F; + copypix->verts[0][4] = 0.0F; + copypix->verts[1][0] = (GLfloat) dstX1; + copypix->verts[1][1] = (GLfloat) dstY; + copypix->verts[1][2] = z; + copypix->verts[1][3] = (GLfloat) width; + copypix->verts[1][4] = 0.0F; + copypix->verts[2][0] = (GLfloat) dstX1; + copypix->verts[2][1] = (GLfloat) dstY1; + copypix->verts[2][2] = z; + copypix->verts[2][3] = (GLfloat) width; + copypix->verts[2][4] = (GLfloat) height; + copypix->verts[3][0] = (GLfloat) dstX; + copypix->verts[3][1] = (GLfloat) dstY1; + copypix->verts[3][2] = z; + copypix->verts[3][3] = 0.0F; + copypix->verts[3][4] = (GLfloat) height; + + /* upload new vertex data */ + _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, + sizeof(copypix->verts), copypix->verts); + + /* copy framebuffer image to texture */ + if (type == GL_COLOR) { + if (copypix->TexWidth == width && + copypix->TexHeight == height && + copypix->TexType == type) { + /* replace existing tex image */ + _mesa_CopyTexSubImage2D(GL_TEXTURE_RECTANGLE, 0, + 0, 0, srcX, srcY, width, height); + } + else { + /* create new tex image */ + _mesa_CopyTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA, + srcX, srcY, width, height, 0); + copypix->TexWidth = width; + copypix->TexHeight = height; + copypix->TexType = type; + } + } + else if (type == GL_DEPTH) { + /* TO-DO: Use a GL_DEPTH_COMPONENT texture and a fragment program/shader + * that replaces the fragment.z value. + */ + } + else { + ASSERT(type == GL_STENCIL); + /* have to use sw fallback */ + } + + _mesa_Enable(GL_TEXTURE_RECTANGLE); + + /* draw textured quad */ + _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); + + _mesa_Disable(GL_TEXTURE_RECTANGLE); + + _mesa_meta_end(ctx); +} + + + +/** + * When the glDrawPixels() image size is greater than the max rectangle + * texture size we use this function to break the glDrawPixels() image + * into tiles which fit into the max texture size. + */ +static void +tiled_draw_pixels(GLcontext *ctx, + GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *unpack, + const GLvoid *pixels) +{ + const GLint maxSize = ctx->Const.MaxTextureRectSize; + struct gl_pixelstore_attrib tileUnpack = *unpack; + GLint i, j; + + for (i = 0; i < width; i += maxSize) { + const GLint tileWidth = MIN2(maxSize, width - i); + const GLint tileX = (GLint) (x + i * ctx->Pixel.ZoomX); + + tileUnpack.SkipPixels = unpack->SkipPixels + i; + + for (j = 0; j < height; j += maxSize) { + const GLint tileHeight = MIN2(maxSize, height - j); + const GLint tileY = (GLint) (y + j * ctx->Pixel.ZoomY); + + tileUnpack.SkipRows = unpack->SkipRows + j; + + _mesa_meta_draw_pixels(ctx, tileX, tileY, + tileWidth, tileHeight, + format, type, &tileUnpack, pixels); + } + } +} + + +/** + * Meta implementation of ctx->Driver.DrawPixels() in terms + * of texture mapping and polygon rendering. + * Note: this function requires GL_ARB_texture_rectangle support. + */ +void +_mesa_meta_draw_pixels(GLcontext *ctx, + GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *unpack, + const GLvoid *pixels) +{ + const GLenum filter = GL_NEAREST; + struct drawpix_state *drawpix = &ctx->Meta->DrawPix; + const GLfloat z = ctx->Current.RasterPos[2]; + const GLfloat x1 = x + width * ctx->Pixel.ZoomX; + const GLfloat y1 = y + height * ctx->Pixel.ZoomY; + const struct gl_pixelstore_attrib unpackSave = ctx->Unpack; + GLenum texIntFormat; + GLboolean fallback; + + ASSERT(ctx->Extensions.NV_texture_rectangle); + + /* + * Determine if we can do the glDrawPixels with texture mapping. + */ + fallback = GL_FALSE; + if (ctx->_ImageTransferState || + ctx->Fog.Enabled) { + fallback = GL_TRUE; + } + + if (_mesa_is_color_format(format)) { + texIntFormat = GL_RGBA; + } + else { + fallback = GL_TRUE; + } + + if (fallback) { + _swrast_DrawPixels(ctx, x, y, width, height, + format, type, unpack, pixels); + return; + } + + /* + * Check image size against max texture size, draw as tiles if needed. + */ + if (width > ctx->Const.MaxTextureRectSize || + height > ctx->Const.MaxTextureRectSize) { + tiled_draw_pixels(ctx, x, y, width, height, + format, type, unpack, pixels); + return; + } + + /* Most GL state applies to glDrawPixels, but a there's a few things + * we need to override: + */ + _mesa_meta_begin(ctx, (META_RASTERIZATION | + META_SHADER | + META_TEXTURE | + META_TRANSFORM | + META_VERTEX | + META_VIEWPORT)); + + if (drawpix->TexObj == 0) { + /* one-time setup */ + + /* create texture object */ + _mesa_GenTextures(1, &drawpix->TexObj); + _mesa_BindTexture(GL_TEXTURE_RECTANGLE, drawpix->TexObj); + _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + _mesa_TexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, filter); + _mesa_TexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, filter); + } + else { + _mesa_BindTexture(GL_TEXTURE_RECTANGLE, drawpix->TexObj); + } + + if (drawpix->ArrayObj == 0) { + /* one-time setup */ + + /* create vertex array object */ + _mesa_GenVertexArrays(1, &drawpix->ArrayObj); + _mesa_BindVertexArray(drawpix->ArrayObj); + + /* create vertex array buffer */ + _mesa_GenBuffersARB(1, &drawpix->VBO); + _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, drawpix->VBO); + _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(drawpix->verts), + drawpix->verts, GL_STREAM_DRAW_ARB); + + /* setup vertex arrays */ + _mesa_VertexPointer(3, GL_FLOAT, sizeof(drawpix->verts[0]), + (void*) (0 * sizeof(GLfloat))); + _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(drawpix->verts[0]), + (void *) (3 * sizeof(GLfloat))); + _mesa_EnableClientState(GL_VERTEX_ARRAY); + _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY); + } + else { + _mesa_BindVertexArray(drawpix->ArrayObj); + _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, drawpix->VBO); + } + + /* vertex positions, texcoords */ + drawpix->verts[0][0] = (GLfloat) x; + drawpix->verts[0][1] = (GLfloat) y; + drawpix->verts[0][2] = z; + drawpix->verts[0][3] = 0.0F; + drawpix->verts[0][4] = 0.0F; + drawpix->verts[1][0] = (GLfloat) x1; + drawpix->verts[1][1] = (GLfloat) y; + drawpix->verts[1][2] = z; + drawpix->verts[1][3] = (GLfloat) width; + drawpix->verts[1][4] = 0.0F; + drawpix->verts[2][0] = (GLfloat) x1; + drawpix->verts[2][1] = (GLfloat) y1; + drawpix->verts[2][2] = z; + drawpix->verts[2][3] = (GLfloat) width; + drawpix->verts[2][4] = (GLfloat) height; + drawpix->verts[3][0] = (GLfloat) x; + drawpix->verts[3][1] = (GLfloat) y1; + drawpix->verts[3][2] = z; + drawpix->verts[3][3] = 0.0F; + drawpix->verts[3][4] = (GLfloat) height; + + /* upload new vertex data */ + _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, + sizeof(drawpix->verts), drawpix->verts); + + /* set given unpack params */ + ctx->Unpack = *unpack; /* XXX bufobj */ + + /* copy pixel data to texture */ + if (drawpix->TexWidth == width && + drawpix->TexHeight == height && + drawpix->TexIntFormat == texIntFormat) { + /* replace existing tex image */ + _mesa_TexSubImage2D(GL_TEXTURE_RECTANGLE, 0, + 0, 0, width, height, format, type, pixels); + } + else { + /* create new tex image */ + _mesa_TexImage2D(GL_TEXTURE_RECTANGLE, 0, texIntFormat, + width, height, 0, format, type, pixels); + drawpix->TexWidth = width; + drawpix->TexHeight = height; + drawpix->TexIntFormat = texIntFormat; + } + + /* restore unpack params */ + ctx->Unpack = unpackSave; /* XXX bufobj */ + + _mesa_Enable(GL_TEXTURE_RECTANGLE); + + /* draw textured quad */ + _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); + + _mesa_Disable(GL_TEXTURE_RECTANGLE); + + _mesa_meta_end(ctx); +} diff --git a/src/mesa/drivers/common/meta.h b/src/mesa/drivers/common/meta.h new file mode 100644 index 0000000000..a9c5f98043 --- /dev/null +++ b/src/mesa/drivers/common/meta.h @@ -0,0 +1,80 @@ +/* + * Mesa 3-D graphics library + * Version: 7.6 + * + * Copyright (C) 2009 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, 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 + * BRIAN PAUL 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 META_H +#define META_H + + +/** + * Flags passed to _mesa_meta_begin(). + * XXX these flags may evolve... + */ +/*@{*/ +#define META_ALPHA_TEST 0x1 +#define META_BLEND 0x2 /**< includes logicop */ +#define META_COLOR_MASK 0x4 +#define META_DEPTH_TEST 0x8 +#define META_FOG 0x10 +#define META_RASTERIZATION 0x20 +#define META_SCISSOR 0x40 +#define META_SHADER 0x80 +#define META_STENCIL_TEST 0x100 +#define META_TRANSFORM 0x200 /**< modelview, projection */ +#define META_TEXTURE 0x400 +#define META_VERTEX 0x800 +#define META_VIEWPORT 0x1000 +#define META_ALL ~0x0 +/*@}*/ + + +extern void +_mesa_meta_init(GLcontext *ctx); + +extern void +_mesa_meta_free(GLcontext *ctx); + +extern void +_mesa_meta_blit_framebuffer(GLcontext *ctx, + GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, + GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, + GLbitfield mask, GLenum filter); + +extern void +_mesa_meta_clear(GLcontext *ctx, GLbitfield buffers); + +extern void +_mesa_meta_copy_pixels(GLcontext *ctx, GLint srcx, GLint srcy, + GLsizei width, GLsizei height, + GLint dstx, GLint dsty, GLenum type); + +extern void +_mesa_meta_draw_pixels(GLcontext *ctx, + GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *unpack, + const GLvoid *pixels); + + +#endif /* META_H */ diff --git a/src/mesa/drivers/dri/common/.gitignore b/src/mesa/drivers/dri/common/.gitignore new file mode 100644 index 0000000000..1edeb79fd1 --- /dev/null +++ b/src/mesa/drivers/dri/common/.gitignore @@ -0,0 +1 @@ +*.os diff --git a/src/mesa/drivers/dri/common/dri_metaops.c b/src/mesa/drivers/dri/common/dri_metaops.c index fe183c2e87..cdbea34495 100644 --- a/src/mesa/drivers/dri/common/dri_metaops.c +++ b/src/mesa/drivers/dri/common/dri_metaops.c @@ -357,6 +357,7 @@ meta_clear_tris(struct dri_metaops *meta, GLbitfield mask) GLuint saved_shader_program = 0; unsigned int saved_active_texture; struct gl_array_object *arraySave = NULL; + GLfloat saved_near, saved_far; if (!meta->clear.arrayObj) meta_init_clear(meta); @@ -370,8 +371,7 @@ meta_clear_tris(struct dri_metaops *meta, GLbitfield mask) GL_POLYGON_BIT | GL_STENCIL_BUFFER_BIT | GL_TRANSFORM_BIT | - GL_CURRENT_BIT | - GL_VIEWPORT_BIT); + GL_CURRENT_BIT); saved_active_texture = ctx->Texture.CurrentUnit; /* Disable existing GL state we don't want to apply to a clear. */ @@ -440,6 +440,8 @@ meta_clear_tris(struct dri_metaops *meta, GLbitfield mask) /* The ClearDepth value is unaffected by DepthRange, so do a default * mapping. */ + saved_near = ctx->Viewport.Near; + saved_far = ctx->Viewport.Far; _mesa_DepthRange(0.0, 1.0); /* Prepare the vertices, which are the same regardless of which buffer we're @@ -519,6 +521,7 @@ meta_clear_tris(struct dri_metaops *meta, GLbitfield mask) if (saved_shader_program) _mesa_UseProgramObjectARB(saved_shader_program); + _mesa_DepthRange(saved_near, saved_far); _mesa_PopAttrib(); /* restore current array object */ diff --git a/src/mesa/drivers/dri/common/dri_util.c b/src/mesa/drivers/dri/common/dri_util.c index 1d940603fa..e48e10d7c0 100644 --- a/src/mesa/drivers/dri/common/dri_util.c +++ b/src/mesa/drivers/dri/common/dri_util.c @@ -778,7 +778,7 @@ dri2CreateNewScreen(int scrn, int fd, if (driDriverAPI.InitScreen2 == NULL) return NULL; - psp = _mesa_malloc(sizeof(*psp)); + psp = _mesa_calloc(sizeof(*psp)); if (!psp) return NULL; diff --git a/src/mesa/drivers/dri/common/extension_helper.h b/src/mesa/drivers/dri/common/extension_helper.h index 62801494ce..08a97bb111 100644 --- a/src/mesa/drivers/dri/common/extension_helper.h +++ b/src/mesa/drivers/dri/common/extension_helper.h @@ -752,6 +752,13 @@ static const char VertexAttrib4ubNV_names[] = ""; #endif +#if defined(need_GL_APPLE_texture_range) +static const char TextureRangeAPPLE_names[] = + "iip\0" /* Parameter signature */ + "glTextureRangeAPPLE\0" + ""; +#endif + #if defined(need_GL_SUN_vertex) static const char TexCoord2fColor4fNormal3fVertex3fSUN_names[] = "ffffffffffff\0" /* Parameter signature */ @@ -1567,6 +1574,13 @@ static const char FragmentLightivSGIX_names[] = ""; #endif +#if defined(need_GL_APPLE_texture_range) +static const char GetTexParameterPointervAPPLE_names[] = + "iip\0" /* Parameter signature */ + "glGetTexParameterPointervAPPLE\0" + ""; +#endif + #if defined(need_GL_EXT_pixel_transform) static const char PixelTransformParameterfvEXT_names[] = "iip\0" /* Parameter signature */ @@ -1771,6 +1785,13 @@ static const char DeleteFencesNV_names[] = ""; #endif +#if defined(need_GL_SGIX_polynomial_ffd) +static const char DeformationMap3dSGIX_names[] = + "iddiiddiiddiip\0" /* Parameter signature */ + "glDeformationMap3dSGIX\0" + ""; +#endif + #if defined(need_GL_VERSION_2_0) static const char IsShader_names[] = "i\0" /* Parameter signature */ @@ -1997,13 +2018,6 @@ static const char GetCombinerOutputParameterivNV_names[] = ""; #endif -#if defined(need_GL_IBM_multimode_draw_arrays) -static const char MultiModeDrawArraysIBM_names[] = - "pppii\0" /* Parameter signature */ - "glMultiModeDrawArraysIBM\0" - ""; -#endif - #if defined(need_GL_SGIS_pixel_texture) static const char PixelTexGenParameterivSGIS_names[] = "ip\0" /* Parameter signature */ @@ -2079,6 +2093,13 @@ static const char Uniform2fvARB_names[] = ""; #endif +#if defined(need_GL_APPLE_flush_buffer_range) +static const char BufferParameteriAPPLE_names[] = + "iii\0" /* Parameter signature */ + "glBufferParameteriAPPLE\0" + ""; +#endif + #if defined(need_GL_VERSION_1_3) static const char MultiTexCoord3dvARB_names[] = "ip\0" /* Parameter signature */ @@ -2803,6 +2824,13 @@ static const char IsProgramNV_names[] = ""; #endif +#if defined(need_GL_APPLE_flush_buffer_range) +static const char FlushMappedBufferRangeAPPLE_names[] = + "iii\0" /* Parameter signature */ + "glFlushMappedBufferRangeAPPLE\0" + ""; +#endif + #if defined(need_GL_SUN_triangle_list) static const char ReplacementCodePointerSUN_names[] = "iip\0" /* Parameter signature */ @@ -3920,6 +3948,13 @@ static const char VertexAttribs4dvNV_names[] = ""; #endif +#if defined(need_GL_IBM_multimode_draw_arrays) +static const char MultiModeDrawArraysIBM_names[] = + "pppii\0" /* Parameter signature */ + "glMultiModeDrawArraysIBM\0" + ""; +#endif + #if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program) static const char VertexAttrib4dARB_names[] = "idddd\0" /* Parameter signature */ @@ -4604,13 +4639,6 @@ static const char Minmax_names[] = ""; #endif -#if defined(need_GL_SGIX_polynomial_ffd) -static const char DeformationMap3dSGIX_names[] = - "iddiiddiiddiip\0" /* Parameter signature */ - "glDeformationMap3dSGIX\0" - ""; -#endif - #if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_fog_coord) static const char FogCoorddvEXT_names[] = "p\0" /* Parameter signature */ @@ -4973,6 +5001,22 @@ static const struct dri_extension_function GL_3DFX_tbuffer_functions[] = { }; #endif +#if defined(need_GL_APPLE_flush_buffer_range) +static const struct dri_extension_function GL_APPLE_flush_buffer_range_functions[] = { + { BufferParameteriAPPLE_names, BufferParameteriAPPLE_remap_index, -1 }, + { FlushMappedBufferRangeAPPLE_names, FlushMappedBufferRangeAPPLE_remap_index, -1 }, + { NULL, 0, 0 } +}; +#endif + +#if defined(need_GL_APPLE_texture_range) +static const struct dri_extension_function GL_APPLE_texture_range_functions[] = { + { TextureRangeAPPLE_names, TextureRangeAPPLE_remap_index, -1 }, + { GetTexParameterPointervAPPLE_names, GetTexParameterPointervAPPLE_remap_index, -1 }, + { NULL, 0, 0 } +}; +#endif + #if defined(need_GL_APPLE_vertex_array_object) static const struct dri_extension_function GL_APPLE_vertex_array_object_functions[] = { { DeleteVertexArraysAPPLE_names, DeleteVertexArraysAPPLE_remap_index, -1 }, @@ -6131,9 +6175,9 @@ static const struct dri_extension_function GL_SGIX_pixel_texture_functions[] = { #if defined(need_GL_SGIX_polynomial_ffd) static const struct dri_extension_function GL_SGIX_polynomial_ffd_functions[] = { { LoadIdentityDeformationMapSGIX_names, LoadIdentityDeformationMapSGIX_remap_index, -1 }, + { DeformationMap3dSGIX_names, DeformationMap3dSGIX_remap_index, -1 }, { DeformSGIX_names, DeformSGIX_remap_index, -1 }, { DeformationMap3fSGIX_names, DeformationMap3fSGIX_remap_index, -1 }, - { DeformationMap3dSGIX_names, DeformationMap3dSGIX_remap_index, -1 }, { NULL, 0, 0 } }; #endif diff --git a/src/mesa/drivers/dri/fb/fb_egl.c b/src/mesa/drivers/dri/fb/fb_egl.c index dee67feb5a..4e41860d8c 100644 --- a/src/mesa/drivers/dri/fb/fb_egl.c +++ b/src/mesa/drivers/dri/fb/fb_egl.c @@ -605,7 +605,7 @@ fbDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface) { fbSurface *fs = Lookup_fbSurface(surface); _eglUnlinkSurface(&fs->Base); - if (!fs->Base.IsBound) + if (!_eglIsSurfaceBound(&fs->Base)) free(fs); return EGL_TRUE; } @@ -616,7 +616,7 @@ fbDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext context) { fbContext *fc = Lookup_fbContext(context); _eglUnlinkContext(&fc->Base); - if (!fc->Base.IsBound) + if (!_eglIsContextBound(&fc->Base)) free(fc); return EGL_TRUE; } diff --git a/src/mesa/drivers/dri/i915/i830_context.h b/src/mesa/drivers/dri/i915/i830_context.h index 1bdb32049d..f73cbbf88b 100644 --- a/src/mesa/drivers/dri/i915/i830_context.h +++ b/src/mesa/drivers/dri/i915/i830_context.h @@ -40,6 +40,7 @@ #define I830_UPLOAD_BUFFERS 0x2 #define I830_UPLOAD_STIPPLE 0x4 #define I830_UPLOAD_INVARIENT 0x8 +#define I830_UPLOAD_RASTER_RULES 0x10 #define I830_UPLOAD_TEX(i) (0x10<<(i)) #define I830_UPLOAD_TEXBLEND(i) (0x100<<(i)) #define I830_UPLOAD_TEX_ALL (0x0f0) @@ -99,6 +100,11 @@ #define I830_TEXBLEND_SIZE 12 /* (4 args + op) * 2 + COLOR_FACTOR */ +enum { + I830_RASTER_RULES, + I830_RASTER_RULES_SIZE +}; + struct i830_texture_object { struct intel_texture_object intel; @@ -112,6 +118,7 @@ struct i830_hw_state GLuint Ctx[I830_CTX_SETUP_SIZE]; GLuint Buffer[I830_DEST_SETUP_SIZE]; GLuint Stipple[I830_STP_SETUP_SIZE]; + GLuint RasterRules[I830_RASTER_RULES_SIZE]; GLuint Tex[I830_TEX_UNITS][I830_TEX_SETUP_SIZE]; GLuint TexBlend[I830_TEX_UNITS][I830_TEXBLEND_SIZE]; GLuint TexBlendWordsUsed[I830_TEX_UNITS]; @@ -197,6 +204,7 @@ extern void i830InitStateFuncs(struct dd_function_table *functions); extern void i830EmitState(struct i830_context *i830); extern void i830InitState(struct i830_context *i830); +extern void i830_update_provoking_vertex(GLcontext *ctx); /* i830_metaops.c */ diff --git a/src/mesa/drivers/dri/i915/i830_reg.h b/src/mesa/drivers/dri/i915/i830_reg.h index db16871001..ae1317029a 100644 --- a/src/mesa/drivers/dri/i915/i830_reg.h +++ b/src/mesa/drivers/dri/i915/i830_reg.h @@ -420,8 +420,11 @@ #define ENABLE_LINE_STRIP_PROVOKE_VRTX (1<<8) #define ENABLE_TRI_FAN_PROVOKE_VRTX (1<<5) #define ENABLE_TRI_STRIP_PROVOKE_VRTX (1<<2) +#define LINE_STRIP_PROVOKE_VRTX_MASK (3<<6) #define LINE_STRIP_PROVOKE_VRTX(x) ((x)<<6) +#define TRI_FAN_PROVOKE_VRTX_MASK (3<<3) #define TRI_FAN_PROVOKE_VRTX(x) ((x)<<3) +#define TRI_STRIP_PROVOKE_VRTX_MASK (3<<0) #define TRI_STRIP_PROVOKE_VRTX(x) (x) /* _3DSTATE_SCISSOR_ENABLE, p200 */ diff --git a/src/mesa/drivers/dri/i915/i830_state.c b/src/mesa/drivers/dri/i915/i830_state.c index 8ef6c9144f..645ebe3057 100644 --- a/src/mesa/drivers/dri/i915/i830_state.c +++ b/src/mesa/drivers/dri/i915/i830_state.c @@ -1047,6 +1047,16 @@ i830_init_packets(struct i830_context *i830) TEXBIND_SET1(TEXCOORDSRC_VTXSET_1) | TEXBIND_SET0(TEXCOORDSRC_VTXSET_0)); + i830->state.RasterRules[I830_RASTER_RULES] = (_3DSTATE_RASTER_RULES_CMD | + ENABLE_POINT_RASTER_RULE | + OGL_POINT_RASTER_RULE | + ENABLE_LINE_STRIP_PROVOKE_VRTX | + ENABLE_TRI_FAN_PROVOKE_VRTX | + ENABLE_TRI_STRIP_PROVOKE_VRTX | + LINE_STRIP_PROVOKE_VRTX(1) | + TRI_FAN_PROVOKE_VRTX(2) | + TRI_STRIP_PROVOKE_VRTX(2)); + i830->state.Stipple[I830_STPREG_ST0] = _3DSTATE_STIPPLE; @@ -1058,6 +1068,27 @@ i830_init_packets(struct i830_context *i830) i830->state.Buffer[I830_DESTREG_SR2] = 0; } +void +i830_update_provoking_vertex(GLcontext * ctx) +{ + struct i830_context *i830 = i830_context(ctx); + + I830_STATECHANGE(i830, I830_UPLOAD_RASTER_RULES); + i830->state.RasterRules[I830_RASTER_RULES] &= ~(LINE_STRIP_PROVOKE_VRTX_MASK | + TRI_FAN_PROVOKE_VRTX_MASK | + TRI_STRIP_PROVOKE_VRTX_MASK); + + /* _NEW_LIGHT */ + if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION) { + i830->state.RasterRules[I830_RASTER_RULES] |= (LINE_STRIP_PROVOKE_VRTX(1) | + TRI_FAN_PROVOKE_VRTX(2) | + TRI_STRIP_PROVOKE_VRTX(2)); + } else { + i830->state.RasterRules[I830_RASTER_RULES] |= (LINE_STRIP_PROVOKE_VRTX(0) | + TRI_FAN_PROVOKE_VRTX(1) | + TRI_STRIP_PROVOKE_VRTX(0)); + } +} void i830InitStateFuncs(struct dd_function_table *functions) @@ -1101,6 +1132,7 @@ i830InitState(struct i830_context *i830) i830->current = &i830->state; i830->state.emitted = 0; i830->state.active = (I830_UPLOAD_INVARIENT | + I830_UPLOAD_RASTER_RULES | I830_UPLOAD_TEXBLEND(0) | I830_UPLOAD_STIPPLE | I830_UPLOAD_CTX | I830_UPLOAD_BUFFERS); diff --git a/src/mesa/drivers/dri/i915/i830_vtbl.c b/src/mesa/drivers/dri/i915/i830_vtbl.c index 9c6f891dd3..983f6724c9 100644 --- a/src/mesa/drivers/dri/i915/i830_vtbl.c +++ b/src/mesa/drivers/dri/i915/i830_vtbl.c @@ -299,7 +299,7 @@ i830_emit_invarient_state(struct intel_context *intel) { BATCH_LOCALS; - BEGIN_BATCH(30, IGNORE_CLIPRECTS); + BEGIN_BATCH(29, IGNORE_CLIPRECTS); OUT_BATCH(_3DSTATE_DFLT_DIFFUSE_CMD); OUT_BATCH(0); @@ -351,15 +351,6 @@ i830_emit_invarient_state(struct intel_context *intel) OUT_BATCH(_3DSTATE_MAP_COORD_TRANSFORM); OUT_BATCH(DISABLE_TEX_TRANSFORM | TEXTURE_SET(3)); - OUT_BATCH(_3DSTATE_RASTER_RULES_CMD | - ENABLE_POINT_RASTER_RULE | - OGL_POINT_RASTER_RULE | - ENABLE_LINE_STRIP_PROVOKE_VRTX | - ENABLE_TRI_FAN_PROVOKE_VRTX | - ENABLE_TRI_STRIP_PROVOKE_VRTX | - LINE_STRIP_PROVOKE_VRTX(1) | - TRI_FAN_PROVOKE_VRTX(2) | TRI_STRIP_PROVOKE_VRTX(2)); - OUT_BATCH(_3DSTATE_VERTEX_TRANSFORM); OUT_BATCH(DISABLE_VIEWPORT_TRANSFORM | DISABLE_PERSPECTIVE_DIVIDE); @@ -394,6 +385,9 @@ get_state_size(struct i830_hw_state *state) if (dirty & I830_UPLOAD_INVARIENT) sz += 40 * sizeof(int); + if (dirty & I830_UPLOAD_RASTER_RULES) + sz += sizeof(state->RasterRules); + if (dirty & I830_UPLOAD_CTX) sz += sizeof(state->Ctx); @@ -486,6 +480,11 @@ i830_emit_state(struct intel_context *intel) i830_emit_invarient_state(intel); } + if (dirty & I830_UPLOAD_RASTER_RULES) { + DBG("I830_UPLOAD_RASTER_RULES:\n"); + emit(intel, state->RasterRules, sizeof(state->RasterRules)); + } + if (dirty & I830_UPLOAD_CTX) { DBG("I830_UPLOAD_CTX:\n"); emit(intel, state->Ctx, sizeof(state->Ctx)); @@ -737,6 +736,13 @@ i830_assert_not_dirty( struct intel_context *intel ) assert(!get_dirty(state)); } +static void +i830_invalidate_state(struct intel_context *intel, GLuint new_state) +{ + if (new_state & _NEW_LIGHT) + i830_update_provoking_vertex(&intel->ctx); +} + void i830InitVtbl(struct i830_context *i830) { @@ -752,4 +758,5 @@ i830InitVtbl(struct i830_context *i830) i830->intel.vtbl.render_prevalidate = i830_render_prevalidate; i830->intel.vtbl.assert_not_dirty = i830_assert_not_dirty; i830->intel.vtbl.finish_batch = intel_finish_vb; + i830->intel.vtbl.invalidate_state = i830_invalidate_state; } diff --git a/src/mesa/drivers/dri/i915/i915_context.c b/src/mesa/drivers/dri/i915/i915_context.c index 5aa41334b0..bb08cf8d18 100644 --- a/src/mesa/drivers/dri/i915/i915_context.c +++ b/src/mesa/drivers/dri/i915/i915_context.c @@ -77,6 +77,8 @@ i915InvalidateState(GLcontext * ctx, GLuint new_state) i915_update_fog(ctx); if (new_state & (_NEW_STENCIL | _NEW_BUFFERS | _NEW_POLYGON)) i915_update_stencil(ctx); + if (new_state & (_NEW_LIGHT)) + i915_update_provoking_vertex(ctx); } diff --git a/src/mesa/drivers/dri/i915/i915_context.h b/src/mesa/drivers/dri/i915/i915_context.h index c6b7377da8..8de4a9d0d3 100644 --- a/src/mesa/drivers/dri/i915/i915_context.h +++ b/src/mesa/drivers/dri/i915/i915_context.h @@ -48,6 +48,7 @@ #define I915_UPLOAD_FOG 0x20 #define I915_UPLOAD_INVARIENT 0x40 #define I915_UPLOAD_DEFAULTS 0x80 +#define I915_UPLOAD_RASTER_RULES 0x100 #define I915_UPLOAD_TEX(i) (0x00010000<<(i)) #define I915_UPLOAD_TEX_ALL (0x00ff0000) #define I915_UPLOAD_TEX_0_SHIFT 16 @@ -112,6 +113,10 @@ #define I915_DEFREG_Z1 5 #define I915_DEF_SETUP_SIZE 6 +enum { + I915_RASTER_RULES, + I915_RASTER_RULES_SETUP_SIZE, +}; #define I915_MAX_CONSTANT 32 #define I915_CONSTANT_SIZE (2+(4*I915_MAX_CONSTANT)) @@ -208,6 +213,7 @@ struct i915_hw_state GLuint Stipple[I915_STP_SETUP_SIZE]; GLuint Fog[I915_FOG_SETUP_SIZE]; GLuint Defaults[I915_DEF_SETUP_SIZE]; + GLuint RasterRules[I915_RASTER_RULES_SETUP_SIZE]; GLuint Tex[I915_TEX_UNITS][I915_TEX_SETUP_SIZE]; GLuint Constant[I915_CONSTANT_SIZE]; GLuint ConstantSize; @@ -324,6 +330,7 @@ extern void i915InitStateFunctions(struct dd_function_table *functions); extern void i915InitState(struct i915_context *i915); extern void i915_update_fog(GLcontext * ctx); extern void i915_update_stencil(GLcontext * ctx); +extern void i915_update_provoking_vertex(GLcontext *ctx); /*====================================================================== diff --git a/src/mesa/drivers/dri/i915/i915_reg.h b/src/mesa/drivers/dri/i915/i915_reg.h index 80ec46190d..b5fa7fddb9 100644 --- a/src/mesa/drivers/dri/i915/i915_reg.h +++ b/src/mesa/drivers/dri/i915/i915_reg.h @@ -297,7 +297,9 @@ #define TEXKILL_4D (1<<9) #define ENABLE_LINE_STRIP_PROVOKE_VRTX (1<<8) #define ENABLE_TRI_FAN_PROVOKE_VRTX (1<<5) +#define LINE_STRIP_PROVOKE_VRTX_MASK (3 << 6) #define LINE_STRIP_PROVOKE_VRTX(x) ((x)<<6) +#define TRI_FAN_PROVOKE_VRTX_MASK (3 << 3) #define TRI_FAN_PROVOKE_VRTX(x) ((x)<<3) /* _3DSTATE_SCISSOR_ENABLE, p256 */ diff --git a/src/mesa/drivers/dri/i915/i915_state.c b/src/mesa/drivers/dri/i915/i915_state.c index 670451bc83..b60efea75b 100644 --- a/src/mesa/drivers/dri/i915/i915_state.c +++ b/src/mesa/drivers/dri/i915/i915_state.c @@ -1033,6 +1033,13 @@ i915_init_packets(struct i915_context *i915) i915->state.Buffer[I915_DESTREG_SR2] = 0; } + i915->state.RasterRules[I915_RASTER_RULES] = _3DSTATE_RASTER_RULES_CMD | + ENABLE_POINT_RASTER_RULE | + OGL_POINT_RASTER_RULE | + ENABLE_LINE_STRIP_PROVOKE_VRTX | + ENABLE_TRI_FAN_PROVOKE_VRTX | + LINE_STRIP_PROVOKE_VRTX(1) | + TRI_FAN_PROVOKE_VRTX(2) | ENABLE_TEXKILL_3D_4D | TEXKILL_4D; #if 0 { @@ -1053,7 +1060,33 @@ i915_init_packets(struct i915_context *i915) i915->state.active = (I915_UPLOAD_PROGRAM | I915_UPLOAD_STIPPLE | I915_UPLOAD_CTX | - I915_UPLOAD_BUFFERS | I915_UPLOAD_INVARIENT); + I915_UPLOAD_BUFFERS | + I915_UPLOAD_INVARIENT | + I915_UPLOAD_RASTER_RULES); +} + +void +i915_update_provoking_vertex(GLcontext * ctx) +{ + struct i915_context *i915 = I915_CONTEXT(ctx); + + I915_STATECHANGE(i915, I915_UPLOAD_CTX); + i915->state.Ctx[I915_CTXREG_LIS6] &= ~(S6_TRISTRIP_PV_MASK); + + I915_STATECHANGE(i915, I915_UPLOAD_RASTER_RULES); + i915->state.RasterRules[I915_RASTER_RULES] &= ~(LINE_STRIP_PROVOKE_VRTX_MASK | + TRI_FAN_PROVOKE_VRTX_MASK); + + /* _NEW_LIGHT */ + if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION) { + i915->state.RasterRules[I915_RASTER_RULES] |= (LINE_STRIP_PROVOKE_VRTX(1) | + TRI_FAN_PROVOKE_VRTX(2)); + i915->state.Ctx[I915_CTXREG_LIS6] |= (2 << S6_TRISTRIP_PV_SHIFT); + } else { + i915->state.RasterRules[I915_RASTER_RULES] |= (LINE_STRIP_PROVOKE_VRTX(0) | + TRI_FAN_PROVOKE_VRTX(1)); + i915->state.Ctx[I915_CTXREG_LIS6] |= (0 << S6_TRISTRIP_PV_SHIFT); + } } void diff --git a/src/mesa/drivers/dri/i915/i915_vtbl.c b/src/mesa/drivers/dri/i915/i915_vtbl.c index 707864ebfd..9a723d3cd7 100644 --- a/src/mesa/drivers/dri/i915/i915_vtbl.c +++ b/src/mesa/drivers/dri/i915/i915_vtbl.c @@ -176,7 +176,7 @@ i915_emit_invarient_state(struct intel_context *intel) { BATCH_LOCALS; - BEGIN_BATCH(18, IGNORE_CLIPRECTS); + BEGIN_BATCH(17, IGNORE_CLIPRECTS); OUT_BATCH(_3DSTATE_AA_CMD | AA_LINE_ECAAR_WIDTH_ENABLE | @@ -200,14 +200,6 @@ i915_emit_invarient_state(struct intel_context *intel) CSB_TCB(3, 3) | CSB_TCB(4, 4) | CSB_TCB(5, 5) | CSB_TCB(6, 6) | CSB_TCB(7, 7)); - OUT_BATCH(_3DSTATE_RASTER_RULES_CMD | - ENABLE_POINT_RASTER_RULE | - OGL_POINT_RASTER_RULE | - ENABLE_LINE_STRIP_PROVOKE_VRTX | - ENABLE_TRI_FAN_PROVOKE_VRTX | - LINE_STRIP_PROVOKE_VRTX(1) | - TRI_FAN_PROVOKE_VRTX(2) | ENABLE_TEXKILL_3D_4D | TEXKILL_4D); - /* Need to initialize this to zero. */ OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(3) | (0)); @@ -258,6 +250,9 @@ get_state_size(struct i915_hw_state *state) if (dirty & I915_UPLOAD_INVARIENT) sz += 30 * 4; + if (dirty & I915_UPLOAD_RASTER_RULES) + sz += sizeof(state->RasterRules); + if (dirty & I915_UPLOAD_CTX) sz += sizeof(state->Ctx); @@ -366,6 +361,12 @@ i915_emit_state(struct intel_context *intel) i915_emit_invarient_state(intel); } + if (dirty & I915_UPLOAD_RASTER_RULES) { + if (INTEL_DEBUG & DEBUG_STATE) + fprintf(stderr, "I915_UPLOAD_RASTER_RULES:\n"); + emit(intel, state->RasterRules, sizeof(state->RasterRules)); + } + if (dirty & I915_UPLOAD_CTX) { if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_CTX:\n"); diff --git a/src/mesa/drivers/dri/i965/Makefile b/src/mesa/drivers/dri/i965/Makefile index 00a42111da..128afb5686 100644 --- a/src/mesa/drivers/dri/i965/Makefile +++ b/src/mesa/drivers/dri/i965/Makefile @@ -43,6 +43,7 @@ DRIVER_SOURCES = \ brw_clip_util.c \ brw_context.c \ brw_curbe.c \ + brw_disasm.c \ brw_draw.c \ brw_draw_upload.c \ brw_eu.c \ diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h index 57ddf75413..847c44ed83 100644 --- a/src/mesa/drivers/dri/i965/brw_context.h +++ b/src/mesa/drivers/dri/i965/brw_context.h @@ -143,6 +143,7 @@ struct brw_context; #define BRW_NEW_DEPTH_BUFFER 0x20000 #define BRW_NEW_NR_WM_SURFACES 0x40000 #define BRW_NEW_NR_VS_SURFACES 0x80000 +#define BRW_NEW_INDEX_BUFFER 0x100000 struct brw_state_flags { /** State update flags signalled by mesa internals */ @@ -438,9 +439,13 @@ struct brw_query_object { unsigned int count; }; + +/** + * brw_context is derived from intel_context. + */ struct brw_context { - struct intel_context intel; + struct intel_context intel; /**< base class, must be first field */ GLuint primitive; GLboolean emit_state_always; @@ -475,6 +480,9 @@ struct brw_context struct { struct brw_vertex_element inputs[VERT_ATTRIB_MAX]; + struct brw_vertex_element *enabled[VERT_ATTRIB_MAX]; + GLuint nr_enabled; + #define BRW_NR_UPLOAD_BUFS 17 #define BRW_UPLOAD_INIT_SIZE (128*1024) @@ -498,8 +506,15 @@ struct brw_context */ const struct _mesa_index_buffer *ib; + /* Updates to these fields are signaled by BRW_NEW_INDEX_BUFFER. */ dri_bo *bo; unsigned int offset; + unsigned int size; + /* Offset to index buffer index to use in CMD_3D_PRIM so that we can + * avoid re-uploading the IB packet over and over if we're actually + * referencing the same index buffer. + */ + unsigned int start_vertex_offset; } ib; /* Active vertex program: @@ -706,6 +721,8 @@ void brw_upload_urb_fence(struct brw_context *brw); */ void brw_upload_cs_urb_state(struct brw_context *brw); +/* brw_disasm.c */ +int brw_disasm (FILE *file, struct brw_instruction *inst); /*====================================================================== * Inline conversion functions. These are better-typed than the diff --git a/src/mesa/drivers/dri/i965/brw_defines.h b/src/mesa/drivers/dri/i965/brw_defines.h index d166250b4f..78d457ad2b 100644 --- a/src/mesa/drivers/dri/i965/brw_defines.h +++ b/src/mesa/drivers/dri/i965/brw_defines.h @@ -471,8 +471,9 @@ #define BRW_CONDITIONAL_GE 4 #define BRW_CONDITIONAL_L 5 #define BRW_CONDITIONAL_LE 6 -#define BRW_CONDITIONAL_C 7 +#define BRW_CONDITIONAL_R 7 #define BRW_CONDITIONAL_O 8 +#define BRW_CONDITIONAL_U 9 #define BRW_DEBUG_NONE 0 #define BRW_DEBUG_BREAKPOINT 1 @@ -512,6 +513,7 @@ #define BRW_OPCODE_RSL 11 #define BRW_OPCODE_ASR 12 #define BRW_OPCODE_CMP 16 +#define BRW_OPCODE_CMPN 17 #define BRW_OPCODE_JMPI 32 #define BRW_OPCODE_IF 34 #define BRW_OPCODE_IFF 35 diff --git a/src/mesa/drivers/dri/i965/brw_disasm.c b/src/mesa/drivers/dri/i965/brw_disasm.c new file mode 100644 index 0000000000..9fef230507 --- /dev/null +++ b/src/mesa/drivers/dri/i965/brw_disasm.c @@ -0,0 +1,903 @@ +/* + * Copyright © 2008 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <getopt.h> +#include <unistd.h> +#include <stdarg.h> + +#include "main/mtypes.h" + +#include "brw_context.h" +#include "brw_defines.h" + +struct { + char *name; + int nsrc; + int ndst; +} opcode[128] = { + [BRW_OPCODE_MOV] = { .name = "mov", .nsrc = 1, .ndst = 1 }, + [BRW_OPCODE_FRC] = { .name = "frc", .nsrc = 1, .ndst = 1 }, + [BRW_OPCODE_RNDU] = { .name = "rndu", .nsrc = 1, .ndst = 1 }, + [BRW_OPCODE_RNDD] = { .name = "rndd", .nsrc = 1, .ndst = 1 }, + [BRW_OPCODE_RNDE] = { .name = "rnde", .nsrc = 1, .ndst = 1 }, + [BRW_OPCODE_RNDZ] = { .name = "rndz", .nsrc = 1, .ndst = 1 }, + [BRW_OPCODE_NOT] = { .name = "not", .nsrc = 1, .ndst = 1 }, + [BRW_OPCODE_LZD] = { .name = "lzd", .nsrc = 1, .ndst = 1 }, + + [BRW_OPCODE_MUL] = { .name = "mul", .nsrc = 2, .ndst = 1 }, + [BRW_OPCODE_MAC] = { .name = "mac", .nsrc = 2, .ndst = 1 }, + [BRW_OPCODE_MACH] = { .name = "mach", .nsrc = 2, .ndst = 1 }, + [BRW_OPCODE_LINE] = { .name = "line", .nsrc = 2, .ndst = 1 }, + [BRW_OPCODE_SAD2] = { .name = "sad2", .nsrc = 2, .ndst = 1 }, + [BRW_OPCODE_SADA2] = { .name = "sada2", .nsrc = 2, .ndst = 1 }, + [BRW_OPCODE_DP4] = { .name = "dp4", .nsrc = 2, .ndst = 1 }, + [BRW_OPCODE_DPH] = { .name = "dph", .nsrc = 2, .ndst = 1 }, + [BRW_OPCODE_DP3] = { .name = "dp3", .nsrc = 2, .ndst = 1 }, + [BRW_OPCODE_DP2] = { .name = "dp2", .nsrc = 2, .ndst = 1 }, + + [BRW_OPCODE_AVG] = { .name = "avg", .nsrc = 2, .ndst = 1 }, + [BRW_OPCODE_ADD] = { .name = "add", .nsrc = 2, .ndst = 1 }, + [BRW_OPCODE_SEL] = { .name = "sel", .nsrc = 2, .ndst = 1 }, + [BRW_OPCODE_AND] = { .name = "and", .nsrc = 2, .ndst = 1 }, + [BRW_OPCODE_OR] = { .name = "or", .nsrc = 2, .ndst = 1 }, + [BRW_OPCODE_XOR] = { .name = "xor", .nsrc = 2, .ndst = 1 }, + [BRW_OPCODE_SHR] = { .name = "shr", .nsrc = 2, .ndst = 1 }, + [BRW_OPCODE_SHL] = { .name = "shl", .nsrc = 2, .ndst = 1 }, + [BRW_OPCODE_ASR] = { .name = "asr", .nsrc = 2, .ndst = 1 }, + [BRW_OPCODE_CMP] = { .name = "cmp", .nsrc = 2, .ndst = 1 }, + [BRW_OPCODE_CMPN] = { .name = "cmpn", .nsrc = 2, .ndst = 1 }, + + [BRW_OPCODE_SEND] = { .name = "send", .nsrc = 1, .ndst = 1 }, + [BRW_OPCODE_NOP] = { .name = "nop", .nsrc = 0, .ndst = 0 }, + [BRW_OPCODE_JMPI] = { .name = "jmpi", .nsrc = 1, .ndst = 0 }, + [BRW_OPCODE_IF] = { .name = "if", .nsrc = 2, .ndst = 0 }, + [BRW_OPCODE_IFF] = { .name = "iff", .nsrc = 1, .ndst = 01 }, + [BRW_OPCODE_WHILE] = { .name = "while", .nsrc = 1, .ndst = 0 }, + [BRW_OPCODE_ELSE] = { .name = "else", .nsrc = 2, .ndst = 0 }, + [BRW_OPCODE_BREAK] = { .name = "break", .nsrc = 1, .ndst = 0 }, + [BRW_OPCODE_CONTINUE] = { .name = "cont", .nsrc = 1, .ndst = 0 }, + [BRW_OPCODE_HALT] = { .name = "halt", .nsrc = 1, .ndst = 0 }, + [BRW_OPCODE_MSAVE] = { .name = "msave", .nsrc = 1, .ndst = 1 }, + [BRW_OPCODE_PUSH] = { .name = "push", .nsrc = 1, .ndst = 1 }, + [BRW_OPCODE_MRESTORE] = { .name = "mrest", .nsrc = 1, .ndst = 1 }, + [BRW_OPCODE_POP] = { .name = "pop", .nsrc = 2, .ndst = 0 }, + [BRW_OPCODE_WAIT] = { .name = "wait", .nsrc = 1, .ndst = 0 }, + [BRW_OPCODE_DO] = { .name = "do", .nsrc = 0, .ndst = 0 }, + [BRW_OPCODE_ENDIF] = { .name = "endif", .nsrc = 2, .ndst = 0 }, +}; + +char *conditional_modifier[16] = { + [BRW_CONDITIONAL_NONE] = "", + [BRW_CONDITIONAL_Z] = ".e", + [BRW_CONDITIONAL_NZ] = ".ne", + [BRW_CONDITIONAL_G] = ".g", + [BRW_CONDITIONAL_GE] = ".ge", + [BRW_CONDITIONAL_L] = ".l", + [BRW_CONDITIONAL_LE] = ".le", + [BRW_CONDITIONAL_R] = ".r", + [BRW_CONDITIONAL_O] = ".o", + [BRW_CONDITIONAL_U] = ".u", +}; + +char *negate[2] = { + [0] = "", + [1] = "-", +}; + +char *_abs[2] = { + [0] = "", + [1] = "(abs)", +}; + +char *vert_stride[16] = { + [0] = "0", + [1] = "1", + [2] = "2", + [3] = "4", + [4] = "8", + [5] = "16", + [6] = "32", + [15] = "VxH", +}; + +char *width[8] = { + [0] = "1", + [1] = "2", + [2] = "4", + [3] = "8", + [4] = "16", +}; + +char *horiz_stride[4] = { + [0] = "0", + [1] = "1", + [2] = "2", + [3] = "4" +}; + +char *chan_sel[4] = { + [0] = "x", + [1] = "y", + [2] = "z", + [3] = "w", +}; + +char *dest_condmod[16] = { +}; + +char *debug_ctrl[2] = { + [0] = "", + [1] = ".breakpoint" +}; + +char *saturate[2] = { + [0] = "", + [1] = ".sat" +}; + +char *exec_size[8] = { + [0] = "1", + [1] = "2", + [2] = "4", + [3] = "8", + [4] = "16", + [5] = "32" +}; + +char *pred_inv[2] = { + [0] = "+", + [1] = "-" +}; + +char *pred_ctrl_align16[16] = { + [1] = "", + [2] = ".x", + [3] = ".y", + [4] = ".z", + [5] = ".w", + [6] = ".any4h", + [7] = ".all4h", +}; + +char *pred_ctrl_align1[16] = { + [1] = "", + [2] = ".anyv", + [3] = ".allv", + [4] = ".any2h", + [5] = ".all2h", + [6] = ".any4h", + [7] = ".all4h", + [8] = ".any8h", + [9] = ".all8h", + [10] = ".any16h", + [11] = ".all16h", +}; + +char *thread_ctrl[4] = { + [0] = "", + [2] = "switch" +}; + +char *compr_ctrl[4] = { + [0] = "", + [1] = "sechalf", + [2] = "compr", +}; + +char *dep_ctrl[4] = { + [0] = "", + [1] = "NoDDClr", + [2] = "NoDDChk", + [3] = "NoDDClr,NoDDChk", +}; + +char *mask_ctrl[4] = { + [0] = "", + [1] = "nomask", +}; + +char *access_mode[2] = { + [0] = "align1", + [1] = "align16", +}; + +char *reg_encoding[8] = { + [0] = "UD", + [1] = "D", + [2] = "UW", + [3] = "W", + [4] = "UB", + [5] = "B", + [7] = "F" +}; + +char *imm_encoding[8] = { + [0] = "UD", + [1] = "D", + [2] = "UW", + [3] = "W", + [5] = "VF", + [5] = "V", + [7] = "F" +}; + +char *reg_file[4] = { + [0] = "A", + [1] = "g", + [2] = "m", + [3] = "imm", +}; + +char *writemask[16] = { + [0x0] = ".", + [0x1] = ".x", + [0x2] = ".y", + [0x3] = ".xy", + [0x4] = ".z", + [0x5] = ".xz", + [0x6] = ".yz", + [0x7] = ".xyz", + [0x8] = ".w", + [0x9] = ".xw", + [0xa] = ".yw", + [0xb] = ".xyw", + [0xc] = ".zw", + [0xd] = ".xzw", + [0xe] = ".yzw", + [0xf] = "", +}; + +char *end_of_thread[2] = { + [0] = "", + [1] = "EOT" +}; + +char *target_function[16] = { + [BRW_MESSAGE_TARGET_NULL] = "null", + [BRW_MESSAGE_TARGET_MATH] = "math", + [BRW_MESSAGE_TARGET_SAMPLER] = "sampler", + [BRW_MESSAGE_TARGET_GATEWAY] = "gateway", + [BRW_MESSAGE_TARGET_DATAPORT_READ] = "read", + [BRW_MESSAGE_TARGET_DATAPORT_WRITE] = "write", + [BRW_MESSAGE_TARGET_URB] = "urb", + [BRW_MESSAGE_TARGET_THREAD_SPAWNER] = "thread_spawner" +}; + +char *math_function[16] = { + [BRW_MATH_FUNCTION_INV] = "inv", + [BRW_MATH_FUNCTION_LOG] = "log", + [BRW_MATH_FUNCTION_EXP] = "exp", + [BRW_MATH_FUNCTION_SQRT] = "sqrt", + [BRW_MATH_FUNCTION_RSQ] = "rsq", + [BRW_MATH_FUNCTION_SIN] = "sin", + [BRW_MATH_FUNCTION_COS] = "cos", + [BRW_MATH_FUNCTION_SINCOS] = "sincos", + [BRW_MATH_FUNCTION_TAN] = "tan", + [BRW_MATH_FUNCTION_POW] = "pow", + [BRW_MATH_FUNCTION_INT_DIV_QUOTIENT_AND_REMAINDER] = "intdivmod", + [BRW_MATH_FUNCTION_INT_DIV_QUOTIENT] = "intmod", + [BRW_MATH_FUNCTION_INT_DIV_REMAINDER] = "intdiv", +}; + +char *math_saturate[2] = { + [0] = "", + [1] = "sat" +}; + +char *math_signed[2] = { + [0] = "", + [1] = "signed" +}; + +char *math_scalar[2] = { + [0] = "", + [1] = "scalar" +}; + +char *math_precision[2] = { + [0] = "", + [1] = "partial_precision" +}; + +char *urb_swizzle[4] = { + [BRW_URB_SWIZZLE_NONE] = "", + [BRW_URB_SWIZZLE_INTERLEAVE] = "interleave", + [BRW_URB_SWIZZLE_TRANSPOSE] = "transpose", +}; + +char *urb_allocate[2] = { + [0] = "", + [1] = "allocate" +}; + +char *urb_used[2] = { + [0] = "", + [1] = "used" +}; + +char *urb_complete[2] = { + [0] = "", + [1] = "complete" +}; + +char *sampler_target_format[4] = { + [0] = "F", + [2] = "UD", + [3] = "D" +}; + + +static int column; + +static int string (FILE *file, char *string) +{ + fputs (string, file); + column += strlen (string); + return 0; +} + +static int format (FILE *f, char *format, ...) +{ + char buf[1024]; + va_list args; + va_start (args, format); + + vsnprintf (buf, sizeof (buf) - 1, format, args); + string (f, buf); + return 0; +} + +static int newline (FILE *f) +{ + putc ('\n', f); + column = 0; + return 0; +} + +static int pad (FILE *f, int c) +{ + do + string (f, " "); + while (column < c); + return 0; +} + +static int control (FILE *file, char *name, char *ctrl[], GLuint id, int *space) +{ + if (!ctrl[id]) { + fprintf (file, "*** invalid %s value %d ", + name, id); + return 1; + } + if (ctrl[id][0]) + { + if (space && *space) + string (file, " "); + string (file, ctrl[id]); + if (space) + *space = 1; + } + return 0; +} + +static int print_opcode (FILE *file, int id) +{ + if (!opcode[id].name) { + format (file, "*** invalid opcode value %d ", id); + return 1; + } + string (file, opcode[id].name); + return 0; +} + +static int reg (FILE *file, GLuint _reg_file, GLuint _reg_nr) +{ + int err = 0; + if (_reg_file == BRW_ARCHITECTURE_REGISTER_FILE) { + switch (_reg_nr & 0xf0) { + case BRW_ARF_NULL: + string (file, "null"); + return -1; + case BRW_ARF_ADDRESS: + format (file, "a%d", _reg_nr & 0x0f); + break; + case BRW_ARF_ACCUMULATOR: + format (file, "acc%d", _reg_nr & 0x0f); + break; + case BRW_ARF_MASK: + format (file, "mask%d", _reg_nr & 0x0f); + break; + case BRW_ARF_MASK_STACK: + format (file, "msd%d", _reg_nr & 0x0f); + break; + case BRW_ARF_STATE: + format (file, "sr%d", _reg_nr & 0x0f); + break; + case BRW_ARF_CONTROL: + format (file, "cr%d", _reg_nr & 0x0f); + break; + case BRW_ARF_NOTIFICATION_COUNT: + format (file, "n%d", _reg_nr & 0x0f); + break; + case BRW_ARF_IP: + string (file, "ip"); + return -1; + break; + default: + format (file, "ARF%d", _reg_nr); + break; + } + } else { + err |= control (file, "src reg file", reg_file, _reg_file, NULL); + format (file, "%d", _reg_nr); + } + return err; +} + +static int dest (FILE *file, struct brw_instruction *inst) +{ + int err = 0; + + if (inst->header.access_mode == BRW_ALIGN_1) + { + if (inst->bits1.da1.dest_address_mode == BRW_ADDRESS_DIRECT) + { + err |= reg (file, inst->bits1.da1.dest_reg_file, inst->bits1.da1.dest_reg_nr); + if (err == -1) + return 0; + if (inst->bits1.da1.dest_subreg_nr) + format (file, ".%d", inst->bits1.da1.dest_subreg_nr); + format (file, "<%d>", inst->bits1.da1.dest_horiz_stride); + err |= control (file, "dest reg encoding", reg_encoding, inst->bits1.da1.dest_reg_type, NULL); + } + else + { + string (file, "g[a0"); + if (inst->bits1.ia1.dest_subreg_nr) + format (file, ".%d", inst->bits1.ia1.dest_subreg_nr); + if (inst->bits1.ia1.dest_indirect_offset) + format (file, " %d", inst->bits1.ia1.dest_indirect_offset); + string (file, "]"); + format (file, "<%d>", inst->bits1.ia1.dest_horiz_stride); + err |= control (file, "dest reg encoding", reg_encoding, inst->bits1.ia1.dest_reg_type, NULL); + } + } + else + { + if (inst->bits1.da16.dest_address_mode == BRW_ADDRESS_DIRECT) + { + err |= reg (file, inst->bits1.da16.dest_reg_file, inst->bits1.da16.dest_reg_nr); + if (err == -1) + return 0; + if (inst->bits1.da16.dest_subreg_nr) + format (file, ".%d", inst->bits1.da16.dest_subreg_nr); + string (file, "<1>"); + err |= control (file, "writemask", writemask, inst->bits1.da16.dest_writemask, NULL); + err |= control (file, "dest reg encoding", reg_encoding, inst->bits1.da16.dest_reg_type, NULL); + } + else + { + err = 1; + string (file, "Indirect align16 address mode not supported"); + } + } + + return 0; +} + +static int src_align1_region (FILE *file, + GLuint _vert_stride, GLuint _width, GLuint _horiz_stride) +{ + int err = 0; + string (file, "<"); + err |= control (file, "vert stride", vert_stride, _vert_stride, NULL); + string (file, ","); + err |= control (file, "width", width, _width, NULL); + string (file, ","); + err |= control (file, "horiz_stride", horiz_stride, _horiz_stride, NULL); + string (file, ">"); + return err; +} + +static int src_da1 (FILE *file, GLuint type, GLuint _reg_file, + GLuint _vert_stride, GLuint _width, GLuint _horiz_stride, + GLuint reg_num, GLuint sub_reg_num, GLuint __abs, GLuint _negate) +{ + int err = 0; + err |= control (file, "negate", negate, _negate, NULL); + err |= control (file, "abs", _abs, __abs, NULL); + + err |= reg (file, _reg_file, reg_num); + if (err == -1) + return 0; + if (sub_reg_num) + format (file, ".%d", sub_reg_num); + src_align1_region (file, _vert_stride, _width, _horiz_stride); + err |= control (file, "src reg encoding", reg_encoding, type, NULL); + return err; +} + +static int src_ia1 (FILE *file, + GLuint type, + GLuint _reg_file, + GLint _addr_imm, + GLuint _addr_subreg_nr, + GLuint _negate, + GLuint __abs, + GLuint _addr_mode, + GLuint _horiz_stride, + GLuint _width, + GLuint _vert_stride) +{ + int err = 0; + err |= control (file, "negate", negate, _negate, NULL); + err |= control (file, "abs", _abs, __abs, NULL); + + string (file, "g[a0"); + if (_addr_subreg_nr) + format (file, ".%d", _addr_subreg_nr); + if (_addr_imm) + format (file, " %d", _addr_imm); + string (file, "]"); + src_align1_region (file, _vert_stride, _width, _horiz_stride); + err |= control (file, "src reg encoding", reg_encoding, type, NULL); + return err; +} + +static int src_da16 (FILE *file, + GLuint _reg_type, + GLuint _reg_file, + GLuint _vert_stride, + GLuint _reg_nr, + GLuint _subreg_nr, + GLuint __abs, + GLuint _negate, + GLuint swz_x, + GLuint swz_y, + GLuint swz_z, + GLuint swz_w) +{ + int err = 0; + err |= control (file, "negate", negate, _negate, NULL); + err |= control (file, "abs", _abs, __abs, NULL); + + err |= reg (file, _reg_file, _reg_nr); + if (err == -1) + return 0; + if (_subreg_nr) + format (file, ".%d", _subreg_nr); + string (file, "<"); + err |= control (file, "vert stride", vert_stride, _vert_stride, NULL); + string (file, ",1,1>"); + err |= control (file, "src da16 reg type", reg_encoding, _reg_type, NULL); + /* + * Three kinds of swizzle display: + * identity - nothing printed + * 1->all - print the single channel + * 1->1 - print the mapping + */ + if (swz_x == BRW_CHANNEL_X && + swz_y == BRW_CHANNEL_Y && + swz_z == BRW_CHANNEL_Z && + swz_w == BRW_CHANNEL_W) + { + ; + } + else if (swz_x == swz_y && swz_x == swz_z && swz_x == swz_w) + { + string (file, "."); + err |= control (file, "channel select", chan_sel, swz_x, NULL); + } + else + { + string (file, "."); + err |= control (file, "channel select", chan_sel, swz_x, NULL); + err |= control (file, "channel select", chan_sel, swz_y, NULL); + err |= control (file, "channel select", chan_sel, swz_z, NULL); + err |= control (file, "channel select", chan_sel, swz_w, NULL); + } + return err; +} + + +static int imm (FILE *file, GLuint type, struct brw_instruction *inst) { + switch (type) { + case BRW_REGISTER_TYPE_UD: + format (file, "0x%08xUD", inst->bits3.ud); + break; + case BRW_REGISTER_TYPE_D: + format (file, "%dD", inst->bits3.d); + break; + case BRW_REGISTER_TYPE_UW: + format (file, "0x%04xUW", (uint16_t) inst->bits3.ud); + break; + case BRW_REGISTER_TYPE_W: + format (file, "%dW", (int16_t) inst->bits3.d); + break; + case BRW_REGISTER_TYPE_UB: + format (file, "0x%02xUB", (int8_t) inst->bits3.ud); + break; + case BRW_REGISTER_TYPE_VF: + format (file, "Vector Float"); + break; + case BRW_REGISTER_TYPE_V: + format (file, "0x%08xV", inst->bits3.ud); + break; + case BRW_REGISTER_TYPE_F: + format (file, "%-gF", inst->bits3.f); + } + return 0; +} + +static int src0 (FILE *file, struct brw_instruction *inst) +{ + if (inst->bits1.da1.src0_reg_file == BRW_IMMEDIATE_VALUE) + return imm (file, inst->bits1.da1.src0_reg_type, + inst); + else if (inst->header.access_mode == BRW_ALIGN_1) + { + if (inst->bits2.da1.src0_address_mode == BRW_ADDRESS_DIRECT) + { + return src_da1 (file, + inst->bits1.da1.src0_reg_type, + inst->bits1.da1.src0_reg_file, + inst->bits2.da1.src0_vert_stride, + inst->bits2.da1.src0_width, + inst->bits2.da1.src0_horiz_stride, + inst->bits2.da1.src0_reg_nr, + inst->bits2.da1.src0_subreg_nr, + inst->bits2.da1.src0_abs, + inst->bits2.da1.src0_negate); + } + else + { + return src_ia1 (file, + inst->bits1.ia1.src0_reg_type, + inst->bits1.ia1.src0_reg_file, + inst->bits2.ia1.src0_indirect_offset, + inst->bits2.ia1.src0_subreg_nr, + inst->bits2.ia1.src0_negate, + inst->bits2.ia1.src0_abs, + inst->bits2.ia1.src0_address_mode, + inst->bits2.ia1.src0_horiz_stride, + inst->bits2.ia1.src0_width, + inst->bits2.ia1.src0_vert_stride); + } + } + else + { + if (inst->bits2.da16.src0_address_mode == BRW_ADDRESS_DIRECT) + { + return src_da16 (file, + inst->bits1.da16.src0_reg_type, + inst->bits1.da16.src0_reg_file, + inst->bits2.da16.src0_vert_stride, + inst->bits2.da16.src0_reg_nr, + inst->bits2.da16.src0_subreg_nr, + inst->bits2.da16.src0_abs, + inst->bits2.da16.src0_negate, + inst->bits2.da16.src0_swz_x, + inst->bits2.da16.src0_swz_y, + inst->bits2.da16.src0_swz_z, + inst->bits2.da16.src0_swz_w); + } + else + { + string (file, "Indirect align16 address mode not supported"); + return 1; + } + } +} + +static int src1 (FILE *file, struct brw_instruction *inst) +{ + if (inst->bits1.da1.src1_reg_file == BRW_IMMEDIATE_VALUE) + return imm (file, inst->bits1.da1.src1_reg_type, + inst); + else if (inst->header.access_mode == BRW_ALIGN_1) + { + if (inst->bits3.da1.src1_address_mode == BRW_ADDRESS_DIRECT) + { + return src_da1 (file, + inst->bits1.da1.src1_reg_type, + inst->bits1.da1.src1_reg_file, + inst->bits3.da1.src1_vert_stride, + inst->bits3.da1.src1_width, + inst->bits3.da1.src1_horiz_stride, + inst->bits3.da1.src1_reg_nr, + inst->bits3.da1.src1_subreg_nr, + inst->bits3.da1.src1_abs, + inst->bits3.da1.src1_negate); + } + else + { + return src_ia1 (file, + inst->bits1.ia1.src1_reg_type, + inst->bits1.ia1.src1_reg_file, + inst->bits3.ia1.src1_indirect_offset, + inst->bits3.ia1.src1_subreg_nr, + inst->bits3.ia1.src1_negate, + inst->bits3.ia1.src1_abs, + inst->bits3.ia1.src1_address_mode, + inst->bits3.ia1.src1_horiz_stride, + inst->bits3.ia1.src1_width, + inst->bits3.ia1.src1_vert_stride); + } + } + else + { + if (inst->bits3.da16.src1_address_mode == BRW_ADDRESS_DIRECT) + { + return src_da16 (file, + inst->bits1.da16.src1_reg_type, + inst->bits1.da16.src1_reg_file, + inst->bits3.da16.src1_vert_stride, + inst->bits3.da16.src1_reg_nr, + inst->bits3.da16.src1_subreg_nr, + inst->bits3.da16.src1_abs, + inst->bits3.da16.src1_negate, + inst->bits3.da16.src1_swz_x, + inst->bits3.da16.src1_swz_y, + inst->bits3.da16.src1_swz_z, + inst->bits3.da16.src1_swz_w); + } + else + { + string (file, "Indirect align16 address mode not supported"); + return 1; + } + } +} + +int brw_disasm (FILE *file, struct brw_instruction *inst) +{ + int err = 0; + int space = 0; + + if (inst->header.predicate_control) { + string (file, "("); + err |= control (file, "predicate inverse", pred_inv, inst->header.predicate_inverse, NULL); + string (file, "f0"); + if (inst->bits2.da1.flag_reg_nr) + format (file, ".%d", inst->bits2.da1.flag_reg_nr); + if (inst->header.access_mode == BRW_ALIGN_1) + err |= control (file, "predicate control align1", pred_ctrl_align1, + inst->header.predicate_control, NULL); + else + err |= control (file, "predicate control align16", pred_ctrl_align16, + inst->header.predicate_control, NULL); + string (file, ") "); + } + + err |= print_opcode (file, inst->header.opcode); + err |= control (file, "saturate", saturate, inst->header.saturate, NULL); + err |= control (file, "debug control", debug_ctrl, inst->header.debug_control, NULL); + + if (inst->header.opcode != BRW_OPCODE_SEND) + err |= control (file, "conditional modifier", conditional_modifier, + inst->header.destreg__conditionalmod, NULL); + + if (inst->header.opcode != BRW_OPCODE_NOP) { + string (file, "("); + err |= control (file, "execution size", exec_size, inst->header.execution_size, NULL); + string (file, ")"); + } + + if (inst->header.opcode == BRW_OPCODE_SEND) + format (file, " %d", inst->header.destreg__conditionalmod); + + if (opcode[inst->header.opcode].ndst > 0) { + pad (file, 16); + err |= dest (file, inst); + } + if (opcode[inst->header.opcode].nsrc > 0) { + pad (file, 32); + err |= src0 (file, inst); + } + if (opcode[inst->header.opcode].nsrc > 1) { + pad (file, 48); + err |= src1 (file, inst); + } + + if (inst->header.opcode == BRW_OPCODE_SEND) { + newline (file); + pad (file, 16); + space = 0; + err |= control (file, "target function", target_function, + inst->bits3.generic.msg_target, &space); + switch (inst->bits3.generic.msg_target) { + case BRW_MESSAGE_TARGET_MATH: + err |= control (file, "math function", math_function, + inst->bits3.math.function, &space); + err |= control (file, "math saturate", math_saturate, + inst->bits3.math.saturate, &space); + err |= control (file, "math signed", math_signed, + inst->bits3.math.int_type, &space); + err |= control (file, "math scalar", math_scalar, + inst->bits3.math.data_type, &space); + err |= control (file, "math precision", math_precision, + inst->bits3.math.precision, &space); + break; + case BRW_MESSAGE_TARGET_SAMPLER: + format (file, " (%d, %d, ", + inst->bits3.sampler.binding_table_index, + inst->bits3.sampler.sampler); + err |= control (file, "sampler target format", sampler_target_format, + inst->bits3.sampler.return_format, NULL); + string (file, ")"); + break; + case BRW_MESSAGE_TARGET_DATAPORT_WRITE: + format (file, " (%d, %d, %d, %d)", + inst->bits3.dp_write.binding_table_index, + (inst->bits3.dp_write.pixel_scoreboard_clear << 3) | + inst->bits3.dp_write.msg_control, + inst->bits3.dp_write.msg_type, + inst->bits3.dp_write.send_commit_msg); + break; + case BRW_MESSAGE_TARGET_URB: + format (file, " %d", inst->bits3.urb.offset); + space = 1; + err |= control (file, "urb swizzle", urb_swizzle, + inst->bits3.urb.swizzle_control, &space); + err |= control (file, "urb allocate", urb_allocate, + inst->bits3.urb.allocate, &space); + err |= control (file, "urb used", urb_used, + inst->bits3.urb.used, &space); + err |= control (file, "urb complete", urb_complete, + inst->bits3.urb.complete, &space); + break; + case BRW_MESSAGE_TARGET_THREAD_SPAWNER: + break; + default: + format (file, "unsupported target %d", inst->bits3.generic.msg_target); + break; + } + if (space) + string (file, " "); + format (file, "mlen %d", + inst->bits3.generic.msg_length); + format (file, " rlen %d", + inst->bits3.generic.response_length); + } + pad (file, 64); + if (inst->header.opcode != BRW_OPCODE_NOP) { + string (file, "{"); + space = 1; + err |= control(file, "access mode", access_mode, inst->header.access_mode, &space); + err |= control (file, "mask control", mask_ctrl, inst->header.mask_control, &space); + err |= control (file, "dependency control", dep_ctrl, inst->header.dependency_control, &space); + err |= control (file, "compression control", compr_ctrl, inst->header.compression_control, &space); + err |= control (file, "thread control", thread_ctrl, inst->header.thread_control, &space); + if (inst->header.opcode == BRW_OPCODE_SEND) + err |= control (file, "end of thread", end_of_thread, + inst->bits3.generic.end_of_thread, &space); + if (space) + string (file, " "); + string (file, "}"); + } + string (file, ";"); + newline (file); + return err; +} diff --git a/src/mesa/drivers/dri/i965/brw_draw.c b/src/mesa/drivers/dri/i965/brw_draw.c index 5152c3f3a5..682094ff13 100644 --- a/src/mesa/drivers/dri/i965/brw_draw.c +++ b/src/mesa/drivers/dri/i965/brw_draw.c @@ -141,6 +141,8 @@ static void brw_emit_prim(struct brw_context *brw, prim_packet.verts_per_instance = trim(prim->mode, prim->count); prim_packet.start_vert_location = prim->start; + if (prim->indexed) + prim_packet.start_vert_location += brw->ib.start_vertex_offset; prim_packet.instance_count = 1; prim_packet.start_instance_location = 0; prim_packet.base_vert_location = 0; @@ -422,54 +424,31 @@ static GLboolean brw_try_draw_prims( GLcontext *ctx, return retval; } -static GLboolean brw_need_rebase( GLcontext *ctx, - const struct gl_client_array *arrays[], - const struct _mesa_index_buffer *ib, - GLuint min_index ) -{ - if (min_index == 0) - return GL_FALSE; - - if (ib) { - if (!vbo_all_varyings_in_vbos(arrays)) - return GL_TRUE; - else - return GL_FALSE; - } - else { - /* Hmm. This isn't quite what I wanted. BRW can actually - * handle the mixed case well enough that we shouldn't need to - * rebase. However, it's probably not very common, nor hugely - * expensive to do it this way: - */ - if (!vbo_all_varyings_in_vbos(arrays)) - return GL_TRUE; - else - return GL_FALSE; - } -} - - void brw_draw_prims( GLcontext *ctx, const struct gl_client_array *arrays[], const struct _mesa_prim *prim, GLuint nr_prims, const struct _mesa_index_buffer *ib, + GLboolean index_bounds_valid, GLuint min_index, GLuint max_index ) { GLboolean retval; - /* Decide if we want to rebase. If so we end up recursing once - * only into this function. - */ - if (brw_need_rebase( ctx, arrays, ib, min_index )) { - vbo_rebase_prims( ctx, arrays, - prim, nr_prims, - ib, min_index, max_index, - brw_draw_prims ); - - return; + if (!vbo_all_varyings_in_vbos(arrays)) { + if (!index_bounds_valid) + vbo_get_minmax_index(ctx, prim, ib, &min_index, &max_index); + + /* Decide if we want to rebase. If so we end up recursing once + * only into this function. + */ + if (min_index != 0) { + vbo_rebase_prims(ctx, arrays, + prim, nr_prims, + ib, min_index, max_index, + brw_draw_prims ); + return; + } } /* Make a first attempt at drawing: diff --git a/src/mesa/drivers/dri/i965/brw_draw.h b/src/mesa/drivers/dri/i965/brw_draw.h index 9aebbdb1b8..2a14db217f 100644 --- a/src/mesa/drivers/dri/i965/brw_draw.h +++ b/src/mesa/drivers/dri/i965/brw_draw.h @@ -39,6 +39,7 @@ void brw_draw_prims( GLcontext *ctx, const struct _mesa_prim *prims, GLuint nr_prims, const struct _mesa_index_buffer *ib, + GLboolean index_bounds_valid, GLuint min_index, GLuint max_index ); diff --git a/src/mesa/drivers/dri/i965/brw_draw_upload.c b/src/mesa/drivers/dri/i965/brw_draw_upload.c index c29f1dd5c0..ab6b62812f 100644 --- a/src/mesa/drivers/dri/i965/brw_draw_upload.c +++ b/src/mesa/drivers/dri/i965/brw_draw_upload.c @@ -350,9 +350,6 @@ static void brw_prepare_vertices(struct brw_context *brw) unsigned int min_index = brw->vb.min_index; unsigned int max_index = brw->vb.max_index; - struct brw_vertex_element *enabled[VERT_ATTRIB_MAX]; - GLuint nr_enabled = 0; - struct brw_vertex_element *upload[VERT_ATTRIB_MAX]; GLuint nr_uploads = 0; @@ -362,12 +359,13 @@ static void brw_prepare_vertices(struct brw_context *brw) _mesa_printf("%s %d..%d\n", __FUNCTION__, min_index, max_index); /* Accumulate the list of enabled arrays. */ + brw->vb.nr_enabled = 0; while (vs_inputs) { GLuint i = _mesa_ffsll(vs_inputs) - 1; struct brw_vertex_element *input = &brw->vb.inputs[i]; vs_inputs &= ~(1 << i); - enabled[nr_enabled++] = input; + brw->vb.enabled[brw->vb.nr_enabled++] = input; } /* XXX: In the rare cases where this happens we fallback all @@ -376,16 +374,15 @@ static void brw_prepare_vertices(struct brw_context *brw) * cases with > 17 vertex attributes enabled, so it probably * isn't an issue at this point. */ - if (nr_enabled >= BRW_VEP_MAX) { + if (brw->vb.nr_enabled >= BRW_VEP_MAX) { intel->Fallback = 1; return; } - for (i = 0; i < nr_enabled; i++) { - struct brw_vertex_element *input = enabled[i]; + for (i = 0; i < brw->vb.nr_enabled; i++) { + struct brw_vertex_element *input = brw->vb.enabled[i]; input->element_size = get_size(input->glarray->Type) * input->glarray->Size; - input->count = input->glarray->StrideB ? max_index + 1 - min_index : 1; if (input->glarray->BufferObj->Name != 0) { struct intel_buffer_object *intel_buffer = @@ -398,7 +395,23 @@ static void brw_prepare_vertices(struct brw_context *brw) dri_bo_reference(input->bo); input->offset = (unsigned long)input->glarray->Ptr; input->stride = input->glarray->StrideB; + input->count = input->glarray->_MaxElement; + + /* This is a common place to reach if the user mistakenly supplies + * a pointer in place of a VBO offset. If we just let it go through, + * we may end up dereferencing a pointer beyond the bounds of the + * GTT. We would hope that the VBO's max_index would save us, but + * Mesa appears to hand us min/max values not clipped to the + * array object's _MaxElement, and _MaxElement frequently appears + * to be wrong anyway. + * + * The VBO spec allows application termination in this case, and it's + * probably a service to the poor programmer to do so rather than + * trying to just not render. + */ + assert(input->offset < input->bo->size); } else { + input->count = input->glarray->StrideB ? max_index + 1 - min_index : 1; if (input->bo != NULL) { /* Already-uploaded vertex data is present from a previous * prepare_vertices, but we had to re-validate state due to @@ -466,8 +479,8 @@ static void brw_prepare_vertices(struct brw_context *brw) brw_prepare_query_begin(brw); - for (i = 0; i < nr_enabled; i++) { - struct brw_vertex_element *input = enabled[i]; + for (i = 0; i < brw->vb.nr_enabled; i++) { + struct brw_vertex_element *input = brw->vb.enabled[i]; brw_add_validated_bo(brw, input->bo); } @@ -477,34 +490,44 @@ static void brw_emit_vertices(struct brw_context *brw) { GLcontext *ctx = &brw->intel.ctx; struct intel_context *intel = intel_context(ctx); - GLbitfield vs_inputs = brw->vs.prog_data->inputs_read; - struct brw_vertex_element *enabled[VERT_ATTRIB_MAX]; GLuint i; - GLuint nr_enabled = 0; - /* Accumulate the list of enabled arrays. */ - while (vs_inputs) { - i = _mesa_ffsll(vs_inputs) - 1; - struct brw_vertex_element *input = &brw->vb.inputs[i]; + brw_emit_query_begin(brw); - vs_inputs &= ~(1 << i); - enabled[nr_enabled++] = input; + /* If the VS doesn't read any inputs (calculating vertex position from + * a state variable for some reason, for example), emit a single pad + * VERTEX_ELEMENT struct and bail. + * + * The stale VB state stays in place, but they don't do anything unless + * a VE loads from them. + */ + if (brw->vb.nr_enabled == 0) { + BEGIN_BATCH(3, IGNORE_CLIPRECTS); + OUT_BATCH((CMD_VERTEX_ELEMENT << 16) | 1); + OUT_BATCH((0 << BRW_VE0_INDEX_SHIFT) | + BRW_VE0_VALID | + (BRW_SURFACEFORMAT_R32G32B32A32_FLOAT << BRW_VE0_FORMAT_SHIFT) | + (0 << BRW_VE0_SRC_OFFSET_SHIFT)); + OUT_BATCH((BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_0_SHIFT) | + (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_1_SHIFT) | + (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_2_SHIFT) | + (BRW_VE1_COMPONENT_STORE_1_FLT << BRW_VE1_COMPONENT_3_SHIFT)); + ADVANCE_BATCH(); + return; } - brw_emit_query_begin(brw); - /* Now emit VB and VEP state packets. * * This still defines a hardware VB for each input, even if they * are interleaved or from the same VBO. TBD if this makes a * performance difference. */ - BEGIN_BATCH(1 + nr_enabled * 4, IGNORE_CLIPRECTS); + BEGIN_BATCH(1 + brw->vb.nr_enabled * 4, IGNORE_CLIPRECTS); OUT_BATCH((CMD_VERTEX_BUFFER << 16) | - ((1 + nr_enabled * 4) - 2)); + ((1 + brw->vb.nr_enabled * 4) - 2)); - for (i = 0; i < nr_enabled; i++) { - struct brw_vertex_element *input = enabled[i]; + for (i = 0; i < brw->vb.nr_enabled; i++) { + struct brw_vertex_element *input = brw->vb.enabled[i]; OUT_BATCH((i << BRW_VB0_INDEX_SHIFT) | BRW_VB0_ACCESS_VERTEXDATA | @@ -524,15 +547,15 @@ static void brw_emit_vertices(struct brw_context *brw) input->offset + input->element_size); } } else - OUT_BATCH(brw->vb.max_index); + OUT_BATCH(input->count); OUT_BATCH(0); /* Instance data step rate */ } ADVANCE_BATCH(); - BEGIN_BATCH(1 + nr_enabled * 2, IGNORE_CLIPRECTS); - OUT_BATCH((CMD_VERTEX_ELEMENT << 16) | ((1 + nr_enabled * 2) - 2)); - for (i = 0; i < nr_enabled; i++) { - struct brw_vertex_element *input = enabled[i]; + BEGIN_BATCH(1 + brw->vb.nr_enabled * 2, IGNORE_CLIPRECTS); + OUT_BATCH((CMD_VERTEX_ELEMENT << 16) | ((1 + brw->vb.nr_enabled * 2) - 2)); + for (i = 0; i < brw->vb.nr_enabled; i++) { + struct brw_vertex_element *input = brw->vb.enabled[i]; uint32_t format = get_surface_type(input->glarray->Type, input->glarray->Size, input->glarray->Format, @@ -589,17 +612,20 @@ static void brw_prepare_indices(struct brw_context *brw) dri_bo *bo = NULL; struct gl_buffer_object *bufferobj; GLuint offset; + GLuint ib_type_size; if (index_buffer == NULL) return; - ib_size = get_size(index_buffer->type) * index_buffer->count; + ib_type_size = get_size(index_buffer->type); + ib_size = ib_type_size * index_buffer->count; bufferobj = index_buffer->obj;; /* Turn into a proper VBO: */ if (!bufferobj->Name) { - + brw->ib.start_vertex_offset = 0; + /* Get new bufferobj, offset: */ get_space(brw, ib_size, &bo, &offset); @@ -615,6 +641,7 @@ static void brw_prepare_indices(struct brw_context *brw) } } else { offset = (GLuint) (unsigned long) index_buffer->ptr; + brw->ib.start_vertex_offset = 0; /* If the index buffer isn't aligned to its element size, we have to * rebase it into a temporary. @@ -635,39 +662,62 @@ static void brw_prepare_indices(struct brw_context *brw) bo = intel_bufferobj_buffer(intel, intel_buffer_object(bufferobj), INTEL_READ); dri_bo_reference(bo); + + /* Use CMD_3D_PRIM's start_vertex_offset to avoid re-uploading + * the index buffer state when we're just moving the start index + * of our drawing. + */ + brw->ib.start_vertex_offset = offset / ib_type_size; + offset = 0; + ib_size = bo->size; } } - dri_bo_unreference(brw->ib.bo); - brw->ib.bo = bo; - brw->ib.offset = offset; + if (brw->ib.bo != bo || + brw->ib.offset != offset || + brw->ib.size != ib_size) + { + drm_intel_bo_unreference(brw->ib.bo); + brw->ib.bo = bo; + brw->ib.offset = offset; + brw->ib.size = ib_size; + + brw->state.dirty.brw |= BRW_NEW_INDEX_BUFFER; + } else { + drm_intel_bo_unreference(bo); + } brw_add_validated_bo(brw, brw->ib.bo); } -static void brw_emit_indices(struct brw_context *brw) +const struct brw_tracked_state brw_indices = { + .dirty = { + .mesa = 0, + .brw = BRW_NEW_INDICES, + .cache = 0, + }, + .prepare = brw_prepare_indices, +}; + +static void brw_emit_index_buffer(struct brw_context *brw) { struct intel_context *intel = &brw->intel; const struct _mesa_index_buffer *index_buffer = brw->ib.ib; - GLuint ib_size; if (index_buffer == NULL) return; - ib_size = get_size(index_buffer->type) * index_buffer->count - 1; - /* Emit the indexbuffer packet: */ { struct brw_indexbuffer ib; memset(&ib, 0, sizeof(ib)); - + ib.header.bits.opcode = CMD_INDEX_BUFFER; ib.header.bits.length = sizeof(ib)/4 - 2; ib.header.bits.index_format = get_index_type(index_buffer->type); ib.header.bits.cut_index_enable = 0; - BEGIN_BATCH(4, IGNORE_CLIPRECTS); OUT_BATCH( ib.header.dword ); @@ -676,18 +726,17 @@ static void brw_emit_indices(struct brw_context *brw) brw->ib.offset); OUT_RELOC(brw->ib.bo, I915_GEM_DOMAIN_VERTEX, 0, - brw->ib.offset + ib_size); + brw->ib.offset + brw->ib.size); OUT_BATCH( 0 ); ADVANCE_BATCH(); } } -const struct brw_tracked_state brw_indices = { +const struct brw_tracked_state brw_index_buffer = { .dirty = { .mesa = 0, - .brw = BRW_NEW_BATCH | BRW_NEW_INDICES, + .brw = BRW_NEW_BATCH | BRW_NEW_INDEX_BUFFER, .cache = 0, }, - .prepare = brw_prepare_indices, - .emit = brw_emit_indices, + .emit = brw_emit_index_buffer, }; diff --git a/src/mesa/drivers/dri/i965/brw_eu.c b/src/mesa/drivers/dri/i965/brw_eu.c index c53efba599..1df561386e 100644 --- a/src/mesa/drivers/dri/i965/brw_eu.c +++ b/src/mesa/drivers/dri/i965/brw_eu.c @@ -62,7 +62,7 @@ void brw_set_predicate_control( struct brw_compile *p, GLuint pc ) void brw_set_conditionalmod( struct brw_compile *p, GLuint conditional ) { - p->current->header.destreg__conditonalmod = conditional; + p->current->header.destreg__conditionalmod = conditional; } void brw_set_access_mode( struct brw_compile *p, GLuint access_mode ) diff --git a/src/mesa/drivers/dri/i965/brw_eu_emit.c b/src/mesa/drivers/dri/i965/brw_eu_emit.c index 2412014248..241cdc33f8 100644 --- a/src/mesa/drivers/dri/i965/brw_eu_emit.c +++ b/src/mesa/drivers/dri/i965/brw_eu_emit.c @@ -481,8 +481,8 @@ static struct brw_instruction *next_insn( struct brw_compile *p, /* Reset this one-shot flag: */ - if (p->current->header.destreg__conditonalmod) { - p->current->header.destreg__conditonalmod = 0; + if (p->current->header.destreg__conditionalmod) { + p->current->header.destreg__conditionalmod = 0; p->current->header.predicate_control = BRW_PREDICATE_NORMAL; } @@ -679,7 +679,7 @@ struct brw_instruction *brw_ELSE(struct brw_compile *p, assert(if_insn->header.opcode == BRW_OPCODE_IF); if_insn->bits3.if_else.jump_count = br * (insn - if_insn); - if_insn->bits3.if_else.pop_count = 1; + if_insn->bits3.if_else.pop_count = 0; if_insn->bits3.if_else.pad0 = 0; } @@ -871,7 +871,7 @@ void brw_CMP(struct brw_compile *p, { struct brw_instruction *insn = next_insn(p, BRW_OPCODE_CMP); - insn->header.destreg__conditonalmod = conditional; + insn->header.destreg__conditionalmod = conditional; brw_set_dest(insn, dest); brw_set_src0(insn, src0); brw_set_src1(insn, src1); @@ -915,7 +915,7 @@ void brw_math( struct brw_compile *p, * instructions. */ insn->header.predicate_control = 0; - insn->header.destreg__conditonalmod = msg_reg_nr; + insn->header.destreg__conditionalmod = msg_reg_nr; brw_set_dest(insn, dest); brw_set_src0(insn, src); @@ -952,7 +952,7 @@ void brw_math_16( struct brw_compile *p, brw_set_compression_control(p, BRW_COMPRESSION_NONE); insn = next_insn(p, BRW_OPCODE_SEND); - insn->header.destreg__conditonalmod = msg_reg_nr; + insn->header.destreg__conditionalmod = msg_reg_nr; brw_set_dest(insn, dest); brw_set_src0(insn, src); @@ -969,7 +969,7 @@ void brw_math_16( struct brw_compile *p, */ insn = next_insn(p, BRW_OPCODE_SEND); insn->header.compression_control = BRW_COMPRESSION_2NDHALF; - insn->header.destreg__conditonalmod = msg_reg_nr+1; + insn->header.destreg__conditionalmod = msg_reg_nr+1; brw_set_dest(insn, offset(dest,1)); brw_set_src0(insn, src); @@ -1016,7 +1016,7 @@ void brw_dp_WRITE_16( struct brw_compile *p, insn->header.predicate_control = 0; /* XXX */ insn->header.compression_control = BRW_COMPRESSION_NONE; - insn->header.destreg__conditonalmod = msg_reg_nr; + insn->header.destreg__conditionalmod = msg_reg_nr; brw_set_dest(insn, dest); brw_set_src0(insn, src); @@ -1062,7 +1062,7 @@ void brw_dp_READ_16( struct brw_compile *p, insn->header.predicate_control = 0; /* XXX */ insn->header.compression_control = BRW_COMPRESSION_NONE; - insn->header.destreg__conditonalmod = msg_reg_nr; + insn->header.destreg__conditionalmod = msg_reg_nr; brw_set_dest(insn, dest); /* UW? */ brw_set_src0(insn, retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UW)); @@ -1116,7 +1116,7 @@ void brw_dp_READ_4( struct brw_compile *p, insn->header.predicate_control = BRW_PREDICATE_NONE; insn->header.compression_control = BRW_COMPRESSION_NONE; - insn->header.destreg__conditonalmod = msg_reg_nr; + insn->header.destreg__conditionalmod = msg_reg_nr; insn->header.mask_control = BRW_MASK_DISABLE; /* cast dest to a uword[8] vector */ @@ -1190,7 +1190,7 @@ void brw_dp_READ_4_vs(struct brw_compile *p, insn->header.predicate_control = BRW_PREDICATE_NONE; insn->header.compression_control = BRW_COMPRESSION_NONE; - insn->header.destreg__conditonalmod = msg_reg_nr; + insn->header.destreg__conditionalmod = msg_reg_nr; insn->header.mask_control = BRW_MASK_DISABLE; /*insn->header.access_mode = BRW_ALIGN_16;*/ @@ -1224,7 +1224,7 @@ void brw_fb_WRITE(struct brw_compile *p, insn->header.predicate_control = 0; /* XXX */ insn->header.compression_control = BRW_COMPRESSION_NONE; - insn->header.destreg__conditonalmod = msg_reg_nr; + insn->header.destreg__conditionalmod = msg_reg_nr; brw_set_dest(insn, dest); brw_set_src0(insn, src0); @@ -1322,7 +1322,7 @@ void brw_SAMPLE(struct brw_compile *p, insn->header.predicate_control = 0; /* XXX */ insn->header.compression_control = BRW_COMPRESSION_NONE; - insn->header.destreg__conditonalmod = msg_reg_nr; + insn->header.destreg__conditionalmod = msg_reg_nr; brw_set_dest(insn, dest); brw_set_src0(insn, src0); @@ -1375,7 +1375,7 @@ void brw_urb_WRITE(struct brw_compile *p, brw_set_src0(insn, src0); brw_set_src1(insn, brw_imm_d(0)); - insn->header.destreg__conditonalmod = msg_reg_nr; + insn->header.destreg__conditionalmod = msg_reg_nr; brw_set_urb_message(p->brw, insn, @@ -1410,7 +1410,7 @@ void brw_ff_sync(struct brw_compile *p, brw_set_src0(insn, src0); brw_set_src1(insn, brw_imm_d(0)); - insn->header.destreg__conditonalmod = msg_reg_nr; + insn->header.destreg__conditionalmod = msg_reg_nr; brw_set_ff_sync_message(p->brw, insn, diff --git a/src/mesa/drivers/dri/i965/brw_gs_emit.c b/src/mesa/drivers/dri/i965/brw_gs_emit.c index 980eac7646..a9b2aa2eac 100644 --- a/src/mesa/drivers/dri/i965/brw_gs_emit.c +++ b/src/mesa/drivers/dri/i965/brw_gs_emit.c @@ -101,7 +101,7 @@ static void brw_gs_emit_vue(struct brw_gs_compile *c, BRW_URB_SWIZZLE_NONE); } -void brw_gs_ff_sync(struct brw_gs_compile *c, int num_prim) +static void brw_gs_ff_sync(struct brw_gs_compile *c, int num_prim) { struct brw_compile *p = &c->func; brw_MOV(p, get_element_ud(c->reg.R0, 1), brw_imm_ud(num_prim)); diff --git a/src/mesa/drivers/dri/i965/brw_sf_state.c b/src/mesa/drivers/dri/i965/brw_sf_state.c index b5f6371c82..bc0f076073 100644 --- a/src/mesa/drivers/dri/i965/brw_sf_state.c +++ b/src/mesa/drivers/dri/i965/brw_sf_state.c @@ -113,7 +113,7 @@ struct brw_sf_unit_key { unsigned int nr_urb_entries, urb_size, sfsize; - GLenum front_face, cull_face; + GLenum front_face, cull_face, provoking_vertex; unsigned scissor:1; unsigned line_smooth:1; unsigned point_sprite:1; @@ -153,6 +153,9 @@ sf_unit_populate_key(struct brw_context *brw, struct brw_sf_unit_key *key) key->point_size = CLAMP(ctx->Point.Size, ctx->Point.MinSize, ctx->Point.MaxSize); key->point_attenuated = ctx->Point._Attenuated; + /* _NEW_LIGHT */ + key->provoking_vertex = ctx->Light.ProvokingVertex; + key->render_to_fbo = brw->intel.ctx.DrawBuffer->Name != 0; } @@ -284,9 +287,15 @@ sf_unit_create_from_key(struct brw_context *brw, struct brw_sf_unit_key *key, /* might be BRW_NEW_PRIMITIVE if we have to adjust pv for polygons: */ - sf.sf7.trifan_pv = 2; - sf.sf7.linestrip_pv = 1; - sf.sf7.tristrip_pv = 2; + if (key->provoking_vertex == GL_LAST_VERTEX_CONVENTION) { + sf.sf7.trifan_pv = 2; + sf.sf7.linestrip_pv = 1; + sf.sf7.tristrip_pv = 2; + } else { + sf.sf7.trifan_pv = 1; + sf.sf7.linestrip_pv = 0; + sf.sf7.tristrip_pv = 0; + } sf.sf7.line_last_pixel_enable = 0; /* Set bias for OpenGL rasterization rules: @@ -300,6 +309,9 @@ sf_unit_create_from_key(struct brw_context *brw, struct brw_sf_unit_key *key, &sf, sizeof(sf), NULL, NULL); + /* STATE_PREFETCH command description describes this state as being + * something loaded through the GPE (L2 ISC), so it's INSTRUCTION domain. + */ /* Emit SF program relocation */ dri_bo_emit_reloc(bo, I915_GEM_DOMAIN_INSTRUCTION, 0, @@ -340,6 +352,7 @@ static void upload_sf_unit( struct brw_context *brw ) const struct brw_tracked_state brw_sf_unit = { .dirty = { .mesa = (_NEW_POLYGON | + _NEW_LIGHT | _NEW_LINE | _NEW_POINT | _NEW_SCISSOR | diff --git a/src/mesa/drivers/dri/i965/brw_state.h b/src/mesa/drivers/dri/i965/brw_state.h index bf9f6cae55..78572356a3 100644 --- a/src/mesa/drivers/dri/i965/brw_state.h +++ b/src/mesa/drivers/dri/i965/brw_state.h @@ -92,6 +92,7 @@ const struct brw_tracked_state brw_clear_batch_cache; const struct brw_tracked_state brw_drawing_rect; const struct brw_tracked_state brw_indices; const struct brw_tracked_state brw_vertices; +const struct brw_tracked_state brw_index_buffer; /** * Use same key for WM and VS surfaces. diff --git a/src/mesa/drivers/dri/i965/brw_state_upload.c b/src/mesa/drivers/dri/i965/brw_state_upload.c index 38d9dd8991..95d42d2dcc 100644 --- a/src/mesa/drivers/dri/i965/brw_state_upload.c +++ b/src/mesa/drivers/dri/i965/brw_state_upload.c @@ -94,6 +94,7 @@ const struct brw_tracked_state *atoms[] = &brw_drawing_rect, &brw_indices, + &brw_index_buffer, &brw_vertices, &brw_constant_buffer @@ -208,6 +209,7 @@ static struct dirty_bit_map brw_bits[] = { DEFINE_BIT(BRW_NEW_PSP), DEFINE_BIT(BRW_NEW_FENCE), DEFINE_BIT(BRW_NEW_INDICES), + DEFINE_BIT(BRW_NEW_INDEX_BUFFER), DEFINE_BIT(BRW_NEW_VERTICES), DEFINE_BIT(BRW_NEW_BATCH), DEFINE_BIT(BRW_NEW_DEPTH_BUFFER), diff --git a/src/mesa/drivers/dri/i965/brw_structs.h b/src/mesa/drivers/dri/i965/brw_structs.h index 8ba7eb27b3..a6de09207b 100644 --- a/src/mesa/drivers/dri/i965/brw_structs.h +++ b/src/mesa/drivers/dri/i965/brw_structs.h @@ -1200,7 +1200,7 @@ struct brw_instruction GLuint predicate_control:4; GLuint predicate_inverse:1; GLuint execution_size:3; - GLuint destreg__conditonalmod:4; /* destreg - send, conditionalmod - others */ + GLuint destreg__conditionalmod:4; /* destreg - send, conditionalmod - others */ GLuint pad0:2; GLuint debug_control:1; GLuint saturate:1; @@ -1228,7 +1228,9 @@ struct brw_instruction GLuint dest_reg_type:3; GLuint src0_reg_file:2; GLuint src0_reg_type:3; - GLuint pad:6; + GLuint src1_reg_file:2; /* 0x00000c00 */ + GLuint src1_reg_type:3; /* 0x00007000 */ + GLuint pad:1; GLint dest_indirect_offset:10; /* offset against the deref'd address reg */ GLuint dest_subreg_nr:3; /* subnr for the address reg a0.x */ GLuint dest_horiz_stride:2; @@ -1243,7 +1245,7 @@ struct brw_instruction GLuint src0_reg_type:3; GLuint src1_reg_file:2; GLuint src1_reg_type:3; - GLuint pad0:1; + GLuint pad:1; GLuint dest_writemask:4; GLuint dest_subreg_nr:1; GLuint dest_reg_nr:8; @@ -1348,7 +1350,7 @@ struct brw_instruction GLuint src1_reg_nr:8; GLuint src1_abs:1; GLuint src1_negate:1; - GLuint pad:1; + GLuint src1_address_mode:1; GLuint src1_horiz_stride:2; GLuint src1_width:3; GLuint src1_vert_stride:4; @@ -1363,7 +1365,7 @@ struct brw_instruction GLuint src1_reg_nr:8; GLuint src1_abs:1; GLuint src1_negate:1; - GLuint pad0:1; + GLuint src1_address_mode:1; GLuint src1_swz_z:2; GLuint src1_swz_w:2; GLuint pad1:1; @@ -1377,7 +1379,7 @@ struct brw_instruction GLuint src1_subreg_nr:3; GLuint src1_abs:1; GLuint src1_negate:1; - GLuint pad0:1; + GLuint src1_address_mode:1; GLuint src1_horiz_stride:2; GLuint src1_width:3; GLuint src1_vert_stride:4; @@ -1565,6 +1567,7 @@ struct brw_instruction GLint d; GLuint ud; + float f; } bits3; }; diff --git a/src/mesa/drivers/dri/i965/brw_tex_layout.c b/src/mesa/drivers/dri/i965/brw_tex_layout.c index 7f9b253534..1d2e953eb1 100644 --- a/src/mesa/drivers/dri/i965/brw_tex_layout.c +++ b/src/mesa/drivers/dri/i965/brw_tex_layout.c @@ -65,11 +65,6 @@ GLboolean brw_miptree_layout(struct intel_context *intel, if (mt->compressed) { mt->pitch = ALIGN(mt->width0, align_w); - qpitch = (y_pitch + ALIGN(minify(y_pitch), align_h) + 11 * align_h) / 4 * mt->pitch * mt->cpp; - mt->total_height = (y_pitch + ALIGN(minify(y_pitch), align_h) + 11 * align_h) / 4 * 6; - } else { - qpitch = (y_pitch + ALIGN(minify(y_pitch), align_h) + 11 * align_h) * mt->pitch * mt->cpp; - mt->total_height = (y_pitch + ALIGN(minify(y_pitch), align_h) + 11 * align_h) * 6; } if (mt->first_level != mt->last_level) { @@ -90,6 +85,14 @@ GLboolean brw_miptree_layout(struct intel_context *intel, mt->pitch = intel_miptree_pitch_align(intel, mt, tiling, mt->pitch); + if (mt->compressed) { + qpitch = (y_pitch + ALIGN(minify(y_pitch), align_h) + 11 * align_h) / 4 * mt->pitch * mt->cpp; + mt->total_height = (y_pitch + ALIGN(minify(y_pitch), align_h) + 11 * align_h) / 4 * 6; + } else { + qpitch = (y_pitch + ALIGN(minify(y_pitch), align_h) + 11 * align_h) * mt->pitch * mt->cpp; + mt->total_height = (y_pitch + ALIGN(minify(y_pitch), align_h) + 11 * align_h) * 6; + } + for (level = mt->first_level; level <= mt->last_level; level++) { GLuint img_height; GLuint nr_images = 6; diff --git a/src/mesa/drivers/dri/i965/brw_vs_emit.c b/src/mesa/drivers/dri/i965/brw_vs_emit.c index 514f15d5e3..83167b9258 100644 --- a/src/mesa/drivers/dri/i965/brw_vs_emit.c +++ b/src/mesa/drivers/dri/i965/brw_vs_emit.c @@ -68,6 +68,7 @@ static void release_tmps( struct brw_vs_compile *c ) static void brw_vs_alloc_regs( struct brw_vs_compile *c ) { GLuint i, reg = 0, mrf; + int attributes_in_vue; /* Determine whether to use a real constant buffer or use a block * of GRF registers for constants. The later is faster but only @@ -128,6 +129,11 @@ static void brw_vs_alloc_regs( struct brw_vs_compile *c ) reg++; } } + /* If there are no inputs, we'll still be reading one attribute's worth + * because it's required -- see urb_read_length setting. + */ + if (c->nr_inputs == 0) + reg++; /* Allocate outputs. The non-position outputs go straight into message regs. */ @@ -220,11 +226,22 @@ static void brw_vs_alloc_regs( struct brw_vs_compile *c ) * vertex urb, so is half the amount: */ c->prog_data.urb_read_length = (c->nr_inputs + 1) / 2; + /* Setting this field to 0 leads to undefined behavior according to the + * the VS_STATE docs. Our VUEs will always have at least one attribute + * sitting in them, even if it's padding. + */ + if (c->prog_data.urb_read_length == 0) + c->prog_data.urb_read_length = 1; + + /* The VS VUEs are shared by VF (outputting our inputs) and VS, so size + * them to fit the biggest thing they need to. + */ + attributes_in_vue = MAX2(c->nr_outputs, c->nr_inputs); if (BRW_IS_IGDNG(c->func.brw)) - c->prog_data.urb_entry_size = (c->nr_outputs + 6 + 3) / 4; + c->prog_data.urb_entry_size = (attributes_in_vue + 6 + 3) / 4; else - c->prog_data.urb_entry_size = (c->nr_outputs + 2 + 3) / 4; + c->prog_data.urb_entry_size = (attributes_in_vue + 2 + 3) / 4; c->prog_data.total_grf = reg; @@ -1245,9 +1262,30 @@ post_vs_emit( struct brw_vs_compile *c, /* patch up the END code to jump past subroutines, etc */ offset = last_inst - end_inst; - brw_set_src1(end_inst, brw_imm_d(offset * 16)); + if (offset > 1) { + brw_set_src1(end_inst, brw_imm_d(offset * 16)); + } else { + end_inst->header.opcode = BRW_OPCODE_NOP; + } } +static uint32_t +get_predicate(uint32_t swizzle) +{ + switch (swizzle) { + case SWIZZLE_XXXX: + return BRW_PREDICATE_ALIGN16_REPLICATE_X; + case SWIZZLE_YYYY: + return BRW_PREDICATE_ALIGN16_REPLICATE_Y; + case SWIZZLE_ZZZZ: + return BRW_PREDICATE_ALIGN16_REPLICATE_Z; + case SWIZZLE_WWWW: + return BRW_PREDICATE_ALIGN16_REPLICATE_W; + default: + _mesa_problem(NULL, "Unexpected predicate: 0x%08x\n", swizzle); + return BRW_PREDICATE_NORMAL; + } +} /* Emit the vertex program instructions here. */ @@ -1266,7 +1304,7 @@ void brw_vs_emit(struct brw_vs_compile *c ) GLuint file; if (INTEL_DEBUG & DEBUG_VS) { - _mesa_printf("vs-emit:\n"); + _mesa_printf("vs-mesa:\n"); _mesa_print_program(&c->vp->program.Base); _mesa_printf("\n"); } @@ -1453,7 +1491,10 @@ void brw_vs_emit(struct brw_vs_compile *c ) break; case OPCODE_IF: assert(if_depth < MAX_IF_DEPTH); - if_inst[if_depth++] = brw_IF(p, BRW_EXECUTE_8); + if_inst[if_depth] = brw_IF(p, BRW_EXECUTE_8); + if_inst[if_depth]->header.predicate_control = + get_predicate(inst->DstReg.CondSwizzle); + if_depth++; break; case OPCODE_ELSE: if_inst[if_depth-1] = brw_ELSE(p, if_inst[if_depth-1]); @@ -1541,6 +1582,19 @@ void brw_vs_emit(struct brw_vs_compile *c ) "unknown"); } + /* Set the predication update on the last instruction of the native + * instruction sequence. + * + * This would be problematic if it was set on a math instruction, + * but that shouldn't be the case with the current GLSL compiler. + */ + if (inst->CondUpdate) { + struct brw_instruction *hw_insn = &p->store[p->nr_insn - 1]; + + assert(hw_insn->header.destreg__conditionalmod == 0); + hw_insn->header.destreg__conditionalmod = BRW_CONDITIONAL_NZ; + } + if ((inst->DstReg.File == PROGRAM_OUTPUT) && (inst->DstReg.Index != VERT_RESULT_HPOS) && c->output_regs[inst->DstReg.Index].used_in_src) { @@ -1578,4 +1632,13 @@ void brw_vs_emit(struct brw_vs_compile *c ) emit_vertex_write(c); post_vs_emit(c, end_inst, last_inst); + + if (INTEL_DEBUG & DEBUG_VS) { + int i; + + _mesa_printf("vs-native:\n"); + for (i = 0; i < p->nr_insn; i++) + brw_disasm(stderr, &p->store[i]); + _mesa_printf("\n"); + } } diff --git a/src/mesa/drivers/dri/i965/brw_wm.c b/src/mesa/drivers/dri/i965/brw_wm.c index 14e05be4f6..2292de94c4 100644 --- a/src/mesa/drivers/dri/i965/brw_wm.c +++ b/src/mesa/drivers/dri/i965/brw_wm.c @@ -41,13 +41,13 @@ GLuint brw_wm_nr_args( GLuint opcode ) { switch (opcode) { case WM_FRONTFACING: - return 0; case WM_PIXELXY: + return 0; case WM_CINTERP: case WM_WPOSXY: + case WM_DELTAXY: return 1; case WM_LINTERP: - case WM_DELTAXY: case WM_PIXELW: return 2; case WM_FB_WRITE: @@ -171,9 +171,11 @@ static void do_wm_prog( struct brw_context *brw, * differently from "simple" shaders. */ if (fp->isGLSL) { + c->dispatch_width = 8; brw_wm_glsl_emit(brw, c); } else { + c->dispatch_width = 16; brw_wm_non_glsl_emit(brw, c); } @@ -202,6 +204,7 @@ static void brw_wm_populate_key( struct brw_context *brw, /* BRW_NEW_FRAGMENT_PROGRAM */ const struct brw_fragment_program *fp = (struct brw_fragment_program *)brw->fragment_program; + GLboolean uses_depth = (fp->program.Base.InputsRead & (1 << FRAG_ATTRIB_WPOS)) != 0; GLuint lookup = 0; GLuint line_aa; GLuint i; @@ -263,6 +266,7 @@ static void brw_wm_populate_key( struct brw_context *brw, brw_wm_lookup_iz(line_aa, lookup, + uses_depth, key); diff --git a/src/mesa/drivers/dri/i965/brw_wm.h b/src/mesa/drivers/dri/i965/brw_wm.h index ba497432c6..ae98b5492d 100644 --- a/src/mesa/drivers/dri/i965/brw_wm.h +++ b/src/mesa/drivers/dri/i965/brw_wm.h @@ -260,6 +260,7 @@ struct brw_wm_compile { GLuint tmp_index; GLuint tmp_max; GLuint subroutines[BRW_WM_MAX_SUBROUTINE]; + GLuint dispatch_width; /** we may need up to 3 constants per instruction (if use_const_buffer) */ struct { @@ -292,6 +293,7 @@ void brw_wm_print_program( struct brw_wm_compile *c, void brw_wm_lookup_iz( GLuint line_aa, GLuint lookup, + GLboolean ps_uses_depth, struct brw_wm_prog_key *key ); GLboolean brw_wm_is_glsl(const struct gl_fragment_program *fp); diff --git a/src/mesa/drivers/dri/i965/brw_wm_emit.c b/src/mesa/drivers/dri/i965/brw_wm_emit.c index 9f82916c02..b3cf524c63 100644 --- a/src/mesa/drivers/dri/i965/brw_wm_emit.c +++ b/src/mesa/drivers/dri/i965/brw_wm_emit.c @@ -65,8 +65,7 @@ static INLINE struct brw_reg sechalf( struct brw_reg reg ) static void emit_pixel_xy(struct brw_compile *p, const struct brw_reg *dst, - GLuint mask, - const struct brw_reg *arg0) + GLuint mask) { struct brw_reg r1 = brw_vec1_grf(1, 0); struct brw_reg r1_uw = retype(r1, BRW_REGISTER_TYPE_UW); @@ -98,8 +97,7 @@ static void emit_pixel_xy(struct brw_compile *p, static void emit_delta_xy(struct brw_compile *p, const struct brw_reg *dst, GLuint mask, - const struct brw_reg *arg0, - const struct brw_reg *arg1) + const struct brw_reg *arg0) { struct brw_reg r1 = brw_vec1_grf(1, 0); @@ -545,16 +543,18 @@ static void emit_dp3( struct brw_compile *p, const struct brw_reg *arg0, const struct brw_reg *arg1 ) { + int dst_chan = _mesa_ffs(mask & WRITEMASK_XYZW) - 1; + if (!(mask & WRITEMASK_XYZW)) return; /* Do not emit dead code */ - assert((mask & WRITEMASK_XYZW) == WRITEMASK_X); + assert(is_power_of_two(mask & WRITEMASK_XYZW)); brw_MUL(p, brw_null_reg(), arg0[0], arg1[0]); brw_MAC(p, brw_null_reg(), arg0[1], arg1[1]); brw_set_saturate(p, (mask & SATURATE) ? 1 : 0); - brw_MAC(p, dst[0], arg0[2], arg1[2]); + brw_MAC(p, dst[dst_chan], arg0[2], arg1[2]); brw_set_saturate(p, 0); } @@ -565,17 +565,19 @@ static void emit_dp4( struct brw_compile *p, const struct brw_reg *arg0, const struct brw_reg *arg1 ) { + int dst_chan = _mesa_ffs(mask & WRITEMASK_XYZW) - 1; + if (!(mask & WRITEMASK_XYZW)) return; /* Do not emit dead code */ - assert((mask & WRITEMASK_XYZW) == WRITEMASK_X); + assert(is_power_of_two(mask & WRITEMASK_XYZW)); brw_MUL(p, brw_null_reg(), arg0[0], arg1[0]); brw_MAC(p, brw_null_reg(), arg0[1], arg1[1]); brw_MAC(p, brw_null_reg(), arg0[2], arg1[2]); brw_set_saturate(p, (mask & SATURATE) ? 1 : 0); - brw_MAC(p, dst[0], arg0[3], arg1[3]); + brw_MAC(p, dst[dst_chan], arg0[3], arg1[3]); brw_set_saturate(p, 0); } @@ -632,18 +634,19 @@ static void emit_math1( struct brw_compile *p, GLuint mask, const struct brw_reg *arg0 ) { + int dst_chan = _mesa_ffs(mask & WRITEMASK_XYZW) - 1; + if (!(mask & WRITEMASK_XYZW)) return; /* Do not emit dead code */ - //assert((mask & WRITEMASK_XYZW) == WRITEMASK_X || - // function == BRW_MATH_FUNCTION_SINCOS); - + assert(is_power_of_two(mask & WRITEMASK_XYZW)); + brw_MOV(p, brw_message_reg(2), arg0[0]); /* Send two messages to perform all 16 operations: */ brw_math_16(p, - dst[0], + dst[dst_chan], function, (mask & SATURATE) ? BRW_MATH_SATURATE_SATURATE : BRW_MATH_SATURATE_NONE, 2, @@ -659,10 +662,12 @@ static void emit_math2( struct brw_compile *p, const struct brw_reg *arg0, const struct brw_reg *arg1) { + int dst_chan = _mesa_ffs(mask & WRITEMASK_XYZW) - 1; + if (!(mask & WRITEMASK_XYZW)) return; /* Do not emit dead code */ - assert((mask & WRITEMASK_XYZW) == WRITEMASK_X); + assert(is_power_of_two(mask & WRITEMASK_XYZW)); brw_push_insn_state(p); @@ -681,7 +686,7 @@ static void emit_math2( struct brw_compile *p, */ brw_set_compression_control(p, BRW_COMPRESSION_NONE); brw_math(p, - dst[0], + dst[dst_chan], function, (mask & SATURATE) ? BRW_MATH_SATURATE_SATURATE : BRW_MATH_SATURATE_NONE, 2, @@ -691,7 +696,7 @@ static void emit_math2( struct brw_compile *p, brw_set_compression_control(p, BRW_COMPRESSION_2NDHALF); brw_math(p, - offset(dst[0],1), + offset(dst[dst_chan],1), function, (mask & SATURATE) ? BRW_MATH_SATURATE_SATURATE : BRW_MATH_SATURATE_NONE, 4, @@ -1194,11 +1199,11 @@ void brw_wm_emit( struct brw_wm_compile *c ) /* Generated instructions for calculating triangle interpolants: */ case WM_PIXELXY: - emit_pixel_xy(p, dst, dst_flags, args[0]); + emit_pixel_xy(p, dst, dst_flags); break; case WM_DELTAXY: - emit_delta_xy(p, dst, dst_flags, args[0], args[1]); + emit_delta_xy(p, dst, dst_flags, args[0]); break; case WM_WPOSXY: @@ -1385,4 +1390,13 @@ void brw_wm_emit( struct brw_wm_compile *c ) inst->dst[i]->hw_reg, inst->dst[i]->spill_slot); } + + if (INTEL_DEBUG & DEBUG_WM) { + int i; + + _mesa_printf("wm-native:\n"); + for (i = 0; i < p->nr_insn; i++) + brw_disasm(stderr, &p->store[i]); + _mesa_printf("\n"); + } } diff --git a/src/mesa/drivers/dri/i965/brw_wm_fp.c b/src/mesa/drivers/dri/i965/brw_wm_fp.c index b9e8dd2e96..5dc076a825 100644 --- a/src/mesa/drivers/dri/i965/brw_wm_fp.c +++ b/src/mesa/drivers/dri/i965/brw_wm_fp.c @@ -226,9 +226,42 @@ static struct prog_instruction * emit_op(struct brw_wm_compile *c, 0, 0, 0, /* tex unit, target, shadow */ src0, src1, src2); } - +/* Many Mesa opcodes produce the same value across all the result channels. + * We'd rather not have to support that splatting in the opcode implementations, + * and brw_wm_pass*.c wants to optimize them out by shuffling references around + * anyway. We can easily get both by emitting the opcode to one channel, and + * then MOVing it to the others, which brw_wm_pass*.c already understands. + */ +static struct prog_instruction *emit_scalar_insn(struct brw_wm_compile *c, + const struct prog_instruction *inst0) +{ + struct prog_instruction *inst; + unsigned int dst_chan; + unsigned int other_channel_mask; + + if (inst0->DstReg.WriteMask == 0) + return NULL; + + dst_chan = _mesa_ffs(inst0->DstReg.WriteMask) - 1; + inst = get_fp_inst(c); + *inst = *inst0; + inst->DstReg.WriteMask = 1 << dst_chan; + + other_channel_mask = inst0->DstReg.WriteMask & ~(1 << dst_chan); + if (other_channel_mask != 0) { + inst = emit_op(c, + OPCODE_MOV, + dst_mask(inst0->DstReg, other_channel_mask), + 0, + src_swizzle1(src_reg_from_dst(inst0->DstReg), dst_chan), + src_undef(), + src_undef()); + } + return inst; +} + /*********************************************************************** * Special instructions for interpolation and other tasks @@ -376,14 +409,6 @@ static void emit_interp( struct brw_wm_compile *c, } break; case FRAG_ATTRIB_FOGC: - /* The FOGC input is really special. When a program uses glFogFragCoord, - * the results returned are supposed to be (f,0,0,1). But for Mesa GLSL, - * the glFrontFacing and glPointCoord values are also stashed in FOGC. - * So, write the interpolated fog value to X, then either 0, 1, or the - * stashed values to Y, Z, W. Note that this means that - * glFogFragCoord.yzw can be wrong in those cases! - */ - /* Interpolate the fog coordinate */ emit_op(c, WM_PINTERP, @@ -393,26 +418,40 @@ static void emit_interp( struct brw_wm_compile *c, deltas, get_pixel_w(c)); - /* Move the front facing value into FOGC.y if it's needed. */ - if (c->fp->program.UsesFrontFacing) { - emit_op(c, - WM_FRONTFACING, - dst_mask(dst, WRITEMASK_Y), - 0, - src_undef(), - src_undef(), - src_undef()); - } else { - emit_op(c, - OPCODE_MOV, - dst_mask(dst, WRITEMASK_Y), - 0, - src_swizzle1(interp, SWIZZLE_ZERO), - src_undef(), - src_undef()); - } + emit_op(c, + OPCODE_MOV, + dst_mask(dst, WRITEMASK_YZW), + 0, + src_swizzle(interp, + SWIZZLE_ZERO, + SWIZZLE_ZERO, + SWIZZLE_ZERO, + SWIZZLE_ONE), + src_undef(), + src_undef()); + break; + + case FRAG_ATTRIB_FACE: + /* XXX review/test this case */ + emit_op(c, + WM_FRONTFACING, + dst_mask(dst, WRITEMASK_X), + 0, + src_undef(), + src_undef(), + src_undef()); + break; + + case FRAG_ATTRIB_PNTC: + /* XXX review/test this case */ + emit_op(c, + WM_PINTERP, + dst_mask(dst, WRITEMASK_XY), + 0, + interp, + deltas, + get_pixel_w(c)); - /* Should do the PointCoord thing here. */ emit_op(c, OPCODE_MOV, dst_mask(dst, WRITEMASK_ZW), @@ -425,6 +464,7 @@ static void emit_interp( struct brw_wm_compile *c, src_undef(), src_undef()); break; + default: emit_op(c, WM_PINTERP, @@ -683,7 +723,7 @@ static void precalc_tex( struct brw_wm_compile *c, /* tmp0 = 1 / tmp1 */ emit_op(c, OPCODE_RCP, - tmp0, + dst_mask(tmp0, WRITEMASK_X), 0, tmp1src, src_undef(), @@ -694,7 +734,7 @@ static void precalc_tex( struct brw_wm_compile *c, tmpcoord, 0, src0, - tmp0src, + src_swizzle1(tmp0src, SWIZZLE_X), src_undef()); release_temp(c, tmp0); @@ -717,7 +757,11 @@ static void precalc_tex( struct brw_wm_compile *c, tmpcoord, 0, inst->SrcReg[0], - scale, + src_swizzle(scale, + SWIZZLE_X, + SWIZZLE_Y, + SWIZZLE_ONE, + SWIZZLE_ONE), src_undef()); coord = src_reg_from_dst(tmpcoord); @@ -1134,9 +1178,11 @@ void brw_wm_pass_fp( struct brw_wm_compile *c ) break; case OPCODE_PRINT: break; - default: - emit_insn(c, inst); + if (brw_wm_is_scalar_result(inst->Opcode)) + emit_scalar_insn(c, inst); + else + emit_insn(c, inst); break; } } diff --git a/src/mesa/drivers/dri/i965/brw_wm_glsl.c b/src/mesa/drivers/dri/i965/brw_wm_glsl.c index 85a4237d5a..a5b18ec7d7 100644 --- a/src/mesa/drivers/dri/i965/brw_wm_glsl.c +++ b/src/mesa/drivers/dri/i965/brw_wm_glsl.c @@ -10,6 +10,9 @@ enum _subroutine { SUB_NOISE1, SUB_NOISE2, SUB_NOISE3, SUB_NOISE4 }; +static struct brw_reg get_dst_reg(struct brw_wm_compile *c, + const struct prog_instruction *inst, + GLuint component); /** * Determine if the given fragment program uses GLSL features such @@ -22,6 +25,7 @@ GLboolean brw_wm_is_glsl(const struct gl_fragment_program *fp) for (i = 0; i < fp->Base.NumInstructions; i++) { const struct prog_instruction *inst = &fp->Base.Instructions[i]; switch (inst->Opcode) { + case OPCODE_ARL: case OPCODE_IF: case OPCODE_ENDIF: case OPCODE_CAL: @@ -130,19 +134,6 @@ static void set_reg(struct brw_wm_compile *c, int file, int index, c->wm_regs[file][index][component].inited = GL_TRUE; } -/** - * Examine instruction's write mask to find index of first component - * enabled for writing. - */ -static int get_scalar_dst_index(const struct prog_instruction *inst) -{ - int i; - for (i = 0; i < 4; i++) - if (inst->DstReg.WriteMask & (1<<i)) - break; - return i; -} - static struct brw_reg alloc_tmp(struct brw_wm_compile *c) { struct brw_reg reg; @@ -402,6 +393,27 @@ static void prealloc_reg(struct brw_wm_compile *c) prealloc_grf(c, 126); prealloc_grf(c, 127); + for (i = 0; i < c->nr_fp_insns; i++) { + const struct prog_instruction *inst = &c->prog_instructions[i]; + struct brw_reg dst[4]; + + switch (inst->Opcode) { + case OPCODE_TEX: + case OPCODE_TXB: + /* Allocate the channels of texture results contiguously, + * since they are written out that way by the sampler unit. + */ + for (j = 0; j < 4; j++) { + dst[j] = get_dst_reg(c, inst, j); + if (j != 0) + assert(dst[j].nr == dst[j - 1].nr + 1); + } + break; + default: + break; + } + } + /* An instruction may reference up to three constants. * They'll be found in these registers. * XXX alloc these on demand! @@ -639,23 +651,6 @@ static void invoke_subroutine( struct brw_wm_compile *c, } } -static void emit_abs( struct brw_wm_compile *c, - const struct prog_instruction *inst) -{ - int i; - struct brw_compile *p = &c->func; - brw_set_saturate(p, inst->SaturateMode != SATURATE_OFF); - for (i = 0; i < 4; i++) { - if (inst->DstReg.WriteMask & (1<<i)) { - struct brw_reg src, dst; - dst = get_dst_reg(c, inst, i); - src = get_src_reg(c, inst, 0, i); - brw_MOV(p, dst, brw_abs(src)); - } - } - brw_set_saturate(p, 0); -} - static void emit_trunc( struct brw_wm_compile *c, const struct prog_instruction *inst) { @@ -1031,12 +1026,20 @@ static void emit_dp3(struct brw_wm_compile *c, struct brw_reg src0[3], src1[3], dst; int i; struct brw_compile *p = &c->func; + GLuint mask = inst->DstReg.WriteMask; + int dst_chan = _mesa_ffs(mask & WRITEMASK_XYZW) - 1; + + if (!(mask & WRITEMASK_XYZW)) + return; + + assert(is_power_of_two(mask & WRITEMASK_XYZW)); + for (i = 0; i < 3; i++) { src0[i] = get_src_reg(c, inst, 0, i); src1[i] = get_src_reg_imm(c, inst, 1, i); } - dst = get_dst_reg(c, inst, get_scalar_dst_index(inst)); + dst = get_dst_reg(c, inst, dst_chan); brw_MUL(p, brw_null_reg(), src0[0], src1[0]); brw_MAC(p, brw_null_reg(), src0[1], src1[1]); brw_set_saturate(p, (inst->SaturateMode != SATURATE_OFF) ? 1 : 0); @@ -1050,11 +1053,19 @@ static void emit_dp4(struct brw_wm_compile *c, struct brw_reg src0[4], src1[4], dst; int i; struct brw_compile *p = &c->func; + GLuint mask = inst->DstReg.WriteMask; + int dst_chan = _mesa_ffs(mask & WRITEMASK_XYZW) - 1; + + if (!(mask & WRITEMASK_XYZW)) + return; + + assert(is_power_of_two(mask & WRITEMASK_XYZW)); + for (i = 0; i < 4; i++) { src0[i] = get_src_reg(c, inst, 0, i); src1[i] = get_src_reg_imm(c, inst, 1, i); } - dst = get_dst_reg(c, inst, get_scalar_dst_index(inst)); + dst = get_dst_reg(c, inst, dst_chan); brw_MUL(p, brw_null_reg(), src0[0], src1[0]); brw_MAC(p, brw_null_reg(), src0[1], src1[1]); brw_MAC(p, brw_null_reg(), src0[2], src1[2]); @@ -1069,11 +1080,19 @@ static void emit_dph(struct brw_wm_compile *c, struct brw_reg src0[4], src1[4], dst; int i; struct brw_compile *p = &c->func; + GLuint mask = inst->DstReg.WriteMask; + int dst_chan = _mesa_ffs(mask & WRITEMASK_XYZW) - 1; + + if (!(mask & WRITEMASK_XYZW)) + return; + + assert(is_power_of_two(mask & WRITEMASK_XYZW)); + for (i = 0; i < 4; i++) { src0[i] = get_src_reg(c, inst, 0, i); src1[i] = get_src_reg_imm(c, inst, 1, i); } - dst = get_dst_reg(c, inst, get_scalar_dst_index(inst)); + dst = get_dst_reg(c, inst, dst_chan); brw_MUL(p, brw_null_reg(), src0[0], src1[0]); brw_MAC(p, brw_null_reg(), src0[1], src1[1]); brw_MAC(p, dst, src0[2], src1[2]); @@ -1091,37 +1110,28 @@ static void emit_math1(struct brw_wm_compile *c, const struct prog_instruction *inst, GLuint func) { struct brw_compile *p = &c->func; - struct brw_reg src0, dst, tmp; - const int mark = mark_tmps( c ); - int i; + struct brw_reg src0, dst; + GLuint mask = inst->DstReg.WriteMask; + int dst_chan = _mesa_ffs(mask & WRITEMASK_XYZW) - 1; + + if (!(mask & WRITEMASK_XYZW)) + return; - tmp = alloc_tmp(c); + assert(is_power_of_two(mask & WRITEMASK_XYZW)); /* Get first component of source register */ + dst = get_dst_reg(c, inst, dst_chan); src0 = get_src_reg(c, inst, 0, 0); - /* tmp = func(src0) */ brw_MOV(p, brw_message_reg(2), src0); brw_math(p, - tmp, + dst, func, (inst->SaturateMode != SATURATE_OFF) ? BRW_MATH_SATURATE_SATURATE : BRW_MATH_SATURATE_NONE, 2, brw_null_reg(), BRW_MATH_DATA_VECTOR, BRW_MATH_PRECISION_FULL); - - /*tmp.dw1.bits.swizzle = SWIZZLE_XXXX;*/ - - /* replicate tmp value across enabled dest channels */ - for (i = 0; i < 4; i++) { - if (inst->DstReg.WriteMask & (1 << i)) { - dst = get_dst_reg(c, inst, i); - brw_MOV(p, dst, tmp); - } - } - - release_tmps(c, mark); } static void emit_rcp(struct brw_wm_compile *c, @@ -1192,24 +1202,6 @@ static void emit_arl(struct brw_wm_compile *c, brw_set_saturate(p, 0); } -static void emit_sub(struct brw_wm_compile *c, - const struct prog_instruction *inst) -{ - struct brw_compile *p = &c->func; - struct brw_reg src0, src1, dst; - GLuint mask = inst->DstReg.WriteMask; - int i; - brw_set_saturate(p, (inst->SaturateMode != SATURATE_OFF) ? 1 : 0); - for (i = 0 ; i < 4; i++) { - if (mask & (1<<i)) { - dst = get_dst_reg(c, inst, i); - src0 = get_src_reg(c, inst, 0, i); - src1 = get_src_reg_imm(c, inst, 1, i); - brw_ADD(p, dst, src0, negate(src1)); - } - } - brw_set_saturate(p, 0); -} static void emit_mul(struct brw_wm_compile *c, const struct prog_instruction *inst) @@ -1321,7 +1313,15 @@ static void emit_pow(struct brw_wm_compile *c, { struct brw_compile *p = &c->func; struct brw_reg dst, src0, src1; - dst = get_dst_reg(c, inst, get_scalar_dst_index(inst)); + GLuint mask = inst->DstReg.WriteMask; + int dst_chan = _mesa_ffs(mask & WRITEMASK_XYZW) - 1; + + if (!(mask & WRITEMASK_XYZW)) + return; + + assert(is_power_of_two(mask & WRITEMASK_XYZW)); + + dst = get_dst_reg(c, inst, dst_chan); src0 = get_src_reg_imm(c, inst, 0, 0); src1 = get_src_reg_imm(c, inst, 1, 0); @@ -2828,18 +2828,12 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c) case WM_FRONTFACING: emit_frontfacing(c, inst); break; - case OPCODE_ABS: - emit_abs(c, inst); - break; case OPCODE_ADD: emit_add(c, inst); break; case OPCODE_ARL: emit_arl(c, inst); break; - case OPCODE_SUB: - emit_sub(c, inst); - break; case OPCODE_FRC: emit_frc(c, inst); break; @@ -3032,8 +3026,14 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c) brw_set_predicate_control(p, BRW_PREDICATE_NONE); } post_wm_emit(c); -} + if (INTEL_DEBUG & DEBUG_WM) { + _mesa_printf("wm-native:\n"); + for (i = 0; i < p->nr_insn; i++) + brw_disasm(stderr, &p->store[i]); + _mesa_printf("\n"); + } +} /** * Do GPU code generation for shaders that use GLSL features such as diff --git a/src/mesa/drivers/dri/i965/brw_wm_iz.c b/src/mesa/drivers/dri/i965/brw_wm_iz.c index 8fd067abe7..5e399ac62a 100644 --- a/src/mesa/drivers/dri/i965/brw_wm_iz.c +++ b/src/mesa/drivers/dri/i965/brw_wm_iz.c @@ -122,6 +122,7 @@ const struct { */ void brw_wm_lookup_iz( GLuint line_aa, GLuint lookup, + GLboolean ps_uses_depth, struct brw_wm_prog_key *key ) { GLuint reg = 2; @@ -131,7 +132,7 @@ void brw_wm_lookup_iz( GLuint line_aa, if (lookup & IZ_PS_COMPUTES_DEPTH_BIT) key->computes_depth = 1; - if (wm_iz_table[lookup].sd_present) { + if (wm_iz_table[lookup].sd_present || ps_uses_depth) { key->source_depth_reg = reg; reg += 2; } diff --git a/src/mesa/drivers/dri/i965/brw_wm_pass0.c b/src/mesa/drivers/dri/i965/brw_wm_pass0.c index 92142764f5..6279258339 100644 --- a/src/mesa/drivers/dri/i965/brw_wm_pass0.c +++ b/src/mesa/drivers/dri/i965/brw_wm_pass0.c @@ -257,34 +257,6 @@ static void pass0_set_dst( struct brw_wm_compile *c, } -static void pass0_set_dst_scalar( struct brw_wm_compile *c, - struct brw_wm_instruction *out, - const struct prog_instruction *inst, - GLuint writemask ) -{ - if (writemask) { - const struct prog_dst_register *dst = &inst->DstReg; - GLuint i; - - /* Compute only the first (X) value: - */ - out->writemask = WRITEMASK_X; - out->dst[0] = get_value(c); - - /* Update our tracking register file for all the components in - * writemask: - */ - for (i = 0; i < 4; i++) { - if (writemask & (1<<i)) { - pass0_set_fpreg_value(c, dst->File, dst->Index, i, out->dst[0]); - } - } - } - else - out->writemask = 0; -} - - static const struct brw_wm_ref *get_fp_src_reg_ref( struct brw_wm_compile *c, struct prog_src_register src, GLuint i ) @@ -363,10 +335,7 @@ translate_insn(struct brw_wm_compile *c, /* Dst: */ - if (brw_wm_is_scalar_result(out->opcode)) - pass0_set_dst_scalar(c, out, inst, writemask); - else - pass0_set_dst(c, out, inst, writemask); + pass0_set_dst(c, out, inst, writemask); } diff --git a/src/mesa/drivers/dri/intel/intel_batchbuffer.c b/src/mesa/drivers/dri/intel/intel_batchbuffer.c index 0f87fc46a4..6aa36d10b1 100644 --- a/src/mesa/drivers/dri/intel/intel_batchbuffer.c +++ b/src/mesa/drivers/dri/intel/intel_batchbuffer.c @@ -196,6 +196,16 @@ _intel_batchbuffer_flush(struct intel_batchbuffer *batch, const char *file, struct intel_context *intel = batch->intel; GLuint used = batch->ptr - batch->map; + if (intel->first_post_swapbuffers_batch == NULL) { + intel->first_post_swapbuffers_batch = intel->batch->buf; + drm_intel_bo_reference(intel->first_post_swapbuffers_batch); + } + + if (intel->first_post_swapbuffers_batch == NULL) { + intel->first_post_swapbuffers_batch = intel->batch->buf; + drm_intel_bo_reference(intel->first_post_swapbuffers_batch); + } + if (used == 0) { batch->cliprect_mode = IGNORE_CLIPRECTS; return; diff --git a/src/mesa/drivers/dri/intel/intel_blit.c b/src/mesa/drivers/dri/intel/intel_blit.c index 2e95bd1013..979f202584 100644 --- a/src/mesa/drivers/dri/intel/intel_blit.c +++ b/src/mesa/drivers/dri/intel/intel_blit.c @@ -477,6 +477,8 @@ intelClearWithBlit(GLcontext *ctx, GLbitfield mask) BR13 |= BR13_565; } + assert(irb->region->tiling != I915_TILING_Y); + #ifndef I915 if (irb->region->tiling != I915_TILING_NONE) { CMD |= XY_DST_TILED; @@ -571,6 +573,7 @@ intelEmitImmediateColorExpandBlit(struct intel_context *intel, assert( logic_op - GL_CLEAR >= 0 ); assert( logic_op - GL_CLEAR < 0x10 ); + assert(dst_pitch > 0); if (w < 0 || h < 0) return GL_TRUE; diff --git a/src/mesa/drivers/dri/intel/intel_context.c b/src/mesa/drivers/dri/intel/intel_context.c index 4abb525f78..46f1a7f720 100644 --- a/src/mesa/drivers/dri/intel/intel_context.c +++ b/src/mesa/drivers/dri/intel/intel_context.c @@ -38,6 +38,7 @@ #include "swrast_setup/swrast_setup.h" #include "tnl/tnl.h" #include "drivers/common/driverfuncs.h" +#include "drivers/common/meta.h" #include "i830_dri.h" @@ -513,7 +514,7 @@ intel_flush(GLcontext *ctx, GLboolean needs_mi_flush) * each of N places that do rendering. This has worse performances, * but it is much easier to get correct. */ - if (intel->is_front_buffer_rendering) { + if (!intel->is_front_buffer_rendering) { intel->front_buffer_dirty = GL_FALSE; } } @@ -529,7 +530,27 @@ intelFlush(GLcontext * ctx) static void intel_glFlush(GLcontext *ctx) { + struct intel_context *intel = intel_context(ctx); + intel_flush(ctx, GL_TRUE); + + /* We're using glFlush as an indicator that a frame is done, which is + * what DRI2 does before calling SwapBuffers (and means we should catch + * people doing front-buffer rendering, as well).. + * + * Wait for the swapbuffers before the one we just emitted, so we don't + * get too many swaps outstanding for apps that are GPU-heavy but not + * CPU-heavy. + * + * Unfortunately, we don't have a handle to the batch containing the swap, + * and getting our hands on that doesn't seem worth it, so we just us the + * first batch we emitted after the last swap. + */ + if (intel->first_post_swapbuffers_batch != NULL) { + drm_intel_bo_wait_rendering(intel->first_post_swapbuffers_batch); + drm_intel_bo_unreference(intel->first_post_swapbuffers_batch); + intel->first_post_swapbuffers_batch = NULL; + } } void @@ -692,6 +713,8 @@ intelInitContext(struct intel_context *intel, _swrast_allow_pixel_fog(ctx, GL_FALSE); _swrast_allow_vertex_fog(ctx, GL_TRUE); + _mesa_meta_init(ctx); + intel->hw_stencil = mesaVis->stencilBits && mesaVis->depthBits == 24; intel->hw_stipple = 1; @@ -752,7 +775,7 @@ intelInitContext(struct intel_context *intel, if (intel->use_texture_tiling && !intel->intelScreen->kernel_exec_fencing) { fprintf(stderr, "No kernel support for execution fencing, " - "disabling texture tiling"); + "disabling texture tiling\n"); intel->use_texture_tiling = GL_FALSE; } intel->use_early_z = driQueryOptionb(&intel->optionCache, "early_z"); @@ -795,6 +818,8 @@ intelDestroyContext(__DRIcontextPrivate * driContextPriv) INTEL_FIREVERTICES(intel); + _mesa_meta_free(&intel->ctx); + meta_destroy_metaops(&intel->meta); intel->vtbl.destroy(intel); @@ -814,6 +839,8 @@ intelDestroyContext(__DRIcontextPrivate * driContextPriv) intel->prim.vb = NULL; dri_bo_unreference(intel->prim.vb_bo); intel->prim.vb_bo = NULL; + dri_bo_unreference(intel->first_post_swapbuffers_batch); + intel->first_post_swapbuffers_batch = NULL; if (release_texture_heaps) { /* Nothing is currently done here to free texture heaps; diff --git a/src/mesa/drivers/dri/intel/intel_context.h b/src/mesa/drivers/dri/intel/intel_context.h index 08bea88c95..0d9db5eb1d 100644 --- a/src/mesa/drivers/dri/intel/intel_context.h +++ b/src/mesa/drivers/dri/intel/intel_context.h @@ -80,9 +80,13 @@ extern void intelFallback(struct intel_context *intel, GLuint bit, #define INTEL_MAX_FIXUP 64 + +/** + * intel_context is derived from Mesa's context class: GLcontext. + */ struct intel_context { - GLcontext ctx; /* the parent class */ + GLcontext ctx; /**< base class, must be first field */ struct { @@ -178,6 +182,7 @@ struct intel_context GLboolean ttm; struct intel_batchbuffer *batch; + drm_intel_bo *first_post_swapbuffers_batch; GLboolean no_batch_wrap; unsigned batch_id; @@ -307,7 +312,7 @@ struct intel_context __DRIdrawablePrivate *driReadDrawable; __DRIscreenPrivate *driScreen; intelScreenPrivate *intelScreen; - volatile struct drm_i915_sarea *sarea; + volatile drm_i915_sarea_t *sarea; GLuint lastStamp; diff --git a/src/mesa/drivers/dri/intel/intel_extensions.c b/src/mesa/drivers/dri/intel/intel_extensions.c index 6a68021c69..aa3d704f29 100644 --- a/src/mesa/drivers/dri/intel/intel_extensions.c +++ b/src/mesa/drivers/dri/intel/intel_extensions.c @@ -48,6 +48,7 @@ #define need_GL_EXT_framebuffer_blit #define need_GL_EXT_gpu_program_parameters #define need_GL_EXT_point_parameters +#define need_GL_EXT_provoking_vertex #define need_GL_EXT_secondary_color #define need_GL_EXT_stencil_two_side #define need_GL_APPLE_vertex_array_object @@ -93,6 +94,7 @@ static const struct dri_extension card_extensions[] = { { "GL_EXT_fog_coord", GL_EXT_fog_coord_functions }, { "GL_EXT_gpu_program_parameters", GL_EXT_gpu_program_parameters_functions }, { "GL_EXT_packed_depth_stencil", NULL }, + { "GL_EXT_provoking_vertex", GL_EXT_provoking_vertex_functions }, { "GL_EXT_secondary_color", GL_EXT_secondary_color_functions }, { "GL_EXT_stencil_wrap", NULL }, { "GL_EXT_texture_edge_clamp", NULL }, diff --git a/src/mesa/drivers/dri/intel/intel_fbo.c b/src/mesa/drivers/dri/intel/intel_fbo.c index 666893596e..804c034840 100644 --- a/src/mesa/drivers/dri/intel/intel_fbo.c +++ b/src/mesa/drivers/dri/intel/intel_fbo.c @@ -35,6 +35,7 @@ #include "main/context.h" #include "main/texformat.h" #include "main/texrender.h" +#include "drivers/common/meta.h" #include "intel_context.h" #include "intel_buffers.h" @@ -700,74 +701,6 @@ intel_validate_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb) /** - * Called from glBlitFramebuffer(). - * For now, we're doing an approximation with glCopyPixels(). - * XXX we need to bypass all the per-fragment operations, except scissor. - */ -static void -intel_blit_framebuffer(GLcontext *ctx, - GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, - GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, - GLbitfield mask, GLenum filter) -{ - const GLfloat xZoomSave = ctx->Pixel.ZoomX; - const GLfloat yZoomSave = ctx->Pixel.ZoomY; - GLsizei width, height; - GLfloat xFlip = 1.0F, yFlip = 1.0F; - - if (srcX1 < srcX0) { - GLint tmp = srcX1; - srcX1 = srcX0; - srcX0 = tmp; - xFlip = -1.0F; - } - - if (srcY1 < srcY0) { - GLint tmp = srcY1; - srcY1 = srcY0; - srcY0 = tmp; - yFlip = -1.0F; - } - - width = srcX1 - srcX0; - height = srcY1 - srcY0; - - ctx->Pixel.ZoomX = xFlip * (dstX1 - dstX0) / (srcX1 - srcY0); - ctx->Pixel.ZoomY = yFlip * (dstY1 - dstY0) / (srcY1 - srcY0); - - if (ctx->Pixel.ZoomX < 0.0F) { - dstX0 = MAX2(dstX0, dstX1); - } - else { - dstX0 = MIN2(dstX0, dstX1); - } - - if (ctx->Pixel.ZoomY < 0.0F) { - dstY0 = MAX2(dstY0, dstY1); - } - else { - dstY0 = MIN2(dstY0, dstY1); - } - - if (mask & GL_COLOR_BUFFER_BIT) { - ctx->Driver.CopyPixels(ctx, srcX0, srcY0, width, height, - dstX0, dstY0, GL_COLOR); - } - if (mask & GL_DEPTH_BUFFER_BIT) { - ctx->Driver.CopyPixels(ctx, srcX0, srcY0, width, height, - dstX0, dstY0, GL_DEPTH); - } - if (mask & GL_STENCIL_BUFFER_BIT) { - ctx->Driver.CopyPixels(ctx, srcX0, srcY0, width, height, - dstX0, dstY0, GL_STENCIL); - } - - ctx->Pixel.ZoomX = xZoomSave; - ctx->Pixel.ZoomY = yZoomSave; -} - - -/** * Do one-time context initializations related to GL_EXT_framebuffer_object. * Hook in device driver functions. */ @@ -782,5 +715,5 @@ intel_fbo_init(struct intel_context *intel) intel->ctx.Driver.FinishRenderTexture = intel_finish_render_texture; intel->ctx.Driver.ResizeBuffers = intel_resize_buffers; intel->ctx.Driver.ValidateFramebuffer = intel_validate_framebuffer; - intel->ctx.Driver.BlitFramebuffer = intel_blit_framebuffer; + intel->ctx.Driver.BlitFramebuffer = _mesa_meta_blit_framebuffer; } diff --git a/src/mesa/drivers/dri/intel/intel_pixel_copy.c b/src/mesa/drivers/dri/intel/intel_pixel_copy.c index 5d52335dee..ca796b3655 100644 --- a/src/mesa/drivers/dri/intel/intel_pixel_copy.c +++ b/src/mesa/drivers/dri/intel/intel_pixel_copy.c @@ -31,7 +31,7 @@ #include "main/state.h" #include "main/mtypes.h" #include "main/macros.h" -#include "swrast/swrast.h" +#include "drivers/common/meta.h" #include "intel_screen.h" #include "intel_context.h" @@ -97,162 +97,6 @@ intel_check_copypixel_blit_fragment_ops(GLcontext * ctx) ctx->Color.BlendEnabled); } -#ifdef I915 -/* Doesn't work for overlapping regions. Could do a double copy or - * just fallback. - */ -static GLboolean -do_texture_copypixels(GLcontext * ctx, - GLint srcx, GLint srcy, - GLsizei width, GLsizei height, - GLint dstx, GLint dsty, GLenum type) -{ - struct intel_context *intel = intel_context(ctx); - struct intel_region *dst = intel_drawbuf_region(intel); - struct intel_region *src = copypix_src_region(intel, type); - GLenum src_format; - GLenum src_type; - - DBG("%s %d,%d %dx%d --> %d,%d\n", __FUNCTION__, - srcx, srcy, width, height, dstx, dsty); - - if (!src || !dst || type != GL_COLOR) - return GL_FALSE; - - if (ctx->_ImageTransferState) { - if (INTEL_DEBUG & DEBUG_PIXEL) - fprintf(stderr, "%s: check_color failed\n", __FUNCTION__); - return GL_FALSE; - } - - /* Can't handle overlapping regions. Don't have sufficient control - * over rasterization to pull it off in-place. Punt on these for - * now. - * - * XXX: do a copy to a temporary. - */ - if (src->buffer == dst->buffer) { - drm_clip_rect_t srcbox; - drm_clip_rect_t dstbox; - drm_clip_rect_t tmp; - - srcbox.x1 = srcx; - srcbox.y1 = srcy; - srcbox.x2 = srcx + width; - srcbox.y2 = srcy + height; - - if (ctx->Pixel.ZoomX > 0) { - dstbox.x1 = dstx; - dstbox.x2 = dstx + width * ctx->Pixel.ZoomX; - } else { - dstbox.x1 = dstx + width * ctx->Pixel.ZoomX; - dstbox.x2 = dstx; - } - if (ctx->Pixel.ZoomY > 0) { - dstbox.y1 = dsty; - dstbox.y2 = dsty + height * ctx->Pixel.ZoomY; - } else { - dstbox.y1 = dsty + height * ctx->Pixel.ZoomY; - dstbox.y2 = dsty; - } - - DBG("src %d,%d %d,%d\n", srcbox.x1, srcbox.y1, srcbox.x2, srcbox.y2); - DBG("dst %d,%d %d,%d (%dx%d) (%f,%f)\n", dstbox.x1, dstbox.y1, dstbox.x2, dstbox.y2, - width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY); - - if (intel_intersect_cliprects(&tmp, &srcbox, &dstbox)) { - DBG("%s: regions overlap\n", __FUNCTION__); - return GL_FALSE; - } - } - - intelFlush(&intel->ctx); - - intel->vtbl.install_meta_state(intel); - - /* Is this true? Also will need to turn depth testing on according - * to state: - */ - intel->vtbl.meta_no_stencil_write(intel); - intel->vtbl.meta_no_depth_write(intel); - - /* Set the 3d engine to draw into the destination region: - */ - intel->vtbl.meta_draw_region(intel, dst, intel->depth_region); - - intel->vtbl.meta_import_pixel_state(intel); - - if (src->cpp == 2) { - src_format = GL_RGB; - src_type = GL_UNSIGNED_SHORT_5_6_5; - } - else { - src_format = GL_BGRA; - src_type = GL_UNSIGNED_BYTE; - } - - /* Set the frontbuffer up as a large rectangular texture. - */ - if (!intel->vtbl.meta_tex_rect_source(intel, src->buffer, 0, - src->pitch, - src->height, src_format, src_type)) { - intel->vtbl.leave_meta_state(intel); - return GL_FALSE; - } - - - intel->vtbl.meta_texture_blend_replace(intel); - - LOCK_HARDWARE(intel); - - if (intel->driDrawable->numClipRects) { - __DRIdrawablePrivate *dPriv = intel->driDrawable; - - - srcy = dPriv->h - srcy - height; /* convert from gl to hardware coords */ - - srcx += dPriv->x; - srcy += dPriv->y; - - /* Clip against the source region. This is the only source - * clipping we do. XXX: Just set the texcord wrap mode to clamp - * or similar. - * - */ - if (0) { - GLint orig_x = srcx; - GLint orig_y = srcy; - - if (!_mesa_clip_to_region(0, 0, src->pitch, src->height, - &srcx, &srcy, &width, &height)) - goto out; - - dstx += srcx - orig_x; - dsty += (srcy - orig_y) * ctx->Pixel.ZoomY; - } - - /* Just use the regular cliprect mechanism... Does this need to - * even hold the lock??? - */ - intel->vtbl.meta_draw_quad(intel, - dstx, - dstx + width * ctx->Pixel.ZoomX, - dPriv->h - (dsty + height * ctx->Pixel.ZoomY), - dPriv->h - (dsty), 0, /* XXX: what z value? */ - 0x00ff00ff, - srcx, srcx + width, srcy, srcy + height); - - out: - intel->vtbl.leave_meta_state(intel); - intel_batchbuffer_emit_mi_flush(intel->batch); - } - UNLOCK_HARDWARE(intel); - - DBG("%s: success\n", __FUNCTION__); - return GL_TRUE; -} -#endif /* I915 */ - /** * CopyPixels with the blitter. Don't support zooming, pixel transfer, etc. @@ -400,12 +244,5 @@ intelCopyPixels(GLcontext * ctx, if (do_blit_copypixels(ctx, srcx, srcy, width, height, destx, desty, type)) return; -#ifdef I915 - if (do_texture_copypixels(ctx, srcx, srcy, width, height, destx, desty, type)) - return; -#endif - - DBG("fallback to _swrast_CopyPixels\n"); - - _swrast_CopyPixels(ctx, srcx, srcy, width, height, destx, desty, type); + _mesa_meta_copy_pixels(ctx, srcx, srcy, width, height, destx, desty, type); } diff --git a/src/mesa/drivers/dri/intel/intel_regions.c b/src/mesa/drivers/dri/intel/intel_regions.c index 7525cd9c4d..497f796764 100644 --- a/src/mesa/drivers/dri/intel/intel_regions.c +++ b/src/mesa/drivers/dri/intel/intel_regions.c @@ -181,6 +181,11 @@ intel_region_alloc(struct intel_context *intel, dri_bo *buffer; struct intel_region *region; + if (tiling == I915_TILING_X) + height = ALIGN(height, 8); + else if (tiling == I915_TILING_Y) + height = ALIGN(height, 32); + if (expect_accelerated_upload) { buffer = drm_intel_bo_alloc_for_render(intel->bufmgr, "region", pitch * cpp * height, 64); @@ -452,6 +457,7 @@ void intel_region_cow(struct intel_context *intel, struct intel_region *region) { struct intel_buffer_object *pbo = region->pbo; + GLboolean ok; intel_region_release_pbo(intel, region); @@ -463,13 +469,14 @@ intel_region_cow(struct intel_context *intel, struct intel_region *region) */ LOCK_HARDWARE(intel); - assert(intelEmitCopyBlit(intel, - region->cpp, - region->pitch, pbo->buffer, 0, region->tiling, - region->pitch, region->buffer, 0, region->tiling, - 0, 0, 0, 0, - region->pitch, region->height, - GL_COPY)); + ok = intelEmitCopyBlit(intel, + region->cpp, + region->pitch, pbo->buffer, 0, region->tiling, + region->pitch, region->buffer, 0, region->tiling, + 0, 0, 0, 0, + region->pitch, region->height, + GL_COPY); + assert(ok); UNLOCK_HARDWARE(intel); } diff --git a/src/mesa/drivers/dri/intel/intel_screen.c b/src/mesa/drivers/dri/intel/intel_screen.c index 14cc815139..1b8c56e68d 100644 --- a/src/mesa/drivers/dri/intel/intel_screen.c +++ b/src/mesa/drivers/dri/intel/intel_screen.c @@ -69,7 +69,11 @@ PUBLIC const char __driConfigOptions[] = DRI_CONF_DESC_END DRI_CONF_OPT_END - DRI_CONF_TEXTURE_TILING(false) +#ifdef I915 + DRI_CONF_TEXTURE_TILING(false) +#else + DRI_CONF_TEXTURE_TILING(true) +#endif DRI_CONF_OPT_BEGIN(early_z, bool, false) DRI_CONF_DESC(en, "Enable early Z in classic mode (unstable, 945-only).") diff --git a/src/mesa/drivers/dri/intel/intel_span.c b/src/mesa/drivers/dri/intel/intel_span.c index 34b78ebc1a..8df4990880 100644 --- a/src/mesa/drivers/dri/intel/intel_span.c +++ b/src/mesa/drivers/dri/intel/intel_span.c @@ -501,7 +501,7 @@ intel_map_unmap_buffers(struct intel_context *intel, GLboolean map) /** - * Prepare for softare rendering. Map current read/draw framebuffers' + * Prepare for software rendering. Map current read/draw framebuffers' * renderbuffes and all currently bound texture objects. * * Old note: Moved locking out to get reasonable span performance. @@ -526,7 +526,7 @@ intelSpanRenderStart(GLcontext * ctx) } /** - * Called when done softare rendering. Unmap the buffers we mapped in + * Called when done software rendering. Unmap the buffers we mapped in * the above function. */ void diff --git a/src/mesa/drivers/dri/intel/intel_tex_subimage.c b/src/mesa/drivers/dri/intel/intel_tex_subimage.c index 1f27131dac..89037073f8 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_subimage.c +++ b/src/mesa/drivers/dri/intel/intel_tex_subimage.c @@ -44,10 +44,12 @@ intelTexSubimage(GLcontext * ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint width, GLint height, GLint depth, + GLsizei imageSize, GLenum format, GLenum type, const void *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, - struct gl_texture_image *texImage) + struct gl_texture_image *texImage, + GLboolean compressed) { struct intel_context *intel = intel_context(ctx); struct intel_texture_image *intelImage = intel_texture_image(texImage); @@ -59,9 +61,14 @@ intelTexSubimage(GLcontext * ctx, intelFlush(ctx); - pixels = - _mesa_validate_pbo_teximage(ctx, dims, width, height, depth, format, - type, pixels, packing, "glTexSubImage2D"); + if (compressed) + pixels = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, + pixels, packing, + "glCompressedTexImage"); + else + pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, depth, + format, type, pixels, packing, + "glTexSubImage"); if (!pixels) return; @@ -90,15 +97,28 @@ intelTexSubimage(GLcontext * ctx, assert(dstRowStride); - if (!texImage->TexFormat->StoreImage(ctx, dims, texImage->_BaseFormat, - texImage->TexFormat, - texImage->Data, - xoffset, yoffset, zoffset, - dstRowStride, - texImage->ImageOffsets, - width, height, depth, - format, type, pixels, packing)) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "intelTexSubImage"); + if (compressed) { + if (intelImage->mt) { + struct intel_region *dst = intelImage->mt->region; + + _mesa_copy_rect(texImage->Data, dst->cpp, dst->pitch, + xoffset, yoffset / 4, + (width + 3) & ~3, (height + 3) / 4, + pixels, (width + 3) & ~3, 0, 0); + } else + memcpy(texImage->Data, pixels, imageSize); + } + else { + if (!texImage->TexFormat->StoreImage(ctx, dims, texImage->_BaseFormat, + texImage->TexFormat, + texImage->Data, + xoffset, yoffset, zoffset, + dstRowStride, + texImage->ImageOffsets, + width, height, depth, + format, type, pixels, packing)) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "intelTexSubImage"); + } } _mesa_unmap_teximage_pbo(ctx, packing); @@ -132,8 +152,8 @@ intelTexSubImage3D(GLcontext * ctx, intelTexSubimage(ctx, 3, target, level, xoffset, yoffset, zoffset, - width, height, depth, - format, type, pixels, packing, texObj, texImage); + width, height, depth, 0, + format, type, pixels, packing, texObj, texImage, GL_FALSE); } @@ -152,8 +172,8 @@ intelTexSubImage2D(GLcontext * ctx, intelTexSubimage(ctx, 2, target, level, xoffset, yoffset, 0, - width, height, 1, - format, type, pixels, packing, texObj, texImage); + width, height, 1, 0, + format, type, pixels, packing, texObj, texImage, GL_FALSE); } @@ -172,8 +192,8 @@ intelTexSubImage1D(GLcontext * ctx, intelTexSubimage(ctx, 1, target, level, xoffset, 0, 0, - width, 1, 1, - format, type, pixels, packing, texObj, texImage); + width, 1, 1, 0, + format, type, pixels, packing, texObj, texImage, GL_FALSE); } static void @@ -187,8 +207,11 @@ intelCompressedTexSubImage2D(GLcontext * ctx, struct gl_texture_object *texObj, struct gl_texture_image *texImage) { - fprintf(stderr, "stubbed CompressedTexSubImage2D: %dx%d@%dx%d\n", - width, height, xoffset, yoffset); + intelTexSubimage(ctx, 2, + target, level, + xoffset, yoffset, 0, + width, height, 1, imageSize, + format, 0, pixels, &ctx->Unpack, texObj, texImage, GL_TRUE); } diff --git a/src/mesa/drivers/dri/r200/r200_cmdbuf.c b/src/mesa/drivers/dri/r200/r200_cmdbuf.c index d49f4fabe7..5d0f367b38 100644 --- a/src/mesa/drivers/dri/r200/r200_cmdbuf.c +++ b/src/mesa/drivers/dri/r200/r200_cmdbuf.c @@ -107,31 +107,37 @@ void r200SetUpAtomList( r200ContextPtr rmesa ) void r200EmitScissor(r200ContextPtr rmesa) { + unsigned x1, y1, x2, y2; + struct radeon_renderbuffer *rrb; BATCH_LOCALS(&rmesa->radeon); if (!rmesa->radeon.radeonScreen->kernel_mm) { return; } + rrb = radeon_get_colorbuffer(&rmesa->radeon); + if (!rrb || !rrb->bo) + return; + if (rmesa->radeon.state.scissor.enabled) { - BEGIN_BATCH(8); - OUT_BATCH(CP_PACKET0(R200_RE_CNTL, 0)); - OUT_BATCH(R200_SCISSOR_ENABLE | rmesa->hw.set.cmd[SET_RE_CNTL]); - OUT_BATCH(CP_PACKET0(R200_RE_AUX_SCISSOR_CNTL, 0)); - OUT_BATCH(R200_SCISSOR_ENABLE_0); - OUT_BATCH(CP_PACKET0(R200_RE_SCISSOR_TL_0, 0)); - OUT_BATCH((rmesa->radeon.state.scissor.rect.y1 << 16) | - rmesa->radeon.state.scissor.rect.x1); - OUT_BATCH(CP_PACKET0(R200_RE_SCISSOR_BR_0, 0)); - OUT_BATCH(((rmesa->radeon.state.scissor.rect.y2 - 1) << 16) | - (rmesa->radeon.state.scissor.rect.x2 - 1)); - END_BATCH(); + x1 = rmesa->radeon.state.scissor.rect.x1; + y1 = rmesa->radeon.state.scissor.rect.y1; + x2 = rmesa->radeon.state.scissor.rect.x2 - 1; + y2 = rmesa->radeon.state.scissor.rect.y2 - 1; } else { - BEGIN_BATCH(4); - OUT_BATCH(CP_PACKET0(R200_RE_CNTL, 0)); - OUT_BATCH(rmesa->hw.set.cmd[SET_RE_CNTL] & ~R200_SCISSOR_ENABLE); - OUT_BATCH(CP_PACKET0(R200_RE_AUX_SCISSOR_CNTL, 0)); - OUT_BATCH(0); - END_BATCH(); + x1 = 0; + y1 = 0; + x2 = rrb->base.Width - 1; + y2 = rrb->base.Height - 1; } + BEGIN_BATCH(8); + OUT_BATCH(CP_PACKET0(R200_RE_CNTL, 0)); + OUT_BATCH(R200_SCISSOR_ENABLE | rmesa->hw.set.cmd[SET_RE_CNTL]); + OUT_BATCH(CP_PACKET0(R200_RE_AUX_SCISSOR_CNTL, 0)); + OUT_BATCH(0); + OUT_BATCH(CP_PACKET0(R200_RE_TOP_LEFT, 0)); + OUT_BATCH((y1 << 16) | x1); + OUT_BATCH(CP_PACKET0(R200_RE_WIDTH_HEIGHT, 0)); + OUT_BATCH((y2 << 16) | x2); + END_BATCH(); } /* Fire a section of the retained (indexed_verts) buffer as a regular diff --git a/src/mesa/drivers/dri/r200/r200_context.c b/src/mesa/drivers/dri/r200/r200_context.c index 9a92a32079..8cb287de26 100644 --- a/src/mesa/drivers/dri/r200/r200_context.c +++ b/src/mesa/drivers/dri/r200/r200_context.c @@ -500,3 +500,15 @@ GLboolean r200CreateContext( const __GLcontextModes *glVisual, } +void r200DestroyContext( __DRIcontextPrivate *driContextPriv ) +{ + int i; + r200ContextPtr rmesa = (r200ContextPtr)driContextPriv->driverPrivate; + if (rmesa) + { + for ( i = 0 ; i < R200_MAX_TEXTURE_UNITS ; i++ ) { + _math_matrix_dtr( &rmesa->TexGenMatrix[i] ); + } + } + radeonDestroyContext(driContextPriv); +} diff --git a/src/mesa/drivers/dri/r200/r200_state_init.c b/src/mesa/drivers/dri/r200/r200_state_init.c index bc871d9904..78ad5baebb 100644 --- a/src/mesa/drivers/dri/r200/r200_state_init.c +++ b/src/mesa/drivers/dri/r200/r200_state_init.c @@ -515,7 +515,7 @@ static void ctx_emit_cs(GLcontext *ctx, struct radeon_state_atom *atom) if (drb) dwords += 6; if (rrb) - dwords += 6; + dwords += 8; if (atom->cmd_size == CTX_STATE_SIZE_NEWDRM) dwords += 4; @@ -546,7 +546,7 @@ static void ctx_emit_cs(GLcontext *ctx, struct radeon_state_atom *atom) OUT_BATCH_RELOC(0, rrb->bo, 0, 0, RADEON_GEM_DOMAIN_VRAM, 0); OUT_BATCH(CP_PACKET0(RADEON_RB3D_COLORPITCH, 0)); - OUT_BATCH(cbpitch); + OUT_BATCH_RELOC(cbpitch, rrb->bo, cbpitch, 0, RADEON_GEM_DOMAIN_VRAM, 0); } if (atom->cmd_size == CTX_STATE_SIZE_NEWDRM) { @@ -563,7 +563,6 @@ static void tex_emit(GLcontext *ctx, struct radeon_state_atom *atom) uint32_t dwords = atom->cmd_size; int i = atom->idx; radeonTexObj *t = r200->state.texture.unit[i].texobj; - radeon_mipmap_level *lvl; if (t && t->mt && !t->image_override) dwords += 2; @@ -591,7 +590,6 @@ static void tex_emit_cs(GLcontext *ctx, struct radeon_state_atom *atom) uint32_t dwords = atom->cmd_size; int i = atom->idx; radeonTexObj *t = r200->state.texture.unit[i].texobj; - radeon_mipmap_level *lvl; int hastexture = 1; if (!r200->state.texture.unit[i].unitneeded) @@ -774,7 +772,7 @@ void r200InitState( r200ContextPtr rmesa ) ALLOC_STATE( afs[1], never, AFS_STATE_SIZE, "AFS/afsinst-1", 1 ); } - for (i = 0; i < 5; i++) + for (i = 0; i < 6; i++) if (rmesa->radeon.radeonScreen->kernel_mm) rmesa->hw.tex[i].emit = tex_emit_cs; else @@ -786,7 +784,7 @@ void r200InitState( r200ContextPtr rmesa ) ALLOC_STATE( cube[3], tex_cube, CUBE_STATE_SIZE, "CUBE/tex-3", 3 ); ALLOC_STATE( cube[4], tex_cube, CUBE_STATE_SIZE, "CUBE/tex-4", 4 ); ALLOC_STATE( cube[5], tex_cube, CUBE_STATE_SIZE, "CUBE/tex-5", 5 ); - for (i = 0; i < 5; i++) + for (i = 0; i < 6; i++) if (rmesa->radeon.radeonScreen->kernel_mm) rmesa->hw.cube[i].emit = cube_emit_cs; else diff --git a/src/mesa/drivers/dri/r300/r300_cmdbuf.c b/src/mesa/drivers/dri/r300/r300_cmdbuf.c index 7eb11aaf27..bd46f9acf2 100644 --- a/src/mesa/drivers/dri/r300/r300_cmdbuf.c +++ b/src/mesa/drivers/dri/r300/r300_cmdbuf.c @@ -177,14 +177,17 @@ static void emit_tex_offsets(GLcontext *ctx, struct radeon_state_atom * atom) } else if (!t) { /* Texture unit hasn't a texture bound. * We assign the current color buffer as a fakery to make - * KIL work. */ - struct radeon_renderbuffer *rrb = radeon_get_colorbuffer(&r300->radeon); - if (rrb && rrb->bo) { - BEGIN_BATCH_NO_AUTOSTATE(4); - OUT_BATCH_REGSEQ(R300_TX_OFFSET_0 + (i * 4), 1); - OUT_BATCH_RELOC(0, rrb->bo, 0, - RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0); - END_BATCH(); + * KIL work on KMS (without it, the CS checker will complain). + */ + if (r300->radeon.radeonScreen->kernel_mm) { + struct radeon_renderbuffer *rrb = radeon_get_colorbuffer(&r300->radeon); + if (rrb && rrb->bo) { + BEGIN_BATCH_NO_AUTOSTATE(4); + OUT_BATCH_REGSEQ(R300_TX_OFFSET_0 + (i * 4), 1); + OUT_BATCH_RELOC(0, rrb->bo, 0, + RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0); + END_BATCH(); + } } } else { /* override cases */ if (t->bo) { diff --git a/src/mesa/drivers/dri/r300/r300_draw.c b/src/mesa/drivers/dri/r300/r300_draw.c index cebb9a10d8..ab2287a5e2 100644 --- a/src/mesa/drivers/dri/r300/r300_draw.c +++ b/src/mesa/drivers/dri/r300/r300_draw.c @@ -604,11 +604,19 @@ static void r300DrawPrims(GLcontext *ctx, const struct _mesa_prim *prim, GLuint nr_prims, const struct _mesa_index_buffer *ib, + GLboolean index_bounds_valid, GLuint min_index, GLuint max_index) { GLboolean retval; + /* This check should get folded into just the places that + * min/max index are really needed. + */ + if (!index_bounds_valid) { + vbo_get_minmax_index(ctx, prim, ib, &min_index, &max_index); + } + if (min_index) { vbo_rebase_prims( ctx, arrays, prim, nr_prims, ib, min_index, max_index, r300DrawPrims ); return; diff --git a/src/mesa/drivers/dri/r600/r600_cmdbuf.c b/src/mesa/drivers/dri/r600/r600_cmdbuf.c index 8debecbab9..dc2fb0144a 100644 --- a/src/mesa/drivers/dri/r600/r600_cmdbuf.c +++ b/src/mesa/drivers/dri/r600/r600_cmdbuf.c @@ -457,6 +457,9 @@ void r600InitCmdBuf(context_t *r600) /* from rcommonInitCmdBuf */ GLuint size; rmesa->hw.max_state_size = 4000; /* rough estimate */ + rmesa->hw.all_dirty = GL_TRUE; + rmesa->hw.is_dirty = GL_TRUE; + /* Initialize command buffer */ size = 256 * driQueryOptioni(&rmesa->optionCache, "command_buffer_size"); diff --git a/src/mesa/drivers/dri/r600/r600_context.c b/src/mesa/drivers/dri/r600/r600_context.c index eacf811282..7009374b0c 100644 --- a/src/mesa/drivers/dri/r600/r600_context.c +++ b/src/mesa/drivers/dri/r600/r600_context.c @@ -395,6 +395,8 @@ r600DestroyContext (__DRIcontextPrivate * driContextPriv) if (context) FREE(context->hw.pStateList); + + radeonDestroyContext(driContextPriv); } diff --git a/src/mesa/drivers/dri/r600/r600_context.h b/src/mesa/drivers/dri/r600/r600_context.h index fbb8164af5..30ddce682c 100644 --- a/src/mesa/drivers/dri/r600/r600_context.h +++ b/src/mesa/drivers/dri/r600/r600_context.h @@ -158,6 +158,17 @@ extern GLboolean r700InitChipObject(context_t *context); extern GLboolean r700SendContextStates(context_t *context); extern GLboolean r700SendViewportState(context_t *context, int id); extern GLboolean r700SendRenderTargetState(context_t *context, int id); +extern GLboolean r700SendTextureState(context_t *context); +extern GLboolean r700SendDepthTargetState(context_t *context); +extern GLboolean r700SendUCPState(context_t *context); +extern GLboolean r700SendFSState(context_t *context); +extern void r700EmitState(GLcontext * ctx); + +extern GLboolean r700SyncSurf(context_t *context, + struct radeon_bo *pbo, + uint32_t read_domain, + uint32_t write_domain, + uint32_t sync_type); extern int r700SetupStreams(GLcontext * ctx); extern void r700SetupVTXConstants(GLcontext * ctx, diff --git a/src/mesa/drivers/dri/r600/r600_texstate.c b/src/mesa/drivers/dri/r600/r600_texstate.c index 4840586858..ee9b64ee43 100644 --- a/src/mesa/drivers/dri/r600/r600_texstate.c +++ b/src/mesa/drivers/dri/r600/r600_texstate.c @@ -568,9 +568,6 @@ static void setup_hardware_state(context_t *rmesa, struct gl_texture_object *tex } } - if (t->image_override && t->bo) - return; - switch (texObj->Target) { case GL_TEXTURE_1D: SETfield(t->SQ_TEX_RESOURCE0, SQ_TEX_DIM_1D, DIM_shift, DIM_mask); @@ -701,7 +698,7 @@ void r600SetTexOffset(__DRIcontext * pDRICtx, GLint texname, struct gl_texture_object *tObj = _mesa_lookup_texture(rmesa->radeon.glCtx, texname); radeonTexObjPtr t = radeon_tex_obj(tObj); - uint32_t pitch_val; + uint32_t pitch_val, size; if (!tObj) return; @@ -711,7 +708,12 @@ void r600SetTexOffset(__DRIcontext * pDRICtx, GLint texname, if (!offset) return; - t->bo = NULL; + size = pitch;//h * w * (depth / 8); + if (t->bo) { + radeon_bo_unref(t->bo); + t->bo = NULL; + } + t->bo = radeon_legacy_bo_alloc_fake(rmesa->radeon.radeonScreen->bom, size, offset); t->override_offset = offset; pitch_val = pitch; switch (depth) { diff --git a/src/mesa/drivers/dri/r600/r700_assembler.c b/src/mesa/drivers/dri/r600/r700_assembler.c index 0abf112b55..eaacd06113 100644 --- a/src/mesa/drivers/dri/r600/r700_assembler.c +++ b/src/mesa/drivers/dri/r600/r700_assembler.c @@ -3839,6 +3839,9 @@ GLboolean Process_Export(r700_AssemblerBase* pAsm, if (export_count == 1) { ucWriteMask = pAsm->pucOutMask[starting_register_number - pAsm->starting_export_register_number]; + /* exports Z as a float into Red channel */ + if (GL_TRUE == is_depth_export) + ucWriteMask = 0x1; if( (ucWriteMask & 0x1) != 0) { diff --git a/src/mesa/drivers/dri/r600/r700_chip.c b/src/mesa/drivers/dri/r600/r700_chip.c index 78779e841d..0fb355a0b6 100644 --- a/src/mesa/drivers/dri/r600/r700_chip.c +++ b/src/mesa/drivers/dri/r600/r700_chip.c @@ -138,6 +138,19 @@ GLboolean r700InitChipObject(context_t *context) LINK_STATES(CB_CLRCMP_MSK); LINK_STATES(CB_BLEND_CONTROL); + //DB + LINK_STATES(DB_HTILE_DATA_BASE); + LINK_STATES(DB_STENCIL_CLEAR); + LINK_STATES(DB_DEPTH_CLEAR); + LINK_STATES(DB_STENCILREFMASK); + LINK_STATES(DB_STENCILREFMASK_BF); + LINK_STATES(DB_DEPTH_CONTROL); + LINK_STATES(DB_SHADER_CONTROL); + LINK_STATES(DB_RENDER_CONTROL); + LINK_STATES(DB_RENDER_OVERRIDE); + LINK_STATES(DB_HTILE_SURFACE); + LINK_STATES(DB_ALPHA_TO_MASK); + // SX LINK_STATES(SX_MISC); LINK_STATES(SX_ALPHA_TEST_CONTROL); @@ -322,7 +335,7 @@ void r700SetupVTXConstants(GLcontext * ctx, unsigned int uSQ_VTX_CONSTANT_WORD6_0 = 0; if (!paos->bo) - return GL_FALSE; + return; if ((context->radeon.radeonScreen->chip_family == CHIP_FAMILY_RV610) || (context->radeon.radeonScreen->chip_family == CHIP_FAMILY_RV620) || @@ -474,6 +487,18 @@ GLboolean r700SendContextStates(context_t *context) for(ui = 0; ui < R700_MAX_SHADER_EXPORTS; ui++) R600_OUT_BATCH(r700->SPI_PS_INPUT_CNTL[ui].u32All); END_BATCH(); + + if (context->radeon.radeonScreen->chip_family > CHIP_FAMILY_R600) { + for (ui = 0; ui < R700_MAX_RENDER_TARGETS; ui++) { + if (r700->render_target[ui].enabled) { + BEGIN_BATCH_NO_AUTOSTATE(3); + R600_OUT_BATCH_REGVAL(CB_BLEND0_CONTROL + (4 * ui), + r700->render_target[ui].CB_BLEND0_CONTROL.u32All); + END_BATCH(); + } + } + } + COMMIT_BATCH(); return GL_TRUE; @@ -491,38 +516,25 @@ GLboolean r700SendDepthTargetState(context_t *context) return GL_FALSE; } - BEGIN_BATCH_NO_AUTOSTATE(9); + BEGIN_BATCH_NO_AUTOSTATE(8); R600_OUT_BATCH_REGSEQ(DB_DEPTH_SIZE, 2); R600_OUT_BATCH(r700->DB_DEPTH_SIZE.u32All); R600_OUT_BATCH(r700->DB_DEPTH_VIEW.u32All); - R600_OUT_BATCH_REGSEQ(DB_DEPTH_BASE, 3); + R600_OUT_BATCH_REGSEQ(DB_DEPTH_BASE, 2); R600_OUT_BATCH_RELOC(r700->DB_DEPTH_BASE.u32All, rrb->bo, r700->DB_DEPTH_BASE.u32All, 0, RADEON_GEM_DOMAIN_VRAM, 0); R600_OUT_BATCH(r700->DB_DEPTH_INFO.u32All); - R600_OUT_BATCH(r700->DB_HTILE_DATA_BASE.u32All); END_BATCH(); - BEGIN_BATCH_NO_AUTOSTATE(24); - R600_OUT_BATCH_REGSEQ(DB_STENCIL_CLEAR, 2); - R600_OUT_BATCH(r700->DB_STENCIL_CLEAR.u32All); - R600_OUT_BATCH(r700->DB_DEPTH_CLEAR.u32All); - - R600_OUT_BATCH_REGSEQ(DB_STENCILREFMASK, 2); - R600_OUT_BATCH(r700->DB_STENCILREFMASK.u32All); - R600_OUT_BATCH(r700->DB_STENCILREFMASK_BF.u32All); - - R600_OUT_BATCH_REGVAL(DB_DEPTH_CONTROL, r700->DB_DEPTH_CONTROL.u32All); - R600_OUT_BATCH_REGVAL(DB_SHADER_CONTROL, r700->DB_SHADER_CONTROL.u32All); - - R600_OUT_BATCH_REGSEQ(DB_RENDER_CONTROL, 2); - R600_OUT_BATCH(r700->DB_RENDER_CONTROL.u32All); - R600_OUT_BATCH(r700->DB_RENDER_OVERRIDE.u32All); - - R600_OUT_BATCH_REGVAL(DB_HTILE_SURFACE, r700->DB_HTILE_SURFACE.u32All); - R600_OUT_BATCH_REGVAL(DB_ALPHA_TO_MASK, r700->DB_ALPHA_TO_MASK.u32All); - END_BATCH(); + if ((context->radeon.radeonScreen->chip_family > CHIP_FAMILY_R600) && + (context->radeon.radeonScreen->chip_family < CHIP_FAMILY_RV770)) { + BEGIN_BATCH_NO_AUTOSTATE(2); + R600_OUT_BATCH(CP_PACKET3(R600_IT_SURFACE_BASE_UPDATE, 0)); + R600_OUT_BATCH(1 << 0); + END_BATCH(); + } COMMIT_BATCH(); @@ -575,12 +587,6 @@ GLboolean r700SendRenderTargetState(context_t *context, int id) R600_OUT_BATCH_REGVAL(CB_COLOR0_MASK + (4 * id), r700->render_target[id].CB_COLOR0_MASK.u32All); END_BATCH(); - if (context->radeon.radeonScreen->chip_family > CHIP_FAMILY_R600) { - BEGIN_BATCH_NO_AUTOSTATE(3); - R600_OUT_BATCH_REGVAL(CB_BLEND0_CONTROL + (4 * id), r700->render_target[id].CB_BLEND0_CONTROL.u32All); - END_BATCH(); - } - COMMIT_BATCH(); r700SyncSurf(context, rrb->bo, 0, RADEON_GEM_DOMAIN_VRAM, diff --git a/src/mesa/drivers/dri/r600/r700_clear.c b/src/mesa/drivers/dri/r600/r700_clear.c index e84be38622..05d4af331e 100644 --- a/src/mesa/drivers/dri/r600/r700_clear.c +++ b/src/mesa/drivers/dri/r600/r700_clear.c @@ -31,6 +31,7 @@ #include "main/imports.h" #include "main/mtypes.h" #include "main/enums.h" +#include "swrast/swrast.h" #include "radeon_lock.h" #include "r600_context.h" diff --git a/src/mesa/drivers/dri/r600/r700_fragprog.c b/src/mesa/drivers/dri/r600/r700_fragprog.c index 4ac37f1dfe..6249bde6f1 100644 --- a/src/mesa/drivers/dri/r600/r700_fragprog.c +++ b/src/mesa/drivers/dri/r600/r700_fragprog.c @@ -55,6 +55,12 @@ void Map_Fragment_Program(r700_AssemblerBase *pAsm, //Input mapping : mesa_fp->Base.InputsRead set the flag, set in //The flags parsed in parse_attrib_binding. FRAG_ATTRIB_COLx, FRAG_ATTRIB_TEXx, ... //MUST match order in Map_Vertex_Output + unBit = 1 << FRAG_ATTRIB_WPOS; + if(mesa_fp->Base.InputsRead & unBit) + { + pAsm->uiFP_AttributeMap[FRAG_ATTRIB_WPOS] = pAsm->number_used_registers++; + } + unBit = 1 << FRAG_ATTRIB_COL0; if(mesa_fp->Base.InputsRead & unBit) { @@ -112,6 +118,7 @@ void Map_Fragment_Program(r700_AssemblerBase *pAsm, pAsm->uiFP_OutputMap[FRAG_RESULT_DEPTH] = pAsm->number_used_registers++; pAsm->number_of_exports++; pAsm->number_of_colorandz_exports++; + pAsm->pR700Shader->depthIsExported = 1; } pAsm->pucOutMask = (unsigned char*) MALLOC(pAsm->number_of_exports); @@ -263,11 +270,13 @@ GLboolean r700SetupFragmentProgram(GLcontext * ctx) { context_t *context = R700_CONTEXT(ctx); R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw); - + BATCH_LOCALS(&context->radeon); struct r700_fragment_program *fp = (struct r700_fragment_program *) (ctx->FragmentProgram._Current); r700_AssemblerBase *pAsm = &(fp->r700AsmCode); struct gl_fragment_program *mesa_fp = &(fp->mesa_program); + struct gl_program_parameter_list *paramList; + unsigned int unNumParamData; unsigned int ui, i; unsigned int unNumOfReg; unsigned int unBit; @@ -302,6 +311,16 @@ GLboolean r700SetupFragmentProgram(GLcontext * ctx) ui = (r700->SPI_PS_IN_CONTROL_0.u32All & NUM_INTERP_mask) / (1 << NUM_INTERP_shift); + /* PS uses fragment.position */ + if (mesa_fp->Base.InputsRead & (1 << FRAG_ATTRIB_WPOS)) + { + ui += 1; + SETfield(r700->SPI_PS_IN_CONTROL_0.u32All, ui, NUM_INTERP_shift, NUM_INTERP_mask); + SETfield(r700->SPI_PS_IN_CONTROL_0.u32All, CENTERS_ONLY, BARYC_SAMPLE_CNTL_shift, BARYC_SAMPLE_CNTL_mask); + SETbit(r700->SPI_PS_IN_CONTROL_0.u32All, POSITION_ENA_bit); + SETbit(r700->SPI_INPUT_Z.u32All, PROVIDE_Z_TO_SPI_bit); + } + ui = (unNumOfReg < ui) ? ui : unNumOfReg; SETfield(r700->ps.SQ_PGM_RESOURCES_PS.u32All, ui, NUM_GPRS_shift, NUM_GPRS_mask); @@ -335,7 +354,49 @@ GLboolean r700SetupFragmentProgram(GLcontext * ctx) CLEARbit(r700->DB_SHADER_CONTROL.u32All, Z_EXPORT_ENABLE_bit); } + /* sent out shader constants. */ + paramList = fp->mesa_program.Base.Parameters; + + if(NULL != paramList) + { + _mesa_load_state_parameters(ctx, paramList); + + unNumParamData = paramList->NumParameters * 4; + + BEGIN_BATCH_NO_AUTOSTATE(2 + unNumParamData); + + R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_ALU_CONST, unNumParamData)); + + /* assembler map const from very beginning. */ + R600_OUT_BATCH(SQ_ALU_CONSTANT_PS_OFFSET * 4); + + unNumParamData = paramList->NumParameters; + + for(ui=0; ui<unNumParamData; ui++) + { + R600_OUT_BATCH(*((unsigned int*)&(paramList->ParameterValues[ui][0]))); + R600_OUT_BATCH(*((unsigned int*)&(paramList->ParameterValues[ui][1]))); + R600_OUT_BATCH(*((unsigned int*)&(paramList->ParameterValues[ui][2]))); + R600_OUT_BATCH(*((unsigned int*)&(paramList->ParameterValues[ui][3]))); + } + END_BATCH(); + COMMIT_BATCH(); + } + // emit ps input map + unBit = 1 << FRAG_ATTRIB_WPOS; + if(mesa_fp->Base.InputsRead & unBit) + { + ui = pAsm->uiFP_AttributeMap[FRAG_ATTRIB_WPOS]; + SETbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, SEL_CENTROID_bit); + SETfield(r700->SPI_PS_INPUT_CNTL[ui].u32All, ui, + SEMANTIC_shift, SEMANTIC_mask); + if (r700->SPI_INTERP_CONTROL_0.u32All & FLAT_SHADE_ENA_bit) + SETbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); + else + CLEARbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit); + } + unBit = 1 << FRAG_ATTRIB_COL0; if(mesa_fp->Base.InputsRead & unBit) { @@ -391,45 +452,3 @@ GLboolean r700SetupFragmentProgram(GLcontext * ctx) return GL_TRUE; } -GLboolean r700SendPSConstants(GLcontext * ctx) -{ - context_t *context = R700_CONTEXT(ctx); - BATCH_LOCALS(&context->radeon); - struct r700_fragment_program *fp = (struct r700_fragment_program *) - (ctx->FragmentProgram._Current); - struct gl_program_parameter_list *paramList; - unsigned int unNumParamData; - unsigned int ui; - - /* sent out shader constants. */ - paramList = fp->mesa_program.Base.Parameters; - - if(NULL != paramList) - { - _mesa_load_state_parameters(ctx, paramList); - - unNumParamData = paramList->NumParameters * 4; - - BEGIN_BATCH_NO_AUTOSTATE(2 + unNumParamData); - - R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_ALU_CONST, unNumParamData)); - - /* assembler map const from very beginning. */ - R600_OUT_BATCH(SQ_ALU_CONSTANT_PS_OFFSET * 4); - - unNumParamData = paramList->NumParameters; - - for(ui=0; ui<unNumParamData; ui++) - { - R600_OUT_BATCH(*((unsigned int*)&(paramList->ParameterValues[ui][0]))); - R600_OUT_BATCH(*((unsigned int*)&(paramList->ParameterValues[ui][1]))); - R600_OUT_BATCH(*((unsigned int*)&(paramList->ParameterValues[ui][2]))); - R600_OUT_BATCH(*((unsigned int*)&(paramList->ParameterValues[ui][3]))); - } - END_BATCH(); - COMMIT_BATCH(); - } - - return GL_TRUE; -} - diff --git a/src/mesa/drivers/dri/r600/r700_oglprog.c b/src/mesa/drivers/dri/r600/r700_oglprog.c index 36de143b1a..c49b90c1cc 100644 --- a/src/mesa/drivers/dri/r600/r700_oglprog.c +++ b/src/mesa/drivers/dri/r600/r700_oglprog.c @@ -33,6 +33,7 @@ #include "tnl/tnl.h" #include "r600_context.h" +#include "r600_emit.h" #include "r700_oglprog.h" #include "r700_fragprog.h" @@ -87,7 +88,6 @@ static void r700DeleteProgram(GLcontext * ctx, struct gl_program *prog) { struct r700_vertex_program * vp; struct r700_fragment_program * fp; - context_t *context = R700_CONTEXT(ctx); switch (prog->Target) { diff --git a/src/mesa/drivers/dri/r600/r700_render.c b/src/mesa/drivers/dri/r600/r700_render.c index 2592d7df14..6705dbcf4b 100644 --- a/src/mesa/drivers/dri/r600/r700_render.c +++ b/src/mesa/drivers/dri/r600/r700_render.c @@ -139,6 +139,13 @@ static GLboolean r700SetupShaders(GLcontext * ctx) r600UpdateTextureState(ctx); + r700SendFSState(context); // FIXME just a place holder for now + r700SendPSState(context); + r700SendVSState(context); + + r700SendTextureState(context); + r700SetupStreams(ctx); + return GL_TRUE; } @@ -274,20 +281,15 @@ static void r700RunRenderPrimitive(GLcontext * ctx, int start, int end, int prim void r700EmitState(GLcontext * ctx) { context_t *context = R700_CONTEXT(ctx); + radeonContextPtr radeon = &context->radeon; + + if (radeon->cmdbuf.cs->cdw && !radeon->hw.is_dirty && !radeon->hw.all_dirty) + return; rcommonEnsureCmdBufSpace(&context->radeon, context->radeon.hw.max_state_size, __FUNCTION__); - r700Start3D(context); r700SendSQConfig(context); - r700SendFSState(context); // FIXME just a place holder for now - r700SendPSState(context); - r700SendVSState(context); - r700SendVSConstants(ctx); - r700SendPSConstants(ctx); - - r700SendTextureState(context); - r700SetupStreams(ctx); r700SendUCPState(context); r700SendContextStates(context); @@ -305,13 +307,12 @@ static GLboolean r700RunRender(GLcontext * ctx, TNLcontext *tnl = TNL_CONTEXT(ctx); struct vertex_buffer *vb = &tnl->vb; + r700Start3D(context); + r700UpdateShaders(ctx); r700SetScissor(context); r700SetupShaders(ctx); - r700SetRenderTarget(context, 0); - r700SetDepthTarget(context); - r700EmitState(ctx); /* richard test code */ @@ -327,8 +328,6 @@ static GLboolean r700RunRender(GLcontext * ctx, radeonReleaseArrays(ctx, ~0); - rcommonFlushCmdBuf( &context->radeon, __FUNCTION__ ); - return GL_FALSE; } diff --git a/src/mesa/drivers/dri/r600/r700_state.c b/src/mesa/drivers/dri/r600/r700_state.c index e0a5742591..835b5e18c2 100644 --- a/src/mesa/drivers/dri/r600/r700_state.c +++ b/src/mesa/drivers/dri/r600/r700_state.c @@ -60,6 +60,8 @@ static void r700SetClipPlaneState(GLcontext * ctx, GLenum cap, GLboolean state); static void r700UpdatePolygonMode(GLcontext * ctx); static void r700SetPolygonOffsetState(GLcontext * ctx, GLboolean state); static void r700SetStencilState(GLcontext * ctx, GLboolean state); +static void r700SetRenderTarget(context_t *context, int id); +static void r700SetDepthTarget(context_t *context); void r700SetDefaultStates(context_t *context) //-------------------- { @@ -158,29 +160,16 @@ void r700UpdateViewportOffset(GLcontext * ctx) //------------------ */ void r700UpdateDrawBuffer(GLcontext * ctx) /* TODO */ //--------------------- { -#if 0 /* to be enabled */ - context_t *context = R700_CONTEXT(ctx); + context_t *context = R700_CONTEXT(ctx); - switch (ctx->DrawBuffer->_ColorDrawBufferIndexes[0]) - { - case BUFFER_FRONT_LEFT: - context->target.rt = context->screen->frontBuffer; - break; - case BUFFER_BACK_LEFT: - context->target.rt = context->screen->backBuffer; - break; - default: - memset (&context->target.rt, sizeof(context->target.rt), 0); - } -#endif /* to be enabled */ + r700SetRenderTarget(context, 0); + r700SetDepthTarget(context); } static void r700FetchStateParameter(GLcontext * ctx, const gl_state_index state[STATE_LENGTH], GLfloat * value) { - context_t *context = R700_CONTEXT(ctx); - /* TODO */ } @@ -600,14 +589,46 @@ static void r700BlendFuncSeparate(GLcontext * ctx, /** * Translate LogicOp enums into hardware representation. - * Both use a very logical bit-wise layout, but unfortunately the order - * of bits is reversed. */ static GLuint translate_logicop(GLenum logicop) { - GLuint bits = logicop - GL_CLEAR; - bits = ((bits & 1) << 3) | ((bits & 2) << 1) | ((bits & 4) >> 1) | ((bits & 8) >> 3); - return bits; + switch (logicop) { + case GL_CLEAR: + return 0x00; + case GL_SET: + return 0xff; + case GL_COPY: + return 0xcc; + case GL_COPY_INVERTED: + return 0x33; + case GL_NOOP: + return 0xaa; + case GL_INVERT: + return 0x55; + case GL_AND: + return 0x88; + case GL_NAND: + return 0x77; + case GL_OR: + return 0xee; + case GL_NOR: + return 0x11; + case GL_XOR: + return 0x66; + case GL_EQUIV: + return 0xaa; + case GL_AND_REVERSE: + return 0x44; + case GL_AND_INVERTED: + return 0x22; + case GL_OR_REVERSE: + return 0xdd; + case GL_OR_INVERTED: + return 0xbb; + default: + fprintf(stderr, "unknown blend logic operation %x\n", logicop); + return 0xcc; + } } /** @@ -1327,22 +1348,22 @@ void r700SetScissor(context_t *context) //--------------- r700->viewport[id].enabled = GL_TRUE; } -void r700SetRenderTarget(context_t *context, int id) +static void r700SetRenderTarget(context_t *context, int id) { R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw); struct radeon_renderbuffer *rrb; unsigned int nPitchInPixel; + rrb = radeon_get_colorbuffer(&context->radeon); + if (!rrb || !rrb->bo) { + fprintf(stderr, "no rrb\n"); + return; + } + /* screen/window/view */ SETfield(r700->CB_TARGET_MASK.u32All, 0xF, (4 * id), TARGET0_ENABLE_mask); - rrb = radeon_get_colorbuffer(&context->radeon); - if (!rrb || !rrb->bo) { - fprintf(stderr, "no rrb\n"); - return; - } - /* color buffer */ r700->render_target[id].CB_COLOR0_BASE.u32All = context->radeon.state.color.draw_offset; @@ -1375,39 +1396,22 @@ void r700SetRenderTarget(context_t *context, int id) r700->render_target[id].enabled = GL_TRUE; } -void r700SetDepthTarget(context_t *context) +static void r700SetDepthTarget(context_t *context) { R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw); struct radeon_renderbuffer *rrb; unsigned int nPitchInPixel; + rrb = radeon_get_depthbuffer(&context->radeon); + if (!rrb) + return; + /* depth buf */ r700->DB_DEPTH_SIZE.u32All = 0; r700->DB_DEPTH_BASE.u32All = 0; r700->DB_DEPTH_INFO.u32All = 0; - - r700->DB_DEPTH_CLEAR.u32All = 0x3F800000; - r700->DB_DEPTH_VIEW.u32All = 0; - r700->DB_RENDER_CONTROL.u32All = 0; - SETbit(r700->DB_RENDER_CONTROL.u32All, STENCIL_COMPRESS_DISABLE_bit); - SETbit(r700->DB_RENDER_CONTROL.u32All, DEPTH_COMPRESS_DISABLE_bit); - r700->DB_RENDER_OVERRIDE.u32All = 0; - if (context->radeon.radeonScreen->chip_family < CHIP_FAMILY_RV770) - SETbit(r700->DB_RENDER_OVERRIDE.u32All, FORCE_SHADER_Z_ORDER_bit); - SETfield(r700->DB_RENDER_OVERRIDE.u32All, FORCE_DISABLE, FORCE_HIZ_ENABLE_shift, FORCE_HIZ_ENABLE_mask); - SETfield(r700->DB_RENDER_OVERRIDE.u32All, FORCE_DISABLE, FORCE_HIS_ENABLE0_shift, FORCE_HIS_ENABLE0_mask); - SETfield(r700->DB_RENDER_OVERRIDE.u32All, FORCE_DISABLE, FORCE_HIS_ENABLE1_shift, FORCE_HIS_ENABLE1_mask); - - r700->DB_ALPHA_TO_MASK.u32All = 0; - SETfield(r700->DB_ALPHA_TO_MASK.u32All, 2, ALPHA_TO_MASK_OFFSET0_shift, ALPHA_TO_MASK_OFFSET0_mask); - SETfield(r700->DB_ALPHA_TO_MASK.u32All, 2, ALPHA_TO_MASK_OFFSET1_shift, ALPHA_TO_MASK_OFFSET1_mask); - SETfield(r700->DB_ALPHA_TO_MASK.u32All, 2, ALPHA_TO_MASK_OFFSET2_shift, ALPHA_TO_MASK_OFFSET2_mask); - SETfield(r700->DB_ALPHA_TO_MASK.u32All, 2, ALPHA_TO_MASK_OFFSET3_shift, ALPHA_TO_MASK_OFFSET3_mask); - - rrb = radeon_get_depthbuffer(&context->radeon); - if (!rrb) - return; + r700->DB_DEPTH_VIEW.u32All = 0; nPitchInPixel = rrb->pitch/rrb->cpp; @@ -1757,6 +1761,24 @@ void r700InitState(GLcontext * ctx) //------------------- r700DepthFunc(ctx, ctx->Depth.Func); SETbit(r700->DB_SHADER_CONTROL.u32All, DUAL_EXPORT_ENABLE_bit); + r700->DB_DEPTH_CLEAR.u32All = 0x3F800000; + + r700->DB_RENDER_CONTROL.u32All = 0; + SETbit(r700->DB_RENDER_CONTROL.u32All, STENCIL_COMPRESS_DISABLE_bit); + SETbit(r700->DB_RENDER_CONTROL.u32All, DEPTH_COMPRESS_DISABLE_bit); + r700->DB_RENDER_OVERRIDE.u32All = 0; + if (context->radeon.radeonScreen->chip_family < CHIP_FAMILY_RV770) + SETbit(r700->DB_RENDER_OVERRIDE.u32All, FORCE_SHADER_Z_ORDER_bit); + SETfield(r700->DB_RENDER_OVERRIDE.u32All, FORCE_DISABLE, FORCE_HIZ_ENABLE_shift, FORCE_HIZ_ENABLE_mask); + SETfield(r700->DB_RENDER_OVERRIDE.u32All, FORCE_DISABLE, FORCE_HIS_ENABLE0_shift, FORCE_HIS_ENABLE0_mask); + SETfield(r700->DB_RENDER_OVERRIDE.u32All, FORCE_DISABLE, FORCE_HIS_ENABLE1_shift, FORCE_HIS_ENABLE1_mask); + + r700->DB_ALPHA_TO_MASK.u32All = 0; + SETfield(r700->DB_ALPHA_TO_MASK.u32All, 2, ALPHA_TO_MASK_OFFSET0_shift, ALPHA_TO_MASK_OFFSET0_mask); + SETfield(r700->DB_ALPHA_TO_MASK.u32All, 2, ALPHA_TO_MASK_OFFSET1_shift, ALPHA_TO_MASK_OFFSET1_mask); + SETfield(r700->DB_ALPHA_TO_MASK.u32All, 2, ALPHA_TO_MASK_OFFSET2_shift, ALPHA_TO_MASK_OFFSET2_mask); + SETfield(r700->DB_ALPHA_TO_MASK.u32All, 2, ALPHA_TO_MASK_OFFSET3_shift, ALPHA_TO_MASK_OFFSET3_mask); + /* stencil */ r700Enable(ctx, GL_STENCIL_TEST, ctx->Stencil._Enabled); r700StencilMaskSeparate(ctx, 0, ctx->Stencil.WriteMask[0]); @@ -1822,6 +1844,8 @@ void r700InitState(GLcontext * ctx) //------------------- /* Set up color compare mask */ r700->CB_CLRCMP_MSK.u32All = 0xFFFFFFFF; + context->radeon.hw.all_dirty = GL_TRUE; + } void r700InitStateFuncs(struct dd_function_table *functions) //----------------- diff --git a/src/mesa/drivers/dri/r600/r700_state.h b/src/mesa/drivers/dri/r600/r700_state.h index 23246367db..30eb54e8b0 100644 --- a/src/mesa/drivers/dri/r600/r700_state.h +++ b/src/mesa/drivers/dri/r600/r700_state.h @@ -42,10 +42,8 @@ extern void r700UpdateDrawBuffer (GLcontext * ctx); extern void r700InitState (GLcontext * ctx); extern void r700InitStateFuncs (struct dd_function_table *functions); -extern void r700SetRenderTarget(context_t *context, int id); extern void r700SetDefaultStates(context_t * context); -void r700SetScissor(context_t *context); -void r700SetDepthTarget(context_t *context); +extern void r700SetScissor(context_t *context); #endif /* _R600_SCREEN_H */ diff --git a/src/mesa/drivers/dri/r600/r700_vertprog.c b/src/mesa/drivers/dri/r600/r700_vertprog.c index 1c5c20f66e..31e71cdfa3 100644 --- a/src/mesa/drivers/dri/r600/r700_vertprog.c +++ b/src/mesa/drivers/dri/r600/r700_vertprog.c @@ -336,10 +336,14 @@ GLboolean r700SetupVertexProgram(GLcontext * ctx) { context_t *context = R700_CONTEXT(ctx); R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw); - + BATCH_LOCALS(&context->radeon); struct r700_vertex_program *vp = (struct r700_vertex_program *)ctx->VertexProgram._Current; + struct gl_program_parameter_list *paramList; + unsigned int unNumParamData; + unsigned int ui; + if(GL_FALSE == vp->loaded) { if(vp->r700Shader.bNeedsAssembly == GL_TRUE) @@ -385,21 +389,7 @@ GLboolean r700SetupVertexProgram(GLcontext * ctx) CLEARbit(r700->SPI_PS_IN_CONTROL_0.u32All, LINEAR_GRADIENT_ENA_bit); */ - return GL_TRUE; -} - -GLboolean r700SendVSConstants(GLcontext * ctx) -{ - context_t *context = R700_CONTEXT(ctx); - BATCH_LOCALS(&context->radeon); - struct r700_vertex_program *vp - = (struct r700_vertex_program *)ctx->VertexProgram._Current; - struct gl_program_parameter_list *paramList; - unsigned int unNumParamData; - unsigned int ui; - /* sent out shader constants. */ - paramList = vp->mesa_program.Base.Parameters; if(NULL != paramList) diff --git a/src/mesa/drivers/dri/radeon/radeon_bo_drm.h b/src/mesa/drivers/dri/radeon/radeon_bo_drm.h index 8eeaea1cb2..d52fb017d8 100644 --- a/src/mesa/drivers/dri/radeon/radeon_bo_drm.h +++ b/src/mesa/drivers/dri/radeon/radeon_bo_drm.h @@ -83,6 +83,10 @@ struct radeon_bo_funcs { int (*bo_unmap)(struct radeon_bo *bo); int (*bo_wait)(struct radeon_bo *bo); int (*bo_is_static)(struct radeon_bo *bo); + int (*bo_set_tiling)(struct radeon_bo *bo, uint32_t tiling_flags, + uint32_t pitch); + int (*bo_get_tiling)(struct radeon_bo *bo, uint32_t *tiling_flags, + uint32_t *pitch); }; struct radeon_bo_manager { @@ -187,6 +191,18 @@ static inline int _radeon_bo_wait(struct radeon_bo *bo, return bo->bom->funcs->bo_wait(bo); } +static inline int radeon_bo_set_tiling(struct radeon_bo *bo, + uint32_t tiling_flags, uint32_t pitch) +{ + return bo->bom->funcs->bo_set_tiling(bo, tiling_flags, pitch); +} + +static inline int radeon_bo_get_tiling(struct radeon_bo *bo, + uint32_t *tiling_flags, uint32_t *pitch) +{ + return bo->bom->funcs->bo_get_tiling(bo, tiling_flags, pitch); +} + static inline int radeon_bo_is_static(struct radeon_bo *bo) { if (bo->bom->funcs->bo_is_static) diff --git a/src/mesa/drivers/dri/radeon/radeon_bo_legacy.c b/src/mesa/drivers/dri/radeon/radeon_bo_legacy.c index 992eb4611b..d6d22cb4c3 100644 --- a/src/mesa/drivers/dri/radeon/radeon_bo_legacy.c +++ b/src/mesa/drivers/dri/radeon/radeon_bo_legacy.c @@ -577,6 +577,8 @@ static struct radeon_bo_funcs bo_legacy_funcs = { bo_unmap, NULL, bo_is_static, + NULL, + NULL, }; static int bo_vram_validate(struct radeon_bo *bo, @@ -622,12 +624,34 @@ static int bo_vram_validate(struct radeon_bo *bo, if (bo_legacy->dirty || bo_legacy->tobj->base.dirty_images[0]) { if (IS_R600_CLASS(boml->screen)) { - char *src = bo_legacy->ptr; - char *dst = (char *) boml->screen->driScreen->pFB + - (bo_legacy->offset - boml->fb_location); + drm_radeon_texture_t tex; + drm_radeon_tex_image_t tmp; + int ret; - /* FIXME: alignment, pitch, etc. */ - memcpy(dst, src, bo->size); + tex.offset = bo_legacy->offset; + tex.image = &tmp; + assert(!(tex.offset & 1023)); + + tmp.x = 0; + tmp.y = 0; + tmp.width = bo->size; + tmp.height = 1; + tmp.data = bo_legacy->ptr; + tex.format = RADEON_TXFORMAT_ARGB8888; + tex.width = tmp.width; + tex.height = tmp.height; + tex.pitch = bo->size; + do { + ret = drmCommandWriteRead(bo->bom->fd, + DRM_RADEON_TEXTURE, + &tex, + sizeof(drm_radeon_texture_t)); + if (ret) { + if (RADEON_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "DRM_RADEON_TEXTURE: again!\n"); + usleep(1); + } + } while (ret == -EAGAIN); } else { /* Copy to VRAM using a blit. * All memory is 4K aligned. We're using 1024 pixels wide blits. @@ -904,3 +928,32 @@ unsigned radeon_bo_legacy_relocs_size(struct radeon_bo *bo) return bo->size; } +/* + * Fake up a bo for things like texture image_override. + * bo->offset already includes fb_location + */ +struct radeon_bo *radeon_legacy_bo_alloc_fake(struct radeon_bo_manager *bom, + int size, + uint32_t offset) +{ + struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bom; + struct bo_legacy *bo; + +#ifdef RADEON_DEBUG_BO + bo = bo_allocate(boml, size, 0, RADEON_GEM_DOMAIN_VRAM, 0, "fake bo"); +#else + bo = bo_allocate(boml, size, 0, RADEON_GEM_DOMAIN_VRAM, 0); +#endif /* RADEON_DEBUG_BO */ + if (bo == NULL) + return NULL; + bo->static_bo = 1; + bo->offset = offset; + bo->base.handle = bo->offset; + bo->ptr = boml->screen->driScreen->pFB + (offset - boml->fb_location); + if (bo->base.handle > boml->nhandle) { + boml->nhandle = bo->base.handle + 1; + } + radeon_bo_ref(&(bo->base)); + return &(bo->base); +} + diff --git a/src/mesa/drivers/dri/radeon/radeon_bo_legacy.h b/src/mesa/drivers/dri/radeon/radeon_bo_legacy.h index 0db817cab0..455adebc09 100644 --- a/src/mesa/drivers/dri/radeon/radeon_bo_legacy.h +++ b/src/mesa/drivers/dri/radeon/radeon_bo_legacy.h @@ -42,5 +42,8 @@ struct radeon_bo_manager *radeon_bo_manager_legacy_ctor(struct radeon_screen *sc void radeon_bo_manager_legacy_dtor(struct radeon_bo_manager *bom); void radeon_bo_legacy_texture_age(struct radeon_bo_manager *bom); unsigned radeon_bo_legacy_relocs_size(struct radeon_bo *bo); +struct radeon_bo *radeon_legacy_bo_alloc_fake(struct radeon_bo_manager *bom, + int size, + uint32_t offset); #endif diff --git a/src/mesa/drivers/dri/radeon/radeon_bocs_wrapper.h b/src/mesa/drivers/dri/radeon/radeon_bocs_wrapper.h index e0c70dd9a1..a42870f4a9 100644 --- a/src/mesa/drivers/dri/radeon/radeon_bocs_wrapper.h +++ b/src/mesa/drivers/dri/radeon/radeon_bocs_wrapper.h @@ -15,6 +15,12 @@ #define RADEON_GEM_DOMAIN_GTT 0x2 // GTT or cache flushed #define RADEON_GEM_DOMAIN_VRAM 0x4 // VRAM domain +#define RADEON_TILING_MACRO 0x1 +#define RADEON_TILING_MICRO 0x2 +#define RADEON_TILING_SWAP 0x4 +#define RADEON_TILING_SURFACE 0x8 /* this object requires a surface + * when mapped - i.e. front buffer */ + /* to be used to build locally in mesa with no libdrm bits */ #include "../radeon/radeon_bo_drm.h" #include "../radeon/radeon_cs_drm.h" diff --git a/src/mesa/drivers/dri/radeon/radeon_chipset.h b/src/mesa/drivers/dri/radeon/radeon_chipset.h index 0a6a2df35b..a275c8fb14 100644 --- a/src/mesa/drivers/dri/radeon/radeon_chipset.h +++ b/src/mesa/drivers/dri/radeon/radeon_chipset.h @@ -356,11 +356,14 @@ #define PCI_CHIP_RV770_947A 0x947A #define PCI_CHIP_RV770_947B 0x947B +#define PCI_CHIP_RV730_9480 0x9480 #define PCI_CHIP_RV730_9487 0x9487 +#define PCI_CHIP_RV730_9488 0x9488 #define PCI_CHIP_RV730_9489 0x9489 #define PCI_CHIP_RV730_948F 0x948F #define PCI_CHIP_RV730_9490 0x9490 #define PCI_CHIP_RV730_9491 0x9491 +#define PCI_CHIP_RV730_9495 0x9495 #define PCI_CHIP_RV730_9498 0x9498 #define PCI_CHIP_RV730_949C 0x949C #define PCI_CHIP_RV730_949E 0x949E @@ -374,12 +377,16 @@ #define PCI_CHIP_RV710_9552 0x9552 #define PCI_CHIP_RV710_9553 0x9553 #define PCI_CHIP_RV710_9555 0x9555 +#define PCI_CHIP_RV710_9557 0x9557 #define PCI_CHIP_RV740_94A0 0x94A0 #define PCI_CHIP_RV740_94A1 0x94A1 +#define PCI_CHIP_RV740_94A3 0x94A3 #define PCI_CHIP_RV740_94B1 0x94B1 #define PCI_CHIP_RV740_94B3 0x94B3 +#define PCI_CHIP_RV740_94B4 0x94B4 #define PCI_CHIP_RV740_94B5 0x94B5 +#define PCI_CHIP_RV740_94B9 0x94B9 enum { CHIP_FAMILY_R100, diff --git a/src/mesa/drivers/dri/radeon/radeon_common.c b/src/mesa/drivers/dri/radeon/radeon_common.c index 7f503a9ff7..330c2c8a86 100644 --- a/src/mesa/drivers/dri/radeon/radeon_common.c +++ b/src/mesa/drivers/dri/radeon/radeon_common.c @@ -481,32 +481,6 @@ void radeonCopyBuffer( __DRIdrawablePrivate *dPriv, if (!n) continue; - if (IS_R600_CLASS(rmesa->radeonScreen)) { - int cpp = rmesa->radeonScreen->cpp; - int src_pitch = rmesa->radeonScreen->backPitch * cpp; - int dst_pitch = rmesa->radeonScreen->frontPitch * cpp; - char *src = (char *)rmesa->radeonScreen->driScreen->pFB + rmesa->radeonScreen->backOffset; - char *dst = (char *)rmesa->radeonScreen->driScreen->pFB + rmesa->radeonScreen->frontOffset; - int j; - drm_clip_rect_t *pb = rmesa->sarea->boxes; - - for (j = 0; j < n; j++) { - int x = pb[j].x1; - int y = pb[j].y1; - int w = pb[j].x2 - x; - int h = pb[j].y2 - y; - - src += (y * src_pitch) + (x * cpp); - dst += (y * dst_pitch) + (x * cpp); - - while (h--) { - memcpy(dst, src, w * cpp); - src += src_pitch; - dst += dst_pitch; - } - } - } - ret = drmCommandNone( rmesa->dri.fd, DRM_RADEON_SWAP ); if ( ret ) { @@ -1093,7 +1067,7 @@ void radeonFlush(GLcontext *ctx) * each of N places that do rendering. This has worse performances, * but it is much easier to get correct. */ - if (radeon->is_front_buffer_rendering) { + if (!radeon->is_front_buffer_rendering) { radeon->front_buffer_dirty = GL_FALSE; } } diff --git a/src/mesa/drivers/dri/radeon/radeon_common_context.c b/src/mesa/drivers/dri/radeon/radeon_common_context.c index 2a017b59cf..f71dc1cb23 100644 --- a/src/mesa/drivers/dri/radeon/radeon_common_context.c +++ b/src/mesa/drivers/dri/radeon/radeon_common_context.c @@ -211,6 +211,7 @@ GLboolean radeonInitContext(radeonContextPtr radeon, radeon->dri.screen = sPriv; radeon->dri.hwContext = driContextPriv->hHWContext; radeon->dri.hwLock = &sPriv->pSAREA->lock; + radeon->dri.hwLockCount = 0; radeon->dri.fd = sPriv->fd; radeon->dri.drmMinor = sPriv->drm_version.minor; @@ -294,11 +295,10 @@ void radeonDestroyContext(__DRIcontextPrivate *driContextPriv ) GET_CURRENT_CONTEXT(ctx); radeonContextPtr radeon = (radeonContextPtr) driContextPriv->driverPrivate; radeonContextPtr current = ctx ? RADEON_CONTEXT(ctx) : NULL; - - /* +r6/r7 */ - __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv; +#if RADEON_COMMON && defined(RADEON_COMMON_FOR_R600) /* +r6/r7 */ + __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv; radeonScreenPtr screen = (radeonScreenPtr) (sPriv->private); - /* --------- */ +#endif if (radeon == current) { radeon_firevertices(radeon); @@ -306,16 +306,7 @@ void radeonDestroyContext(__DRIcontextPrivate *driContextPriv ) } assert(radeon); - if (radeon) - { - -#if RADEON_COMMON && defined(RADEON_COMMON_FOR_R600) /* +r6/r7 */ - if (IS_R600_CLASS(screen)) - { - r600DestroyContext(driContextPriv); - } -#endif - + if (radeon) { if (radeon->dma.current) { rcommonFlushCmdBuf( radeon, __FUNCTION__ ); } @@ -762,8 +753,10 @@ radeon_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable) bo = depth_bo; radeon_bo_ref(bo); } else { + uint32_t tiling_flags = 0, pitch = 0; + int ret; #ifdef RADEON_DEBUG_BO - bo = radeon_bo_open(radeon->radeonScreen->bom, + bo = radeon_bo_open(radeon->radeonScreen->bom, buffers[i].name, 0, 0, @@ -784,6 +777,13 @@ radeon_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable) regname, buffers[i].name); } + + ret = radeon_bo_get_tiling(bo, &tiling_flags, &pitch); + if (tiling_flags & RADEON_TILING_MACRO) + bo->flags |= RADEON_BO_FLAGS_MACRO_TILE; + if (tiling_flags & RADEON_TILING_MICRO) + bo->flags |= RADEON_BO_FLAGS_MICRO_TILE; + } if (buffers[i].attachment == __DRI_BUFFER_DEPTH) { diff --git a/src/mesa/drivers/dri/radeon/radeon_common_context.h b/src/mesa/drivers/dri/radeon/radeon_common_context.h index d7e94a6894..f8e1a25c9f 100644 --- a/src/mesa/drivers/dri/radeon/radeon_common_context.h +++ b/src/mesa/drivers/dri/radeon/radeon_common_context.h @@ -365,6 +365,7 @@ struct radeon_dri_mirror { drm_context_t hwContext; drm_hw_lock_t *hwLock; + int hwLockCount; int fd; int drmMinor; }; diff --git a/src/mesa/drivers/dri/radeon/radeon_fbo.c b/src/mesa/drivers/dri/radeon/radeon_fbo.c index f28efa33e9..f05b106aaf 100644 --- a/src/mesa/drivers/dri/radeon/radeon_fbo.c +++ b/src/mesa/drivers/dri/radeon/radeon_fbo.c @@ -291,7 +291,7 @@ radeon_create_renderbuffer(GLenum format, __DRIdrawablePrivate *driDrawPriv) rrb->base.RedBits = 8; rrb->base.GreenBits = 8; rrb->base.BlueBits = 8; - rrb->base.AlphaBits = 8; + rrb->base.AlphaBits = 0; rrb->base.DataType = GL_UNSIGNED_BYTE; break; case GL_RGBA8: @@ -407,7 +407,7 @@ restart: rrb->cpp = 2; rrb->base._ActualFormat = GL_RGB5; rrb->base._BaseFormat = GL_RGB; - rrb->base.DataType = GL_UNSIGNED_SHORT; + rrb->base.DataType = GL_UNSIGNED_BYTE; DBG("Render to RGB5 texture OK\n"); } else if (texImage->TexFormat == &_mesa_texformat_argb1555) { diff --git a/src/mesa/drivers/dri/radeon/radeon_lock.c b/src/mesa/drivers/dri/radeon/radeon_lock.c index 2f0ed1cfce..6294b7e42b 100644 --- a/src/mesa/drivers/dri/radeon/radeon_lock.c +++ b/src/mesa/drivers/dri/radeon/radeon_lock.c @@ -86,8 +86,34 @@ void radeonGetLock(radeonContextPtr rmesa, GLuint flags) rmesa->vtbl.get_lock(rmesa); } - -void radeon_lock_hardware(radeonContextPtr radeon) +#ifndef NDEBUG +struct lock_debug { + const char* function; + const char* file; + int line; +}; + +static struct lock_debug ldebug = {0}; +#endif + +#if 0 +/** TODO: use atomic operations for reference counting **/ +/** gcc 4.2 has builtin functios for this **/ +#define ATOMIC_INC_AND_FETCH(atomic) __sync_add_and_fetch(&atomic, 1) +#define ATOMIC_DEC_AND_FETCH(atomic) __sync_sub_and_fetch(&atomic, 1) +#else +#define ATOMIC_INC_AND_FETCH(atomic) (++atomic) +#define ATOMIC_DEC_AND_FETCH(atomic) (--atomic) +#endif + + +void radeon_lock_hardware(radeonContextPtr radeon +#ifndef NDEBUG + ,const char* function + ,const char* file + ,const int line +#endif + ) { char ret = 0; struct radeon_framebuffer *rfb = NULL; @@ -102,16 +128,39 @@ void radeon_lock_hardware(radeonContextPtr radeon) } if (!radeon->radeonScreen->driScreen->dri2.enabled) { + if (ATOMIC_INC_AND_FETCH(radeon->dri.hwLockCount) > 1) + { +#ifndef NDEBUG + if ( RADEON_DEBUG & DEBUG_SANITY ) + fprintf(stderr, "*** %d times of recursive call to %s ***\n" + "Original call was from %s (file: %s line: %d)\n" + "Now call is coming from %s (file: %s line: %d)\n" + , radeon->dri.hwLockCount, __FUNCTION__ + , ldebug.function, ldebug.file, ldebug.line + , function, file, line + ); +#endif + return; + } DRM_CAS(radeon->dri.hwLock, radeon->dri.hwContext, (DRM_LOCK_HELD | radeon->dri.hwContext), ret ); if (ret) radeonGetLock(radeon, 0); +#ifndef NDEBUG + ldebug.function = function; + ldebug.file = file; + ldebug.line = line; +#endif } } void radeon_unlock_hardware(radeonContextPtr radeon) { if (!radeon->radeonScreen->driScreen->dri2.enabled) { + if (ATOMIC_DEC_AND_FETCH(radeon->dri.hwLockCount) > 0) + { + return; + } DRM_UNLOCK( radeon->dri.fd, radeon->dri.hwLock, radeon->dri.hwContext ); diff --git a/src/mesa/drivers/dri/radeon/radeon_lock.h b/src/mesa/drivers/dri/radeon/radeon_lock.h index 2817709eed..da5a5b4371 100644 --- a/src/mesa/drivers/dri/radeon/radeon_lock.h +++ b/src/mesa/drivers/dri/radeon/radeon_lock.h @@ -48,12 +48,22 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. extern void radeonGetLock(radeonContextPtr rmesa, GLuint flags); -void radeon_lock_hardware(radeonContextPtr rmesa); +void radeon_lock_hardware(radeonContextPtr rmesa +#ifndef NDEBUG + ,const char* function + ,const char* file + ,const int line +#endif + ); void radeon_unlock_hardware(radeonContextPtr rmesa); /* Lock the hardware and validate our state. */ +#ifdef NDEBUG #define LOCK_HARDWARE( rmesa ) radeon_lock_hardware(rmesa) +#else +#define LOCK_HARDWARE( rmesa ) radeon_lock_hardware(rmesa, __FUNCTION__, __FILE__, __LINE__) +#endif #define UNLOCK_HARDWARE( rmesa ) radeon_unlock_hardware(rmesa) #endif diff --git a/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c b/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c index 071a18e7d8..d4082bf68f 100644 --- a/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c +++ b/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c @@ -326,7 +326,8 @@ GLboolean radeon_miptree_matches_image(radeon_mipmap_tree *mt, if (face >= mt->faces || level < mt->firstLevel || level > mt->lastLevel) return GL_FALSE; - if (texImage->IsCompressed != mt->compressed) + if ((!texImage->IsCompressed && mt->compressed) || + (texImage->IsCompressed && !mt->compressed)) return GL_FALSE; if (!texImage->IsCompressed && @@ -366,8 +367,8 @@ GLboolean radeon_miptree_matches_texture(radeon_mipmap_tree *mt, struct gl_textu mt->width0 == firstImage->Width && mt->height0 == firstImage->Height && mt->depth0 == firstImage->Depth && - mt->bpp == firstImage->TexFormat->TexelBytes && - mt->compressed == compressed); + mt->compressed == compressed && + (!mt->compressed ? (mt->bpp == firstImage->TexFormat->TexelBytes) : 1)); } diff --git a/src/mesa/drivers/dri/radeon/radeon_screen.c b/src/mesa/drivers/dri/radeon/radeon_screen.c index 5f1af5b0da..7b759661ca 100644 --- a/src/mesa/drivers/dri/radeon/radeon_screen.c +++ b/src/mesa/drivers/dri/radeon/radeon_screen.c @@ -878,11 +878,14 @@ static int radeon_set_screen_flags(radeonScreenPtr screen, int device_id) screen->chip_flags = RADEON_CHIPSET_TCL; break; + case PCI_CHIP_RV730_9480: case PCI_CHIP_RV730_9487: + case PCI_CHIP_RV730_9488: case PCI_CHIP_RV730_9489: case PCI_CHIP_RV730_948F: case PCI_CHIP_RV730_9490: case PCI_CHIP_RV730_9491: + case PCI_CHIP_RV730_9495: case PCI_CHIP_RV730_9498: case PCI_CHIP_RV730_949C: case PCI_CHIP_RV730_949E: @@ -899,15 +902,19 @@ static int radeon_set_screen_flags(radeonScreenPtr screen, int device_id) case PCI_CHIP_RV710_9552: case PCI_CHIP_RV710_9553: case PCI_CHIP_RV710_9555: + case PCI_CHIP_RV710_9557: screen->chip_family = CHIP_FAMILY_RV710; screen->chip_flags = RADEON_CHIPSET_TCL; break; case PCI_CHIP_RV740_94A0: case PCI_CHIP_RV740_94A1: + case PCI_CHIP_RV740_94A3: case PCI_CHIP_RV740_94B1: case PCI_CHIP_RV740_94B3: + case PCI_CHIP_RV740_94B4: case PCI_CHIP_RV740_94B5: + case PCI_CHIP_RV740_94B9: screen->chip_family = CHIP_FAMILY_RV740; screen->chip_flags = RADEON_CHIPSET_TCL; break; @@ -1579,21 +1586,11 @@ static GLboolean radeonCreateContext(const __GLcontextModes * glVisual, { __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv; radeonScreenPtr screen = (radeonScreenPtr) (sPriv->private); -#if RADEON_COMMON && defined(RADEON_COMMON_FOR_R600) - if (IS_R600_CLASS(screen)) - return r600CreateContext(glVisual, driContextPriv, sharedContextPriv); -#endif - #if RADEON_COMMON && defined(RADEON_COMMON_FOR_R300) if (IS_R300_CLASS(screen)) return r300CreateContext(glVisual, driContextPriv, sharedContextPriv); #endif -#if RADEON_COMMON && defined(RADEON_COMMON_FOR_R200) - if (IS_R200_CLASS(screen)) - return r200CreateContext(glVisual, driContextPriv, sharedContextPriv); -#endif - #if !RADEON_COMMON (void)screen; return r100CreateContext(glVisual, driContextPriv, sharedContextPriv); @@ -1793,8 +1790,16 @@ getSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo ) const struct __DriverAPIRec driDriverAPI = { .InitScreen = radeonInitScreen, .DestroyScreen = radeonDestroyScreen, +#if RADEON_COMMON && defined(RADEON_COMMON_FOR_R200) + .CreateContext = r200CreateContext, + .DestroyContext = r200DestroyContext, +#elif RADEON_COMMON && defined(RADEON_COMMON_FOR_R600) + .CreateContext = r600CreateContext, + .DestroyContext = r600DestroyContext, +#else .CreateContext = radeonCreateContext, .DestroyContext = radeonDestroyContext, +#endif .CreateBuffer = radeonCreateBuffer, .DestroyBuffer = radeonDestroyBuffer, .SwapBuffers = radeonSwapBuffers, diff --git a/src/mesa/drivers/dri/radeon/radeon_span.c b/src/mesa/drivers/dri/radeon/radeon_span.c index b2a468b4fd..5e4bf00d7a 100644 --- a/src/mesa/drivers/dri/radeon/radeon_span.c +++ b/src/mesa/drivers/dri/radeon/radeon_span.c @@ -51,6 +51,59 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. static void radeonSetSpanFunctions(struct radeon_renderbuffer *rrb); + +/* r200 depth buffer is always tiled - this is the formula + according to the docs unless I typo'ed in it +*/ +static GLubyte *r200_depth_2byte(const struct radeon_renderbuffer * rrb, + GLint x, GLint y) +{ + GLubyte *ptr = rrb->bo->ptr; + GLint offset; + if (rrb->has_surface) { + offset = x * rrb->cpp + y * rrb->pitch; + } else { + GLuint b; + offset = 0; + b = (((y >> 4) * (rrb->pitch >> 8) + (x >> 6))); + offset += (b >> 1) << 12; + offset += (((rrb->pitch >> 8) & 0x1) ? (b & 0x1) : ((b & 0x1) ^ ((y >> 4) & 0x1))) << 11; + offset += ((y >> 2) & 0x3) << 9; + offset += ((x >> 3) & 0x1) << 8; + offset += ((x >> 4) & 0x3) << 6; + offset += ((x >> 2) & 0x1) << 5; + offset += ((y >> 1) & 0x1) << 4; + offset += ((x >> 1) & 0x1) << 3; + offset += (y & 0x1) << 2; + offset += (x & 0x1) << 1; + } + return &ptr[offset]; +} + +static GLubyte *r200_depth_4byte(const struct radeon_renderbuffer * rrb, + GLint x, GLint y) +{ + GLubyte *ptr = rrb->bo->ptr; + GLint offset; + if (rrb->has_surface) { + offset = x * rrb->cpp + y * rrb->pitch; + } else { + GLuint b; + offset = 0; + b = (((y & 0x7ff) >> 4) * (rrb->pitch >> 7) + (x >> 5)); + offset += (b >> 1) << 12; + offset += (((rrb->pitch >> 7) & 0x1) ? (b & 0x1) : ((b & 0x1) ^ ((y >> 4) & 0x1))) << 11; + offset += ((y >> 2) & 0x3) << 9; + offset += ((x >> 2) & 0x1) << 8; + offset += ((x >> 3) & 0x3) << 6; + offset += ((y >> 1) & 0x1) << 5; + offset += ((x >> 1) & 0x1) << 4; + offset += (y & 0x1) << 3; + offset += (x & 0x1) << 2; + } + return &ptr[offset]; +} + /* radeon tiling on r300-r500 has 4 states, macro-linear/micro-linear macro-linear/micro-tiled @@ -61,7 +114,6 @@ static void radeonSetSpanFunctions(struct radeon_renderbuffer *rrb); 4 byte surface 8/16 byte (unused) */ - static GLubyte *radeon_ptr_4byte(const struct radeon_renderbuffer * rrb, GLint x, GLint y) { @@ -285,11 +337,21 @@ s8z24_to_z24s8(uint32_t val) */ #define VALUE_TYPE GLushort +#if defined(RADEON_COMMON_FOR_R200) +#define WRITE_DEPTH( _x, _y, d ) \ + *(GLushort *)r200_depth_2byte(rrb, _x + x_off, _y + y_off) = d +#else #define WRITE_DEPTH( _x, _y, d ) \ *(GLushort *)radeon_ptr_2byte_8x2(rrb, _x + x_off, _y + y_off) = d +#endif +#if defined(RADEON_COMMON_FOR_R200) +#define READ_DEPTH( d, _x, _y ) \ + d = *(GLushort *)r200_depth_2byte(rrb, _x + x_off, _y + y_off) +#else #define READ_DEPTH( d, _x, _y ) \ d = *(GLushort *)radeon_ptr_2byte_8x2(rrb, _x + x_off, _y + y_off) +#endif #define TAG(x) radeon##x##_z16 #include "depthtmp.h" @@ -301,7 +363,7 @@ s8z24_to_z24s8(uint32_t val) */ #define VALUE_TYPE GLuint -#ifdef COMPILE_R300 +#if defined(COMPILE_R300) #define WRITE_DEPTH( _x, _y, d ) \ do { \ GLuint *_ptr = (GLuint*)radeon_ptr_4byte( rrb, _x + x_off, _y + y_off ); \ @@ -310,6 +372,15 @@ do { \ tmp |= ((d << 8) & 0xffffff00); \ *_ptr = tmp; \ } while (0) +#elif defined(RADEON_COMMON_FOR_R200) +#define WRITE_DEPTH( _x, _y, d ) \ +do { \ + GLuint *_ptr = (GLuint*)r200_depth_4byte( rrb, _x + x_off, _y + y_off ); \ + GLuint tmp = *_ptr; \ + tmp &= 0xff000000; \ + tmp |= ((d) & 0x00ffffff); \ + *_ptr = tmp; \ +} while (0) #else #define WRITE_DEPTH( _x, _y, d ) \ do { \ @@ -321,19 +392,21 @@ do { \ } while (0) #endif -#ifdef COMPILE_R300 +#if defined(COMPILE_R300) #define READ_DEPTH( d, _x, _y ) \ do { \ d = (*(GLuint*)(radeon_ptr_4byte(rrb, _x + x_off, _y + y_off)) & 0xffffff00) >> 8; \ }while(0) +#elif defined(RADEON_COMMON_FOR_R200) +#define READ_DEPTH( d, _x, _y ) \ + do { \ + d = *(GLuint*)(r200_depth_4byte(rrb, _x + x_off, _y + y_off)) & 0x00ffffff; \ + }while(0) #else #define READ_DEPTH( d, _x, _y ) \ d = *(GLuint*)(radeon_ptr_4byte(rrb, _x + x_off, _y + y_off)) & 0x00ffffff; #endif -/* - fprintf(stderr, "dval(%d, %d, %d, %d)=0x%08X\n", _x, xo, _y, yo, d);\ - d = *(GLuint*)(radeon_ptr(rrb, _x, _y )) & 0x00ffffff; -*/ + #define TAG(x) radeon##x##_z24 #include "depthtmp.h" @@ -345,12 +418,19 @@ do { \ */ #define VALUE_TYPE GLuint -#ifdef COMPILE_R300 +#if defined(COMPILE_R300) #define WRITE_DEPTH( _x, _y, d ) \ do { \ GLuint *_ptr = (GLuint*)radeon_ptr_4byte( rrb, _x + x_off, _y + y_off ); \ *_ptr = d; \ } while (0) +#elif defined(RADEON_COMMON_FOR_R200) +#define WRITE_DEPTH( _x, _y, d ) \ +do { \ + GLuint *_ptr = (GLuint*)r200_depth_4byte( rrb, _x + x_off, _y + y_off ); \ + GLuint tmp = z24s8_to_s8z24(d); \ + *_ptr = tmp; \ +} while (0) #else #define WRITE_DEPTH( _x, _y, d ) \ do { \ @@ -360,20 +440,22 @@ do { \ } while (0) #endif -#ifdef COMPILE_R300 +#if defined(COMPILE_R300) #define READ_DEPTH( d, _x, _y ) \ do { \ d = (*(GLuint*)(radeon_ptr_4byte(rrb, _x + x_off, _y + y_off))); \ }while(0) +#elif defined(RADEON_COMMON_FOR_R200) +#define READ_DEPTH( d, _x, _y ) \ + do { \ + d = s8z24_to_z24s8(*(GLuint*)(r200_depth_4byte(rrb, _x + x_off, _y + y_off))); \ + }while(0) #else #define READ_DEPTH( d, _x, _y ) do { \ d = s8z24_to_z24s8(*(GLuint*)(radeon_ptr_4byte(rrb, _x + x_off, _y + y_off ))); \ } while (0) #endif -/* - fprintf(stderr, "dval(%d, %d, %d, %d)=0x%08X\n", _x, xo, _y, yo, d);\ - d = *(GLuint*)(radeon_ptr(rrb, _x, _y )) & 0x00ffffff; -*/ + #define TAG(x) radeon##x##_z24_s8 #include "depthtmp.h" @@ -392,6 +474,15 @@ do { \ tmp |= (d) & 0xff; \ *_ptr = tmp; \ } while (0) +#elif defined(RADEON_COMMON_FOR_R200) +#define WRITE_STENCIL( _x, _y, d ) \ +do { \ + GLuint *_ptr = (GLuint*)r200_depth_4byte(rrb, _x + x_off, _y + y_off); \ + GLuint tmp = *_ptr; \ + tmp &= 0x00ffffff; \ + tmp |= (((d) & 0xff) << 24); \ + *_ptr = tmp; \ +} while (0) #else #define WRITE_STENCIL( _x, _y, d ) \ do { \ @@ -410,6 +501,13 @@ do { \ GLuint tmp = *_ptr; \ d = tmp & 0x000000ff; \ } while (0) +#elif defined(RADEON_COMMON_FOR_R200) +#define READ_STENCIL( d, _x, _y ) \ +do { \ + GLuint *_ptr = (GLuint*)r200_depth_4byte( rrb, _x + x_off, _y + y_off ); \ + GLuint tmp = *_ptr; \ + d = (tmp & 0xff000000) >> 24; \ +} while (0) #else #define READ_STENCIL( d, _x, _y ) \ do { \ diff --git a/src/mesa/drivers/dri/radeon/radeon_texture.c b/src/mesa/drivers/dri/radeon/radeon_texture.c index 6a065f0468..fa16f44c18 100644 --- a/src/mesa/drivers/dri/radeon/radeon_texture.c +++ b/src/mesa/drivers/dri/radeon/radeon_texture.c @@ -610,9 +610,17 @@ static void radeon_teximage( if (pixels) { radeon_teximage_map(image, GL_TRUE); - if (compressed) { - memcpy(texImage->Data, pixels, imageSize); + if (image->mt) { + uint32_t srcRowStride, bytesPerRow, rows; + srcRowStride = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, width); + bytesPerRow = srcRowStride; + rows = (height + 3) / 4; + copy_rows(texImage->Data, image->mt->levels[level].rowstride, + pixels, srcRowStride, rows, bytesPerRow); + } else { + memcpy(texImage->Data, pixels, imageSize); + } } else { GLuint dstRowStride; GLuint *dstImageOffsets; @@ -756,14 +764,23 @@ static void radeon_texsubimage(GLcontext* ctx, int dims, GLenum target, int leve } if (compressed) { - uint32_t srcRowStride, bytesPerRow, rows; - dstRowStride = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, texImage->Width); + uint32_t srcRowStride, bytesPerRow, rows; + GLubyte *img_start; + if (!image->mt) { + dstRowStride = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, texImage->Width); + img_start = _mesa_compressed_image_address(xoffset, yoffset, 0, + texImage->TexFormat->MesaFormat, + texImage->Width, texImage->Data); + } + else { + uint32_t blocks_x = dstRowStride / (image->mt->bpp * 4); + img_start = texImage->Data + image->mt->bpp * 4 * (blocks_x * (yoffset / 4) + xoffset / 4); + } srcRowStride = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, width); bytesPerRow = srcRowStride; - rows = height / 4; + rows = (height + 3) / 4; - copy_rows(texImage->Data, dstRowStride, image->base.Data, srcRowStride, rows, - bytesPerRow); + copy_rows(img_start, dstRowStride, pixels, srcRowStride, rows, bytesPerRow); } else { if (!texImage->TexFormat->StoreImage(ctx, dims, texImage->_BaseFormat, @@ -884,8 +901,8 @@ static void migrate_image_to_miptree(radeon_mipmap_tree *mt, radeon_texture_imag uint32_t height; /* need to confirm this value is correct */ if (mt->compressed) { - height = image->base.Height / 4; - srcrowstride = image->base.RowStride * mt->bpp; + height = (image->base.Height + 3) / 4; + srcrowstride = _mesa_compressed_row_stride(image->base.TexFormat->MesaFormat, image->base.Width); } else { height = image->base.Height * image->base.Depth; srcrowstride = image->base.Width * image->base.TexFormat->TexelBytes; @@ -1000,6 +1017,8 @@ radeon_get_tex_image(GLcontext * ctx, GLenum target, GLint level, } if (compressed) { + /* FIXME: this can't work for small textures (mips) which + use different hw stride */ _mesa_get_compressed_teximage(ctx, target, level, pixels, texObj, texImage); } else { diff --git a/src/mesa/glapi/EXT_framebuffer_object.xml b/src/mesa/glapi/EXT_framebuffer_object.xml index 1b0de2ad23..5559b48b11 100644 --- a/src/mesa/glapi/EXT_framebuffer_object.xml +++ b/src/mesa/glapi/EXT_framebuffer_object.xml @@ -192,42 +192,4 @@ </function> </category> - - -<category name="GL_EXT_texture_array" number="329"> - <enum name="TEXTURE_1D_ARRAY_EXT" value="0x8C18"/> - <enum name="PROXY_TEXTURE_1D_ARRAY_EXT" value="0x8C19"/> - <enum name="TEXTURE_2D_ARRAY_EXT" value="0x8C1A"/> - <enum name="PROXY_TEXTURE_2D_ARRAY_EXT" value="0x8C1B"/> - - <enum name="TEXTURE_BINDING_1D_ARRAY_EXT" count="1" value="0x8C1C"> - <size name="Get" mode="get"/> - </enum> - - <enum name="TEXTURE_BINDING_2D_ARRAY_EXT" count="1" value="0x8C1D"> - <size name="Get" mode="get"/> - </enum> - - <enum name="MAX_ARRAY_TEXTURE_LAYERS_EXT" count="1" value="0x88FF"> - <size name="Get" mode="get"/> - </enum> - - <enum name="COMPARE_REF_DEPTH_TO_TEXTURE_EXT" count="1" value="0x884E"> - <size name="Get" mode="get"/> - </enum> - - <enum name="FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT" count="1" value="0x8CD4"> - <size name="GetFramebufferAttachmentParameterivEXT" mode="get"/> - </enum> - - <function name="FramebufferTextureLayerEXT" offset="assign"> - <param name="target" type="GLenum"/> - <param name="attachment" type="GLenum"/> - <param name="texture" type="GLuint"/> - <param name="level" type="GLint"/> - <param name="layer" type="GLint"/> - </function> -</category> - - </OpenGLAPI> diff --git a/src/mesa/glapi/EXT_texture_array.xml b/src/mesa/glapi/EXT_texture_array.xml new file mode 100644 index 0000000000..e5bd9f3c69 --- /dev/null +++ b/src/mesa/glapi/EXT_texture_array.xml @@ -0,0 +1,41 @@ +<?xml version="1.0"?> +<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd"> + +<OpenGLAPI> + +<category name="GL_EXT_texture_array" number="329"> + <enum name="TEXTURE_1D_ARRAY_EXT" value="0x8C18"/> + <enum name="PROXY_TEXTURE_1D_ARRAY_EXT" value="0x8C19"/> + <enum name="TEXTURE_2D_ARRAY_EXT" value="0x8C1A"/> + <enum name="PROXY_TEXTURE_2D_ARRAY_EXT" value="0x8C1B"/> + + <enum name="TEXTURE_BINDING_1D_ARRAY_EXT" count="1" value="0x8C1C"> + <size name="Get" mode="get"/> + </enum> + + <enum name="TEXTURE_BINDING_2D_ARRAY_EXT" count="1" value="0x8C1D"> + <size name="Get" mode="get"/> + </enum> + + <enum name="MAX_ARRAY_TEXTURE_LAYERS_EXT" count="1" value="0x88FF"> + <size name="Get" mode="get"/> + </enum> + + <enum name="COMPARE_REF_DEPTH_TO_TEXTURE_EXT" count="1" value="0x884E"> + <size name="Get" mode="get"/> + </enum> + + <enum name="FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT" count="1" value="0x8CD4"> + <size name="GetFramebufferAttachmentParameterivEXT" mode="get"/> + </enum> + + <function name="FramebufferTextureLayerEXT" offset="assign"> + <param name="target" type="GLenum"/> + <param name="attachment" type="GLenum"/> + <param name="texture" type="GLuint"/> + <param name="level" type="GLint"/> + <param name="layer" type="GLint"/> + </function> +</category> + +</OpenGLAPI> diff --git a/src/mesa/glapi/gl_API.xml b/src/mesa/glapi/gl_API.xml index 06560d175a..1703637c7b 100644 --- a/src/mesa/glapi/gl_API.xml +++ b/src/mesa/glapi/gl_API.xml @@ -12255,6 +12255,65 @@ </function> </category> +<category name="GL_APPLE_flush_buffer_range" number="321"> + <enum name="BUFFER_SERIALIZED_MODIFY_APPLE" count="1" value="0x8A12"> + <size name="GetBufferParameteriv" mode="get"/> + </enum> + <enum name="BUFFER_FLUSHING_UNMAP_APPLE" count="1" value="0x8A13"> + <size name="GetBufferParameteriv" mode="get"/> + </enum> + <function name="BufferParameteriAPPLE" offset="assign" static_dispatch="false"> + <param name="target" type="GLenum"/> + <param name="pname" type="GLenum"/> + <param name="param" type="GLint"/> + </function> + <function name="FlushMappedBufferRangeAPPLE" offset="assign" static_dispatch="false"> + <param name="target" type="GLenum"/> + <param name="offset" type="GLintptr"/> + <param name="size" type="GLsizeiptr"/> + </function> +</category> + +<xi:include href="EXT_texture_array.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> + +<category name="GL_APPLE_texture_range" number="367"> + <enum name="TEXTURE_STORAGE_HINT_APPLE" count="1" value="0x85BC"> + <size name="TexParameteriv"/> + <size name="TexParameterfv"/> + <size name="GetTexParameteriv" mode="get"/> + <size name="GetTexParameterfv" mode="get"/> + </enum> + <enum name="STORAGE_PRIVATE_APPLE" count="1" value="0x85BD"> + <size name="TexParameteriv"/> + <size name="TexParameterfv"/> + </enum> + <enum name="STORAGE_CACHED_APPLE" count="1" value="0x85BE"> + <size name="TexParameteriv"/> + <size name="TexParameterfv"/> + </enum> + <enum name="STORAGE_SHARED_APPLE" count="1" value="0x85BF"> + <size name="TexParameteriv"/> + <size name="TexParameterfv"/> + </enum> + <enum name="TEXTURE_RANGE_LENGTH_APPLE" count="1" value="0x85B7"> + <size name="GetTexParameteriv" mode="get"/> + <size name="GetTexParameterfv" mode="get"/> + </enum> + <enum name="TEXTURE_RANGE_POINTER_APPLE" count="1" value="0x85B8"> + <size name="GetTexParameterPointervAPPLE" mode="get"/> + </enum> + <function name="TextureRangeAPPLE" offset="assign" static_dispatch="false"> + <param name="target" type="GLenum"/> + <param name="length" type="GLsizei"/> + <param name="pointer" type="GLvoid *"/> + </function> + <function name="GetTexParameterPointervAPPLE" offset="assign" static_dispatch="false"> + <param name="target" type="GLenum"/> + <param name="pname" type="GLenum"/> + <param name="params" type="GLvoid **"/> + </function> +</category> + <!-- Unnumbered extensions sorted by name. --> <category name="GL_ATI_blend_equation_separate"> diff --git a/src/mesa/main/api_arrayelt.c b/src/mesa/main/api_arrayelt.c index f5b7d1e138..2462a1b003 100644 --- a/src/mesa/main/api_arrayelt.c +++ b/src/mesa/main/api_arrayelt.c @@ -28,6 +28,7 @@ #include "glheader.h" #include "api_arrayelt.h" +#include "bufferobj.h" #include "context.h" #include "imports.h" #include "macros.h" @@ -1071,7 +1072,7 @@ void _ae_destroy_context( GLcontext *ctx ) static void check_vbo( AEcontext *actx, struct gl_buffer_object *vbo ) { - if (vbo->Name && !vbo->Pointer) { + if (_mesa_is_bufferobj(vbo) && !_mesa_bufferobj_mapped(vbo)) { GLuint i; for (i = 0; i < actx->nr_vbos; i++) if (actx->vbo[i] == vbo) diff --git a/src/mesa/main/api_exec.c b/src/mesa/main/api_exec.c index e49cd041a6..199550b35d 100644 --- a/src/mesa/main/api_exec.c +++ b/src/mesa/main/api_exec.c @@ -107,6 +107,7 @@ #include "state.h" #include "stencil.h" #include "texenv.h" +#include "texgetimage.h" #include "teximage.h" #if FEATURE_texgen #include "texgen.h" diff --git a/src/mesa/main/api_validate.c b/src/mesa/main/api_validate.c index b2f11ffbfe..2df4f17389 100644 --- a/src/mesa/main/api_validate.c +++ b/src/mesa/main/api_validate.c @@ -24,6 +24,7 @@ #include "glheader.h" #include "api_validate.h" +#include "bufferobj.h" #include "context.h" #include "imports.h" #include "mtypes.h" @@ -62,7 +63,7 @@ max_buffer_index(GLcontext *ctx, GLuint count, GLenum type, GLuint max = 0; GLuint i; - if (elementBuf->Name) { + if (_mesa_is_bufferobj(elementBuf)) { /* elements are in a user-defined buffer object. need to map it */ map = ctx->Driver.MapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER, GL_READ_ONLY, elementBuf); @@ -96,14 +97,12 @@ max_buffer_index(GLcontext *ctx, GLuint count, GLenum type, /** - * Check if OK to render by examining framebuffer status and vertex arrays. + * Check if OK to draw arrays/elements. */ static GLboolean -check_valid_to_render(GLcontext *ctx, char *function) +check_valid_to_render(GLcontext *ctx, const char *function) { - if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { - _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, - "glDraw%s(incomplete framebuffer)", function); + if (!_mesa_valid_to_render(ctx, function)) { return GL_FALSE; } @@ -160,11 +159,11 @@ _mesa_validate_DrawElements(GLcontext *ctx, if (ctx->NewState) _mesa_update_state(ctx); - if (!check_valid_to_render(ctx, "Elements")) + if (!check_valid_to_render(ctx, "glDrawElements")) return GL_FALSE; /* Vertex buffer object tests */ - if (ctx->Array.ElementArrayBufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj)) { /* use indices in the buffer object */ /* make sure count doesn't go outside buffer bounds */ if (index_bytes(type, count) > ctx->Array.ElementArrayBufferObj->Size) { @@ -233,11 +232,11 @@ _mesa_validate_DrawRangeElements(GLcontext *ctx, GLenum mode, if (ctx->NewState) _mesa_update_state(ctx); - if (!check_valid_to_render(ctx, "RangeElements")) + if (!check_valid_to_render(ctx, "glDrawRangeElements")) return GL_FALSE; /* Vertex buffer object tests */ - if (ctx->Array.ElementArrayBufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj)) { /* use indices in the buffer object */ /* make sure count doesn't go outside buffer bounds */ if (index_bytes(type, count) > ctx->Array.ElementArrayBufferObj->Size) { @@ -289,7 +288,7 @@ _mesa_validate_DrawArrays(GLcontext *ctx, if (ctx->NewState) _mesa_update_state(ctx); - if (!check_valid_to_render(ctx, "Arrays")) + if (!check_valid_to_render(ctx, "glDrawArrays")) return GL_FALSE; if (ctx->Const.CheckArrayBounds) { diff --git a/src/mesa/main/attrib.c b/src/mesa/main/attrib.c index cb49c4cb07..ab99ca1c64 100644 --- a/src/mesa/main/attrib.c +++ b/src/mesa/main/attrib.c @@ -174,24 +174,30 @@ struct texture_state /** - * Allocate a new attribute state node. These nodes have a - * "kind" value and a pointer to a struct of state data. + * Allocate new attribute node of given type/kind. Attach payload data. + * Insert it into the linked list named by 'head'. */ -static struct gl_attrib_node * -new_attrib_node( GLbitfield kind ) +static void +save_attrib_data(struct gl_attrib_node **head, + GLbitfield kind, void *payload) { - struct gl_attrib_node *an = MALLOC_STRUCT(gl_attrib_node); - if (an) { - an->kind = kind; + struct gl_attrib_node *n = MALLOC_STRUCT(gl_attrib_node); + if (n) { + n->kind = kind; + n->data = payload; + /* insert at head */ + n->next = *head; + *head = n; + } + else { + /* out of memory! */ } - return an; } void GLAPIENTRY _mesa_PushAttrib(GLbitfield mask) { - struct gl_attrib_node *newnode; struct gl_attrib_node *head; GET_CURRENT_CONTEXT(ctx); @@ -213,10 +219,7 @@ _mesa_PushAttrib(GLbitfield mask) struct gl_accum_attrib *attr; attr = MALLOC_STRUCT( gl_accum_attrib ); MEMCPY( attr, &ctx->Accum, sizeof(struct gl_accum_attrib) ); - newnode = new_attrib_node( GL_ACCUM_BUFFER_BIT ); - newnode->data = attr; - newnode->next = head; - head = newnode; + save_attrib_data(&head, GL_ACCUM_BUFFER_BIT, attr); } if (mask & GL_COLOR_BUFFER_BIT) { @@ -227,10 +230,7 @@ _mesa_PushAttrib(GLbitfield mask) /* push the Draw FBO's DrawBuffer[] state, not ctx->Color.DrawBuffer[] */ for (i = 0; i < ctx->Const.MaxDrawBuffers; i ++) attr->DrawBuffer[i] = ctx->DrawBuffer->ColorDrawBuffer[i]; - newnode = new_attrib_node( GL_COLOR_BUFFER_BIT ); - newnode->data = attr; - newnode->next = head; - head = newnode; + save_attrib_data(&head, GL_COLOR_BUFFER_BIT, attr); } if (mask & GL_CURRENT_BIT) { @@ -238,20 +238,14 @@ _mesa_PushAttrib(GLbitfield mask) FLUSH_CURRENT( ctx, 0 ); attr = MALLOC_STRUCT( gl_current_attrib ); MEMCPY( attr, &ctx->Current, sizeof(struct gl_current_attrib) ); - newnode = new_attrib_node( GL_CURRENT_BIT ); - newnode->data = attr; - newnode->next = head; - head = newnode; + save_attrib_data(&head, GL_CURRENT_BIT, attr); } if (mask & GL_DEPTH_BUFFER_BIT) { struct gl_depthbuffer_attrib *attr; attr = MALLOC_STRUCT( gl_depthbuffer_attrib ); MEMCPY( attr, &ctx->Depth, sizeof(struct gl_depthbuffer_attrib) ); - newnode = new_attrib_node( GL_DEPTH_BUFFER_BIT ); - newnode->data = attr; - newnode->next = head; - head = newnode; + save_attrib_data(&head, GL_DEPTH_BUFFER_BIT, attr); } if (mask & GL_ENABLE_BIT) { @@ -331,40 +325,28 @@ _mesa_PushAttrib(GLbitfield mask) attr->VertexProgram = ctx->VertexProgram.Enabled; attr->VertexProgramPointSize = ctx->VertexProgram.PointSizeEnabled; attr->VertexProgramTwoSide = ctx->VertexProgram.TwoSideEnabled; - newnode = new_attrib_node( GL_ENABLE_BIT ); - newnode->data = attr; - newnode->next = head; - head = newnode; + save_attrib_data(&head, GL_ENABLE_BIT, attr); } if (mask & GL_EVAL_BIT) { struct gl_eval_attrib *attr; attr = MALLOC_STRUCT( gl_eval_attrib ); MEMCPY( attr, &ctx->Eval, sizeof(struct gl_eval_attrib) ); - newnode = new_attrib_node( GL_EVAL_BIT ); - newnode->data = attr; - newnode->next = head; - head = newnode; + save_attrib_data(&head, GL_EVAL_BIT, attr); } if (mask & GL_FOG_BIT) { struct gl_fog_attrib *attr; attr = MALLOC_STRUCT( gl_fog_attrib ); MEMCPY( attr, &ctx->Fog, sizeof(struct gl_fog_attrib) ); - newnode = new_attrib_node( GL_FOG_BIT ); - newnode->data = attr; - newnode->next = head; - head = newnode; + save_attrib_data(&head, GL_FOG_BIT, attr); } if (mask & GL_HINT_BIT) { struct gl_hint_attrib *attr; attr = MALLOC_STRUCT( gl_hint_attrib ); MEMCPY( attr, &ctx->Hint, sizeof(struct gl_hint_attrib) ); - newnode = new_attrib_node( GL_HINT_BIT ); - newnode->data = attr; - newnode->next = head; - head = newnode; + save_attrib_data(&head, GL_HINT_BIT, attr); } if (mask & GL_LIGHTING_BIT) { @@ -372,30 +354,21 @@ _mesa_PushAttrib(GLbitfield mask) FLUSH_CURRENT(ctx, 0); /* flush material changes */ attr = MALLOC_STRUCT( gl_light_attrib ); MEMCPY( attr, &ctx->Light, sizeof(struct gl_light_attrib) ); - newnode = new_attrib_node( GL_LIGHTING_BIT ); - newnode->data = attr; - newnode->next = head; - head = newnode; + save_attrib_data(&head, GL_LIGHTING_BIT, attr); } if (mask & GL_LINE_BIT) { struct gl_line_attrib *attr; attr = MALLOC_STRUCT( gl_line_attrib ); MEMCPY( attr, &ctx->Line, sizeof(struct gl_line_attrib) ); - newnode = new_attrib_node( GL_LINE_BIT ); - newnode->data = attr; - newnode->next = head; - head = newnode; + save_attrib_data(&head, GL_LINE_BIT, attr); } if (mask & GL_LIST_BIT) { struct gl_list_attrib *attr; attr = MALLOC_STRUCT( gl_list_attrib ); MEMCPY( attr, &ctx->List, sizeof(struct gl_list_attrib) ); - newnode = new_attrib_node( GL_LIST_BIT ); - newnode->data = attr; - newnode->next = head; - head = newnode; + save_attrib_data(&head, GL_LIST_BIT, attr); } if (mask & GL_PIXEL_MODE_BIT) { @@ -404,60 +377,42 @@ _mesa_PushAttrib(GLbitfield mask) MEMCPY( attr, &ctx->Pixel, sizeof(struct gl_pixel_attrib) ); /* push the Read FBO's ReadBuffer state, not ctx->Pixel.ReadBuffer */ attr->ReadBuffer = ctx->ReadBuffer->ColorReadBuffer; - newnode = new_attrib_node( GL_PIXEL_MODE_BIT ); - newnode->data = attr; - newnode->next = head; - head = newnode; + save_attrib_data(&head, GL_PIXEL_MODE_BIT, attr); } if (mask & GL_POINT_BIT) { struct gl_point_attrib *attr; attr = MALLOC_STRUCT( gl_point_attrib ); MEMCPY( attr, &ctx->Point, sizeof(struct gl_point_attrib) ); - newnode = new_attrib_node( GL_POINT_BIT ); - newnode->data = attr; - newnode->next = head; - head = newnode; + save_attrib_data(&head, GL_POINT_BIT, attr); } if (mask & GL_POLYGON_BIT) { struct gl_polygon_attrib *attr; attr = MALLOC_STRUCT( gl_polygon_attrib ); MEMCPY( attr, &ctx->Polygon, sizeof(struct gl_polygon_attrib) ); - newnode = new_attrib_node( GL_POLYGON_BIT ); - newnode->data = attr; - newnode->next = head; - head = newnode; + save_attrib_data(&head, GL_POLYGON_BIT, attr); } if (mask & GL_POLYGON_STIPPLE_BIT) { GLuint *stipple; stipple = (GLuint *) MALLOC( 32*sizeof(GLuint) ); MEMCPY( stipple, ctx->PolygonStipple, 32*sizeof(GLuint) ); - newnode = new_attrib_node( GL_POLYGON_STIPPLE_BIT ); - newnode->data = stipple; - newnode->next = head; - head = newnode; + save_attrib_data(&head, GL_POLYGON_STIPPLE_BIT, stipple); } if (mask & GL_SCISSOR_BIT) { struct gl_scissor_attrib *attr; attr = MALLOC_STRUCT( gl_scissor_attrib ); MEMCPY( attr, &ctx->Scissor, sizeof(struct gl_scissor_attrib) ); - newnode = new_attrib_node( GL_SCISSOR_BIT ); - newnode->data = attr; - newnode->next = head; - head = newnode; + save_attrib_data(&head, GL_SCISSOR_BIT, attr); } if (mask & GL_STENCIL_BUFFER_BIT) { struct gl_stencil_attrib *attr; attr = MALLOC_STRUCT( gl_stencil_attrib ); MEMCPY( attr, &ctx->Stencil, sizeof(struct gl_stencil_attrib) ); - newnode = new_attrib_node( GL_STENCIL_BUFFER_BIT ); - newnode->data = attr; - newnode->next = head; - head = newnode; + save_attrib_data(&head, GL_STENCIL_BUFFER_BIT, attr); } if (mask & GL_TEXTURE_BIT) { @@ -494,30 +449,21 @@ _mesa_PushAttrib(GLbitfield mask) _mesa_unlock_context_textures(ctx); - newnode = new_attrib_node( GL_TEXTURE_BIT ); - newnode->data = texstate; - newnode->next = head; - head = newnode; + save_attrib_data(&head, GL_TEXTURE_BIT, texstate); } if (mask & GL_TRANSFORM_BIT) { struct gl_transform_attrib *attr; attr = MALLOC_STRUCT( gl_transform_attrib ); MEMCPY( attr, &ctx->Transform, sizeof(struct gl_transform_attrib) ); - newnode = new_attrib_node( GL_TRANSFORM_BIT ); - newnode->data = attr; - newnode->next = head; - head = newnode; + save_attrib_data(&head, GL_TRANSFORM_BIT, attr); } if (mask & GL_VIEWPORT_BIT) { struct gl_viewport_attrib *attr; attr = MALLOC_STRUCT( gl_viewport_attrib ); MEMCPY( attr, &ctx->Viewport, sizeof(struct gl_viewport_attrib) ); - newnode = new_attrib_node( GL_VIEWPORT_BIT ); - newnode->data = attr; - newnode->next = head; - head = newnode; + save_attrib_data(&head, GL_VIEWPORT_BIT, attr); } /* GL_ARB_multisample */ @@ -525,10 +471,7 @@ _mesa_PushAttrib(GLbitfield mask) struct gl_multisample_attrib *attr; attr = MALLOC_STRUCT( gl_multisample_attrib ); MEMCPY( attr, &ctx->Multisample, sizeof(struct gl_multisample_attrib) ); - newnode = new_attrib_node( GL_MULTISAMPLE_BIT_ARB ); - newnode->data = attr; - newnode->next = head; - head = newnode; + save_attrib_data(&head, GL_MULTISAMPLE_BIT_ARB, attr); } end: @@ -1373,7 +1316,6 @@ copy_pixelstore(GLcontext *ctx, void GLAPIENTRY _mesa_PushClientAttrib(GLbitfield mask) { - struct gl_attrib_node *newnode; struct gl_attrib_node *head; GET_CURRENT_CONTEXT(ctx); @@ -1394,17 +1336,11 @@ _mesa_PushClientAttrib(GLbitfield mask) /* packing attribs */ attr = CALLOC_STRUCT( gl_pixelstore_attrib ); copy_pixelstore(ctx, attr, &ctx->Pack); - newnode = new_attrib_node( GL_CLIENT_PACK_BIT ); - newnode->data = attr; - newnode->next = head; - head = newnode; + save_attrib_data(&head, GL_CLIENT_PACK_BIT, attr); /* unpacking attribs */ attr = CALLOC_STRUCT( gl_pixelstore_attrib ); copy_pixelstore(ctx, attr, &ctx->Unpack); - newnode = new_attrib_node( GL_CLIENT_UNPACK_BIT ); - newnode->data = attr; - newnode->next = head; - head = newnode; + save_attrib_data(&head, GL_CLIENT_UNPACK_BIT, attr); } if (mask & GL_CLIENT_VERTEX_ARRAY_BIT) { @@ -1425,10 +1361,8 @@ _mesa_PushClientAttrib(GLbitfield mask) attr->ArrayObj = obj; - newnode = new_attrib_node( GL_CLIENT_VERTEX_ARRAY_BIT ); - newnode->data = attr; - newnode->next = head; - head = newnode; + save_attrib_data(&head, GL_CLIENT_VERTEX_ARRAY_BIT, attr); + /* bump reference counts on buffer objects */ adjust_buffer_object_ref_counts(ctx->Array.ArrayObj, 1); } diff --git a/src/mesa/main/bufferobj.c b/src/mesa/main/bufferobj.c index d640f5358e..f96185a4b5 100644 --- a/src/mesa/main/bufferobj.c +++ b/src/mesa/main/bufferobj.c @@ -156,7 +156,7 @@ buffer_object_subdata_range_good( GLcontext * ctx, GLenum target, _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", caller); return NULL; } - if (bufObj->Name == 0) { + if (!_mesa_is_bufferobj(bufObj)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller); return NULL; } @@ -165,7 +165,7 @@ buffer_object_subdata_range_good( GLcontext * ctx, GLenum target, "%s(size + offset > buffer size)", caller); return NULL; } - if (bufObj->Pointer) { + if (_mesa_bufferobj_mapped(bufObj)) { /* Buffer is currently mapped */ _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller); return NULL; @@ -423,7 +423,7 @@ _mesa_buffer_map( GLcontext *ctx, GLenum target, GLenum access, (void) target; (void) access; /* Just return a direct pointer to the data */ - if (bufObj->Pointer) { + if (_mesa_bufferobj_mapped(bufObj)) { /* already mapped! */ return NULL; } @@ -445,7 +445,7 @@ _mesa_buffer_map_range( GLcontext *ctx, GLenum target, GLintptr offset, (void) target; (void) access; (void) length; - assert(!bufObj->Pointer); + assert(!_mesa_bufferobj_mapped(bufObj)); /* Just return a direct pointer to the data */ return bufObj->Data + offset; } @@ -502,8 +502,8 @@ _mesa_copy_buffer_subdata(GLcontext *ctx, GLubyte *srcPtr, *dstPtr; /* buffer should not already be mapped */ - assert(!src->Pointer); - assert(!dst->Pointer); + assert(!_mesa_bufferobj_mapped(src)); + assert(!_mesa_bufferobj_mapped(dst)); srcPtr = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_COPY_READ_BUFFER, GL_READ_ONLY, src); @@ -663,7 +663,7 @@ _mesa_validate_pbo_access(GLuint dimensions, GLvoid *start, *end; const GLubyte *sizeAddr; /* buffer size, cast to a pointer */ - ASSERT(pack->BufferObj->Name != 0); + ASSERT(_mesa_is_bufferobj(pack->BufferObj)); if (pack->BufferObj->Size == 0) /* no buffer! */ @@ -709,7 +709,7 @@ _mesa_map_bitmap_pbo(GLcontext *ctx, { const GLubyte *buf; - if (unpack->BufferObj->Name) { + if (_mesa_is_bufferobj(unpack->BufferObj)) { /* unpack from PBO */ buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, GL_READ_ONLY_ARB, @@ -736,7 +736,7 @@ void _mesa_unmap_bitmap_pbo(GLcontext *ctx, const struct gl_pixelstore_attrib *unpack) { - if (unpack->BufferObj->Name) { + if (_mesa_is_bufferobj(unpack->BufferObj)) { ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, unpack->BufferObj); } @@ -753,7 +753,7 @@ _mesa_map_drawpix_pbo(GLcontext *ctx, { const GLvoid *buf; - if (unpack->BufferObj->Name) { + if (_mesa_is_bufferobj(unpack->BufferObj)) { /* unpack from PBO */ buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, GL_READ_ONLY_ARB, @@ -779,7 +779,7 @@ void _mesa_unmap_drawpix_pbo(GLcontext *ctx, const struct gl_pixelstore_attrib *unpack) { - if (unpack->BufferObj->Name) { + if (_mesa_is_bufferobj(unpack->BufferObj)) { ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, unpack->BufferObj); } @@ -798,7 +798,7 @@ _mesa_map_readpix_pbo(GLcontext *ctx, { void *buf; - if (pack->BufferObj->Name) { + if (_mesa_is_bufferobj(pack->BufferObj)) { /* pack into PBO */ buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, GL_WRITE_ONLY_ARB, @@ -824,7 +824,7 @@ void _mesa_unmap_readpix_pbo(GLcontext *ctx, const struct gl_pixelstore_attrib *pack) { - if (pack->BufferObj->Name) { + if (_mesa_is_bufferobj(pack->BufferObj)) { ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, pack->BufferObj); } } @@ -932,7 +932,7 @@ _mesa_DeleteBuffersARB(GLsizei n, const GLuint *ids) ASSERT(bufObj->Name == ids[i]); - if (bufObj->Pointer) { + if (_mesa_bufferobj_mapped(bufObj)) { /* if mapped, unmap it now */ ctx->Driver.UnmapBuffer(ctx, 0, bufObj); bufObj->AccessFlags = DEFAULT_ACCESS; @@ -1086,12 +1086,12 @@ _mesa_BufferDataARB(GLenum target, GLsizeiptrARB size, _mesa_error(ctx, GL_INVALID_ENUM, "glBufferDataARB(target)" ); return; } - if (bufObj->Name == 0) { + if (!_mesa_is_bufferobj(bufObj)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferDataARB(buffer 0)" ); return; } - if (bufObj->Pointer) { + if (_mesa_bufferobj_mapped(bufObj)) { /* Unmap the existing buffer. We'll replace it now. Not an error. */ ctx->Driver.UnmapBuffer(ctx, target, bufObj); bufObj->AccessFlags = DEFAULT_ACCESS; @@ -1187,18 +1187,18 @@ _mesa_MapBufferARB(GLenum target, GLenum access) _mesa_error(ctx, GL_INVALID_ENUM, "glMapBufferARB(target)" ); return NULL; } - if (bufObj->Name == 0) { + if (!_mesa_is_bufferobj(bufObj)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferARB(buffer 0)" ); return NULL; } - if (bufObj->Pointer) { + if (_mesa_bufferobj_mapped(bufObj)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferARB(already mapped)"); return NULL; } ASSERT(ctx->Driver.MapBuffer); bufObj->Pointer = ctx->Driver.MapBuffer( ctx, target, access, bufObj ); - if (!bufObj->Pointer) { + if (!_mesa_bufferobj_mapped(bufObj)) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(access)"); } @@ -1248,11 +1248,11 @@ _mesa_UnmapBufferARB(GLenum target) _mesa_error(ctx, GL_INVALID_ENUM, "glUnmapBufferARB(target)" ); return GL_FALSE; } - if (bufObj->Name == 0) { + if (!_mesa_is_bufferobj(bufObj)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glUnmapBufferARB" ); return GL_FALSE; } - if (!bufObj->Pointer) { + if (!_mesa_bufferobj_mapped(bufObj)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glUnmapBufferARB"); return GL_FALSE; } @@ -1315,7 +1315,7 @@ _mesa_GetBufferParameterivARB(GLenum target, GLenum pname, GLint *params) _mesa_error(ctx, GL_INVALID_ENUM, "GetBufferParameterivARB(target)" ); return; } - if (bufObj->Name == 0) { + if (!_mesa_is_bufferobj(bufObj)) { _mesa_error(ctx, GL_INVALID_OPERATION, "GetBufferParameterivARB" ); return; } @@ -1331,7 +1331,7 @@ _mesa_GetBufferParameterivARB(GLenum target, GLenum pname, GLint *params) *params = simplified_access_mode(bufObj->AccessFlags); break; case GL_BUFFER_MAPPED_ARB: - *params = (bufObj->Pointer != NULL); + *params = _mesa_bufferobj_mapped(bufObj); break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameterivARB(pname)"); @@ -1357,7 +1357,7 @@ _mesa_GetBufferPointervARB(GLenum target, GLenum pname, GLvoid **params) _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferPointervARB(target)" ); return; } - if (bufObj->Name == 0) { + if (!_mesa_is_bufferobj(bufObj)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetBufferPointervARB" ); return; } @@ -1376,26 +1376,26 @@ _mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget, ASSERT_OUTSIDE_BEGIN_END(ctx); src = get_buffer(ctx, readTarget); - if (!src || src->Name == 0) { + if (!src || !_mesa_is_bufferobj(src)) { _mesa_error(ctx, GL_INVALID_ENUM, "glCopyBuffserSubData(readTarget = 0x%x)", readTarget); return; } dst = get_buffer(ctx, writeTarget); - if (!dst || dst->Name == 0) { + if (!dst || !_mesa_is_bufferobj(dst)) { _mesa_error(ctx, GL_INVALID_ENUM, "glCopyBuffserSubData(writeTarget = 0x%x)", writeTarget); return; } - if (src->Pointer) { + if (_mesa_bufferobj_mapped(src)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyBuffserSubData(readBuffer is mapped)"); return; } - if (dst->Pointer) { + if (_mesa_bufferobj_mapped(dst)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyBuffserSubData(writeBuffer is mapped)"); return; @@ -1499,7 +1499,7 @@ _mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, } bufObj = get_buffer(ctx, target); - if (!bufObj || bufObj->Name == 0) { + if (!bufObj || !_mesa_is_bufferobj(bufObj)) { _mesa_error(ctx, GL_INVALID_ENUM, "glMapBufferRange(target = 0x%x)", target); return NULL; @@ -1511,7 +1511,7 @@ _mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, return NULL; } - if (bufObj->Pointer) { + if (_mesa_bufferobj_mapped(bufObj)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferRange(buffer already mapped)"); return NULL; @@ -1564,13 +1564,13 @@ _mesa_FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length) return; } - if (bufObj->Name == 0) { + if (!_mesa_is_bufferobj(bufObj)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferRange(current buffer is 0)"); return; } - if (!bufObj->Pointer) { + if (!_mesa_bufferobj_mapped(bufObj)) { /* buffer is not mapped */ _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferRange(buffer is not mapped)"); diff --git a/src/mesa/main/bufferobj.h b/src/mesa/main/bufferobj.h index ef59ff83c8..decb44a65e 100644 --- a/src/mesa/main/bufferobj.h +++ b/src/mesa/main/bufferobj.h @@ -36,6 +36,26 @@ * Internal functions */ + +/** Is the given buffer object currently mapped? */ +static INLINE GLboolean +_mesa_bufferobj_mapped(const struct gl_buffer_object *obj) +{ + return obj->Pointer != NULL; +} + +/** + * Is the given buffer object a user-created buffer object? + * Mesa uses default buffer objects in several places. Default buffers + * always have Name==0. User created buffers have Name!=0. + */ +static INLINE GLboolean +_mesa_is_bufferobj(const struct gl_buffer_object *obj) +{ + return obj->Name != 0; +} + + extern void _mesa_init_buffer_objects( GLcontext *ctx ); diff --git a/src/mesa/main/colortab.c b/src/mesa/main/colortab.c index bd9cf438b4..36304065eb 100644 --- a/src/mesa/main/colortab.c +++ b/src/mesa/main/colortab.c @@ -179,7 +179,7 @@ store_colortable_entries(GLcontext *ctx, struct gl_color_table *table, GLfloat bScale, GLfloat bBias, GLfloat aScale, GLfloat aBias) { - if (ctx->Unpack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) { /* Get/unpack the color table data from a PBO */ GLubyte *buf; if (!_mesa_validate_pbo_access(1, &ctx->Unpack, count, 1, 1, @@ -279,7 +279,7 @@ store_colortable_entries(GLcontext *ctx, struct gl_color_table *table, } } - if (ctx->Unpack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) { ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, ctx->Unpack.BufferObj); } @@ -696,7 +696,7 @@ _mesa_GetColorTable( GLenum target, GLenum format, return; } - if (ctx->Pack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { /* pack color table into PBO */ GLubyte *buf; if (!_mesa_validate_pbo_access(1, &ctx->Pack, table->Size, 1, 1, @@ -720,7 +720,7 @@ _mesa_GetColorTable( GLenum target, GLenum format, _mesa_pack_rgba_span_float(ctx, table->Size, rgba, format, type, data, &ctx->Pack, 0x0); - if (ctx->Pack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, ctx->Pack.BufferObj); } diff --git a/src/mesa/main/config.h b/src/mesa/main/config.h index f77a29a43e..e4995c35c4 100644 --- a/src/mesa/main/config.h +++ b/src/mesa/main/config.h @@ -138,9 +138,14 @@ /** * Maximum viewport/image width. Must accomodate all texture sizes too. */ -#define MAX_WIDTH 4096 + +#ifndef MAX_WIDTH +# define MAX_WIDTH 4096 +#endif /** Maximum viewport/image height */ -#define MAX_HEIGHT 4096 +#ifndef MAX_HEIGHT +# define MAX_HEIGHT 4096 +#endif /** Maxmimum size for CVA. May be overridden by the drivers. */ #define MAX_ARRAY_LOCK_SIZE 3000 diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index 415e339cb8..38ec418809 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -150,6 +150,7 @@ #include "glapi/glapioffsets.h" #include "glapi/glapitable.h" #include "shader/program.h" +#include "shader/prog_print.h" #include "shader/shader_api.h" #if FEATURE_ATI_fragment_shader #include "shader/atifragshader.h" @@ -1576,4 +1577,72 @@ _mesa_set_mvp_with_dp4( GLcontext *ctx, } + +/** + * Prior to drawing anything with glBegin, glDrawArrays, etc. this function + * is called to see if it's valid to render. This involves checking that + * the current shader is valid and the framebuffer is complete. + * If an error is detected it'll be recorded here. + * \return GL_TRUE if OK to render, GL_FALSE if not + */ +GLboolean +_mesa_valid_to_render(GLcontext *ctx, const char *where) +{ + if (ctx->Shader.CurrentProgram) { + /* using shaders */ + if (!ctx->Shader.CurrentProgram->LinkStatus) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(shader not linked), where"); + return GL_FALSE; + } + } + else { + if (ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(vertex program not valid)", where); + return GL_FALSE; + } + if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(fragment program not valid)", where); + return GL_FALSE; + } + } + + if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { + _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, + "%s(incomplete framebuffer)", where); + return GL_FALSE; + } + +#ifdef DEBUG + if (ctx->Shader.Flags & GLSL_LOG) { + struct gl_shader_program *shProg = ctx->Shader.CurrentProgram; + if (shProg) { + if (!shProg->_Used) { + /* This is the first time this shader is being used. + * Append shader's constants/uniforms to log file. + */ + GLuint i; + for (i = 0; i < shProg->NumShaders; i++) { + struct gl_shader *sh = shProg->Shaders[i]; + if (sh->Type == GL_VERTEX_SHADER) { + _mesa_append_uniforms_to_file(sh, + &shProg->VertexProgram->Base); + } + else if (sh->Type == GL_FRAGMENT_SHADER) { + _mesa_append_uniforms_to_file(sh, + &shProg->FragmentProgram->Base); + } + } + shProg->_Used = GL_TRUE; + } + } + } +#endif + + return GL_TRUE; +} + + /*@}*/ diff --git a/src/mesa/main/context.h b/src/mesa/main/context.h index 0531ae8ee8..5587695fa0 100644 --- a/src/mesa/main/context.h +++ b/src/mesa/main/context.h @@ -159,6 +159,11 @@ _mesa_set_mvp_with_dp4( GLcontext *ctx, GLboolean flag ); +extern GLboolean +_mesa_valid_to_render(GLcontext *ctx, const char *where); + + + /** \name Miscellaneous */ /*@{*/ @@ -174,7 +179,6 @@ _mesa_Flush( void ); /*@}*/ - /** * \name Macros for flushing buffered rendering commands before state changes, * checking if inside glBegin/glEnd, etc. diff --git a/src/mesa/main/convolve.c b/src/mesa/main/convolve.c index 814c6a0a5a..69dba72ed3 100644 --- a/src/mesa/main/convolve.c +++ b/src/mesa/main/convolve.c @@ -144,7 +144,7 @@ _mesa_ConvolutionFilter1D(GLenum target, GLenum internalFormat, GLsizei width, G ctx->Convolution1D.Width = width; ctx->Convolution1D.Height = 1; - if (ctx->Unpack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) { /* unpack filter from PBO */ GLubyte *buf; if (!_mesa_validate_pbo_access(1, &ctx->Unpack, width, 1, 1, @@ -173,7 +173,7 @@ _mesa_ConvolutionFilter1D(GLenum target, GLenum internalFormat, GLsizei width, G format, type, image, &ctx->Unpack, 0); /* transferOps */ - if (ctx->Unpack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) { ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, ctx->Unpack.BufferObj); } @@ -242,7 +242,7 @@ _mesa_ConvolutionFilter2D(GLenum target, GLenum internalFormat, GLsizei width, G ctx->Convolution2D.Width = width; ctx->Convolution2D.Height = height; - if (ctx->Unpack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) { /* unpack filter from PBO */ GLubyte *buf; if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height, 1, @@ -276,7 +276,7 @@ _mesa_ConvolutionFilter2D(GLenum target, GLenum internalFormat, GLsizei width, G 0); /* transferOps */ } - if (ctx->Unpack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) { ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, ctx->Unpack.BufferObj); } @@ -598,7 +598,7 @@ _mesa_GetConvolutionFilter(GLenum target, GLenum format, GLenum type, return; } - if (ctx->Pack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { /* Pack the filter into a PBO */ GLubyte *buf; if (!_mesa_validate_pbo_access(2, &ctx->Pack, @@ -629,7 +629,7 @@ _mesa_GetConvolutionFilter(GLenum target, GLenum format, GLenum type, format, type, dst, &ctx->Pack, 0x0); } - if (ctx->Pack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, ctx->Pack.BufferObj); } @@ -802,7 +802,7 @@ _mesa_GetSeparableFilter(GLenum target, GLenum format, GLenum type, filter = &ctx->Separable2D; - if (ctx->Pack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { /* Pack filter into PBO */ GLubyte *buf; if (!_mesa_validate_pbo_access(1, &ctx->Pack, filter->Width, 1, 1, @@ -850,7 +850,7 @@ _mesa_GetSeparableFilter(GLenum target, GLenum format, GLenum type, (void) span; /* unused at this time */ - if (ctx->Pack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { /* Pack filter into PBO */ ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, ctx->Unpack.BufferObj); @@ -905,7 +905,7 @@ _mesa_SeparableFilter2D(GLenum target, GLenum internalFormat, GLsizei width, GLs ctx->Separable2D.Width = width; ctx->Separable2D.Height = height; - if (ctx->Unpack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) { /* unpack filter from PBO */ GLubyte *buf; if (!_mesa_validate_pbo_access(1, &ctx->Unpack, width, 1, 1, @@ -971,7 +971,7 @@ _mesa_SeparableFilter2D(GLenum target, GLenum internalFormat, GLsizei width, GLs ctx->Pixel.ConvolutionFilterBias[2][3]); } - if (ctx->Unpack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) { ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, ctx->Unpack.BufferObj); } diff --git a/src/mesa/main/debug.c b/src/mesa/main/debug.c index 1c8c44fcb9..8492c8561d 100644 --- a/src/mesa/main/debug.c +++ b/src/mesa/main/debug.c @@ -33,6 +33,7 @@ #include "get.h" #include "pixelstore.h" #include "readpix.h" +#include "texgetimage.h" #include "texobj.h" #include "texformat.h" @@ -234,11 +235,11 @@ _mesa_init_debug( GLcontext *ctx ) */ static void write_ppm(const char *filename, const GLubyte *buffer, int width, int height, - int comps, int rcomp, int gcomp, int bcomp) + int comps, int rcomp, int gcomp, int bcomp, GLboolean invert) { FILE *f = fopen( filename, "w" ); if (f) { - int i, x, y; + int x, y; const GLubyte *ptr = buffer; fprintf(f,"P6\n"); fprintf(f,"# ppm-file created by osdemo.c\n"); @@ -246,10 +247,11 @@ write_ppm(const char *filename, const GLubyte *buffer, int width, int height, fprintf(f,"255\n"); fclose(f); f = fopen( filename, "ab" ); /* reopen in binary append mode */ - for (y=height-1; y>=0; y--) { - for (x=0; x<width; x++) { - i = (y*width + x) * comps; - fputc(ptr[i+rcomp], f); /* write red */ + for (y=0; y < height; y++) { + for (x = 0; x < width; x++) { + int yy = invert ? (height - 1 - y) : y; + int i = (yy * width + x) * comps; + fputc(ptr[i+rcomp], f); /* write red */ fputc(ptr[i+gcomp], f); /* write green */ fputc(ptr[i+bcomp], f); /* write blue */ } @@ -263,47 +265,34 @@ write_ppm(const char *filename, const GLubyte *buffer, int width, int height, * Write level[0] image to a ppm file. */ static void -write_texture_image(struct gl_texture_object *texObj) +write_texture_image(struct gl_texture_object *texObj, GLuint face, GLuint level) { - const struct gl_texture_image *img = texObj->Image[0][0]; - if (img && img->Data) { + struct gl_texture_image *img = texObj->Image[face][level]; + if (img) { + GET_CURRENT_CONTEXT(ctx); + struct gl_pixelstore_attrib store; + GLubyte *buffer; char s[100]; + buffer = (GLubyte *) _mesa_malloc(img->Width * img->Height + * img->Depth * 4); + + store = ctx->Pack; /* save */ + ctx->Pack = ctx->DefaultPacking; + + ctx->Driver.GetTexImage(ctx, texObj->Target, level, + GL_RGBA, GL_UNSIGNED_BYTE, + buffer, texObj, img); + /* make filename */ - sprintf(s, "/tmp/teximage%u.ppm", texObj->Name); - - switch (img->TexFormat->MesaFormat) { - case MESA_FORMAT_RGBA8888: - write_ppm(s, img->Data, img->Width, img->Height, 4, 3, 2, 1); - break; - case MESA_FORMAT_ARGB8888: - write_ppm(s, img->Data, img->Width, img->Height, 4, 2, 1, 0); - break; - case MESA_FORMAT_RGB888: - write_ppm(s, img->Data, img->Width, img->Height, 3, 2, 1, 0); - break; - case MESA_FORMAT_RGB565: - { - GLubyte *buf2 = (GLubyte *) _mesa_malloc(img->Width * img->Height * 3); - GLuint i; - for (i = 0; i < img->Width * img->Height; i++) { - GLint r, g, b; - GLushort s = ((GLushort *) img->Data)[i]; - r = UBYTE_TO_CHAN( ((s >> 8) & 0xf8) | ((s >> 13) & 0x7) ); - g = UBYTE_TO_CHAN( ((s >> 3) & 0xfc) | ((s >> 9) & 0x3) ); - b = UBYTE_TO_CHAN( ((s << 3) & 0xf8) | ((s >> 2) & 0x7) ); - buf2[i*3+1] = r; - buf2[i*3+2] = g; - buf2[i*3+3] = b; - } - write_ppm(s, buf2, img->Width, img->Height, 3, 2, 1, 0); - _mesa_free(buf2); - } - break; - default: - printf("XXXX unsupported mesa tex format %d in %s\n", - img->TexFormat->MesaFormat, __FUNCTION__); - } + _mesa_sprintf(s, "/tmp/teximage%u.ppm", texObj->Name); + + _mesa_printf(" Writing image level %u to %s\n", level, s); + write_ppm(s, buffer, img->Width, img->Height, 4, 0, 1, 2, GL_FALSE); + + ctx->Pack = store; /* restore */ + + _mesa_free(buffer); } } @@ -316,17 +305,21 @@ dump_texture_cb(GLuint id, void *data, void *userData) { struct gl_texture_object *texObj = (struct gl_texture_object *) data; int i; + GLboolean written = GL_FALSE; (void) userData; - printf("Texture %u\n", texObj->Name); - printf(" Target 0x%x\n", texObj->Target); + _mesa_printf("Texture %u\n", texObj->Name); + _mesa_printf(" Target 0x%x\n", texObj->Target); for (i = 0; i < MAX_TEXTURE_LEVELS; i++) { struct gl_texture_image *texImg = texObj->Image[0][i]; if (texImg) { - printf(" Image %u: %d x %d x %d at %p\n", i, - texImg->Width, texImg->Height, texImg->Depth, texImg->Data); - if (DumpImages && i == 0) { - write_texture_image(texObj); + _mesa_printf(" Image %u: %d x %d x %d, format %u at %p\n", i, + texImg->Width, texImg->Height, texImg->Depth, + texImg->TexFormat->MesaFormat, texImg->Data); + if (DumpImages && !written) { + GLuint face = 0; + write_texture_image(texObj, face, i); + written = GL_TRUE; } } } @@ -368,7 +361,7 @@ _mesa_dump_color_buffer(const char *filename) ctx->DrawBuffer->_ColorDrawBuffers[0], ctx->DrawBuffer->ColorDrawBuffer[0]); _mesa_printf("Writing %d x %d color buffer to %s\n", w, h, filename); - write_ppm(filename, buf, w, h, 4, 0, 1, 2); + write_ppm(filename, buf, w, h, 4, 0, 1, 2, GL_TRUE); _mesa_PopClientAttrib(); @@ -403,7 +396,7 @@ _mesa_dump_depth_buffer(const char *filename) } _mesa_printf("Writing %d x %d depth buffer to %s\n", w, h, filename); - write_ppm(filename, buf2, w, h, 3, 0, 1, 2); + write_ppm(filename, buf2, w, h, 3, 0, 1, 2, GL_TRUE); _mesa_PopClientAttrib(); @@ -438,7 +431,7 @@ _mesa_dump_stencil_buffer(const char *filename) } _mesa_printf("Writing %d x %d stencil buffer to %s\n", w, h, filename); - write_ppm(filename, buf2, w, h, 3, 0, 1, 2); + write_ppm(filename, buf2, w, h, 3, 0, 1, 2, GL_TRUE); _mesa_PopClientAttrib(); diff --git a/src/mesa/main/dlist.c b/src/mesa/main/dlist.c index 49f202daa1..9b68b3e116 100644 --- a/src/mesa/main/dlist.c +++ b/src/mesa/main/dlist.c @@ -683,24 +683,48 @@ translate_id(GLsizei n, GLenum type, const GLvoid * list) /** * Wrapper for _mesa_unpack_image() that handles pixel buffer objects. - * \todo This won't suffice when the PBO is really in VRAM/GPU memory. + * If we run out of memory, GL_OUT_OF_MEMORY will be recorded. */ static GLvoid * -unpack_image(GLuint dimensions, GLsizei width, GLsizei height, GLsizei depth, +unpack_image(GLcontext *ctx, GLuint dimensions, + GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid * pixels, const struct gl_pixelstore_attrib *unpack) { - if (unpack->BufferObj->Name == 0) { + if (!_mesa_is_bufferobj(unpack->BufferObj)) { /* no PBO */ - return _mesa_unpack_image(dimensions, width, height, depth, format, - type, pixels, unpack); + GLvoid *image = _mesa_unpack_image(dimensions, width, height, depth, + format, type, pixels, unpack); + if (pixels && !image) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "display list construction"); + } + return image; } - else - if (_mesa_validate_pbo_access - (dimensions, unpack, width, height, depth, format, type, pixels)) { - const GLubyte *src = ADD_POINTERS(unpack->BufferObj->Data, pixels); - return _mesa_unpack_image(dimensions, width, height, depth, format, - type, src, unpack); + else if (_mesa_validate_pbo_access(dimensions, unpack, width, height, depth, + format, type, pixels)) { + const GLubyte *map, *src; + GLvoid *image; + + map = (GLubyte *) + ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, + GL_READ_ONLY_ARB, unpack->BufferObj); + if (!map) { + /* unable to map src buffer! */ + _mesa_error(ctx, GL_INVALID_OPERATION, "unable to map PBO"); + return NULL; + } + + src = ADD_POINTERS(map, pixels); + image = _mesa_unpack_image(dimensions, width, height, depth, + format, type, src, unpack); + + ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, + unpack->BufferObj); + + if (!image) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "display list construction"); + } + return image; } /* bad access! */ return NULL; @@ -858,7 +882,6 @@ save_Bitmap(GLsizei width, GLsizei height, GLfloat xmove, GLfloat ymove, const GLubyte * pixels) { GET_CURRENT_CONTEXT(ctx); - GLvoid *image = _mesa_unpack_bitmap(width, height, pixels, &ctx->Unpack); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); n = ALLOC_INSTRUCTION(ctx, OPCODE_BITMAP, 7); @@ -869,10 +892,7 @@ save_Bitmap(GLsizei width, GLsizei height, n[4].f = yorig; n[5].f = xmove; n[6].f = ymove; - n[7].data = image; - } - else if (image) { - _mesa_free(image); + n[7].data = _mesa_unpack_bitmap(width, height, pixels, &ctx->Unpack); } if (ctx->ExecuteFlag) { CALL_Bitmap(ctx->Exec, (width, height, @@ -999,7 +1019,7 @@ _mesa_save_CallList(GLuint list) void GLAPIENTRY -_mesa_save_CallLists(GLsizei n, GLenum type, const GLvoid * lists) +_mesa_save_CallLists(GLsizei num, GLenum type, const GLvoid * lists) { GET_CURRENT_CONTEXT(ctx); GLint i; @@ -1024,7 +1044,7 @@ _mesa_save_CallLists(GLsizei n, GLenum type, const GLvoid * lists) typeErrorFlag = GL_TRUE; } - for (i = 0; i < n; i++) { + for (i = 0; i < num; i++) { GLint list = translate_id(i, type, lists); Node *n = ALLOC_INSTRUCTION(ctx, OPCODE_CALL_LIST_OFFSET, 2); if (n) { @@ -1039,7 +1059,7 @@ _mesa_save_CallLists(GLsizei n, GLenum type, const GLvoid * lists) invalidate_saved_current_state( ctx ); if (ctx->ExecuteFlag) { - CALL_CallLists(ctx->Exec, (n, type, lists)); + CALL_CallLists(ctx->Exec, (num, type, lists)); } } @@ -1217,8 +1237,6 @@ save_ColorTable(GLenum target, GLenum internalFormat, format, type, table)); } else { - GLvoid *image = unpack_image(1, width, 1, 1, format, type, table, - &ctx->Unpack); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); n = ALLOC_INSTRUCTION(ctx, OPCODE_COLOR_TABLE, 6); @@ -1228,10 +1246,8 @@ save_ColorTable(GLenum target, GLenum internalFormat, n[3].i = width; n[4].e = format; n[5].e = type; - n[6].data = image; - } - else if (image) { - _mesa_free(image); + n[6].data = unpack_image(ctx, 1, width, 1, 1, format, type, table, + &ctx->Unpack); } if (ctx->ExecuteFlag) { CALL_ColorTable(ctx->Exec, (target, internalFormat, width, @@ -1307,8 +1323,6 @@ save_ColorSubTable(GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid * table) { GET_CURRENT_CONTEXT(ctx); - GLvoid *image = unpack_image(1, count, 1, 1, format, type, table, - &ctx->Unpack); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); n = ALLOC_INSTRUCTION(ctx, OPCODE_COLOR_SUB_TABLE, 6); @@ -1318,10 +1332,8 @@ save_ColorSubTable(GLenum target, GLsizei start, GLsizei count, n[3].i = count; n[4].e = format; n[5].e = type; - n[6].data = image; - } - else if (image) { - _mesa_free(image); + n[6].data = unpack_image(ctx, 1, count, 1, 1, format, type, table, + &ctx->Unpack); } if (ctx->ExecuteFlag) { CALL_ColorSubTable(ctx->Exec, @@ -1379,10 +1391,10 @@ save_ConvolutionFilter1D(GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid * filter) { GET_CURRENT_CONTEXT(ctx); - GLvoid *image = unpack_image(1, width, 1, 1, format, type, filter, - &ctx->Unpack); Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION(ctx, OPCODE_CONVOLUTION_FILTER_1D, 6); if (n) { n[1].e = target; @@ -1390,10 +1402,8 @@ save_ConvolutionFilter1D(GLenum target, GLenum internalFormat, GLsizei width, n[3].i = width; n[4].e = format; n[5].e = type; - n[6].data = image; - } - else if (image) { - _mesa_free(image); + n[6].data = unpack_image(ctx, 1, width, 1, 1, format, type, filter, + &ctx->Unpack); } if (ctx->ExecuteFlag) { CALL_ConvolutionFilter1D(ctx->Exec, (target, internalFormat, width, @@ -1408,10 +1418,10 @@ save_ConvolutionFilter2D(GLenum target, GLenum internalFormat, GLenum type, const GLvoid * filter) { GET_CURRENT_CONTEXT(ctx); - GLvoid *image = unpack_image(2, width, height, 1, format, type, filter, - &ctx->Unpack); Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION(ctx, OPCODE_CONVOLUTION_FILTER_2D, 7); if (n) { n[1].e = target; @@ -1420,10 +1430,8 @@ save_ConvolutionFilter2D(GLenum target, GLenum internalFormat, n[4].i = height; n[5].e = format; n[6].e = type; - n[7].data = image; - } - else if (image) { - _mesa_free(image); + n[7].data = unpack_image(ctx, 2, width, height, 1, format, type, filter, + &ctx->Unpack); } if (ctx->ExecuteFlag) { CALL_ConvolutionFilter2D(ctx->Exec, @@ -1778,20 +1786,18 @@ save_DrawPixels(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * pixels) { GET_CURRENT_CONTEXT(ctx); - GLvoid *image = unpack_image(2, width, height, 1, format, type, - pixels, &ctx->Unpack); Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION(ctx, OPCODE_DRAW_PIXELS, 5); if (n) { n[1].i = width; n[2].i = height; n[3].e = format; n[4].e = type; - n[5].data = image; - } - else if (image) { - _mesa_free(image); + n[5].data = unpack_image(ctx, 2, width, height, 1, format, type, + pixels, &ctx->Unpack); } if (ctx->ExecuteFlag) { CALL_DrawPixels(ctx->Exec, (width, height, format, type, pixels)); @@ -1880,7 +1886,10 @@ save_Fogfv(GLenum pname, const GLfloat *params) static void GLAPIENTRY save_Fogf(GLenum pname, GLfloat param) { - save_Fogfv(pname, ¶m); + GLfloat parray[4]; + parray[0] = param; + parray[1] = parray[2] = parray[3] = 0.0F; + save_Fogfv(pname, parray); } @@ -1904,7 +1913,7 @@ save_Fogiv(GLenum pname, const GLint *params) break; default: /* Error will be caught later in gl_Fogfv */ - ; + ASSIGN_4V(p, 0.0F, 0.0F, 0.0F, 0.0F); } save_Fogfv(pname, p); } @@ -1913,7 +1922,10 @@ save_Fogiv(GLenum pname, const GLint *params) static void GLAPIENTRY save_Fogi(GLenum pname, GLint param) { - save_Fogiv(pname, ¶m); + GLint parray[4]; + parray[0] = param; + parray[1] = parray[2] = parray[3] = 0; + save_Fogiv(pname, parray); } @@ -2077,9 +2089,12 @@ save_Lightfv(GLenum light, GLenum pname, const GLfloat *params) static void GLAPIENTRY -save_Lightf(GLenum light, GLenum pname, GLfloat params) +save_Lightf(GLenum light, GLenum pname, GLfloat param) { - save_Lightfv(light, pname, ¶ms); + GLfloat parray[4]; + parray[0] = param; + parray[1] = parray[2] = parray[3] = 0.0F; + save_Lightfv(light, pname, parray); } @@ -2125,7 +2140,10 @@ save_Lightiv(GLenum light, GLenum pname, const GLint *params) static void GLAPIENTRY save_Lighti(GLenum light, GLenum pname, GLint param) { - save_Lightiv(light, pname, ¶m); + GLint parray[4]; + parray[0] = param; + parray[1] = parray[2] = parray[3] = 0; + save_Lightiv(light, pname, parray); } @@ -2152,7 +2170,10 @@ save_LightModelfv(GLenum pname, const GLfloat *params) static void GLAPIENTRY save_LightModelf(GLenum pname, GLfloat param) { - save_LightModelfv(pname, ¶m); + GLfloat parray[4]; + parray[0] = param; + parray[1] = parray[2] = parray[3] = 0.0F; + save_LightModelfv(pname, parray); } @@ -2174,7 +2195,7 @@ save_LightModeliv(GLenum pname, const GLint *params) break; default: /* Error will be caught later in gl_LightModelfv */ - ; + ASSIGN_4V(fparam, 0.0F, 0.0F, 0.0F, 0.0F); } save_LightModelfv(pname, fparam); } @@ -2183,7 +2204,10 @@ save_LightModeliv(GLenum pname, const GLint *params) static void GLAPIENTRY save_LightModeli(GLenum pname, GLint param) { - save_LightModeliv(pname, ¶m); + GLint parray[4]; + parray[0] = param; + parray[1] = parray[2] = parray[3] = 0; + save_LightModeliv(pname, parray); } @@ -2698,21 +2722,28 @@ save_PointParameterfvEXT(GLenum pname, const GLfloat *params) static void GLAPIENTRY save_PointParameterfEXT(GLenum pname, GLfloat param) { - save_PointParameterfvEXT(pname, ¶m); + GLfloat parray[3]; + parray[0] = param; + parray[1] = parray[2] = 0.0F; + save_PointParameterfvEXT(pname, parray); } static void GLAPIENTRY save_PointParameteriNV(GLenum pname, GLint param) { - GLfloat p = (GLfloat) param; - save_PointParameterfvEXT(pname, &p); + GLfloat parray[3]; + parray[0] = (GLfloat) param; + parray[1] = parray[2] = 0.0F; + save_PointParameterfvEXT(pname, parray); } static void GLAPIENTRY save_PointParameterivNV(GLenum pname, const GLint * param) { - GLfloat p = (GLfloat) param[0]; - save_PointParameterfvEXT(pname, &p); + GLfloat parray[3]; + parray[0] = (GLfloat) param[0]; + parray[1] = parray[2] = 0.0F; + save_PointParameterfvEXT(pname, parray); } @@ -2753,16 +2784,14 @@ static void GLAPIENTRY save_PolygonStipple(const GLubyte * pattern) { GET_CURRENT_CONTEXT(ctx); - GLvoid *image = unpack_image(2, 32, 32, 1, GL_COLOR_INDEX, GL_BITMAP, - pattern, &ctx->Unpack); Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION(ctx, OPCODE_POLYGON_STIPPLE, 1); if (n) { - n[1].data = image; - } - else if (image) { - _mesa_free(image); + n[1].data = unpack_image(ctx, 2, 32, 32, 1, GL_COLOR_INDEX, GL_BITMAP, + pattern, &ctx->Unpack); } if (ctx->ExecuteFlag) { CALL_PolygonStipple(ctx->Exec, ((GLubyte *) pattern)); @@ -3386,7 +3415,10 @@ save_TexEnvfv(GLenum target, GLenum pname, const GLfloat *params) static void GLAPIENTRY save_TexEnvf(GLenum target, GLenum pname, GLfloat param) { - save_TexEnvfv(target, pname, ¶m); + GLfloat parray[4]; + parray[0] = (GLfloat) param; + parray[1] = parray[2] = parray[3] = 0.0F; + save_TexEnvfv(target, pname, parray); } @@ -3454,8 +3486,10 @@ save_TexGeniv(GLenum coord, GLenum pname, const GLint *params) static void GLAPIENTRY save_TexGend(GLenum coord, GLenum pname, GLdouble param) { - GLfloat p = (GLfloat) param; - save_TexGenfv(coord, pname, &p); + GLfloat parray[4]; + parray[0] = (GLfloat) param; + parray[1] = parray[2] = parray[3] = 0.0F; + save_TexGenfv(coord, pname, parray); } @@ -3474,14 +3508,20 @@ save_TexGendv(GLenum coord, GLenum pname, const GLdouble *params) static void GLAPIENTRY save_TexGenf(GLenum coord, GLenum pname, GLfloat param) { - save_TexGenfv(coord, pname, ¶m); + GLfloat parray[4]; + parray[0] = param; + parray[1] = parray[2] = parray[3] = 0.0F; + save_TexGenfv(coord, pname, parray); } static void GLAPIENTRY save_TexGeni(GLenum coord, GLenum pname, GLint param) { - save_TexGeniv(coord, pname, ¶m); + GLint parray[4]; + parray[0] = param; + parray[1] = parray[2] = parray[3] = 0; + save_TexGeniv(coord, pname, parray); } @@ -3509,7 +3549,10 @@ save_TexParameterfv(GLenum target, GLenum pname, const GLfloat *params) static void GLAPIENTRY save_TexParameterf(GLenum target, GLenum pname, GLfloat param) { - save_TexParameterfv(target, pname, ¶m); + GLfloat parray[4]; + parray[0] = param; + parray[1] = parray[2] = parray[3] = 0.0F; + save_TexParameterfv(target, pname, parray); } @@ -3546,8 +3589,6 @@ save_TexImage1D(GLenum target, border, format, type, pixels)); } else { - GLvoid *image = unpack_image(1, width, 1, 1, format, type, - pixels, &ctx->Unpack); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); n = ALLOC_INSTRUCTION(ctx, OPCODE_TEX_IMAGE1D, 8); @@ -3559,10 +3600,8 @@ save_TexImage1D(GLenum target, n[5].i = border; n[6].e = format; n[7].e = type; - n[8].data = image; - } - else if (image) { - _mesa_free(image); + n[8].data = unpack_image(ctx, 1, width, 1, 1, format, type, + pixels, &ctx->Unpack); } if (ctx->ExecuteFlag) { CALL_TexImage1D(ctx->Exec, (target, level, components, width, @@ -3585,8 +3624,6 @@ save_TexImage2D(GLenum target, height, border, format, type, pixels)); } else { - GLvoid *image = unpack_image(2, width, height, 1, format, type, - pixels, &ctx->Unpack); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); n = ALLOC_INSTRUCTION(ctx, OPCODE_TEX_IMAGE2D, 9); @@ -3599,10 +3636,8 @@ save_TexImage2D(GLenum target, n[6].i = border; n[7].e = format; n[8].e = type; - n[9].data = image; - } - else if (image) { - _mesa_free(image); + n[9].data = unpack_image(ctx, 2, width, height, 1, format, type, + pixels, &ctx->Unpack); } if (ctx->ExecuteFlag) { CALL_TexImage2D(ctx->Exec, (target, level, components, width, @@ -3628,8 +3663,6 @@ save_TexImage3D(GLenum target, } else { Node *n; - GLvoid *image = unpack_image(3, width, height, depth, format, type, - pixels, &ctx->Unpack); ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); n = ALLOC_INSTRUCTION(ctx, OPCODE_TEX_IMAGE3D, 10); if (n) { @@ -3642,10 +3675,8 @@ save_TexImage3D(GLenum target, n[7].i = border; n[8].e = format; n[9].e = type; - n[10].data = image; - } - else if (image) { - _mesa_free(image); + n[10].data = unpack_image(ctx, 3, width, height, depth, format, type, + pixels, &ctx->Unpack); } if (ctx->ExecuteFlag) { CALL_TexImage3D(ctx->Exec, (target, level, internalFormat, width, @@ -3663,9 +3694,9 @@ save_TexSubImage1D(GLenum target, GLint level, GLint xoffset, { GET_CURRENT_CONTEXT(ctx); Node *n; - GLvoid *image = unpack_image(1, width, 1, 1, format, type, - pixels, &ctx->Unpack); + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION(ctx, OPCODE_TEX_SUB_IMAGE1D, 7); if (n) { n[1].e = target; @@ -3674,10 +3705,8 @@ save_TexSubImage1D(GLenum target, GLint level, GLint xoffset, n[4].i = (GLint) width; n[5].e = format; n[6].e = type; - n[7].data = image; - } - else if (image) { - _mesa_free(image); + n[7].data = unpack_image(ctx, 1, width, 1, 1, format, type, + pixels, &ctx->Unpack); } if (ctx->ExecuteFlag) { CALL_TexSubImage1D(ctx->Exec, (target, level, xoffset, width, @@ -3694,9 +3723,9 @@ save_TexSubImage2D(GLenum target, GLint level, { GET_CURRENT_CONTEXT(ctx); Node *n; - GLvoid *image = unpack_image(2, width, height, 1, format, type, - pixels, &ctx->Unpack); + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION(ctx, OPCODE_TEX_SUB_IMAGE2D, 9); if (n) { n[1].e = target; @@ -3707,10 +3736,8 @@ save_TexSubImage2D(GLenum target, GLint level, n[6].i = (GLint) height; n[7].e = format; n[8].e = type; - n[9].data = image; - } - else if (image) { - _mesa_free(image); + n[9].data = unpack_image(ctx, 2, width, height, 1, format, type, + pixels, &ctx->Unpack); } if (ctx->ExecuteFlag) { CALL_TexSubImage2D(ctx->Exec, (target, level, xoffset, yoffset, @@ -3727,9 +3754,9 @@ save_TexSubImage3D(GLenum target, GLint level, { GET_CURRENT_CONTEXT(ctx); Node *n; - GLvoid *image = unpack_image(3, width, height, depth, format, type, - pixels, &ctx->Unpack); + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION(ctx, OPCODE_TEX_SUB_IMAGE3D, 11); if (n) { n[1].e = target; @@ -3742,10 +3769,8 @@ save_TexSubImage3D(GLenum target, GLint level, n[8].i = (GLint) depth; n[9].e = format; n[10].e = type; - n[11].data = image; - } - else if (image) { - _mesa_free(image); + n[11].data = unpack_image(ctx, 3, width, height, depth, format, type, + pixels, &ctx->Unpack); } if (ctx->ExecuteFlag) { CALL_TexSubImage3D(ctx->Exec, (target, level, @@ -4458,18 +4483,17 @@ save_LoadProgramNV(GLenum target, GLuint id, GLsizei len, { GET_CURRENT_CONTEXT(ctx); Node *n; - GLubyte *programCopy; - - programCopy = (GLubyte *) _mesa_malloc(len); - if (!programCopy) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV"); - return; - } - _mesa_memcpy(programCopy, program, len); ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION(ctx, OPCODE_LOAD_PROGRAM_NV, 4); if (n) { + GLubyte *programCopy = (GLubyte *) _mesa_malloc(len); + if (!programCopy) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV"); + return; + } + _mesa_memcpy(programCopy, program, len); n[1].e = target; n[2].ui = id; n[3].i = len; @@ -4486,15 +4510,17 @@ save_RequestResidentProgramsNV(GLsizei num, const GLuint * ids) { GET_CURRENT_CONTEXT(ctx); Node *n; - GLuint *idCopy = (GLuint *) _mesa_malloc(num * sizeof(GLuint)); - if (!idCopy) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glRequestResidentProgramsNV"); - return; - } - _mesa_memcpy(idCopy, ids, num * sizeof(GLuint)); + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION(ctx, OPCODE_TRACK_MATRIX_NV, 2); if (n) { + GLuint *idCopy = (GLuint *) _mesa_malloc(num * sizeof(GLuint)); + if (!idCopy) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glRequestResidentProgramsNV"); + return; + } + _mesa_memcpy(idCopy, ids, num * sizeof(GLuint)); n[1].i = num; n[2].data = idCopy; } @@ -4655,16 +4681,17 @@ save_ProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte * name, { GET_CURRENT_CONTEXT(ctx); Node *n; - GLubyte *nameCopy = (GLubyte *) _mesa_malloc(len); - if (!nameCopy) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glProgramNamedParameter4fNV"); - return; - } - _mesa_memcpy(nameCopy, name, len); ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION(ctx, OPCODE_PROGRAM_NAMED_PARAMETER_NV, 6); if (n) { + GLubyte *nameCopy = (GLubyte *) _mesa_malloc(len); + if (!nameCopy) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glProgramNamedParameter4fNV"); + return; + } + _mesa_memcpy(nameCopy, name, len); n[1].ui = id; n[2].i = len; n[3].data = nameCopy; @@ -4753,18 +4780,17 @@ save_ProgramStringARB(GLenum target, GLenum format, GLsizei len, { GET_CURRENT_CONTEXT(ctx); Node *n; - GLubyte *programCopy; - - programCopy = (GLubyte *) _mesa_malloc(len); - if (!programCopy) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glProgramStringARB"); - return; - } - _mesa_memcpy(programCopy, string, len); ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION(ctx, OPCODE_PROGRAM_STRING_ARB, 4); if (n) { + GLubyte *programCopy = (GLubyte *) _mesa_malloc(len); + if (!programCopy) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glProgramStringARB"); + return; + } + _mesa_memcpy(programCopy, string, len); n[1].e = target; n[2].e = format; n[3].i = len; diff --git a/src/mesa/main/drawpix.c b/src/mesa/main/drawpix.c index 6682b5e725..6d31f32443 100644 --- a/src/mesa/main/drawpix.c +++ b/src/mesa/main/drawpix.c @@ -27,6 +27,7 @@ #include "bufferobj.h" #include "context.h" #include "drawpix.h" +#include "enums.h" #include "feedback.h" #include "framebuffer.h" #include "image.h" @@ -34,6 +35,18 @@ #include "state.h" + +/** + * If a fragment program is enabled, check that it's valid. + * \return GL_TRUE if valid, GL_FALSE otherwise + */ +static GLboolean +valid_fragment_program(GLcontext *ctx) +{ + return !(ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled); +} + + #if _HAVE_FULL_GL /* @@ -51,29 +64,34 @@ _mesa_DrawPixels( GLsizei width, GLsizei height, return; } + /* We're not using the current vertex program, and the driver may install + * it's own. + */ + _mesa_set_vp_override(ctx, GL_TRUE); + if (ctx->NewState) { _mesa_update_state(ctx); } - if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) { + if (!valid_fragment_program(ctx)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels (invalid fragment program)"); - return; + goto end; } if (_mesa_error_check_format_type(ctx, format, type, GL_TRUE)) { - /* found an error */ - return; + /* the error was already recorded */ + goto end; } if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, "glDrawPixels(incomplete framebuffer)" ); - return; + goto end; } if (!ctx->Current.RasterPosValid) { - return; + goto end; /* no-op, not an error */ } if (ctx->RenderMode == GL_RENDER) { @@ -88,13 +106,13 @@ _mesa_DrawPixels( GLsizei width, GLsizei height, format, type, pixels)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels(invalid PBO access)"); - return; + goto end; } - if (ctx->Unpack.BufferObj->Pointer) { + if (_mesa_bufferobj_mapped(ctx->Unpack.BufferObj)) { /* buffer is mapped - that's an error */ _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels(PBO is mapped)"); - return; + goto end; } } @@ -116,6 +134,9 @@ _mesa_DrawPixels( GLsizei width, GLsizei height, ASSERT(ctx->RenderMode == GL_SELECT); /* Do nothing. See OpenGL Spec, Appendix B, Corollary 6. */ } + +end: + _mesa_set_vp_override(ctx, GL_FALSE); } @@ -126,37 +147,48 @@ _mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height, GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + if (width < 0 || height < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glCopyPixels(width or height < 0)"); + return; + } + + if (type != GL_COLOR && type != GL_DEPTH && type != GL_STENCIL) { + _mesa_error(ctx, GL_INVALID_ENUM, "glCopyPixels(type=%s)", + _mesa_lookup_enum_by_nr(type)); + return; + } + + /* We're not using the current vertex program, and the driver may install + * it's own. + */ + _mesa_set_vp_override(ctx, GL_TRUE); + if (ctx->NewState) { _mesa_update_state(ctx); } - if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) { + if (!valid_fragment_program(ctx)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyPixels (invalid fragment program)"); - return; - } - - if (width < 0 || height < 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "glCopyPixels(width or height < 0)"); - return; + goto end; } if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT || ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, "glCopyPixels(incomplete framebuffer)" ); - return; + goto end; } if (!_mesa_source_buffer_exists(ctx, type) || !_mesa_dest_buffer_exists(ctx, type)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyPixels(missing source or dest buffer)"); - return; + goto end; } if (!ctx->Current.RasterPosValid || width ==0 || height == 0) { - return; + goto end; /* no-op, not an error */ } if (ctx->RenderMode == GL_RENDER) { @@ -181,6 +213,9 @@ _mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height, ASSERT(ctx->RenderMode == GL_SELECT); /* Do nothing. See OpenGL Spec, Appendix B, Corollary 6. */ } + +end: + _mesa_set_vp_override(ctx, GL_FALSE); } #endif /* _HAVE_FULL_GL */ @@ -208,7 +243,7 @@ _mesa_Bitmap( GLsizei width, GLsizei height, _mesa_update_state(ctx); } - if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) { + if (!valid_fragment_program(ctx)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBitmap (invalid fragment program)"); return; @@ -235,7 +270,7 @@ _mesa_Bitmap( GLsizei width, GLsizei height, "glBitmap(invalid PBO access)"); return; } - if (ctx->Unpack.BufferObj->Pointer) { + if (_mesa_bufferobj_mapped(ctx->Unpack.BufferObj)) { /* buffer is mapped - that's an error */ _mesa_error(ctx, GL_INVALID_OPERATION, "glBitmap(PBO is mapped)"); return; @@ -264,68 +299,3 @@ _mesa_Bitmap( GLsizei width, GLsizei height, ctx->Current.RasterPos[0] += xmove; ctx->Current.RasterPos[1] += ymove; } - - - -#if 0 /* experimental */ -/* - * Execute glDrawDepthPixelsMESA(). This function accepts both a color - * image and depth (Z) image. Rasterization produces fragments with - * color and Z taken from these images. This function is intended for - * Z-compositing. Normally, this operation requires two glDrawPixels - * calls with stencil testing. - */ -void GLAPIENTRY -_mesa_DrawDepthPixelsMESA( GLsizei width, GLsizei height, - GLenum colorFormat, GLenum colorType, - const GLvoid *colors, - GLenum depthType, const GLvoid *depths ) -{ - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); - - if (width < 0 || height < 0) { - _mesa_error( ctx, GL_INVALID_VALUE, - "glDrawDepthPixelsMESA(width or height < 0" ); - return; - } - - if (!ctx->Current.RasterPosValid) { - return; - } - - if (ctx->NewState) { - _mesa_update_state(ctx); - } - - if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { - _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, - "glDrawDepthPixelsMESA(incomplete framebuffer)"); - return; - } - - if (ctx->RenderMode == GL_RENDER) { - /* Round, to satisfy conformance tests (matches SGI's OpenGL) */ - GLint x = IROUND(ctx->Current.RasterPos[0]); - GLint y = IROUND(ctx->Current.RasterPos[1]); - ctx->Driver.DrawDepthPixelsMESA(ctx, x, y, width, height, - colorFormat, colorType, colors, - depthType, depths, &ctx->Unpack); - } - else if (ctx->RenderMode == GL_FEEDBACK) { - /* Feedback the current raster pos info */ - FLUSH_CURRENT( ctx, 0 ); - _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN ); - _mesa_feedback_vertex( ctx, - ctx->Current.RasterPos, - ctx->Current.RasterColor, - ctx->Current.RasterIndex, - ctx->Current.RasterTexCoords[0] ); - } - else { - ASSERT(ctx->RenderMode == GL_SELECT); - /* Do nothing. See OpenGL Spec, Appendix B, Corollary 6. */ - } -} - -#endif diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c index c60b58a492..8870a20d0e 100644 --- a/src/mesa/main/extensions.c +++ b/src/mesa/main/extensions.c @@ -78,6 +78,7 @@ static const struct { { OFF, "GL_ARB_texture_non_power_of_two", F(ARB_texture_non_power_of_two)}, { OFF, "GL_ARB_texture_rectangle", F(NV_texture_rectangle) }, { ON, "GL_ARB_transpose_matrix", F(ARB_transpose_matrix) }, + { OFF, "GL_ARB_vertex_array_bgra", F(EXT_vertex_array_bgra) }, { OFF, "GL_ARB_vertex_array_object", F(ARB_vertex_array_object) }, { ON, "GL_ARB_vertex_buffer_object", F(ARB_vertex_buffer_object) }, { OFF, "GL_ARB_vertex_program", F(ARB_vertex_program) }, @@ -413,6 +414,7 @@ _mesa_enable_2_0_extensions(GLcontext *ctx) ctx->Extensions.ARB_fragment_shader = GL_TRUE; #endif ctx->Extensions.ARB_point_sprite = GL_TRUE; + ctx->Extensions.EXT_blend_equation_separate = GL_TRUE; ctx->Extensions.ARB_texture_non_power_of_two = GL_TRUE; #if FEATURE_ARB_shader_objects ctx->Extensions.ARB_shader_objects = GL_TRUE; diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c index 83301f1e62..825a23090b 100644 --- a/src/mesa/main/fbobject.c +++ b/src/mesa/main/fbobject.c @@ -417,21 +417,22 @@ test_attachment_completeness(const GLcontext *ctx, GLenum format, if (format == GL_COLOR) { if (att->Renderbuffer->_BaseFormat != GL_RGB && att->Renderbuffer->_BaseFormat != GL_RGBA) { - ASSERT(att->Renderbuffer->RedBits); - ASSERT(att->Renderbuffer->GreenBits); - ASSERT(att->Renderbuffer->BlueBits); att_incomplete("bad renderbuffer color format"); att->Complete = GL_FALSE; return; } + ASSERT(att->Renderbuffer->RedBits); + ASSERT(att->Renderbuffer->GreenBits); + ASSERT(att->Renderbuffer->BlueBits); } else if (format == GL_DEPTH) { - ASSERT(att->Renderbuffer->DepthBits); if (att->Renderbuffer->_BaseFormat == GL_DEPTH_COMPONENT) { + ASSERT(att->Renderbuffer->DepthBits); /* OK */ } else if (ctx->Extensions.EXT_packed_depth_stencil && att->Renderbuffer->_BaseFormat == GL_DEPTH_STENCIL_EXT) { + ASSERT(att->Renderbuffer->DepthBits); /* OK */ } else { @@ -442,12 +443,13 @@ test_attachment_completeness(const GLcontext *ctx, GLenum format, } else { assert(format == GL_STENCIL); - ASSERT(att->Renderbuffer->StencilBits); if (att->Renderbuffer->_BaseFormat == GL_STENCIL_INDEX) { + ASSERT(att->Renderbuffer->StencilBits); /* OK */ } else if (ctx->Extensions.EXT_packed_depth_stencil && att->Renderbuffer->_BaseFormat == GL_DEPTH_STENCIL_EXT) { + ASSERT(att->Renderbuffer->StencilBits); /* OK */ } else { @@ -2038,7 +2040,9 @@ _mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, if (mask & GL_STENCIL_BUFFER_BIT) { struct gl_renderbuffer *readRb = readFb->_StencilBuffer; struct gl_renderbuffer *drawRb = drawFb->_StencilBuffer; - if (readRb->StencilBits != drawRb->StencilBits) { + if (!readRb || + !drawRb || + readRb->StencilBits != drawRb->StencilBits) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT(stencil buffer size mismatch"); return; @@ -2048,7 +2052,9 @@ _mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, if (mask & GL_DEPTH_BUFFER_BIT) { struct gl_renderbuffer *readRb = readFb->_DepthBuffer; struct gl_renderbuffer *drawRb = drawFb->_DepthBuffer; - if (readRb->DepthBits != drawRb->DepthBits) { + if (!readRb || + !drawRb || + readRb->DepthBits != drawRb->DepthBits) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT(depth buffer size mismatch"); return; diff --git a/src/mesa/main/fog.c b/src/mesa/main/fog.c index 50a61bd84b..4323d3db82 100644 --- a/src/mesa/main/fog.c +++ b/src/mesa/main/fog.c @@ -67,7 +67,7 @@ _mesa_Fogiv(GLenum pname, const GLint *params ) break; default: /* Error will be caught later in _mesa_Fogfv */ - ; + ASSIGN_4V(p, 0.0F, 0.0F, 0.0F, 0.0F); } _mesa_Fogfv(pname, p); } diff --git a/src/mesa/main/framebuffer.c b/src/mesa/main/framebuffer.c index 5a13c88a7a..dc79b8ca61 100644 --- a/src/mesa/main/framebuffer.c +++ b/src/mesa/main/framebuffer.c @@ -817,7 +817,7 @@ _mesa_update_framebuffer(GLcontext *ctx) /** * Check if the renderbuffer for a read operation (glReadPixels, glCopyPixels, - * glCopyTex[Sub]Image, etc. exists. + * glCopyTex[Sub]Image, etc) exists. * \param format a basic image format such as GL_RGB, GL_RGBA, GL_ALPHA, * GL_DEPTH_COMPONENT, etc. or GL_COLOR, GL_DEPTH, GL_STENCIL. * \return GL_TRUE if buffer exists, GL_FALSE otherwise @@ -825,8 +825,12 @@ _mesa_update_framebuffer(GLcontext *ctx) GLboolean _mesa_source_buffer_exists(GLcontext *ctx, GLenum format) { - const struct gl_renderbuffer_attachment *att - = ctx->ReadBuffer->Attachment; + const struct gl_renderbuffer_attachment *att = ctx->ReadBuffer->Attachment; + + /* If we don't know the framebuffer status, update it now */ + if (ctx->ReadBuffer->_Status == 0) { + _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer); + } if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { return GL_FALSE; @@ -850,10 +854,8 @@ _mesa_source_buffer_exists(GLcontext *ctx, GLenum format) if (ctx->ReadBuffer->_ColorReadBuffer == NULL) { return GL_FALSE; } - /* XXX enable this post 6.5 release: ASSERT(ctx->ReadBuffer->_ColorReadBuffer->RedBits > 0 || ctx->ReadBuffer->_ColorReadBuffer->IndexBits > 0); - */ break; case GL_DEPTH: case GL_DEPTH_COMPONENT: @@ -891,13 +893,17 @@ _mesa_source_buffer_exists(GLcontext *ctx, GLenum format) /** * As above, but for drawing operations. - * XXX code do some code merging w/ above function. + * XXX could do some code merging w/ above function. */ GLboolean _mesa_dest_buffer_exists(GLcontext *ctx, GLenum format) { - const struct gl_renderbuffer_attachment *att - = ctx->ReadBuffer->Attachment; + const struct gl_renderbuffer_attachment *att = ctx->DrawBuffer->Attachment; + + /* If we don't know the framebuffer status, update it now */ + if (ctx->DrawBuffer->_Status == 0) { + _mesa_test_framebuffer_completeness(ctx, ctx->DrawBuffer); + } if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { return GL_FALSE; @@ -918,7 +924,7 @@ _mesa_dest_buffer_exists(GLcontext *ctx, GLenum format) case GL_BGRA: case GL_ABGR_EXT: case GL_COLOR_INDEX: - /* nothing special */ + /* Nothing special since GL_DRAW_BUFFER could be GL_NONE. */ /* Could assert that colorbuffer has RedBits > 0 */ break; case GL_DEPTH: @@ -945,7 +951,7 @@ _mesa_dest_buffer_exists(GLcontext *ctx, GLenum format) break; default: _mesa_problem(ctx, - "Unexpected format 0x%x in _mesa_source_buffer_exists", + "Unexpected format 0x%x in _mesa_dest_buffer_exists", format); return GL_FALSE; } diff --git a/src/mesa/main/getstring.c b/src/mesa/main/getstring.c index 41fd786d7d..6599ed9698 100644 --- a/src/mesa/main/getstring.c +++ b/src/mesa/main/getstring.c @@ -266,5 +266,6 @@ _mesa_GetError( void ) _mesa_debug(ctx, "glGetError <-- %s\n", _mesa_lookup_enum_by_nr(e)); ctx->ErrorValue = (GLenum) GL_NO_ERROR; + ctx->ErrorDebugCount = 0; return e; } diff --git a/src/mesa/main/histogram.c b/src/mesa/main/histogram.c index 5fee4fd0e3..726a50d3b1 100644 --- a/src/mesa/main/histogram.c +++ b/src/mesa/main/histogram.c @@ -649,7 +649,7 @@ _mesa_GetMinmax(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvo return; } - if (ctx->Pack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { /* pack min/max values into a PBO */ GLubyte *buf; if (!_mesa_validate_pbo_access(1, &ctx->Pack, 2, 1, 1, @@ -687,7 +687,7 @@ _mesa_GetMinmax(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvo format, type, values, &ctx->Pack, 0x0); } - if (ctx->Pack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, ctx->Pack.BufferObj); } @@ -733,7 +733,7 @@ _mesa_GetHistogram(GLenum target, GLboolean reset, GLenum format, GLenum type, G return; } - if (ctx->Pack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { /* pack min/max values into a PBO */ GLubyte *buf; if (!_mesa_validate_pbo_access(1, &ctx->Pack, ctx->Histogram.Width, 1, 1, @@ -761,7 +761,7 @@ _mesa_GetHistogram(GLenum target, GLboolean reset, GLenum format, GLenum type, G (CONST GLuint (*)[4]) ctx->Histogram.Count, format, type, values, &ctx->Pack); - if (ctx->Pack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, ctx->Pack.BufferObj); } diff --git a/src/mesa/main/image.c b/src/mesa/main/image.c index 090e5eb330..d77c593ac7 100644 --- a/src/mesa/main/image.c +++ b/src/mesa/main/image.c @@ -531,6 +531,210 @@ _mesa_is_legal_format_and_type( GLcontext *ctx, GLenum format, GLenum type ) /** + * Test if the given image format is a color/RGBA format (i.e., not color + * index, depth, stencil, etc). + * \param format the image format value (may by an internal texture format) + * \return GL_TRUE if its a color/RGBA format, GL_FALSE otherwise. + */ +GLboolean +_mesa_is_color_format(GLenum format) +{ + switch (format) { + case GL_RED: + case GL_GREEN: + case GL_BLUE: + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + case GL_ALPHA12: + case GL_ALPHA16: + case 1: + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + case 2: + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE4_ALPHA4: + case GL_LUMINANCE6_ALPHA2: + case GL_LUMINANCE8_ALPHA8: + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY8: + case GL_INTENSITY12: + case GL_INTENSITY16: + case 3: + case GL_RGB: + case GL_BGR: + case GL_R3_G3_B2: + case GL_RGB4: + case GL_RGB5: + case GL_RGB8: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + case 4: + case GL_ABGR_EXT: + case GL_RGBA: + case GL_BGRA: + case GL_RGBA2: + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + /* float texture formats */ + case GL_ALPHA16F_ARB: + case GL_ALPHA32F_ARB: + case GL_LUMINANCE16F_ARB: + case GL_LUMINANCE32F_ARB: + case GL_LUMINANCE_ALPHA16F_ARB: + case GL_LUMINANCE_ALPHA32F_ARB: + case GL_INTENSITY16F_ARB: + case GL_INTENSITY32F_ARB: + case GL_RGB16F_ARB: + case GL_RGB32F_ARB: + case GL_RGBA16F_ARB: + case GL_RGBA32F_ARB: + /* compressed formats */ + case GL_COMPRESSED_ALPHA: + case GL_COMPRESSED_LUMINANCE: + case GL_COMPRESSED_LUMINANCE_ALPHA: + case GL_COMPRESSED_INTENSITY: + case GL_COMPRESSED_RGB: + case GL_COMPRESSED_RGBA: + case GL_RGB_S3TC: + case GL_RGB4_S3TC: + case GL_RGBA_S3TC: + case GL_RGBA4_S3TC: + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + case GL_COMPRESSED_RGB_FXT1_3DFX: + case GL_COMPRESSED_RGBA_FXT1_3DFX: +#if FEATURE_EXT_texture_sRGB + case GL_SRGB_EXT: + case GL_SRGB8_EXT: + case GL_SRGB_ALPHA_EXT: + case GL_SRGB8_ALPHA8_EXT: + case GL_SLUMINANCE_ALPHA_EXT: + case GL_SLUMINANCE8_ALPHA8_EXT: + case GL_SLUMINANCE_EXT: + case GL_SLUMINANCE8_EXT: + case GL_COMPRESSED_SRGB_EXT: + case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_SRGB_ALPHA_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: + case GL_COMPRESSED_SLUMINANCE_EXT: + case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT: +#endif /* FEATURE_EXT_texture_sRGB */ + return GL_TRUE; + /* signed texture formats */ + case GL_RGBA_SNORM: + case GL_RGBA8_SNORM: + return GL_TRUE; + case GL_YCBCR_MESA: /* not considered to be RGB */ + /* fall-through */ + default: + return GL_FALSE; + } +} + + +/** + * Test if the given image format is a color index format. + */ +GLboolean +_mesa_is_index_format(GLenum format) +{ + switch (format) { + case GL_COLOR_INDEX: + case GL_COLOR_INDEX1_EXT: + case GL_COLOR_INDEX2_EXT: + case GL_COLOR_INDEX4_EXT: + case GL_COLOR_INDEX8_EXT: + case GL_COLOR_INDEX12_EXT: + case GL_COLOR_INDEX16_EXT: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + +/** + * Test if the given image format is a depth component format. + */ +GLboolean +_mesa_is_depth_format(GLenum format) +{ + switch (format) { + case GL_DEPTH_COMPONENT: + case GL_DEPTH_COMPONENT16: + case GL_DEPTH_COMPONENT24: + case GL_DEPTH_COMPONENT32: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + +/** + * Test if the given image format is a YCbCr format. + */ +GLboolean +_mesa_is_ycbcr_format(GLenum format) +{ + switch (format) { + case GL_YCBCR_MESA: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + +/** + * Test if the given image format is a depth+stencil format. + */ +GLboolean +_mesa_is_depthstencil_format(GLenum format) +{ + switch (format) { + case GL_DEPTH24_STENCIL8_EXT: + case GL_DEPTH_STENCIL_EXT: + return GL_TRUE; + default: + return GL_FALSE; + } +} + +/** + * Test if the given image format is a dudv format. + */ +GLboolean +_mesa_is_dudv_format(GLenum format) +{ + switch (format) { + case GL_DUDV_ATI: + case GL_DU8DV8_ATI: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + +/** * Return the address of a specific pixel in an image (1D, 2D or 3D). * * Pixel unpacking/packing parameters are observed according to \p packing. @@ -5335,3 +5539,181 @@ _mesa_clip_to_region(GLint xmin, GLint ymin, return GL_TRUE; } + + +/** + * Clip dst coords against Xmax (or Ymax). + */ +static INLINE void +clip_right_or_top(GLint *srcX0, GLint *srcX1, + GLint *dstX0, GLint *dstX1, + GLint maxValue) +{ + GLfloat t, bias; + + if (*dstX1 > maxValue) { + /* X1 outside right edge */ + ASSERT(*dstX0 < maxValue); /* X0 should be inside right edge */ + t = (GLfloat) (maxValue - *dstX0) / (GLfloat) (*dstX1 - *dstX0); + /* chop off [t, 1] part */ + ASSERT(t >= 0.0 && t <= 1.0); + *dstX1 = maxValue; + bias = (*srcX0 < *srcX1) ? 0.5 : -0.5; + *srcX1 = *srcX0 + (GLint) (t * (*srcX1 - *srcX0) + bias); + } + else if (*dstX0 > maxValue) { + /* X0 outside right edge */ + ASSERT(*dstX1 < maxValue); /* X1 should be inside right edge */ + t = (GLfloat) (maxValue - *dstX1) / (GLfloat) (*dstX0 - *dstX1); + /* chop off [t, 1] part */ + ASSERT(t >= 0.0 && t <= 1.0); + *dstX0 = maxValue; + bias = (*srcX0 < *srcX1) ? -0.5 : 0.5; + *srcX0 = *srcX1 + (GLint) (t * (*srcX0 - *srcX1) + bias); + } +} + + +/** + * Clip dst coords against Xmin (or Ymin). + */ +static INLINE void +clip_left_or_bottom(GLint *srcX0, GLint *srcX1, + GLint *dstX0, GLint *dstX1, + GLint minValue) +{ + GLfloat t, bias; + + if (*dstX0 < minValue) { + /* X0 outside left edge */ + ASSERT(*dstX1 > minValue); /* X1 should be inside left edge */ + t = (GLfloat) (minValue - *dstX0) / (GLfloat) (*dstX1 - *dstX0); + /* chop off [0, t] part */ + ASSERT(t >= 0.0 && t <= 1.0); + *dstX0 = minValue; + bias = (*srcX0 < *srcX1) ? 0.5 : -0.5; /* flipped??? */ + *srcX0 = *srcX0 + (GLint) (t * (*srcX1 - *srcX0) + bias); + } + else if (*dstX1 < minValue) { + /* X1 outside left edge */ + ASSERT(*dstX0 > minValue); /* X0 should be inside left edge */ + t = (GLfloat) (minValue - *dstX1) / (GLfloat) (*dstX0 - *dstX1); + /* chop off [0, t] part */ + ASSERT(t >= 0.0 && t <= 1.0); + *dstX1 = minValue; + bias = (*srcX0 < *srcX1) ? 0.5 : -0.5; + *srcX1 = *srcX1 + (GLint) (t * (*srcX0 - *srcX1) + bias); + } +} + + +/** + * Do clipping of blit src/dest rectangles. + * The dest rect is clipped against both the buffer bounds and scissor bounds. + * The src rect is just clipped against the buffer bounds. + * + * When either the src or dest rect is clipped, the other is also clipped + * proportionately! + * + * Note that X0 need not be less than X1 (same for Y) for either the source + * and dest rects. That makes the clipping a little trickier. + * + * \return GL_TRUE if anything is left to draw, GL_FALSE if totally clipped + */ +GLboolean +_mesa_clip_blit(GLcontext *ctx, + GLint *srcX0, GLint *srcY0, GLint *srcX1, GLint *srcY1, + GLint *dstX0, GLint *dstY0, GLint *dstX1, GLint *dstY1) +{ + const GLint srcXmin = 0; + const GLint srcXmax = ctx->ReadBuffer->Width; + const GLint srcYmin = 0; + const GLint srcYmax = ctx->ReadBuffer->Height; + + /* these include scissor bounds */ + const GLint dstXmin = ctx->DrawBuffer->_Xmin; + const GLint dstXmax = ctx->DrawBuffer->_Xmax; + const GLint dstYmin = ctx->DrawBuffer->_Ymin; + const GLint dstYmax = ctx->DrawBuffer->_Ymax; + + /* + printf("PreClipX: src: %d .. %d dst: %d .. %d\n", + *srcX0, *srcX1, *dstX0, *dstX1); + printf("PreClipY: src: %d .. %d dst: %d .. %d\n", + *srcY0, *srcY1, *dstY0, *dstY1); + */ + + /* trivial rejection tests */ + if (*dstX0 == *dstX1) + return GL_FALSE; /* no width */ + if (*dstX0 <= dstXmin && *dstX1 <= dstXmin) + return GL_FALSE; /* totally out (left) of bounds */ + if (*dstX0 >= dstXmax && *dstX1 >= dstXmax) + return GL_FALSE; /* totally out (right) of bounds */ + + if (*dstY0 == *dstY1) + return GL_FALSE; + if (*dstY0 <= dstYmin && *dstY1 <= dstYmin) + return GL_FALSE; + if (*dstY0 >= dstYmax && *dstY1 >= dstYmax) + return GL_FALSE; + + if (*srcX0 == *srcX1) + return GL_FALSE; + if (*srcX0 <= srcXmin && *srcX1 <= srcXmin) + return GL_FALSE; + if (*srcX0 >= srcXmax && *srcX1 >= srcXmax) + return GL_FALSE; + + if (*srcY0 == *srcY1) + return GL_FALSE; + if (*srcY0 <= srcYmin && *srcY1 <= srcYmin) + return GL_FALSE; + if (*srcY0 >= srcYmax && *srcY1 >= srcYmax) + return GL_FALSE; + + /* + * dest clip + */ + clip_right_or_top(srcX0, srcX1, dstX0, dstX1, dstXmax); + clip_right_or_top(srcY0, srcY1, dstY0, dstY1, dstYmax); + clip_left_or_bottom(srcX0, srcX1, dstX0, dstX1, dstXmin); + clip_left_or_bottom(srcY0, srcY1, dstY0, dstY1, dstYmin); + + /* + * src clip (just swap src/dst values from above) + */ + clip_right_or_top(dstX0, dstX1, srcX0, srcX1, srcXmax); + clip_right_or_top(dstY0, dstY1, srcY0, srcY1, srcYmax); + clip_left_or_bottom(dstX0, dstX1, srcX0, srcX1, srcXmin); + clip_left_or_bottom(dstY0, dstY1, srcY0, srcY1, srcYmin); + + /* + printf("PostClipX: src: %d .. %d dst: %d .. %d\n", + *srcX0, *srcX1, *dstX0, *dstX1); + printf("PostClipY: src: %d .. %d dst: %d .. %d\n", + *srcY0, *srcY1, *dstY0, *dstY1); + */ + + ASSERT(*dstX0 >= dstXmin); + ASSERT(*dstX0 <= dstXmax); + ASSERT(*dstX1 >= dstXmin); + ASSERT(*dstX1 <= dstXmax); + + ASSERT(*dstY0 >= dstYmin); + ASSERT(*dstY0 <= dstYmax); + ASSERT(*dstY1 >= dstYmin); + ASSERT(*dstY1 <= dstYmax); + + ASSERT(*srcX0 >= srcXmin); + ASSERT(*srcX0 <= srcXmax); + ASSERT(*srcX1 >= srcXmin); + ASSERT(*srcX1 <= srcXmax); + + ASSERT(*srcY0 >= srcYmin); + ASSERT(*srcY0 <= srcYmax); + ASSERT(*srcY1 >= srcYmin); + ASSERT(*srcY1 <= srcYmax); + + return GL_TRUE; +} diff --git a/src/mesa/main/image.h b/src/mesa/main/image.h index b26c27e5a8..20459a5f1e 100644 --- a/src/mesa/main/image.h +++ b/src/mesa/main/image.h @@ -54,6 +54,24 @@ _mesa_bytes_per_pixel( GLenum format, GLenum type ); extern GLboolean _mesa_is_legal_format_and_type( GLcontext *ctx, GLenum format, GLenum type ); +extern GLboolean +_mesa_is_color_format(GLenum format); + +extern GLboolean +_mesa_is_index_format(GLenum format); + +extern GLboolean +_mesa_is_depth_format(GLenum format); + +extern GLboolean +_mesa_is_ycbcr_format(GLenum format); + +extern GLboolean +_mesa_is_depthstencil_format(GLenum format); + +extern GLboolean +_mesa_is_dudv_format(GLenum format); + extern GLvoid * _mesa_image_address( GLuint dimensions, @@ -291,4 +309,10 @@ _mesa_clip_to_region(GLint xmin, GLint ymin, GLint *x, GLint *y, GLsizei *width, GLsizei *height ); +extern GLboolean +_mesa_clip_blit(GLcontext *ctx, + GLint *srcX0, GLint *srcY0, GLint *srcX1, GLint *srcY1, + GLint *dstX0, GLint *dstY0, GLint *dstX1, GLint *dstY1); + + #endif diff --git a/src/mesa/main/imports.c b/src/mesa/main/imports.c index 1722579e82..6ffaddcde9 100644 --- a/src/mesa/main/imports.c +++ b/src/mesa/main/imports.c @@ -911,6 +911,20 @@ _mesa_strtod( const char *s, char **end ) return strtod(s, end); } +/** Compute simple checksum/hash for a string */ +unsigned int +_mesa_str_checksum(const char *str) +{ + /* This could probably be much better */ + unsigned int sum, i; + const char *c; + sum = i = 1; + for (c = str; *c; c++) + sum += *c * (i % 100); + return sum; +} + + /*@}*/ @@ -1021,23 +1035,59 @@ output_if_debug(const char *prefixString, const char *outputString, } } -static const char *error_string( GLenum error ); -static void flush_delayed_errors( GLcontext *ctx ) +/** + * Return string version of GL error code. + */ +static const char * +error_string( GLenum error ) +{ + switch (error) { + case GL_NO_ERROR: + return "GL_NO_ERROR"; + case GL_INVALID_VALUE: + return "GL_INVALID_VALUE"; + case GL_INVALID_ENUM: + return "GL_INVALID_ENUM"; + case GL_INVALID_OPERATION: + return "GL_INVALID_OPERATION"; + case GL_STACK_OVERFLOW: + return "GL_STACK_OVERFLOW"; + case GL_STACK_UNDERFLOW: + return "GL_STACK_UNDERFLOW"; + case GL_OUT_OF_MEMORY: + return "GL_OUT_OF_MEMORY"; + case GL_TABLE_TOO_LARGE: + return "GL_TABLE_TOO_LARGE"; + case GL_INVALID_FRAMEBUFFER_OPERATION_EXT: + return "GL_INVALID_FRAMEBUFFER_OPERATION"; + default: + return "unknown"; + } +} + + +/** + * When a new type of error is recorded, print a message describing + * previous errors which were accumulated. + */ +static void +flush_delayed_errors( GLcontext *ctx ) { - char s2[MAXSTRING]; + char s[MAXSTRING]; if (ctx->ErrorDebugCount) { - _mesa_snprintf(s2, MAXSTRING, "%d similar %s errors", + _mesa_snprintf(s, MAXSTRING, "%d similar %s errors", ctx->ErrorDebugCount, error_string(ctx->ErrorValue)); - output_if_debug("Mesa: ", s2, GL_TRUE); + output_if_debug("Mesa", s, GL_TRUE); ctx->ErrorDebugCount = 0; } } + /** * Report a warning (a recoverable error condition) to stderr if * either DEBUG is defined or the MESA_DEBUG env var is set. @@ -1083,31 +1133,6 @@ _mesa_problem( const GLcontext *ctx, const char *fmtString, ... ) fprintf(stderr, "Please report at bugzilla.freedesktop.org\n"); } -static const char *error_string( GLenum error ) -{ - switch (error) { - case GL_NO_ERROR: - return "GL_NO_ERROR"; - case GL_INVALID_VALUE: - return "GL_INVALID_VALUE"; - case GL_INVALID_ENUM: - return "GL_INVALID_ENUM"; - case GL_INVALID_OPERATION: - return "GL_INVALID_OPERATION"; - case GL_STACK_OVERFLOW: - return "GL_STACK_OVERFLOW"; - case GL_STACK_UNDERFLOW: - return "GL_STACK_UNDERFLOW"; - case GL_OUT_OF_MEMORY: - return "GL_OUT_OF_MEMORY"; - case GL_TABLE_TOO_LARGE: - return "GL_TABLE_TOO_LARGE"; - case GL_INVALID_FRAMEBUFFER_OPERATION_EXT: - return "GL_INVALID_FRAMEBUFFER_OPERATION"; - default: - return "unknown"; - } -} /** * Record an OpenGL state error. These usually occur when the user diff --git a/src/mesa/main/imports.h b/src/mesa/main/imports.h index 7b61e22e93..fb85f0862c 100644 --- a/src/mesa/main/imports.h +++ b/src/mesa/main/imports.h @@ -586,6 +586,9 @@ _mesa_atoi( const char *s ); extern double _mesa_strtod( const char *s, char **end ); +extern unsigned int +_mesa_str_checksum(const char *str); + extern int _mesa_sprintf( char *str, const char *fmt, ... ); diff --git a/src/mesa/main/light.c b/src/mesa/main/light.c index 0f0d831fee..10c89f4368 100644 --- a/src/mesa/main/light.c +++ b/src/mesa/main/light.c @@ -528,7 +528,7 @@ _mesa_LightModeliv( GLenum pname, const GLint *params ) break; default: /* Error will be caught later in gl_LightModelfv */ - ; + ASSIGN_4V(fparam, 0.0F, 0.0F, 0.0F, 0.0F); } _mesa_LightModelfv( pname, fparam ); } @@ -1256,15 +1256,15 @@ _mesa_update_tnl_spaces( GLcontext *ctx, GLuint new_state ) ctx->Driver.LightingSpaceChange( ctx ); } else { - GLuint new_state = ctx->NewState; + GLuint new_state2 = ctx->NewState; /* Recalculate that same state only if it has been invalidated * by other statechanges. */ - if (new_state & _NEW_MODELVIEW) + if (new_state2 & _NEW_MODELVIEW) update_modelview_scale(ctx); - if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW)) + if (new_state2 & (_NEW_LIGHT|_NEW_MODELVIEW)) compute_light_positions( ctx ); } } diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index d0309f5e90..41172788ef 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -83,6 +83,7 @@ /*@{*/ struct _mesa_HashTable; struct gl_attrib_node; +struct gl_meta_state; struct gl_pixelstore_attrib; struct gl_program_cache; struct gl_texture_format; @@ -227,7 +228,9 @@ typedef enum FRAG_ATTRIB_TEX5 = 9, FRAG_ATTRIB_TEX6 = 10, FRAG_ATTRIB_TEX7 = 11, - FRAG_ATTRIB_VAR0 = 12, /**< shader varying */ + FRAG_ATTRIB_FACE = 12, /**< front/back face */ + FRAG_ATTRIB_PNTC = 13, /**< sprite/point coord */ + FRAG_ATTRIB_VAR0 = 14, /**< shader varying */ FRAG_ATTRIB_MAX = (FRAG_ATTRIB_VAR0 + MAX_VARYING) } gl_frag_attrib; @@ -239,6 +242,8 @@ typedef enum #define FRAG_BIT_COL0 (1 << FRAG_ATTRIB_COL0) #define FRAG_BIT_COL1 (1 << FRAG_ATTRIB_COL1) #define FRAG_BIT_FOGC (1 << FRAG_ATTRIB_FOGC) +#define FRAG_BIT_FACE (1 << FRAG_ATTRIB_FACE) +#define FRAG_BIT_PNTC (1 << FRAG_ATTRIB_PNTC) #define FRAG_BIT_TEX0 (1 << FRAG_ATTRIB_TEX0) #define FRAG_BIT_TEX1 (1 << FRAG_ATTRIB_TEX1) #define FRAG_BIT_TEX2 (1 << FRAG_ATTRIB_TEX2) @@ -1834,9 +1839,6 @@ struct gl_fragment_program struct gl_program Base; /**< base class */ GLenum FogOption; GLboolean UsesKill; /**< shader uses KIL instruction */ - GLboolean UsesPointCoord; /**< shader uses gl_PointCoord */ - GLboolean UsesFrontFacing; /**< shader used gl_FrontFacing */ - GLboolean UsesFogFragCoord; /**< shader used gl_FogFragCoord */ }; @@ -2004,6 +2006,7 @@ struct gl_shader GLboolean Main; /**< shader defines main() */ GLboolean UnresolvedRefs; const GLchar *Source; /**< Source code string */ + GLuint SourceChecksum; /**< for debug/logging purposes */ struct gl_program *Program; /**< Post-compile assembly code */ GLchar *InfoLog; struct gl_sl_pragmas Pragmas; @@ -2034,6 +2037,7 @@ struct gl_shader_program struct gl_program_parameter_list *Varying; GLboolean LinkStatus; /**< GL_LINK_STATUS */ GLboolean Validated; + GLboolean _Used; /**< Ever used for drawing? */ GLchar *InfoLog; }; @@ -2981,6 +2985,8 @@ struct __GLcontextRec struct gl_buffer_object *CopyWriteBuffer; /**< GL_ARB_copy_buffer */ /*@}*/ + struct gl_meta_state *Meta; /**< for "meta" operations */ + #if FEATURE_EXT_framebuffer_object struct gl_renderbuffer *CurrentRenderbuffer; #endif diff --git a/src/mesa/main/pixel.c b/src/mesa/main/pixel.c index d9f3e476e8..25f55a422f 100644 --- a/src/mesa/main/pixel.c +++ b/src/mesa/main/pixel.c @@ -158,7 +158,7 @@ _mesa_PixelMapfv( GLenum map, GLsizei mapsize, const GLfloat *values ) FLUSH_VERTICES(ctx, _NEW_PIXEL); - if (ctx->Unpack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) { /* unpack pixelmap from PBO */ GLubyte *buf; /* Note, need to use DefaultPacking and Unpack's buffer object */ @@ -188,7 +188,7 @@ _mesa_PixelMapfv( GLenum map, GLsizei mapsize, const GLfloat *values ) store_pixelmap(ctx, map, mapsize, values); - if (ctx->Unpack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) { ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, ctx->Unpack.BufferObj); } @@ -217,7 +217,7 @@ _mesa_PixelMapuiv(GLenum map, GLsizei mapsize, const GLuint *values ) FLUSH_VERTICES(ctx, _NEW_PIXEL); - if (ctx->Unpack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) { /* unpack pixelmap from PBO */ GLubyte *buf; /* Note, need to use DefaultPacking and Unpack's buffer object */ @@ -259,7 +259,7 @@ _mesa_PixelMapuiv(GLenum map, GLsizei mapsize, const GLuint *values ) } } - if (ctx->Unpack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) { ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, ctx->Unpack.BufferObj); } @@ -290,7 +290,7 @@ _mesa_PixelMapusv(GLenum map, GLsizei mapsize, const GLushort *values ) FLUSH_VERTICES(ctx, _NEW_PIXEL); - if (ctx->Unpack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) { /* unpack pixelmap from PBO */ GLubyte *buf; /* Note, need to use DefaultPacking and Unpack's buffer object */ @@ -333,7 +333,7 @@ _mesa_PixelMapusv(GLenum map, GLsizei mapsize, const GLushort *values ) } } - if (ctx->Unpack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) { ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, ctx->Unpack.BufferObj); } @@ -359,7 +359,7 @@ _mesa_GetPixelMapfv( GLenum map, GLfloat *values ) mapsize = pm->Size; - if (ctx->Pack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { /* pack pixelmap into PBO */ GLubyte *buf; /* Note, need to use DefaultPacking and Pack's buffer object */ @@ -397,7 +397,7 @@ _mesa_GetPixelMapfv( GLenum map, GLfloat *values ) MEMCPY(values, pm->Map, mapsize * sizeof(GLfloat)); } - if (ctx->Pack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, ctx->Pack.BufferObj); } @@ -420,7 +420,7 @@ _mesa_GetPixelMapuiv( GLenum map, GLuint *values ) } mapsize = pm->Size; - if (ctx->Pack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { /* pack pixelmap into PBO */ GLubyte *buf; /* Note, need to use DefaultPacking and Pack's buffer object */ @@ -458,7 +458,7 @@ _mesa_GetPixelMapuiv( GLenum map, GLuint *values ) } } - if (ctx->Pack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, ctx->Pack.BufferObj); } @@ -481,7 +481,7 @@ _mesa_GetPixelMapusv( GLenum map, GLushort *values ) } mapsize = pm ? pm->Size : 0; - if (ctx->Pack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { /* pack pixelmap into PBO */ GLubyte *buf; /* Note, need to use DefaultPacking and Pack's buffer object */ @@ -528,7 +528,7 @@ _mesa_GetPixelMapusv( GLenum map, GLushort *values ) } } - if (ctx->Pack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, ctx->Pack.BufferObj); } diff --git a/src/mesa/main/polygon.c b/src/mesa/main/polygon.c index 564250b881..d11c9424d5 100644 --- a/src/mesa/main/polygon.c +++ b/src/mesa/main/polygon.c @@ -193,7 +193,7 @@ _mesa_PolygonMode( GLenum face, GLenum mode ) void _mesa_polygon_stipple(GLcontext *ctx, const GLubyte *pattern) { - if (ctx->Unpack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) { /* Get/unpack the stipple pattern from a PBO */ GLubyte *buf; if (!_mesa_validate_pbo_access(2, &ctx->Unpack, 32, 32, 1, @@ -258,7 +258,7 @@ _mesa_GetPolygonStipple( GLubyte *dest ) /* XXX someday we may put this code into a separate function and call * it with ctx->Driver.GetPolygonStipple(). */ - if (ctx->Pack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { /* Put/pack the stipple pattern into a PBO */ GLubyte *buf; if (!_mesa_validate_pbo_access(2, &ctx->Pack, 32, 32, 1, diff --git a/src/mesa/main/readpix.c b/src/mesa/main/readpix.c index 2326776ecb..feea1d375f 100644 --- a/src/mesa/main/readpix.c +++ b/src/mesa/main/readpix.c @@ -44,6 +44,10 @@ _mesa_error_check_format_type(GLcontext *ctx, GLenum format, GLenum type, GLboolean drawing) { const char *readDraw = drawing ? "Draw" : "Read"; + const GLboolean reading = !drawing; + + /* state validation should have already been done */ + ASSERT(ctx->NewState == 0x0); if (ctx->Extensions.EXT_packed_depth_stencil && type == GL_UNSIGNED_INT_24_8_EXT @@ -73,32 +77,45 @@ _mesa_error_check_format_type(GLcontext *ctx, GLenum format, GLenum type, case GL_RGBA: case GL_BGRA: case GL_ABGR_EXT: - if (drawing && !ctx->Visual.rgbMode) { - _mesa_error(ctx, GL_INVALID_OPERATION, + if (drawing) { + if (!ctx->DrawBuffer->Visual.rgbMode) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels(drawing RGB pixels into color index buffer)"); - return GL_TRUE; + return GL_TRUE; + } } - if (!drawing && !_mesa_dest_buffer_exists(ctx, GL_COLOR)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glReadPixels(no color buffer)"); - return GL_TRUE; + else { + /* reading */ + if (!_mesa_source_buffer_exists(ctx, GL_COLOR)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glReadPixels(no color buffer)"); + return GL_TRUE; + } } break; case GL_COLOR_INDEX: - if (!drawing && ctx->Visual.rgbMode) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glReadPixels(reading color index format from RGB buffer)"); - return GL_TRUE; + if (drawing) { + if (ctx->DrawBuffer->Visual.rgbMode && + (ctx->PixelMaps.ItoR.Size == 0 || + ctx->PixelMaps.ItoG.Size == 0 || + ctx->PixelMaps.ItoB.Size == 0)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glDrawPixels(drawing color index pixels into RGB buffer)"); + return GL_TRUE; + } } - if (!drawing && !_mesa_dest_buffer_exists(ctx, GL_COLOR)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glReadPixels(no color buffer)"); - return GL_TRUE; + else { + /* reading */ + if (!_mesa_source_buffer_exists(ctx, GL_COLOR)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glReadPixels(no color buffer)"); + return GL_TRUE; + } } break; case GL_STENCIL_INDEX: if ((drawing && !_mesa_dest_buffer_exists(ctx, format)) || - (!drawing && !_mesa_source_buffer_exists(ctx, format))) { + (reading && !_mesa_source_buffer_exists(ctx, format))) { _mesa_error(ctx, GL_INVALID_OPERATION, "gl%sPixels(no stencil buffer)", readDraw); return GL_TRUE; @@ -118,7 +135,7 @@ _mesa_error_check_format_type(GLcontext *ctx, GLenum format, GLenum type, return GL_TRUE; } if ((drawing && !_mesa_dest_buffer_exists(ctx, format)) || - (!drawing && !_mesa_source_buffer_exists(ctx, format))) { + (reading && !_mesa_source_buffer_exists(ctx, format))) { _mesa_error(ctx, GL_INVALID_OPERATION, "gl%sPixels(no depth or stencil buffer)", readDraw); return GL_TRUE; @@ -173,7 +190,7 @@ _mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height, if (width == 0 || height == 0) return; /* nothing to do */ - if (ctx->Pack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { if (!_mesa_validate_pbo_access(2, &ctx->Pack, width, height, 1, format, type, pixels)) { _mesa_error(ctx, GL_INVALID_OPERATION, @@ -181,7 +198,7 @@ _mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height, return; } - if (ctx->Pack.BufferObj->Pointer) { + if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) { /* buffer is mapped - that's an error */ _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(PBO is mapped)"); return; diff --git a/src/mesa/main/shared.c b/src/mesa/main/shared.c index ad6e6ce7cd..93bbccd3c7 100644 --- a/src/mesa/main/shared.c +++ b/src/mesa/main/shared.c @@ -196,7 +196,7 @@ delete_bufferobj_cb(GLuint id, void *data, void *userData) { struct gl_buffer_object *bufObj = (struct gl_buffer_object *) data; GLcontext *ctx = (GLcontext *) userData; - if (bufObj->Pointer) { + if (_mesa_bufferobj_mapped(bufObj)) { ctx->Driver.UnmapBuffer(ctx, 0, bufObj); bufObj->Pointer = NULL; } diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c index d8191ab518..140a998df2 100644 --- a/src/mesa/main/state.c +++ b/src/mesa/main/state.c @@ -547,7 +547,8 @@ _mesa_update_state_locked( GLcontext *ctx ) /* Determine which state flags effect vertex/fragment program state */ if (ctx->FragmentProgram._MaintainTexEnvProgram) { prog_flags |= (_NEW_TEXTURE | _NEW_FOG | - _NEW_ARRAY | _NEW_LIGHT | _NEW_POINT | _NEW_RENDERMODE); + _NEW_ARRAY | _NEW_LIGHT | _NEW_POINT | _NEW_RENDERMODE | + _NEW_PROGRAM); } if (ctx->VertexProgram._MaintainTnlProgram) { prog_flags |= (_NEW_ARRAY | _NEW_TEXTURE | _NEW_TEXTURE_MATRIX | @@ -712,6 +713,6 @@ _mesa_set_vp_override(GLcontext *ctx, GLboolean flag) /* Set one of the bits which will trigger fragment program * regeneration: */ - ctx->NewState |= _NEW_ARRAY; + ctx->NewState |= _NEW_PROGRAM; } } diff --git a/src/mesa/main/texenv.c b/src/mesa/main/texenv.c index 4c04a7ed37..6d86a4275c 100644 --- a/src/mesa/main/texenv.c +++ b/src/mesa/main/texenv.c @@ -35,6 +35,7 @@ #include "main/enums.h" #include "main/macros.h" #include "main/texenv.h" +#include "main/texstate.h" #define TE_ERROR(errCode, msg, value) \ @@ -466,7 +467,7 @@ _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param ) return; } - texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texUnit = _mesa_get_current_tex_unit(ctx); if (target == GL_TEXTURE_ENV) { switch (pname) { @@ -793,7 +794,7 @@ _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params ) return; } - texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texUnit = _mesa_get_current_tex_unit(ctx); if (target == GL_TEXTURE_ENV) { if (pname == GL_TEXTURE_ENV_COLOR) { @@ -857,7 +858,7 @@ _mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params ) return; } - texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texUnit = _mesa_get_current_tex_unit(ctx); if (target == GL_TEXTURE_ENV) { if (pname == GL_TEXTURE_ENV_COLOR) { @@ -908,12 +909,26 @@ _mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params ) } } -/* why does ATI_envmap_bumpmap require new entrypoints? Should just - reuse TexEnv ones... */ + +/** + * Why does ATI_envmap_bumpmap require new entrypoints? Should just + * reuse TexEnv ones... + */ void GLAPIENTRY _mesa_TexBumpParameterivATI( GLenum pname, const GLint *param ) { GLfloat p[4]; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (!ctx->Extensions.ATI_envmap_bumpmap) { + /* This isn't an "official" error case, but let's tell the user + * that something's wrong. + */ + _mesa_error(ctx, GL_INVALID_OPERATION, "glTexBumpParameterivATI"); + return; + } + if (pname == GL_BUMP_ROT_MATRIX_ATI) { /* hope that conversion is correct here */ p[0] = INT_TO_FLOAT( param[0] ); @@ -923,11 +938,12 @@ _mesa_TexBumpParameterivATI( GLenum pname, const GLint *param ) } else { p[0] = (GLfloat) param[0]; - p[1] = p[2] = p[3] = 0; /* init to zero, just to be safe */ + p[1] = p[2] = p[3] = 0.0F; /* init to zero, just to be safe */ } _mesa_TexBumpParameterfvATI( pname, p ); } + void GLAPIENTRY _mesa_TexBumpParameterfvATI( GLenum pname, const GLfloat *param ) { @@ -935,8 +951,12 @@ _mesa_TexBumpParameterfvATI( GLenum pname, const GLfloat *param ) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); - /* should return error if extension not supported? */ - texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + if (!ctx->Extensions.ATI_envmap_bumpmap) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glTexBumpParameterfvATI"); + return; + } + + texUnit = _mesa_get_current_tex_unit(ctx); if (pname == GL_BUMP_ROT_MATRIX_ATI) { if (TEST_EQ_4V(param, texUnit->RotMatrix)) @@ -955,17 +975,21 @@ _mesa_TexBumpParameterfvATI( GLenum pname, const GLfloat *param ) } } + void GLAPIENTRY _mesa_GetTexBumpParameterivATI( GLenum pname, GLint *param ) { const struct gl_texture_unit *texUnit; GLuint i; - GLint temp = 0; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); - /* should return error if extension not supported? */ - texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + if (!ctx->Extensions.ATI_envmap_bumpmap) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexBumpParameterivATI"); + return; + } + + texUnit = _mesa_get_current_tex_unit(ctx); if (pname == GL_BUMP_ROT_MATRIX_SIZE_ATI) { /* spec leaves open to support larger matrices. @@ -982,12 +1006,13 @@ _mesa_GetTexBumpParameterivATI( GLenum pname, GLint *param ) param[3] = FLOAT_TO_INT(texUnit->RotMatrix[3]); } else if (pname == GL_BUMP_NUM_TEX_UNITS_ATI) { + GLint count = 0; for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) { if (ctx->Const.SupportedBumpUnits & (1 << i)) { - temp++; + count++; } } - *param = temp; + *param = count; } else if (pname == GL_BUMP_TEX_UNITS_ATI) { for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) { @@ -1002,23 +1027,27 @@ _mesa_GetTexBumpParameterivATI( GLenum pname, GLint *param ) } } + void GLAPIENTRY _mesa_GetTexBumpParameterfvATI( GLenum pname, GLfloat *param ) { const struct gl_texture_unit *texUnit; GLuint i; - GLint temp = 0; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); - /* should return error if extension not supported? */ - texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + if (!ctx->Extensions.ATI_envmap_bumpmap) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexBumpParameterfvATI"); + return; + } + + texUnit = _mesa_get_current_tex_unit(ctx); if (pname == GL_BUMP_ROT_MATRIX_SIZE_ATI) { /* spec leaves open to support larger matrices. Don't think anyone would ever want to use it (and apps might not understand it) so hardcode this. */ - *param = (GLfloat) 4; + *param = 4.0F; } else if (pname == GL_BUMP_ROT_MATRIX_ATI) { param[0] = texUnit->RotMatrix[0]; @@ -1027,12 +1056,13 @@ _mesa_GetTexBumpParameterfvATI( GLenum pname, GLfloat *param ) param[3] = texUnit->RotMatrix[3]; } else if (pname == GL_BUMP_NUM_TEX_UNITS_ATI) { + GLint count = 0; for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) { if (ctx->Const.SupportedBumpUnits & (1 << i)) { - temp++; + count++; } } - *param = (GLfloat) temp; + *param = (GLfloat) count; } else if (pname == GL_BUMP_TEX_UNITS_ATI) { for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) { @@ -1046,4 +1076,3 @@ _mesa_GetTexBumpParameterfvATI( GLenum pname, GLfloat *param ) return; } } - diff --git a/src/mesa/main/texenvprogram.c b/src/mesa/main/texenvprogram.c index 6b090ff399..3736138b9e 100644 --- a/src/mesa/main/texenvprogram.c +++ b/src/mesa/main/texenvprogram.c @@ -275,6 +275,7 @@ static GLbitfield get_fp_input_mask( GLcontext *ctx ) { /* _NEW_PROGRAM */ const GLboolean vertexShader = (ctx->Shader.CurrentProgram && + ctx->Shader.CurrentProgram->LinkStatus && ctx->Shader.CurrentProgram->VertexProgram); const GLboolean vertexProgram = ctx->VertexProgram._Enabled; GLbitfield fp_inputs = 0x0; @@ -321,8 +322,10 @@ static GLbitfield get_fp_input_mask( GLcontext *ctx ) /* Then look at what might be varying as a result of enabled * arrays, etc: */ - if (varying_inputs & VERT_BIT_COLOR0) fp_inputs |= FRAG_BIT_COL0; - if (varying_inputs & VERT_BIT_COLOR1) fp_inputs |= FRAG_BIT_COL1; + if (varying_inputs & VERT_BIT_COLOR0) + fp_inputs |= FRAG_BIT_COL0; + if (varying_inputs & VERT_BIT_COLOR1) + fp_inputs |= FRAG_BIT_COL1; fp_inputs |= (((varying_inputs & VERT_BIT_TEX_ANY) >> VERT_ATTRIB_TEX0) << FRAG_ATTRIB_TEX0); @@ -340,7 +343,7 @@ static GLbitfield get_fp_input_mask( GLcontext *ctx ) if (vertexShader) vprog = ctx->Shader.CurrentProgram->VertexProgram; else - vprog = ctx->VertexProgram._Current; + vprog = ctx->VertexProgram.Current; vp_outputs = vprog->Base.OutputsWritten; @@ -351,8 +354,10 @@ static GLbitfield get_fp_input_mask( GLcontext *ctx ) if (ctx->Point.PointSprite) vp_outputs |= FRAG_BITS_TEX_ANY; - if (vp_outputs & (1 << VERT_RESULT_COL0)) fp_inputs |= FRAG_BIT_COL0; - if (vp_outputs & (1 << VERT_RESULT_COL1)) fp_inputs |= FRAG_BIT_COL1; + if (vp_outputs & (1 << VERT_RESULT_COL0)) + fp_inputs |= FRAG_BIT_COL0; + if (vp_outputs & (1 << VERT_RESULT_COL1)) + fp_inputs |= FRAG_BIT_COL1; fp_inputs |= (((vp_outputs & VERT_RESULT_TEX_ANY) >> VERT_RESULT_TEX0) << FRAG_ATTRIB_TEX0); diff --git a/src/mesa/main/texgetimage.c b/src/mesa/main/texgetimage.c index 02409d8009..14d6fc7659 100644 --- a/src/mesa/main/texgetimage.c +++ b/src/mesa/main/texgetimage.c @@ -30,11 +30,14 @@ #include "glheader.h" +#include "bufferobj.h" #include "context.h" #include "image.h" #include "texcompress.h" #include "texformat.h" #include "texgetimage.h" +#include "teximage.h" +#include "texstate.h" @@ -116,7 +119,7 @@ _mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level, { const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2; - if (ctx->Pack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { /* Packing texture image into a PBO. * Map the (potentially) VRAM-based buffer into our process space so * we can write into it with the code below. @@ -296,7 +299,7 @@ _mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level, } /* img */ } - if (ctx->Pack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, ctx->Pack.BufferObj); } @@ -316,7 +319,7 @@ _mesa_get_compressed_teximage(GLcontext *ctx, GLenum target, GLint level, { GLuint size; - if (ctx->Pack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { /* pack texture image into a PBO */ GLubyte *buf; if ((const GLubyte *) img + texImage->CompressedSize > @@ -349,8 +352,230 @@ _mesa_get_compressed_teximage(GLcontext *ctx, GLenum target, GLint level, /* just memcpy, no pixelstore or pixel transfer */ _mesa_memcpy(img, texImage->Data, size); - if (ctx->Pack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, ctx->Pack.BufferObj); } } + + + +/** + * Do error checking for a glGetTexImage() call. + * \return GL_TRUE if any error, GL_FALSE if no errors. + */ +static GLboolean +getteximage_error_check(GLcontext *ctx, GLenum target, GLint level, + GLenum format, GLenum type, GLvoid *pixels ) +{ + const struct gl_texture_unit *texUnit; + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + const GLuint maxLevels = _mesa_max_texture_levels(ctx, target); + + if (maxLevels == 0) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target=0x%x)", target); + return GL_TRUE; + } + + if (level < 0 || level >= maxLevels) { + _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" ); + return GL_TRUE; + } + + if (_mesa_sizeof_packed_type(type) <= 0) { + _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" ); + return GL_TRUE; + } + + if (_mesa_components_in_format(format) <= 0 || + format == GL_STENCIL_INDEX) { + _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" ); + return GL_TRUE; + } + + if (!ctx->Extensions.EXT_paletted_texture && _mesa_is_index_format(format)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); + return GL_TRUE; + } + + if (!ctx->Extensions.ARB_depth_texture && _mesa_is_depth_format(format)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); + return GL_TRUE; + } + + if (!ctx->Extensions.MESA_ycbcr_texture && _mesa_is_ycbcr_format(format)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); + return GL_TRUE; + } + + if (!ctx->Extensions.EXT_packed_depth_stencil + && _mesa_is_depthstencil_format(format)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); + return GL_TRUE; + } + + if (!ctx->Extensions.ATI_envmap_bumpmap + && _mesa_is_dudv_format(format)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); + return GL_TRUE; + } + + texUnit = _mesa_get_current_tex_unit(ctx); + texObj = _mesa_select_tex_object(ctx, texUnit, target); + + if (!texObj || _mesa_is_proxy_texture(target)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)"); + return GL_TRUE; + } + + texImage = _mesa_select_tex_image(ctx, texObj, target, level); + if (!texImage) { + /* out of memory */ + return GL_TRUE; + } + + /* Make sure the requested image format is compatible with the + * texture's format. Note that a color index texture can be converted + * to RGBA so that combo is allowed. + */ + if (_mesa_is_color_format(format) + && !_mesa_is_color_format(texImage->TexFormat->BaseFormat) + && !_mesa_is_index_format(texImage->TexFormat->BaseFormat)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); + return GL_TRUE; + } + else if (_mesa_is_index_format(format) + && !_mesa_is_index_format(texImage->TexFormat->BaseFormat)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); + return GL_TRUE; + } + else if (_mesa_is_depth_format(format) + && !_mesa_is_depth_format(texImage->TexFormat->BaseFormat) + && !_mesa_is_depthstencil_format(texImage->TexFormat->BaseFormat)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); + return GL_TRUE; + } + else if (_mesa_is_ycbcr_format(format) + && !_mesa_is_ycbcr_format(texImage->TexFormat->BaseFormat)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); + return GL_TRUE; + } + else if (_mesa_is_depthstencil_format(format) + && !_mesa_is_depthstencil_format(texImage->TexFormat->BaseFormat)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); + return GL_TRUE; + } + else if (_mesa_is_dudv_format(format) + && !_mesa_is_dudv_format(texImage->TexFormat->BaseFormat)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); + return GL_TRUE; + } + + if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { + /* packing texture image into a PBO */ + const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2; + if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width, + texImage->Height, texImage->Depth, + format, type, pixels)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetTexImage(invalid PBO access)"); + return GL_TRUE; + } + } + + return GL_FALSE; +} + + + +/** + * Get texture image. Called by glGetTexImage. + * + * \param target texture target. + * \param level image level. + * \param format pixel data format for returned image. + * \param type pixel data type for returned image. + * \param pixels returned pixel data. + */ +void GLAPIENTRY +_mesa_GetTexImage( GLenum target, GLint level, GLenum format, + GLenum type, GLvoid *pixels ) +{ + const struct gl_texture_unit *texUnit; + struct gl_texture_object *texObj; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (getteximage_error_check(ctx, target, level, format, type, pixels)) { + return; + } + + texUnit = _mesa_get_current_tex_unit(ctx); + texObj = _mesa_select_tex_object(ctx, texUnit, target); + + _mesa_lock_texture(ctx, texObj); + { + struct gl_texture_image *texImage = + _mesa_select_tex_image(ctx, texObj, target, level); + + /* typically, this will call _mesa_get_teximage() */ + ctx->Driver.GetTexImage(ctx, target, level, format, type, pixels, + texObj, texImage); + } + _mesa_unlock_texture(ctx, texObj); +} + + +void GLAPIENTRY +_mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img) +{ + const struct gl_texture_unit *texUnit; + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + GLint maxLevels; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + texUnit = _mesa_get_current_tex_unit(ctx); + texObj = _mesa_select_tex_object(ctx, texUnit, target); + if (!texObj) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB"); + return; + } + + maxLevels = _mesa_max_texture_levels(ctx, target); + ASSERT(maxLevels > 0); /* 0 indicates bad target, caught above */ + + if (level < 0 || level >= maxLevels) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)"); + return; + } + + if (_mesa_is_proxy_texture(target)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)"); + return; + } + + _mesa_lock_texture(ctx, texObj); + { + texImage = _mesa_select_tex_image(ctx, texObj, target, level); + if (texImage) { + if (texImage->IsCompressed) { + /* this typically calls _mesa_get_compressed_teximage() */ + ctx->Driver.GetCompressedTexImage(ctx, target, level, img, + texObj, texImage); + } + else { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetCompressedTexImageARB"); + } + } + else { + /* probably invalid mipmap level */ + _mesa_error(ctx, GL_INVALID_VALUE, + "glGetCompressedTexImageARB(level)"); + } + } + _mesa_unlock_texture(ctx, texObj); +} diff --git a/src/mesa/main/texgetimage.h b/src/mesa/main/texgetimage.h index 01f486e8f0..088d27c7e1 100644 --- a/src/mesa/main/texgetimage.h +++ b/src/mesa/main/texgetimage.h @@ -43,4 +43,13 @@ _mesa_get_compressed_teximage(GLcontext *ctx, GLenum target, GLint level, +extern void GLAPIENTRY +_mesa_GetTexImage( GLenum target, GLint level, + GLenum format, GLenum type, GLvoid *pixels ); + + +extern void GLAPIENTRY +_mesa_GetCompressedTexImageARB(GLenum target, GLint lod, GLvoid *img); + + #endif /* TEXGETIMAGE_H */ diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c index 825f5e26bf..8228303040 100644 --- a/src/mesa/main/teximage.c +++ b/src/mesa/main/teximage.c @@ -182,6 +182,8 @@ logbase2( int n ) * * This is the format which is used during texture application (i.e. the * texture format and env mode determine the arithmetic used. + * + * XXX this could be static */ GLint _mesa_base_tex_format( GLcontext *ctx, GLint internalFormat ) @@ -415,211 +417,6 @@ _mesa_base_tex_format( GLcontext *ctx, GLint internalFormat ) /** - * Test if the given image format is a color/RGBA format (i.e., not color - * index, depth, stencil, etc). - * \param format the image format value (may by an internal texture format) - * \return GL_TRUE if its a color/RGBA format, GL_FALSE otherwise. - * XXX maybe move this func to image.c - */ -GLboolean -_mesa_is_color_format(GLenum format) -{ - switch (format) { - case GL_RED: - case GL_GREEN: - case GL_BLUE: - case GL_ALPHA: - case GL_ALPHA4: - case GL_ALPHA8: - case GL_ALPHA12: - case GL_ALPHA16: - case 1: - case GL_LUMINANCE: - case GL_LUMINANCE4: - case GL_LUMINANCE8: - case GL_LUMINANCE12: - case GL_LUMINANCE16: - case 2: - case GL_LUMINANCE_ALPHA: - case GL_LUMINANCE4_ALPHA4: - case GL_LUMINANCE6_ALPHA2: - case GL_LUMINANCE8_ALPHA8: - case GL_LUMINANCE12_ALPHA4: - case GL_LUMINANCE12_ALPHA12: - case GL_LUMINANCE16_ALPHA16: - case GL_INTENSITY: - case GL_INTENSITY4: - case GL_INTENSITY8: - case GL_INTENSITY12: - case GL_INTENSITY16: - case 3: - case GL_RGB: - case GL_BGR: - case GL_R3_G3_B2: - case GL_RGB4: - case GL_RGB5: - case GL_RGB8: - case GL_RGB10: - case GL_RGB12: - case GL_RGB16: - case 4: - case GL_ABGR_EXT: - case GL_RGBA: - case GL_BGRA: - case GL_RGBA2: - case GL_RGBA4: - case GL_RGB5_A1: - case GL_RGBA8: - case GL_RGB10_A2: - case GL_RGBA12: - case GL_RGBA16: - /* float texture formats */ - case GL_ALPHA16F_ARB: - case GL_ALPHA32F_ARB: - case GL_LUMINANCE16F_ARB: - case GL_LUMINANCE32F_ARB: - case GL_LUMINANCE_ALPHA16F_ARB: - case GL_LUMINANCE_ALPHA32F_ARB: - case GL_INTENSITY16F_ARB: - case GL_INTENSITY32F_ARB: - case GL_RGB16F_ARB: - case GL_RGB32F_ARB: - case GL_RGBA16F_ARB: - case GL_RGBA32F_ARB: - /* compressed formats */ - case GL_COMPRESSED_ALPHA: - case GL_COMPRESSED_LUMINANCE: - case GL_COMPRESSED_LUMINANCE_ALPHA: - case GL_COMPRESSED_INTENSITY: - case GL_COMPRESSED_RGB: - case GL_COMPRESSED_RGBA: - case GL_RGB_S3TC: - case GL_RGB4_S3TC: - case GL_RGBA_S3TC: - case GL_RGBA4_S3TC: - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: - case GL_COMPRESSED_RGB_FXT1_3DFX: - case GL_COMPRESSED_RGBA_FXT1_3DFX: -#if FEATURE_EXT_texture_sRGB - case GL_SRGB_EXT: - case GL_SRGB8_EXT: - case GL_SRGB_ALPHA_EXT: - case GL_SRGB8_ALPHA8_EXT: - case GL_SLUMINANCE_ALPHA_EXT: - case GL_SLUMINANCE8_ALPHA8_EXT: - case GL_SLUMINANCE_EXT: - case GL_SLUMINANCE8_EXT: - case GL_COMPRESSED_SRGB_EXT: - case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_SRGB_ALPHA_EXT: - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: - case GL_COMPRESSED_SLUMINANCE_EXT: - case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT: -#endif /* FEATURE_EXT_texture_sRGB */ - return GL_TRUE; - /* signed texture formats */ - case GL_RGBA_SNORM: - case GL_RGBA8_SNORM: - return GL_TRUE; - case GL_YCBCR_MESA: /* not considered to be RGB */ - /* fall-through */ - default: - return GL_FALSE; - } -} - - -/** - * Test if the given image format is a color index format. - */ -static GLboolean -is_index_format(GLenum format) -{ - switch (format) { - case GL_COLOR_INDEX: - case GL_COLOR_INDEX1_EXT: - case GL_COLOR_INDEX2_EXT: - case GL_COLOR_INDEX4_EXT: - case GL_COLOR_INDEX8_EXT: - case GL_COLOR_INDEX12_EXT: - case GL_COLOR_INDEX16_EXT: - return GL_TRUE; - default: - return GL_FALSE; - } -} - - -/** - * Test if the given image format is a depth component format. - */ -static GLboolean -is_depth_format(GLenum format) -{ - switch (format) { - case GL_DEPTH_COMPONENT16: - case GL_DEPTH_COMPONENT24: - case GL_DEPTH_COMPONENT32: - case GL_DEPTH_COMPONENT: - return GL_TRUE; - default: - return GL_FALSE; - } -} - - -/** - * Test if the given image format is a YCbCr format. - */ -static GLboolean -is_ycbcr_format(GLenum format) -{ - switch (format) { - case GL_YCBCR_MESA: - return GL_TRUE; - default: - return GL_FALSE; - } -} - - -/** - * Test if the given image format is a Depth/Stencil format. - */ -static GLboolean -is_depthstencil_format(GLenum format) -{ - switch (format) { - case GL_DEPTH24_STENCIL8_EXT: - case GL_DEPTH_STENCIL_EXT: - return GL_TRUE; - default: - return GL_FALSE; - } -} - -/** - * Test if the given image format is a dudv format. - */ -static GLboolean -is_dudv_format(GLenum format) -{ - switch (format) { - case GL_DUDV_ATI: - case GL_DU8DV8_ATI: - return GL_TRUE; - default: - return GL_FALSE; - } -} - - -/** * Test if it is a supported compressed format. * * \param internalFormat the internal format token provided by the user. @@ -765,6 +562,9 @@ _mesa_delete_texture_image( GLcontext *ctx, struct gl_texture_image *texImage ) GLboolean _mesa_is_proxy_texture(GLenum target) { + /* NUM_TEXTURE_TARGETS should match number of terms below */ + assert(NUM_TEXTURE_TARGETS == 7); + return (target == GL_PROXY_TEXTURE_1D || target == GL_PROXY_TEXTURE_2D || target == GL_PROXY_TEXTURE_3D || @@ -776,18 +576,6 @@ _mesa_is_proxy_texture(GLenum target) /** - * Return pointer to current texture unit. - * This the texture unit set by glActiveTexture(), not glClientActiveTexture(). - */ -static INLINE struct gl_texture_unit * -get_current_tex_unit(GLcontext *ctx) -{ - ASSERT(ctx->Texture.CurrentUnit < Elements(ctx->Texture.Unit)); - return &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]); -} - - -/** * Get the texture object that corresponds to the target of the given texture unit. * * \param ctx GL context. @@ -996,10 +784,6 @@ _mesa_max_texture_levels(GLcontext *ctx, GLenum target) case GL_PROXY_TEXTURE_1D: case GL_TEXTURE_2D: case GL_PROXY_TEXTURE_2D: - case GL_TEXTURE_1D_ARRAY_EXT: - case GL_PROXY_TEXTURE_1D_ARRAY_EXT: - case GL_TEXTURE_2D_ARRAY_EXT: - case GL_PROXY_TEXTURE_2D_ARRAY_EXT: return ctx->Const.MaxTextureLevels; case GL_TEXTURE_3D: case GL_PROXY_TEXTURE_3D: @@ -1012,10 +796,17 @@ _mesa_max_texture_levels(GLcontext *ctx, GLenum target) case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: case GL_TEXTURE_CUBE_MAP_ARB: case GL_PROXY_TEXTURE_CUBE_MAP_ARB: - return ctx->Const.MaxCubeTextureLevels; + return ctx->Extensions.ARB_texture_cube_map + ? ctx->Const.MaxCubeTextureLevels : 0; case GL_TEXTURE_RECTANGLE_NV: case GL_PROXY_TEXTURE_RECTANGLE_NV: - return 1; + return ctx->Extensions.NV_texture_rectangle ? 1 : 0; + case GL_TEXTURE_1D_ARRAY_EXT: + case GL_PROXY_TEXTURE_1D_ARRAY_EXT: + case GL_TEXTURE_2D_ARRAY_EXT: + case GL_PROXY_TEXTURE_2D_ARRAY_EXT: + return ctx->Extensions.MESA_texture_array + ? ctx->Const.MaxTextureLevels : 0; default: return 0; /* bad target */ } @@ -1216,6 +1007,23 @@ _mesa_init_teximage_fields(GLcontext *ctx, GLenum target, /** + * Free and clear fields of the gl_texture_image struct. + * + * \param ctx GL context. + * \param texImage texture image structure to be cleared. + * + * After the call, \p texImage will have no data associated with it. Its + * fields are cleared so that its parent object will test incomplete. + */ +void +_mesa_clear_texture_image(GLcontext *ctx, struct gl_texture_image *texImage) +{ + ctx->Driver.FreeTexImageData(ctx, texImage); + clear_teximage_fields(texImage); +} + + +/** * This is the fallback for Driver.TestProxyTexImage(). Test the texture * level, width, height and depth against the ctx->Const limits for textures. * @@ -1529,13 +1337,13 @@ texture_error_check( GLcontext *ctx, GLenum target, /* make sure internal format and format basically agree */ colorFormat = _mesa_is_color_format(format); - indexFormat = is_index_format(format); + indexFormat = _mesa_is_index_format(format); if ((_mesa_is_color_format(internalFormat) && !colorFormat && !indexFormat) || - (is_index_format(internalFormat) && !indexFormat) || - (is_depth_format(internalFormat) != is_depth_format(format)) || - (is_ycbcr_format(internalFormat) != is_ycbcr_format(format)) || - (is_depthstencil_format(internalFormat) != is_depthstencil_format(format)) || - (is_dudv_format(internalFormat) != is_dudv_format(format))) { + (_mesa_is_index_format(internalFormat) && !indexFormat) || + (_mesa_is_depth_format(internalFormat) != _mesa_is_depth_format(format)) || + (_mesa_is_ycbcr_format(internalFormat) != _mesa_is_ycbcr_format(format)) || + (_mesa_is_depthstencil_format(internalFormat) != _mesa_is_depthstencil_format(format)) || + (_mesa_is_dudv_format(internalFormat) != _mesa_is_dudv_format(format))) { if (!isProxy) _mesa_error(ctx, GL_INVALID_OPERATION, "glTexImage%dD(incompatible internalFormat 0x%x, format 0x%x)", @@ -1970,7 +1778,7 @@ copytexture_error_check( GLcontext *ctx, GLuint dimensions, return GL_TRUE; } } - else if (is_depth_format(internalFormat)) { + else if (_mesa_is_depth_format(internalFormat)) { /* make sure we have depth/stencil buffers */ if (!ctx->ReadBuffer->_DepthBuffer) { _mesa_error(ctx, GL_INVALID_OPERATION, @@ -1978,7 +1786,7 @@ copytexture_error_check( GLcontext *ctx, GLuint dimensions, return GL_TRUE; } } - else if (is_depthstencil_format(internalFormat)) { + else if (_mesa_is_depthstencil_format(internalFormat)) { /* make sure we have depth/stencil buffers */ if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) { _mesa_error(ctx, GL_INVALID_OPERATION, @@ -2203,169 +2011,6 @@ copytexsubimage_error_check2( GLcontext *ctx, GLuint dimensions, } -/** - * Do error checking for a glGetTexImage() call. - * \return GL_TRUE if any error, GL_FALSE if no errors. - */ -static GLboolean -getteximage_error_check(GLcontext *ctx, GLenum target, GLint level, - GLenum format, GLenum type, GLvoid *pixels ) -{ - const struct gl_texture_unit *texUnit; - struct gl_texture_object *texObj; - struct gl_texture_image *texImage; - const GLuint maxLevels = _mesa_max_texture_levels(ctx, target); - - ASSERT(maxLevels > 0); /* 0 indicates bad target, caught above */ - - if (level < 0 || level >= maxLevels) { - _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" ); - return GL_TRUE; - } - - if (_mesa_sizeof_packed_type(type) <= 0) { - _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" ); - return GL_TRUE; - } - - if (_mesa_components_in_format(format) <= 0 || - format == GL_STENCIL_INDEX) { - _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" ); - return GL_TRUE; - } - - if (!ctx->Extensions.EXT_paletted_texture && is_index_format(format)) { - _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); - return GL_TRUE; - } - - if (!ctx->Extensions.ARB_depth_texture && is_depth_format(format)) { - _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); - return GL_TRUE; - } - - if (!ctx->Extensions.MESA_ycbcr_texture && is_ycbcr_format(format)) { - _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); - return GL_TRUE; - } - - if (!ctx->Extensions.EXT_packed_depth_stencil - && is_depthstencil_format(format)) { - _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); - return GL_TRUE; - } - - if (!ctx->Extensions.ATI_envmap_bumpmap - && is_dudv_format(format)) { - _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); - return GL_TRUE; - } - - - texUnit = get_current_tex_unit(ctx); - texObj = _mesa_select_tex_object(ctx, texUnit, target); - texImage = _mesa_select_tex_image(ctx, texObj, target, level); - if (!texImage) { - /* out of memory */ - return GL_TRUE; - } - - /* Make sure the requested image format is compatible with the - * texture's format. Note that a color index texture can be converted - * to RGBA so that combo is allowed. - */ - if (_mesa_is_color_format(format) - && !_mesa_is_color_format(texImage->TexFormat->BaseFormat) - && !is_index_format(texImage->TexFormat->BaseFormat)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); - return GL_TRUE; - } - else if (is_index_format(format) - && !is_index_format(texImage->TexFormat->BaseFormat)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); - return GL_TRUE; - } - else if (is_depth_format(format) - && !is_depth_format(texImage->TexFormat->BaseFormat) - && !is_depthstencil_format(texImage->TexFormat->BaseFormat)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); - return GL_TRUE; - } - else if (is_ycbcr_format(format) - && !is_ycbcr_format(texImage->TexFormat->BaseFormat)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); - return GL_TRUE; - } - else if (is_depthstencil_format(format) - && !is_depthstencil_format(texImage->TexFormat->BaseFormat)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); - return GL_TRUE; - } - else if (is_dudv_format(format) - && !is_dudv_format(texImage->TexFormat->BaseFormat)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); - return GL_TRUE; - } - - if (ctx->Pack.BufferObj->Name) { - /* packing texture image into a PBO */ - const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2; - if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width, - texImage->Height, texImage->Depth, - format, type, pixels)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetTexImage(invalid PBO access)"); - return GL_TRUE; - } - } - - return GL_FALSE; -} - - - -/** - * Get texture image. Called by glGetTexImage. - * - * \param target texture target. - * \param level image level. - * \param format pixel data format for returned image. - * \param type pixel data type for returned image. - * \param pixels returned pixel data. - */ -void GLAPIENTRY -_mesa_GetTexImage( GLenum target, GLint level, GLenum format, - GLenum type, GLvoid *pixels ) -{ - const struct gl_texture_unit *texUnit; - struct gl_texture_object *texObj; - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); - - texUnit = get_current_tex_unit(ctx); - texObj = _mesa_select_tex_object(ctx, texUnit, target); - if (!texObj || _mesa_is_proxy_texture(target)) { - _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)"); - return; - } - - if (getteximage_error_check(ctx, target, level, format, type, pixels)) { - return; - } - - _mesa_lock_texture(ctx, texObj); - { - struct gl_texture_image *texImage = - _mesa_select_tex_image(ctx, texObj, target, level); - - /* typically, this will call _mesa_get_teximage() */ - ctx->Driver.GetTexImage(ctx, target, level, format, type, pixels, - texObj, texImage); - } - _mesa_unlock_texture(ctx, texObj); -} - - /** Callback info for walking over FBO hash table */ struct cb_info { @@ -2509,7 +2154,7 @@ _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat, if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) _mesa_update_state(ctx); - texUnit = get_current_tex_unit(ctx); + texUnit = _mesa_get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); { @@ -2617,7 +2262,7 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat, if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) _mesa_update_state(ctx); - texUnit = get_current_tex_unit(ctx); + texUnit = _mesa_get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); { @@ -2720,7 +2365,7 @@ _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat, if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) _mesa_update_state(ctx); - texUnit = get_current_tex_unit(ctx); + texUnit = _mesa_get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); { @@ -2826,7 +2471,7 @@ _mesa_TexSubImage1D( GLenum target, GLint level, } - texUnit = get_current_tex_unit(ctx); + texUnit = _mesa_get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); assert(texObj); @@ -2886,7 +2531,7 @@ _mesa_TexSubImage2D( GLenum target, GLint level, return; /* error was detected */ } - texUnit = get_current_tex_unit(ctx); + texUnit = _mesa_get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); { @@ -2938,7 +2583,7 @@ _mesa_TexSubImage3D( GLenum target, GLint level, return; /* error was detected */ } - texUnit = get_current_tex_unit(ctx); + texUnit = _mesa_get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); @@ -2999,7 +2644,7 @@ _mesa_CopyTexImage1D( GLenum target, GLint level, postConvWidth, 1, border)) return; - texUnit = get_current_tex_unit(ctx); + texUnit = _mesa_get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); { @@ -3065,7 +2710,7 @@ _mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat, postConvWidth, postConvHeight, border)) return; - texUnit = get_current_tex_unit(ctx); + texUnit = _mesa_get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); @@ -3125,7 +2770,7 @@ _mesa_CopyTexSubImage1D( GLenum target, GLint level, if (copytexsubimage_error_check1(ctx, 1, target, level)) return; - texUnit = get_current_tex_unit(ctx); + texUnit = _mesa_get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); @@ -3180,7 +2825,7 @@ _mesa_CopyTexSubImage2D( GLenum target, GLint level, if (copytexsubimage_error_check1(ctx, 2, target, level)) return; - texUnit = get_current_tex_unit(ctx); + texUnit = _mesa_get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); @@ -3235,7 +2880,7 @@ _mesa_CopyTexSubImage3D( GLenum target, GLint level, if (copytexsubimage_error_check1(ctx, 3, target, level)) return; - texUnit = get_current_tex_unit(ctx); + texUnit = _mesa_get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); @@ -3489,7 +3134,7 @@ _mesa_CompressedTexImage1DARB(GLenum target, GLint level, return; } - texUnit = get_current_tex_unit(ctx); + texUnit = _mesa_get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); @@ -3543,7 +3188,7 @@ _mesa_CompressedTexImage1DARB(GLenum target, GLint level, struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; struct gl_texture_image *texImage; - texUnit = get_current_tex_unit(ctx); + texUnit = _mesa_get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); @@ -3586,7 +3231,7 @@ _mesa_CompressedTexImage2DARB(GLenum target, GLint level, return; } - texUnit = get_current_tex_unit(ctx); + texUnit = _mesa_get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); @@ -3642,7 +3287,7 @@ _mesa_CompressedTexImage2DARB(GLenum target, GLint level, struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; struct gl_texture_image *texImage; - texUnit = get_current_tex_unit(ctx); + texUnit = _mesa_get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); @@ -3682,7 +3327,7 @@ _mesa_CompressedTexImage3DARB(GLenum target, GLint level, return; } - texUnit = get_current_tex_unit(ctx); + texUnit = _mesa_get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); { @@ -3736,7 +3381,7 @@ _mesa_CompressedTexImage3DARB(GLenum target, GLint level, struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; struct gl_texture_image *texImage; - texUnit = get_current_tex_unit(ctx); + texUnit = _mesa_get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); { @@ -3775,7 +3420,7 @@ _mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset, return; } - texUnit = get_current_tex_unit(ctx); + texUnit = _mesa_get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); { @@ -3832,7 +3477,7 @@ _mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset, return; } - texUnit = get_current_tex_unit(ctx); + texUnit = _mesa_get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); { @@ -3889,7 +3534,7 @@ _mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset, return; } - texUnit = get_current_tex_unit(ctx); + texUnit = _mesa_get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); { @@ -3926,55 +3571,3 @@ _mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset, } -void GLAPIENTRY -_mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img) -{ - const struct gl_texture_unit *texUnit; - struct gl_texture_object *texObj; - struct gl_texture_image *texImage; - GLint maxLevels; - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); - - texUnit = get_current_tex_unit(ctx); - texObj = _mesa_select_tex_object(ctx, texUnit, target); - if (!texObj) { - _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB"); - return; - } - - maxLevels = _mesa_max_texture_levels(ctx, target); - ASSERT(maxLevels > 0); /* 0 indicates bad target, caught above */ - - if (level < 0 || level >= maxLevels) { - _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)"); - return; - } - - if (_mesa_is_proxy_texture(target)) { - _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)"); - return; - } - - _mesa_lock_texture(ctx, texObj); - { - texImage = _mesa_select_tex_image(ctx, texObj, target, level); - if (texImage) { - if (texImage->IsCompressed) { - /* this typically calls _mesa_get_compressed_teximage() */ - ctx->Driver.GetCompressedTexImage(ctx, target, level, img, - texObj, texImage); - } - else { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetCompressedTexImageARB"); - } - } - else { - /* probably invalid mipmap level */ - _mesa_error(ctx, GL_INVALID_VALUE, - "glGetCompressedTexImageARB(level)"); - } - } - _mesa_unlock_texture(ctx, texObj); -} diff --git a/src/mesa/main/teximage.h b/src/mesa/main/teximage.h index eb60a1fa8f..094177da79 100644 --- a/src/mesa/main/teximage.h +++ b/src/mesa/main/teximage.h @@ -73,6 +73,10 @@ _mesa_init_teximage_fields(GLcontext *ctx, GLenum target, extern void +_mesa_clear_texture_image(GLcontext *ctx, struct gl_texture_image *texImage); + + +extern void _mesa_set_tex_image(struct gl_texture_object *tObj, GLenum target, GLint level, struct gl_texture_image *texImage); @@ -111,10 +115,6 @@ extern GLuint _mesa_tex_target_to_face(GLenum target); -extern GLboolean -_mesa_is_color_format(GLenum format); - - /** * Lock a texture for updating. See also _mesa_lock_context_textures(). */ @@ -164,11 +164,6 @@ _mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalformat, extern void GLAPIENTRY -_mesa_GetTexImage( GLenum target, GLint level, - GLenum format, GLenum type, GLvoid *pixels ); - - -extern void GLAPIENTRY _mesa_TexSubImage1D( GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, @@ -260,9 +255,6 @@ _mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); -extern void GLAPIENTRY -_mesa_GetCompressedTexImageARB(GLenum target, GLint lod, GLvoid *img); - /*@}*/ #endif diff --git a/src/mesa/main/texobj.c b/src/mesa/main/texobj.c index 2082f945f1..d09c439250 100644 --- a/src/mesa/main/texobj.c +++ b/src/mesa/main/texobj.c @@ -261,6 +261,32 @@ _mesa_copy_texture_object( struct gl_texture_object *dest, /** + * Clear all texture images of the given texture object. + * + * \param ctx GL context. + * \param t texture object. + * + * \sa _mesa_clear_texture_image(). + */ +void +_mesa_clear_texture_object(GLcontext *ctx, struct gl_texture_object *texObj) +{ + GLuint i, j; + + if (texObj->Target == 0) + return; + + for (i = 0; i < MAX_FACES; i++) { + for (j = 0; j < MAX_TEXTURE_LEVELS; j++) { + struct gl_texture_image *texImage = texObj->Image[i][j]; + if (texImage) + _mesa_clear_texture_image(ctx, texImage); + } + } +} + + +/** * Check if the given texture object is valid by examining its Target field. * For debugging only. */ @@ -308,7 +334,7 @@ _mesa_reference_texobj(struct gl_texture_object **ptr, GLboolean deleteFlag = GL_FALSE; struct gl_texture_object *oldTex = *ptr; - assert(valid_texture_object(oldTex)); + ASSERT(valid_texture_object(oldTex)); _glthread_LOCK_MUTEX(oldTex->Mutex); ASSERT(oldTex->RefCount > 0); @@ -331,7 +357,7 @@ _mesa_reference_texobj(struct gl_texture_object **ptr, if (tex) { /* reference new texture */ - assert(valid_texture_object(tex)); + ASSERT(valid_texture_object(tex)); _glthread_LOCK_MUTEX(tex->Mutex); if (tex->RefCount == 0) { /* this texture's being deleted (look just above) */ @@ -665,6 +691,24 @@ _mesa_test_texobj_completeness( const GLcontext *ctx, /** + * Mark a texture object dirty. It forces the object to be incomplete + * and optionally forces the context to re-validate its state. + * + * \param ctx GL context. + * \param texObj texture object. + * \param invalidate_state also invalidate context state. + */ +void +_mesa_dirty_texobj(GLcontext *ctx, struct gl_texture_object *texObj, + GLboolean invalidate_state) +{ + texObj->_Complete = GL_FALSE; + if (invalidate_state) + ctx->NewState |= _NEW_TEXTURE; +} + + +/** * Return pointer to a default/fallback texture. * The texture is a 2D 8x8 RGBA texture with all texels = (0,0,0,1). * That's the value a sampler should get when sampling from an @@ -715,7 +759,6 @@ _mesa_get_fallback_texture(GLcontext *ctx) } - /*@}*/ @@ -1160,10 +1203,9 @@ _mesa_IsTexture( GLuint texture ) /** - * Simplest implementation of texture locking: Grab the a new mutex in - * the shared context. Examine the shared context state timestamp and - * if there has been a change, set the appropriate bits in - * ctx->NewState. + * Simplest implementation of texture locking: grab the shared tex + * mutex. Examine the shared context state timestamp and if there has + * been a change, set the appropriate bits in ctx->NewState. * * This is used to deal with synchronizing things when a texture object * is used/modified by different contexts (or threads) which are sharing diff --git a/src/mesa/main/texobj.h b/src/mesa/main/texobj.h index 2599c0816a..9bfebd45c8 100644 --- a/src/mesa/main/texobj.h +++ b/src/mesa/main/texobj.h @@ -58,6 +58,9 @@ _mesa_copy_texture_object( struct gl_texture_object *dest, const struct gl_texture_object *src ); extern void +_mesa_clear_texture_object(GLcontext *ctx, struct gl_texture_object *obj); + +extern void _mesa_reference_texobj(struct gl_texture_object **ptr, struct gl_texture_object *tex); @@ -65,6 +68,10 @@ extern void _mesa_test_texobj_completeness( const GLcontext *ctx, struct gl_texture_object *obj ); +extern void +_mesa_dirty_texobj(GLcontext *ctx, struct gl_texture_object *texObj, + GLboolean invalidate_state); + extern struct gl_texture_object * _mesa_get_fallback_texture(GLcontext *ctx); @@ -76,7 +83,6 @@ _mesa_lock_context_textures( GLcontext *ctx ); /*@}*/ - /** * \name API functions */ diff --git a/src/mesa/main/texparam.c b/src/mesa/main/texparam.c index d27c59381c..05d144270e 100644 --- a/src/mesa/main/texparam.c +++ b/src/mesa/main/texparam.c @@ -38,6 +38,7 @@ #include "main/texcompress.h" #include "main/texparam.h" #include "main/teximage.h" +#include "main/texstate.h" #include "shader/prog_instruction.h" @@ -88,7 +89,7 @@ get_texobj(GLcontext *ctx, GLenum target) return NULL; } - texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texUnit = _mesa_get_current_tex_unit(ctx); switch (target) { case GL_TEXTURE_1D: @@ -716,44 +717,6 @@ _mesa_GetTexLevelParameterfv( GLenum target, GLint level, } -static GLuint -tex_image_dimensions(GLcontext *ctx, GLenum target) -{ - switch (target) { - case GL_TEXTURE_1D: - case GL_PROXY_TEXTURE_1D: - return 1; - case GL_TEXTURE_2D: - case GL_PROXY_TEXTURE_2D: - return 2; - case GL_TEXTURE_3D: - case GL_PROXY_TEXTURE_3D: - return 3; - case GL_TEXTURE_CUBE_MAP: - case GL_PROXY_TEXTURE_CUBE_MAP: - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - return ctx->Extensions.ARB_texture_cube_map ? 2 : 0; - case GL_TEXTURE_RECTANGLE_NV: - case GL_PROXY_TEXTURE_RECTANGLE_NV: - return ctx->Extensions.NV_texture_rectangle ? 2 : 0; - case GL_TEXTURE_1D_ARRAY_EXT: - case GL_PROXY_TEXTURE_1D_ARRAY_EXT: - return ctx->Extensions.MESA_texture_array ? 2 : 0; - case GL_TEXTURE_2D_ARRAY_EXT: - case GL_PROXY_TEXTURE_2D_ARRAY_EXT: - return ctx->Extensions.MESA_texture_array ? 3 : 0; - default: - _mesa_problem(ctx, "bad target in _mesa_tex_target_dimensions()"); - return 0; - } -} - - void GLAPIENTRY _mesa_GetTexLevelParameteriv( GLenum target, GLint level, GLenum pname, GLint *params ) @@ -761,7 +724,6 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level, const struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; const struct gl_texture_image *img = NULL; - GLuint dimensions; GLboolean isProxy; GLint maxLevels; GET_CURRENT_CONTEXT(ctx); @@ -773,19 +735,13 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level, return; } - texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texUnit = _mesa_get_current_tex_unit(ctx); /* this will catch bad target values */ - dimensions = tex_image_dimensions(ctx, target); /* 1, 2 or 3 */ - if (dimensions == 0) { - _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexLevelParameter[if]v(target)"); - return; - } - maxLevels = _mesa_max_texture_levels(ctx, target); if (maxLevels == 0) { - /* should not happen since <target> was just checked above */ - _mesa_problem(ctx, "maxLevels=0 in _mesa_GetTexLevelParameter"); + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetTexLevelParameter[if]v(target=0x%x)", target); return; } @@ -1002,7 +958,7 @@ _mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params ) return; } - texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texUnit = _mesa_get_current_tex_unit(ctx); obj = _mesa_select_tex_object(ctx, texUnit, target); if (!obj) { @@ -1169,7 +1125,7 @@ _mesa_GetTexParameteriv( GLenum target, GLenum pname, GLint *params ) return; } - texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texUnit = _mesa_get_current_tex_unit(ctx); obj = _mesa_select_tex_object(ctx, texUnit, target); if (!obj) { diff --git a/src/mesa/main/texstate.h b/src/mesa/main/texstate.h index a7d7088c62..17ac68000c 100644 --- a/src/mesa/main/texstate.h +++ b/src/mesa/main/texstate.h @@ -35,6 +35,18 @@ #include "mtypes.h" +/** + * Return pointer to current texture unit. + * This the texture unit set by glActiveTexture(), not glClientActiveTexture(). + */ +static INLINE struct gl_texture_unit * +_mesa_get_current_tex_unit(GLcontext *ctx) +{ + ASSERT(ctx->Texture.CurrentUnit < Elements(ctx->Texture.Unit)); + return &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]); +} + + extern void _mesa_copy_texture_state( const GLcontext *src, GLcontext *dst ); @@ -48,16 +60,14 @@ _mesa_print_texunit_state( GLcontext *ctx, GLuint unit ); */ /*@{*/ - -/* - * GL_ARB_multitexture - */ extern void GLAPIENTRY _mesa_ActiveTextureARB( GLenum target ); extern void GLAPIENTRY _mesa_ClientActiveTextureARB( GLenum target ); +/*@}*/ + /** * \name Initialization, state maintenance diff --git a/src/mesa/main/texstore.c b/src/mesa/main/texstore.c index bfced1b3f4..a22db628d3 100644 --- a/src/mesa/main/texstore.c +++ b/src/mesa/main/texstore.c @@ -3138,7 +3138,7 @@ _mesa_validate_pbo_teximage(GLcontext *ctx, GLuint dimensions, { GLubyte *buf; - if (unpack->BufferObj->Name == 0) { + if (!_mesa_is_bufferobj(unpack->BufferObj)) { /* no PBO */ return pixels; } @@ -3174,7 +3174,7 @@ _mesa_validate_pbo_compressed_teximage(GLcontext *ctx, { GLubyte *buf; - if (packing->BufferObj->Name == 0) { + if (!_mesa_is_bufferobj(packing->BufferObj)) { /* not using a PBO - return pointer unchanged */ return pixels; } @@ -3204,7 +3204,7 @@ void _mesa_unmap_teximage_pbo(GLcontext *ctx, const struct gl_pixelstore_attrib *unpack) { - if (unpack->BufferObj->Name) { + if (_mesa_is_bufferobj(unpack->BufferObj)) { ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, unpack->BufferObj); } diff --git a/src/mesa/main/varray.c b/src/mesa/main/varray.c index 3d5b8faecf..be1c03cec2 100644 --- a/src/mesa/main/varray.c +++ b/src/mesa/main/varray.c @@ -135,7 +135,8 @@ _mesa_VertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr) break; #endif default: - _mesa_error( ctx, GL_INVALID_ENUM, "glVertexPointer(type)" ); + _mesa_error( ctx, GL_INVALID_ENUM, "glVertexPointer(type=%s)", + _mesa_lookup_enum_by_nr(type)); return; } @@ -186,7 +187,8 @@ _mesa_NormalPointer(GLenum type, GLsizei stride, const GLvoid *ptr ) break; #endif default: - _mesa_error( ctx, GL_INVALID_ENUM, "glNormalPointer(type)" ); + _mesa_error( ctx, GL_INVALID_ENUM, "glNormalPointer(type=%s)", + _mesa_lookup_enum_by_nr(type)); return; } @@ -265,7 +267,8 @@ _mesa_ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr) break; #endif default: - _mesa_error( ctx, GL_INVALID_ENUM, "glColorPointer(type)" ); + _mesa_error( ctx, GL_INVALID_ENUM, "glColorPointer(type=%s)", + _mesa_lookup_enum_by_nr(type)); return; } @@ -415,7 +418,8 @@ _mesa_SecondaryColorPointerEXT(GLint size, GLenum type, elementSize = size * sizeof(GLdouble); break; default: - _mesa_error( ctx, GL_INVALID_ENUM, "glSecondaryColorPointer(type)" ); + _mesa_error( ctx, GL_INVALID_ENUM, "glSecondaryColorPointer(type=%s)", + _mesa_lookup_enum_by_nr(type)); return; } @@ -476,7 +480,8 @@ _mesa_TexCoordPointer(GLint size, GLenum type, GLsizei stride, break; #endif default: - _mesa_error( ctx, GL_INVALID_ENUM, "glTexCoordPointer(type)" ); + _mesa_error( ctx, GL_INVALID_ENUM, "glTexCoordPointer(type=%s)", + _mesa_lookup_enum_by_nr(type)); return; } @@ -610,7 +615,8 @@ _mesa_VertexAttribPointerNV(GLuint index, GLint size, GLenum type, elementSize = size * sizeof(GLdouble); break; default: - _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttribPointerNV(type)" ); + _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttribPointerNV(type=%s)", + _mesa_lookup_enum_by_nr(type)); return; } @@ -1093,6 +1099,29 @@ _mesa_MultiModeDrawElementsIBM( const GLenum * mode, const GLsizei * count, /** + * Copy one client vertex array to another. + */ +void +_mesa_copy_client_array(GLcontext *ctx, + struct gl_client_array *dst, + struct gl_client_array *src) +{ + dst->Size = src->Size; + dst->Type = src->Type; + dst->Format = src->Format; + dst->Stride = src->Stride; + dst->StrideB = src->StrideB; + dst->Ptr = src->Ptr; + dst->Enabled = src->Enabled; + dst->Normalized = src->Normalized; + dst->_ElementSize = src->_ElementSize; + _mesa_reference_buffer_object(ctx, &dst->BufferObj, src->BufferObj); + dst->_MaxElement = src->_MaxElement; +} + + + +/** * Print vertex array's fields. */ static void diff --git a/src/mesa/main/varray.h b/src/mesa/main/varray.h index d4d505ae04..becc67c29d 100644 --- a/src/mesa/main/varray.h +++ b/src/mesa/main/varray.h @@ -161,6 +161,12 @@ _mesa_DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, extern void +_mesa_copy_client_array(GLcontext *ctx, + struct gl_client_array *dst, + struct gl_client_array *src); + + +extern void _mesa_print_arrays(GLcontext *ctx); extern void diff --git a/src/mesa/main/viewport.c b/src/mesa/main/viewport.c index 50e0402d27..309308c983 100644 --- a/src/mesa/main/viewport.c +++ b/src/mesa/main/viewport.c @@ -120,6 +120,10 @@ _mesa_DepthRange(GLclampd nearval, GLclampd farval) if (MESA_VERBOSE&VERBOSE_API) _mesa_debug(ctx, "glDepthRange %f %f\n", nearval, farval); + if (ctx->Viewport.Near == nearval && + ctx->Viewport.Far == farval) + return; + ctx->Viewport.Near = (GLfloat) CLAMP(nearval, 0.0, 1.0); ctx->Viewport.Far = (GLfloat) CLAMP(farval, 0.0, 1.0); ctx->NewState |= _NEW_VIEWPORT; diff --git a/src/mesa/shader/arbprogparse.c b/src/mesa/shader/arbprogparse.c index 0f530ebb8a..381445c0e8 100644 --- a/src/mesa/shader/arbprogparse.c +++ b/src/mesa/shader/arbprogparse.c @@ -3975,13 +3975,6 @@ _mesa_parse_arb_fragment_program(GLcontext* ctx, GLenum target, if (program->FogOption) program->Base.InputsRead |= FRAG_BIT_FOGC; - /* XXX: assume that ARB fragment programs don't have access to the - * FrontFacing and PointCoord values stuffed into the fog - * coordinate in GLSL shaders. - */ - if (program->Base.InputsRead & FRAG_BIT_FOGC) - program->UsesFogFragCoord = GL_TRUE; - if (program->Base.Instructions) _mesa_free(program->Base.Instructions); program->Base.Instructions = ap.Base.Instructions; diff --git a/src/mesa/shader/prog_print.c b/src/mesa/shader/prog_print.c index cef0288a9c..3c1c17e099 100644 --- a/src/mesa/shader/prog_print.c +++ b/src/mesa/shader/prog_print.c @@ -933,7 +933,7 @@ _mesa_write_shader_to_file(const struct gl_shader *shader) return; } - fprintf(f, "/* Shader %u source */\n", shader->Name); + fprintf(f, "/* Shader %u source, checksum %u */\n", shader->Name, shader->SourceChecksum); fputs(shader->Source, f); fprintf(f, "\n"); @@ -958,3 +958,35 @@ _mesa_write_shader_to_file(const struct gl_shader *shader) } +/** + * Append the shader's uniform info/values to the shader log file. + * The log file will typically have been created by the + * _mesa_write_shader_to_file function. + */ +void +_mesa_append_uniforms_to_file(const struct gl_shader *shader, + const struct gl_program *prog) +{ + const char *type; + char filename[100]; + FILE *f; + + if (shader->Type == GL_FRAGMENT_SHADER) + type = "frag"; + else + type = "vert"; + + _mesa_snprintf(filename, sizeof(filename), "shader_%u.%s", shader->Name, type); + f = fopen(filename, "a"); /* append */ + if (!f) { + fprintf(stderr, "Unable to open %s for appending\n", filename); + return; + } + + fprintf(f, "/* First-draw parameters / constants */\n"); + fprintf(f, "/*\n"); + _mesa_fprint_parameter_list(f, prog->Parameters); + fprintf(f, "*/\n"); + + fclose(f); +} diff --git a/src/mesa/shader/prog_print.h b/src/mesa/shader/prog_print.h index 3da3e767cd..fc286ded54 100644 --- a/src/mesa/shader/prog_print.h +++ b/src/mesa/shader/prog_print.h @@ -86,5 +86,9 @@ _mesa_print_parameter_list(const struct gl_program_parameter_list *list); extern void _mesa_write_shader_to_file(const struct gl_shader *shader); +extern void +_mesa_append_uniforms_to_file(const struct gl_shader *shader, + const struct gl_program *prog); + #endif /* PROG_PRINT_H */ diff --git a/src/mesa/shader/programopt.c b/src/mesa/shader/programopt.c index ac5fe0f691..f70c75cec8 100644 --- a/src/mesa/shader/programopt.c +++ b/src/mesa/shader/programopt.c @@ -396,7 +396,6 @@ _mesa_append_fog_code(GLcontext *ctx, struct gl_fragment_program *fprog) fprog->Base.Instructions = newInst; fprog->Base.NumInstructions = inst - newInst; fprog->Base.InputsRead |= FRAG_BIT_FOGC; - fprog->UsesFogFragCoord = GL_TRUE; /* XXX do this? fprog->FogOption = GL_NONE; */ } diff --git a/src/mesa/shader/shader_api.c b/src/mesa/shader/shader_api.c index 648fbc186b..cf0a902389 100644 --- a/src/mesa/shader/shader_api.c +++ b/src/mesa/shader/shader_api.c @@ -885,7 +885,7 @@ _mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index, static struct gl_program_parameter * get_uniform_parameter(const struct gl_shader_program *shProg, GLuint index) { - const struct gl_program *prog; + const struct gl_program *prog = NULL; GLint progPos; progPos = shProg->Uniforms->Uniforms[index].VertPos; @@ -915,7 +915,7 @@ _mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index, GLenum *type, GLchar *nameOut) { const struct gl_shader_program *shProg; - const struct gl_program *prog; + const struct gl_program *prog = NULL; const struct gl_program_parameter *param; GLint progPos; @@ -1431,6 +1431,9 @@ _mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source) } sh->Source = source; sh->CompileStatus = GL_FALSE; +#ifdef DEBUG + sh->SourceChecksum = _mesa_str_checksum(sh->Source); +#endif } @@ -1506,9 +1509,10 @@ _mesa_use_program(GLcontext *ctx, GLuint program) GLuint i; _mesa_printf("Use Shader %u\n", shProg->Name); for (i = 0; i < shProg->NumShaders; i++) { - _mesa_printf(" shader %u, type 0x%x\n", + _mesa_printf(" shader %u, type 0x%x, checksum %u\n", shProg->Shaders[i]->Name, - shProg->Shaders[i]->Type); + shProg->Shaders[i]->Type, + shProg->Shaders[i]->SourceChecksum); } if (shProg->VertexProgram) printf(" vert prog %u\n", shProg->VertexProgram->Base.Id); diff --git a/src/mesa/shader/slang/slang_builtin.c b/src/mesa/shader/slang/slang_builtin.c index 289d94644f..ad2e306c19 100644 --- a/src/mesa/shader/slang/slang_builtin.c +++ b/src/mesa/shader/slang/slang_builtin.c @@ -710,3 +710,186 @@ _slang_alloc_statevar(slang_ir_node *n, *direct = GL_FALSE; return alloc_state_var_array(n->Var, paramList); } + + + + +#define SWIZZLE_ZWWW MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W) + + +/** Predefined shader inputs */ +struct input_info +{ + const char *Name; + GLuint Attrib; + GLenum Type; + GLuint Swizzle; +}; + +/** Predefined vertex shader inputs/attributes */ +static const struct input_info vertInputs[] = { + { "gl_Vertex", VERT_ATTRIB_POS, GL_FLOAT_VEC4, SWIZZLE_NOOP }, + { "gl_Normal", VERT_ATTRIB_NORMAL, GL_FLOAT_VEC3, SWIZZLE_NOOP }, + { "gl_Color", VERT_ATTRIB_COLOR0, GL_FLOAT_VEC4, SWIZZLE_NOOP }, + { "gl_SecondaryColor", VERT_ATTRIB_COLOR1, GL_FLOAT_VEC4, SWIZZLE_NOOP }, + { "gl_FogCoord", VERT_ATTRIB_FOG, GL_FLOAT, SWIZZLE_XXXX }, + { "gl_MultiTexCoord0", VERT_ATTRIB_TEX0, GL_FLOAT_VEC4, SWIZZLE_NOOP }, + { "gl_MultiTexCoord1", VERT_ATTRIB_TEX1, GL_FLOAT_VEC4, SWIZZLE_NOOP }, + { "gl_MultiTexCoord2", VERT_ATTRIB_TEX2, GL_FLOAT_VEC4, SWIZZLE_NOOP }, + { "gl_MultiTexCoord3", VERT_ATTRIB_TEX3, GL_FLOAT_VEC4, SWIZZLE_NOOP }, + { "gl_MultiTexCoord4", VERT_ATTRIB_TEX4, GL_FLOAT_VEC4, SWIZZLE_NOOP }, + { "gl_MultiTexCoord5", VERT_ATTRIB_TEX5, GL_FLOAT_VEC4, SWIZZLE_NOOP }, + { "gl_MultiTexCoord6", VERT_ATTRIB_TEX6, GL_FLOAT_VEC4, SWIZZLE_NOOP }, + { "gl_MultiTexCoord7", VERT_ATTRIB_TEX7, GL_FLOAT_VEC4, SWIZZLE_NOOP }, + { NULL, 0, SWIZZLE_NOOP } +}; + +/** Predefined fragment shader inputs */ +static const struct input_info fragInputs[] = { + { "gl_FragCoord", FRAG_ATTRIB_WPOS, GL_FLOAT_VEC4, SWIZZLE_NOOP }, + { "gl_Color", FRAG_ATTRIB_COL0, GL_FLOAT_VEC4, SWIZZLE_NOOP }, + { "gl_SecondaryColor", FRAG_ATTRIB_COL1, GL_FLOAT_VEC4, SWIZZLE_NOOP }, + { "gl_TexCoord", FRAG_ATTRIB_TEX0, GL_FLOAT_VEC4, SWIZZLE_NOOP }, + /* note: we're packing several quantities into the fogcoord vector */ + { "gl_FogFragCoord", FRAG_ATTRIB_FOGC, GL_FLOAT, SWIZZLE_XXXX }, + { "gl_FrontFacing", FRAG_ATTRIB_FACE, GL_FLOAT, SWIZZLE_XXXX }, + { "gl_PointCoord", FRAG_ATTRIB_PNTC, GL_FLOAT_VEC2, SWIZZLE_XYZW }, + { NULL, 0, SWIZZLE_NOOP } +}; + + +/** + * Return the VERT_ATTRIB_* or FRAG_ATTRIB_* value that corresponds to + * a vertex or fragment program input variable. Return -1 if the input + * name is invalid. + * XXX return size too + */ +GLint +_slang_input_index(const char *name, GLenum target, GLuint *swizzleOut) +{ + const struct input_info *inputs; + GLuint i; + + switch (target) { + case GL_VERTEX_PROGRAM_ARB: + inputs = vertInputs; + break; + case GL_FRAGMENT_PROGRAM_ARB: + inputs = fragInputs; + break; + /* XXX geom program */ + default: + _mesa_problem(NULL, "bad target in _slang_input_index"); + return -1; + } + + ASSERT(MAX_TEXTURE_COORD_UNITS == 8); /* if this fails, fix vertInputs above */ + + for (i = 0; inputs[i].Name; i++) { + if (strcmp(inputs[i].Name, name) == 0) { + /* found */ + *swizzleOut = inputs[i].Swizzle; + return inputs[i].Attrib; + } + } + return -1; +} + + +/** + * Return name of the given vertex attribute (VERT_ATTRIB_x). + */ +const char * +_slang_vert_attrib_name(GLuint attrib) +{ + GLuint i; + assert(attrib < VERT_ATTRIB_GENERIC0); + for (i = 0; vertInputs[i].Name; i++) { + if (vertInputs[i].Attrib == attrib) + return vertInputs[i].Name; + } + return NULL; +} + + +/** + * Return type (GL_FLOAT, GL_FLOAT_VEC2, etc) of the given vertex + * attribute (VERT_ATTRIB_x). + */ +GLenum +_slang_vert_attrib_type(GLuint attrib) +{ + GLuint i; + assert(attrib < VERT_ATTRIB_GENERIC0); + for (i = 0; vertInputs[i].Name; i++) { + if (vertInputs[i].Attrib == attrib) + return vertInputs[i].Type; + } + return GL_NONE; +} + + + + + +/** Predefined shader output info */ +struct output_info +{ + const char *Name; + GLuint Attrib; +}; + +/** Predefined vertex shader outputs */ +static const struct output_info vertOutputs[] = { + { "gl_Position", VERT_RESULT_HPOS }, + { "gl_FrontColor", VERT_RESULT_COL0 }, + { "gl_BackColor", VERT_RESULT_BFC0 }, + { "gl_FrontSecondaryColor", VERT_RESULT_COL1 }, + { "gl_BackSecondaryColor", VERT_RESULT_BFC1 }, + { "gl_TexCoord", VERT_RESULT_TEX0 }, + { "gl_FogFragCoord", VERT_RESULT_FOGC }, + { "gl_PointSize", VERT_RESULT_PSIZ }, + { NULL, 0 } +}; + +/** Predefined fragment shader outputs */ +static const struct output_info fragOutputs[] = { + { "gl_FragColor", FRAG_RESULT_COLOR }, + { "gl_FragDepth", FRAG_RESULT_DEPTH }, + { "gl_FragData", FRAG_RESULT_DATA0 }, + { NULL, 0 } +}; + + +/** + * Return the VERT_RESULT_* or FRAG_RESULT_* value that corresponds to + * a vertex or fragment program output variable. Return -1 for an invalid + * output name. + */ +GLint +_slang_output_index(const char *name, GLenum target) +{ + const struct output_info *outputs; + GLuint i; + + switch (target) { + case GL_VERTEX_PROGRAM_ARB: + outputs = vertOutputs; + break; + case GL_FRAGMENT_PROGRAM_ARB: + outputs = fragOutputs; + break; + /* XXX geom program */ + default: + _mesa_problem(NULL, "bad target in _slang_output_index"); + return -1; + } + + for (i = 0; outputs[i].Name; i++) { + if (strcmp(outputs[i].Name, name) == 0) { + /* found */ + return outputs[i].Attrib; + } + } + return -1; +} diff --git a/src/mesa/shader/slang/slang_builtin.h b/src/mesa/shader/slang/slang_builtin.h index 7f6fe80fcc..f814d11ac7 100644 --- a/src/mesa/shader/slang/slang_builtin.h +++ b/src/mesa/shader/slang/slang_builtin.h @@ -37,4 +37,18 @@ _slang_alloc_statevar(slang_ir_node *n, GLboolean *direct); +extern GLint +_slang_input_index(const char *name, GLenum target, GLuint *swizzleOut); + +extern GLint +_slang_output_index(const char *name, GLenum target); + + +extern const char * +_slang_vert_attrib_name(GLuint attrib); + +extern GLenum +_slang_vert_attrib_type(GLuint attrib); + + #endif /* SLANG_BUILTIN_H */ diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c index 2b7e781f98..349f432dec 100644 --- a/src/mesa/shader/slang/slang_codegen.c +++ b/src/mesa/shader/slang/slang_codegen.c @@ -46,6 +46,7 @@ #include "shader/prog_print.h" #include "shader/prog_statevars.h" #include "slang_typeinfo.h" +#include "slang_builtin.h" #include "slang_codegen.h" #include "slang_compile.h" #include "slang_label.h" @@ -342,109 +343,6 @@ slang_operation_identifier(slang_operation *oper, } -#define SWIZZLE_ZWWW MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W) - -/** - * Return the VERT_ATTRIB_* or FRAG_ATTRIB_* value that corresponds to - * a vertex or fragment program input variable. Return -1 if the input - * name is invalid. - * XXX return size too - */ -static GLint -_slang_input_index(const char *name, GLenum target, GLuint *swizzleOut) -{ - struct input_info { - const char *Name; - GLuint Attrib; - GLuint Swizzle; - }; - static const struct input_info vertInputs[] = { - { "gl_Vertex", VERT_ATTRIB_POS, SWIZZLE_NOOP }, - { "gl_Normal", VERT_ATTRIB_NORMAL, SWIZZLE_NOOP }, - { "gl_Color", VERT_ATTRIB_COLOR0, SWIZZLE_NOOP }, - { "gl_SecondaryColor", VERT_ATTRIB_COLOR1, SWIZZLE_NOOP }, - { "gl_FogCoord", VERT_ATTRIB_FOG, SWIZZLE_XXXX }, - { "gl_MultiTexCoord0", VERT_ATTRIB_TEX0, SWIZZLE_NOOP }, - { "gl_MultiTexCoord1", VERT_ATTRIB_TEX1, SWIZZLE_NOOP }, - { "gl_MultiTexCoord2", VERT_ATTRIB_TEX2, SWIZZLE_NOOP }, - { "gl_MultiTexCoord3", VERT_ATTRIB_TEX3, SWIZZLE_NOOP }, - { "gl_MultiTexCoord4", VERT_ATTRIB_TEX4, SWIZZLE_NOOP }, - { "gl_MultiTexCoord5", VERT_ATTRIB_TEX5, SWIZZLE_NOOP }, - { "gl_MultiTexCoord6", VERT_ATTRIB_TEX6, SWIZZLE_NOOP }, - { "gl_MultiTexCoord7", VERT_ATTRIB_TEX7, SWIZZLE_NOOP }, - { NULL, 0, SWIZZLE_NOOP } - }; - static const struct input_info fragInputs[] = { - { "gl_FragCoord", FRAG_ATTRIB_WPOS, SWIZZLE_NOOP }, - { "gl_Color", FRAG_ATTRIB_COL0, SWIZZLE_NOOP }, - { "gl_SecondaryColor", FRAG_ATTRIB_COL1, SWIZZLE_NOOP }, - { "gl_TexCoord", FRAG_ATTRIB_TEX0, SWIZZLE_NOOP }, - /* note: we're packing several quantities into the fogcoord vector */ - { "gl_FogFragCoord", FRAG_ATTRIB_FOGC, SWIZZLE_XXXX }, - { "gl_FrontFacing", FRAG_ATTRIB_FOGC, SWIZZLE_YYYY }, /*XXX*/ - { "gl_PointCoord", FRAG_ATTRIB_FOGC, SWIZZLE_ZWWW }, - { NULL, 0, SWIZZLE_NOOP } - }; - GLuint i; - const struct input_info *inputs - = (target == GL_VERTEX_PROGRAM_ARB) ? vertInputs : fragInputs; - - ASSERT(MAX_TEXTURE_COORD_UNITS == 8); /* if this fails, fix vertInputs above */ - - for (i = 0; inputs[i].Name; i++) { - if (strcmp(inputs[i].Name, name) == 0) { - /* found */ - *swizzleOut = inputs[i].Swizzle; - return inputs[i].Attrib; - } - } - return -1; -} - - -/** - * Return the VERT_RESULT_* or FRAG_RESULT_* value that corresponds to - * a vertex or fragment program output variable. Return -1 for an invalid - * output name. - */ -static GLint -_slang_output_index(const char *name, GLenum target) -{ - struct output_info { - const char *Name; - GLuint Attrib; - }; - static const struct output_info vertOutputs[] = { - { "gl_Position", VERT_RESULT_HPOS }, - { "gl_FrontColor", VERT_RESULT_COL0 }, - { "gl_BackColor", VERT_RESULT_BFC0 }, - { "gl_FrontSecondaryColor", VERT_RESULT_COL1 }, - { "gl_BackSecondaryColor", VERT_RESULT_BFC1 }, - { "gl_TexCoord", VERT_RESULT_TEX0 }, - { "gl_FogFragCoord", VERT_RESULT_FOGC }, - { "gl_PointSize", VERT_RESULT_PSIZ }, - { NULL, 0 } - }; - static const struct output_info fragOutputs[] = { - { "gl_FragColor", FRAG_RESULT_COLOR }, - { "gl_FragDepth", FRAG_RESULT_DEPTH }, - { "gl_FragData", FRAG_RESULT_DATA0 }, - { NULL, 0 } - }; - GLuint i; - const struct output_info *outputs - = (target == GL_VERTEX_PROGRAM_ARB) ? vertOutputs : fragOutputs; - - for (i = 0; outputs[i].Name; i++) { - if (strcmp(outputs[i].Name, name) == 0) { - /* found */ - return outputs[i].Attrib; - } - } - return -1; -} - - /** * Called when we begin code/IR generation for a new while/do/for loop. */ diff --git a/src/mesa/shader/slang/slang_link.c b/src/mesa/shader/slang/slang_link.c index f6032d1e9a..1caf5946fd 100644 --- a/src/mesa/shader/slang/slang_link.c +++ b/src/mesa/shader/slang/slang_link.c @@ -40,6 +40,7 @@ #include "shader/prog_statevars.h" #include "shader/prog_uniform.h" #include "shader/shader_api.h" +#include "slang_builtin.h" #include "slang_link.h" @@ -327,6 +328,7 @@ _slang_resolve_attributes(struct gl_shader_program *shProg, GLint attribMap[MAX_VERTEX_GENERIC_ATTRIBS]; GLuint i, j; GLbitfield usedAttributes; /* generics only, not legacy attributes */ + GLbitfield inputsRead = 0x0; assert(origProg != linkedProg); assert(origProg->Target == GL_VERTEX_PROGRAM_ARB); @@ -370,6 +372,10 @@ _slang_resolve_attributes(struct gl_shader_program *shProg, for (i = 0; i < linkedProg->NumInstructions; i++) { struct prog_instruction *inst = linkedProg->Instructions + i; for (j = 0; j < 3; j++) { + if (inst->SrcReg[j].File == PROGRAM_INPUT) { + inputsRead |= (1 << inst->SrcReg[j].Index); + } + if (inst->SrcReg[j].File == PROGRAM_INPUT && inst->SrcReg[j].Index >= VERT_ATTRIB_GENERIC0) { /* @@ -431,6 +437,20 @@ _slang_resolve_attributes(struct gl_shader_program *shProg, } } + /* Handle pre-defined attributes here (gl_Vertex, gl_Normal, etc). + * When the user queries the active attributes we need to include both + * the user-defined attributes and the built-in ones. + */ + for (i = VERT_ATTRIB_POS; i < VERT_ATTRIB_GENERIC0; i++) { + if (inputsRead & (1 << i)) { + _mesa_add_attribute(linkedProg->Attributes, + _slang_vert_attrib_name(i), + 4, /* size in floats */ + _slang_vert_attrib_type(i), + -1 /* attrib/input */); + } + } + return GL_TRUE; } @@ -484,20 +504,6 @@ _slang_update_inputs_outputs(struct gl_program *prog) for (j = 0; j < numSrc; j++) { if (inst->SrcReg[j].File == PROGRAM_INPUT) { prog->InputsRead |= 1 << inst->SrcReg[j].Index; - if (prog->Target == GL_FRAGMENT_PROGRAM_ARB && - inst->SrcReg[j].Index == FRAG_ATTRIB_FOGC) { - /* The fragment shader FOGC input is used for fog, - * front-facing and sprite/point coord. - */ - struct gl_fragment_program *fp = fragment_program(prog); - const GLint swz = GET_SWZ(inst->SrcReg[j].Swizzle, 0); - if (swz == SWIZZLE_X) - fp->UsesFogFragCoord = GL_TRUE; - else if (swz == SWIZZLE_Y) - fp->UsesFrontFacing = GL_TRUE; - else if (swz == SWIZZLE_Z || swz == SWIZZLE_W) - fp->UsesPointCoord = GL_TRUE; - } } else if (inst->SrcReg[j].File == PROGRAM_ADDRESS) { maxAddrReg = MAX2(maxAddrReg, (GLuint) (inst->SrcReg[j].Index + 1)); diff --git a/src/mesa/sources.mak b/src/mesa/sources.mak index b4b36368cf..d1c109c2c5 100644 --- a/src/mesa/sources.mak +++ b/src/mesa/sources.mak @@ -303,7 +303,8 @@ SPARC_API = \ sparc/glapi_sparc.S COMMON_DRIVER_SOURCES = \ - drivers/common/driverfuncs.c + drivers/common/driverfuncs.c \ + drivers/common/meta.c # Sources for building non-Gallium drivers diff --git a/src/mesa/state_tracker/st_atom_shader.c b/src/mesa/state_tracker/st_atom_shader.c index 8b3bb5cc03..ee649be885 100644 --- a/src/mesa/state_tracker/st_atom_shader.c +++ b/src/mesa/state_tracker/st_atom_shader.c @@ -139,23 +139,6 @@ find_translated_vp(struct st_context *st, if (fragInputsRead & (1 << inAttr)) { stfp->input_to_slot[inAttr] = numIn; numIn++; - if (((1 << inAttr) & FRAG_BIT_FOGC)) { - /* leave placeholders for the - * extra registers we extract from fog */ - if (stfp->Base.UsesFrontFacing) { - if (!stfp->Base.UsesFogFragCoord) - --stfp->input_to_slot[inAttr]; - else - ++numIn; - } - if (stfp->Base.UsesPointCoord) { - if (!stfp->Base.UsesFrontFacing && - !stfp->Base.UsesFogFragCoord) - stfp->input_to_slot[inAttr] -= 2; - else - ++numIn; - } - } } else { stfp->input_to_slot[inAttr] = UNUSED; diff --git a/src/mesa/state_tracker/st_cb_blit.c b/src/mesa/state_tracker/st_cb_blit.c index 2852623472..c741940bcf 100644 --- a/src/mesa/state_tracker/st_cb_blit.c +++ b/src/mesa/state_tracker/st_cb_blit.c @@ -69,34 +69,107 @@ st_BlitFramebuffer(GLcontext *ctx, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) { + const GLbitfield depthStencil = (GL_DEPTH_BUFFER_BIT | + GL_STENCIL_BUFFER_BIT); struct st_context *st = ctx->st; - const uint pFilter = ((filter == GL_NEAREST) ? PIPE_TEX_MIPFILTER_NEAREST : PIPE_TEX_MIPFILTER_LINEAR); + struct gl_framebuffer *readFB = ctx->ReadBuffer; + struct gl_framebuffer *drawFB = ctx->DrawBuffer; + + if (!_mesa_clip_blit(ctx, &srcX0, &srcY0, &srcX1, &srcY1, + &dstX0, &dstY0, &dstX1, &dstY1)) { + return; /* nothing to draw/blit */ + } + + if (st_fb_orientation(drawFB) == Y_0_TOP) { + /* invert Y for dest */ + dstY0 = drawFB->Height - dstY0; + dstY1 = drawFB->Height - dstY1; + } + + if (st_fb_orientation(readFB) == Y_0_TOP) { + /* invert Y for src */ + srcY0 = readFB->Height - srcY0; + srcY1 = readFB->Height - srcY1; + } + + if (srcY0 > srcY1 && dstY0 > dstY1) { + /* Both src and dst are upside down. Swap Y to make it + * right-side up to increase odds of using a fast path. + * Recall that all Gallium raster coords have Y=0=top. + */ + GLint tmp; + tmp = srcY0; + srcY0 = srcY1; + srcY1 = tmp; + tmp = dstY0; + dstY0 = dstY1; + dstY1 = tmp; + } if (mask & GL_COLOR_BUFFER_BIT) { struct st_renderbuffer *srcRb = - st_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer); + st_renderbuffer(readFB->_ColorReadBuffer); struct st_renderbuffer *dstRb = - st_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0]); + st_renderbuffer(drawFB->_ColorDrawBuffers[0]); struct pipe_surface *srcSurf = srcRb->surface; struct pipe_surface *dstSurf = dstRb->surface; - if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { - /* invert Y */ - srcY0 = srcRb->Base.Height - srcY0; - srcY1 = srcRb->Base.Height - srcY1; - - dstY0 = dstRb->Base.Height - dstY0; - dstY1 = dstRb->Base.Height - dstY1; - } - util_blit_pixels(st->blit, srcSurf, srcX0, srcY0, srcX1, srcY1, dstSurf, dstX0, dstY0, dstX1, dstY1, 0.0, pFilter); + } + if (mask & depthStencil) { + /* depth and/or stencil blit */ + + /* get src/dst depth surfaces */ + struct st_renderbuffer *srcDepthRb = + st_renderbuffer(readFB->Attachment[BUFFER_DEPTH].Renderbuffer); + struct st_renderbuffer *dstDepthRb = + st_renderbuffer(drawFB->Attachment[BUFFER_DEPTH].Renderbuffer); + struct pipe_surface *srcDepthSurf = + srcDepthRb ? srcDepthRb->surface : NULL; + struct pipe_surface *dstDepthSurf = + dstDepthRb ? dstDepthRb->surface : NULL; + + /* get src/dst stencil surfaces */ + struct st_renderbuffer *srcStencilRb = + st_renderbuffer(readFB->Attachment[BUFFER_STENCIL].Renderbuffer); + struct st_renderbuffer *dstStencilRb = + st_renderbuffer(drawFB->Attachment[BUFFER_STENCIL].Renderbuffer); + struct pipe_surface *srcStencilSurf = + srcStencilRb ? srcStencilRb->surface : NULL; + struct pipe_surface *dstStencilSurf = + dstStencilRb ? dstStencilRb->surface : NULL; + + if ((mask & depthStencil) == depthStencil && + srcDepthSurf == srcStencilSurf && + dstDepthSurf == dstStencilSurf) { + /* Blitting depth and stencil values between combined + * depth/stencil buffers. This is the ideal case for such buffers. + */ + util_blit_pixels(st->blit, + srcDepthSurf, srcX0, srcY0, srcX1, srcY1, + dstDepthSurf, dstX0, dstY0, dstX1, dstY1, + 0.0, pFilter); + } + else { + /* blitting depth and stencil separately */ + + if (mask & GL_DEPTH_BUFFER_BIT) { + /* blit Z only */ + _mesa_problem(ctx, "st_BlitFramebuffer(DEPTH) not completed"); + } + + if (mask & GL_STENCIL_BUFFER_BIT) { + /* blit stencil only */ + _mesa_problem(ctx, "st_BlitFramebuffer(STENCIL) not completed"); + } + } } } diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c index b39403129d..d19a88fa7c 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/src/mesa/state_tracker/st_cb_drawpixels.c @@ -804,8 +804,8 @@ st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, return; } - _mesa_set_vp_override( ctx, TRUE ); - _mesa_update_state( ctx ); + /* Mesa state should be up to date by now */ + assert(ctx->NewState == 0x0); st_validate_state(st); @@ -833,8 +833,6 @@ st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, pipe_texture_reference(&pt, NULL); } } - - _mesa_set_vp_override( ctx, FALSE ); } diff --git a/src/mesa/state_tracker/st_cb_rasterpos.c b/src/mesa/state_tracker/st_cb_rasterpos.c index 3bcccd0df4..d82b2a2035 100644 --- a/src/mesa/state_tracker/st_cb_rasterpos.c +++ b/src/mesa/state_tracker/st_cb_rasterpos.c @@ -251,7 +251,7 @@ st_RasterPos(GLcontext *ctx, const GLfloat v[4]) rs->array[0].Ptr = (GLubyte *) v; /* draw the point */ - st_feedback_draw_vbo(ctx, rs->arrays, &rs->prim, 1, NULL, 0, 1); + st_feedback_draw_vbo(ctx, rs->arrays, &rs->prim, 1, NULL, GL_TRUE, 0, 1); } diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c index e8d7f70ad6..90a059ca69 100644 --- a/src/mesa/state_tracker/st_cb_texture.c +++ b/src/mesa/state_tracker/st_cb_texture.c @@ -523,6 +523,12 @@ st_TexImage(GLcontext * ctx, DBG("%s target %s level %d %dx%dx%d border %d\n", __FUNCTION__, _mesa_lookup_enum_by_nr(target), level, width, height, depth, border); + /* switch to "normal" */ + if (stObj->surface_based) { + _mesa_clear_texture_object(ctx, texObj); + stObj->surface_based = GL_FALSE; + } + /* gallium does not support texture borders, strip it off */ if (border) { strip_texture_border(border, &width, &height, &depth, unpack, &unpackNB); diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c index 914a507bef..503a5f34a3 100644 --- a/src/mesa/state_tracker/st_draw.c +++ b/src/mesa/state_tracker/st_draw.c @@ -533,6 +533,7 @@ st_draw_vbo(GLcontext *ctx, const struct _mesa_prim *prims, GLuint nr_prims, const struct _mesa_index_buffer *ib, + GLboolean index_bounds_valid, GLuint min_index, GLuint max_index) { @@ -545,6 +546,10 @@ st_draw_vbo(GLcontext *ctx, unsigned num_vbuffers, num_velements; GLboolean userSpace; + /* Gallium probably doesn't want this in some cases. */ + if (!index_bounds_valid) + vbo_get_minmax_index(ctx, prims, ib, &min_index, &max_index); + /* sanity check for pointer arithmetic below */ assert(sizeof(arrays[0]->Ptr[0]) == 1); diff --git a/src/mesa/state_tracker/st_draw.h b/src/mesa/state_tracker/st_draw.h index dcfe7e1536..3e0face656 100644 --- a/src/mesa/state_tracker/st_draw.h +++ b/src/mesa/state_tracker/st_draw.h @@ -47,6 +47,7 @@ st_draw_vbo(GLcontext *ctx, const struct _mesa_prim *prims, GLuint nr_prims, const struct _mesa_index_buffer *ib, + GLboolean index_bounds_valid, GLuint min_index, GLuint max_index); @@ -56,6 +57,7 @@ st_feedback_draw_vbo(GLcontext *ctx, const struct _mesa_prim *prims, GLuint nr_prims, const struct _mesa_index_buffer *ib, + GLboolean index_bounds_valid, GLuint min_index, GLuint max_index); diff --git a/src/mesa/state_tracker/st_draw_feedback.c b/src/mesa/state_tracker/st_draw_feedback.c index 2712c131c0..b2d682ef64 100644 --- a/src/mesa/state_tracker/st_draw_feedback.c +++ b/src/mesa/state_tracker/st_draw_feedback.c @@ -96,6 +96,7 @@ st_feedback_draw_vbo(GLcontext *ctx, const struct _mesa_prim *prims, GLuint nr_prims, const struct _mesa_index_buffer *ib, + GLboolean index_bounds_valid, GLuint min_index, GLuint max_index) { @@ -114,6 +115,9 @@ st_feedback_draw_vbo(GLcontext *ctx, st_validate_state(ctx->st); + if (!index_bounds_valid) + vbo_get_minmax_index(ctx, prims, ib, &min_index, &max_index); + /* must get these after state validation! */ vp = ctx->st->vp; vs = &st->vp->state; diff --git a/src/mesa/state_tracker/st_extensions.c b/src/mesa/state_tracker/st_extensions.c index 8a958e8bd8..3f835d38dd 100644 --- a/src/mesa/state_tracker/st_extensions.c +++ b/src/mesa/state_tracker/st_extensions.c @@ -233,7 +233,9 @@ void st_init_extensions(struct st_context *st) if (screen->get_param(screen, PIPE_CAP_POINT_SPRITE)) { ctx->Extensions.ARB_point_sprite = GL_TRUE; - ctx->Extensions.NV_point_sprite = GL_TRUE; + /* GL_NV_point_sprite is not supported by gallium because we don't + * support the GL_POINT_SPRITE_R_MODE_NV option. + */ } if (screen->get_param(screen, PIPE_CAP_OCCLUSION_QUERY)) { diff --git a/src/mesa/state_tracker/st_mesa_to_tgsi.c b/src/mesa/state_tracker/st_mesa_to_tgsi.c index dd7e40be08..2ab12d3cf3 100644 --- a/src/mesa/state_tracker/st_mesa_to_tgsi.c +++ b/src/mesa/state_tracker/st_mesa_to_tgsi.c @@ -112,27 +112,6 @@ map_register_file_index( { switch( file ) { case TGSI_FILE_INPUT: - if (procType == TGSI_PROCESSOR_FRAGMENT && - index == FRAG_ATTRIB_FOGC) { - if (GET_SWZ(*swizzle, 0) == SWIZZLE_X) { - /* do nothing we're, ok */ - } else if (GET_SWZ(*swizzle, 0) == SWIZZLE_Y) { - /* replace the swizzle with xxxx */ - *swizzle = MAKE_SWIZZLE4(SWIZZLE_X, - SWIZZLE_X, - SWIZZLE_X, - SWIZZLE_X); - /* register after fog */ - return inputMapping[index] + 1; - } else { - *swizzle = MAKE_SWIZZLE4(SWIZZLE_Z, - SWIZZLE_W, - SWIZZLE_Z, - SWIZZLE_W); - /* register after frontface */ - return inputMapping[index] + 2; - } - } /* inputs are mapped according to the user-defined map */ return inputMapping[index]; diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c index 806e0ca8f6..d2da20ae42 100644 --- a/src/mesa/state_tracker/st_program.c +++ b/src/mesa/state_tracker/st_program.c @@ -458,34 +458,20 @@ st_translate_fragment_program(struct st_context *st, stfp->input_semantic_index[slot] = 1; interpMode[slot] = TGSI_INTERPOLATE_LINEAR; break; - case FRAG_ATTRIB_FOGC: { - int extra_decls = 0; - if (stfp->Base.UsesFogFragCoord) { - stfp->input_semantic_name[slot] = TGSI_SEMANTIC_FOG; - stfp->input_semantic_index[slot] = 0; - interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; - input_flags[slot] = stfp->Base.Base.InputFlags[attr]; - ++extra_decls; - } - if (stfp->Base.UsesFrontFacing) { - GLint idx = slot + extra_decls; - stfp->input_semantic_name[idx] = TGSI_SEMANTIC_FACE; - stfp->input_semantic_index[idx] = 0; - interpMode[idx] = TGSI_INTERPOLATE_CONSTANT; - input_flags[idx] = stfp->Base.Base.InputFlags[attr]; - ++extra_decls; - } - if (stfp->Base.UsesPointCoord) { - GLint idx = slot + extra_decls; - stfp->input_semantic_name[idx] = TGSI_SEMANTIC_GENERIC; - stfp->input_semantic_index[idx] = num_generic++; - interpMode[idx] = TGSI_INTERPOLATE_PERSPECTIVE; - input_flags[idx] = stfp->Base.Base.InputFlags[attr]; - ++extra_decls; - } - fs_num_inputs += extra_decls - 1; - continue; - } + case FRAG_ATTRIB_FOGC: + stfp->input_semantic_name[slot] = TGSI_SEMANTIC_FOG; + stfp->input_semantic_index[slot] = 0; + interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; + break; + case FRAG_ATTRIB_FACE: + stfp->input_semantic_name[slot] = TGSI_SEMANTIC_FACE; + stfp->input_semantic_index[slot] = num_generic++; + interpMode[slot] = TGSI_INTERPOLATE_CONSTANT; + break; + case FRAG_ATTRIB_PNTC: + stfp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; + stfp->input_semantic_index[slot] = num_generic++; + interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; break; case FRAG_ATTRIB_TEX0: case FRAG_ATTRIB_TEX1: diff --git a/src/mesa/state_tracker/st_public.h b/src/mesa/state_tracker/st_public.h index 04d3a3d7c2..a5fdac32d1 100644 --- a/src/mesa/state_tracker/st_public.h +++ b/src/mesa/state_tracker/st_public.h @@ -107,7 +107,9 @@ void st_swapbuffers(struct st_framebuffer *stfb, struct pipe_surface **front_left, struct pipe_surface **front_right); -int st_set_teximage(struct pipe_texture *pt, int target); +int st_bind_texture_surface(struct pipe_surface *ps, int target, int level, + enum pipe_format format); +int st_unbind_texture_surface(struct pipe_surface *ps, int target, int level); /** Redirect rendering into stfb's surface to a texture image */ int st_bind_teximage(struct st_framebuffer *stfb, uint surfIndex, diff --git a/src/mesa/state_tracker/st_texture.c b/src/mesa/state_tracker/st_texture.c index 10faa633ea..d58803991a 100644 --- a/src/mesa/state_tracker/st_texture.c +++ b/src/mesa/state_tracker/st_texture.c @@ -32,6 +32,7 @@ #include "st_cb_fbo.h" #include "st_inlines.h" #include "main/enums.h" +#include "main/texobj.h" #include "main/teximage.h" #include "main/texstore.h" @@ -353,25 +354,95 @@ st_texture_image_copy(struct pipe_context *pipe, } } -/** Bind a pipe surface for use as a texture image */ + +/** + * Bind a pipe surface to a texture object. After the call, + * the texture object is marked dirty and will be (re-)validated. + * + * If this is the first surface bound, the texture object is said to + * switch from normal to surface based. It will be cleared first in + * this case. + * + * \param ps pipe surface to be unbound + * \param target texture target + * \param level image level + * \param format internal format of the texture + */ int -st_set_teximage(struct pipe_texture *pt, int target) +st_bind_texture_surface(struct pipe_surface *ps, int target, int level, + enum pipe_format format) { GET_CURRENT_CONTEXT(ctx); const GLuint unit = ctx->Texture.CurrentUnit; struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; struct gl_texture_object *texObj; struct gl_texture_image *texImage; + struct st_texture_object *stObj; struct st_texture_image *stImage; - int internalFormat; + GLenum internalFormat; - switch (pt->format) { - case PIPE_FORMAT_A8R8G8B8_UNORM: - internalFormat = GL_RGBA8; + switch (target) { + case ST_TEXTURE_2D: + target = GL_TEXTURE_2D; + break; + case ST_TEXTURE_RECT: + target = GL_TEXTURE_RECTANGLE_ARB; break; default: return 0; - }; + } + + /* map pipe format to base format for now */ + if (pf_get_component_bits(format, PIPE_FORMAT_COMP_A) > 0) + internalFormat = GL_RGBA; + else + internalFormat = GL_RGB; + + texObj = _mesa_select_tex_object(ctx, texUnit, target); + _mesa_lock_texture(ctx, texObj); + + stObj = st_texture_object(texObj); + /* switch to surface based */ + if (!stObj->surface_based) { + _mesa_clear_texture_object(ctx, texObj); + stObj->surface_based = GL_TRUE; + } + + texImage = _mesa_get_tex_image(ctx, texObj, target, level); + stImage = st_texture_image(texImage); + + _mesa_init_teximage_fields(ctx, target, texImage, + ps->width, ps->height, 1, 0, internalFormat); + texImage->TexFormat = st_ChooseTextureFormat(ctx, internalFormat, + GL_RGBA, GL_UNSIGNED_BYTE); + _mesa_set_fetch_functions(texImage, 2); + pipe_texture_reference(&stImage->pt, ps->texture); + + _mesa_dirty_texobj(ctx, texObj, GL_TRUE); + _mesa_unlock_texture(ctx, texObj); + + return 1; +} + + +/** + * Unbind a pipe surface from a texture object. After the call, + * the texture object is marked dirty and will be (re-)validated. + * + * \param ps pipe surface to be unbound + * \param target texture target + * \param level image level + */ +int +st_unbind_texture_surface(struct pipe_surface *ps, int target, int level) +{ + GET_CURRENT_CONTEXT(ctx); + const GLuint unit = ctx->Texture.CurrentUnit; + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + struct st_texture_object *stObj; + struct st_texture_image *stImage; switch (target) { case ST_TEXTURE_2D: @@ -385,21 +456,28 @@ st_set_teximage(struct pipe_texture *pt, int target) } texObj = _mesa_select_tex_object(ctx, texUnit, target); - texImage = _mesa_get_tex_image(ctx, texObj, target, 0); + + _mesa_lock_texture(ctx, texObj); + + texImage = _mesa_get_tex_image(ctx, texObj, target, level); + stObj = st_texture_object(texObj); stImage = st_texture_image(texImage); - - _mesa_init_teximage_fields(ctx, GL_TEXTURE_2D, texImage, pt->width[0], - pt->height[0], 1, 0, internalFormat); - texImage->TexFormat = st_ChooseTextureFormat(ctx, internalFormat, GL_RGBA, - GL_UNSIGNED_BYTE); - _mesa_set_fetch_functions(texImage, 2); + /* Make sure the pipe surface is still bound. The texture object is still + * considered surface based even if this is the last bound surface. */ + if (stImage->pt == ps->texture) { + pipe_texture_reference(&stImage->pt, NULL); + _mesa_clear_texture_image(ctx, texImage); - pipe_texture_reference(&stImage->pt, pt); + _mesa_dirty_texobj(ctx, texObj, GL_TRUE); + } + _mesa_unlock_texture(ctx, texObj); + return 1; } + /** Redirect rendering into stfb's surface to a texture image */ int st_bind_teximage(struct st_framebuffer *stfb, uint surfIndex, diff --git a/src/mesa/state_tracker/st_texture.h b/src/mesa/state_tracker/st_texture.h index b9d447cb56..60868ce067 100644 --- a/src/mesa/state_tracker/st_texture.h +++ b/src/mesa/state_tracker/st_texture.h @@ -69,6 +69,11 @@ struct st_texture_object struct pipe_texture *pt; GLboolean teximage_realloc; + + /* True if there is/was a surface bound to this texture object. It helps + * track whether the texture object is surface based or not. + */ + GLboolean surface_based; }; diff --git a/src/mesa/swrast/s_blit.c b/src/mesa/swrast/s_blit.c index 0e32cb8f65..8303e4debc 100644 --- a/src/mesa/swrast/s_blit.c +++ b/src/mesa/swrast/s_blit.c @@ -24,6 +24,7 @@ #include "main/glheader.h" +#include "main/image.h" #include "main/macros.h" #include "s_context.h" @@ -104,7 +105,7 @@ static void blit_nearest(GLcontext *ctx, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, - GLenum buffer) + GLbitfield buffer) { struct gl_renderbuffer *readRb, *drawRb; @@ -456,7 +457,7 @@ static void simple_blit(GLcontext *ctx, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, - GLenum buffer) + GLbitfield buffer) { struct gl_renderbuffer *readRb, *drawRb; const GLint width = srcX1 - srcX0; @@ -551,184 +552,6 @@ simple_blit(GLcontext *ctx, /** - * Clip dst coords against Xmax (or Ymax). - */ -static INLINE void -clip_right_or_top(GLint *srcX0, GLint *srcX1, - GLint *dstX0, GLint *dstX1, - GLint maxValue) -{ - GLfloat t, bias; - - if (*dstX1 > maxValue) { - /* X1 outside right edge */ - ASSERT(*dstX0 < maxValue); /* X0 should be inside right edge */ - t = (GLfloat) (maxValue - *dstX0) / (GLfloat) (*dstX1 - *dstX0); - /* chop off [t, 1] part */ - ASSERT(t >= 0.0 && t <= 1.0); - *dstX1 = maxValue; - bias = (*srcX0 < *srcX1) ? 0.5 : -0.5; - *srcX1 = *srcX0 + (GLint) (t * (*srcX1 - *srcX0) + bias); - } - else if (*dstX0 > maxValue) { - /* X0 outside right edge */ - ASSERT(*dstX1 < maxValue); /* X1 should be inside right edge */ - t = (GLfloat) (maxValue - *dstX1) / (GLfloat) (*dstX0 - *dstX1); - /* chop off [t, 1] part */ - ASSERT(t >= 0.0 && t <= 1.0); - *dstX0 = maxValue; - bias = (*srcX0 < *srcX1) ? -0.5 : 0.5; - *srcX0 = *srcX1 + (GLint) (t * (*srcX0 - *srcX1) + bias); - } -} - - -/** - * Clip dst coords against Xmin (or Ymin). - */ -static INLINE void -clip_left_or_bottom(GLint *srcX0, GLint *srcX1, - GLint *dstX0, GLint *dstX1, - GLint minValue) -{ - GLfloat t, bias; - - if (*dstX0 < minValue) { - /* X0 outside left edge */ - ASSERT(*dstX1 > minValue); /* X1 should be inside left edge */ - t = (GLfloat) (minValue - *dstX0) / (GLfloat) (*dstX1 - *dstX0); - /* chop off [0, t] part */ - ASSERT(t >= 0.0 && t <= 1.0); - *dstX0 = minValue; - bias = (*srcX0 < *srcX1) ? 0.5 : -0.5; /* flipped??? */ - *srcX0 = *srcX0 + (GLint) (t * (*srcX1 - *srcX0) + bias); - } - else if (*dstX1 < minValue) { - /* X1 outside left edge */ - ASSERT(*dstX0 > minValue); /* X0 should be inside left edge */ - t = (GLfloat) (minValue - *dstX1) / (GLfloat) (*dstX0 - *dstX1); - /* chop off [0, t] part */ - ASSERT(t >= 0.0 && t <= 1.0); - *dstX1 = minValue; - bias = (*srcX0 < *srcX1) ? 0.5 : -0.5; - *srcX1 = *srcX1 + (GLint) (t * (*srcX0 - *srcX1) + bias); - } -} - - -/** - * Do clipping of blit src/dest rectangles. - * The dest rect is clipped against both the buffer bounds and scissor bounds. - * The src rect is just clipped against the buffer bounds. - * - * When either the src or dest rect is clipped, the other is also clipped - * proportionately! - * - * Note that X0 need not be less than X1 (same for Y) for either the source - * and dest rects. That makes the clipping a little trickier. - * - * \return GL_TRUE if anything is left to draw, GL_FALSE if totally clipped - */ -static GLboolean -clip_blit(GLcontext *ctx, - GLint *srcX0, GLint *srcY0, GLint *srcX1, GLint *srcY1, - GLint *dstX0, GLint *dstY0, GLint *dstX1, GLint *dstY1) -{ - const GLint srcXmin = 0; - const GLint srcXmax = ctx->ReadBuffer->Width; - const GLint srcYmin = 0; - const GLint srcYmax = ctx->ReadBuffer->Height; - - /* these include scissor bounds */ - const GLint dstXmin = ctx->DrawBuffer->_Xmin; - const GLint dstXmax = ctx->DrawBuffer->_Xmax; - const GLint dstYmin = ctx->DrawBuffer->_Ymin; - const GLint dstYmax = ctx->DrawBuffer->_Ymax; - - /* - printf("PreClipX: src: %d .. %d dst: %d .. %d\n", - *srcX0, *srcX1, *dstX0, *dstX1); - printf("PreClipY: src: %d .. %d dst: %d .. %d\n", - *srcY0, *srcY1, *dstY0, *dstY1); - */ - - /* trivial rejection tests */ - if (*dstX0 == *dstX1) - return GL_FALSE; /* no width */ - if (*dstX0 <= dstXmin && *dstX1 <= dstXmin) - return GL_FALSE; /* totally out (left) of bounds */ - if (*dstX0 >= dstXmax && *dstX1 >= dstXmax) - return GL_FALSE; /* totally out (right) of bounds */ - - if (*dstY0 == *dstY1) - return GL_FALSE; - if (*dstY0 <= dstYmin && *dstY1 <= dstYmin) - return GL_FALSE; - if (*dstY0 >= dstYmax && *dstY1 >= dstYmax) - return GL_FALSE; - - if (*srcX0 == *srcX1) - return GL_FALSE; - if (*srcX0 <= srcXmin && *srcX1 <= srcXmin) - return GL_FALSE; - if (*srcX0 >= srcXmax && *srcX1 >= srcXmax) - return GL_FALSE; - - if (*srcY0 == *srcY1) - return GL_FALSE; - if (*srcY0 <= srcYmin && *srcY1 <= srcYmin) - return GL_FALSE; - if (*srcY0 >= srcYmax && *srcY1 >= srcYmax) - return GL_FALSE; - - /* - * dest clip - */ - clip_right_or_top(srcX0, srcX1, dstX0, dstX1, dstXmax); - clip_right_or_top(srcY0, srcY1, dstY0, dstY1, dstYmax); - clip_left_or_bottom(srcX0, srcX1, dstX0, dstX1, dstXmin); - clip_left_or_bottom(srcY0, srcY1, dstY0, dstY1, dstYmin); - - /* - * src clip (just swap src/dst values from above) - */ - clip_right_or_top(dstX0, dstX1, srcX0, srcX1, srcXmax); - clip_right_or_top(dstY0, dstY1, srcY0, srcY1, srcYmax); - clip_left_or_bottom(dstX0, dstX1, srcX0, srcX1, srcXmin); - clip_left_or_bottom(dstY0, dstY1, srcY0, srcY1, srcYmin); - - /* - printf("PostClipX: src: %d .. %d dst: %d .. %d\n", - *srcX0, *srcX1, *dstX0, *dstX1); - printf("PostClipY: src: %d .. %d dst: %d .. %d\n", - *srcY0, *srcY1, *dstY0, *dstY1); - */ - - ASSERT(*dstX0 >= dstXmin); - ASSERT(*dstX0 <= dstXmax); - ASSERT(*dstX1 >= dstXmin); - ASSERT(*dstX1 <= dstXmax); - - ASSERT(*dstY0 >= dstYmin); - ASSERT(*dstY0 <= dstYmax); - ASSERT(*dstY1 >= dstYmin); - ASSERT(*dstY1 <= dstYmax); - - ASSERT(*srcX0 >= srcXmin); - ASSERT(*srcX0 <= srcXmax); - ASSERT(*srcX1 >= srcXmin); - ASSERT(*srcX1 <= srcXmax); - - ASSERT(*srcY0 >= srcYmin); - ASSERT(*srcY0 <= srcYmax); - ASSERT(*srcY1 >= srcYmin); - ASSERT(*srcY1 <= srcYmax); - - return GL_TRUE; -} - - -/** * Software fallback for glBlitFramebufferEXT(). */ void @@ -737,7 +560,7 @@ _swrast_BlitFramebuffer(GLcontext *ctx, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) { - static const GLint buffers[3] = { + static const GLbitfield buffers[3] = { GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT @@ -747,8 +570,8 @@ _swrast_BlitFramebuffer(GLcontext *ctx, if (!ctx->DrawBuffer->_NumColorDrawBuffers) return; - if (!clip_blit(ctx, &srcX0, &srcY0, &srcX1, &srcY1, - &dstX0, &dstY0, &dstX1, &dstY1)) { + if (!_mesa_clip_blit(ctx, &srcX0, &srcY0, &srcX1, &srcY1, + &dstX0, &dstY0, &dstX1, &dstY1)) { return; } diff --git a/src/mesa/swrast/s_fragprog.c b/src/mesa/swrast/s_fragprog.c index b71fb9eae9..613a91b0ec 100644 --- a/src/mesa/swrast/s_fragprog.c +++ b/src/mesa/swrast/s_fragprog.c @@ -157,9 +157,8 @@ init_machine(GLcontext *ctx, struct gl_program_machine *machine, /* if running a GLSL program (not ARB_fragment_program) */ if (ctx->Shader.CurrentProgram) { - /* Store front/back facing value in register FOGC.Y */ - machine->Attribs[FRAG_ATTRIB_FOGC][col][1] = 1.0 - span->facing; - /* Note FOGC.ZW is gl_PointCoord if drawing a sprite */ + /* Store front/back facing value */ + machine->Attribs[FRAG_ATTRIB_FACE][col][0] = 1.0 - span->facing; } machine->CurElement = col; diff --git a/src/mesa/swrast/s_points.c b/src/mesa/swrast/s_points.c index 0a3ad97a71..50ec2063a5 100644 --- a/src/mesa/swrast/s_points.c +++ b/src/mesa/swrast/s_points.c @@ -139,9 +139,10 @@ sprite_point(GLcontext *ctx, const SWvertex *vert) } ATTRIB_LOOP_BEGIN - if (attr >= FRAG_ATTRIB_TEX0 && attr < FRAG_ATTRIB_VAR0) { + if (attr >= FRAG_ATTRIB_TEX0 && attr <= FRAG_ATTRIB_TEX7) { + /* a texcoord attribute */ const GLuint u = attr - FRAG_ATTRIB_TEX0; - /* a texcoord */ + ASSERT(u < Elements(ctx->Point.CoordReplace)); if (ctx->Point.CoordReplace[u]) { tCoords[numTcoords++] = attr; @@ -170,15 +171,15 @@ sprite_point(GLcontext *ctx, const SWvertex *vert) continue; } } - else if (attr == FRAG_ATTRIB_FOGC) { - /* GLSL gl_PointCoord is stored in fog.zw */ - span.attrStart[FRAG_ATTRIB_FOGC][2] = 0.0; - span.attrStart[FRAG_ATTRIB_FOGC][3] = 0.0; /* t0 set below */ - span.attrStepX[FRAG_ATTRIB_FOGC][2] = dsdx; - span.attrStepX[FRAG_ATTRIB_FOGC][3] = 0.0; - span.attrStepY[FRAG_ATTRIB_FOGC][2] = 0.0; - span.attrStepY[FRAG_ATTRIB_FOGC][3] = dtdy; - tCoords[numTcoords++] = FRAG_ATTRIB_FOGC; + else if (attr == FRAG_ATTRIB_PNTC) { + /* GLSL gl_PointCoord.xy (.zw undefined) */ + span.attrStart[FRAG_ATTRIB_PNTC][0] = 0.0; + span.attrStart[FRAG_ATTRIB_PNTC][1] = 0.0; /* t0 set below */ + span.attrStepX[FRAG_ATTRIB_PNTC][0] = dsdx; + span.attrStepX[FRAG_ATTRIB_PNTC][1] = 0.0; + span.attrStepY[FRAG_ATTRIB_PNTC][0] = 0.0; + span.attrStepY[FRAG_ATTRIB_PNTC][1] = dtdy; + tCoords[numTcoords++] = FRAG_ATTRIB_PNTC; continue; } /* use vertex's texcoord/attrib */ @@ -221,10 +222,7 @@ sprite_point(GLcontext *ctx, const SWvertex *vert) GLuint i; /* setup texcoord T for this row */ for (i = 0; i < numTcoords; i++) { - if (tCoords[i] == FRAG_ATTRIB_FOGC) - span.attrStart[FRAG_ATTRIB_FOGC][3] = tcoord; - else - span.attrStart[tCoords[i]][1] = tcoord; + span.attrStart[tCoords[i]][1] = tcoord; } /* these might get changed by span clipping */ diff --git a/src/mesa/tnl/t_context.c b/src/mesa/tnl/t_context.c index f69b122046..f2771cde09 100644 --- a/src/mesa/tnl/t_context.c +++ b/src/mesa/tnl/t_context.c @@ -81,7 +81,7 @@ _tnl_CreateContext( GLcontext *ctx ) tnl->nr_blocks = 0; /* plug in the VBO drawing function */ - vbo_set_draw_func(ctx, _tnl_draw_prims); + vbo_set_draw_func(ctx, _tnl_vbo_draw_prims); _math_init_transformation(); _math_init_translate(); diff --git a/src/mesa/tnl/t_draw.c b/src/mesa/tnl/t_draw.c index 2ec65d5323..c64c2c2077 100644 --- a/src/mesa/tnl/t_draw.c +++ b/src/mesa/tnl/t_draw.c @@ -360,6 +360,20 @@ static void unmap_vbos( GLcontext *ctx, } +void _tnl_vbo_draw_prims(GLcontext *ctx, + const struct gl_client_array *arrays[], + const struct _mesa_prim *prim, + GLuint nr_prims, + const struct _mesa_index_buffer *ib, + GLboolean index_bounds_valid, + GLuint min_index, + GLuint max_index) +{ + if (!index_bounds_valid) + vbo_get_minmax_index(ctx, prim, ib, &min_index, &max_index); + + _tnl_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index); +} /* This is the main entrypoint into the slimmed-down software tnl * module. In a regular swtnl driver, this can be plugged straight @@ -393,7 +407,7 @@ void _tnl_draw_prims( GLcontext *ctx, */ vbo_rebase_prims( ctx, arrays, prim, nr_prims, ib, min_index, max_index, - _tnl_draw_prims ); + _tnl_vbo_draw_prims ); return; } else if (max_index > max) { @@ -411,7 +425,7 @@ void _tnl_draw_prims( GLcontext *ctx, */ vbo_split_prims( ctx, arrays, prim, nr_prims, ib, 0, max_index, - _tnl_draw_prims, + _tnl_vbo_draw_prims, &limits ); } else { diff --git a/src/mesa/tnl/t_vb_program.c b/src/mesa/tnl/t_vb_program.c index 66c5e13729..dc954bcba1 100644 --- a/src/mesa/tnl/t_vb_program.c +++ b/src/mesa/tnl/t_vb_program.c @@ -386,6 +386,9 @@ run_vp( GLcontext *ctx, struct tnl_pipeline_stage *stage ) #endif COPY_4V(store->results[attr].data[i], machine.Outputs[attr]); } +#ifdef NAN_CHECK + ASSERT(machine.Outputs[0][3] != 0.0F); +#endif #if 0 printf("HPOS: %f %f %f %f\n", machine.Outputs[0][0], diff --git a/src/mesa/tnl/tnl.h b/src/mesa/tnl/tnl.h index 4d628aa9a6..9c66d3b019 100644 --- a/src/mesa/tnl/tnl.h +++ b/src/mesa/tnl/tnl.h @@ -81,6 +81,16 @@ _tnl_draw_prims( GLcontext *ctx, GLuint min_index, GLuint max_index); +void +_tnl_vbo_draw_prims( GLcontext *ctx, + const struct gl_client_array *arrays[], + const struct _mesa_prim *prim, + GLuint nr_prims, + const struct _mesa_index_buffer *ib, + GLboolean index_bounds_valid, + GLuint min_index, + GLuint max_index); + extern void _mesa_load_tracked_matrices(GLcontext *ctx); diff --git a/src/mesa/vbo/vbo.h b/src/mesa/vbo/vbo.h index 5362226c2f..5986e93576 100644 --- a/src/mesa/vbo/vbo.h +++ b/src/mesa/vbo/vbo.h @@ -69,6 +69,7 @@ typedef void (*vbo_draw_func)( GLcontext *ctx, const struct _mesa_prim *prims, GLuint nr_prims, const struct _mesa_index_buffer *ib, + GLboolean index_bounds_valid, GLuint min_index, GLuint max_index ); @@ -112,7 +113,10 @@ void vbo_rebase_prims( GLcontext *ctx, GLuint min_index, GLuint max_index, vbo_draw_func draw ); - +void +vbo_get_minmax_index(GLcontext *ctx, const struct _mesa_prim *prim, + const struct _mesa_index_buffer *ib, + GLuint *min_index, GLuint *max_index); void vbo_use_buffer_objects(GLcontext *ctx); diff --git a/src/mesa/vbo/vbo_exec_api.c b/src/mesa/vbo/vbo_exec_api.c index b746a77bc1..387d4ee3d4 100644 --- a/src/mesa/vbo/vbo_exec_api.c +++ b/src/mesa/vbo/vbo_exec_api.c @@ -486,23 +486,6 @@ static void GLAPIENTRY vbo_exec_EvalPoint2( GLint i, GLint j ) } -/** - * Check if programs/shaders are enabled and valid at glBegin time. - */ -GLboolean -vbo_validate_shaders(GLcontext *ctx) -{ - if ((ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) || - (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled)) { - return GL_FALSE; - } - if (ctx->Shader.CurrentProgram && !ctx->Shader.CurrentProgram->LinkStatus) { - return GL_FALSE; - } - return GL_TRUE; -} - - /* Build a list of primitives on the fly. Keep * ctx->Driver.CurrentExecPrimitive uptodate as well. */ @@ -521,9 +504,7 @@ static void GLAPIENTRY vbo_exec_Begin( GLenum mode ) return; } - if (!vbo_validate_shaders(ctx)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBegin (invalid vertex/fragment program)"); + if (!_mesa_valid_to_render(ctx, "glBegin")) { return; } diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c index f4b9b2f744..4148469ef4 100644 --- a/src/mesa/vbo/vbo_exec_array.c +++ b/src/mesa/vbo/vbo_exec_array.c @@ -41,13 +41,27 @@ /** * Compute min and max elements for glDraw[Range]Elements() calls. */ -static void -get_minmax_index(GLuint count, GLuint type, const GLvoid *indices, - GLuint *min_index, GLuint *max_index) +void +vbo_get_minmax_index(GLcontext *ctx, + const struct _mesa_prim *prim, + const struct _mesa_index_buffer *ib, + GLuint *min_index, GLuint *max_index) { GLuint i; + GLsizei count = prim->count; + const void *indices; + + if (_mesa_is_bufferobj(ib->obj)) { + const GLvoid *map = ctx->Driver.MapBuffer(ctx, + GL_ELEMENT_ARRAY_BUFFER_ARB, + GL_READ_ONLY, + ib->obj); + indices = ADD_POINTERS(map, ib->ptr); + } else { + indices = ib->ptr; + } - switch(type) { + switch (ib->type) { case GL_UNSIGNED_INT: { const GLuint *ui_indices = (const GLuint *)indices; GLuint max_ui = ui_indices[count-1]; @@ -88,6 +102,12 @@ get_minmax_index(GLuint count, GLuint type, const GLvoid *indices, assert(0); break; } + + if (_mesa_is_bufferobj(ib->obj)) { + ctx->Driver.UnmapBuffer(ctx, + GL_ELEMENT_ARRAY_BUFFER_ARB, + ib->obj); + } } @@ -101,7 +121,7 @@ check_array_data(GLcontext *ctx, struct gl_client_array *array, { if (array->Enabled) { const void *data = array->Ptr; - if (array->BufferObj->Name) { + if (_mesa_is_bufferobj(array->BufferObj)) { if (!array->BufferObj->Pointer) { /* need to map now */ array->BufferObj->Pointer = ctx->Driver.MapBuffer(ctx, @@ -146,8 +166,8 @@ static void unmap_array_buffer(GLcontext *ctx, struct gl_client_array *array) { if (array->Enabled && - array->BufferObj->Name && - array->BufferObj->Pointer) { + _mesa_is_bufferobj(array->BufferObj) && + _mesa_bufferobj_mapped(array->BufferObj)) { ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER_ARB, array->BufferObj); @@ -166,7 +186,7 @@ check_draw_elements_data(GLcontext *ctx, GLsizei count, GLenum elemType, const void *elemMap; GLint i, k; - if (ctx->Array.ElementArrayBufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj)) { elemMap = ctx->Driver.MapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER_ARB, GL_READ_ONLY, @@ -205,7 +225,7 @@ check_draw_elements_data(GLcontext *ctx, GLsizei count, GLenum elemType, } } - if (ctx->Array.ElementArrayBufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj)) { ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER_ARB, ctx->Array.ElementArrayBufferObj); @@ -469,8 +489,7 @@ vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count) if (ctx->NewState) _mesa_update_state( ctx ); - if (!vbo_validate_shaders(ctx)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawArrays(bad shader)"); + if (!_mesa_valid_to_render(ctx, "glDrawArrays")) { return; } @@ -500,7 +519,7 @@ vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count) prim[0].indexed = 0; vbo->draw_prims( ctx, exec->array.inputs, prim, 1, NULL, - start, start + count - 1 ); + GL_TRUE, start, start + count - 1 ); #if 0 print_draw_arrays(ctx, exec, mode, start, count); @@ -566,70 +585,35 @@ dump_element_buffer(GLcontext *ctx, GLenum type) ctx->Array.ElementArrayBufferObj); } - -static void GLAPIENTRY -vbo_exec_DrawRangeElements(GLenum mode, - GLuint start, GLuint end, - GLsizei count, GLenum type, const GLvoid *indices) +/* Inner support for both _mesa_DrawElements and _mesa_DrawRangeElements */ +static void +vbo_validated_drawrangeelements(GLcontext *ctx, GLenum mode, + GLboolean index_bounds_valid, + GLuint start, GLuint end, + GLsizei count, GLenum type, + const GLvoid *indices) { - GET_CURRENT_CONTEXT(ctx); struct vbo_context *vbo = vbo_context(ctx); struct vbo_exec_context *exec = &vbo->exec; struct _mesa_index_buffer ib; struct _mesa_prim prim[1]; - if (!_mesa_validate_DrawRangeElements( ctx, mode, start, end, count, - type, indices )) - return; - - if (end >= ctx->Array.ArrayObj->_MaxElement) { - /* the max element is out of bounds of one or more enabled arrays */ - _mesa_warning(ctx, "glDraw[Range]Elements(start %u, end %u, count %d, " - "type 0x%x, indices=%p)\n" - "\tindex=%u is out of bounds (max=%u) " - "Element Buffer %u (size %d)", - start, end, count, type, indices, end, - ctx->Array.ArrayObj->_MaxElement - 1, - ctx->Array.ElementArrayBufferObj->Name, - ctx->Array.ElementArrayBufferObj->Size); - - if (0) - dump_element_buffer(ctx, type); - - if (0) - _mesa_print_arrays(ctx); - return; - } - else if (0) { - _mesa_printf("glDraw[Range]Elements" - "(start %u, end %u, type 0x%x, count %d) ElemBuf %u\n", - start, end, type, count, - ctx->Array.ElementArrayBufferObj->Name); - } - -#if 0 - check_draw_elements_data(ctx, count, type, indices); -#else - (void) check_draw_elements_data; -#endif - FLUSH_CURRENT( ctx, 0 ); if (ctx->NewState) _mesa_update_state( ctx ); - if (!vbo_validate_shaders(ctx)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawRangeElements(bad shader)"); + if (!_mesa_valid_to_render(ctx, "glDraw[Range]Elements")) { return; } - bind_arrays( ctx ); - if (ctx->NewState) _mesa_update_state( ctx ); + bind_arrays( ctx ); + ib.count = count; - ib.type = type; + ib.type = type; ib.obj = ctx->Array.ElementArrayBufferObj; ib.ptr = indices; @@ -673,44 +657,68 @@ vbo_exec_DrawRangeElements(GLenum mode, * for the latter case elsewhere. */ - vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib, start, end ); + vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib, + index_bounds_valid, start, end ); } - static void GLAPIENTRY -vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type, - const GLvoid *indices) +vbo_exec_DrawRangeElements(GLenum mode, + GLuint start, GLuint end, + GLsizei count, GLenum type, const GLvoid *indices) { GET_CURRENT_CONTEXT(ctx); - GLuint min_index = 0; - GLuint max_index = 0; - if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices )) + if (!_mesa_validate_DrawRangeElements( ctx, mode, start, end, count, + type, indices )) return; - if (!vbo_validate_shaders(ctx)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawElements(bad shader)"); + if (end >= ctx->Array.ArrayObj->_MaxElement) { + /* the max element is out of bounds of one or more enabled arrays */ + _mesa_warning(ctx, "glDraw[Range]Elements(start %u, end %u, count %d, " + "type 0x%x, indices=%p)\n" + "\tindex=%u is out of bounds (max=%u) " + "Element Buffer %u (size %d)", + start, end, count, type, indices, end, + ctx->Array.ArrayObj->_MaxElement - 1, + ctx->Array.ElementArrayBufferObj->Name, + ctx->Array.ElementArrayBufferObj->Size); + + if (0) + dump_element_buffer(ctx, type); + + if (0) + _mesa_print_arrays(ctx); return; } + else if (0) { + _mesa_printf("glDraw[Range]Elements" + "(start %u, end %u, type 0x%x, count %d) ElemBuf %u\n", + start, end, type, count, + ctx->Array.ElementArrayBufferObj->Name); + } - if (ctx->Array.ElementArrayBufferObj->Name) { - const GLvoid *map = ctx->Driver.MapBuffer(ctx, - GL_ELEMENT_ARRAY_BUFFER_ARB, - GL_READ_ONLY, - ctx->Array.ElementArrayBufferObj); +#if 0 + check_draw_elements_data(ctx, count, type, indices); +#else + (void) check_draw_elements_data; +#endif - get_minmax_index(count, type, ADD_POINTERS(map, indices), - &min_index, &max_index); + vbo_validated_drawrangeelements(ctx, mode, GL_TRUE, start, end, + count, type, indices); +} - ctx->Driver.UnmapBuffer(ctx, - GL_ELEMENT_ARRAY_BUFFER_ARB, - ctx->Array.ElementArrayBufferObj); - } - else { - get_minmax_index(count, type, indices, &min_index, &max_index); - } - vbo_exec_DrawRangeElements(mode, min_index, max_index, count, type, indices); +static void GLAPIENTRY +vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices) +{ + GET_CURRENT_CONTEXT(ctx); + + if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices )) + return; + + vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0, + count, type, indices); } diff --git a/src/mesa/vbo/vbo_exec_draw.c b/src/mesa/vbo/vbo_exec_draw.c index 18419928b2..d76c45f356 100644 --- a/src/mesa/vbo/vbo_exec_draw.c +++ b/src/mesa/vbo/vbo_exec_draw.c @@ -214,7 +214,7 @@ vbo_exec_bind_arrays( GLcontext *ctx ) /* override the default array set above */ exec->vtx.inputs[attr] = &arrays[attr]; - if (exec->vtx.bufferobj->Name) { + if (_mesa_is_bufferobj(exec->vtx.bufferobj)) { /* a real buffer obj: Ptr is an offset, not a pointer*/ GLsizeiptr offset; assert(exec->vtx.bufferobj->Pointer); /* buf should be mapped */ @@ -251,7 +251,7 @@ vbo_exec_vtx_unmap( struct vbo_exec_context *exec ) { GLenum target = GL_ARRAY_BUFFER_ARB; - if (exec->vtx.bufferobj->Name) { + if (_mesa_is_bufferobj(exec->vtx.bufferobj)) { GLcontext *ctx = exec->ctx; if (ctx->Driver.FlushMappedBufferRange) { @@ -291,7 +291,7 @@ vbo_exec_vtx_map( struct vbo_exec_context *exec ) MESA_MAP_NOWAIT_BIT; const GLenum usage = GL_STREAM_DRAW_ARB; - if (exec->vtx.bufferobj->Name == 0) + if (!_mesa_is_bufferobj(exec->vtx.bufferobj)) return; if (exec->vtx.buffer_map != NULL) { @@ -365,7 +365,7 @@ vbo_exec_vtx_flush( struct vbo_exec_context *exec, GLboolean unmap ) if (ctx->NewState) _mesa_update_state( ctx ); - if (exec->vtx.bufferobj->Name) { + if (_mesa_is_bufferobj(exec->vtx.bufferobj)) { vbo_exec_vtx_unmap( exec ); } @@ -378,12 +378,13 @@ vbo_exec_vtx_flush( struct vbo_exec_context *exec, GLboolean unmap ) exec->vtx.prim, exec->vtx.prim_count, NULL, + GL_TRUE, 0, exec->vtx.vert_count - 1); /* If using a real VBO, get new storage -- unless asked not to. */ - if (exec->vtx.bufferobj->Name && !unmap) { + if (_mesa_is_bufferobj(exec->vtx.bufferobj) && !unmap) { vbo_exec_vtx_map( exec ); } } @@ -392,7 +393,7 @@ vbo_exec_vtx_flush( struct vbo_exec_context *exec, GLboolean unmap ) /* May have to unmap explicitly if we didn't draw: */ if (unmap && - exec->vtx.bufferobj->Name && + _mesa_is_bufferobj(exec->vtx.bufferobj) && exec->vtx.buffer_map) { vbo_exec_vtx_unmap( exec ); } diff --git a/src/mesa/vbo/vbo_rebase.c b/src/mesa/vbo/vbo_rebase.c index ea87dede64..3bf7ef580f 100644 --- a/src/mesa/vbo/vbo_rebase.c +++ b/src/mesa/vbo/vbo_rebase.c @@ -208,6 +208,7 @@ void vbo_rebase_prims( GLcontext *ctx, prim, nr_prims, ib, + GL_TRUE, 0, max_index - min_index ); diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c index d00d304d2e..cdbbc9c187 100644 --- a/src/mesa/vbo/vbo_save_api.c +++ b/src/mesa/vbo/vbo_save_api.c @@ -911,7 +911,7 @@ static void GLAPIENTRY _save_OBE_DrawElements(GLenum mode, GLsizei count, GLenum _ae_map_vbos( ctx ); - if (ctx->Array.ElementArrayBufferObj->Name) + if (_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj)) indices = ADD_POINTERS(ctx->Array.ElementArrayBufferObj->Pointer, indices); vbo_save_NotifyBegin( ctx, mode | VBO_SAVE_PRIM_WEAK ); diff --git a/src/mesa/vbo/vbo_save_draw.c b/src/mesa/vbo/vbo_save_draw.c index 5110648c28..d834fa1f2e 100644 --- a/src/mesa/vbo/vbo_save_draw.c +++ b/src/mesa/vbo/vbo_save_draw.c @@ -279,6 +279,7 @@ void vbo_save_playback_vertex_list( GLcontext *ctx, void *data ) node->prim, node->prim_count, NULL, + GL_TRUE, 0, /* Node is a VBO, so this is ok */ node->count - 1); } diff --git a/src/mesa/vbo/vbo_split_copy.c b/src/mesa/vbo/vbo_split_copy.c index d7ffebf607..8ec180d550 100644 --- a/src/mesa/vbo/vbo_split_copy.c +++ b/src/mesa/vbo/vbo_split_copy.c @@ -30,6 +30,7 @@ */ #include "main/glheader.h" +#include "main/bufferobj.h" #include "main/imports.h" #include "main/image.h" #include "main/macros.h" @@ -194,6 +195,7 @@ flush( struct copy_context *copy ) copy->dstprim, copy->dstprim_nr, ©->dstib, + GL_TRUE, 0, copy->dstbuf_nr ); @@ -443,7 +445,7 @@ replay_init( struct copy_context *copy ) copy->varying[j].size = attr_size(copy->array[i]); copy->vertex_size += attr_size(copy->array[i]); - if (vbo->Name && !vbo->Pointer) + if (_mesa_is_bufferobj(vbo) && !_mesa_bufferobj_mapped(vbo)) ctx->Driver.MapBuffer(ctx, GL_ARRAY_BUFFER, GL_READ_ONLY, vbo); copy->varying[j].src_ptr = ADD_POINTERS(vbo->Pointer, @@ -457,7 +459,8 @@ replay_init( struct copy_context *copy ) * caller convert non-indexed prims to indexed. Could alternately * do it internally. */ - if (copy->ib->obj->Name && !copy->ib->obj->Pointer) + if (_mesa_is_bufferobj(copy->ib->obj) && + !_mesa_bufferobj_mapped(copy->ib->obj)) ctx->Driver.MapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER, GL_READ_ONLY, copy->ib->obj); @@ -561,13 +564,14 @@ replay_finish( struct copy_context *copy ) */ for (i = 0; i < copy->nr_varying; i++) { struct gl_buffer_object *vbo = copy->varying[i].array->BufferObj; - if (vbo->Name && vbo->Pointer) + if (_mesa_is_bufferobj(vbo) && _mesa_bufferobj_mapped(vbo)) ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER, vbo); } /* Unmap index buffer: */ - if (copy->ib->obj->Name && copy->ib->obj->Pointer) { + if (_mesa_is_bufferobj(copy->ib->obj) && + _mesa_bufferobj_mapped(copy->ib->obj)) { ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER, copy->ib->obj); } } diff --git a/src/mesa/vbo/vbo_split_inplace.c b/src/mesa/vbo/vbo_split_inplace.c index 9628227e7c..da84eaa6ea 100644 --- a/src/mesa/vbo/vbo_split_inplace.c +++ b/src/mesa/vbo/vbo_split_inplace.c @@ -85,6 +85,7 @@ static void flush_vertex( struct split_context *split ) split->dstprim, split->dstprim_nr, NULL, + GL_TRUE, min_index, max_index); |