diff options
Diffstat (limited to 'src/mesa')
36 files changed, 1032 insertions, 497 deletions
diff --git a/src/mesa/SConscript b/src/mesa/SConscript index c85085434e..5a04dfd68f 100644 --- a/src/mesa/SConscript +++ b/src/mesa/SConscript @@ -103,6 +103,7 @@ if env['platform'] != 'winddk': 'main/texrender.c', 'main/texstate.c', 'main/texstore.c', + 'main/transformfeedback.c', 'main/varray.c', 'main/version.c', 'main/viewport.c', diff --git a/src/mesa/drivers/dri/common/dri_util.c b/src/mesa/drivers/dri/common/dri_util.c index badbb5ff82..f1bbd38612 100644 --- a/src/mesa/drivers/dri/common/dri_util.c +++ b/src/mesa/drivers/dri/common/dri_util.c @@ -129,11 +129,6 @@ static int driUnbindContext(__DRIcontext *pcp) */ pcp->driDrawablePriv = pcp->driReadablePriv = NULL; -#if 0 - /* Unbind the drawable */ - pdp->driContextPriv = &psp->dummyContextPriv; -#endif - return GL_TRUE; } @@ -433,7 +428,6 @@ driCreateNewDrawable(__DRIscreen *psp, const __DRIconfig *config, pdp->vblFlags = 0; pdp->driScreenPriv = psp; - pdp->driContextPriv = &psp->dummyContextPriv; if (!(*psp->DriverAPI.CreateBuffer)(psp, pdp, &config->modes, renderType == GLX_PIXMAP_BIT)) { @@ -567,17 +561,6 @@ driCreateNewContext(__DRIscreen *psp, const __DRIconfig *config, pcp->dri2.draw_stamp = 0; pcp->dri2.read_stamp = 0; - /* When the first context is created for a screen, initialize a "dummy" - * context. - */ - - if (!psp->dri2.enabled && !psp->dummyContextPriv.driScreenPriv) { - psp->dummyContextPriv.hHWContext = psp->pSAREA->dummy_context; - psp->dummyContextPriv.driScreenPriv = psp; - psp->dummyContextPriv.driDrawablePriv = NULL; - psp->dummyContextPriv.driverPrivate = NULL; - /* No other fields should be used! */ - } pcp->hHWContext = hwContext; @@ -734,13 +717,6 @@ driCreateNewScreen(int scrn, psp->myNum = scrn; psp->dri2.enabled = GL_FALSE; - /* - ** Do not init dummy context here; actual initialization will be - ** done when the first DRI context is created. Init screen priv ptr - ** to NULL to let CreateContext routine that it needs to be inited. - */ - psp->dummyContextPriv.driScreenPriv = NULL; - psp->DriverAPI = driDriverAPI; *driver_modes = driDriverAPI.InitScreen(psp); diff --git a/src/mesa/drivers/dri/common/dri_util.h b/src/mesa/drivers/dri/common/dri_util.h index f63583cebc..038a81604f 100644 --- a/src/mesa/drivers/dri/common/dri_util.h +++ b/src/mesa/drivers/dri/common/dri_util.h @@ -399,11 +399,6 @@ struct __DRIcontextRec { void *driverPrivate; /** - * Pointer back to the \c __DRIcontext that contains this structure. - */ - __DRIcontext *pctx; - - /** * Pointer to drawable currently bound to this context for drawing. */ __DRIdrawable *driDrawablePriv; @@ -511,29 +506,12 @@ struct __DRIscreenRec { /*@}*/ /** - * Dummy context to which drawables are bound when not bound to any - * other context. - * - * A dummy hHWContext is created for this context, and is used by the GL - * core when a hardware lock is required but the drawable is not currently - * bound (e.g., potentially during a SwapBuffers request). The dummy - * context is created when the first "real" context is created on this - * screen. - */ - __DRIcontext dummyContextPriv; - - /** * Device-dependent private information (not stored in the SAREA). * * This pointer is never touched by the DRI layer. */ void *private; - /** - * Pointer back to the \c __DRIscreen that contains this structure. - */ - __DRIscreen *psc; - /* Extensions provided by the loader. */ const __DRIgetDrawableInfoExtension *getDrawableInfo; const __DRIsystemTimeExtension *systemTime; diff --git a/src/mesa/drivers/dri/common/drisw_util.c b/src/mesa/drivers/dri/common/drisw_util.c index 3f4e94c8f6..8d08b93bfb 100644 --- a/src/mesa/drivers/dri/common/drisw_util.c +++ b/src/mesa/drivers/dri/common/drisw_util.c @@ -184,8 +184,6 @@ static int driUnbindContext(__DRIcontext *pcp) pcp->driDrawablePriv = NULL; pcp->driReadablePriv = NULL; - pdp->driContextPriv = NULL; - return GL_TRUE; } diff --git a/src/mesa/drivers/dri/i915/i915_state.c b/src/mesa/drivers/dri/i915/i915_state.c index 7275617a6f..91b228d52b 100644 --- a/src/mesa/drivers/dri/i915/i915_state.c +++ b/src/mesa/drivers/dri/i915/i915_state.c @@ -374,7 +374,7 @@ intelCalcViewport(GLcontext * ctx) else { /* window buffer, y=0=top */ yScale = -1.0; - yBias = (intel->driDrawable) ? intel->driDrawable->h : 0.0F; + yBias = ctx->DrawBuffer->Height; } m[MAT_SX] = v[MAT_SX]; diff --git a/src/mesa/drivers/dri/i915/intel_tris.c b/src/mesa/drivers/dri/i915/intel_tris.c index 81c4adeaf3..9449a158dc 100644 --- a/src/mesa/drivers/dri/i915/intel_tris.c +++ b/src/mesa/drivers/dri/i915/intel_tris.c @@ -488,9 +488,9 @@ intel_wpos_triangle(struct intel_context *intel, __memcpy(v1_wpos, v1, size); __memcpy(v2_wpos, v2, size); - v0_wpos[1] = -v0_wpos[1] + intel->driDrawable->h; - v1_wpos[1] = -v1_wpos[1] + intel->driDrawable->h; - v2_wpos[1] = -v2_wpos[1] + intel->driDrawable->h; + v0_wpos[1] = -v0_wpos[1] + intel->ctx.DrawBuffer->Height; + v1_wpos[1] = -v1_wpos[1] + intel->ctx.DrawBuffer->Height; + v2_wpos[1] = -v2_wpos[1] + intel->ctx.DrawBuffer->Height; intel_draw_triangle(intel, v0, v1, v2); @@ -509,8 +509,8 @@ intel_wpos_line(struct intel_context *intel, __memcpy(v0_wpos, v0, size); __memcpy(v1_wpos, v1, size); - v0_wpos[1] = -v0_wpos[1] + intel->driDrawable->h; - v1_wpos[1] = -v1_wpos[1] + intel->driDrawable->h; + v0_wpos[1] = -v0_wpos[1] + intel->ctx.DrawBuffer->Height; + v1_wpos[1] = -v1_wpos[1] + intel->ctx.DrawBuffer->Height; intel_draw_line(intel, v0, v1); } @@ -524,7 +524,7 @@ intel_wpos_point(struct intel_context *intel, intelVertexPtr v0) GLfloat *v0_wpos = (GLfloat *)((char *)v0 + offset); __memcpy(v0_wpos, v0, size); - v0_wpos[1] = -v0_wpos[1] + intel->driDrawable->h; + v0_wpos[1] = -v0_wpos[1] + intel->ctx.DrawBuffer->Height; intel_draw_point(intel, v0); } diff --git a/src/mesa/drivers/dri/intel/intel_context.c b/src/mesa/drivers/dri/intel/intel_context.c index 5289e954db..9077a61132 100644 --- a/src/mesa/drivers/dri/intel/intel_context.c +++ b/src/mesa/drivers/dri/intel/intel_context.c @@ -63,7 +63,7 @@ int INTEL_DEBUG = (0); #endif -#define DRIVER_DATE "20091221 DEVELOPMENT" +#define DRIVER_DATE "20100330 DEVELOPMENT" #define DRIVER_DATE_GEM "GEM " DRIVER_DATE @@ -389,7 +389,7 @@ intel_prepare_render(struct intel_context *intel) __DRIcontext *driContext = intel->driContext; __DRIdrawable *drawable; - drawable = intel->driDrawable; + drawable = driContext->driDrawablePriv; if (drawable->dri2.stamp != driContext->dri2.draw_stamp) { if (drawable->lastStamp != drawable->dri2.stamp) intel_update_renderbuffers(driContext, drawable); @@ -397,7 +397,7 @@ intel_prepare_render(struct intel_context *intel) driContext->dri2.draw_stamp = drawable->dri2.stamp; } - drawable = intel->driReadDrawable; + drawable = driContext->driReadablePriv; if (drawable->dri2.stamp != driContext->dri2.read_stamp) { if (drawable->lastStamp != drawable->dri2.stamp) intel_update_renderbuffers(driContext, drawable); @@ -472,6 +472,7 @@ void intel_flush(GLcontext *ctx, GLboolean needs_mi_flush) { struct intel_context *intel = intel_context(ctx); + __DRIcontext *driContext = intel->driContext; if (intel->Fallback) _swrast_flush(ctx); @@ -488,9 +489,10 @@ intel_flush(GLcontext *ctx, GLboolean needs_mi_flush) if (screen->dri2.loader && (screen->dri2.loader->base.version >= 2) && (screen->dri2.loader->flushFrontBuffer != NULL) && - intel->driDrawable && intel->driDrawable->loaderPrivate) { - (*screen->dri2.loader->flushFrontBuffer)(intel->driDrawable, - intel->driDrawable->loaderPrivate); + driContext->driDrawablePriv && + driContext->driDrawablePriv->loaderPrivate) { + (*screen->dri2.loader->flushFrontBuffer)(driContext->driDrawablePriv, + driContext->driDrawablePriv->loaderPrivate); /* Only clear the dirty bit if front-buffer rendering is no longer * enabled. This is done so that the dirty bit can only be set in @@ -607,7 +609,6 @@ intelInitContext(struct intel_context *intel, driContextPriv->driverPrivate = intel; intel->intelScreen = intelScreen; - intel->driScreen = sPriv; intel->driContext = driContextPriv; intel->driFd = sPriv->fd; @@ -636,8 +637,7 @@ intelInitContext(struct intel_context *intel, } driParseConfigFiles(&intel->optionCache, &intelScreen->optionCache, - intel->driScreen->myNum, - (intel->gen >= 4) ? "i965" : "i915"); + sPriv->myNum, (intel->gen >= 4) ? "i965" : "i915"); if (intelScreen->deviceID == PCI_CHIP_I865_G) intel->maxBatchSize = 4096; else @@ -845,14 +845,6 @@ intelDestroyContext(__DRIcontext * driContextPriv) GLboolean intelUnbindContext(__DRIcontext * driContextPriv) { - struct intel_context *intel = - (struct intel_context *) driContextPriv->driverPrivate; - - /* Deassociate the context with the drawables. - */ - intel->driDrawable = NULL; - intel->driReadDrawable = NULL; - return GL_TRUE; } @@ -881,8 +873,6 @@ intelMakeCurrent(__DRIcontext * driContextPriv, struct gl_framebuffer *fb = driDrawPriv->driverPrivate; struct gl_framebuffer *readFb = driReadPriv->driverPrivate; - intel->driReadDrawable = driReadPriv; - intel->driDrawable = driDrawPriv; driContextPriv->dri2.draw_stamp = driDrawPriv->dri2.stamp - 1; driContextPriv->dri2.read_stamp = driReadPriv->dri2.stamp - 1; intel_prepare_render(intel); diff --git a/src/mesa/drivers/dri/intel/intel_context.h b/src/mesa/drivers/dri/intel/intel_context.h index 6a68c903ee..c4bb2bed8e 100644 --- a/src/mesa/drivers/dri/intel/intel_context.h +++ b/src/mesa/drivers/dri/intel/intel_context.h @@ -243,9 +243,6 @@ struct intel_context int driFd; __DRIcontext *driContext; - __DRIdrawable *driDrawable; - __DRIdrawable *driReadDrawable; - __DRIscreen *driScreen; struct intel_screen *intelScreen; /** diff --git a/src/mesa/drivers/dri/intel/intel_tex_copy.c b/src/mesa/drivers/dri/intel/intel_tex_copy.c index 618f690a5f..62e1e78f59 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_copy.c +++ b/src/mesa/drivers/dri/intel/intel_tex_copy.c @@ -130,18 +130,8 @@ do_copy_texsubimage(struct intel_context *intel, } if (ctx->ReadBuffer->Name == 0) { - /* reading from a window, adjust x, y */ - const __DRIdrawable *dPriv = intel->driReadDrawable; - y = dPriv->y + (dPriv->h - (y + height)); - x += dPriv->x; - - /* Invert the data coming from the source rectangle due to GL - * and hardware disagreeing on where y=0 is. - * - * It appears that our offsets and pitches get mangled - * appropriately by the hardware, and we don't need to adjust them - * on our own. - */ + /* Flip vertical orientation for system framebuffers */ + y = ctx->ReadBuffer->Height - (y + height); src_pitch = -src->pitch; } else { /* reading from a FBO, y is already oriented the way we like */ 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 4e84eefd65..b6dfe28def 100644 --- a/src/mesa/drivers/dri/r300/compiler/r500_fragprog_emit.c +++ b/src/mesa/drivers/dri/r300/compiler/r500_fragprog_emit.c @@ -190,6 +190,17 @@ static unsigned int use_source(struct r500_fragment_program_code* code, struct r return 0; } +/** + * NOP the specified instruction if it is not a texture lookup. + */ +static void alu_nop(struct r300_fragment_program_compiler *c, int ip) +{ + PROG_CODE; + + if ((code->inst[ip].inst0 & 0x3) != R500_INST_TYPE_TEX) { + code->inst[ip].inst0 |= R500_INST_NOP; + } +} /** * Emit a paired ALU instruction. @@ -205,6 +216,14 @@ static void emit_paired(struct r300_fragment_program_compiler *c, struct rc_pair int ip = ++code->inst_end; + /* Quirk: MDH/MDV (DDX/DDY) need a NOP on previous non-TEX instructions. */ + if (inst->RGB.Opcode == RC_OPCODE_DDX || inst->Alpha.Opcode == RC_OPCODE_DDX || + inst->RGB.Opcode == RC_OPCODE_DDY || inst->Alpha.Opcode == RC_OPCODE_DDY) { + if (ip > 0) { + alu_nop(c, ip - 1); + } + } + code->inst[ip].inst5 = translate_rgb_op(c, inst->RGB.Opcode); code->inst[ip].inst4 = translate_alpha_op(c, inst->Alpha.Opcode); @@ -252,8 +271,8 @@ static void emit_paired(struct r300_fragment_program_compiler *c, struct rc_pair code->inst[ip].inst4 |= translate_arg_alpha(inst, 1) << R500_ALPHA_SEL_B_SHIFT; code->inst[ip].inst5 |= translate_arg_alpha(inst, 2) << R500_ALU_RGBA_ALPHA_SEL_C_SHIFT; - code->inst[ip].inst3 |= R500_ALU_RGB_TARGET(inst->RGB.Target); - code->inst[ip].inst4 |= R500_ALPHA_TARGET(inst->Alpha.Target); + code->inst[ip].inst3 |= R500_ALU_RGB_TARGET(inst->RGB.Target); + code->inst[ip].inst4 |= R500_ALPHA_TARGET(inst->Alpha.Target); if (inst->WriteALUResult) { code->inst[ip].inst3 |= R500_ALU_RGB_WMASK; diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_opcodes.c b/src/mesa/drivers/dri/r300/compiler/radeon_opcodes.c index c1c0181fac..9d289fce34 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_opcodes.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_opcodes.c @@ -75,14 +75,14 @@ struct rc_opcode_info rc_opcodes[MAX_RC_OPCODE] = { { .Opcode = RC_OPCODE_DDX, .Name = "DDX", - .NumSrcRegs = 1, + .NumSrcRegs = 2, .HasDstReg = 1, .IsComponentwise = 1 }, { .Opcode = RC_OPCODE_DDY, .Name = "DDY", - .NumSrcRegs = 1, + .NumSrcRegs = 2, .HasDstReg = 1, .IsComponentwise = 1 }, diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_pair_translate.c b/src/mesa/drivers/dri/r300/compiler/radeon_pair_translate.c index fff5b0c217..3a26e7daaf 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_pair_translate.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_pair_translate.c @@ -159,11 +159,6 @@ static void set_pair_instruction(struct r300_fragment_program_compiler *c, int nargs = opcode->NumSrcRegs; int i; - /* Special case for DDX/DDY (MDH/MDV). */ - if (inst->Opcode == RC_OPCODE_DDX || inst->Opcode == RC_OPCODE_DDY) { - nargs++; - } - for(i = 0; i < opcode->NumSrcRegs; ++i) { int source; if (needrgb && !istranscendent) { diff --git a/src/mesa/es/Makefile b/src/mesa/es/Makefile index fbe67445c9..8b484853af 100644 --- a/src/mesa/es/Makefile +++ b/src/mesa/es/Makefile @@ -19,9 +19,8 @@ es1: $(ES1_LIBS) es2: $(ES2_LIBS) @rm -f subdirs-stamp-tmp -# force the inclusion of es's mfeatures.h -ES1_CPPFLAGS := -include main/mfeatures_es1.h -D__GL_EXPORTS -ES2_CPPFLAGS := -include main/mfeatures_es2.h -D__GL_EXPORTS +ES1_CPPFLAGS := -DFEATURE_ES1=1 -D__GL_EXPORTS +ES2_CPPFLAGS := -DFEATURE_ES2=1 -D__GL_EXPORTS ES1_OBJ_DIR := objs-es1 ES2_OBJ_DIR := objs-es2 diff --git a/src/mesa/es/main/mfeatures_es1.h b/src/mesa/es/main/mfeatures_es1.h deleted file mode 100644 index 1793550268..0000000000 --- a/src/mesa/es/main/mfeatures_es1.h +++ /dev/null @@ -1,118 +0,0 @@ -/************************************************************************** - * - * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/** - * \file mfeatures.h - * - * The #defines in this file enable/disable Mesa features needed - * for OpenGL ES 1.1. - */ - - -#ifndef MFEATURES_ES1_H -#define MFEATURES_ES1_H - -/* this file replaces main/mfeatures.h */ -#ifdef FEATURES_H -#error "main/mfeatures.h was wrongly included" -#endif -#define FEATURES_H - -#define ASSERT_NO_FEATURE() ASSERT(0) - -/* - * Enable/disable features (blocks of code) by setting FEATURE_xyz to 0 or 1. - */ -#ifndef _HAVE_FULL_GL -#define _HAVE_FULL_GL 1 -#endif - -#ifdef IN_DRI_DRIVER -#define FEATURE_remap_table 1 -#else -#define FEATURE_remap_table 0 -#endif - -#define FEATURE_accum 0 -#define FEATURE_arrayelt 0 -#define FEATURE_attrib 0 -#define FEATURE_beginend 0 -#define FEATURE_colortable 0 -#define FEATURE_convolve 0 -#define FEATURE_dispatch 1 -#define FEATURE_dlist 0 -#define FEATURE_draw_read_buffer 0 -#define FEATURE_drawpix 0 -#define FEATURE_eval 0 -#define FEATURE_feedback 0 -#define FEATURE_fixedpt 1 -#define FEATURE_histogram 0 -#define FEATURE_pixel 0 -#define FEATURE_point_size_array 1 -#define FEATURE_queryobj 0 -#define FEATURE_rastpos 0 -#define FEATURE_texgen 1 -#define FEATURE_texture_fxt1 0 -#define FEATURE_texture_s3tc 0 -#define FEATURE_userclip 1 -#define FEATURE_vertex_array_byte 1 -#define FEATURE_es2_glsl 0 - -#define FEATURE_ARB_fragment_program _HAVE_FULL_GL -#define FEATURE_ARB_vertex_buffer_object _HAVE_FULL_GL -#define FEATURE_ARB_vertex_program _HAVE_FULL_GL - -#define FEATURE_ARB_vertex_shader _HAVE_FULL_GL -#define FEATURE_ARB_fragment_shader _HAVE_FULL_GL -#define FEATURE_ARB_shader_objects (FEATURE_ARB_vertex_shader || FEATURE_ARB_fragment_shader) -#define FEATURE_ARB_shading_language_100 FEATURE_ARB_shader_objects -#define FEATURE_ARB_shading_language_120 FEATURE_ARB_shader_objects - -#define FEATURE_EXT_framebuffer_blit 0 -#define FEATURE_EXT_framebuffer_object _HAVE_FULL_GL -#define FEATURE_EXT_pixel_buffer_object _HAVE_FULL_GL -#define FEATURE_EXT_texture_sRGB 0 -#define FEATURE_ATI_fragment_shader 0 -#define FEATURE_MESA_program_debug _HAVE_FULL_GL -#define FEATURE_NV_fence 0 -#define FEATURE_NV_fragment_program 0 -#define FEATURE_NV_vertex_program 0 - -#define FEATURE_OES_framebuffer_object 1 -#define FEATURE_OES_draw_texture 1 -#define FEATURE_OES_mapbuffer 1 - -#define FEATURE_OES_EGL_image 1 - -#define FEATURE_extra_context_init 1 - -/*@}*/ - - - - -#endif /* MFEATURES_ES1_H */ diff --git a/src/mesa/es/main/mfeatures_es2.h b/src/mesa/es/main/mfeatures_es2.h deleted file mode 100644 index a463bed11c..0000000000 --- a/src/mesa/es/main/mfeatures_es2.h +++ /dev/null @@ -1,118 +0,0 @@ -/************************************************************************** - * - * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/** - * \file mfeatures.h - * - * The #defines in this file enable/disable Mesa features needed - * for OpenGL ES 2.0. - */ - - -#ifndef MFEATURES_ES2_H -#define MFEATURES_ES2_H - -/* this file replaces main/mfeatures.h */ -#ifdef FEATURES_H -#error "main/mfeatures.h was wrongly included" -#endif -#define FEATURES_H - -#define ASSERT_NO_FEATURE() ASSERT(0) - -/* - * Enable/disable features (blocks of code) by setting FEATURE_xyz to 0 or 1. - */ -#ifndef _HAVE_FULL_GL -#define _HAVE_FULL_GL 1 -#endif - -#ifdef IN_DRI_DRIVER -#define FEATURE_remap_table 1 -#else -#define FEATURE_remap_table 0 -#endif - -#define FEATURE_accum 0 -#define FEATURE_arrayelt 0 -#define FEATURE_attrib 0 -#define FEATURE_beginend 0 -#define FEATURE_colortable 0 -#define FEATURE_convolve 0 -#define FEATURE_dispatch 1 -#define FEATURE_dlist 0 -#define FEATURE_draw_read_buffer 0 -#define FEATURE_drawpix 0 -#define FEATURE_eval 0 -#define FEATURE_feedback 0 -#define FEATURE_fixedpt 1 -#define FEATURE_histogram 0 -#define FEATURE_pixel 0 -#define FEATURE_point_size_array 1 -#define FEATURE_queryobj 0 -#define FEATURE_rastpos 0 -#define FEATURE_texgen 1 -#define FEATURE_texture_fxt1 0 -#define FEATURE_texture_s3tc 0 -#define FEATURE_userclip 1 -#define FEATURE_vertex_array_byte 1 -#define FEATURE_es2_glsl 1 - -#define FEATURE_ARB_fragment_program _HAVE_FULL_GL -#define FEATURE_ARB_vertex_buffer_object _HAVE_FULL_GL -#define FEATURE_ARB_vertex_program _HAVE_FULL_GL - -#define FEATURE_ARB_vertex_shader _HAVE_FULL_GL -#define FEATURE_ARB_fragment_shader _HAVE_FULL_GL -#define FEATURE_ARB_shader_objects (FEATURE_ARB_vertex_shader || FEATURE_ARB_fragment_shader) -#define FEATURE_ARB_shading_language_100 FEATURE_ARB_shader_objects -#define FEATURE_ARB_shading_language_120 FEATURE_ARB_shader_objects - -#define FEATURE_EXT_framebuffer_blit 0 -#define FEATURE_EXT_framebuffer_object _HAVE_FULL_GL -#define FEATURE_EXT_pixel_buffer_object _HAVE_FULL_GL -#define FEATURE_EXT_texture_sRGB 0 -#define FEATURE_ATI_fragment_shader 0 -#define FEATURE_MESA_program_debug _HAVE_FULL_GL -#define FEATURE_NV_fence 0 -#define FEATURE_NV_fragment_program 0 -#define FEATURE_NV_vertex_program 0 - -#define FEATURE_OES_framebuffer_object 1 -#define FEATURE_OES_draw_texture 0 -#define FEATURE_OES_mapbuffer 1 - -#define FEATURE_OES_EGL_image 1 - -#define FEATURE_extra_context_init 1 - -/*@}*/ - - - - -#endif /* MFEATURES_ES2_H */ diff --git a/src/mesa/es/main/stubs.c b/src/mesa/es/main/stubs.c index e7b8bc780f..b829543cc0 100644 --- a/src/mesa/es/main/stubs.c +++ b/src/mesa/es/main/stubs.c @@ -37,13 +37,6 @@ _mesa_error(ctx, GL_INVALID_OPERATION, __FUNCTION__); \ } while (0) -#if FEATURE_accum -/* This is a sanity check that to be sure we're using the correct mfeatures.h - * header. We don't want to accidentally use the one from mainline Mesa. - */ -#error "The wrong mfeatures.h file is being included!" -#endif - /* silence compiler warnings */ extern void GLAPIENTRY _vbo_Materialf(GLenum face, GLenum pname, GLfloat param); diff --git a/src/mesa/main/bufferobj.c b/src/mesa/main/bufferobj.c index 1854b980be..235cafcf1e 100644 --- a/src/mesa/main/bufferobj.c +++ b/src/mesa/main/bufferobj.c @@ -47,7 +47,7 @@ /*#define BOUNDS_CHECK*/ -#ifdef FEATURE_OES_mapbuffer +#if FEATURE_OES_mapbuffer #define DEFAULT_ACCESS GL_MAP_WRITE_BIT #else #define DEFAULT_ACCESS (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT) @@ -83,6 +83,13 @@ get_buffer_target(GLcontext *ctx, GLenum target) return &ctx->CopyWriteBuffer; } break; +#if FEATURE_EXT_transform_feedback + case GL_TRANSFORM_FEEDBACK_BUFFER: + if (ctx->Extensions.EXT_transform_feedback) { + return &ctx->TransformFeedback.CurrentBuffer; + } + break; +#endif default: return NULL; } diff --git a/src/mesa/main/config.h b/src/mesa/main/config.h index 2eac1cc2ed..30b48e4bd0 100644 --- a/src/mesa/main/config.h +++ b/src/mesa/main/config.h @@ -262,6 +262,11 @@ /** For GL_ATI_envmap_bump - support bump mapping on first 8 units */ #define SUPPORTED_ATI_BUMP_UNITS 0xff +/** For GL_EXT_transform_feedback */ +#define MAX_FEEDBACK_ATTRIBS 32 + + + /** * \name Mesa-specific parameters */ diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index 73126b9575..2074b32b25 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -123,6 +123,7 @@ #include "stencil.h" #include "texcompress_s3tc.h" #include "texstate.h" +#include "transformfeedback.h" #include "mtypes.h" #include "varray.h" #include "version.h" @@ -560,6 +561,11 @@ _mesa_init_constants(GLcontext *ctx) /* GL_EXT_provoking_vertex */ ctx->Const.QuadsFollowProvokingVertexConvention = GL_TRUE; + + /* GL_EXT_transform_feedback */ + ctx->Const.MaxTransformFeedbackSeparateAttribs = MAX_FEEDBACK_ATTRIBS; + ctx->Const.MaxTransformFeedbackSeparateComponents = 4 * MAX_FEEDBACK_ATTRIBS; + ctx->Const.MaxTransformFeedbackInterleavedComponents = 4 * MAX_FEEDBACK_ATTRIBS; } @@ -684,6 +690,7 @@ init_attrib_groups(GLcontext *ctx) _mesa_init_shader_state( ctx ); _mesa_init_stencil( ctx ); _mesa_init_transform( ctx ); + _mesa_init_transform_feedback( ctx ); _mesa_init_varray( ctx ); _mesa_init_viewport( ctx ); @@ -873,7 +880,7 @@ _mesa_initialize_context(GLcontext *ctx, ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE; } -#ifdef FEATURE_extra_context_init +#if FEATURE_extra_context_init _mesa_initialize_context_extra(ctx); #endif @@ -969,6 +976,7 @@ _mesa_free_context_data( GLcontext *ctx ) _mesa_free_sync_data(ctx); #endif _mesa_free_varray_data(ctx); + _mesa_free_transform_feedback(ctx); _mesa_delete_array_object(ctx, ctx->Array.DefaultArrayObj); diff --git a/src/mesa/main/enable.c b/src/mesa/main/enable.c index f5c88a63e6..f9decc31ab 100644 --- a/src/mesa/main/enable.c +++ b/src/mesa/main/enable.c @@ -982,6 +982,16 @@ _mesa_set_enable(GLcontext *ctx, GLenum cap, GLboolean state) ctx->Texture.CubeMapSeamless = state; break; +#if FEATURE_EXT_transform_feedback + case GL_RASTERIZER_DISCARD: + CHECK_EXTENSION(EXT_transform_feedback, cap); + if (ctx->TransformFeedback.RasterDiscard != state) { + ctx->TransformFeedback.RasterDiscard = state; + FLUSH_VERTICES(ctx, _NEW_TRANSFORM); + } + break; +#endif + default: _mesa_error(ctx, GL_INVALID_ENUM, "%s(0x%x)", state ? "glEnable" : "glDisable", cap); @@ -1493,6 +1503,12 @@ _mesa_IsEnabled( GLenum cap ) CHECK_EXTENSION(ARB_seamless_cube_map); return ctx->Texture.CubeMapSeamless; +#if FEATURE_EXT_transform_feedback + case GL_RASTERIZER_DISCARD: + CHECK_EXTENSION(EXT_transform_feedback); + return ctx->TransformFeedback.RasterDiscard; +#endif + default: _mesa_error(ctx, GL_INVALID_ENUM, "glIsEnabled(0x%x)", (int) cap); return GL_FALSE; diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c index 30245d6aaf..f7b0e5abf5 100644 --- a/src/mesa/main/extensions.c +++ b/src/mesa/main/extensions.c @@ -146,6 +146,7 @@ static const struct { { OFF, "GL_EXT_texture_sRGB", F(EXT_texture_sRGB) }, { OFF, "GL_EXT_texture_swizzle", F(EXT_texture_swizzle) }, { OFF, "GL_EXT_timer_query", F(EXT_timer_query) }, + { OFF, "GL_EXT_transform_feedback", F(EXT_transform_feedback) }, { ON, "GL_EXT_vertex_array", F(EXT_vertex_array) }, { OFF, "GL_EXT_vertex_array_bgra", F(EXT_vertex_array_bgra) }, { OFF, "GL_EXT_vertex_array_set", F(EXT_vertex_array_set) }, @@ -319,6 +320,9 @@ _mesa_enable_sw_extensions(GLcontext *ctx) ctx->Extensions.EXT_texture_sRGB = GL_TRUE; #endif ctx->Extensions.EXT_texture_swizzle = GL_TRUE; +#if FEATURE_EXT_transform_feedback + ctx->Extensions.EXT_transform_feedback = GL_TRUE; +#endif ctx->Extensions.EXT_vertex_array_bgra = GL_TRUE; /*ctx->Extensions.IBM_multimode_draw_arrays = GL_TRUE;*/ ctx->Extensions.MESA_pack_invert = GL_TRUE; @@ -480,7 +484,7 @@ _mesa_enable_2_1_extensions(GLcontext *ctx) #if FEATURE_EXT_texture_sRGB ctx->Extensions.EXT_texture_sRGB = GL_TRUE; #endif -#ifdef FEATURE_ARB_shading_language_120 +#if FEATURE_ARB_shading_language_120 ctx->Extensions.ARB_shading_language_120 = GL_TRUE; #endif } diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c index 0782734869..e3e006bb94 100644 --- a/src/mesa/main/fbobject.c +++ b/src/mesa/main/fbobject.c @@ -629,7 +629,7 @@ _mesa_test_framebuffer_completeness(GLcontext *ctx, struct gl_framebuffer *fb) } } -#ifndef FEATURE_OES_framebuffer_object +#if !FEATURE_OES_framebuffer_object /* Check that all DrawBuffers are present */ for (j = 0; j < ctx->Const.MaxDrawBuffers; j++) { if (fb->ColorDrawBuffer[j] != GL_NONE) { diff --git a/src/mesa/main/get.c b/src/mesa/main/get.c index 266fda40ec..eaa6d7f730 100644 --- a/src/mesa/main/get.c +++ b/src/mesa/main/get.c @@ -1922,6 +1922,26 @@ _mesa_GetBooleanv( GLenum pname, GLboolean *params ) CHECK_EXT1(ARB_sync, "GetBooleanv"); params[0] = INT64_TO_BOOLEAN(ctx->Const.MaxServerWaitTimeout); break; + case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: + CHECK_EXT1(EXT_transform_feedback, "GetBooleanv"); + params[0] = INT_TO_BOOLEAN(ctx->TransformFeedback.CurrentBuffer->Name); + break; + case GL_RASTERIZER_DISCARD: + CHECK_EXT1(EXT_transform_feedback, "GetBooleanv"); + params[0] = ctx->TransformFeedback.RasterDiscard; + break; + case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS: + CHECK_EXT1(EXT_transform_feedback, "GetBooleanv"); + params[0] = INT_TO_BOOLEAN(ctx->Const.MaxTransformFeedbackInterleavedComponents); + break; + case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS: + CHECK_EXT1(EXT_transform_feedback, "GetBooleanv"); + params[0] = INT_TO_BOOLEAN(ctx->Const.MaxTransformFeedbackSeparateAttribs); + break; + case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS: + CHECK_EXT1(EXT_transform_feedback, "GetBooleanv"); + params[0] = INT_TO_BOOLEAN(ctx->Const.MaxTransformFeedbackSeparateComponents); + break; case GL_NUM_EXTENSIONS: params[0] = INT_TO_BOOLEAN(_mesa_get_extension_count(ctx)); break; @@ -3793,6 +3813,26 @@ _mesa_GetFloatv( GLenum pname, GLfloat *params ) CHECK_EXT1(ARB_sync, "GetFloatv"); params[0] = (GLfloat)(ctx->Const.MaxServerWaitTimeout); break; + case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: + CHECK_EXT1(EXT_transform_feedback, "GetFloatv"); + params[0] = (GLfloat)(ctx->TransformFeedback.CurrentBuffer->Name); + break; + case GL_RASTERIZER_DISCARD: + CHECK_EXT1(EXT_transform_feedback, "GetFloatv"); + params[0] = BOOLEAN_TO_FLOAT(ctx->TransformFeedback.RasterDiscard); + break; + case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS: + CHECK_EXT1(EXT_transform_feedback, "GetFloatv"); + params[0] = (GLfloat)(ctx->Const.MaxTransformFeedbackInterleavedComponents); + break; + case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS: + CHECK_EXT1(EXT_transform_feedback, "GetFloatv"); + params[0] = (GLfloat)(ctx->Const.MaxTransformFeedbackSeparateAttribs); + break; + case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS: + CHECK_EXT1(EXT_transform_feedback, "GetFloatv"); + params[0] = (GLfloat)(ctx->Const.MaxTransformFeedbackSeparateComponents); + break; case GL_NUM_EXTENSIONS: params[0] = (GLfloat)(_mesa_get_extension_count(ctx)); break; @@ -5664,6 +5704,26 @@ _mesa_GetIntegerv( GLenum pname, GLint *params ) CHECK_EXT1(ARB_sync, "GetIntegerv"); params[0] = INT64_TO_INT(ctx->Const.MaxServerWaitTimeout); break; + case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: + CHECK_EXT1(EXT_transform_feedback, "GetIntegerv"); + params[0] = ctx->TransformFeedback.CurrentBuffer->Name; + break; + case GL_RASTERIZER_DISCARD: + CHECK_EXT1(EXT_transform_feedback, "GetIntegerv"); + params[0] = BOOLEAN_TO_INT(ctx->TransformFeedback.RasterDiscard); + break; + case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS: + CHECK_EXT1(EXT_transform_feedback, "GetIntegerv"); + params[0] = ctx->Const.MaxTransformFeedbackInterleavedComponents; + break; + case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS: + CHECK_EXT1(EXT_transform_feedback, "GetIntegerv"); + params[0] = ctx->Const.MaxTransformFeedbackSeparateAttribs; + break; + case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS: + CHECK_EXT1(EXT_transform_feedback, "GetIntegerv"); + params[0] = ctx->Const.MaxTransformFeedbackSeparateComponents; + break; case GL_NUM_EXTENSIONS: params[0] = _mesa_get_extension_count(ctx); break; @@ -7536,6 +7596,26 @@ _mesa_GetInteger64v( GLenum pname, GLint64 *params ) CHECK_EXT1(ARB_sync, "GetInteger64v"); params[0] = ctx->Const.MaxServerWaitTimeout; break; + case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: + CHECK_EXT1(EXT_transform_feedback, "GetInteger64v"); + params[0] = (GLint64)(ctx->TransformFeedback.CurrentBuffer->Name); + break; + case GL_RASTERIZER_DISCARD: + CHECK_EXT1(EXT_transform_feedback, "GetInteger64v"); + params[0] = BOOLEAN_TO_INT64(ctx->TransformFeedback.RasterDiscard); + break; + case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS: + CHECK_EXT1(EXT_transform_feedback, "GetInteger64v"); + params[0] = (GLint64)(ctx->Const.MaxTransformFeedbackInterleavedComponents); + break; + case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS: + CHECK_EXT1(EXT_transform_feedback, "GetInteger64v"); + params[0] = (GLint64)(ctx->Const.MaxTransformFeedbackSeparateAttribs); + break; + case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS: + CHECK_EXT1(EXT_transform_feedback, "GetInteger64v"); + params[0] = (GLint64)(ctx->Const.MaxTransformFeedbackSeparateComponents); + break; case GL_NUM_EXTENSIONS: params[0] = (GLint64)(_mesa_get_extension_count(ctx)); break; @@ -7606,6 +7686,30 @@ _mesa_GetBooleanIndexedv( GLenum pname, GLuint index, GLboolean *params ) params[2] = INT_TO_BOOLEAN(ctx->Color.ColorMask[index][BCOMP] ? 1 : 0); params[3] = INT_TO_BOOLEAN(ctx->Color.ColorMask[index][ACOMP] ? 1 : 0); break; + case GL_TRANSFORM_FEEDBACK_BUFFER_START: + CHECK_EXT1(EXT_transform_feedback, "GetBooleanIndexedv"); + if (index >= ctx->Const.MaxTransformFeedbackSeparateAttribs) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetBooleanIndexedv(index=%u), index", pname); + return; + } + params[0] = INT64_TO_BOOLEAN(ctx->TransformFeedback.Offset[index]); + break; + case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: + CHECK_EXT1(EXT_transform_feedback, "GetBooleanIndexedv"); + if (index >= ctx->Const.MaxTransformFeedbackSeparateAttribs) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetBooleanIndexedv(index=%u), index", pname); + return; + } + params[0] = INT64_TO_BOOLEAN(ctx->TransformFeedback.Size[index]); + break; + case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: + CHECK_EXT1(EXT_transform_feedback, "GetBooleanIndexedv"); + if (index >= ctx->Const.MaxTransformFeedbackSeparateAttribs) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetBooleanIndexedv(index=%u), index", pname); + return; + } + params[0] = INT_TO_BOOLEAN(ctx->TransformFeedback.Buffers[index]->Name); + break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetBooleanIndexedv(pname=0x%x)", pname); } @@ -7640,6 +7744,30 @@ _mesa_GetIntegerIndexedv( GLenum pname, GLuint index, GLint *params ) params[2] = ctx->Color.ColorMask[index][BCOMP] ? 1 : 0; params[3] = ctx->Color.ColorMask[index][ACOMP] ? 1 : 0; break; + case GL_TRANSFORM_FEEDBACK_BUFFER_START: + CHECK_EXT1(EXT_transform_feedback, "GetIntegerIndexedv"); + if (index >= ctx->Const.MaxTransformFeedbackSeparateAttribs) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetIntegerIndexedv(index=%u), index", pname); + return; + } + params[0] = INT64_TO_INT(ctx->TransformFeedback.Offset[index]); + break; + case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: + CHECK_EXT1(EXT_transform_feedback, "GetIntegerIndexedv"); + if (index >= ctx->Const.MaxTransformFeedbackSeparateAttribs) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetIntegerIndexedv(index=%u), index", pname); + return; + } + params[0] = INT64_TO_INT(ctx->TransformFeedback.Size[index]); + break; + case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: + CHECK_EXT1(EXT_transform_feedback, "GetIntegerIndexedv"); + if (index >= ctx->Const.MaxTransformFeedbackSeparateAttribs) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetIntegerIndexedv(index=%u), index", pname); + return; + } + params[0] = ctx->TransformFeedback.Buffers[index]->Name; + break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetIntegerIndexedv(pname=0x%x)", pname); } @@ -7675,6 +7803,30 @@ _mesa_GetInteger64Indexedv( GLenum pname, GLuint index, GLint64 *params ) params[2] = (GLint64)(ctx->Color.ColorMask[index][BCOMP] ? 1 : 0); params[3] = (GLint64)(ctx->Color.ColorMask[index][ACOMP] ? 1 : 0); break; + case GL_TRANSFORM_FEEDBACK_BUFFER_START: + CHECK_EXT1(EXT_transform_feedback, "GetInteger64Indexedv"); + if (index >= ctx->Const.MaxTransformFeedbackSeparateAttribs) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetInteger64Indexedv(index=%u), index", pname); + return; + } + params[0] = ctx->TransformFeedback.Offset[index]; + break; + case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: + CHECK_EXT1(EXT_transform_feedback, "GetInteger64Indexedv"); + if (index >= ctx->Const.MaxTransformFeedbackSeparateAttribs) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetInteger64Indexedv(index=%u), index", pname); + return; + } + params[0] = ctx->TransformFeedback.Size[index]; + break; + case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: + CHECK_EXT1(EXT_transform_feedback, "GetInteger64Indexedv"); + if (index >= ctx->Const.MaxTransformFeedbackSeparateAttribs) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetInteger64Indexedv(index=%u), index", pname); + return; + } + params[0] = (GLint64)(ctx->TransformFeedback.Buffers[index]->Name); + break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetInteger64Indexedv(pname=0x%x)", pname); } diff --git a/src/mesa/main/get_gen.py b/src/mesa/main/get_gen.py index cecb86d76a..bfaca1536d 100644 --- a/src/mesa/main/get_gen.py +++ b/src/mesa/main/get_gen.py @@ -1122,6 +1122,23 @@ StateVars = [ ( "GL_MAX_SERVER_WAIT_TIMEOUT", GLint64, ["ctx->Const.MaxServerWaitTimeout"], "", NoState, ["ARB_sync"] ), + # GL_EXT_transform_feedback + ( "GL_TRANSFORM_FEEDBACK_BUFFER_BINDING", GLint, + ["ctx->TransformFeedback.CurrentBuffer->Name"], "", + NoState, ["EXT_transform_feedback"] ), + ( "GL_RASTERIZER_DISCARD", GLboolean, + ["ctx->TransformFeedback.RasterDiscard"], "", + NoState, ["EXT_transform_feedback"] ), + ( "GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS", GLint, + ["ctx->Const.MaxTransformFeedbackInterleavedComponents"], "", + NoState, ["EXT_transform_feedback"] ), + ( "GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS", GLint, + ["ctx->Const.MaxTransformFeedbackSeparateAttribs"], "", + NoState, ["EXT_transform_feedback"] ), + ( "GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS", GLint, + ["ctx->Const.MaxTransformFeedbackSeparateComponents"], "", + NoState, ["EXT_transform_feedback"] ), + # GL3 ( "GL_NUM_EXTENSIONS", GLint, ["_mesa_get_extension_count(ctx)"], "", NoState, NoExt ), ( "GL_MAJOR_VERSION", GLint, ["ctx->VersionMajor"], "", NoState, NoExt ), @@ -1134,6 +1151,7 @@ StateVars = [ # The tuples are the same as above, with one exception: the "optional" # code field is instead the max legal index value. IndexedStateVars = [ + # GL_EXT_draw_buffers2 / GL3 ( "GL_BLEND", GLint, ["((ctx->Color.BlendEnabled >> index) & 1)"], "ctx->Const.MaxDrawBuffers", NoState, ["EXT_draw_buffers2"] ), ( "GL_COLOR_WRITEMASK", GLint, @@ -1142,6 +1160,21 @@ IndexedStateVars = [ "ctx->Color.ColorMask[index][BCOMP] ? 1 : 0", "ctx->Color.ColorMask[index][ACOMP] ? 1 : 0" ], "ctx->Const.MaxDrawBuffers", NoState, ["EXT_draw_buffers2"] ), + + # GL_EXT_transform_feedback + ( "GL_TRANSFORM_FEEDBACK_BUFFER_START", GLint64, + ["ctx->TransformFeedback.Offset[index]"], + "ctx->Const.MaxTransformFeedbackSeparateAttribs", + NoState, ["EXT_transform_feedback"] ), + ( "GL_TRANSFORM_FEEDBACK_BUFFER_SIZE", GLint64, + ["ctx->TransformFeedback.Size[index]"], + "ctx->Const.MaxTransformFeedbackSeparateAttribs", + NoState, ["EXT_transform_feedback"] ), + ( "GL_TRANSFORM_FEEDBACK_BUFFER_BINDING", GLint, + ["ctx->TransformFeedback.Buffers[index]->Name"], + "ctx->Const.MaxTransformFeedbackSeparateAttribs", + NoState, ["EXT_transform_feedback"] ), + # XXX more to come... ] diff --git a/src/mesa/main/hash.c b/src/mesa/main/hash.c index 975775469d..b624e6ecac 100644 --- a/src/mesa/main/hash.c +++ b/src/mesa/main/hash.c @@ -120,15 +120,11 @@ _mesa_DeleteHashTable(struct _mesa_HashTable *table) /** - * Lookup an entry in the hash table. - * - * \param table the hash table. - * \param key the key. - * - * \return pointer to user's data or NULL if key not in table + * Lookup an entry in the hash table, without locking. + * \sa _mesa_HashLookup */ -void * -_mesa_HashLookup(struct _mesa_HashTable *table, GLuint key) +static INLINE void * +_mesa_HashLookup_unlocked(struct _mesa_HashTable *table, GLuint key) { GLuint pos; const struct HashEntry *entry; @@ -137,20 +133,36 @@ _mesa_HashLookup(struct _mesa_HashTable *table, GLuint key) assert(key); pos = HASH_FUNC(key); - _glthread_LOCK_MUTEX(table->Mutex); entry = table->Table[pos]; while (entry) { if (entry->Key == key) { - _glthread_UNLOCK_MUTEX(table->Mutex); return entry->Data; } entry = entry->Next; } - _glthread_UNLOCK_MUTEX(table->Mutex); return NULL; } +/** + * Lookup an entry in the hash table. + * + * \param table the hash table. + * \param key the key. + * + * \return pointer to user's data or NULL if key not in table + */ +void * +_mesa_HashLookup(struct _mesa_HashTable *table, GLuint key) +{ + void *res; + assert(table); + _glthread_LOCK_MUTEX(table->Mutex); + res = _mesa_HashLookup_unlocked(table, key); + _glthread_UNLOCK_MUTEX(table->Mutex); + return res; +} + /** * Insert a key/pointer pair into the hash table. @@ -447,7 +459,7 @@ _mesa_HashFindFreeKeyBlock(struct _mesa_HashTable *table, GLuint numKeys) GLuint freeStart = 1; GLuint key; for (key = 1; key != maxKey; key++) { - if (_mesa_HashLookup(table, key)) { + if (_mesa_HashLookup_unlocked(table, key)) { /* darn, this key is already in use */ freeCount = 0; freeStart = key+1; diff --git a/src/mesa/main/mfeatures.h b/src/mesa/main/mfeatures.h index cb96c4d1d0..6ed05da7ac 100644 --- a/src/mesa/main/mfeatures.h +++ b/src/mesa/main/mfeatures.h @@ -68,62 +68,84 @@ * enabled or not. */ +#ifndef FEATURE_ES1 +#define FEATURE_ES1 0 +#endif +#ifndef FEATURE_ES2 +#define FEATURE_ES2 0 +#endif + +#define FEATURE_ES (FEATURE_ES1 || FEATURE_ES2) + +#ifndef FEATURE_GL +#define FEATURE_GL !FEATURE_ES +#endif + #ifdef IN_DRI_DRIVER -#define FEATURE_remap_table 1 +#define FEATURE_remap_table 1 #else -#define FEATURE_remap_table 0 +#define FEATURE_remap_table 0 #endif -#define FEATURE_accum _HAVE_FULL_GL -#define FEATURE_arrayelt _HAVE_FULL_GL -#define FEATURE_attrib_stack _HAVE_FULL_GL +#define FEATURE_dispatch 1 +#define FEATURE_texgen 1 +#define FEATURE_userclip 1 + +#define FEATURE_accum FEATURE_GL +#define FEATURE_arrayelt FEATURE_GL +#define FEATURE_attrib_stack FEATURE_GL /* this disables vtxfmt, api_loopback, and api_noop completely */ -#define FEATURE_beginend _HAVE_FULL_GL -#define FEATURE_colortable _HAVE_FULL_GL -#define FEATURE_convolve _HAVE_FULL_GL -#define FEATURE_dispatch _HAVE_FULL_GL -#define FEATURE_dlist (_HAVE_FULL_GL && FEATURE_arrayelt && FEATURE_beginend) -#define FEATURE_draw_read_buffer _HAVE_FULL_GL -#define FEATURE_drawpix _HAVE_FULL_GL -#define FEATURE_evaluators _HAVE_FULL_GL -#define FEATURE_feedback _HAVE_FULL_GL -#define FEATURE_fixedpt 0 -#define FEATURE_histogram _HAVE_FULL_GL -#define FEATURE_pixel_transfer _HAVE_FULL_GL -#define FEATURE_point_size_array 0 -#define FEATURE_queryobj _HAVE_FULL_GL -#define FEATURE_rastpos _HAVE_FULL_GL -#define FEATURE_texgen _HAVE_FULL_GL -#define FEATURE_texture_fxt1 _HAVE_FULL_GL -#define FEATURE_texture_s3tc _HAVE_FULL_GL -#define FEATURE_userclip _HAVE_FULL_GL -#define FEATURE_vertex_array_byte 0 -#define FEATURE_es2_glsl 0 - -#define FEATURE_ARB_fragment_program _HAVE_FULL_GL -#define FEATURE_ARB_framebuffer_object _HAVE_FULL_GL -#define FEATURE_ARB_map_buffer_range _HAVE_FULL_GL -#define FEATURE_ARB_pixel_buffer_object _HAVE_FULL_GL -#define FEATURE_ARB_vertex_buffer_object _HAVE_FULL_GL -#define FEATURE_ARB_vertex_program _HAVE_FULL_GL -#define FEATURE_ARB_vertex_shader _HAVE_FULL_GL -#define FEATURE_ARB_fragment_shader _HAVE_FULL_GL -#define FEATURE_ARB_shader_objects (FEATURE_ARB_vertex_shader || FEATURE_ARB_fragment_shader) -#define FEATURE_ARB_shading_language_100 FEATURE_ARB_shader_objects -#define FEATURE_ARB_shading_language_120 FEATURE_ARB_shader_objects -#define FEATURE_ARB_sync _HAVE_FULL_GL - -#define FEATURE_EXT_framebuffer_blit _HAVE_FULL_GL -#define FEATURE_EXT_framebuffer_object _HAVE_FULL_GL -#define FEATURE_EXT_pixel_buffer_object _HAVE_FULL_GL -#define FEATURE_APPLE_object_purgeable _HAVE_FULL_GL -#define FEATURE_EXT_texture_sRGB _HAVE_FULL_GL -#define FEATURE_ATI_fragment_shader _HAVE_FULL_GL -#define FEATURE_NV_fence _HAVE_FULL_GL -#define FEATURE_NV_fragment_program _HAVE_FULL_GL -#define FEATURE_NV_vertex_program _HAVE_FULL_GL - -#define FEATURE_OES_EGL_image _HAVE_FULL_GL +#define FEATURE_beginend FEATURE_GL +#define FEATURE_colortable FEATURE_GL +#define FEATURE_convolve FEATURE_GL +#define FEATURE_dlist (FEATURE_GL && FEATURE_arrayelt && FEATURE_beginend) +#define FEATURE_draw_read_buffer FEATURE_GL +#define FEATURE_drawpix FEATURE_GL +#define FEATURE_evaluators FEATURE_GL +#define FEATURE_feedback FEATURE_GL +#define FEATURE_histogram FEATURE_GL +#define FEATURE_pixel_transfer FEATURE_GL +#define FEATURE_queryobj FEATURE_GL +#define FEATURE_rastpos FEATURE_GL +#define FEATURE_texture_fxt1 FEATURE_GL +#define FEATURE_texture_s3tc FEATURE_GL + +#define FEATURE_extra_context_init FEATURE_ES +#define FEATURE_fixedpt FEATURE_ES +#define FEATURE_point_size_array FEATURE_ES +#define FEATURE_vertex_array_byte FEATURE_ES + +#define FEATURE_es2_glsl FEATURE_ES2 + +#define FEATURE_ARB_fragment_program 1 +#define FEATURE_ARB_vertex_program 1 +#define FEATURE_ARB_vertex_shader 1 +#define FEATURE_ARB_fragment_shader 1 +#define FEATURE_ARB_shader_objects (FEATURE_ARB_vertex_shader || FEATURE_ARB_fragment_shader) +#define FEATURE_ARB_shading_language_100 FEATURE_ARB_shader_objects +#define FEATURE_ARB_shading_language_120 FEATURE_ARB_shader_objects + +#define FEATURE_ARB_framebuffer_object (FEATURE_GL && FEATURE_EXT_framebuffer_object) +#define FEATURE_ARB_map_buffer_range FEATURE_GL +#define FEATURE_ARB_pixel_buffer_object (FEATURE_GL && FEATURE_EXT_pixel_buffer_object) +#define FEATURE_ARB_sync FEATURE_GL +#define FEATURE_ARB_vertex_buffer_object 1 + +#define FEATURE_EXT_framebuffer_blit FEATURE_GL +#define FEATURE_EXT_framebuffer_object 1 +#define FEATURE_EXT_pixel_buffer_object 1 +#define FEATURE_EXT_texture_sRGB FEATURE_GL +#define FEATURE_EXT_transform_feedback FEATURE_GL + +#define FEATURE_APPLE_object_purgeable FEATURE_GL +#define FEATURE_ATI_fragment_shader FEATURE_GL +#define FEATURE_NV_fence FEATURE_GL +#define FEATURE_NV_fragment_program FEATURE_GL +#define FEATURE_NV_vertex_program FEATURE_GL +#define FEATURE_OES_EGL_image 1 +#define FEATURE_OES_draw_texture FEATURE_ES1 +#define FEATURE_OES_framebuffer_object FEATURE_ES +#define FEATURE_OES_mapbuffer FEATURE_ES #endif /* FEATURES_H */ diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 82e004f348..7657efb077 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -1910,6 +1910,11 @@ struct gl_query_state /** GL_NV_conditional_render */ struct gl_query_object *CondRenderQuery; + + /** GL_EXT_transform_feedback */ + struct gl_query_object *PrimitivesGenerated; + struct gl_query_object *PrimitivesWritten; + GLenum CondRenderMode; }; @@ -1976,6 +1981,13 @@ struct gl_shader_program /** User-defined attribute bindings (glBindAttribLocation) */ struct gl_program_parameter_list *Attributes; + /** Transform feedback varyings */ + struct { + GLenum BufferMode; + GLuint NumVarying; + GLchar **VaryingNames; /**< Array [NumVarying] of char * */ + } TransformFeedback; + /* post-link info: */ struct gl_vertex_program *VertexProgram; /**< Linked vertex program */ struct gl_fragment_program *FragmentProgram; /**< Linked fragment prog */ @@ -2017,6 +2029,29 @@ struct gl_shader_state /** + * Context state for transform feedback. + */ +struct gl_transform_feedback +{ + GLboolean Active; /**< Is transform feedback enabled? */ + GLenum Mode; /**< GL_POINTS, GL_LINES or GL_TRIANGLES */ + /** Start of feedback data in dest buffer */ + GLintptr Offset[MAX_FEEDBACK_ATTRIBS]; + /** Max data to put into dest buffer (in bytes) */ + GLsizeiptr Size[MAX_FEEDBACK_ATTRIBS]; + GLboolean RasterDiscard; /**< GL_RASTERIZER_DISCARD */ + + /** The general binding point (GL_TRANSFORM_FEEDBACK_BUFFER) */ + struct gl_buffer_object *CurrentBuffer; + + /** The feedback buffers */ + GLuint BufferNames[MAX_FEEDBACK_ATTRIBS]; + struct gl_buffer_object *Buffers[MAX_FEEDBACK_ATTRIBS]; +}; + + + +/** * State which can be shared by multiple contexts: */ struct gl_shared_state @@ -2388,6 +2423,11 @@ struct gl_constants /**< OpenGL version 3.x */ GLbitfield ContextFlags; /**< Ex: GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT */ + + /** GL_EXT_transform_feedback */ + GLuint MaxTransformFeedbackSeparateAttribs; + GLuint MaxTransformFeedbackSeparateComponents; + GLuint MaxTransformFeedbackInterleavedComponents; }; @@ -2489,6 +2529,7 @@ struct gl_extensions GLboolean EXT_texture_mirror_clamp; GLboolean EXT_texture_sRGB; GLboolean EXT_texture_swizzle; + GLboolean EXT_transform_feedback; GLboolean EXT_timer_query; GLboolean EXT_vertex_array; GLboolean EXT_vertex_array_bgra; @@ -2956,6 +2997,8 @@ struct __GLcontextRec struct gl_query_state Query; /**< occlusion, timer queries */ + struct gl_transform_feedback TransformFeedback; + struct gl_buffer_object *CopyReadBuffer; /**< GL_ARB_copy_buffer */ struct gl_buffer_object *CopyWriteBuffer; /**< GL_ARB_copy_buffer */ /*@}*/ diff --git a/src/mesa/main/queryobj.c b/src/mesa/main/queryobj.c index e14511a388..a907dac836 100644 --- a/src/mesa/main/queryobj.c +++ b/src/mesa/main/queryobj.c @@ -130,6 +130,42 @@ _mesa_init_query_object_functions(struct dd_function_table *driver) } +/** + * Return pointer to the query object binding point for the given target. + * \return NULL if invalid target, else the address of binding point + */ +static struct gl_query_object ** +get_query_binding_point(GLcontext *ctx, GLenum target) +{ + switch (target) { + case GL_SAMPLES_PASSED_ARB: + if (ctx->Extensions.ARB_occlusion_query) + return &ctx->Query.CurrentOcclusionObject; + else + return NULL; + case GL_TIME_ELAPSED_EXT: + if (ctx->Extensions.EXT_timer_query) + return &ctx->Query.CurrentTimerObject; + else + return NULL; +#if FEATURE_EXT_transform_feedback + case GL_PRIMITIVES_GENERATED: + if (ctx->Extensions.EXT_transform_feedback) + return &ctx->Query.PrimitivesGenerated; + else + return NULL; + case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: + if (ctx->Extensions.EXT_transform_feedback) + return &ctx->Query.PrimitivesWritten; + else + return NULL; +#endif + default: + return NULL; + } +} + + void GLAPIENTRY _mesa_GenQueriesARB(GLsizei n, GLuint *ids) { @@ -214,36 +250,16 @@ _mesa_IsQueryARB(GLuint id) static void GLAPIENTRY _mesa_BeginQueryARB(GLenum target, GLuint id) { - struct gl_query_object *q; + struct gl_query_object *q, **bindpt; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); FLUSH_VERTICES(ctx, _NEW_DEPTH); - switch (target) { - case GL_SAMPLES_PASSED_ARB: - if (!ctx->Extensions.ARB_occlusion_query) { - _mesa_error(ctx, GL_INVALID_ENUM, "glBeginQueryARB(target)"); - return; - } - if (ctx->Query.CurrentOcclusionObject) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginQueryARB"); - return; - } - break; - case GL_TIME_ELAPSED_EXT: - if (!ctx->Extensions.EXT_timer_query) { - _mesa_error(ctx, GL_INVALID_ENUM, "glBeginQueryARB(target)"); - return; - } - if (ctx->Query.CurrentTimerObject) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginQueryARB"); - return; - } - break; - default: - _mesa_error(ctx, GL_INVALID_ENUM, "glBeginQueryARB(target)"); - return; + bindpt = get_query_binding_point(ctx, target); + if (!bindpt) { + _mesa_error(ctx, GL_INVALID_ENUM, "glBeginQueryARB(target)"); + return; } if (id == 0) { @@ -275,12 +291,8 @@ _mesa_BeginQueryARB(GLenum target, GLuint id) q->Result = 0; q->Ready = GL_FALSE; - if (target == GL_SAMPLES_PASSED_ARB) { - ctx->Query.CurrentOcclusionObject = q; - } - else if (target == GL_TIME_ELAPSED_EXT) { - ctx->Query.CurrentTimerObject = q; - } + /* XXX should probably refcount query objects */ + *bindpt = q; ctx->Driver.BeginQuery(ctx, q); } @@ -289,34 +301,22 @@ _mesa_BeginQueryARB(GLenum target, GLuint id) static void GLAPIENTRY _mesa_EndQueryARB(GLenum target) { - struct gl_query_object *q; + struct gl_query_object *q, **bindpt; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); FLUSH_VERTICES(ctx, _NEW_DEPTH); - switch (target) { - case GL_SAMPLES_PASSED_ARB: - if (!ctx->Extensions.ARB_occlusion_query) { - _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)"); - return; - } - q = ctx->Query.CurrentOcclusionObject; - ctx->Query.CurrentOcclusionObject = NULL; - break; - case GL_TIME_ELAPSED_EXT: - if (!ctx->Extensions.EXT_timer_query) { - _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)"); - return; - } - q = ctx->Query.CurrentTimerObject; - ctx->Query.CurrentTimerObject = NULL; - break; - default: - _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)"); - return; + bindpt = get_query_binding_point(ctx, target); + if (!bindpt) { + _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)"); + return; } + /* XXX should probably refcount query objects */ + q = *bindpt; + *bindpt = NULL; + if (!q || !q->Active) { _mesa_error(ctx, GL_INVALID_OPERATION, "glEndQueryARB(no matching glBeginQueryARB)"); @@ -331,30 +331,18 @@ _mesa_EndQueryARB(GLenum target) void GLAPIENTRY _mesa_GetQueryivARB(GLenum target, GLenum pname, GLint *params) { - struct gl_query_object *q; + struct gl_query_object *q, **bindpt; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); - switch (target) { - case GL_SAMPLES_PASSED_ARB: - if (!ctx->Extensions.ARB_occlusion_query) { - _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)"); - return; - } - q = ctx->Query.CurrentOcclusionObject; - break; - case GL_TIME_ELAPSED_EXT: - if (!ctx->Extensions.EXT_timer_query) { - _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)"); - return; - } - q = ctx->Query.CurrentTimerObject; - break; - default: - _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryivARB(target)"); - return; + bindpt = get_query_binding_point(ctx, target); + if (!bindpt) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryARB(target)"); + return; } + q = *bindpt; + switch (pname) { case GL_QUERY_COUNTER_BITS_ARB: *params = 8 * sizeof(q->Result); diff --git a/src/mesa/main/texparam.c b/src/mesa/main/texparam.c index 714c4cfd52..ca03404f12 100644 --- a/src/mesa/main/texparam.c +++ b/src/mesa/main/texparam.c @@ -371,7 +371,7 @@ set_tex_parameteri(GLcontext *ctx, } return GL_FALSE; -#ifdef FEATURE_OES_draw_texture +#if FEATURE_OES_draw_texture case GL_TEXTURE_CROP_RECT_OES: texObj->CropRect[0] = params[0]; texObj->CropRect[1] = params[1]; @@ -604,7 +604,7 @@ _mesa_TexParameterfv(GLenum target, GLenum pname, const GLfloat *params) } break; -#ifdef FEATURE_OES_draw_texture +#if FEATURE_OES_draw_texture case GL_TEXTURE_CROP_RECT_OES: { /* convert float params to int */ @@ -1160,7 +1160,7 @@ _mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params ) else error = GL_TRUE; break; -#ifdef FEATURE_OES_draw_texture +#if FEATURE_OES_draw_texture case GL_TEXTURE_CROP_RECT_OES: params[0] = obj->CropRect[0]; params[1] = obj->CropRect[1]; @@ -1330,7 +1330,7 @@ _mesa_GetTexParameteriv( GLenum target, GLenum pname, GLint *params ) error = GL_TRUE; } break; -#ifdef FEATURE_OES_draw_texture +#if FEATURE_OES_draw_texture case GL_TEXTURE_CROP_RECT_OES: params[0] = obj->CropRect[0]; params[1] = obj->CropRect[1]; diff --git a/src/mesa/main/transformfeedback.c b/src/mesa/main/transformfeedback.c new file mode 100644 index 0000000000..3490110bae --- /dev/null +++ b/src/mesa/main/transformfeedback.c @@ -0,0 +1,427 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 2010 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 + * THE AUTHORS 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. + */ + + +/* + * Vertex transform feedback support. + * + * Authors: + * Brian Paul + */ + + +#include "buffers.h" +#include "bufferobj.h" +#include "context.h" +#include "enums.h" +#include "transformfeedback.h" + +#include "shader/prog_parameter.h" +#include "shader/shader_api.h" + + +/** + * Check if the given primitive mode (as in glBegin(mode)) is compatible + * with the current transform feedback mode (if it's enabled). + * This is to be called from glBegin(), glDrawArrays(), glDrawElements(), etc. + * + * \return GL_TRUE if the mode is OK, GL_FALSE otherwise. + */ +GLboolean +_mesa_validate_primitive_mode(GLcontext *ctx, GLenum mode) +{ + if (ctx->TransformFeedback.Active) { + switch (mode) { + case GL_POINTS: + return ctx->TransformFeedback.Mode == GL_POINTS; + case GL_LINES: + case GL_LINE_STRIP: + case GL_LINE_LOOP: + return ctx->TransformFeedback.Mode == GL_LINES; + default: + return ctx->TransformFeedback.Mode == GL_TRIANGLES; + } + } + return GL_TRUE; +} + + +/** + * Check that all the buffer objects currently bound for transform + * feedback actually exist. Raise a GL_INVALID_OPERATION error if + * any buffers are missing. + * \return GL_TRUE for success, GL_FALSE if error + */ +GLboolean +_mesa_validate_transform_feedback_buffers(GLcontext *ctx) +{ + + return GL_TRUE; +} + + + +/** + * Per-context init for transform feedback. + */ +void +_mesa_init_transform_feedback(GLcontext *ctx) +{ + _mesa_reference_buffer_object(ctx, + &ctx->TransformFeedback.CurrentBuffer, + ctx->Shared->NullBufferObj); +} + + +/** + * Per-context free/clean-up for transform feedback. + */ +void +_mesa_free_transform_feedback(GLcontext *ctx) +{ + _mesa_reference_buffer_object(ctx, + &ctx->TransformFeedback.CurrentBuffer, + NULL); +} + + +void GLAPIENTRY +_mesa_BeginTransformFeedback(GLenum mode) +{ + GET_CURRENT_CONTEXT(ctx); + + switch (mode) { + case GL_POINTS: + case GL_LINES: + case GL_TRIANGLES: + /* legal */ + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glBeginTransformFeedback(mode)"); + return; + } + + if (ctx->TransformFeedback.Active) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBeginTransformFeedback(already active)"); + return; + } + + ctx->TransformFeedback.Active = GL_TRUE; + ctx->TransformFeedback.Mode = mode; +} + + +void GLAPIENTRY +_mesa_EndTransformFeedback(void) +{ + GET_CURRENT_CONTEXT(ctx); + + if (!ctx->TransformFeedback.Active) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glEndTransformFeedback(not active)"); + return; + } + + ctx->TransformFeedback.Active = GL_FALSE; +} + + +/** + * Helper used by BindBufferRange() and BindBufferBase(). + */ +static void +bind_buffer_range(GLcontext *ctx, GLuint index, + struct gl_buffer_object *bufObj, + GLintptr offset, GLsizeiptr size) +{ + /* The general binding point */ + _mesa_reference_buffer_object(ctx, + &ctx->TransformFeedback.CurrentBuffer, + bufObj); + + /* The per-attribute binding point */ + _mesa_reference_buffer_object(ctx, + &ctx->TransformFeedback.Buffers[index], + bufObj); + + ctx->TransformFeedback.BufferNames[index] = bufObj->Name; + + ctx->TransformFeedback.Offset[index] = offset; + ctx->TransformFeedback.Size[index] = size; +} + + +/** + * Specify a buffer object to receive vertex shader results. Plus, + * specify the starting offset to place the results, and max size. + */ +void GLAPIENTRY +_mesa_BindBufferRange(GLenum target, GLuint index, + GLuint buffer, GLintptr offset, GLsizeiptr size) +{ + struct gl_buffer_object *bufObj; + GET_CURRENT_CONTEXT(ctx); + + if (target != GL_TRANSFORM_FEEDBACK_BUFFER) { + _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferRange(target)"); + return; + } + + if (ctx->TransformFeedback.Active) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBindBufferRange(transform feedback active)"); + return; + } + + if (index >= ctx->Const.MaxTransformFeedbackSeparateAttribs) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(index=%d)", index); + return; + } + + if ((size <= 0) || (size & 0x3)) { + /* must be positive and multiple of four */ + _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(size%d)", size); + return; + } + + if (offset & 0x3) { + /* must be multiple of four */ + _mesa_error(ctx, GL_INVALID_VALUE, + "glBindBufferRange(offset=%d)", offset); + return; + } + + bufObj = _mesa_lookup_bufferobj(ctx, buffer); + if (!bufObj) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBindBufferRange(invalid buffer=%u)", buffer); + return; + } + + if (offset + size >= bufObj->Size) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glBindBufferRange(offset + size > buffer size)", size); + return; + } + + bind_buffer_range(ctx, index, bufObj, offset, size); +} + + +/** + * Specify a buffer object to receive vertex shader results. + * As above, but start at offset = 0. + */ +void GLAPIENTRY +_mesa_BindBufferBase(GLenum target, GLuint index, GLuint buffer) +{ + struct gl_buffer_object *bufObj; + GET_CURRENT_CONTEXT(ctx); + GLsizeiptr size; + + if (target != GL_TRANSFORM_FEEDBACK_BUFFER) { + _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferBase(target)"); + return; + } + + if (ctx->TransformFeedback.Active) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBindBufferRange(transform feedback active)"); + return; + } + + if (index >= ctx->Const.MaxTransformFeedbackSeparateAttribs) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferBase(index=%d)", index); + return; + } + + bufObj = _mesa_lookup_bufferobj(ctx, buffer); + if (!bufObj) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBindBufferBase(invalid buffer=%u)", buffer); + return; + } + + /* default size is the buffer size rounded down to nearest + * multiple of four. + */ + size = bufObj->Size & ~0x3; + + bind_buffer_range(ctx, index, bufObj, 0, size); +} + + +/** + * Specify a buffer object to receive vertex shader results, plus the + * offset in the buffer to start placing results. + * This function is part of GL_EXT_transform_feedback, but not GL3. + */ +void GLAPIENTRY +_mesa_BindBufferOffsetEXT(GLenum target, GLuint index, GLuint buffer, + GLintptr offset) +{ + struct gl_buffer_object *bufObj; + GET_CURRENT_CONTEXT(ctx); + GLsizeiptr size; + + if (target != GL_TRANSFORM_FEEDBACK_BUFFER) { + _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferOffsetEXT(target)"); + return; + } + + if (ctx->TransformFeedback.Active) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBindBufferRange(transform feedback active)"); + return; + } + + if (index >= ctx->Const.MaxTransformFeedbackSeparateAttribs) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glBindBufferOffsetEXT(index=%d)", index); + return; + } + + bufObj = _mesa_lookup_bufferobj(ctx, buffer); + if (!bufObj) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBindBufferOffsetEXT(invalid buffer=%u)", buffer); + return; + } + + /* default size is the buffer size rounded down to nearest + * multiple of four. + */ + size = (bufObj->Size - offset) & ~0x3; + + bind_buffer_range(ctx, index, bufObj, offset, size); +} + + +/** + * This function specifies the vertex shader outputs to be written + * to the feedback buffer(s), and in what order. + */ +void GLAPIENTRY +_mesa_TransformFeedbackVaryings(GLuint program, GLsizei count, + const GLchar **varyings, GLenum bufferMode) +{ + struct gl_shader_program *shProg; + GLuint i; + GET_CURRENT_CONTEXT(ctx); + + switch (bufferMode) { + case GL_INTERLEAVED_ATTRIBS: + break; + case GL_SEPARATE_ATTRIBS: + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, + "glTransformFeedbackVaryings(bufferMode)"); + return; + } + + if (count < 0 || count > ctx->Const.MaxTransformFeedbackSeparateAttribs) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glTransformFeedbackVaryings(count=%d)", count); + return; + } + + shProg = _mesa_lookup_shader_program(ctx, program); + if (!shProg) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glTransformFeedbackVaryings(program=%u)", program); + return; + } + + /* free existing varyings, if any */ + for (i = 0; i < shProg->TransformFeedback.NumVarying; i++) { + free(shProg->TransformFeedback.VaryingNames[i]); + } + free(shProg->TransformFeedback.VaryingNames); + + /* allocate new memory for varying names */ + shProg->TransformFeedback.VaryingNames = + (GLchar **) malloc(count * sizeof(GLchar *)); + + if (!shProg->TransformFeedback.VaryingNames) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTransformFeedbackVaryings()"); + return; + } + + /* Save the new names and the count */ + for (i = 0; i < (GLuint) count; i++) { + shProg->TransformFeedback.VaryingNames[i] = _mesa_strdup(varyings[i]); + } + shProg->TransformFeedback.NumVarying = count; + + shProg->TransformFeedback.BufferMode = bufferMode; + + /* The varyings won't be used until shader link time */ +} + + +/** + * Get info about the vertex shader's outputs which are to be written + * to the feedback buffer(s). + */ +void GLAPIENTRY +_mesa_GetTransformFeedbackVarying(GLuint program, GLuint index, + GLsizei bufSize, GLsizei *length, + GLsizei *size, GLenum *type, GLchar *name) +{ + const struct gl_shader_program *shProg; + const GLchar *varyingName; + GLint v; + GET_CURRENT_CONTEXT(ctx); + + shProg = _mesa_lookup_shader_program(ctx, program); + if (!shProg) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glGetTransformFeedbackVaryings(program=%u)", program); + return; + } + + if (index >= shProg->TransformFeedback.NumVarying) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glGetTransformFeedbackVaryings(index=%u)", index); + return; + } + + varyingName = shProg->TransformFeedback.VaryingNames[index]; + + v = _mesa_lookup_parameter_index(shProg->Varying, -1, varyingName); + if (v >= 0) { + struct gl_program_parameter *param = &shProg->Varying->Parameters[v]; + + /* return the varying's name and length */ + _mesa_copy_string(name, bufSize, length, varyingName); + + /* return the datatype and value's size (in datatype units) */ + if (type) + *type = param->Type; + if (size) + *size = param->Size; + } +} + diff --git a/src/mesa/main/transformfeedback.h b/src/mesa/main/transformfeedback.h new file mode 100644 index 0000000000..e89cc41473 --- /dev/null +++ b/src/mesa/main/transformfeedback.h @@ -0,0 +1,71 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 2010 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 + * THE AUTHORS 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 TRANSFORM_FEEDBACK_H +#define TRANSFORM_FEEDBACK_H + +#include "glheader.h" + + +extern GLboolean +_mesa_validate_primitive_mode(GLcontext *ctx, GLenum mode); + +extern GLboolean +_mesa_validate_transform_feedback_buffers(GLcontext *ctx); + +extern void +_mesa_init_transform_feedback(GLcontext *ctx); + +extern void +_mesa_free_transform_feedback(GLcontext *ctx); + + +extern void GLAPIENTRY +_mesa_BeginTransformFeedback(GLenum mode); + +extern void GLAPIENTRY +_mesa_EndTransformFeedback(void); + +extern void GLAPIENTRY +_mesa_BindBufferRange(GLenum target, GLuint index, + GLuint buffer, GLintptr offset, GLsizeiptr size); + +extern void GLAPIENTRY +_mesa_BindBufferBase(GLenum target, GLuint index, GLuint buffer); + +extern void GLAPIENTRY +_mesa_BindBufferOffsetEXT(GLenum target, GLuint index, GLuint buffer, + GLintptr offset); + +extern void GLAPIENTRY +_mesa_TransformFeedbackVaryings(GLuint program, GLsizei count, + const GLchar **varyings, GLenum bufferMode); + +extern void GLAPIENTRY +_mesa_GetTransformFeedbackVarying(GLuint program, GLuint index, + GLsizei bufSize, GLsizei *length, + GLsizei *size, GLenum *type, GLchar *name); + + +#endif /* TRANSFORM_FEEDBACK_H */ diff --git a/src/mesa/shader/shader_api.c b/src/mesa/shader/shader_api.c index 940fe2d03c..36fe0a1bb7 100644 --- a/src/mesa/shader/shader_api.c +++ b/src/mesa/shader/shader_api.c @@ -123,6 +123,14 @@ _mesa_free_shader_program_data(GLcontext *ctx, free(shProg->InfoLog); shProg->InfoLog = NULL; } + + /* Transform feedback varying vars */ + for (i = 0; i < shProg->TransformFeedback.NumVarying; i++) { + free(shProg->TransformFeedback.VaryingNames[i]); + } + free(shProg->TransformFeedback.VaryingNames); + shProg->TransformFeedback.VaryingNames = NULL; + shProg->TransformFeedback.NumVarying = 0; } @@ -397,6 +405,25 @@ get_shader_flags(void) /** + * Find the length of the longest transform feedback varying name + * which was specified with glTransformFeedbackVaryings(). + */ +static GLint +longest_feedback_varying_name(const struct gl_shader_program *shProg) +{ + GLuint i; + GLint max = 0; + for (i = 0; i < shProg->TransformFeedback.NumVarying; i++) { + GLint len = strlen(shProg->TransformFeedback.VaryingNames[i]); + if (len > max) + max = len; + } + return max; +} + + + +/** * Initialize context's shader state. */ void @@ -437,8 +464,9 @@ _mesa_free_shader_state(GLcontext *ctx) * \param length returns number of chars copied * \param dst the string destination */ -static void -copy_string(GLchar *dst, GLsizei maxLength, GLsizei *length, const GLchar *src) +void +_mesa_copy_string(GLchar *dst, GLsizei maxLength, + GLsizei *length, const GLchar *src) { GLsizei len; for (len = 0; len < maxLength - 1 && src && src[len]; len++) @@ -879,7 +907,8 @@ _mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index, return; } - copy_string(nameOut, maxLength, length, attribs->Parameters[index].Name); + _mesa_copy_string(nameOut, maxLength, length, + attribs->Parameters[index].Name); if (size) *size = attribs->Parameters[index].Size @@ -954,7 +983,7 @@ _mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index, param = &prog->Parameters->Parameters[progPos]; if (nameOut) { - copy_string(nameOut, maxLength, length, param->Name); + _mesa_copy_string(nameOut, maxLength, length, param->Name); } if (size) { @@ -1063,6 +1092,17 @@ _mesa_get_programiv(GLcontext *ctx, GLuint program, case GL_PROGRAM_BINARY_LENGTH_OES: *params = 0; break; +#if FEATURE_EXT_transform_feedback + case GL_TRANSFORM_FEEDBACK_VARYINGS: + *params = shProg->TransformFeedback.NumVarying; + break; + case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH: + *params = longest_feedback_varying_name(shProg) + 1; + break; + case GL_TRANSFORM_FEEDBACK_BUFFER_MODE: + *params = shProg->TransformFeedback.BufferMode; + break; +#endif default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)"); return; @@ -1112,7 +1152,7 @@ _mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize, _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)"); return; } - copy_string(infoLog, bufSize, length, shProg->InfoLog); + _mesa_copy_string(infoLog, bufSize, length, shProg->InfoLog); } @@ -1125,7 +1165,7 @@ _mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize, _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)"); return; } - copy_string(infoLog, bufSize, length, sh->InfoLog); + _mesa_copy_string(infoLog, bufSize, length, sh->InfoLog); } @@ -1141,7 +1181,7 @@ _mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength, if (!sh) { return; } - copy_string(sourceOut, maxLength, length, sh->Source); + _mesa_copy_string(sourceOut, maxLength, length, sh->Source); } diff --git a/src/mesa/shader/shader_api.h b/src/mesa/shader/shader_api.h index d08d47373e..3ed52747cd 100644 --- a/src/mesa/shader/shader_api.h +++ b/src/mesa/shader/shader_api.h @@ -42,6 +42,12 @@ _mesa_init_shader_state(GLcontext * ctx); extern void _mesa_free_shader_state(GLcontext *ctx); + +extern void +_mesa_copy_string(GLchar *dst, GLsizei maxLength, + GLsizei *length, const GLchar *src); + + /* extern struct gl_shader_program * _mesa_new_shader_program(GLcontext *ctx, GLuint name); diff --git a/src/mesa/sources.mak b/src/mesa/sources.mak index d6ae696e39..996172d9a5 100644 --- a/src/mesa/sources.mak +++ b/src/mesa/sources.mak @@ -80,6 +80,7 @@ MAIN_SOURCES = \ main/texrender.c \ main/texstate.c \ main/texstore.c \ + main/transformfeedback.c \ main/varray.c \ main/version.c \ main/viewport.c \ diff --git a/src/mesa/state_tracker/st_atom_rasterizer.c b/src/mesa/state_tracker/st_atom_rasterizer.c index 9c9a99bcfc..5669b1f82a 100644 --- a/src/mesa/state_tracker/st_atom_rasterizer.c +++ b/src/mesa/state_tracker/st_atom_rasterizer.c @@ -209,7 +209,7 @@ static void update_raster_state( struct st_context *st ) */ if (vertProg) { if (vertProg->Base.Id == 0) { - if (vertProg->Base.OutputsWritten & (1 << VERT_RESULT_PSIZ)) { + if (vertProg->Base.OutputsWritten & BITFIELD64_BIT(VERT_RESULT_PSIZ)) { /* generated program which emits point size */ raster->point_size_per_vertex = TRUE; } diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c index 7f8677d400..6e8c446f78 100644 --- a/src/mesa/state_tracker/st_program.c +++ b/src/mesa/state_tracker/st_program.c @@ -121,7 +121,7 @@ st_prepare_vertex_program(struct st_context *st, /* Compute mapping of vertex program outputs to slots. */ for (attr = 0; attr < VERT_RESULT_MAX; attr++) { - if ((stvp->Base.Base.OutputsWritten & (1 << attr)) == 0) { + if ((stvp->Base.Base.OutputsWritten & BITFIELD64_BIT(attr)) == 0) { stvp->result_to_output[attr] = ~0; } else { @@ -388,7 +388,7 @@ st_translate_fragment_program(struct st_context *st, GLbitfield64 outputsWritten = stfp->Base.Base.OutputsWritten; /* if z is written, emit that first */ - if (outputsWritten & (1 << FRAG_RESULT_DEPTH)) { + if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) { fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_POSITION; fs_output_semantic_index[fs_num_outputs] = 0; outputMapping[FRAG_RESULT_DEPTH] = fs_num_outputs; @@ -398,7 +398,7 @@ st_translate_fragment_program(struct st_context *st, /* handle remaning outputs (color) */ for (attr = 0; attr < FRAG_RESULT_MAX; attr++) { - if (outputsWritten & (1 << attr)) { + if (outputsWritten & BITFIELD64_BIT(attr)) { switch (attr) { case FRAG_RESULT_DEPTH: /* handled above */ |