diff options
318 files changed, 13578 insertions, 6780 deletions
@@ -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/docs/relnotes-7.5.1.html b/docs/relnotes-7.5.1.html index 0f475ad2b4..2a7661f601 100644 --- a/docs/relnotes-7.5.1.html +++ b/docs/relnotes-7.5.1.html @@ -43,6 +43,11 @@ tbd <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 1e7ccf88bf..560d50d0d6 100644 --- a/docs/relnotes-7.6.html +++ b/docs/relnotes-7.6.html @@ -46,6 +46,8 @@ This was written by Zack Rusin at Tungsten Graphics. <li>radeon/r200/r300 GL_EXT_framebuffer_object support when used with kernel memory manager <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 </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/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/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/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/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/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/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/SConscript b/progs/tests/SConscript index b17fa90593..bb6a1d2b8a 100644 --- a/progs/tests/SConscript +++ b/progs/tests/SConscript @@ -72,6 +72,7 @@ progs = [ 'fogcoord', 'fptest1', 'fptexture', + 'getteximage', 'glutfx', 'interleave', 'invert', 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 e4818a8fab..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); - - glBindFramebuffer(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); - glBindFramebuffer(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/util/shaderutil.c b/progs/util/shaderutil.c index 13b68d90e0..233252112a 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,24 +130,26 @@ 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: @@ -169,3 +157,99 @@ InitUniforms(GLuint program, struct uniform_info uniforms[]) } } } + + +/** 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/vp/arl-static.txt b/progs/vp/arl-static.txt index aea87b79a4..83aebf689e 100644 --- a/progs/vp/arl-static.txt +++ b/progs/vp/arl-static.txt @@ -1,5 +1,5 @@ !!ARBvp1.0 -PARAM arr[5] = { {.0,.1,.2,.3}, {.4,.5,.6,.7}, {.8,.9,.10,.1}, {.12,.3,.4,.14}, {.5,.8,.1,.9}, {.2,0,.4,.1}, {.6,.1,.8,.9}}; +PARAM arr[7] = { {.0,.1,.2,.3}, {.4,.5,.6,.7}, {.8,.9,.10,.1}, {.12,.3,.4,.14}, {.5,.8,.1,.9}, {.2,0,.4,.1}, {.6,.1,.8,.9}}; ADDRESS addr; ARL addr.x, {3}.x; MOV result.color, arr[addr.x]; diff --git a/progs/vp/arl-unused.txt b/progs/vp/arl-unused.txt index 7bdbb8e86c..c2afe3c092 100644 --- a/progs/vp/arl-unused.txt +++ b/progs/vp/arl-unused.txt @@ -1,5 +1,5 @@ !!ARBvp1.0 -PARAM arr[5] = { {.0,.1,.2,.3}, {.4,.5,.6,.7}, {.8,.9,.10,.1}, {.12,.3,.4,.14}, {.5,.8,.1,.9}, {.2,0,.4,.1}, {.6,.1,.8,.9}}; +PARAM arr[7] = { {.0,.1,.2,.3}, {.4,.5,.6,.7}, {.8,.9,.10,.1}, {.12,.3,.4,.14}, {.5,.8,.1,.9}, {.2,0,.4,.1}, {.6,.1,.8,.9}}; ADDRESS addr; ARL addr.x, {3}.x; # not actually used MOV result.color, arr[3]; 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/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/eglcompiler.h b/src/egl/main/eglcompiler.h index 0b19afedfd..6b639b75c6 100644 --- a/src/egl/main/eglcompiler.h +++ b/src/egl/main/eglcompiler.h @@ -3,6 +3,39 @@ /** + * Get standard integer types + */ +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) +# include <stdint.h> +#elif defined(_MSC_VER) + typedef __int8 int8_t; + typedef unsigned __int8 uint8_t; + typedef __int16 int16_t; + typedef unsigned __int16 uint16_t; +# ifndef __eglplatform_h_ + typedef __int32 int32_t; +# endif + typedef unsigned __int32 uint32_t; + typedef __int64 int64_t; + typedef unsigned __int64 uint64_t; + +# if defined(_WIN64) + typedef __int64 intptr_t; + typedef unsigned __int64 uintptr_t; +# else + typedef __int32 intptr_t; + typedef unsigned __int32 uintptr_t; +# endif + +# define INT64_C(__val) __val##i64 +# define UINT64_C(__val) __val##ui64 +#else +/* hope the best instead of adding a bunch of ifdef's */ +# include <stdint.h> +#endif + + +/** * Function inlining */ #if defined(__GNUC__) diff --git a/src/egl/main/eglconfig.c b/src/egl/main/eglconfig.c index f2f32585c7..bbc585b55e 100644 --- a/src/egl/main/eglconfig.c +++ b/src/egl/main/eglconfig.c @@ -34,7 +34,7 @@ void _eglInitConfig(_EGLConfig *config, EGLint id) { memset(config, 0, sizeof(*config)); - config->Handle = (EGLConfig) id; + config->Handle = (EGLConfig) _eglUIntToPointer((unsigned int) id); _eglSetConfigAttrib(config, EGL_CONFIG_ID, id); _eglSetConfigAttrib(config, EGL_BIND_TO_TEXTURE_RGB, EGL_DONT_CARE); _eglSetConfigAttrib(config, EGL_BIND_TO_TEXTURE_RGBA, EGL_DONT_CARE); 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 89de609d0b..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,11 +112,14 @@ 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); - dpy->Handle = (EGLDisplay) key; + _eglHashInsert(_eglDisplayHash, key, dpy); + dpy->Handle = (EGLDisplay) _eglUIntToPointer(key); return dpy->Handle; } @@ -66,7 +132,11 @@ _eglLinkDisplay(_EGLDisplay *dpy) void _eglUnlinkDisplay(_EGLDisplay *dpy) { - _eglHashRemove(_eglGlobal.Displays, (EGLuint) dpy->Handle); + EGLuint key = _eglPointerToUInt((void *) dpy->Handle); + + _eglInitDisplay(); + + _eglHashRemove(_eglDisplayHash, key); dpy->Handle = EGL_NO_DISPLAY; } @@ -83,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. @@ -91,8 +161,11 @@ _eglGetDisplayHandle(_EGLDisplay *display) _EGLDisplay * _eglLookupDisplay(EGLDisplay dpy) { - EGLuint key = (EGLuint) dpy; - return (_EGLDisplay *) _eglHashLookup(_eglGlobal.Displays, key); + EGLuint key = _eglPointerToUInt((void *) dpy); + + _eglInitDisplay(); + + return (_EGLDisplay *) _eglHashLookup(_eglDisplayHash, key); } @@ -103,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; @@ -224,7 +300,7 @@ _eglUnlinkContext(_EGLContext *ctx) EGLContext _eglGetContextHandle(_EGLContext *ctx) { - return (EGLContext) (ctx && ctx->Display) ? ctx : EGL_NO_CONTEXT; + return (EGLContext) ((ctx && ctx->Display) ? ctx : EGL_NO_CONTEXT); } @@ -253,11 +329,11 @@ _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) key; + surf->Handle = (EGLSurface) _eglUIntToPointer(key); return surf->Handle; } @@ -270,8 +346,9 @@ void _eglUnlinkSurface(_EGLSurface *surf) { _EGLSurface *prev; + EGLuint key = _eglPointerToUInt((void *) surf->Handle); - _eglHashRemove(_eglGlobal.Surfaces, (EGLuint) surf->Handle); + _eglHashRemove(surf->Display->SurfaceHash, key); surf->Handle = EGL_NO_SURFACE; prev = surf->Display->SurfaceList; @@ -314,7 +391,6 @@ _eglGetSurfaceHandle(_EGLSurface *surface) _EGLSurface * _eglLookupSurface(EGLSurface surf) { - _EGLSurface *c = (_EGLSurface *) _eglHashLookup(_eglGlobal.Surfaces, - (EGLuint) surf); - return c; + EGLuint key = _eglPointerToUInt((void *) surf); + return (_EGLSurface *) _eglHashLookup(_eglSurfaceHash, key); } diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h index 372ed3cd79..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 @@ -125,4 +130,25 @@ _eglIsSurfaceLinked(_EGLSurface *surf) } +/** + * Cast an unsigned int to a pointer. + */ +static INLINE void * +_eglUIntToPointer(unsigned int v) +{ + return (void *) ((uintptr_t) v); +} + + +/** + * Cast a pointer to an unsigned int. The pointer must be one that is + * returned by _eglUIntToPointer. + */ +static INLINE unsigned int +_eglPointerToUInt(const void *p) +{ + return (unsigned int) ((uintptr_t) p); +} + + #endif /* EGLDISPLAY_INCLUDED */ 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/gallivm/tgsitollvm.cpp b/src/gallium/auxiliary/gallivm/tgsitollvm.cpp index 8d885e48be..bf84401e11 100644 --- a/src/gallium/auxiliary/gallivm/tgsitollvm.cpp +++ b/src/gallium/auxiliary/gallivm/tgsitollvm.cpp @@ -516,7 +516,7 @@ translate_instruction(llvm::Module *module, return; //just update the state } break; - case TGSI_OPCODE_LOOP: + case TGSI_OPCODE_BGNFOR: break; case TGSI_OPCODE_REP: break; @@ -532,7 +532,7 @@ translate_instruction(llvm::Module *module, return; //just update the state } break; - case TGSI_OPCODE_ENDLOOP: + case TGSI_OPCODE_ENDFOR: break; case TGSI_OPCODE_ENDREP: break; @@ -574,7 +574,7 @@ translate_instruction(llvm::Module *module, break; case TGSI_OPCODE_ENDPRIM: break; - case TGSI_OPCODE_BGNLOOP2: { + case TGSI_OPCODE_BGNLOOP: { instr->beginLoop(); storage->setCurrentBlock(instr->currentBlock()); return; @@ -587,7 +587,7 @@ translate_instruction(llvm::Module *module, return; } break; - case TGSI_OPCODE_ENDLOOP2: { + case TGSI_OPCODE_ENDLOOP: { instr->endLoop(); storage->setCurrentBlock(instr->currentBlock()); return; @@ -890,7 +890,7 @@ translate_instructionir(llvm::Module *module, case TGSI_OPCODE_IF: { } break; - case TGSI_OPCODE_LOOP: + case TGSI_OPCODE_BGNFOR: break; case TGSI_OPCODE_REP: break; @@ -900,7 +900,7 @@ translate_instructionir(llvm::Module *module, case TGSI_OPCODE_ENDIF: { } break; - case TGSI_OPCODE_ENDLOOP: + case TGSI_OPCODE_ENDFOR: break; case TGSI_OPCODE_ENDREP: break; @@ -941,13 +941,13 @@ translate_instructionir(llvm::Module *module, break; case TGSI_OPCODE_ENDPRIM: break; - case TGSI_OPCODE_BGNLOOP2: { + case TGSI_OPCODE_BGNLOOP: { } break; case TGSI_OPCODE_BGNSUB: { } break; - case TGSI_OPCODE_ENDLOOP2: { + case TGSI_OPCODE_ENDLOOP: { } break; case TGSI_OPCODE_ENDSUB: { diff --git a/src/gallium/auxiliary/tgsi/tgsi-instruction-set.txt b/src/gallium/auxiliary/tgsi/tgsi-instruction-set.txt index a3f4947c73..802ec37118 100644 --- a/src/gallium/auxiliary/tgsi/tgsi-instruction-set.txt +++ b/src/gallium/auxiliary/tgsi/tgsi-instruction-set.txt @@ -665,9 +665,18 @@ TGSI Instruction Specification TBD -1.9.8 LOOP - Loop +1.9.8 BGNFOR - Begin a For-Loop - TBD + dst.x = floor(src.x) + dst.y = floor(src.y) + dst.z = floor(src.z) + + if (dst.y <= 0) + pc = [matching ENDFOR] + 1 + endif + + Note: The destination must be a loop register. + The source must be a constant register. 1.9.9 REP - Repeat @@ -685,9 +694,16 @@ TGSI Instruction Specification TBD -1.9.12 ENDLOOP - End Loop +1.9.12 ENDFOR - End a For-Loop - TBD + dst.x = dst.x + dst.z + dst.y = dst.y - 1.0 + + if (dst.y > 0) + pc = [matching BGNFOR instruction] + 1 + endif + + Note: The destination must be a loop register. 1.9.13 ENDREP - End Repeat @@ -840,7 +856,7 @@ TGSI Instruction Specification ---------- -1.13.1 BGNLOOP2 - Begin Loop +1.13.1 BGNLOOP - Begin a Loop TBD @@ -850,7 +866,7 @@ TGSI Instruction Specification TBD -1.13.3 ENDLOOP2 - End Loop +1.13.3 ENDLOOP - End a Loop TBD diff --git a/src/gallium/auxiliary/tgsi/tgsi_dump.c b/src/gallium/auxiliary/tgsi/tgsi_dump.c index e1cd8479cb..f36b1114a9 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_dump.c +++ b/src/gallium/auxiliary/tgsi/tgsi_dump.c @@ -82,7 +82,7 @@ static const char *processor_type_names[] = "GEOM" }; -static const char *file_names[] = +static const char *file_names[TGSI_FILE_COUNT] = { "NULL", "CONST", @@ -91,7 +91,8 @@ static const char *file_names[] = "TEMP", "SAMP", "ADDR", - "IMM" + "IMM", + "LOOP" }; static const char *interpolate_names[] = @@ -472,8 +473,8 @@ iter_instruction( switch (inst->Instruction.Opcode) { case TGSI_OPCODE_IF: case TGSI_OPCODE_ELSE: - case TGSI_OPCODE_BGNLOOP2: - case TGSI_OPCODE_ENDLOOP2: + case TGSI_OPCODE_BGNLOOP: + case TGSI_OPCODE_ENDLOOP: case TGSI_OPCODE_CAL: TXT( " :" ); UID( inst->InstructionExtLabel.Label ); diff --git a/src/gallium/auxiliary/tgsi/tgsi_dump_c.c b/src/gallium/auxiliary/tgsi/tgsi_dump_c.c index c944760ca6..4a9c02b141 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_dump_c.c +++ b/src/gallium/auxiliary/tgsi/tgsi_dump_c.c @@ -69,7 +69,7 @@ static const char *TGSI_TOKEN_TYPES[] = "TOKEN_TYPE_INSTRUCTION" }; -static const char *TGSI_FILES[] = +static const char *TGSI_FILES[TGSI_FILE_COUNT] = { "FILE_NULL", "FILE_CONSTANT", @@ -78,7 +78,8 @@ static const char *TGSI_FILES[] = "FILE_TEMPORARY", "FILE_SAMPLER", "FILE_ADDRESS", - "FILE_IMMEDIATE" + "FILE_IMMEDIATE", + "FILE_LOOP" }; static const char *TGSI_INTERPOLATES[] = diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.c b/src/gallium/auxiliary/tgsi/tgsi_exec.c index 0179bba5a2..5af0a94794 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_exec.c +++ b/src/gallium/auxiliary/tgsi/tgsi_exec.c @@ -3087,9 +3087,9 @@ exec_instruction( mach->Primitives[mach->Temps[TEMP_PRIMITIVE_I].xyzw[TEMP_PRIMITIVE_C].u[0]] = 0; break; - case TGSI_OPCODE_LOOP: + case TGSI_OPCODE_BGNFOR: /* fall-through (for now) */ - case TGSI_OPCODE_BGNLOOP2: + case TGSI_OPCODE_BGNLOOP: /* push LoopMask and ContMasks */ assert(mach->LoopStackTop < TGSI_EXEC_MAX_LOOP_NESTING); mach->LoopStack[mach->LoopStackTop++] = mach->LoopMask; @@ -3097,9 +3097,9 @@ exec_instruction( mach->ContStack[mach->ContStackTop++] = mach->ContMask; break; - case TGSI_OPCODE_ENDLOOP: + case TGSI_OPCODE_ENDFOR: /* fall-through (for now at least) */ - case TGSI_OPCODE_ENDLOOP2: + case TGSI_OPCODE_ENDLOOP: /* Restore ContMask, but don't pop */ assert(mach->ContStackTop > 0); mach->ContMask = mach->ContStack[mach->ContStackTop - 1]; diff --git a/src/gallium/auxiliary/tgsi/tgsi_info.c b/src/gallium/auxiliary/tgsi/tgsi_info.c index fedda7bff9..ccf4b205ff 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_info.c +++ b/src/gallium/auxiliary/tgsi/tgsi_info.c @@ -106,11 +106,11 @@ static const struct tgsi_opcode_info opcode_info[TGSI_OPCODE_LAST] = { 1, 2, 1, 0, "TXL", TGSI_OPCODE_TXL }, { 0, 0, 0, 0, "BRK", TGSI_OPCODE_BRK }, { 0, 1, 0, 1, "IF", TGSI_OPCODE_IF }, - { 0, 0, 0, 0, "LOOP", TGSI_OPCODE_LOOP }, + { 1, 1, 0, 0, "BGNFOR", TGSI_OPCODE_BGNFOR }, { 0, 1, 0, 0, "REP", TGSI_OPCODE_REP }, { 0, 0, 0, 1, "ELSE", TGSI_OPCODE_ELSE }, { 0, 0, 0, 0, "ENDIF", TGSI_OPCODE_ENDIF }, - { 0, 0, 0, 0, "ENDLOOP", TGSI_OPCODE_ENDLOOP }, + { 1, 0, 0, 0, "ENDFOR", TGSI_OPCODE_ENDFOR }, { 0, 0, 0, 0, "ENDREP", TGSI_OPCODE_ENDREP }, { 0, 1, 0, 0, "PUSHA", TGSI_OPCODE_PUSHA }, { 1, 0, 0, 0, "POPA", TGSI_OPCODE_POPA }, @@ -130,9 +130,9 @@ static const struct tgsi_opcode_info opcode_info[TGSI_OPCODE_LAST] = { 0, 0, 0, 0, "CONT", TGSI_OPCODE_CONT }, { 0, 0, 0, 0, "EMIT", TGSI_OPCODE_EMIT }, { 0, 0, 0, 0, "ENDPRIM", TGSI_OPCODE_ENDPRIM }, - { 0, 0, 0, 1, "BGNLOOP2", TGSI_OPCODE_BGNLOOP2 }, + { 0, 0, 0, 1, "BGNLOOP", TGSI_OPCODE_BGNLOOP }, { 0, 0, 0, 0, "BGNSUB", TGSI_OPCODE_BGNSUB }, - { 0, 0, 0, 1, "ENDLOOP2", TGSI_OPCODE_ENDLOOP2 }, + { 0, 0, 0, 1, "ENDLOOP", TGSI_OPCODE_ENDLOOP }, { 0, 0, 0, 0, "ENDSUB", TGSI_OPCODE_ENDSUB }, { 1, 1, 0, 0, "NOISE1", TGSI_OPCODE_NOISE1 }, { 1, 1, 0, 0, "NOISE2", TGSI_OPCODE_NOISE2 }, @@ -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_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_sanity.c b/src/gallium/auxiliary/tgsi/tgsi_sanity.c index 6f1f5c2b4b..4fe8553c42 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_sanity.c +++ b/src/gallium/auxiliary/tgsi/tgsi_sanity.c @@ -131,7 +131,7 @@ is_register_used( return (ctx->regs_used[file][index / BITS_IN_REG_FLAG] & (1 << (index % BITS_IN_REG_FLAG))) ? TRUE : FALSE; } -static const char *file_names[] = +static const char *file_names[TGSI_FILE_COUNT] = { "NULL", "CONST", @@ -140,7 +140,8 @@ static const char *file_names[] = "TEMP", "SAMP", "ADDR", - "IMM" + "IMM", + "LOOP" }; static boolean @@ -234,9 +235,29 @@ iter_instruction( index, "indirect", FALSE ); - if (file != TGSI_FILE_ADDRESS || index != 0) - report_warning( ctx, "Indirect register not ADDR[0]" ); + if (!(file == TGSI_FILE_ADDRESS || file == TGSI_FILE_LOOP) || index != 0) { + report_warning(ctx, "Indirect register neither ADDR[0] nor LOOP[0]"); + } + } + } + + switch (inst->Instruction.Opcode) { + case TGSI_OPCODE_BGNFOR: + case TGSI_OPCODE_ENDFOR: + if (inst->FullDstRegisters[0].DstRegister.File != TGSI_FILE_LOOP || + inst->FullDstRegisters[0].DstRegister.Index != 0) { + report_error(ctx, "Destination register must be LOOP[0]"); + } + break; + } + + switch (inst->Instruction.Opcode) { + case TGSI_OPCODE_BGNFOR: + if (inst->FullSrcRegisters[0].SrcRegister.File != TGSI_FILE_CONSTANT && + inst->FullSrcRegisters[0].SrcRegister.File != TGSI_FILE_IMMEDIATE) { + report_error(ctx, "Source register file must be either CONST or IMM"); } + break; } ctx->num_instructions++; diff --git a/src/gallium/auxiliary/tgsi/tgsi_sse2.c b/src/gallium/auxiliary/tgsi/tgsi_sse2.c index 781ea1e75c..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" @@ -1467,15 +1468,15 @@ emit_tex( struct x86_function *func, switch (inst->InstructionExtTexture.Texture) { case TGSI_TEXTURE_1D: - case TGSI_TEXTURE_SHADOW1D: count = 1; break; case TGSI_TEXTURE_2D: case TGSI_TEXTURE_RECT: - case TGSI_TEXTURE_SHADOW2D: - case TGSI_TEXTURE_SHADOWRECT: count = 2; break; + case TGSI_TEXTURE_SHADOW1D: + case TGSI_TEXTURE_SHADOW2D: + case TGSI_TEXTURE_SHADOWRECT: case TGSI_TEXTURE_3D: case TGSI_TEXTURE_CUBE: count = 3; @@ -2531,7 +2532,7 @@ emit_instruction( return 0; break; - case TGSI_OPCODE_LOOP: + case TGSI_OPCODE_BGNFOR: return 0; break; @@ -2547,7 +2548,7 @@ emit_instruction( return 0; break; - case TGSI_OPCODE_ENDLOOP: + case TGSI_OPCODE_ENDFOR: return 0; break; @@ -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_text.c b/src/gallium/auxiliary/tgsi/tgsi_text.c index bfcbc40982..d438450b1e 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_text.c +++ b/src/gallium/auxiliary/tgsi/tgsi_text.c @@ -231,7 +231,8 @@ static const char *file_names[TGSI_FILE_COUNT] = "TEMP", "SAMP", "ADDR", - "IMM" + "IMM", + "LOOP" }; static boolean 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_debug.c b/src/gallium/auxiliary/util/u_debug.c index a5ca0b72bd..96d400c839 100644 --- a/src/gallium/auxiliary/util/u_debug.c +++ b/src/gallium/auxiliary/util/u_debug.c @@ -143,11 +143,9 @@ void _debug_vprintf(const char *format, va_list ap) #elif defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT) /* TODO */ #else /* !PIPE_SUBSYSTEM_WINDOWS */ -#ifdef DEBUG fflush(stdout); vfprintf(stderr, format, ap); #endif -#endif } diff --git a/src/gallium/auxiliary/util/u_math.h b/src/gallium/auxiliary/util/u_math.h index e5003af01d..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); @@ -216,23 +219,24 @@ util_fast_exp2(float x) int32_t ipart; float fpart, mpart; union fi epart; - + if(x > 129.00000f) return 3.402823466e+38f; - - if(x < -126.99999f) + + if (x < -126.99999f) return 0.0f; ipart = (int32_t) x; fpart = x - (float) ipart; - + /* 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)]; - + return epart.f * mpart; } @@ -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) { @@ -409,7 +421,23 @@ float_to_ubyte(float f) } +/** + * Calc log base 2 + */ +static INLINE unsigned +util_logbase2(unsigned n) +{ + unsigned log2 = 0; + while (n >>= 1) + ++log2; + return log2; +} + +/** + * 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) ) @@ -422,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_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_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_gen_fp.c b/src/gallium/drivers/cell/ppu/cell_gen_fp.c index 7cd5656a7e..58a8b5d0b0 100644 --- a/src/gallium/drivers/cell/ppu/cell_gen_fp.c +++ b/src/gallium/drivers/cell/ppu/cell_gen_fp.c @@ -1834,9 +1834,9 @@ emit_instruction(struct codegen *gen, case TGSI_OPCODE_ENDIF: return emit_ENDIF(gen, inst); - case TGSI_OPCODE_BGNLOOP2: + case TGSI_OPCODE_BGNLOOP: return emit_BGNLOOP(gen, inst); - case TGSI_OPCODE_ENDLOOP2: + case TGSI_OPCODE_ENDLOOP: return emit_ENDLOOP(gen, inst); case TGSI_OPCODE_BRK: return emit_BRK(gen, inst); 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/cell/spu/spu_exec.c b/src/gallium/drivers/cell/spu/spu_exec.c index 570553e1d6..6db9501128 100644 --- a/src/gallium/drivers/cell/spu/spu_exec.c +++ b/src/gallium/drivers/cell/spu/spu_exec.c @@ -1758,9 +1758,9 @@ exec_instruction( mach->Primitives[mach->Temps[TEMP_PRIMITIVE_I].xyzw[TEMP_PRIMITIVE_C].u[0]] = 0; break; - case TGSI_OPCODE_LOOP: + case TGSI_OPCODE_BGNFOR: /* fall-through (for now) */ - case TGSI_OPCODE_BGNLOOP2: + case TGSI_OPCODE_BGNLOOP: /* push LoopMask and ContMasks */ ASSERT(mach->LoopStackTop < TGSI_EXEC_MAX_LOOP_NESTING); mach->LoopStack[mach->LoopStackTop++] = mach->LoopMask; @@ -1768,9 +1768,9 @@ exec_instruction( mach->ContStack[mach->ContStackTop++] = mach->ContMask; break; - case TGSI_OPCODE_ENDLOOP: + case TGSI_OPCODE_ENDFOR: /* fall-through (for now at least) */ - case TGSI_OPCODE_ENDLOOP2: + case TGSI_OPCODE_ENDLOOP: /* Restore ContMask, but don't pop */ ASSERT(mach->ContStackTop > 0); mach->ContMask = mach->ContStack[mach->ContStackTop - 1]; 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/i965simple/brw_wm_glsl.c b/src/gallium/drivers/i965simple/brw_wm_glsl.c index ab6410aa60..db75963932 100644 --- a/src/gallium/drivers/i965simple/brw_wm_glsl.c +++ b/src/gallium/drivers/i965simple/brw_wm_glsl.c @@ -947,7 +947,7 @@ static void brw_wm_emit_instruction( struct brw_wm_compile *c, #endif break; - case TGSI_OPCODE_LOOP: + case TGSI_OPCODE_BGNFOR: c->loop_inst[c->loop_insn++] = brw_DO(p, BRW_EXECUTE_8); break; case TGSI_OPCODE_BRK: @@ -958,11 +958,11 @@ static void brw_wm_emit_instruction( struct brw_wm_compile *c, brw_CONT(p); brw_set_predicate_control(p, BRW_PREDICATE_NONE); break; - case TGSI_OPCODE_ENDLOOP: + case TGSI_OPCODE_ENDFOR: c->loop_insn--; c->inst0 = c->inst1 = brw_WHILE(p, c->loop_inst[c->loop_insn]); /* patch all the BREAK instructions from - last BEGINLOOP */ + last BGNFOR */ while (c->inst0 > c->loop_inst[c->loop_insn]) { c->inst0--; if (c->inst0->header.opcode == BRW_OPCODE_BREAK) { 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/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 7a533dad9f..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; } @@ -224,12 +222,6 @@ softpipe_get_tex_surface(struct pipe_screen *screen, if (ps->usage & PIPE_BUFFER_USAGE_GPU_READ) ps->usage |= PIPE_BUFFER_USAGE_CPU_READ; - if (ps->usage & (PIPE_BUFFER_USAGE_CPU_WRITE | - PIPE_BUFFER_USAGE_GPU_WRITE)) { - /* Mark the surface as dirty. The tile cache will look for this. */ - spt->modified = TRUE; - } - ps->face = face; ps->level = level; ps->zslice = zslice; @@ -376,6 +368,11 @@ softpipe_transfer_unmap(struct pipe_screen *screen, spt = softpipe_texture(transfer->texture); pipe_buffer_unmap( screen, spt->buffer ); + + if (transfer->usage != PIPE_TRANSFER_READ) { + /* Mark the texture as dirty to expire the tile caches. */ + spt->modified = TRUE; + } } 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/include/pipe/p_shader_tokens.h b/src/gallium/include/pipe/p_shader_tokens.h index e6e29a04ec..f0ba4fb308 100644 --- a/src/gallium/include/pipe/p_shader_tokens.h +++ b/src/gallium/include/pipe/p_shader_tokens.h @@ -78,6 +78,7 @@ enum tgsi_file_type { TGSI_FILE_SAMPLER =5, TGSI_FILE_ADDRESS =6, TGSI_FILE_IMMEDIATE =7, + TGSI_FILE_LOOP =8, TGSI_FILE_COUNT /**< how many TGSI_FILE_ types */ }; @@ -237,11 +238,11 @@ union tgsi_immediate_data #define TGSI_OPCODE_TXL 72 #define TGSI_OPCODE_BRK 73 #define TGSI_OPCODE_IF 74 -#define TGSI_OPCODE_LOOP 75 +#define TGSI_OPCODE_BGNFOR 75 #define TGSI_OPCODE_REP 76 #define TGSI_OPCODE_ELSE 77 #define TGSI_OPCODE_ENDIF 78 -#define TGSI_OPCODE_ENDLOOP 79 +#define TGSI_OPCODE_ENDFOR 79 #define TGSI_OPCODE_ENDREP 80 #define TGSI_OPCODE_PUSHA 81 #define TGSI_OPCODE_POPA 82 @@ -261,9 +262,9 @@ union tgsi_immediate_data #define TGSI_OPCODE_CONT 96 #define TGSI_OPCODE_EMIT 97 #define TGSI_OPCODE_ENDPRIM 98 -#define TGSI_OPCODE_BGNLOOP2 99 +#define TGSI_OPCODE_BGNLOOP 99 #define TGSI_OPCODE_BGNSUB 100 -#define TGSI_OPCODE_ENDLOOP2 101 +#define TGSI_OPCODE_ENDLOOP 101 #define TGSI_OPCODE_ENDSUB 102 #define TGSI_OPCODE_NOISE1 103 #define TGSI_OPCODE_NOISE2 104 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..ffaceda7e0 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,68 @@ "GLX_SGIX_fbconfig " \ "GLX_SGIX_pbuffer " -/* +#define DEFAULT_DIRECT GL_TRUE + + + +/** + * Minimal __GLXContextRec that mimics a "real" GLX context. + */ +typedef struct __GLXcontextRec +{ + Display *currentDpy; + GLboolean isDirect; + GLXDrawable currentDrawable; + GLXDrawable currentReadable; + XID xid; +} __GLXcontext; + + +/** * 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. + * XXX merge this struct with the one above. */ -struct fake_glx_context { +struct fake_glx_context +{ __GLXcontext glxContext; /* this MUST be first! */ 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 +401,6 @@ find_glx_visual( Display *dpy, XVisualInfo *vinfo ) } - - - - /** * Try to get an X visual which matches the given arguments. */ @@ -418,7 +449,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 +1032,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,9 +1054,9 @@ 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; @@ -1081,9 +1111,9 @@ 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; static boolean firsttime = 1, no_rast = 0; @@ -1093,7 +1123,6 @@ Fake_glXMakeContextCurrent( Display *dpy, GLXDrawable draw, firsttime = 0; } - if (ctx && draw && read) { XMesaBuffer drawBuffer, readBuffer; XMesaContext xmctx = glxCtx->xmesaContext; @@ -1151,6 +1180,7 @@ Fake_glXMakeContextCurrent( Display *dpy, GLXDrawable draw, ((__GLXcontext *) ctx)->currentDpy = dpy; ((__GLXcontext *) ctx)->currentDrawable = draw; ((__GLXcontext *) ctx)->currentReadable = read; + SetCurrentContext(ctx); return True; } else { @@ -1165,6 +1195,7 @@ Fake_glXMakeContextCurrent( Display *dpy, GLXDrawable draw, MakeCurrent_PrevReadable = 0; MakeCurrent_PrevDrawBuffer = 0; MakeCurrent_PrevReadBuffer = 0; + SetCurrentContext(NULL); return True; } else { @@ -1176,15 +1207,62 @@ 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 glXMakeContextCurrent( dpy, drawable, drawable, ctx ); +} + + +GLXContext +glXGetCurrentContext(void) { - return Fake_glXMakeContextCurrent( dpy, drawable, drawable, ctx ); + return GetCurrentContext(); } -static GLXPixmap -Fake_glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo, Pixmap pixmap ) +Display * +glXGetCurrentDisplay(void) +{ + struct fake_glx_context *glxCtx = + (struct fake_glx_context *) glXGetCurrentContext(); + + return glxCtx ? glxCtx->glxContext.currentDpy : NULL; +} + + +Display * +glXGetCurrentDisplayEXT(void) +{ + return glXGetCurrentDisplay(); +} + + +GLXDrawable +glXGetCurrentDrawable(void) +{ + __GLXcontext *gc = (__GLXcontext *) glXGetCurrentContext(); + return gc ? gc->currentDrawable : 0; +} + + +GLXDrawable +glXGetCurrentReadDrawable(void) +{ + __GLXcontext *gc = (__GLXcontext *) 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 +1286,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 +1310,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,9 +1323,9 @@ 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; @@ -1261,8 +1339,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,16 +1350,8 @@ 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; (void) dpy; @@ -1296,8 +1366,8 @@ 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; (void) ctx; @@ -1306,8 +1376,8 @@ Fake_glXIsDirect( Display *dpy, GLXContext ctx ) -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 +1403,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 +1417,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 +1634,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 +1664,8 @@ Fake_glXGetConfig( Display *dpy, XVisualInfo *visinfo, } -static void -Fake_glXWaitGL( void ) +void +glXWaitGL( void ) { XMesaContext xmesa = XMesaGetCurrentContext(); XMesaFlush( xmesa ); @@ -1603,8 +1673,8 @@ Fake_glXWaitGL( void ) -static void -Fake_glXWaitX( void ) +void +glXWaitX( void ) { XMesaContext xmesa = XMesaGetCurrentContext(); XMesaFlush( xmesa ); @@ -1620,8 +1690,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 +1701,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 +1726,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 +1754,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 +1769,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 +1795,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 +1824,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 +1846,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 +1866,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 +1877,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 +1987,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 +1997,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 +2050,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 +2060,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,8 +2102,8 @@ 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; @@ -2068,8 +2138,8 @@ Fake_glXCreateNewContext( Display *dpy, GLXFBConfig config, } -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; XMesaContext xmctx = glxCtx->xmesaContext; @@ -2097,8 +2167,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 +2176,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 +2191,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 +2204,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 +2229,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 +2247,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 +2259,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 +2271,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 +2307,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,8 +2329,8 @@ 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; @@ -2290,15 +2360,15 @@ Fake_glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, int re } -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 +2383,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 +2422,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 +2432,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 +2465,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 +2476,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 +2492,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 +2504,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 +2514,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 +2527,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 +2540,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 +2553,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 +2568,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 +2582,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 +2594,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 +2615,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 +2633,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 +2646,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 +2655,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/asm_filters.h b/src/gallium/state_trackers/vega/asm_filters.h index 49807b9ab4..9a49f2e12d 100644 --- a/src/gallium/state_trackers/vega/asm_filters.h +++ b/src/gallium/state_trackers/vega/asm_filters.h @@ -60,7 +60,7 @@ static const char convolution_asm[] = "DCL SAMP[0], CONSTANT\n" "0: MOV TEMP[0], CONST[0].xxxx\n" "1: MOV TEMP[1], CONST[0].xxxx\n" - "2: BGNLOOP2 :14\n" + "2: BGNLOOP :14\n" "3: SGE TEMP[0].z, TEMP[0].yyyy, CONST[1].xxxx\n" "4: IF TEMP[0].zzzz :7\n" "5: BRK\n" @@ -72,7 +72,7 @@ static const char convolution_asm[] = "11: MOV TEMP[3], CONST[ADDR[0]+%d]\n" "12: MAD TEMP[1], TEMP[2], TEMP[3], TEMP[1]\n" "13: ADD TEMP[0].y, TEMP[0].yyyy, CONST[0].yyyy\n" - "14: ENDLOOP2 :2\n" + "14: ENDLOOP :2\n" "15: MAD OUT[0], TEMP[1], CONST[1].yyyy, CONST[1].zzzz\n" "16: END\n"; diff --git a/src/gallium/state_trackers/xorg/xorg_dri2.c b/src/gallium/state_trackers/xorg/xorg_dri2.c index ae3338ffef..301e5214e3 100644 --- a/src/gallium/state_trackers/xorg/xorg_dri2.c +++ b/src/gallium/state_trackers/xorg/xorg_dri2.c @@ -39,6 +39,8 @@ #include "pipe/p_state.h" #include "pipe/p_inlines.h" +#include "util/u_rect.h" + typedef struct { PixmapPtr pPixmap; struct pipe_texture *tex; @@ -83,7 +85,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,8 +93,9 @@ 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)); @@ -108,6 +110,9 @@ driCreateBuffers(DrawablePtr pDraw, unsigned int *attachments, int count) tex = ms->screen->texture_create(ms->screen, &template); } + 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,6 +143,7 @@ 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; @@ -172,8 +178,13 @@ driCopyRegion(DrawablePtr pDraw, RegionPtr pRegion, ms->screen->get_tex_surface(ms->screen, src_priv->tex, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ); +#if 1 ms->ctx->surface_copy(ms->ctx, dst_surf, 0, 0, src_surf, 0, 0, pDraw->width, pDraw->height); +#else + util_surface_copy(ms->ctx, false, dst_surf, 0, 0, src_surf, + 0, 0, pDraw->width, pDraw->height); +#endif pipe_surface_reference(&dst_surf, NULL); pipe_surface_reference(&src_surf, NULL); 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/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_glx.c b/src/glx/x11/dri2_glx.c index f4865aecb1..54add049ff 100644 --- a/src/glx/x11/dri2_glx.c +++ b/src/glx/x11/dri2_glx.c @@ -488,6 +488,8 @@ static __GLXDRIscreen *dri2CreateScreen(__GLXscreenConfigs *psc, int screen, 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; diff --git a/src/glx/x11/dri_glx.c b/src/glx/x11/dri_glx.c index ac2eb05341..d24471c436 100644 --- a/src/glx/x11/dri_glx.c +++ b/src/glx/x11/dri_glx.c @@ -418,6 +418,8 @@ CallCreateNewScreen(Display *dpy, int scrn, __GLXscreenConfigs *psc, 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. diff --git a/src/glx/x11/drisw_glx.c b/src/glx/x11/drisw_glx.c index 1c229dde90..15e1586658 100644 --- a/src/glx/x11/drisw_glx.c +++ b/src/glx/x11/drisw_glx.c @@ -401,7 +401,7 @@ driCreateScreen(__GLXscreenConfigs * psc, int screen, psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs); psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs); - free(driver_configs); + psc->driver_configs = driver_configs; psp->destroyScreen = driDestroyScreen; psp->createContext = driCreateContext; diff --git a/src/glx/x11/glxclient.h b/src/glx/x11/glxclient.h index aff1c85fba..09db8ea6a6 100644 --- a/src/glx/x11/glxclient.h +++ b/src/glx/x11/glxclient.h @@ -499,6 +499,8 @@ struct __GLXscreenConfigsRec { __GLXDRIscreen *driScreen; + const __DRIconfig** driver_configs; + #ifdef __DRI_COPY_SUB_BUFFER const __DRIcopySubBufferExtension *driCopySubBuffer; #endif diff --git a/src/glx/x11/glxcmds.c b/src/glx/x11/glxcmds.c index 820d8b9868..39f10296cc 100644 --- a/src/glx/x11/glxcmds.c +++ b/src/glx/x11/glxcmds.c @@ -1446,7 +1446,7 @@ void __glXClientInfo ( Display *dpy, int opcode ) GLX_MAJOR_VERSION, GLX_MINOR_VERSION, size, - (const uint8_t *)ext_str); + ext_str); #else xGLXClientInfoReq *req; diff --git a/src/glx/x11/glxext.c b/src/glx/x11/glxext.c index e07ed29790..c6ab4b5890 100644 --- a/src/glx/x11/glxext.c +++ b/src/glx/x11/glxext.c @@ -149,6 +149,12 @@ FreeScreenConfigs(__GLXdisplayPrivate * priv) Xfree((char *) psc->serverGLXexts); #ifdef GLX_DIRECT_RENDERING + if (psc->driver_configs) { + for(unsigned int i = 0; psc->driver_configs[i]; i++) + free((__DRIconfig*)psc->driver_configs[i]); + free(psc->driver_configs); + psc->driver_configs = NULL; + } if (psc->driScreen) { psc->driScreen->destroyScreen(psc); __glxHashDestroy(psc->drawHash); 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/mesa/drivers/common/meta.c b/src/mesa/drivers/common/meta.c new file mode 100644 index 0000000000..a8db686573 --- /dev/null +++ b/src/mesa/drivers/common/meta.c @@ -0,0 +1,1248 @@ +/* + * 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/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 367d2a3b64..bb08cf8d18 100644 --- a/src/mesa/drivers/dri/i915/i915_context.c +++ b/src/mesa/drivers/dri/i915/i915_context.c @@ -75,6 +75,10 @@ i915InvalidateState(GLcontext * ctx, GLuint new_state) if (new_state & (_NEW_FOG | _NEW_HINT | _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS)) 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 87bbf5f927..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 @@ -82,7 +83,9 @@ #define I915_CTXREG_IAB 6 #define I915_CTXREG_BLENDCOLOR0 7 #define I915_CTXREG_BLENDCOLOR1 8 -#define I915_CTX_SETUP_SIZE 9 +#define I915_CTXREG_BF_STENCIL_OPS 9 +#define I915_CTXREG_BF_STENCIL_MASKS 10 +#define I915_CTX_SETUP_SIZE 11 #define I915_FOGREG_COLOR 0 #define I915_FOGREG_MODE0 1 @@ -110,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)) @@ -206,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; @@ -321,6 +329,8 @@ extern void i915_print_ureg(const char *msg, GLuint ureg); 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 84db58ea95..b5fa7fddb9 100644 --- a/src/mesa/drivers/dri/i915/i915_reg.h +++ b/src/mesa/drivers/dri/i915/i915_reg.h @@ -86,8 +86,10 @@ #define BFM_ENABLE_STENCIL_WRITE_MASK (1<<16) #define BFM_STENCIL_TEST_MASK_SHIFT 8 #define BFM_STENCIL_TEST_MASK_MASK (0xff<<8) +#define BFM_STENCIL_TEST_MASK(x) (((x)&0xff) << 8) #define BFM_STENCIL_WRITE_MASK_SHIFT 0 #define BFM_STENCIL_WRITE_MASK_MASK (0xff<<0) +#define BFM_STENCIL_WRITE_MASK(x) ((x)&0xff) @@ -295,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 814fb59fd3..b60efea75b 100644 --- a/src/mesa/drivers/dri/i915/i915_state.c +++ b/src/mesa/drivers/dri/i915/i915_state.c @@ -48,73 +48,119 @@ #define FILE_DEBUG_FLAG DEBUG_STATE -static void -i915StencilFuncSeparate(GLcontext * ctx, GLenum face, GLenum func, GLint ref, - GLuint mask) +void +i915_update_stencil(GLcontext * ctx) { struct i915_context *i915 = I915_CONTEXT(ctx); - int test = intel_translate_compare_func(func); + GLuint front_ref, front_writemask, front_mask; + GLenum front_func, front_fail, front_pass_z_fail, front_pass_z_pass; + GLuint back_ref, back_writemask, back_mask; + GLenum back_func, back_fail, back_pass_z_fail, back_pass_z_pass; - mask = mask & 0xff; - - DBG("%s : func: %s, ref : 0x%x, mask: 0x%x\n", __FUNCTION__, - _mesa_lookup_enum_by_nr(func), ref, mask); + I915_STATECHANGE(i915, I915_UPLOAD_CTX); + /* The 915 considers CW to be "front" for two-sided stencil, so choose + * appropriately. + */ + /* _NEW_POLYGON | _NEW_STENCIL */ + if (ctx->Polygon.FrontFace == GL_CW) { + front_ref = ctx->Stencil.Ref[0]; + front_mask = ctx->Stencil.ValueMask[0]; + front_writemask = ctx->Stencil.WriteMask[0]; + front_func = ctx->Stencil.Function[0]; + front_fail = ctx->Stencil.FailFunc[0]; + front_pass_z_fail = ctx->Stencil.ZFailFunc[0]; + front_pass_z_pass = ctx->Stencil.ZPassFunc[0]; + back_ref = ctx->Stencil.Ref[ctx->Stencil._BackFace]; + back_mask = ctx->Stencil.ValueMask[ctx->Stencil._BackFace]; + back_writemask = ctx->Stencil.WriteMask[ctx->Stencil._BackFace]; + back_func = ctx->Stencil.Function[ctx->Stencil._BackFace]; + back_fail = ctx->Stencil.FailFunc[ctx->Stencil._BackFace]; + back_pass_z_fail = ctx->Stencil.ZFailFunc[ctx->Stencil._BackFace]; + back_pass_z_pass = ctx->Stencil.ZPassFunc[ctx->Stencil._BackFace]; + } else { + front_ref = ctx->Stencil.Ref[ctx->Stencil._BackFace]; + front_mask = ctx->Stencil.ValueMask[ctx->Stencil._BackFace]; + front_writemask = ctx->Stencil.WriteMask[ctx->Stencil._BackFace]; + front_func = ctx->Stencil.Function[ctx->Stencil._BackFace]; + front_fail = ctx->Stencil.FailFunc[ctx->Stencil._BackFace]; + front_pass_z_fail = ctx->Stencil.ZFailFunc[ctx->Stencil._BackFace]; + front_pass_z_pass = ctx->Stencil.ZPassFunc[ctx->Stencil._BackFace]; + back_ref = ctx->Stencil.Ref[0]; + back_mask = ctx->Stencil.ValueMask[0]; + back_writemask = ctx->Stencil.WriteMask[0]; + back_func = ctx->Stencil.Function[0]; + back_fail = ctx->Stencil.FailFunc[0]; + back_pass_z_fail = ctx->Stencil.ZFailFunc[0]; + back_pass_z_pass = ctx->Stencil.ZPassFunc[0]; + } - I915_STATECHANGE(i915, I915_UPLOAD_CTX); - i915->state.Ctx[I915_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_TEST_MASK; + /* Set front state. */ + i915->state.Ctx[I915_CTXREG_STATE4] &= ~(MODE4_ENABLE_STENCIL_TEST_MASK | + MODE4_ENABLE_STENCIL_WRITE_MASK); i915->state.Ctx[I915_CTXREG_STATE4] |= (ENABLE_STENCIL_TEST_MASK | - STENCIL_TEST_MASK(mask)); + ENABLE_STENCIL_WRITE_MASK | + STENCIL_TEST_MASK(front_mask) | + STENCIL_WRITE_MASK(front_writemask)); i915->state.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_REF_MASK | - S5_STENCIL_TEST_FUNC_MASK); + S5_STENCIL_TEST_FUNC_MASK | + S5_STENCIL_FAIL_MASK | + S5_STENCIL_PASS_Z_FAIL_MASK | + S5_STENCIL_PASS_Z_PASS_MASK); + + i915->state.Ctx[I915_CTXREG_LIS5] |= + (front_ref << S5_STENCIL_REF_SHIFT) | + (intel_translate_compare_func(front_func) << S5_STENCIL_TEST_FUNC_SHIFT) | + (intel_translate_stencil_op(front_fail) << S5_STENCIL_FAIL_SHIFT) | + (intel_translate_stencil_op(front_pass_z_fail) << + S5_STENCIL_PASS_Z_FAIL_SHIFT) | + (intel_translate_stencil_op(front_pass_z_pass) << + S5_STENCIL_PASS_Z_PASS_SHIFT); + + /* Set back state if different from front. */ + if (ctx->Stencil._TestTwoSide) { + i915->state.Ctx[I915_CTXREG_BF_STENCIL_OPS] &= + ~(BFO_STENCIL_REF_MASK | + BFO_STENCIL_TEST_MASK | + BFO_STENCIL_FAIL_MASK | + BFO_STENCIL_PASS_Z_FAIL_MASK | + BFO_STENCIL_PASS_Z_PASS_MASK); + i915->state.Ctx[I915_CTXREG_BF_STENCIL_OPS] |= BFO_STENCIL_TWO_SIDE | + (back_ref << BFO_STENCIL_REF_SHIFT) | + (intel_translate_compare_func(back_func) << BFO_STENCIL_TEST_SHIFT) | + (intel_translate_stencil_op(back_fail) << BFO_STENCIL_FAIL_SHIFT) | + (intel_translate_stencil_op(back_pass_z_fail) << + BFO_STENCIL_PASS_Z_FAIL_SHIFT) | + (intel_translate_stencil_op(back_pass_z_pass) << + BFO_STENCIL_PASS_Z_PASS_SHIFT); + + i915->state.Ctx[I915_CTXREG_BF_STENCIL_MASKS] &= + ~(BFM_STENCIL_TEST_MASK_MASK | + BFM_STENCIL_WRITE_MASK_MASK); + i915->state.Ctx[I915_CTXREG_BF_STENCIL_MASKS] |= + BFM_STENCIL_TEST_MASK(back_mask) | + BFM_STENCIL_WRITE_MASK(back_writemask); + } else { + i915->state.Ctx[I915_CTXREG_BF_STENCIL_OPS] &= ~BFO_STENCIL_TWO_SIDE; + } +} - i915->state.Ctx[I915_CTXREG_LIS5] |= ((ref << S5_STENCIL_REF_SHIFT) | - (test << - S5_STENCIL_TEST_FUNC_SHIFT)); +static void +i915StencilFuncSeparate(GLcontext * ctx, GLenum face, GLenum func, GLint ref, + GLuint mask) +{ } static void i915StencilMaskSeparate(GLcontext * ctx, GLenum face, GLuint mask) { - struct i915_context *i915 = I915_CONTEXT(ctx); - - DBG("%s : mask 0x%x\n", __FUNCTION__, mask); - - mask = mask & 0xff; - - I915_STATECHANGE(i915, I915_UPLOAD_CTX); - i915->state.Ctx[I915_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_WRITE_MASK; - i915->state.Ctx[I915_CTXREG_STATE4] |= (ENABLE_STENCIL_WRITE_MASK | - STENCIL_WRITE_MASK(mask)); } - static void i915StencilOpSeparate(GLcontext * ctx, GLenum face, GLenum fail, GLenum zfail, GLenum zpass) { - struct i915_context *i915 = I915_CONTEXT(ctx); - int fop = intel_translate_stencil_op(fail); - int dfop = intel_translate_stencil_op(zfail); - int dpop = intel_translate_stencil_op(zpass); - - - DBG("%s: fail : %s, zfail: %s, zpass : %s\n", __FUNCTION__, - _mesa_lookup_enum_by_nr(fail), - _mesa_lookup_enum_by_nr(zfail), _mesa_lookup_enum_by_nr(zpass)); - - I915_STATECHANGE(i915, I915_UPLOAD_CTX); - - i915->state.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_FAIL_MASK | - S5_STENCIL_PASS_Z_FAIL_MASK | - S5_STENCIL_PASS_Z_PASS_MASK); - - i915->state.Ctx[I915_CTXREG_LIS5] |= ((fop << S5_STENCIL_FAIL_SHIFT) | - (dfop << - S5_STENCIL_PASS_Z_FAIL_SHIFT) | - (dpop << - S5_STENCIL_PASS_Z_PASS_SHIFT)); } static void @@ -945,6 +991,17 @@ i915_init_packets(struct i915_context *i915) _3DSTATE_CONST_BLEND_COLOR_CMD; i915->state.Ctx[I915_CTXREG_BLENDCOLOR1] = 0; + i915->state.Ctx[I915_CTXREG_BF_STENCIL_MASKS] = + _3DSTATE_BACKFACE_STENCIL_MASKS | + BFM_ENABLE_STENCIL_TEST_MASK | + BFM_ENABLE_STENCIL_WRITE_MASK | + (0xff << BFM_STENCIL_WRITE_MASK_SHIFT) | + (0xff << BFM_STENCIL_TEST_MASK_SHIFT); + i915->state.Ctx[I915_CTXREG_BF_STENCIL_OPS] = + _3DSTATE_BACKFACE_STENCIL_OPS | + BFO_ENABLE_STENCIL_REF | + BFO_ENABLE_STENCIL_FUNCS | + BFO_ENABLE_STENCIL_TWO_SIDE; } { @@ -976,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 { @@ -996,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 fe1be93a6d..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(20, 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)); @@ -225,11 +217,6 @@ i915_emit_invarient_state(struct intel_context *intel) OUT_BATCH(_3DSTATE_LOAD_INDIRECT | 0); /* disable indirect state */ OUT_BATCH(0); - - /* Don't support twosided stencil yet */ - OUT_BATCH(_3DSTATE_BACKFACE_STENCIL_OPS | BFO_ENABLE_STENCIL_TWO_SIDE | 0); - OUT_BATCH(0); - ADVANCE_BATCH(); } @@ -263,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); @@ -371,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_clip.h b/src/mesa/drivers/dri/i965/brw_clip.h index 12e8548df1..957df441ab 100644 --- a/src/mesa/drivers/dri/i965/brw_clip.h +++ b/src/mesa/drivers/dri/i965/brw_clip.h @@ -100,6 +100,8 @@ struct brw_clip_compile { struct brw_reg fixed_planes; struct brw_reg plane_equation; + + struct brw_reg ff_sync; } reg; /* 3 different ways of expressing vertex size: @@ -173,4 +175,5 @@ struct brw_reg get_tmp( struct brw_clip_compile *c ); void brw_clip_project_position(struct brw_clip_compile *c, struct brw_reg pos ); void brw_clip_ff_sync(struct brw_clip_compile *c); +void brw_clip_init_ff_sync(struct brw_clip_compile *c); #endif diff --git a/src/mesa/drivers/dri/i965/brw_clip_line.c b/src/mesa/drivers/dri/i965/brw_clip_line.c index 9abd0642aa..048ca620fa 100644 --- a/src/mesa/drivers/dri/i965/brw_clip_line.c +++ b/src/mesa/drivers/dri/i965/brw_clip_line.c @@ -85,6 +85,10 @@ static void brw_clip_line_alloc_regs( struct brw_clip_compile *c ) i++; } + if (c->need_ff_sync) { + c->reg.ff_sync = retype(brw_vec1_grf(i, 0), BRW_REGISTER_TYPE_UD); + i++; + } c->first_tmp = i; c->last_tmp = i; @@ -246,8 +250,6 @@ static void clip_and_emit_line( struct brw_clip_compile *c ) brw_ADD(p, c->reg.t, c->reg.t0, c->reg.t1); brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_L, c->reg.t, brw_imm_f(1.0)); - if (c->need_ff_sync) - brw_clip_ff_sync(c); not_culled = brw_IF(p, BRW_EXECUTE_1); { brw_clip_interp_vertex(c, newvtx0, vtx0, vtx1, c->reg.t0, GL_FALSE); @@ -265,6 +267,7 @@ static void clip_and_emit_line( struct brw_clip_compile *c ) void brw_emit_line_clip( struct brw_clip_compile *c ) { brw_clip_line_alloc_regs(c); + brw_clip_init_ff_sync(c); if (c->key.do_flat_shading) brw_clip_copy_colors(c, 0, 1); diff --git a/src/mesa/drivers/dri/i965/brw_clip_point.c b/src/mesa/drivers/dri/i965/brw_clip_point.c index 9738299168..8458f61c5a 100644 --- a/src/mesa/drivers/dri/i965/brw_clip_point.c +++ b/src/mesa/drivers/dri/i965/brw_clip_point.c @@ -50,7 +50,7 @@ void brw_emit_point_clip( struct brw_clip_compile *c ) /* Send an empty message to kill the thread: */ brw_clip_tri_alloc_regs(c, 0); - if (c->need_ff_sync) - brw_clip_ff_sync(c); + brw_clip_init_ff_sync(c); + brw_clip_kill_thread(c); } diff --git a/src/mesa/drivers/dri/i965/brw_clip_tri.c b/src/mesa/drivers/dri/i965/brw_clip_tri.c index 4c2d655fb1..0efd77225e 100644 --- a/src/mesa/drivers/dri/i965/brw_clip_tri.c +++ b/src/mesa/drivers/dri/i965/brw_clip_tri.c @@ -119,6 +119,11 @@ void brw_clip_tri_alloc_regs( struct brw_clip_compile *c, i++; } + if (c->need_ff_sync) { + c->reg.ff_sync = retype(brw_vec1_grf(i, 0), BRW_REGISTER_TYPE_UD); + i++; + } + c->first_tmp = i; c->last_tmp = i; @@ -563,6 +568,7 @@ void brw_emit_tri_clip( struct brw_clip_compile *c ) brw_clip_tri_alloc_regs(c, 3 + c->key.nr_userclip + 6); brw_clip_tri_init_vertices(c); brw_clip_init_clipmask(c); + brw_clip_init_ff_sync(c); /* if -ve rhw workaround bit is set, do cliptest */ @@ -589,8 +595,6 @@ void brw_emit_tri_clip( struct brw_clip_compile *c ) else maybe_do_clip_tri(c); - if (c->need_ff_sync) - brw_clip_ff_sync(c); brw_clip_tri_emit_polygon(c); /* Send an empty message to kill the thread: diff --git a/src/mesa/drivers/dri/i965/brw_clip_unfilled.c b/src/mesa/drivers/dri/i965/brw_clip_unfilled.c index 26950383c1..ad1bfa435f 100644 --- a/src/mesa/drivers/dri/i965/brw_clip_unfilled.c +++ b/src/mesa/drivers/dri/i965/brw_clip_unfilled.c @@ -453,6 +453,7 @@ void brw_emit_unfilled_clip( struct brw_clip_compile *c ) brw_clip_tri_alloc_regs(c, 3 + c->key.nr_userclip + 6); brw_clip_tri_init_vertices(c); + brw_clip_init_ff_sync(c); assert(c->offset[VERT_RESULT_EDGE]); @@ -496,8 +497,6 @@ void brw_emit_unfilled_clip( struct brw_clip_compile *c ) } brw_ENDIF(p, do_clip); - if (c->need_ff_sync) - brw_clip_ff_sync(c); emit_unfilled_primitives(c); brw_clip_kill_thread(c); } diff --git a/src/mesa/drivers/dri/i965/brw_clip_util.c b/src/mesa/drivers/dri/i965/brw_clip_util.c index e09efc07ed..5a73abdfee 100644 --- a/src/mesa/drivers/dri/i965/brw_clip_util.c +++ b/src/mesa/drivers/dri/i965/brw_clip_util.c @@ -213,6 +213,8 @@ void brw_clip_emit_vue(struct brw_clip_compile *c, struct brw_compile *p = &c->func; GLuint start = c->last_mrf; + brw_clip_ff_sync(c); + assert(!(allocate && eot)); /* Cycle through mrf regs - probably futile as we have to wait for @@ -263,6 +265,7 @@ void brw_clip_kill_thread(struct brw_clip_compile *c) { struct brw_compile *p = &c->func; + brw_clip_ff_sync(c); /* Send an empty message to kill the thread and release any * allocated urb entry: */ @@ -356,17 +359,38 @@ void brw_clip_init_clipmask( struct brw_clip_compile *c ) void brw_clip_ff_sync(struct brw_clip_compile *c) { + if (c->need_ff_sync) { + struct brw_compile *p = &c->func; + struct brw_instruction *need_ff_sync; + + brw_set_conditionalmod(p, BRW_CONDITIONAL_Z); + brw_AND(p, brw_null_reg(), c->reg.ff_sync, brw_imm_ud(0x1)); + need_ff_sync = brw_IF(p, BRW_EXECUTE_1); + { + brw_OR(p, c->reg.ff_sync, c->reg.ff_sync, brw_imm_ud(0x1)); + brw_ff_sync(p, + c->reg.R0, + 0, + c->reg.R0, + 1, + 1, /* used */ + 1, /* msg length */ + 1, /* response length */ + 0, /* eot */ + 1, /* write compelete */ + 0, /* urb offset */ + BRW_URB_SWIZZLE_NONE); + } + brw_ENDIF(p, need_ff_sync); + brw_set_predicate_control(p, BRW_PREDICATE_NONE); + } +} + +void brw_clip_init_ff_sync(struct brw_clip_compile *c) +{ + if (c->need_ff_sync) { struct brw_compile *p = &c->func; - brw_ff_sync(p, - c->reg.R0, - 0, - c->reg.R0, - 1, - 1, /* used */ - 1, /* msg length */ - 1, /* response length */ - 0, /* eot */ - 1, /* write compelete */ - 0, /* urb offset */ - BRW_URB_SWIZZLE_NONE); + + brw_MOV(p, c->reg.ff_sync, brw_imm_ud(0)); + } } 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_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 606baab967..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 @@ -690,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(), @@ -701,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); @@ -724,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); @@ -1141,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 19f777fe32..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; @@ -3007,7 +3001,7 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c) loop_depth--; inst0 = inst1 = brw_WHILE(p, loop_inst[loop_depth]); - /* patch all the BREAK/CONT instructions from last BEGINLOOP */ + /* patch all the BREAK/CONT instructions from last BGNLOOP */ while (inst0 > loop_inst[loop_depth]) { inst0--; if (inst0->header.opcode == BRW_OPCODE_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..2b13829082 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; diff --git a/src/mesa/drivers/dri/intel/intel_extensions.c b/src/mesa/drivers/dri/intel/intel_extensions.c index 7742609d24..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 @@ -71,6 +72,7 @@ static const struct dri_extension card_extensions[] = { { "GL_ARB_half_float_pixel", NULL }, { "GL_ARB_multitexture", NULL }, { "GL_ARB_point_parameters", GL_ARB_point_parameters_functions }, + { "GL_ARB_point_sprite", NULL }, { "GL_ARB_texture_border_clamp", NULL }, { "GL_ARB_texture_cube_map", NULL }, { "GL_ARB_texture_env_add", NULL }, @@ -92,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 }, @@ -119,8 +122,10 @@ static const struct dri_extension i915_extensions[] = { { "GL_ARB_fragment_program", NULL }, { "GL_ARB_shadow", NULL }, { "GL_ARB_texture_non_power_of_two", NULL }, + { "GL_ATI_separate_stencil", GL_ATI_separate_stencil_functions }, { "GL_ATI_texture_env_combine3", NULL }, { "GL_EXT_shadow_funcs", NULL }, + { "GL_EXT_stencil_two_side", GL_EXT_stencil_two_side_functions }, { "GL_NV_texture_env_combine4", NULL }, { NULL, 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/compiler/r500_fragprog_emit.c b/src/mesa/drivers/dri/r300/compiler/r500_fragprog_emit.c index 3a527210c1..d694725c9b 100644 --- a/src/mesa/drivers/dri/r300/compiler/r500_fragprog_emit.c +++ b/src/mesa/drivers/dri/r300/compiler/r500_fragprog_emit.c @@ -279,7 +279,6 @@ void r500BuildFragmentProgramHwCode(struct r300_fragment_program_compiler *compi _mesa_bzero(code, sizeof(*code)); code->max_temp_idx = 1; - code->inst_offset = 0; code->inst_end = -1; radeonPairProgram(compiler, &pair_handler, compiler); diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_code.h b/src/mesa/drivers/dri/r300/compiler/radeon_code.h index 6f5bc28831..0806fb1b5c 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_code.h +++ b/src/mesa/drivers/dri/r300/compiler/radeon_code.h @@ -160,8 +160,7 @@ struct r500_fragment_program_code { uint32_t inst5; } inst[R500_PFS_MAX_INST]; - int inst_offset; - int inst_end; + int inst_end; /* Number of instructions - 1; also, last instruction to be executed */ int max_temp_idx; }; diff --git a/src/mesa/drivers/dri/r300/r300_cmdbuf.c b/src/mesa/drivers/dri/r300/r300_cmdbuf.c index af535037d0..bd46f9acf2 100644 --- a/src/mesa/drivers/dri/r300/r300_cmdbuf.c +++ b/src/mesa/drivers/dri/r300/r300_cmdbuf.c @@ -164,47 +164,46 @@ static void emit_tex_offsets(GLcontext *ctx, struct radeon_state_atom * atom) r300ContextPtr r300 = R300_CONTEXT(ctx); BATCH_LOCALS(&r300->radeon); int numtmus = packet0_count(r300, r300->hw.tex.offset.cmd); - int notexture = 0; - - if (numtmus) { - int i; - - for(i = 0; i < numtmus; ++i) { - radeonTexObj *t = r300->hw.textures[i]; - - if (!t) - notexture = 1; - } - - if (r300->radeon.radeonScreen->kernel_mm && notexture) { - return; - } - for(i = 0; i < numtmus; ++i) { - radeonTexObj *t = r300->hw.textures[i]; - if (t && !t->image_override) { - BEGIN_BATCH_NO_AUTOSTATE(4); - OUT_BATCH_REGSEQ(R300_TX_OFFSET_0 + (i * 4), 1); - OUT_BATCH_RELOC(t->tile_bits, t->mt->bo, 0, - RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0); - END_BATCH(); - } else if (!t) { - /* Texture unit hasn't a texture bound nothings to do */ - } else { /* override cases */ - if (t->bo) { - BEGIN_BATCH_NO_AUTOSTATE(4); - OUT_BATCH_REGSEQ(R300_TX_OFFSET_0 + (i * 4), 1); - OUT_BATCH_RELOC(t->tile_bits, t->bo, 0, - RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0); - END_BATCH(); - } else if (!r300->radeon.radeonScreen->kernel_mm) { - BEGIN_BATCH_NO_AUTOSTATE(2); - OUT_BATCH_REGSEQ(R300_TX_OFFSET_0 + (i * 4), 1); - OUT_BATCH(t->override_offset); - END_BATCH(); - } else { - /* Texture unit hasn't a texture bound nothings to do */ - } - } + int i; + + for(i = 0; i < numtmus; ++i) { + radeonTexObj *t = r300->hw.textures[i]; + if (t && !t->image_override) { + BEGIN_BATCH_NO_AUTOSTATE(4); + OUT_BATCH_REGSEQ(R300_TX_OFFSET_0 + (i * 4), 1); + OUT_BATCH_RELOC(t->tile_bits, t->mt->bo, 0, + RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0); + END_BATCH(); + } else if (!t) { + /* Texture unit hasn't a texture bound. + * We assign the current color buffer as a fakery to make + * 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) { + BEGIN_BATCH_NO_AUTOSTATE(4); + OUT_BATCH_REGSEQ(R300_TX_OFFSET_0 + (i * 4), 1); + OUT_BATCH_RELOC(t->tile_bits, t->bo, 0, + RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0); + END_BATCH(); + } else if (!r300->radeon.radeonScreen->kernel_mm) { + BEGIN_BATCH_NO_AUTOSTATE(2); + OUT_BATCH_REGSEQ(R300_TX_OFFSET_0 + (i * 4), 1); + OUT_BATCH(t->override_offset); + END_BATCH(); + } else { + /* Texture unit hasn't a texture bound nothings to do */ + } } } } diff --git a/src/mesa/drivers/dri/r300/r300_context.c b/src/mesa/drivers/dri/r300/r300_context.c index 6f3aab986d..db404b3847 100644 --- a/src/mesa/drivers/dri/r300/r300_context.c +++ b/src/mesa/drivers/dri/r300/r300_context.c @@ -451,11 +451,6 @@ GLboolean r300CreateContext(const __GLcontextModes * glVisual, r300InitState(r300); r300InitShaderFunctions(r300); - if (screen->chip_family == CHIP_FAMILY_RS600 || screen->chip_family == CHIP_FAMILY_RS690 || - screen->chip_family == CHIP_FAMILY_RS740) { - r300->radeon.texture_row_align = 64; - } - r300InitGLExtensions(ctx); return GL_TRUE; diff --git a/src/mesa/drivers/dri/r300/r300_draw.c b/src/mesa/drivers/dri/r300/r300_draw.c index fcfd309933..aedc6cfb2a 100644 --- a/src/mesa/drivers/dri/r300/r300_draw.c +++ b/src/mesa/drivers/dri/r300/r300_draw.c @@ -462,6 +462,7 @@ 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) { @@ -476,6 +477,12 @@ static void r300DrawPrims(GLcontext *ctx, limits.max_indices = 65535; limits.max_vb_size = 1024*1024; + /* 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/r300/r300_ioctl.c b/src/mesa/drivers/dri/r300/r300_ioctl.c index 5bded642ef..7558f9e225 100644 --- a/src/mesa/drivers/dri/r300/r300_ioctl.c +++ b/src/mesa/drivers/dri/r300/r300_ioctl.c @@ -168,18 +168,21 @@ static void r300ClearBuffer(r300ContextPtr r300, int flags, } #if 1 if (flags & (CLEARBUFFER_DEPTH | CLEARBUFFER_STENCIL)) { - assert(rrbd != 0); - cbpitch = (rrbd->pitch / rrbd->cpp); + uint32_t zbpitch = (rrbd->pitch / rrbd->cpp); if (rrbd->bo->flags & RADEON_BO_FLAGS_MACRO_TILE){ - cbpitch |= R300_DEPTHMACROTILE_ENABLE; + zbpitch |= R300_DEPTHMACROTILE_ENABLE; } if (rrbd->bo->flags & RADEON_BO_FLAGS_MICRO_TILE){ - cbpitch |= R300_DEPTHMICROTILE_TILED; + zbpitch |= R300_DEPTHMICROTILE_TILED; } BEGIN_BATCH_NO_AUTOSTATE(6); OUT_BATCH_REGSEQ(R300_ZB_DEPTHOFFSET, 1); OUT_BATCH_RELOC(0, rrbd->bo, 0, 0, RADEON_GEM_DOMAIN_VRAM, 0); - OUT_BATCH_REGVAL(R300_ZB_DEPTHPITCH, cbpitch); + OUT_BATCH_REGSEQ(R300_ZB_DEPTHPITCH, 1); + if (!r300->radeon.radeonScreen->kernel_mm) + OUT_BATCH(zbpitch); + else + OUT_BATCH_RELOC(zbpitch, rrbd->bo, zbpitch, 0, RADEON_GEM_DOMAIN_VRAM, 0); END_BATCH(); } #endif diff --git a/src/mesa/drivers/dri/r300/r300_state.c b/src/mesa/drivers/dri/r300/r300_state.c index 1ac14267d5..050e8cd2a7 100644 --- a/src/mesa/drivers/dri/r300/r300_state.c +++ b/src/mesa/drivers/dri/r300/r300_state.c @@ -1253,6 +1253,7 @@ static GLuint translate_lod_bias(GLfloat bias) return (((GLuint)b) << R300_LOD_BIAS_SHIFT) & R300_LOD_BIAS_MASK; } + static void r300SetupTextures(GLcontext * ctx) { int i, mtu; @@ -1345,6 +1346,28 @@ static void r300SetupTextures(GLcontext * ctx) } } + /* R3xx and R4xx chips require that the texture unit corresponding to + * KIL instructions is really enabled. + * + * We do some fakery here and in the state atom emit logic to enable + * the texture without tripping up the CS checker in the kernel. + */ + if (r300->radeon.radeonScreen->chip_family < CHIP_FAMILY_RV515) { + if (ctx->FragmentProgram._Current->UsesKill && last_hw_tmu < 0) { + last_hw_tmu++; + + r300->hw.txe.cmd[R300_TXE_ENABLE] |= 1; + + r300->hw.tex.border_color.cmd[R300_TEX_VALUE_0] = 0; + r300->hw.tex.chroma_key.cmd[R300_TEX_VALUE_0] = 0; + r300->hw.tex.filter.cmd[R300_TEX_VALUE_0] = 0; + r300->hw.tex.filter_1.cmd[R300_TEX_VALUE_0] = 0; + r300->hw.tex.size.cmd[R300_TEX_VALUE_0] = 0; /* 1x1 texture */ + r300->hw.tex.format.cmd[R300_TEX_VALUE_0] = 0; /* A8 format */ + r300->hw.tex.pitch.cmd[R300_TEX_VALUE_0] = 0; + } + } + r300->hw.tex.filter.cmd[R300_TEX_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R300_TX_FILTER0_0, last_hw_tmu + 1); r300->hw.tex.filter_1.cmd[R300_TEX_CMD_0] = @@ -1362,16 +1385,6 @@ static void r300SetupTextures(GLcontext * ctx) r300->hw.tex.border_color.cmd[R300_TEX_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R300_TX_BORDER_COLOR_0, last_hw_tmu + 1); - if (r300->radeon.radeonScreen->chip_family < CHIP_FAMILY_RV515) { - if (ctx->FragmentProgram._Current->UsesKill && last_hw_tmu < 0) { - // The KILL operation requires the first texture unit - // to be enabled. - r300->hw.txe.cmd[R300_TXE_ENABLE] |= 1; - r300->hw.tex.filter.cmd[R300_TEX_VALUE_0] = 0; - r300->hw.tex.filter.cmd[R300_TEX_CMD_0] = - cmdpacket0(r300->radeon.radeonScreen, R300_TX_FILTER0_0, 1); - } - } r300->vtbl.SetupFragmentShaderTextures(ctx, tmu_mappings); if (RADEON_DEBUG & DEBUG_STATE) @@ -2103,13 +2116,13 @@ static void r500SetupPixelShader(GLcontext *ctx) rmesa->hw.fp.cmd[R500_FP_PIXSIZE] = code->max_temp_idx; rmesa->hw.fp.cmd[R500_FP_CODE_ADDR] = - R500_US_CODE_START_ADDR(code->inst_offset) | + R500_US_CODE_START_ADDR(0) | R500_US_CODE_END_ADDR(code->inst_end); rmesa->hw.fp.cmd[R500_FP_CODE_RANGE] = - R500_US_CODE_RANGE_ADDR(code->inst_offset) | + R500_US_CODE_RANGE_ADDR(0) | R500_US_CODE_RANGE_SIZE(code->inst_end); rmesa->hw.fp.cmd[R500_FP_CODE_OFFSET] = - R500_US_CODE_OFFSET_ADDR(0); /* FIXME when we add flow control */ + R500_US_CODE_OFFSET_ADDR(0); R300_STATECHANGE(rmesa, r500fp); /* Emit our shader... */ @@ -2234,6 +2247,7 @@ static void r300InvalidateState(GLcontext * ctx, GLuint new_state) _mesa_update_draw_buffer_bounds(ctx); R300_STATECHANGE(r300, cb); + R300_STATECHANGE(r300, zb); } r300->radeon.NewGLState |= new_state; diff --git a/src/mesa/drivers/dri/r600/r600_cmdbuf.c b/src/mesa/drivers/dri/r600/r600_cmdbuf.c index 74fec02584..dc2fb0144a 100644 --- a/src/mesa/drivers/dri/r600/r600_cmdbuf.c +++ b/src/mesa/drivers/dri/r600/r600_cmdbuf.c @@ -78,8 +78,7 @@ int r600_cs_write_reloc(struct radeon_cs *cs, struct radeon_bo *bo, uint32_t read_domain, uint32_t write_domain, - uint32_t flags, - offset_modifiers* poffset_mod) + uint32_t flags) { struct r600_cs_reloc_legacy *relocs; int i; @@ -135,10 +134,6 @@ int r600_cs_write_reloc(struct radeon_cs *cs, cs->section_ndw += 2; cs->section_cdw += 2; - relocs[i].offset_mod.shift = poffset_mod->shift; - relocs[i].offset_mod.shiftbits = poffset_mod->shiftbits; - relocs[i].offset_mod.mask = poffset_mod->mask; - return 0; } } @@ -160,9 +155,6 @@ int r600_cs_write_reloc(struct radeon_cs *cs, { return -ENOMEM; } - relocs[cs->crelocs].offset_mod.shift = poffset_mod->shift; - relocs[cs->crelocs].offset_mod.shiftbits = poffset_mod->shiftbits; - relocs[cs->crelocs].offset_mod.mask = poffset_mod->mask; relocs[cs->crelocs].indices[0] = cs->cdw - 1; relocs[cs->crelocs].reloc_indices[0] = cs->section_cdw; @@ -255,65 +247,44 @@ static int r600_cs_process_relocs(struct radeon_cs *cs, csm = (struct r600_cs_manager_legacy*)cs->csm; relocs = (struct r600_cs_reloc_legacy *)cs->relocs; restart: - for (i = 0; i < cs->crelocs; i++) - { - for (j = 0; j < relocs[i].cindices; j++) - { + for (i = 0; i < cs->crelocs; i++) { uint32_t soffset, eoffset, asicoffset; r = radeon_bo_legacy_validate(relocs[i].base.bo, - &soffset, &eoffset); - if (r == -EAGAIN) - { - goto restart; + &soffset, &eoffset); + if (r == -EAGAIN) { + goto restart; } - if (r) - { - fprintf(stderr, "validated %p [0x%08X, 0x%08X]\n", - relocs[i].base.bo, soffset, eoffset); - return r; + if (r) { + fprintf(stderr, "validated %p [0x%08X, 0x%08X]\n", + relocs[i].base.bo, soffset, eoffset); + return r; } asicoffset = soffset; - if (asicoffset >= eoffset) - { - /* radeon_bo_debug(relocs[i].base.bo, 12); */ - fprintf(stderr, "validated %p [0x%08X, 0x%08X]\n", - relocs[i].base.bo, soffset, eoffset); - fprintf(stderr, "above end: %p 0x%08X 0x%08X\n", - relocs[i].base.bo, - cs->packets[relocs[i].indices[j]], - eoffset); - exit(0); - return -EINVAL; - } - /* apply offset operator */ - switch (relocs[i].offset_mod.shift) - { - case NO_SHIFT: - asicoffset = asicoffset & relocs[i].offset_mod.mask; - break; - case LEFT_SHIFT: - asicoffset = (asicoffset << relocs[i].offset_mod.shiftbits) & relocs[i].offset_mod.mask; - break; - case RIGHT_SHIFT: - asicoffset = (asicoffset >> relocs[i].offset_mod.shiftbits) & relocs[i].offset_mod.mask; - break; - default: - break; - }; - - /* pkt3 nop header in ib chunk */ - cs->packets[relocs[i].reloc_indices[j]] = 0xC0001000; - - /* reloc index in ib chunk */ - cs->packets[relocs[i].reloc_indices[j] + 1] = offset_dw; - - /* asic offset in reloc chunk */ /* see alex drm r600_nomm_relocate */ - reloc_chunk[offset_dw] = asicoffset; - reloc_chunk[offset_dw + 3] = 0; - - offset_dw += 4; - } + + for (j = 0; j < relocs[i].cindices; j++) { + if (asicoffset >= eoffset) { + /* radeon_bo_debug(relocs[i].base.bo, 12); */ + fprintf(stderr, "validated %p [0x%08X, 0x%08X]\n", + relocs[i].base.bo, soffset, eoffset); + fprintf(stderr, "above end: %p 0x%08X 0x%08X\n", + relocs[i].base.bo, + cs->packets[relocs[i].indices[j]], + eoffset); + exit(0); + return -EINVAL; + } + /* pkt3 nop header in ib chunk */ + cs->packets[relocs[i].reloc_indices[j]] = 0xC0001000; + /* reloc index in ib chunk */ + cs->packets[relocs[i].reloc_indices[j] + 1] = offset_dw; + } + + /* asic offset in reloc chunk */ /* see alex drm r600_nomm_relocate */ + reloc_chunk[offset_dw] = asicoffset; + reloc_chunk[offset_dw + 3] = 0; + + offset_dw += 4; } *length_dw_reloc_chunk = offset_dw; @@ -351,10 +322,7 @@ static int r600_cs_emit(struct radeon_cs *cs) struct r600_cs_manager_legacy *csm = (struct r600_cs_manager_legacy*)cs->csm; struct drm_radeon_cs cs_cmd; struct drm_radeon_cs_chunk cs_chunk[2]; - drm_radeon_cmd_buffer_t cmd; - /* drm_r300_cmd_header_t age; */ uint32_t length_dw_reloc_chunk; - uint64_t ull; uint64_t chunk_ptrs[2]; uint32_t reloc_chunk[128]; int r; @@ -363,43 +331,13 @@ static int r600_cs_emit(struct radeon_cs *cs) /* TODO : put chip level things here if need. */ /* csm->ctx->vtbl.emit_cs_header(cs, csm->ctx); */ - BATCH_LOCALS(csm->ctx); - drm_radeon_getparam_t gp; - uint32_t current_scratchx_age; - - gp.param = RADEON_PARAM_LAST_CLEAR; - gp.value = (int *)¤t_scratchx_age; - r = drmCommandWriteRead(cs->csm->fd, - DRM_RADEON_GETPARAM, - &gp, - sizeof(gp)); - if (r) - { - fprintf(stderr, "%s: drmRadeonGetParam: %d\n", __FUNCTION__, r); - exit(1); - } - - csm->pending_age = 0; csm->pending_count = 1; - current_scratchx_age++; - csm->pending_age = current_scratchx_age; - - BEGIN_BATCH_NO_AUTOSTATE(3); - R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_CONFIG_REG, 1)); - R600_OUT_BATCH((SCRATCH_REG2 - R600_SET_CONFIG_REG_OFFSET) >> 2); - R600_OUT_BATCH(current_scratchx_age); - END_BATCH(); - COMMIT_BATCH(); - - //TODO ioctl to get back cs id assigned in drm - //csm->pending_age = cs_id_back; - r = r600_cs_process_relocs(cs, &(reloc_chunk[0]), &length_dw_reloc_chunk); if (r) { return 0; } - + /* raw ib chunk */ cs_chunk[0].chunk_id = RADEON_CHUNK_ID_IB; cs_chunk[0].length_dw = cs->cdw; @@ -429,6 +367,8 @@ static int r600_cs_emit(struct radeon_cs *cs) return r; } + csm->pending_age = cs_cmd.cs_id; + r600_cs_set_age(cs); cs->csm->read_used = 0; @@ -514,8 +454,12 @@ struct radeon_cs_manager * r600_radeon_cs_manager_legacy_ctor(struct radeon_cont void r600InitCmdBuf(context_t *r600) /* from rcommonInitCmdBuf */ { radeonContextPtr rmesa = &r600->radeon; - 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_cmdbuf.h b/src/mesa/drivers/dri/r600/r600_cmdbuf.h index bd1ed7fdff..5df0cf1ab6 100644 --- a/src/mesa/drivers/dri/r600/r600_cmdbuf.h +++ b/src/mesa/drivers/dri/r600/r600_cmdbuf.h @@ -132,15 +132,13 @@ struct r600_cs_reloc_legacy { uint32_t cindices; uint32_t *indices; uint32_t *reloc_indices; - struct offset_modifiers offset_mod; }; extern int r600_cs_write_reloc(struct radeon_cs *cs, struct radeon_bo *bo, uint32_t read_domain, uint32_t write_domain, - uint32_t flags, - offset_modifiers* poffset_mod); + uint32_t flags); static inline void r600_cs_write_dword(struct radeon_cs *cs, uint32_t dword) { @@ -171,7 +169,7 @@ struct radeon_cs_manager * r600_radeon_cs_manager_legacy_ctor(struct radeon_cont /** * Write a relocated dword to the command buffer. */ -#define R600_OUT_BATCH_RELOC(data, bo, offset, rd, wd, flags, offset_mod) \ +#define R600_OUT_BATCH_RELOC(data, bo, offset, rd, wd, flags) \ do { \ if (0 && offset) { \ fprintf(stderr, "(%s:%s:%d) offset : %d\n", \ @@ -179,7 +177,7 @@ struct radeon_cs_manager * r600_radeon_cs_manager_legacy_ctor(struct radeon_cont } \ r600_cs_write_dword(b_l_rmesa->cmdbuf.cs, offset); \ r600_cs_write_reloc(b_l_rmesa->cmdbuf.cs, \ - bo, rd, wd, flags, offset_mod); \ + bo, rd, wd, flags); \ } while(0) /* R600/R700 */ 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 bcb33e1386..30ddce682c 100644 --- a/src/mesa/drivers/dri/r600/r600_context.h +++ b/src/mesa/drivers/dri/r600/r600_context.h @@ -128,13 +128,6 @@ enum RIGHT_SHIFT = 2, }; -typedef struct offset_modifiers -{ - GLuint shift; - GLuint shiftbits; - GLuint mask; -} offset_modifiers; - /** * \brief R600 context structure. */ @@ -165,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_tex.c b/src/mesa/drivers/dri/r600/r600_tex.c index 853f824b2c..6d531bf0f9 100644 --- a/src/mesa/drivers/dri/r600/r600_tex.c +++ b/src/mesa/drivers/dri/r600/r600_tex.c @@ -160,7 +160,7 @@ static void r600SetTexDefaultState(radeonTexObjPtr t) SETfield(t->SQ_TEX_SAMPLER0, SQ_TEX_BORDER_COLOR_TRANS_BLACK, BORDER_COLOR_TYPE_shift, BORDER_COLOR_TYPE_mask); t->SQ_TEX_SAMPLER1 = 0; - SETfield(t->SQ_TEX_SAMPLER1, MAX_LOD_mask, MAX_LOD_shift, MAX_LOD_mask); + SETfield(t->SQ_TEX_SAMPLER1, 0x3ff, MAX_LOD_shift, MAX_LOD_mask); t->SQ_TEX_SAMPLER2 = 0; SETbit(t->SQ_TEX_SAMPLER2, SQ_TEX_SAMPLER_WORD2_0__TYPE_bit); diff --git a/src/mesa/drivers/dri/r600/r600_texstate.c b/src/mesa/drivers/dri/r600/r600_texstate.c index 1cf3b484ae..ee9b64ee43 100644 --- a/src/mesa/drivers/dri/r600/r600_texstate.c +++ b/src/mesa/drivers/dri/r600/r600_texstate.c @@ -556,7 +556,7 @@ static void setup_hardware_state(context_t *rmesa, struct gl_texture_object *tex radeonTexObj *t = radeon_tex_obj(texObj); const struct gl_texture_image *firstImage; int firstlevel = t->mt ? t->mt->firstLevel : 0; - GLuint uTexelPitch; + GLuint uTexelPitch, row_align; firstImage = t->base.Image[0][firstlevel]; @@ -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); @@ -595,15 +592,26 @@ static void setup_hardware_state(context_t *rmesa, struct gl_texture_object *tex return; } - uTexelPitch = (firstImage->Width + R700_TEXEL_PITCH_ALIGNMENT_MASK) + row_align = rmesa->radeon.texture_row_align - 1; + uTexelPitch = ((firstImage->Width * t->mt->bpp + row_align) & ~row_align) / t->mt->bpp; + uTexelPitch = (uTexelPitch + R700_TEXEL_PITCH_ALIGNMENT_MASK) & ~R700_TEXEL_PITCH_ALIGNMENT_MASK; + /* min pitch is 8 */ + if (uTexelPitch < 8) + uTexelPitch = 8; + SETfield(t->SQ_TEX_RESOURCE0, (uTexelPitch/8)-1, PITCH_shift, PITCH_mask); SETfield(t->SQ_TEX_RESOURCE0, firstImage->Width - 1, TEX_WIDTH_shift, TEX_WIDTH_mask); SETfield(t->SQ_TEX_RESOURCE1, firstImage->Height - 1, TEX_HEIGHT_shift, TEX_HEIGHT_mask); + if ((t->mt->lastLevel - t->mt->firstLevel) > 0) { + t->SQ_TEX_RESOURCE3 = t->mt->levels[0].size / 256; + SETfield(t->SQ_TEX_RESOURCE4, t->mt->firstLevel, BASE_LEVEL_shift, BASE_LEVEL_mask); + SETfield(t->SQ_TEX_RESOURCE5, t->mt->lastLevel, LAST_LEVEL_shift, LAST_LEVEL_mask); + } } /** @@ -690,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; @@ -700,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) { @@ -751,6 +764,11 @@ void r600SetTexOffset(__DRIcontext * pDRICtx, GLint texname, pitch_val = (pitch_val + R700_TEXEL_PITCH_ALIGNMENT_MASK) & ~R700_TEXEL_PITCH_ALIGNMENT_MASK; + + /* min pitch is 8 */ + if (pitch_val < 8) + pitch_val = 8; + SETfield(t->SQ_TEX_RESOURCE0, (pitch_val/8)-1, PITCH_shift, PITCH_mask); } @@ -898,6 +916,10 @@ void r600SetTexBuffer2(__DRIcontext *pDRICtx, GLint target, GLint glx_texture_fo pitch_val = (pitch_val + R700_TEXEL_PITCH_ALIGNMENT_MASK) & ~R700_TEXEL_PITCH_ALIGNMENT_MASK; + /* min pitch is 8 */ + if (pitch_val < 8) + pitch_val = 8; + SETfield(t->SQ_TEX_RESOURCE0, (pitch_val/8)-1, PITCH_shift, PITCH_mask); SETfield(t->SQ_TEX_RESOURCE0, rb->base.Width - 1, TEX_WIDTH_shift, TEX_WIDTH_mask); diff --git a/src/mesa/drivers/dri/r600/r700_assembler.c b/src/mesa/drivers/dri/r600/r700_assembler.c index ebd5ff106b..eaacd06113 100644 --- a/src/mesa/drivers/dri/r600/r700_assembler.c +++ b/src/mesa/drivers/dri/r600/r700_assembler.c @@ -1205,7 +1205,7 @@ GLboolean tex_src(r700_AssemblerBase *pAsm) return GL_TRUE; } -GLboolean assemble_tex_instruction(r700_AssemblerBase *pAsm) +GLboolean assemble_tex_instruction(r700_AssemblerBase *pAsm, GLboolean normalized) { PVSSRC * texture_coordinate_source; PVSSRC * texture_unit_source; @@ -1227,10 +1227,18 @@ GLboolean assemble_tex_instruction(r700_AssemblerBase *pAsm) tex_instruction_ptr->m_Word0.f.resource_id = texture_unit_source->reg; tex_instruction_ptr->m_Word1.f.lod_bias = 0x0; - tex_instruction_ptr->m_Word1.f.coord_type_x = SQ_TEX_NORMALIZED; - tex_instruction_ptr->m_Word1.f.coord_type_y = SQ_TEX_NORMALIZED; - tex_instruction_ptr->m_Word1.f.coord_type_z = SQ_TEX_NORMALIZED; - tex_instruction_ptr->m_Word1.f.coord_type_w = SQ_TEX_NORMALIZED; + if (normalized) { + tex_instruction_ptr->m_Word1.f.coord_type_x = SQ_TEX_NORMALIZED; + tex_instruction_ptr->m_Word1.f.coord_type_y = SQ_TEX_NORMALIZED; + tex_instruction_ptr->m_Word1.f.coord_type_z = SQ_TEX_NORMALIZED; + tex_instruction_ptr->m_Word1.f.coord_type_w = SQ_TEX_NORMALIZED; + } else { + /* XXX: UNNORMALIZED tex coords have limited wrap modes */ + tex_instruction_ptr->m_Word1.f.coord_type_x = SQ_TEX_UNNORMALIZED; + tex_instruction_ptr->m_Word1.f.coord_type_y = SQ_TEX_UNNORMALIZED; + tex_instruction_ptr->m_Word1.f.coord_type_z = SQ_TEX_UNNORMALIZED; + tex_instruction_ptr->m_Word1.f.coord_type_w = SQ_TEX_UNNORMALIZED; + } tex_instruction_ptr->m_Word2.f.offset_x = 0x0; tex_instruction_ptr->m_Word2.f.offset_y = 0x0; @@ -2196,11 +2204,19 @@ GLboolean next_ins(r700_AssemblerBase *pAsm) if( GL_TRUE == IsTex(pILInst->Opcode) ) { - if( GL_FALSE == assemble_tex_instruction(pAsm) ) - { - r700_error(ERROR_ASM_TEXINSTRUCTION, "Error assembling TEX instruction"); - return GL_FALSE; - } + if (pILInst->TexSrcTarget == TEXTURE_RECT_INDEX) { + if( GL_FALSE == assemble_tex_instruction(pAsm, GL_FALSE) ) + { + r700_error(ERROR_ASM_TEXINSTRUCTION, "Error assembling TEX instruction"); + return GL_FALSE; + } + } else { + if( GL_FALSE == assemble_tex_instruction(pAsm, GL_TRUE) ) + { + r700_error(ERROR_ASM_TEXINSTRUCTION, "Error assembling TEX instruction"); + return GL_FALSE; + } + } } else { //ALU @@ -3823,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_assembler.h b/src/mesa/drivers/dri/r600/r700_assembler.h index e9b21b802e..f9c4d849c6 100644 --- a/src/mesa/drivers/dri/r600/r700_assembler.h +++ b/src/mesa/drivers/dri/r600/r700_assembler.h @@ -424,7 +424,7 @@ GLboolean assemble_src(r700_AssemblerBase *pAsm, GLboolean assemble_dst(r700_AssemblerBase *pAsm); GLboolean tex_dst(r700_AssemblerBase *pAsm); GLboolean tex_src(r700_AssemblerBase *pAsm); -GLboolean assemble_tex_instruction(r700_AssemblerBase *pAsm); +GLboolean assemble_tex_instruction(r700_AssemblerBase *pAsm, GLboolean normalized); void initialize(r700_AssemblerBase *pAsm); GLboolean assemble_alu_src(R700ALUInstruction* alu_instruction_ptr, int source_index, diff --git a/src/mesa/drivers/dri/r600/r700_chip.c b/src/mesa/drivers/dri/r600/r700_chip.c index c083862f36..e5e0f556cb 100644 --- a/src/mesa/drivers/dri/r600/r700_chip.c +++ b/src/mesa/drivers/dri/r600/r700_chip.c @@ -38,6 +38,8 @@ #include "r700_vertprog.h" #include "r700_ioctl.h" +#include "radeon_mipmap_tree.h" + #define LINK_STATES(reg) \ do \ { \ @@ -241,6 +243,67 @@ GLboolean r700InitChipObject(context_t *context) return GL_TRUE; } +GLboolean r700SendTextureState(context_t *context) +{ + unsigned int i; + R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw); + struct radeon_bo *bo = NULL; + BATCH_LOCALS(&context->radeon); + + for (i=0; i<R700_TEXTURE_NUMBERUNITS; i++) { + radeonTexObj *t = r700->textures[i]; + if (t) { + if (!t->image_override) + bo = t->mt->bo; + else + bo = t->bo; + if (bo) { + + r700SyncSurf(context, bo, + RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, + 0, TC_ACTION_ENA_bit); + + BEGIN_BATCH_NO_AUTOSTATE(9); + R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_RESOURCE, 7)); + R600_OUT_BATCH(i * 7); + R600_OUT_BATCH(r700->textures[i]->SQ_TEX_RESOURCE0); + R600_OUT_BATCH(r700->textures[i]->SQ_TEX_RESOURCE1); + R600_OUT_BATCH_RELOC(r700->textures[i]->SQ_TEX_RESOURCE2, + bo, + 0, + RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0); + R600_OUT_BATCH_RELOC(r700->textures[i]->SQ_TEX_RESOURCE3, + bo, + r700->textures[i]->SQ_TEX_RESOURCE3, + RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0); + R600_OUT_BATCH(r700->textures[i]->SQ_TEX_RESOURCE4); + R600_OUT_BATCH(r700->textures[i]->SQ_TEX_RESOURCE5); + R600_OUT_BATCH(r700->textures[i]->SQ_TEX_RESOURCE6); + END_BATCH(); + + BEGIN_BATCH_NO_AUTOSTATE(5); + R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_SAMPLER, 3)); + R600_OUT_BATCH(i * 3); + R600_OUT_BATCH(r700->textures[i]->SQ_TEX_SAMPLER0); + R600_OUT_BATCH(r700->textures[i]->SQ_TEX_SAMPLER1); + R600_OUT_BATCH(r700->textures[i]->SQ_TEX_SAMPLER2); + END_BATCH(); + + BEGIN_BATCH_NO_AUTOSTATE(2 + 4); + R600_OUT_BATCH_REGSEQ((TD_PS_SAMPLER0_BORDER_RED + (i * 16)), 4); + R600_OUT_BATCH(r700->textures[i]->TD_PS_SAMPLER0_BORDER_RED); + R600_OUT_BATCH(r700->textures[i]->TD_PS_SAMPLER0_BORDER_GREEN); + R600_OUT_BATCH(r700->textures[i]->TD_PS_SAMPLER0_BORDER_BLUE); + R600_OUT_BATCH(r700->textures[i]->TD_PS_SAMPLER0_BORDER_ALPHA); + END_BATCH(); + + COMMIT_BATCH(); + } + } + } + return GL_TRUE; +} + void r700SetupVTXConstants(GLcontext * ctx, unsigned int nStreamID, void * pAos, @@ -249,10 +312,7 @@ void r700SetupVTXConstants(GLcontext * ctx, unsigned int count) /* number of vectors in stream */ { context_t *context = R700_CONTEXT(ctx); - uint32_t *dest; struct radeon_aos * paos = (struct radeon_aos *)pAos; - offset_modifiers offset_mod = {NO_SHIFT, 0, 0xFFFFFFFF}; - BATCH_LOCALS(&context->radeon); unsigned int uSQ_VTX_CONSTANT_WORD0_0; @@ -261,6 +321,9 @@ void r700SetupVTXConstants(GLcontext * ctx, unsigned int uSQ_VTX_CONSTANT_WORD3_0 = 0; unsigned int uSQ_VTX_CONSTANT_WORD6_0 = 0; + if (!paos->bo) + return; + if ((context->radeon.radeonScreen->chip_family == CHIP_FAMILY_RV610) || (context->radeon.radeonScreen->chip_family == CHIP_FAMILY_RV620) || (context->radeon.radeonScreen->chip_family == CHIP_FAMILY_RS780) || @@ -294,7 +357,7 @@ void r700SetupVTXConstants(GLcontext * ctx, R600_OUT_BATCH_RELOC(uSQ_VTX_CONSTANT_WORD0_0, paos->bo, uSQ_VTX_CONSTANT_WORD0_0, - RADEON_GEM_DOMAIN_GTT, 0, 0, &offset_mod); + RADEON_GEM_DOMAIN_GTT, 0, 0); R600_OUT_BATCH(uSQ_VTX_CONSTANT_WORD1_0); R600_OUT_BATCH(uSQ_VTX_CONSTANT_WORD2_0); R600_OUT_BATCH(uSQ_VTX_CONSTANT_WORD3_0); @@ -310,7 +373,6 @@ void r700SetupVTXConstants(GLcontext * ctx, int r700SetupStreams(GLcontext * ctx) { context_t *context = R700_CONTEXT(ctx); - BATCH_LOCALS(&context->radeon); struct r700_vertex_program *vpc @@ -324,7 +386,7 @@ int r700SetupStreams(GLcontext * ctx) BEGIN_BATCH_NO_AUTOSTATE(6); R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_CTL_CONST, 1)); - R600_OUT_BATCH(mmSQ_VTX_BASE_VTX_LOC - ASIC_CTL_CONST_BASE_INDEX); + R600_OUT_BATCH(mmSQ_VTX_BASE_VTX_LOC - ASIC_CTL_CONST_BASE_INDEX); R600_OUT_BATCH(0); R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_CTL_CONST, 1)); @@ -417,11 +479,10 @@ GLboolean r700SendContextStates(context_t *context) return GL_TRUE; } -GLboolean r700SendDepthTargetState(context_t *context, int id) +GLboolean r700SendDepthTargetState(context_t *context) { R700_CHIP_CONTEXT *r700 = R700_CONTEXT_STATES(context); struct radeon_renderbuffer *rrb; - offset_modifiers offset_mod; BATCH_LOCALS(&context->radeon); rrb = radeon_get_depthbuffer(&context->radeon); @@ -430,10 +491,6 @@ GLboolean r700SendDepthTargetState(context_t *context, int id) return GL_FALSE; } - offset_mod.shift = NO_SHIFT; - offset_mod.shiftbits = 0; - offset_mod.mask = 0xFFFFFFFF; - BEGIN_BATCH_NO_AUTOSTATE(9); R600_OUT_BATCH_REGSEQ(DB_DEPTH_SIZE, 2); R600_OUT_BATCH(r700->DB_DEPTH_SIZE.u32All); @@ -442,7 +499,7 @@ GLboolean r700SendDepthTargetState(context_t *context, int id) R600_OUT_BATCH_RELOC(r700->DB_DEPTH_BASE.u32All, rrb->bo, r700->DB_DEPTH_BASE.u32All, - 0, RADEON_GEM_DOMAIN_VRAM, 0, &offset_mod); + 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(); @@ -479,7 +536,6 @@ GLboolean r700SendRenderTargetState(context_t *context, int id) { R700_CHIP_CONTEXT *r700 = R700_CONTEXT_STATES(context); struct radeon_renderbuffer *rrb; - offset_modifiers offset_mod; BATCH_LOCALS(&context->radeon); rrb = radeon_get_colorbuffer(&context->radeon); @@ -494,16 +550,12 @@ GLboolean r700SendRenderTargetState(context_t *context, int id) if (!r700->render_target[id].enabled) return GL_FALSE; - offset_mod.shift = NO_SHIFT; - offset_mod.shiftbits = 0; - offset_mod.mask = 0xFFFFFFFF; - BEGIN_BATCH_NO_AUTOSTATE(3); R600_OUT_BATCH_REGSEQ(CB_COLOR0_BASE + (4 * id), 1); R600_OUT_BATCH_RELOC(r700->render_target[id].CB_COLOR0_BASE.u32All, rrb->bo, r700->render_target[id].CB_COLOR0_BASE.u32All, - 0, RADEON_GEM_DOMAIN_VRAM, 0, &offset_mod); + 0, RADEON_GEM_DOMAIN_VRAM, 0); END_BATCH(); if ((context->radeon.radeonScreen->chip_family > CHIP_FAMILY_R600) && @@ -540,16 +592,13 @@ GLboolean r700SendRenderTargetState(context_t *context, int id) GLboolean r700SendPSState(context_t *context) { R700_CHIP_CONTEXT *r700 = R700_CONTEXT_STATES(context); - struct radeon_renderbuffer *rrb; struct radeon_bo * pbo; - offset_modifiers offset_mod; BATCH_LOCALS(&context->radeon); pbo = (struct radeon_bo *)r700GetActiveFpShaderBo(GL_CONTEXT(context)); - offset_mod.shift = NO_SHIFT; - offset_mod.shiftbits = 0; - offset_mod.mask = 0xFFFFFFFF; + if (!pbo) + return GL_FALSE; r700SyncSurf(context, pbo, RADEON_GEM_DOMAIN_GTT, 0, SH_ACTION_ENA_bit); @@ -558,7 +607,7 @@ GLboolean r700SendPSState(context_t *context) R600_OUT_BATCH_RELOC(r700->ps.SQ_PGM_START_PS.u32All, pbo, r700->ps.SQ_PGM_START_PS.u32All, - RADEON_GEM_DOMAIN_GTT, 0, 0, &offset_mod); + RADEON_GEM_DOMAIN_GTT, 0, 0); END_BATCH(); BEGIN_BATCH_NO_AUTOSTATE(9); @@ -575,16 +624,13 @@ GLboolean r700SendPSState(context_t *context) GLboolean r700SendVSState(context_t *context) { R700_CHIP_CONTEXT *r700 = R700_CONTEXT_STATES(context); - struct radeon_renderbuffer *rrb; struct radeon_bo * pbo; - offset_modifiers offset_mod; BATCH_LOCALS(&context->radeon); pbo = (struct radeon_bo *)r700GetActiveVpShaderBo(GL_CONTEXT(context)); - offset_mod.shift = NO_SHIFT; - offset_mod.shiftbits = 0; - offset_mod.mask = 0xFFFFFFFF; + if (!pbo) + return GL_FALSE; r700SyncSurf(context, pbo, RADEON_GEM_DOMAIN_GTT, 0, SH_ACTION_ENA_bit); @@ -593,7 +639,7 @@ GLboolean r700SendVSState(context_t *context) R600_OUT_BATCH_RELOC(r700->vs.SQ_PGM_START_VS.u32All, pbo, r700->vs.SQ_PGM_START_VS.u32All, - RADEON_GEM_DOMAIN_GTT, 0, 0, &offset_mod); + RADEON_GEM_DOMAIN_GTT, 0, 0); END_BATCH(); BEGIN_BATCH_NO_AUTOSTATE(6); @@ -609,9 +655,7 @@ GLboolean r700SendVSState(context_t *context) GLboolean r700SendFSState(context_t *context) { R700_CHIP_CONTEXT *r700 = R700_CONTEXT_STATES(context); - struct radeon_renderbuffer *rrb; struct radeon_bo * pbo; - offset_modifiers offset_mod; BATCH_LOCALS(&context->radeon); /* XXX fixme @@ -625,9 +669,8 @@ GLboolean r700SendFSState(context_t *context) r700->fs.SQ_PGM_CF_OFFSET_FS.u32All = 0; /* XXX */ - offset_mod.shift = NO_SHIFT; - offset_mod.shiftbits = 0; - offset_mod.mask = 0xFFFFFFFF; + if (!pbo) + return GL_FALSE; r700SyncSurf(context, pbo, RADEON_GEM_DOMAIN_GTT, 0, SH_ACTION_ENA_bit); @@ -636,7 +679,7 @@ GLboolean r700SendFSState(context_t *context) R600_OUT_BATCH_RELOC(r700->fs.SQ_PGM_START_FS.u32All, pbo, r700->fs.SQ_PGM_START_FS.u32All, - RADEON_GEM_DOMAIN_GTT, 0, 0, &offset_mod); + RADEON_GEM_DOMAIN_GTT, 0, 0); END_BATCH(); BEGIN_BATCH_NO_AUTOSTATE(6); @@ -652,8 +695,6 @@ GLboolean r700SendFSState(context_t *context) GLboolean r700SendViewportState(context_t *context, int id) { R700_CHIP_CONTEXT *r700 = R700_CONTEXT_STATES(context); - struct radeon_renderbuffer *rrb; - offset_modifiers offset_mod; BATCH_LOCALS(&context->radeon); if (id > R700_MAX_VIEWPORTS) 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 180d980442..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); @@ -262,9 +269,8 @@ void * r700GetActiveFpShaderBo(GLcontext * ctx) GLboolean r700SetupFragmentProgram(GLcontext * ctx) { context_t *context = R700_CONTEXT(ctx); - BATCH_LOCALS(&context->radeon); 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); @@ -305,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); @@ -339,7 +355,6 @@ GLboolean r700SetupFragmentProgram(GLcontext * ctx) } /* sent out shader constants. */ - paramList = fp->mesa_program.Base.Parameters; if(NULL != paramList) @@ -349,7 +364,7 @@ GLboolean r700SetupFragmentProgram(GLcontext * ctx) 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. */ @@ -369,6 +384,19 @@ GLboolean r700SetupFragmentProgram(GLcontext * ctx) } // 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) { @@ -424,5 +452,3 @@ GLboolean r700SetupFragmentProgram(GLcontext * ctx) return GL_TRUE; } - - diff --git a/src/mesa/drivers/dri/r600/r700_ioctl.c b/src/mesa/drivers/dri/r600/r700_ioctl.c index c479532001..23cc128d6d 100644 --- a/src/mesa/drivers/dri/r600/r700_ioctl.c +++ b/src/mesa/drivers/dri/r600/r700_ioctl.c @@ -43,7 +43,6 @@ static void r700Flush(GLcontext *ctx) { radeonContextPtr radeon = RADEON_CONTEXT(ctx); - context_t * context = R700_CONTEXT(ctx); if (RADEON_DEBUG & DEBUG_IOCTL) fprintf(stderr, "%s %d\n", __FUNCTION__, radeon->cmdbuf.cs->cdw); @@ -59,7 +58,7 @@ static void r700Flush(GLcontext *ctx) if (radeon->dma.flush) radeon->dma.flush( ctx ); - r700SendContextStates(context); + r700EmitState(ctx); if (radeon->cmdbuf.cs->cdw) rcommonFlushCmdBuf(radeon, __FUNCTION__); 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 4e0d5391d0..6705dbcf4b 100644 --- a/src/mesa/drivers/dri/r600/r700_render.c +++ b/src/mesa/drivers/dri/r600/r700_render.c @@ -44,7 +44,6 @@ #include "tnl/t_vertex.h" #include "tnl/t_pipeline.h" -#include "radeon_mipmap_tree.h" #include "r600_context.h" #include "r600_cmdbuf.h" @@ -58,7 +57,7 @@ void r700WaitForIdle(context_t *context); void r700WaitForIdleClean(context_t *context); void r700Start3D(context_t *context); GLboolean r700SendTextureState(context_t *context); -unsigned int r700PrimitiveType(int prim); +static unsigned int r700PrimitiveType(int prim); void r600UpdateTextureState(GLcontext * ctx); GLboolean r700SyncSurf(context_t *context, struct radeon_bo *pbo, @@ -138,68 +137,15 @@ static GLboolean r700SetupShaders(GLcontext * ctx) exportCount = (r700->ps.SQ_PGM_EXPORTS_PS.u32All & EXPORT_MODE_mask) / (1 << EXPORT_MODE_shift); r700->CB_SHADER_CONTROL.u32All = (1 << exportCount) - 1; - return GL_TRUE; -} + r600UpdateTextureState(ctx); -GLboolean r700SendTextureState(context_t *context) -{ - unsigned int i; - R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw); - offset_modifiers offset_mod = {NO_SHIFT, 0, 0xFFFFFFFF}; - struct radeon_bo *bo = NULL; - BATCH_LOCALS(&context->radeon); + r700SendFSState(context); // FIXME just a place holder for now + r700SendPSState(context); + r700SendVSState(context); + + r700SendTextureState(context); + r700SetupStreams(ctx); - for (i=0; i<R700_TEXTURE_NUMBERUNITS; i++) { - radeonTexObj *t = r700->textures[i]; - if (t) { - if (!t->image_override) - bo = t->mt->bo; - else - bo = t->bo; - if (bo) { - - r700SyncSurf(context, bo, - RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, - 0, TC_ACTION_ENA_bit); - - BEGIN_BATCH_NO_AUTOSTATE(9); - R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_RESOURCE, 7)); - R600_OUT_BATCH(i * 7); - R600_OUT_BATCH(r700->textures[i]->SQ_TEX_RESOURCE0); - R600_OUT_BATCH(r700->textures[i]->SQ_TEX_RESOURCE1); - R600_OUT_BATCH_RELOC(r700->textures[i]->SQ_TEX_RESOURCE2, - bo, - 0, - RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0, &offset_mod); - R600_OUT_BATCH_RELOC(r700->textures[i]->SQ_TEX_RESOURCE3, - bo, - 0, - RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0, &offset_mod); - R600_OUT_BATCH(r700->textures[i]->SQ_TEX_RESOURCE4); - R600_OUT_BATCH(r700->textures[i]->SQ_TEX_RESOURCE5); - R600_OUT_BATCH(r700->textures[i]->SQ_TEX_RESOURCE6); - END_BATCH(); - - BEGIN_BATCH_NO_AUTOSTATE(5); - R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_SAMPLER, 3)); - R600_OUT_BATCH(i * 3); - R600_OUT_BATCH(r700->textures[i]->SQ_TEX_SAMPLER0); - R600_OUT_BATCH(r700->textures[i]->SQ_TEX_SAMPLER1); - R600_OUT_BATCH(r700->textures[i]->SQ_TEX_SAMPLER2); - END_BATCH(); - - BEGIN_BATCH_NO_AUTOSTATE(2 + 4); - R600_OUT_BATCH_REGSEQ((TD_PS_SAMPLER0_BORDER_RED + (i * 16)), 4); - R600_OUT_BATCH(r700->textures[i]->TD_PS_SAMPLER0_BORDER_RED); - R600_OUT_BATCH(r700->textures[i]->TD_PS_SAMPLER0_BORDER_GREEN); - R600_OUT_BATCH(r700->textures[i]->TD_PS_SAMPLER0_BORDER_BLUE); - R600_OUT_BATCH(r700->textures[i]->TD_PS_SAMPLER0_BORDER_ALPHA); - END_BATCH(); - - COMMIT_BATCH(); - } - } - } return GL_TRUE; } @@ -211,17 +157,15 @@ GLboolean r700SyncSurf(context_t *context, { BATCH_LOCALS(&context->radeon); uint32_t cp_coher_size; - offset_modifiers offset_mod; + + if (!pbo) + return GL_FALSE; if (pbo->size == 0xffffffff) cp_coher_size = 0xffffffff; else cp_coher_size = ((pbo->size + 255) >> 8); - offset_mod.shift = NO_SHIFT; - offset_mod.shiftbits = 0; - offset_mod.mask = 0xFFFFFFFF; - BEGIN_BATCH_NO_AUTOSTATE(5); R600_OUT_BATCH(CP_PACKET3(R600_IT_SURFACE_SYNC, 3)); R600_OUT_BATCH(sync_type); @@ -229,7 +173,7 @@ GLboolean r700SyncSurf(context_t *context, R600_OUT_BATCH_RELOC(0, pbo, 0, - read_domain, write_domain, 0, &offset_mod); // ??? + read_domain, write_domain, 0); // ??? R600_OUT_BATCH(10); END_BATCH(); @@ -238,7 +182,7 @@ GLboolean r700SyncSurf(context_t *context, return GL_TRUE; } -unsigned int r700PrimitiveType(int prim) +static unsigned int r700PrimitiveType(int prim) { switch (prim & PRIM_MODE_MASK) { @@ -279,112 +223,110 @@ unsigned int r700PrimitiveType(int prim) } } -static GLboolean r700RunRender(GLcontext * ctx, - struct tnl_pipeline_stage *stage) +static void r700RunRenderPrimitive(GLcontext * ctx, int start, int end, int prim) { - context_t *context = R700_CONTEXT(ctx); - R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw); - int lastIndex = 0; - BATCH_LOCALS(&context->radeon); + context_t *context = R700_CONTEXT(ctx); + BATCH_LOCALS(&context->radeon); + int type, i, total_emit; + int num_indices = end - start; + uint32_t vgt_draw_initiator = 0; + uint32_t vgt_index_type = 0; + uint32_t vgt_primitive_type = 0; + uint32_t vgt_num_indices = 0; - unsigned int i, j; - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_buffer *vb = &tnl->vb; - - r700Start3D(context); /* TODO : this is too much. */ - - r700SendSQConfig(context); - - r700UpdateShaders(ctx); - - r700SetScissor(context); - r700SetRenderTarget(context, 0); - r700SetDepthTarget(context); - - if(r700SetupStreams(ctx)) - { - return GL_TRUE; - } - - r600UpdateTextureState(ctx); - r700SendTextureState(context); - - r700SetupShaders(ctx); - - r700SendFSState(context); // FIXME just a place holder for now - r700SendPSState(context); - r700SendVSState(context); + type = r700PrimitiveType(prim); - r700SendUCPState(context); - r700SendContextStates(context); - r700SendViewportState(context, 0); - r700SendRenderTargetState(context, 0); - r700SendDepthTargetState(context); + if (type < 0 || num_indices <= 0) + return; - /* richard test code */ - for (i = 0; i < vb->PrimitiveCount; i++) - { - GLuint prim = _tnl_translate_prim(&vb->Primitive[i]); - GLuint start = vb->Primitive[i].start; - GLuint end = vb->Primitive[i].start + vb->Primitive[i].count; - GLuint numIndices = vb->Primitive[i].count; - GLuint numEntires; - - unsigned int VGT_DRAW_INITIATOR = 0; - unsigned int VGT_INDEX_TYPE = 0; - unsigned int VGT_PRIMITIVE_TYPE = 0; - unsigned int VGT_NUM_INDICES = 0; - - if (numIndices < 1) - continue; - - numEntires = 3 /* VGT_PRIMITIVE_TYPE */ + total_emit = 3 /* VGT_PRIMITIVE_TYPE */ + 2 /* VGT_INDEX_TYPE */ + 2 /* NUM_INSTANCES */ - + numIndices + 3; /* DRAW_INDEX_IMMD */ - - BEGIN_BATCH_NO_AUTOSTATE(numEntires); + + num_indices + 3; /* DRAW_INDEX_IMMD */ + BEGIN_BATCH_NO_AUTOSTATE(total_emit); // prim - VGT_PRIMITIVE_TYPE |= r700PrimitiveType(prim) << VGT_PRIMITIVE_TYPE__PRIM_TYPE_shift; + SETfield(vgt_primitive_type, type, + VGT_PRIMITIVE_TYPE__PRIM_TYPE_shift, VGT_PRIMITIVE_TYPE__PRIM_TYPE_mask); R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_CONFIG_REG, 1)); R600_OUT_BATCH(mmVGT_PRIMITIVE_TYPE - ASIC_CONFIG_BASE_INDEX); - R600_OUT_BATCH(VGT_PRIMITIVE_TYPE); + R600_OUT_BATCH(vgt_primitive_type); // index type - VGT_INDEX_TYPE |= DI_INDEX_SIZE_32_BIT << INDEX_TYPE_shift; + SETfield(vgt_index_type, DI_INDEX_SIZE_32_BIT, INDEX_TYPE_shift, INDEX_TYPE_mask); R600_OUT_BATCH(CP_PACKET3(R600_IT_INDEX_TYPE, 0)); - R600_OUT_BATCH(VGT_INDEX_TYPE); + R600_OUT_BATCH(vgt_index_type); // num instances R600_OUT_BATCH(CP_PACKET3(R600_IT_NUM_INSTANCES, 0)); R600_OUT_BATCH(1); // draw packet - VGT_NUM_INDICES = numIndices; - VGT_DRAW_INITIATOR |= DI_SRC_SEL_IMMEDIATE << SOURCE_SELECT_shift; - VGT_DRAW_INITIATOR |= DI_MAJOR_MODE_0 << MAJOR_MODE_shift; + vgt_num_indices = num_indices; + SETfield(vgt_draw_initiator, DI_SRC_SEL_IMMEDIATE, SOURCE_SELECT_shift, SOURCE_SELECT_mask); + SETfield(vgt_draw_initiator, DI_MAJOR_MODE_0, MAJOR_MODE_shift, MAJOR_MODE_mask); - R600_OUT_BATCH(CP_PACKET3(R600_IT_DRAW_INDEX_IMMD, (numIndices + 1))); - R600_OUT_BATCH(VGT_NUM_INDICES); - R600_OUT_BATCH(VGT_DRAW_INITIATOR); + R600_OUT_BATCH(CP_PACKET3(R600_IT_DRAW_INDEX_IMMD, (num_indices + 1))); + R600_OUT_BATCH(vgt_num_indices); + R600_OUT_BATCH(vgt_draw_initiator); - for (j = lastIndex; j < lastIndex + numIndices; j++) - { - R600_OUT_BATCH(j); + for (i = start; i < end; i++) { + R600_OUT_BATCH(i); } - lastIndex += numIndices; - END_BATCH(); COMMIT_BATCH(); + +} + +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__); + + r700SendSQConfig(context); + + r700SendUCPState(context); + r700SendContextStates(context); + r700SendViewportState(context, 0); + r700SendRenderTargetState(context, 0); + r700SendDepthTargetState(context); + +} + +static GLboolean r700RunRender(GLcontext * ctx, + struct tnl_pipeline_stage *stage) +{ + context_t *context = R700_CONTEXT(ctx); + unsigned int i; + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *vb = &tnl->vb; + + r700Start3D(context); + + r700UpdateShaders(ctx); + r700SetScissor(context); + r700SetupShaders(ctx); + + r700EmitState(ctx); + + /* richard test code */ + for (i = 0; i < vb->PrimitiveCount; i++) { + GLuint prim = _tnl_translate_prim(&vb->Primitive[i]); + GLuint start = vb->Primitive[i].start; + GLuint end = vb->Primitive[i].start + vb->Primitive[i].count; + r700RunRenderPrimitive(ctx, start, end, prim); } /* Flush render op cached for last several quads. */ r700WaitForIdleClean(context); - radeonReleaseArrays(ctx, 0); - - rcommonFlushCmdBuf( &context->radeon, __FUNCTION__ ); + radeonReleaseArrays(ctx, ~0); return GL_FALSE; } diff --git a/src/mesa/drivers/dri/r600/r700_state.c b/src/mesa/drivers/dri/r600/r700_state.c index 87ea1719c4..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; @@ -1638,9 +1642,10 @@ static void r700InitSQConfig(GLcontext * ctx) void r700InitState(GLcontext * ctx) //------------------- { context_t *context = R700_CONTEXT(ctx); - R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw); + radeon_firevertices(&context->radeon); + r700->TA_CNTL_AUX.u32All = 0; SETfield(r700->TA_CNTL_AUX.u32All, 28, TD_FIFO_CREDIT_shift, TD_FIFO_CREDIT_mask); r700->VC_ENHANCE.u32All = 0; @@ -1756,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]); @@ -1821,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 af6a6b8c29..31e71cdfa3 100644 --- a/src/mesa/drivers/dri/r600/r700_vertprog.c +++ b/src/mesa/drivers/dri/r600/r700_vertprog.c @@ -335,17 +335,13 @@ void * r700GetActiveVpShaderBo(GLcontext * ctx) GLboolean r700SetupVertexProgram(GLcontext * ctx) { context_t *context = R700_CONTEXT(ctx); - - BATCH_LOCALS(&context->radeon); - 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) @@ -394,7 +390,6 @@ GLboolean r700SetupVertexProgram(GLcontext * ctx) */ /* sent out shader constants. */ - paramList = vp->mesa_program.Base.Parameters; if(NULL != paramList) @@ -403,8 +398,8 @@ GLboolean r700SetupVertexProgram(GLcontext * ctx) unNumParamData = paramList->NumParameters * 4; - BEGIN_BATCH_NO_AUTOSTATE(unNumParamData + 2); - + BEGIN_BATCH_NO_AUTOSTATE(unNumParamData + 2); + R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_ALU_CONST, unNumParamData)); /* assembler map const from very beginning. */ R600_OUT_BATCH(SQ_ALU_CONSTANT_VS_OFFSET * 4); 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 dde615a4d9..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 ) { @@ -887,10 +861,11 @@ void radeonUpdatePageFlipping(radeonContextPtr radeon) void radeon_window_moved(radeonContextPtr radeon) { + /* Cliprects has to be updated before doing anything else */ + radeonSetCliprects(radeon); if (!radeon->radeonScreen->driScreen->dri2.enabled) { radeonUpdatePageFlipping(radeon); } - radeonSetCliprects(radeon); } void radeon_viewport(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height) @@ -1092,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 a50cd056e1..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; @@ -241,7 +242,26 @@ GLboolean radeonInitContext(radeonContextPtr radeon, radeon->texture_depth = ( glVisual->rgbBits > 16 ) ? DRI_CONF_TEXTURE_DEPTH_32 : DRI_CONF_TEXTURE_DEPTH_16; - radeon->texture_row_align = 32; + if (IS_R600_CLASS(radeon->radeonScreen)) { + radeon->texture_row_align = 256; + radeon->texture_rect_row_align = 256; + radeon->texture_compressed_row_align = 256; + } else if (IS_R200_CLASS(radeon->radeonScreen) || + IS_R100_CLASS(radeon->radeonScreen)) { + radeon->texture_row_align = 32; + radeon->texture_rect_row_align = 64; + radeon->texture_compressed_row_align = 32; + } else { /* R300 - not sure this is all correct */ + int chip_family = radeon->radeonScreen->chip_family; + if (chip_family == CHIP_FAMILY_RS600 || + chip_family == CHIP_FAMILY_RS690 || + chip_family == CHIP_FAMILY_RS740) + radeon->texture_row_align = 64; + else + radeon->texture_row_align = 32; + radeon->texture_rect_row_align = 64; + radeon->texture_compressed_row_align = 64; + } return GL_TRUE; } @@ -275,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); @@ -287,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__ ); } @@ -743,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, @@ -765,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 0cdacb1c36..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; }; @@ -429,6 +430,8 @@ struct radeon_context { int texture_depth; float initialMaxAnisotropy; uint32_t texture_row_align; + uint32_t texture_rect_row_align; + uint32_t texture_compressed_row_align; struct radeon_dma dma; struct radeon_hw_state hw; @@ -443,7 +446,6 @@ struct radeon_context { GLuint numClipRects; /* Cliprects for the draw buffer */ drm_clip_rect_t *pClipRects; unsigned int lastStamp; - GLboolean lost_context; drm_radeon_sarea_t *sarea; /* Private SAREA data */ /* Mirrors of some DRI state */ 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 5774f7ebcf..6294b7e42b 100644 --- a/src/mesa/drivers/dri/radeon/radeon_lock.c +++ b/src/mesa/drivers/dri/radeon/radeon_lock.c @@ -85,11 +85,35 @@ void radeonGetLock(radeonContextPtr rmesa, GLuint flags) } rmesa->vtbl.get_lock(rmesa); - - rmesa->lost_context = GL_TRUE; } - -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; @@ -104,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 f04a07fecd..d4082bf68f 100644 --- a/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c +++ b/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c @@ -90,16 +90,18 @@ static void compute_tex_image_offset(radeonContextPtr rmesa, radeon_mipmap_tree GLuint face, GLuint level, GLuint* curOffset) { radeon_mipmap_level *lvl = &mt->levels[level]; - uint32_t row_align = rmesa->texture_row_align - 1; + uint32_t row_align; /* Find image size in bytes */ if (mt->compressed) { /* TODO: Is this correct? Need test cases for compressed textures! */ - lvl->rowstride = (lvl->width * mt->bpp + 63) & ~63; + row_align = rmesa->texture_compressed_row_align - 1; + lvl->rowstride = (lvl->width * mt->bpp + row_align) & ~row_align; lvl->size = radeon_compressed_texture_size(mt->radeon->glCtx, lvl->width, lvl->height, lvl->depth, mt->compressed); } else if (mt->target == GL_TEXTURE_RECTANGLE_NV) { - lvl->rowstride = (lvl->width * mt->bpp + 63) & ~63; + row_align = rmesa->texture_rect_row_align - 1; + lvl->rowstride = (lvl->width * mt->bpp + row_align) & ~row_align; lvl->size = lvl->rowstride * lvl->height; } else if (mt->tilebits & RADEON_TXO_MICRO_TILE) { /* tile pattern is 16 bytes x2. mipmaps stay 32 byte aligned, @@ -108,6 +110,7 @@ static void compute_tex_image_offset(radeonContextPtr rmesa, radeon_mipmap_tree lvl->rowstride = (lvl->width * mt->bpp * 2 + 31) & ~31; lvl->size = lvl->rowstride * ((lvl->height + 1) / 2) * lvl->depth; } else { + row_align = rmesa->texture_row_align - 1; lvl->rowstride = (lvl->width * mt->bpp + row_align) & ~row_align; lvl->size = lvl->rowstride * lvl->height * lvl->depth; } @@ -323,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 && @@ -363,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 ad501c454c..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; @@ -951,7 +968,7 @@ int radeon_validate_texture_miptree(GLcontext * ctx, struct gl_texture_object *t fprintf(stderr, " Allocate new miptree\n"); radeon_try_alloc_miptree(rmesa, t, &baseimage->base, 0, texObj->BaseLevel); if (!t->mt) { - _mesa_problem(ctx, "r300_validate_texture failed to alloc miptree"); + _mesa_problem(ctx, "radeon_validate_texture failed to alloc miptree"); return GL_FALSE; } } @@ -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_validate.c b/src/mesa/main/api_validate.c index b2f11ffbfe..33f4dd152a 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); @@ -164,7 +165,7 @@ _mesa_validate_DrawElements(GLcontext *ctx, 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) { @@ -237,7 +238,7 @@ _mesa_validate_DrawRangeElements(GLcontext *ctx, GLenum mode, 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) { 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/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..4133f15dc7 100644 --- a/src/mesa/main/dlist.c +++ b/src/mesa/main/dlist.c @@ -690,7 +690,7 @@ unpack_image(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); 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..ab91fbc4de 100644 --- a/src/mesa/main/fbobject.c +++ b/src/mesa/main/fbobject.c @@ -2038,7 +2038,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 +2050,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/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..e0e8548d7c 100644 --- a/src/mesa/main/image.c +++ b/src/mesa/main/image.c @@ -5335,3 +5335,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..ee17accb80 100644 --- a/src/mesa/main/image.h +++ b/src/mesa/main/image.h @@ -291,4 +291,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/mtypes.h b/src/mesa/main/mtypes.h index da01c58c2d..6a60ad1cee 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; @@ -2005,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; @@ -2982,6 +2984,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/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..5557b694e3 100644 --- a/src/mesa/main/texgetimage.c +++ b/src/mesa/main/texgetimage.c @@ -30,6 +30,7 @@ #include "glheader.h" +#include "bufferobj.h" #include "context.h" #include "image.h" #include "texcompress.h" @@ -116,7 +117,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 +297,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 +317,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,7 +350,7 @@ _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); } diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c index 6e21066537..c758462a46 100644 --- a/src/mesa/main/teximage.c +++ b/src/mesa/main/teximage.c @@ -1,6 +1,6 @@ /* * mesa 3-D graphics library - * Version: 7.5 + * Version: 7.6 * * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. * Copyright (C) 2009 VMware, Inc. All Rights Reserved. @@ -679,37 +679,14 @@ _mesa_set_tex_image(struct gl_texture_object *tObj, GLenum target, GLint level, struct gl_texture_image *texImage) { + const GLuint face = _mesa_tex_target_to_face(target); + ASSERT(tObj); ASSERT(texImage); - /* XXX simplify this with _mesa_tex_target_to_face() */ - switch (target) { - case GL_TEXTURE_1D: - case GL_TEXTURE_2D: - case GL_TEXTURE_3D: - case GL_TEXTURE_1D_ARRAY_EXT: - case GL_TEXTURE_2D_ARRAY_EXT: - tObj->Image[0][level] = texImage; - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: - { - GLuint face = ((GLuint) target - - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X); - tObj->Image[face][level] = texImage; - } - break; - case GL_TEXTURE_RECTANGLE_NV: - ASSERT(level == 0); - tObj->Image[0][level] = texImage; - break; - default: - _mesa_problem(NULL, "bad target in _mesa_set_tex_image()"); - return; - } + ASSERT(target != GL_TEXTURE_RECTANGLE_NV || level == 0); + + tObj->Image[face][level] = texImage; + /* Set the 'back' pointer */ texImage->TexObject = tObj; } @@ -788,6 +765,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 || @@ -799,6 +779,18 @@ _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. @@ -864,74 +856,28 @@ _mesa_select_tex_object(GLcontext *ctx, const struct gl_texture_unit *texUnit, /** - * Get the texture image struct which corresponds to target and level - * of the given texture unit. + * Get a texture image pointer from a texture object, given a texture + * target and mipmap level. The target and level parameters should + * have already been error-checked. * * \param ctx GL context. * \param texObj texture unit. * \param target texture target. * \param level image level. * - * \return pointer to the texture image structure on success, or NULL on failure. - * - * \sa gl_texture_unit. + * \return pointer to the texture image structure, or NULL on failure. */ struct gl_texture_image * _mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_object *texObj, GLenum target, GLint level) { - ASSERT(texObj); - - if (level < 0 || level >= MAX_TEXTURE_LEVELS) - return NULL; - - /* XXX simplify this with _mesa_tex_target_to_face() */ - switch (target) { - case GL_TEXTURE_1D: - case GL_PROXY_TEXTURE_1D: - case GL_TEXTURE_2D: - case GL_PROXY_TEXTURE_2D: - case GL_TEXTURE_3D: - case GL_PROXY_TEXTURE_3D: - return texObj->Image[0][level]; - - case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: - if (ctx->Extensions.ARB_texture_cube_map) { - GLuint face = ((GLuint) target - - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X); - return texObj->Image[face][level]; - } - else - return NULL; - - case GL_PROXY_TEXTURE_CUBE_MAP_ARB: - if (ctx->Extensions.ARB_texture_cube_map) - return texObj->Image[0][level]; - else - return NULL; - - case GL_TEXTURE_RECTANGLE_NV: - case GL_PROXY_TEXTURE_RECTANGLE_NV: - if (ctx->Extensions.NV_texture_rectangle && level == 0) - return texObj->Image[0][level]; - else - return NULL; + const GLuint face = _mesa_tex_target_to_face(target); - 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) - ? texObj->Image[0][level] : NULL; + ASSERT(texObj); + ASSERT(level >= 0); + ASSERT(level < MAX_TEXTURE_LEVELS); - default: - return NULL; - } + return texObj->Image[face][level]; } @@ -1273,6 +1219,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. * @@ -1926,14 +1889,14 @@ copytexture_error_check( GLcontext *ctx, GLuint dimensions, return GL_TRUE; } - /* NOTE: the format and type aren't really significant for - * TestProxyTexImage(). Only the internalformat really matters. if (!_mesa_source_buffer_exists(ctx, format)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyTexImage%dD(missing readbuffer)", dimensions); return GL_TRUE; } + /* NOTE: the format and type aren't really significant for + * TestProxyTexImage(). Only the internalformat really matters. */ type = GL_FLOAT; @@ -2261,142 +2224,165 @@ copytexsubimage_error_check2( GLcontext *ctx, GLuint dimensions, /** - * 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. + * Do error checking for a glGetTexImage() call. + * \return GL_TRUE if any error, GL_FALSE if no errors. */ -void GLAPIENTRY -_mesa_GetTexImage( GLenum target, GLint level, GLenum format, - GLenum type, GLvoid *pixels ) +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; - GLint maxLevels = 0; - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); - - texUnit = &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]); - texObj = _mesa_select_tex_object(ctx, texUnit, target); - if (!texObj || _mesa_is_proxy_texture(target)) { - _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)"); - return; - } + const GLuint maxLevels = _mesa_max_texture_levels(ctx, target); - 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; + return GL_TRUE; } if (_mesa_sizeof_packed_type(type) <= 0) { _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" ); - return; + return GL_TRUE; } if (_mesa_components_in_format(format) <= 0 || format == GL_STENCIL_INDEX) { _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" ); - return; + return GL_TRUE; } if (!ctx->Extensions.EXT_paletted_texture && is_index_format(format)) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); - return; + return GL_TRUE; } if (!ctx->Extensions.ARB_depth_texture && is_depth_format(format)) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); - return; + return GL_TRUE; } if (!ctx->Extensions.MESA_ycbcr_texture && is_ycbcr_format(format)) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); - return; + return GL_TRUE; } if (!ctx->Extensions.EXT_packed_depth_stencil && is_depthstencil_format(format)) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); - return; + return GL_TRUE; } if (!ctx->Extensions.ATI_envmap_bumpmap && is_dudv_format(format)) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); - return; + return GL_TRUE; } - _mesa_lock_texture(ctx, texObj); - { - texImage = _mesa_select_tex_image(ctx, texObj, target, level); - if (!texImage) { - /* invalid mipmap level, not an error */ - goto out; - } + 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 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)"); - goto out; - } - else if (is_index_format(format) - && !is_index_format(texImage->TexFormat->BaseFormat)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); - goto out; - } - 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)"); - goto out; - } - else if (is_ycbcr_format(format) - && !is_ycbcr_format(texImage->TexFormat->BaseFormat)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); - goto out; - } - else if (is_depthstencil_format(format) - && !is_depthstencil_format(texImage->TexFormat->BaseFormat)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); - goto out; - } - else if (is_dudv_format(format) - && !is_dudv_format(texImage->TexFormat->BaseFormat)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); - goto out; - } + 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)"); - goto out; - } + 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 = 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); - + texObj, texImage); } - out: _mesa_unlock_texture(ctx, texObj); } @@ -2544,7 +2530,7 @@ _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat, if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) _mesa_update_state(ctx); - texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texUnit = get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); { @@ -2652,7 +2638,7 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat, if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) _mesa_update_state(ctx); - texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texUnit = get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); { @@ -2755,7 +2741,7 @@ _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat, if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) _mesa_update_state(ctx); - texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texUnit = get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); { @@ -2861,7 +2847,7 @@ _mesa_TexSubImage1D( GLenum target, GLint level, } - texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texUnit = get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); assert(texObj); @@ -2921,7 +2907,7 @@ _mesa_TexSubImage2D( GLenum target, GLint level, return; /* error was detected */ } - texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texUnit = get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); { @@ -2973,7 +2959,7 @@ _mesa_TexSubImage3D( GLenum target, GLint level, return; /* error was detected */ } - texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texUnit = get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); @@ -3034,7 +3020,7 @@ _mesa_CopyTexImage1D( GLenum target, GLint level, postConvWidth, 1, border)) return; - texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texUnit = get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); { @@ -3100,7 +3086,7 @@ _mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat, postConvWidth, postConvHeight, border)) return; - texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texUnit = get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); @@ -3160,7 +3146,7 @@ _mesa_CopyTexSubImage1D( GLenum target, GLint level, if (copytexsubimage_error_check1(ctx, 1, target, level)) return; - texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texUnit = get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); @@ -3215,7 +3201,7 @@ _mesa_CopyTexSubImage2D( GLenum target, GLint level, if (copytexsubimage_error_check1(ctx, 2, target, level)) return; - texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texUnit = get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); @@ -3270,7 +3256,7 @@ _mesa_CopyTexSubImage3D( GLenum target, GLint level, if (copytexsubimage_error_check1(ctx, 3, target, level)) return; - texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texUnit = get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); @@ -3524,7 +3510,7 @@ _mesa_CompressedTexImage1DARB(GLenum target, GLint level, return; } - texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texUnit = get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); @@ -3578,7 +3564,7 @@ _mesa_CompressedTexImage1DARB(GLenum target, GLint level, struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; struct gl_texture_image *texImage; - texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texUnit = get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); @@ -3621,7 +3607,7 @@ _mesa_CompressedTexImage2DARB(GLenum target, GLint level, return; } - texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texUnit = get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); @@ -3677,7 +3663,7 @@ _mesa_CompressedTexImage2DARB(GLenum target, GLint level, struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; struct gl_texture_image *texImage; - texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texUnit = get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); @@ -3717,7 +3703,7 @@ _mesa_CompressedTexImage3DARB(GLenum target, GLint level, return; } - texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texUnit = get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); { @@ -3771,7 +3757,7 @@ _mesa_CompressedTexImage3DARB(GLenum target, GLint level, struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; struct gl_texture_image *texImage; - texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texUnit = get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); { @@ -3810,7 +3796,7 @@ _mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset, return; } - texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texUnit = get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); { @@ -3867,7 +3853,7 @@ _mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset, return; } - texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texUnit = get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); { @@ -3924,7 +3910,7 @@ _mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset, return; } - texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texUnit = get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); { @@ -3971,7 +3957,7 @@ _mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); - texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texUnit = get_current_tex_unit(ctx); texObj = _mesa_select_tex_object(ctx, texUnit, target); if (!texObj) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB"); diff --git a/src/mesa/main/teximage.h b/src/mesa/main/teximage.h index eb60a1fa8f..b0d7c1c3aa 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); diff --git a/src/mesa/main/texobj.c b/src/mesa/main/texobj.c index 2082f945f1..22657ed81b 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. */ @@ -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/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/shader/arbprogparse.c b/src/mesa/shader/arbprogparse.c index f428ee541b..381445c0e8 100644 --- a/src/mesa/shader/arbprogparse.c +++ b/src/mesa/shader/arbprogparse.c @@ -2027,6 +2027,7 @@ parse_param (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head, if (specified_length != (int)param_var->param_binding_length) { program_error(ctx, Program->Position, "Declared parameter array length does not match parameter list"); + return 1; } } diff --git a/src/mesa/shader/prog_print.c b/src/mesa/shader/prog_print.c index cef0288a9c..20d3fdec47 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"); diff --git a/src/mesa/shader/shader_api.c b/src/mesa/shader/shader_api.c index 648fbc186b..9cfc6dd81c 100644 --- a/src/mesa/shader/shader_api.c +++ b/src/mesa/shader/shader_api.c @@ -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..9ed8e3ecb3 100644 --- a/src/mesa/shader/slang/slang_builtin.c +++ b/src/mesa/shader/slang/slang_builtin.c @@ -710,3 +710,187 @@ _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_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 4fe68eafa7..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_PointCoord", FRAG_ATTRIB_PNTC, SWIZZLE_XYZW }, - { "gl_FrontFacing", FRAG_ATTRIB_FACE, SWIZZLE_XXXX }, - { 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 6c19fc895b..c5c94a65a2 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), + 1, /* size */ + _slang_vert_attrib_type(i), + -1 /* attrib/input */); + } + } + return GL_TRUE; } 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_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_clear.c b/src/mesa/state_tracker/st_cb_clear.c index 668acbccb8..8a8c99f7e1 100644 --- a/src/mesa/state_tracker/st_cb_clear.c +++ b/src/mesa/state_tracker/st_cb_clear.c @@ -280,7 +280,11 @@ clear_with_quad(GLcontext *ctx, static INLINE GLboolean check_clear_color_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb) { - if (ctx->Scissor.Enabled) + if (ctx->Scissor.Enabled && + (ctx->Scissor.X != 0 || + ctx->Scissor.Y != 0 || + ctx->Scissor.Width < rb->Width || + ctx->Scissor.Height < rb->Height)) return TRUE; if (!ctx->Color.ColorMask[0] || @@ -300,7 +304,11 @@ check_clear_depth_stencil_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb) GLboolean maskStencil = (ctx->Stencil.WriteMask[0] & stencilMax) != stencilMax; - if (ctx->Scissor.Enabled) + if (ctx->Scissor.Enabled && + (ctx->Scissor.X != 0 || + ctx->Scissor.Y != 0 || + ctx->Scissor.Width < rb->Width || + ctx->Scissor.Height < rb->Height)) return TRUE; if (maskStencil) @@ -319,7 +327,11 @@ check_clear_depth_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb) const struct st_renderbuffer *strb = st_renderbuffer(rb); const GLboolean isDS = pf_is_depth_and_stencil(strb->surface->format); - if (ctx->Scissor.Enabled) + if (ctx->Scissor.Enabled && + (ctx->Scissor.X != 0 || + ctx->Scissor.Y != 0 || + ctx->Scissor.Width < rb->Width || + ctx->Scissor.Height < rb->Height)) return TRUE; if (isDS && @@ -345,7 +357,11 @@ check_clear_stencil_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb) if (maskStencil) return TRUE; - if (ctx->Scissor.Enabled) + if (ctx->Scissor.Enabled && + (ctx->Scissor.X != 0 || + ctx->Scissor.Y != 0 || + ctx->Scissor.Width < rb->Width || + ctx->Scissor.Height < rb->Height)) return TRUE; /* This is correct, but it is necessary to look at the depth clear diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c index 8b5094a04f..d19a88fa7c 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/src/mesa/state_tracker/st_cb_drawpixels.c @@ -60,6 +60,7 @@ #include "pipe/p_inlines.h" #include "util/u_tile.h" #include "util/u_draw_quad.h" +#include "util/u_math.h" #include "shader/prog_instruction.h" #include "cso_cache/cso_context.h" @@ -341,6 +342,7 @@ make_texture(struct st_context *st, enum pipe_format pipeFormat; GLuint cpp; GLenum baseFormat; + int ptw, pth; baseFormat = _mesa_base_format(format); @@ -355,7 +357,28 @@ make_texture(struct st_context *st, if (!pixels) return NULL; - pt = st_texture_create(st, PIPE_TEXTURE_2D, pipeFormat, 0, width, height, 1, + /* Need to use POT texture? */ + ptw = width; + pth = height; + if (!screen->get_param(screen, PIPE_CAP_NPOT_TEXTURES)) { + int l2pt, maxSize; + + l2pt = util_logbase2(width); + if (1<<l2pt != width) { + ptw = 1<<(l2pt+1); + } + l2pt = util_logbase2(height); + if (1<<l2pt != height) { + pth = 1<<(l2pt+1); + } + + /* Check against maximum texture size */ + maxSize = 1 << (pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1); + assert(ptw <= maxSize); + assert(pth <= maxSize); + } + + pt = st_texture_create(st, PIPE_TEXTURE_2D, pipeFormat, 0, ptw, pth, 1, PIPE_TEXTURE_USAGE_SAMPLER); if (!pt) { _mesa_unmap_drawpix_pbo(ctx, unpack); @@ -420,7 +443,7 @@ make_texture(struct st_context *st, static void draw_quad(GLcontext *ctx, GLfloat x0, GLfloat y0, GLfloat z, GLfloat x1, GLfloat y1, const GLfloat *color, - GLboolean invertTex) + GLboolean invertTex, GLfloat maxXcoord, GLfloat maxYcoord) { struct st_context *st = ctx->st; struct pipe_context *pipe = ctx->st->pipe; @@ -435,8 +458,9 @@ draw_quad(GLcontext *ctx, GLfloat x0, GLfloat y0, GLfloat z, const GLfloat clip_y0 = y0 / fb_height * 2.0f - 1.0f; const GLfloat clip_x1 = x1 / fb_width * 2.0f - 1.0f; const GLfloat clip_y1 = y1 / fb_height * 2.0f - 1.0f; - const GLfloat sLeft = 0.0f, sRight = 1.0f; - const GLfloat tTop = invertTex, tBot = 1.0f - tTop; + const GLfloat sLeft = 0.0f, sRight = maxXcoord; + const GLfloat tTop = invertTex ? maxYcoord : 0.0f; + const GLfloat tBot = invertTex ? 0.0f : maxYcoord; GLuint tex, i; /* upper-left */ @@ -608,7 +632,9 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z, y0 = (GLfloat) y; y1 = y + height * ctx->Pixel.ZoomY; - draw_quad(ctx, x0, y0, z, x1, y1, color, invertTex); + draw_quad(ctx, x0, y0, z, x1, y1, color, invertTex, + (GLfloat) width / pt->width[0], + (GLfloat) height / pt->height[0]); /* restore state */ cso_restore_rasterizer(cso); @@ -648,7 +674,7 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y, usage = PIPE_TRANSFER_READ_WRITE; else usage = PIPE_TRANSFER_WRITE; - + pt = st_cond_flush_get_tex_transfer(st_context(ctx), strb->texture, 0, 0, 0, usage, x, y, width, height); @@ -778,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); @@ -807,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 ); } @@ -841,7 +865,7 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy, usage = PIPE_TRANSFER_READ_WRITE; else usage = PIPE_TRANSFER_WRITE; - + ptDraw = st_cond_flush_get_tex_transfer(st_context(ctx), rbDraw->texture, 0, 0, 0, usage, dstx, dsty, @@ -849,7 +873,7 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy, assert(ptDraw->block.width == 1); assert(ptDraw->block.height == 1); - + /* map the stencil buffer */ drawMap = screen->transfer_map(screen, ptDraw); @@ -923,6 +947,7 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, struct pipe_texture *pt; GLfloat *color; enum pipe_format srcFormat, texFormat; + int ptw, pth; pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); @@ -1004,13 +1029,34 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, height -= -srcy; srcy = 0; } - + if (height < 0) return; } + /* Need to use POT texture? */ + ptw = width; + pth = height; + if (!screen->get_param(screen, PIPE_CAP_NPOT_TEXTURES)) { + int l2pt, maxSize; + + l2pt = util_logbase2(width); + if (1<<l2pt != width) { + ptw = 1<<(l2pt+1); + } + l2pt = util_logbase2(height); + if (1<<l2pt != height) { + pth = 1<<(l2pt+1); + } + + /* Check against maximum texture size */ + maxSize = 1 << (pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1); + assert(ptw <= maxSize); + assert(pth <= maxSize); + } + pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, texFormat, 0, - width, height, 1, + ptw, pth, 1, PIPE_TEXTURE_USAGE_SAMPLER); if (!pt) return; diff --git a/src/mesa/state_tracker/st_cb_fbo.c b/src/mesa/state_tracker/st_cb_fbo.c index ecdb988033..a96602878e 100644 --- a/src/mesa/state_tracker/st_cb_fbo.c +++ b/src/mesa/state_tracker/st_cb_fbo.c @@ -446,6 +446,35 @@ st_finish_render_texture(GLcontext *ctx, /** + * Validate a renderbuffer attachment for a particular usage. + */ + +static GLboolean +st_validate_attachment(struct pipe_screen *screen, + const struct gl_renderbuffer_attachment *att, + GLuint usage) +{ + const struct st_texture_object *stObj = + st_texture_object(att->Texture); + + /** + * Only validate texture attachments for now, since + * st_renderbuffer_alloc_storage makes sure that + * the format is supported. + */ + + if (att->Type != GL_TEXTURE) + return GL_TRUE; + + if (!stObj) + return GL_FALSE; + + return screen->is_format_supported(screen, stObj->pt->format, + PIPE_TEXTURE_2D, + usage, 0); +} + +/** * Check that the framebuffer configuration is valid in terms of what * the driver can support. * @@ -454,13 +483,37 @@ st_finish_render_texture(GLcontext *ctx, static void st_validate_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb) { + struct pipe_screen *screen = ctx->st->pipe->screen; const struct gl_renderbuffer *depthRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer; const struct gl_renderbuffer *stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer; + GLuint i; if (stencilRb && depthRb && stencilRb != depthRb) { fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; + return; + } + + if (!st_validate_attachment(screen, + &fb->Attachment[BUFFER_DEPTH], + PIPE_TEXTURE_USAGE_DEPTH_STENCIL)) { + fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; + return; + } + if (!st_validate_attachment(screen, + &fb->Attachment[BUFFER_STENCIL], + PIPE_TEXTURE_USAGE_DEPTH_STENCIL)) { + fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; + return; + } + for (i = 0; i < ctx->Const.MaxColorAttachments; i++) { + if (!st_validate_attachment(screen, + &fb->Attachment[BUFFER_COLOR0 + i], + PIPE_TEXTURE_USAGE_RENDER_TARGET)) { + fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; + return; + } } } diff --git a/src/mesa/state_tracker/st_cb_flush.c b/src/mesa/state_tracker/st_cb_flush.c index 8ceeeabcd3..1329f807bc 100644 --- a/src/mesa/state_tracker/st_cb_flush.c +++ b/src/mesa/state_tracker/st_cb_flush.c @@ -161,4 +161,16 @@ void st_init_flush_functions(struct dd_function_table *functions) { functions->Flush = st_glFlush; functions->Finish = st_glFinish; + + /* Windows opengl32.dll calls glFinish prior to every swapbuffers. + * This is unnecessary and degrades performance. Luckily we have some + * scope to work around this, as the externally-visible behaviour of + * Finish() is identical to Flush() in all cases - no differences in + * rendering or ReadPixels are visible if we opt not to wait here. + * + * Only set this up on windows to avoid suprise elsewhere. + */ +#ifdef PIPE_OS_WINDOWS + functions->Finish = st_glFlush; +#endif } 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 ee71c012c6..90a059ca69 100644 --- a/src/mesa/state_tracker/st_cb_texture.c +++ b/src/mesa/state_tracker/st_cb_texture.c @@ -59,6 +59,7 @@ #include "util/u_tile.h" #include "util/u_blit.h" #include "util/u_surface.h" +#include "util/u_math.h" #define DBG if (0) printf @@ -237,16 +238,6 @@ do_memcpy(void *dest, const void *src, size_t n) } -static INLINE unsigned -logbase2(unsigned n) -{ - unsigned log2 = 0; - while (n >>= 1) - ++log2; - return log2; -} - - /** * Return default texture usage bitmask for the given texture format. */ @@ -340,9 +331,9 @@ guess_and_alloc_texture(struct st_context *st, lastLevel = firstLevel; } else { - GLuint l2width = logbase2(width); - GLuint l2height = logbase2(height); - GLuint l2depth = logbase2(depth); + GLuint l2width = util_logbase2(width); + GLuint l2height = util_logbase2(height); + GLuint l2depth = util_logbase2(depth); lastLevel = firstLevel + MAX2(MAX2(l2width, l2height), l2depth); } @@ -532,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_format.c b/src/mesa/state_tracker/st_format.c index b243c249e3..dcb90a3107 100644 --- a/src/mesa/state_tracker/st_format.c +++ b/src/mesa/state_tracker/st_format.c @@ -435,10 +435,10 @@ st_choose_format(struct pipe_context *pipe, GLenum internalFormat, case GL_RGB5: case GL_RGB4: case GL_R3_G3_B2: - if (screen->is_format_supported( screen, PIPE_FORMAT_A1R5G5B5_UNORM, target, tex_usage, geom_flags )) - return PIPE_FORMAT_A1R5G5B5_UNORM; if (screen->is_format_supported( screen, PIPE_FORMAT_R5G6B5_UNORM, target, tex_usage, geom_flags )) return PIPE_FORMAT_R5G6B5_UNORM; + if (screen->is_format_supported( screen, PIPE_FORMAT_A1R5G5B5_UNORM, target, tex_usage, geom_flags )) + return PIPE_FORMAT_A1R5G5B5_UNORM; return default_rgba_format( screen, target, tex_usage, geom_flags ); case GL_ALPHA: diff --git a/src/mesa/state_tracker/st_mesa_to_tgsi.c b/src/mesa/state_tracker/st_mesa_to_tgsi.c index 210ca82c42..2ab12d3cf3 100644 --- a/src/mesa/state_tracker/st_mesa_to_tgsi.c +++ b/src/mesa/state_tracker/st_mesa_to_tgsi.c @@ -137,12 +137,6 @@ map_texture_target( GLuint textarget, GLboolean shadow ) { -#if 1 - /* XXX remove this line after we've checked that the rest of gallium - * can handle the TGSI_TEXTURE_SHADOWx tokens. - */ - shadow = GL_FALSE; -#endif switch( textarget ) { case TEXTURE_1D_INDEX: if (shadow) @@ -353,7 +347,7 @@ compile_instruction( fullinst->Instruction.Opcode = TGSI_OPCODE_ADD; break; case OPCODE_BGNLOOP: - fullinst->Instruction.Opcode = TGSI_OPCODE_BGNLOOP2; + fullinst->Instruction.Opcode = TGSI_OPCODE_BGNLOOP; fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size; break; case OPCODE_BGNSUB: @@ -411,7 +405,7 @@ compile_instruction( fullinst->Instruction.Opcode = TGSI_OPCODE_ENDIF; break; case OPCODE_ENDLOOP: - fullinst->Instruction.Opcode = TGSI_OPCODE_ENDLOOP2; + fullinst->Instruction.Opcode = TGSI_OPCODE_ENDLOOP; fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size; break; case OPCODE_ENDSUB: 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/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/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_array.c b/src/mesa/vbo/vbo_exec_array.c index f4b9b2f744..ddf6ca1e07 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); @@ -500,7 +520,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,53 +586,19 @@ 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) @@ -623,13 +609,13 @@ vbo_exec_DrawRangeElements(GLenum mode, 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 +659,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 + + vbo_validated_drawrangeelements(ctx, mode, GL_TRUE, start, end, + count, type, indices); +} - get_minmax_index(count, type, ADD_POINTERS(map, indices), - &min_index, &max_index); - ctx->Driver.UnmapBuffer(ctx, - GL_ELEMENT_ARRAY_BUFFER_ARB, - ctx->Array.ElementArrayBufferObj); - } - else { - get_minmax_index(count, type, indices, &min_index, &max_index); - } +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_exec_DrawRangeElements(mode, min_index, max_index, count, type, indices); + 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 266bc56c82..da84eaa6ea 100644 --- a/src/mesa/vbo/vbo_split_inplace.c +++ b/src/mesa/vbo/vbo_split_inplace.c @@ -59,11 +59,11 @@ struct split_context { static void flush_vertex( struct split_context *split ) { GLuint min_index, max_index; + GLuint i; if (!split->dstprim_nr) return; - GLuint i; min_index = split->dstprim[0].start; max_index = min_index + split->dstprim[0].count - 1; @@ -85,6 +85,7 @@ static void flush_vertex( struct split_context *split ) split->dstprim, split->dstprim_nr, NULL, + GL_TRUE, min_index, max_index); |