14006c5e4526a1cdb910500764590e39d32750967Brian Paul/************************************************************************** 24006c5e4526a1cdb910500764590e39d32750967Brian Paul * 34006c5e4526a1cdb910500764590e39d32750967Brian Paul * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. 44006c5e4526a1cdb910500764590e39d32750967Brian Paul * All Rights Reserved. 54006c5e4526a1cdb910500764590e39d32750967Brian Paul * 64006c5e4526a1cdb910500764590e39d32750967Brian Paul * Permission is hereby granted, free of charge, to any person obtaining a 74006c5e4526a1cdb910500764590e39d32750967Brian Paul * copy of this software and associated documentation files (the 84006c5e4526a1cdb910500764590e39d32750967Brian Paul * "Software"), to deal in the Software without restriction, including 94006c5e4526a1cdb910500764590e39d32750967Brian Paul * without limitation the rights to use, copy, modify, merge, publish, 104006c5e4526a1cdb910500764590e39d32750967Brian Paul * distribute, sub license, and/or sell copies of the Software, and to 114006c5e4526a1cdb910500764590e39d32750967Brian Paul * permit persons to whom the Software is furnished to do so, subject to 124006c5e4526a1cdb910500764590e39d32750967Brian Paul * the following conditions: 134006c5e4526a1cdb910500764590e39d32750967Brian Paul * 144006c5e4526a1cdb910500764590e39d32750967Brian Paul * The above copyright notice and this permission notice (including the 154006c5e4526a1cdb910500764590e39d32750967Brian Paul * next paragraph) shall be included in all copies or substantial portions 164006c5e4526a1cdb910500764590e39d32750967Brian Paul * of the Software. 174006c5e4526a1cdb910500764590e39d32750967Brian Paul * 184006c5e4526a1cdb910500764590e39d32750967Brian Paul * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 194006c5e4526a1cdb910500764590e39d32750967Brian Paul * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 204006c5e4526a1cdb910500764590e39d32750967Brian Paul * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 214006c5e4526a1cdb910500764590e39d32750967Brian Paul * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 224006c5e4526a1cdb910500764590e39d32750967Brian Paul * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 234006c5e4526a1cdb910500764590e39d32750967Brian Paul * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 244006c5e4526a1cdb910500764590e39d32750967Brian Paul * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 254006c5e4526a1cdb910500764590e39d32750967Brian Paul * 264006c5e4526a1cdb910500764590e39d32750967Brian Paul **************************************************************************/ 274006c5e4526a1cdb910500764590e39d32750967Brian Paul 2845a56e4730a74a012ad712fd9b6013d900b04742Vinson Lee#include "main/mfeatures.h" 29e4394fb19f735da3fad9340653637bbe54778069Brian Paul#include "main/version.h" 3045a56e4730a74a012ad712fd9b6013d900b04742Vinson Lee 314006c5e4526a1cdb910500764590e39d32750967Brian Paul#include "intel_chipset.h" 324006c5e4526a1cdb910500764590e39d32750967Brian Paul#include "intel_context.h" 334006c5e4526a1cdb910500764590e39d32750967Brian Paul#include "intel_extensions.h" 34f0159018d7709b57d9916575512d75cb3f2fb395Eric Anholt#include "intel_reg.h" 3517ef1f6074d6107c167f1956a5c60993904c0b72Chia-I Wu#include "utils.h" 364006c5e4526a1cdb910500764590e39d32750967Brian Paul 374006c5e4526a1cdb910500764590e39d32750967Brian Paul/** 384006c5e4526a1cdb910500764590e39d32750967Brian Paul * Initializes potential list of extensions if ctx == NULL, or actually enables 394006c5e4526a1cdb910500764590e39d32750967Brian Paul * extensions for a context. 404006c5e4526a1cdb910500764590e39d32750967Brian Paul */ 414006c5e4526a1cdb910500764590e39d32750967Brian Paulvoid 42f9995b30756140724f41daf963fa06167912be7fKristian HøgsbergintelInitExtensions(struct gl_context *ctx) 434006c5e4526a1cdb910500764590e39d32750967Brian Paul{ 44b6b753f72728b734fc9886f4ec513ae09e6b269dIan Romanick struct intel_context *intel = intel_context(ctx); 454006c5e4526a1cdb910500764590e39d32750967Brian Paul 4671ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.ARB_draw_elements_base_vertex = true; 4771ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.ARB_explicit_attrib_location = true; 481fea3df6f4455fd2047e631d4d3c85d3ff1029aeJordan Justen if (_mesa_is_desktop_gl(ctx)) 4988128516d43be5d25288ff5b64db63cda83c04b3Kenneth Graunke ctx->Extensions.ARB_framebuffer_object = true; 5071ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.ARB_half_float_pixel = true; 5171ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.ARB_map_buffer_range = true; 5271ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.ARB_point_sprite = true; 5371ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.ARB_shader_objects = true; 5471ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.ARB_shading_language_100 = true; 5571ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.ARB_sync = true; 5671ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.ARB_texture_border_clamp = true; 5771ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.ARB_texture_cube_map = true; 5871ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.ARB_texture_env_combine = true; 5971ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.ARB_texture_env_crossbar = true; 6071ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.ARB_texture_env_dot3 = true; 619bcb9fad65f0926d665317d6830e9812baafcf86Ian Romanick ctx->Extensions.ARB_texture_storage = true; 6271ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.ARB_vertex_program = true; 6371ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.ARB_vertex_shader = true; 6471ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.EXT_blend_color = true; 6571ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.EXT_blend_equation_separate = true; 6671ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.EXT_blend_func_separate = true; 6771ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.EXT_blend_minmax = true; 6871ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.EXT_framebuffer_blit = true; 6971ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.EXT_framebuffer_object = true; 7071ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.EXT_framebuffer_multisample = true; 7171ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.EXT_fog_coord = true; 7271ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.EXT_gpu_program_parameters = true; 7371ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.EXT_packed_depth_stencil = true; 7471ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.EXT_pixel_buffer_object = true; 7571ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.EXT_point_parameters = true; 7671ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.EXT_provoking_vertex = true; 7771ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.EXT_secondary_color = true; 7871ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.EXT_separate_shader_objects = true; 7971ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.EXT_texture_env_dot3 = true; 8071ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.EXT_texture_filter_anisotropic = true; 8171ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.APPLE_object_purgeable = true; 8271ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.MESA_pack_invert = true; 8371ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.MESA_ycbcr_texture = true; 8471ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.NV_blend_square = true; 8571ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.NV_texture_rectangle = true; 8671ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.NV_vertex_program = true; 8771ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.NV_vertex_program1_1 = true; 8871ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.TDFX_texture_compression_FXT1 = true; 8971ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick#if FEATURE_OES_EGL_image 9071ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.OES_EGL_image = true; 9171ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick#endif 9288128516d43be5d25288ff5b64db63cda83c04b3Kenneth Graunke ctx->Extensions.OES_draw_texture = true; 93a5a34b153d494ad4374e7b2c8ea13b1073a887e2Chad Versace ctx->Extensions.OES_compressed_ETC1_RGB8_texture = true; 94b3900ed5ad9bd5df112490dd2b5d2c17d6124067Jordan Justen ctx->Extensions.ARB_texture_rgb10_a2ui = true; 95a34817917bd8c408d8f732c24b4eb586f666d6c1Chad Versace 968727807f7e218bd161d92e34f6896f4451d14de0Eric Anholt if (intel->gen >= 6) 972a33a997376e1b628ad91e609a090bedf5964704Ian Romanick if (ctx->API == API_OPENGL_CORE) { 982a33a997376e1b628ad91e609a090bedf5964704Ian Romanick ctx->Const.GLSLVersion = 140; 992a33a997376e1b628ad91e609a090bedf5964704Ian Romanick } else { 1002a33a997376e1b628ad91e609a090bedf5964704Ian Romanick ctx->Const.GLSLVersion = 130; 1012a33a997376e1b628ad91e609a090bedf5964704Ian Romanick } 1028727807f7e218bd161d92e34f6896f4451d14de0Eric Anholt else 1038727807f7e218bd161d92e34f6896f4451d14de0Eric Anholt ctx->Const.GLSLVersion = 120; 104a1eff5570f5e3f893fe4d453aef5ce143712ab09Chad Versace _mesa_override_glsl_version(ctx); 105b91dba49e0b08b18dbd6c477facdcc7b5472c8c7Kristian Høgsberg 106cd2a24a4c2cf3aab8cbaf831d9712bc3c09cba66Eric Anholt if (intel->gen == 6 || 107cd2a24a4c2cf3aab8cbaf831d9712bc3c09cba66Eric Anholt (intel->gen == 7 && intel->intelScreen->kernel_has_gen7_sol_reset)) 1086ca61441b5cea8a2996c1adb4cc300a3c2be3ec9Paul Berry ctx->Extensions.EXT_transform_feedback = true; 1096ca61441b5cea8a2996c1adb4cc300a3c2be3ec9Paul Berry 110b7932e183c15a224adc4b04835f82f3c867a4a24Eric Anholt if (intel->gen >= 6) { 111040894391a2cf85035c6ad85f3f85c6efb23324bKenneth Graunke ctx->Extensions.ARB_blend_func_extended = !driQueryOptionb(&intel->optionCache, "disable_blend_func_extended"); 112b7932e183c15a224adc4b04835f82f3c867a4a24Eric Anholt ctx->Extensions.ARB_draw_buffers_blend = true; 1134a078516b6e9dd6876aaa2c95f0a98b7f5e08d19Eric Anholt ctx->Extensions.ARB_uniform_buffer_object = true; 1142a33a997376e1b628ad91e609a090bedf5964704Ian Romanick 1152a33a997376e1b628ad91e609a090bedf5964704Ian Romanick if (ctx->API == API_OPENGL_CORE) { 1162a33a997376e1b628ad91e609a090bedf5964704Ian Romanick ctx->Extensions.ARB_texture_buffer_object = true; 1172a33a997376e1b628ad91e609a090bedf5964704Ian Romanick } 118b7932e183c15a224adc4b04835f82f3c867a4a24Eric Anholt } 119b7932e183c15a224adc4b04835f82f3c867a4a24Eric Anholt 1203b68b6c83e491d7f85baff6a31dcceee28622ae0Eric Anholt if (intel->gen >= 5) 12171ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.EXT_timer_query = true; 12271ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick 123f0159018d7709b57d9916575512d75cb3f2fb395Eric Anholt if (intel->gen >= 6) { 124f0159018d7709b57d9916575512d75cb3f2fb395Eric Anholt uint64_t dummy; 125f0159018d7709b57d9916575512d75cb3f2fb395Eric Anholt /* Test if the kernel has the ioctl. */ 126f0159018d7709b57d9916575512d75cb3f2fb395Eric Anholt if (drm_intel_reg_read(intel->bufmgr, TIMESTAMP, &dummy) == 0) 127f0159018d7709b57d9916575512d75cb3f2fb395Eric Anholt ctx->Extensions.ARB_timer_query = true; 128f0159018d7709b57d9916575512d75cb3f2fb395Eric Anholt } 129f0159018d7709b57d9916575512d75cb3f2fb395Eric Anholt 13071ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick if (intel->gen >= 4) { 13171ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.ARB_color_buffer_float = true; 132deb6dd6b4df7324b4b240799029a80db65b89d96Eric Anholt ctx->Extensions.ARB_depth_buffer_float = true; 13371ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.ARB_depth_clamp = true; 134ae92180d724f9b743a088050cdc4ff7dad20c28bEric Anholt ctx->Extensions.ARB_draw_instanced = true; 1353588098ed85bbd6bacac5a8dd3774569f1314783Jordan Justen ctx->Extensions.ARB_instanced_arrays = true; 13671ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.ARB_fragment_coord_conventions = true; 13771ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.ARB_fragment_program_shadow = true; 13871ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.ARB_fragment_shader = true; 13971ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.ARB_half_float_vertex = true; 14071ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.ARB_occlusion_query = true; 1419a2943ddf28eee417b692d9338b81aa89a51dea8Eric Anholt ctx->Extensions.ARB_occlusion_query2 = true; 14271ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.ARB_point_sprite = true; 14371ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.ARB_seamless_cube_map = true; 14405790746df077183d6c3caf87ca2d276a60302a8Kenneth Graunke ctx->Extensions.ARB_shader_bit_encoding = true; 14571ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.ARB_shader_texture_lod = true; 14671ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick#ifdef TEXTURE_FLOAT_ENABLED 14771ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.ARB_texture_float = true; 1482fd8c4e3edf989c6f7dd1261a67b01f06979feabEric Anholt ctx->Extensions.EXT_texture_shared_exponent = true; 14903e623a27b95ef228fb4fca71c6d7c7a21630033Eric Anholt ctx->Extensions.EXT_packed_float = true; 15071ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick#endif 15171ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.ARB_texture_compression_rgtc = true; 15271ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.ARB_texture_rg = true; 15371ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.EXT_draw_buffers2 = true; 15471ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.EXT_framebuffer_sRGB = true; 155669f1822d2a60865514faf37f9fde21e4567b3d2Eric Anholt ctx->Extensions.EXT_texture_array = true; 156f22ecaa14f4c1b7cbdf0a53d58628f619ea12e8eIan Romanick ctx->Extensions.EXT_texture_integer = true; 15771ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.EXT_texture_snorm = true; 15871ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.EXT_texture_sRGB = true; 15971ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.EXT_texture_sRGB_decode = true; 16071ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.EXT_texture_swizzle = true; 16171ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.EXT_vertex_array_bgra = true; 16271ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.ATI_envmap_bumpmap = true; 163669f1822d2a60865514faf37f9fde21e4567b3d2Eric Anholt ctx->Extensions.MESA_texture_array = true; 16471ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.NV_conditional_render = true; 16571ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick } 166425c803c039735aaaeb70f1613268fd4909862dcIan Romanick 16771ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick if (intel->gen >= 3) { 16871ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.ARB_ES2_compatibility = true; 16971ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.ARB_depth_texture = true; 17071ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.ARB_fragment_program = true; 17171ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.ARB_shadow = true; 17271ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.ARB_texture_non_power_of_two = true; 17371ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.EXT_shadow_funcs = true; 17471ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.EXT_stencil_two_side = true; 17571ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.ATI_separate_stencil = true; 17671ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.ATI_texture_env_combine3 = true; 17771ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.NV_texture_env_combine4 = true; 178862a2a55b35d1dec9224b025a6e7a0cf8593a6a7Eric Anholt 179b6b753f72728b734fc9886f4ec513ae09e6b269dIan Romanick if (driQueryOptionb(&intel->optionCache, "fragment_shader")) 18071ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.ARB_fragment_shader = true; 18181aa5d717bd0098608e9cc292b316293800c7e11Eric Anholt 182b6b753f72728b734fc9886f4ec513ae09e6b269dIan Romanick if (driQueryOptionb(&intel->optionCache, "stub_occlusion_query")) 18371ceccad7e36f23e33d340fa0da157e2e0d2b6acIan Romanick ctx->Extensions.ARB_occlusion_query = true; 184862a2a55b35d1dec9224b025a6e7a0cf8593a6a7Eric Anholt } 1850a5478c1d9f9a892371d9ff004976e783a086694Ian Romanick 1860a5478c1d9f9a892371d9ff004976e783a086694Ian Romanick if (intel->ctx.Mesa_DXTn) { 1870a5478c1d9f9a892371d9ff004976e783a086694Ian Romanick ctx->Extensions.EXT_texture_compression_s3tc = true; 1880a5478c1d9f9a892371d9ff004976e783a086694Ian Romanick ctx->Extensions.S3_s3tc = true; 1890a5478c1d9f9a892371d9ff004976e783a086694Ian Romanick } 1900a5478c1d9f9a892371d9ff004976e783a086694Ian Romanick else if (driQueryOptionb(&intel->optionCache, "force_s3tc_enable")) { 1910a5478c1d9f9a892371d9ff004976e783a086694Ian Romanick ctx->Extensions.EXT_texture_compression_s3tc = true; 1920a5478c1d9f9a892371d9ff004976e783a086694Ian Romanick } 193df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen 194df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen if (intel->gen >= 4) { 195df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen ctx->Extensions.NV_primitive_restart = true; 196df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen } 1974006c5e4526a1cdb910500764590e39d32750967Brian Paul} 198