diff options
author | keithw <keithw> | 2002-08-26 20:02:06 +0000 |
---|---|---|
committer | keithw <keithw> | 2002-08-26 20:02:06 +0000 |
commit | b5b945e19c2b8f44505bc2ee610ef4926f1415a6 (patch) | |
tree | 7e8c7d79f56117136a43ccb15b62d3d827f6a87c | |
parent | c208130512ae88d0233d3e57ac34734dae37caf7 (diff) |
merged trunk into branch
65 files changed, 14195 insertions, 4691 deletions
diff --git a/xc/config/cf/host.def b/xc/config/cf/host.def index 9b75fb55c..59dae4488 100644 --- a/xc/config/cf/host.def +++ b/xc/config/cf/host.def @@ -25,7 +25,7 @@ #else #define XF86CardDrivers tdfx i810 mga ati glint vga -#define DriDrivers tdfx mga i810 r128 radeon gamma i830 /* sis ffb */ +#define DriDrivers r200 tdfx mga i810 r128 radeon gamma i830 /* sis ffb */ #endif @@ -61,6 +61,7 @@ * Warning: trailing blanks will cause build failures. */ /* #define ProjectRoot /usr/X11R6-DRI */ +#define ProjectRoot /home/XF4/xc-r200 /* Optionally turn this on to force the kernel modules to build */ #define BuildXF86DRM YES diff --git a/xc/extras/Mesa/docs/VERSIONS b/xc/extras/Mesa/docs/VERSIONS index c503de8a6..7259f7557 100644 --- a/xc/extras/Mesa/docs/VERSIONS +++ b/xc/extras/Mesa/docs/VERSIONS @@ -1,4 +1,3 @@ -$Id: VERSIONS,v 1.1.1.2 2000/12/05 16:38:42 dawes Exp $ Mesa Version History @@ -776,10 +775,11 @@ Mesa Version History - finished internal support for compressed textures for DRI -3.4.1 December ??, 2000 +3.4.1 February 14, 2001 New: - fixed some Linux build problems - fixed some Windows build problems + - GL_EXT_texture_env_dot3 extension (Gareth Hughes) Bug fixes: - added RENDER_START/RENDER_FINISH macros for glCopyTexImage in DRI - various state-update code changes needed for DRI bugs @@ -789,3 +789,194 @@ Mesa Version History - GLX_PBUFFER enum value was wrong in glx.h - fixed a glColorMaterial lighting bug - fixed bad args to Read/WriteStencilSpan in h/w stencil clear function + - glXCopySubBufferMESA() Y position was off by one + - Error checking of glTexSubImage3D() was broken (bug 128775) + - glPopAttrib() didn't restore all derived Mesa state correctly + - Better glReadPixels accuracy for 16bpp color - fixes lots of OpenGL + conformance problems at 16bpp. + - clearing depth buffer with scissoring was broken, would segfault + - OSMesaGetDepthBuffer() returned bad bytesPerValue value + - fixed a line clipping bug (reported by Craig McDaniel) + - fixed RGB color over/underflow bug for very tiny triangles + Known problems: + - NURBS or evaluator surfaces inside display lists don't always work + + +3.4.2 May 17, 2001 + Bug fixes: + - deleting the currently bound texture could cause bad problems + - using fog could result in random vertex alpha values + - AA triangle rendering could touch pixels outside right window bound + - fixed byteswapping problem in clear_32bit_ximage() function + - fixed bugs in wglUseFontBitmapsA(), by Frank Warmerdam + - fixed memory leak in glXUseXFont() + - fragment sampling in AA triangle function was off by 1/2 pixel + - Windows: reading pixels from framebuffer didn't always work + - glConvolutionFilter2D could segfault or cause FP exception + - fixed segfaults in FX and X drivers when using tex unit 1 but not 0 + - GL_NAND logicop didn't work right in RGBA mode + - fixed a memory corruption bug in vertex buffer reset code + - clearing the softwara alpha buffer with scissoring was broken + - fixed a few color index mode fog bugs + - fixed some bad assertions in color index mode + - fixed FX line 'stipple' bug #420091 + - fixed stencil buffer clear width/height typo + - fixed GL error glitches in gl[Client]ActiveTextureARB() + - fixed Windows compilation problem in texutil.c + - fixed 1/8-pixel AA triangle sampling error + Changes: + - optimized writing mono-colored pixel spans to X pixmaps + - increased max viewport size to 2048 x 2048 + + +3.5 June 21, 2001 + New: + - internals of Mesa divided into modular pieces (Keith Whitwell) + - 100% OpenGL 1.2 conformance (passes all conformance tests) + - new AA line algorithm + - GL_EXT_convolution extension + - GL_ARB_imaging subset + - OSMesaCreateContextExt() function + - GL_ARB_texture_env_add extension (same as GL_EXT_texture_env_add) + - GL_MAX_TEXTURE_UNITS_ARB now defaults to eight + - GL_EXT_fog_coord extension (Keith Whitwell) + - GL_EXT_secondary_color extension (Keith Whitwell) + - GL_ARB_texture_env_add extension (same as GL_EXT_texture_env_add) + - GL_SGIX_depth_texture extension + - GL_SGIX_shadow and GL_SGIX_shadow_ambient extensions + - demos/shadowtex.c demo of GL_SGIX_depth_texture and GL_SGIX_shadow + - GL_ARB_texture_env_combine extension + - GL_ARB_texture_env_dot3 extension + - GL_ARB_texture_border_clamp (aka GL_SGIS_texture_border_clamp) + - OSMesaCreateContextExt() function + - libOSMesa.so library, contains the OSMesa driver interface + - GL/glxext.h header file for GLX extensions + - somewhat faster software texturing, fogging, depth testing + - all color-index conformance tests now pass (only 8bpp tested) + - SPARC assembly language TCL optimizations (David Miller) + - GL_SGIS_generate_mipmap extension + Bug Fixes: + - fbiRev and tmuRev were unitialized when using Glide3 + - fixed a few color index mode conformance failures; all pass now + - now appling antialiasing coverage to alpha after texturing + - colors weren't getting clamped to [0,1] before color table lookup + - fixed RISC alignment errors caused by COPY_4UBV macro + - drawing wide, flat-shaded lines could cause a segfault + - vertices now snapped to 1/16 pixel to fix rendering of tiny triangles + Changes: + - SGI's Sample Implementation (SI) 1.3 GLU library replaces Mesa GLU + - new libOSMesa.so library, contains the OSMesa driver interface + + +4.0 October 22, 2001 + New: + - Mesa 4.0 implements the OpenGL 1.3 specification + - GL_IBM_rasterpos_clip extension + - GL_EXT_texture_edge_clamp extension (aka GL_SGIS_texture_edge_clamp) + - GL_ARB_texture_mirrored_repeat extension + - WindML UGL driver (Stephane Raimbault) + - added OSMESA_MAX_WIDTH/HEIGHT queries + - attempted compiliation fixes for Solaris 5, 7 and 8 + - updated glext.h and glxext.h files + - updated Windows driver (Karl Schultz) + Bug fixes: + - added some missing GLX 1.3 tokens to include/GL/glx.h + - GL_COLOR_MATRIX changes weren't recognized by teximage functions + - glCopyPixels with scale and bias was broken + - glRasterPos with lighting could segfault + - glDeleteTextures could leave a dangling pointer + - Proxy textures for cube maps didn't work + - fixed a number of 16-bit color channel bugs + - fixed a few minor memory leaks + - GLX context sharing was broken in 3.5 + - fixed state-update bugs in glPopClientAttrib() + - fixed glDrawRangeElements() bug + - fixed a glPush/PopAttrib() bug related to texture binding + - flat-shaded, textured lines were broken + - fixed a dangling pointer problem in the XMesa code (Chris Burghart) + - lighting didn't always produce the correct alpha value + - fixed 3DNow! code to not read past end of arrays (Andrew Lewycky) + + +4.0.1 December 17, 2001 + New: + - better sub-pixel sample positions for AA triangles (Ray Tice) + - slightly faster blending for (GL_ZERO, GL_ONE) and (GL_ONE, GL_ZERO) + Bug fixes: + - added missing break statements in glGet*() for multisample cases + - fixed uninitialized hash table mutex bug (display lists / texobjs) + - fixed bad teximage error check conditional (bug 476846) + - fixed demos readtex.c compilation problem on Windows (Karl Schultz) + - added missing glGet() query for GL_MAX_TEXTURE_LOD_BIAS_EXT + - silence some compiler warnings (gcc 2.96) + - enable the #define GL_VERSION_1_3 in GL/gl.h + - added GL 1.3 and GLX 1.4 entries to gl_mangle.h and glx_mangle.h + - fixed glu.h typedef problem found with MSDev 6.0 + - build libGL.so with -Bsymbolic (fixes bug found with Chromium) + - added missing 'const' to glXGetContextIDEXT() in glxext.h + - fixed a few glXGetProcAddress() errors (texture compression, etc) + - fixed start index bug in compiled vertex arrays (Keith) + - fixed compilation problems in src/SPARC/glapi_sparc.S + - fixed triangle strip "parity" bug found in VTK medical1 demo (Keith) + - use glXGetProcAddressARB in GLUT to avoid extension linking problems + - provoking vertex of flat-shaded, color-index triangles was wrong + - fixed a few display list bugs (GLUT walker, molecule, etc) (Keith) + - glTexParameter didn't flush the vertex buffer (Ray Tice) + - feedback attributes for glDraw/CopyPixels and glBitmap were wrong + - fixed bug in normal length caching (ParaView lighting bug) + - fixed separate_specular color bug found in Chimera (18 Dec 2001) + + +4.0.2 April 2, 2002 + New: + - New DOS (DJGPP) driver written by Daniel Borca + - New driver interface functions for TCL drivers (such as Radeon DRI) + - GL_RENDERER string returns "Mesa Offscreen16" or "Mesa Offscreen32" + if using deep color channels + - latest GL/glext.h and GL/glxext.h headers from SGI + Bug fixes: + - GL_BLEND with non-black texture env color wasn't always correct + - GL_REPLACE with GL_RGB texture format wasn't always correct (alpha) + - glTexEnviv( pname != GL_TEXTURE_ENV_COLOR ) was broken + - glReadPixels was sometimes mistakenly clipped by the scissor box + - glDraw/ReadPixels didn't catch all the errors that they should have + - Fixed 24bpp rendering problem in Windows driver (Karl Schultz) + - 16-bit GLchan mode fixes (m_trans_tmp.h, s_triangle.c) + - Fixed 1-bit float->int conversion bug in glDrawPixels(GL_DEPTH_COMP) + - glColorMask as sometimes effecting glXSwapBuffers() + - fixed a potential bug in XMesaGarbageCollect() + - N threads rendering into one window didn't work reliably + - glCopyPixels didn't work for deep color channels + - improved 8 -> 16bit/channel texture image conversion (Gerk Huisma) + - glPopAttrib() didn't correctly restore user clip planes + - user clip planes failed for some perspective projections (Chromium) + Known bugs: + - mipmap LOD computation + + +4.0.3 June 25, 2002 + New: + - updated GL/glext.h file (version 15) + - corrected MMX blend code (Jose Fonseca) + - support for software-based alpha planes in Windows driver + - updated GGI driver (Filip Spacek) + Bug fixes: + - glext.h had wrong values for GL_DOT3_RGB[A]_EXT tokens + - OSMesaMakeCurrent() didn't recognize buffer size changes + - assorted conformance fixes for 16-bit/channel rendering + - texcombine alpha subtraction mode was broken + - fixed lighting bug with non-uniform scaling and display lists + - fixed bug when deleting shared display lists + - disabled SPARC cliptest assembly code (Mesa bug 544665) + - fixed a couple Solaris compilation/link problems + - blending clipped glDrawPixels didn't always work + - glGetTexImage() didn't accept packed pixel types + - glPixelMapu[is]v() could explode given too large of pixelmap + - glGetTexParameter[if]v() didn't accept GL_TEXTURE_MAX_ANISOTROPY_EXT + - glXCopyContext() could lead to segfaults + - glCullFace(GL_FRONT_AND_BACK) didn't work (bug 572665) + Changes: + - lots of C++ (g++) code clean-ups + - lots of T&L updates for the Radeon DRI driver + Known bugs: + - mipmap LOD computation (fixed for Mesa 4.1) diff --git a/xc/extras/Mesa/src/OSmesa/osmesa.c b/xc/extras/Mesa/src/OSmesa/osmesa.c index f3691e900..4ab2d4ca2 100644 --- a/xc/extras/Mesa/src/OSmesa/osmesa.c +++ b/xc/extras/Mesa/src/OSmesa/osmesa.c @@ -485,6 +485,10 @@ OSMesaMakeCurrent( OSMesaContext ctx, void *buffer, GLenum type, _mesa_ResizeBuffersMESA(); } + /* Added by Gerk Huisma: */ + _tnl_MakeCurrent( &ctx->gl_ctx, ctx->gl_ctx.DrawBuffer, + ctx->gl_ctx.ReadBuffer ); + return GL_TRUE; } @@ -630,6 +634,15 @@ OSMesaGetColorBuffer( OSMesaContext c, GLint *width, * Useful macros: */ +#if CHAN_TYPE == GL_FLOAT +#define PACK_RGBA(DST, R, G, B, A) \ +do { \ + (DST)[0] = (R < 0.0f) ? 0.0f : ((R > 1.0f) ? 1.0f : R); \ + (DST)[1] = (G < 0.0f) ? 0.0f : ((G > 1.0f) ? 1.0f : G); \ + (DST)[2] = (B < 0.0f) ? 0.0f : ((B > 1.0f) ? 1.0f : B); \ + (DST)[3] = (A < 0.0f) ? 0.0f : ((A > 1.0f) ? 1.0f : A); \ +} while (0) +#else #define PACK_RGBA(DST, R, G, B, A) \ do { \ (DST)[osmesa->rInd] = R; \ @@ -637,6 +650,7 @@ do { \ (DST)[osmesa->bInd] = B; \ (DST)[osmesa->aInd] = A; \ } while (0) +#endif #define PACK_RGB(DST, R, G, B) \ do { \ @@ -879,7 +893,7 @@ static void clear( GLcontext *ctx, GLbitfield mask, GLboolean all, static void buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height ) { #ifdef WIN32 - /* Hack to get around problems with exporting glapi_Context from MesaGL + /* Hack to get around problems with exporting glapi_Context from Mesa and importing into OSMesa. */ GLcontext *ctx = (GLcontext *) _glapi_get_context(); #else diff --git a/xc/extras/Mesa/src/SPARC/sparc.c b/xc/extras/Mesa/src/SPARC/sparc.c new file mode 100644 index 000000000..9fd1c5692 --- /dev/null +++ b/xc/extras/Mesa/src/SPARC/sparc.c @@ -0,0 +1,176 @@ + +/* + * Mesa 3-D graphics library + * Version: 4.0.3 + * + * Copyright (C) 1999-2002 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Sparc assembly code by David S. Miller + */ + + +#include "context.h" +#include "math/m_vertices.h" +#include "math/m_xform.h" +#include "tnl/t_context.h" +#include "sparc.h" + +#ifdef DEBUG +#include "math/m_debug.h" +#endif + +#define XFORM_ARGS GLvector4f *to_vec, \ + const GLfloat m[16], \ + const GLvector4f *from_vec + +#define DECLARE_XFORM_GROUP(pfx, sz) \ + extern void _mesa_##pfx##_transform_points##sz##_general(XFORM_ARGS); \ + extern void _mesa_##pfx##_transform_points##sz##_identity(XFORM_ARGS); \ + extern void _mesa_##pfx##_transform_points##sz##_3d_no_rot(XFORM_ARGS); \ + extern void _mesa_##pfx##_transform_points##sz##_perspective(XFORM_ARGS); \ + extern void _mesa_##pfx##_transform_points##sz##_2d(XFORM_ARGS); \ + extern void _mesa_##pfx##_transform_points##sz##_2d_no_rot(XFORM_ARGS); \ + extern void _mesa_##pfx##_transform_points##sz##_3d(XFORM_ARGS); + +#define ASSIGN_XFORM_GROUP(pfx, sz) \ + _mesa_transform_tab[sz][MATRIX_GENERAL] = \ + _mesa_##pfx##_transform_points##sz##_general; \ + _mesa_transform_tab[sz][MATRIX_IDENTITY] = \ + _mesa_##pfx##_transform_points##sz##_identity; \ + _mesa_transform_tab[sz][MATRIX_3D_NO_ROT] = \ + _mesa_##pfx##_transform_points##sz##_3d_no_rot; \ + _mesa_transform_tab[sz][MATRIX_PERSPECTIVE] = \ + _mesa_##pfx##_transform_points##sz##_perspective; \ + _mesa_transform_tab[sz][MATRIX_2D] = \ + _mesa_##pfx##_transform_points##sz##_2d; \ + _mesa_transform_tab[sz][MATRIX_2D_NO_ROT] = \ + _mesa_##pfx##_transform_points##sz##_2d_no_rot; \ + _mesa_transform_tab[sz][MATRIX_3D] = \ + _mesa_##pfx##_transform_points##sz##_3d; + + +#ifdef USE_SPARC_ASM +DECLARE_XFORM_GROUP(sparc, 1) +DECLARE_XFORM_GROUP(sparc, 2) +DECLARE_XFORM_GROUP(sparc, 3) +DECLARE_XFORM_GROUP(sparc, 4) + +extern GLvector4f *_mesa_sparc_cliptest_points4(GLvector4f *clip_vec, + GLvector4f *proj_vec, + GLubyte clipMask[], + GLubyte *orMask, + GLubyte *andMask); + +extern GLvector4f *_mesa_sparc_cliptest_points4_np(GLvector4f *clip_vec, + GLvector4f *proj_vec, + GLubyte clipMask[], + GLubyte *orMask, + GLubyte *andMask); + +#define NORM_ARGS const GLmatrix *mat, \ + GLfloat scale, \ + const GLvector3f *in, \ + const GLfloat *lengths, \ + GLvector3f *dest + +extern void _mesa_sparc_transform_normalize_normals(NORM_ARGS); +extern void _mesa_sparc_transform_normalize_normals_no_rot(NORM_ARGS); +extern void _mesa_sparc_transform_rescale_normals_no_rot(NORM_ARGS); +extern void _mesa_sparc_transform_rescale_normals(NORM_ARGS); +extern void _mesa_sparc_transform_normals_no_rot(NORM_ARGS); +extern void _mesa_sparc_transform_normals(NORM_ARGS); +extern void _mesa_sparc_normalize_normals(NORM_ARGS); +extern void _mesa_sparc_rescale_normals(NORM_ARGS); + +#endif + +void _mesa_init_all_sparc_transform_asm(void) +{ +#ifdef USE_SPARC_ASM + ASSIGN_XFORM_GROUP(sparc, 1) + ASSIGN_XFORM_GROUP(sparc, 2) + ASSIGN_XFORM_GROUP(sparc, 3) + ASSIGN_XFORM_GROUP(sparc, 4) + +#if 0 + /* Disabled for now. See Mesa bug report # 544665. Evidently these + * functions are using SPARC registers that shouldn't be touched. + */ + _mesa_clip_tab[4] = _mesa_sparc_cliptest_points4; + _mesa_clip_np_tab[4] = _mesa_sparc_cliptest_points4_np; +#endif + _mesa_normal_tab[NORM_TRANSFORM | NORM_NORMALIZE] = + _mesa_sparc_transform_normalize_normals; + _mesa_normal_tab[NORM_TRANSFORM_NO_ROT | NORM_NORMALIZE] = + _mesa_sparc_transform_normalize_normals_no_rot; + _mesa_normal_tab[NORM_TRANSFORM_NO_ROT | NORM_RESCALE] = + _mesa_sparc_transform_rescale_normals_no_rot; + _mesa_normal_tab[NORM_TRANSFORM | NORM_RESCALE] = + _mesa_sparc_transform_rescale_normals; + _mesa_normal_tab[NORM_TRANSFORM_NO_ROT] = + _mesa_sparc_transform_normals_no_rot; + _mesa_normal_tab[NORM_TRANSFORM] = + _mesa_sparc_transform_normals; + _mesa_normal_tab[NORM_NORMALIZE] = + _mesa_sparc_normalize_normals; + _mesa_normal_tab[NORM_RESCALE] = + _mesa_sparc_rescale_normals; + +#ifdef DEBUG + _math_test_all_transform_functions("sparc"); + _math_test_all_cliptest_functions("sparc"); + _math_test_all_normal_transform_functions("sparc"); +#endif + +#endif +} + +extern unsigned int _mesa_sparc_glapi_begin; +extern unsigned int _mesa_sparc_glapi_end; +extern void __glapi_sparc_icache_flush(unsigned int *); + +void _mesa_init_sparc_glapi_relocs(void) +{ + unsigned int *insn_ptr, *end_ptr; + unsigned long disp_addr; + + insn_ptr = &_mesa_sparc_glapi_begin; + end_ptr = &_mesa_sparc_glapi_end; + disp_addr = (unsigned long) &_glapi_Dispatch; + + while (insn_ptr < end_ptr) { +#ifdef __sparc_v9__ + insn_ptr[0] |= (disp_addr >> (32 + 10)); + insn_ptr[1] |= ((disp_addr & 0xffffffff) >> 10); + __glapi_sparc_icache_flush(&insn_ptr[0]); + insn_ptr[2] |= ((disp_addr >> 32) & ((1 << 10) - 1)); + insn_ptr[3] |= (disp_addr & ((1 << 10) - 1)); + __glapi_sparc_icache_flush(&insn_ptr[2]); + insn_ptr += 11; +#else + insn_ptr[0] |= (disp_addr >> 10); + insn_ptr[1] |= (disp_addr & ((1 << 10) - 1)); + __glapi_sparc_icache_flush(&insn_ptr[0]); + insn_ptr += 5; +#endif + } +} diff --git a/xc/extras/Mesa/src/X/fakeglx.c b/xc/extras/Mesa/src/X/fakeglx.c index c05385239..d900c0c10 100644 --- a/xc/extras/Mesa/src/X/fakeglx.c +++ b/xc/extras/Mesa/src/X/fakeglx.c @@ -1,20 +1,20 @@ /* * Mesa 3-D graphics library - * Version: 3.4.2 - * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. - * + * Version: 4.0.3 + * + * Copyright (C) 1999-2002 Brian Paul All Rights Reserved. + * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL @@ -47,24 +47,25 @@ #include "context.h" #include "config.h" #include "macros.h" +#include "mem.h" #include "mmath.h" -#include "types.h" +#include "mtypes.h" #include "xfonts.h" #include "xmesaP.h" /* This indicates the client-side GLX API and GLX encoder version. */ #define CLIENT_MAJOR_VERSION 1 -#define CLIENT_MINOR_VERSION 2 +#define CLIENT_MINOR_VERSION 4 /* but don't have 1.3's pbuffers, etc yet */ /* This indicates the server-side GLX decoder version. - * GLX 1.3 indicates OpenGL 1.2 support + * GLX 1.4 indicates OpenGL 1.3 support */ #define SERVER_MAJOR_VERSION 1 -#define SERVER_MINOR_VERSION 3 +#define SERVER_MINOR_VERSION 4 /* This is appended onto the glXGetClient/ServerString version strings. */ -#define MESA_GLX_VERSION "Mesa 3.4.2" +#define MESA_GLX_VERSION "Mesa 4.0.3" /* Who implemented this GLX? */ #define VENDOR "Brian Paul" @@ -82,9 +83,28 @@ void Fake_glXDummyFunc( void ) } +/* + * Our fake GLX context will contain a "real" GLX context and an XMesa context. + * + * Note that a pointer to a __GLXcontext is a pointer to a fake_glx_context, + * and vice versa. + * + * We really just need this structure in order to make the libGL functions + * glXGetCurrentContext(), glXGetCurrentDrawable() and glXGetCurrentDisplay() + * work correctly. + */ +struct fake_glx_context { + __GLXcontext glxContext; /* this MUST be first! */ + XMesaContext xmesaContext; +}; + + -#define DONT_CARE -1 +/**********************************************************************/ +/*** GLX Visual Code ***/ +/**********************************************************************/ +#define DONT_CARE -1 #define MAX_VISUALS 100 @@ -92,7 +112,6 @@ static XMesaVisual VisualTable[MAX_VISUALS]; static int NumVisuals = 0; - /* * This struct and some code fragments borrowed * from Mark Kilgard's GLUT library. @@ -268,16 +287,16 @@ save_glx_visual( Display *dpy, XVisualInfo *vinfo, if (v->display == dpy && v->level == level && v->ximage_flag == ximageFlag - && v->gl_visual->RGBAflag == rgbFlag - && v->gl_visual->DBflag == dbFlag - && v->gl_visual->StereoFlag == stereoFlag - && (v->gl_visual->AlphaBits > 0) == alphaFlag - && (v->gl_visual->DepthBits >= depth_size || depth_size == 0) - && (v->gl_visual->StencilBits >= stencil_size || stencil_size == 0) - && (v->gl_visual->AccumRedBits >= accumRedSize || accumRedSize == 0) - && (v->gl_visual->AccumGreenBits >= accumGreenSize || accumGreenSize == 0) - && (v->gl_visual->AccumBlueBits >= accumBlueSize || accumBlueSize == 0) - && (v->gl_visual->AccumAlphaBits >= accumAlphaSize || accumAlphaSize == 0)) { + && v->mesa_visual.rgbMode == rgbFlag + && v->mesa_visual.doubleBufferMode == dbFlag + && v->mesa_visual.stereoMode == stereoFlag + && (v->mesa_visual.alphaBits > 0) == alphaFlag + && (v->mesa_visual.depthBits >= depth_size || depth_size == 0) + && (v->mesa_visual.stencilBits >= stencil_size || stencil_size == 0) + && (v->mesa_visual.accumRedBits >= accumRedSize || accumRedSize == 0) + && (v->mesa_visual.accumGreenBits >= accumGreenSize || accumGreenSize == 0) + && (v->mesa_visual.accumBlueBits >= accumBlueSize || accumBlueSize == 0) + && (v->mesa_visual.accumAlphaBits >= accumAlphaSize || accumAlphaSize == 0)) { /* now either compare XVisualInfo pointers or visual IDs */ if ((!comparePointers && v->visinfo->visualid == vinfo->visualid) || (comparePointers && v->vishandle == vinfo)) { @@ -868,6 +887,10 @@ static XVisualInfo *choose_x_overlay_visual( Display *dpy, int scr, } +/**********************************************************************/ +/*** Begin Fake GLX API Functions ***/ +/**********************************************************************/ + static XVisualInfo * Fake_glXChooseVisual( Display *dpy, int screen, int *list ) @@ -875,7 +898,7 @@ Fake_glXChooseVisual( Display *dpy, int screen, int *list ) int *parselist; XVisualInfo *vis; int min_ci = 0; - int min_red=0, min_green=0, min_blue=0, min_alpha=0; + int min_red=0, min_green=0, min_blue=0; GLboolean rgb_flag = GL_FALSE; GLboolean alpha_flag = GL_FALSE; GLboolean double_flag = GL_FALSE; @@ -939,8 +962,10 @@ Fake_glXChooseVisual( Display *dpy, int screen, int *list ) break; case GLX_ALPHA_SIZE: parselist++; - min_alpha = *parselist++; - alpha_flag = (min_alpha > 0); + { + GLint size = *parselist++; + alpha_flag = size>0 ? 1 : 0; + } break; case GLX_DEPTH_SIZE: parselist++; @@ -1002,7 +1027,7 @@ Fake_glXChooseVisual( Display *dpy, int screen, int *list ) parselist++; parselist++; break; - + /* * GLX_EXT_visual_info extension */ @@ -1019,16 +1044,6 @@ Fake_glXChooseVisual( Display *dpy, int screen, int *list ) } } - /* DEBUG - printf("glXChooseVisual:\n"); - printf(" GLX_RED_SIZE = %d\n", min_red); - printf(" GLX_GREEN_SIZE = %d\n", min_green); - printf(" GLX_BLUE_SIZE = %d\n", min_blue); - printf(" GLX_ALPHA_SIZE = %d\n", min_alpha); - printf(" GLX_DEPTH_SIZE = %d\n", depth_size); - printf(" GLX_STENCIL_SIZE = %d\n", stencil_size); - */ - /* * Since we're only simulating the GLX extension this function will never * find any real GL visuals. Instead, all we can do is try to find an RGB @@ -1085,33 +1100,17 @@ Fake_glXChooseVisual( Display *dpy, int screen, int *list ) else if (depth_size > 0) depth_size = DEFAULT_SOFTWARE_DEPTH_BITS; /*16*/ - /* If using Glide, make sure we don't try to setup an impossible - * visual. This fixes the Q3 bug in which 24-bit Z was being reported. - */ - { - const char *fx = getenv("MESA_GLX_FX"); - if (fx && fx[0] != 'd') - if (depth_size > 16 || - stencil_size > 0 || - (min_red > 1 && min_red > 5) || - (min_green > 1 && min_green > 6) || - (min_blue > 1 && min_blue > 5) || - alpha_flag) - return NULL; - } - - /* we only support one size of stencil and accum buffers. */ if (stencil_size > 0) stencil_size = STENCIL_BITS; - if (accumRedSize > 0) + if (accumRedSize > 0 || accumGreenSize > 0 || accumBlueSize > 0 || + accumAlphaSize > 0) { accumRedSize = ACCUM_BITS; - if (accumGreenSize > 0) accumGreenSize = ACCUM_BITS; - if (accumBlueSize > 0) accumBlueSize = ACCUM_BITS; - if (accumAlphaSize > 0) - accumAlphaSize = ACCUM_BITS; + accumAlphaSize = alpha_flag ? ACCUM_BITS : 0; + } + if (!save_glx_visual( dpy, vis, rgb_flag, alpha_flag, double_flag, stereo_flag, depth_size, stencil_size, accumRedSize, accumGreenSize, @@ -1131,7 +1130,11 @@ Fake_glXCreateContext( Display *dpy, XVisualInfo *visinfo, GLXContext share_list, Bool direct ) { XMesaVisual glxvis; - XMesaContext xmctx; + struct fake_glx_context *glxCtx; + struct fake_glx_context *shareCtx = (struct fake_glx_context *) share_list; + glxCtx = CALLOC_STRUCT(fake_glx_context); + if (!glxCtx) + return 0; /* deallocate unused windows/buffers */ XMesaGarbageCollect(); @@ -1142,33 +1145,47 @@ Fake_glXCreateContext( Display *dpy, XVisualInfo *visinfo, glxvis = create_glx_visual( dpy, visinfo ); if (!glxvis) { /* unusable visual */ + FREE(glxCtx); return NULL; } } - xmctx = XMesaCreateContext( glxvis, (XMesaContext) share_list ); - if (xmctx) { - /* set the direct/indirect flag */ - xmctx->direct = direct; + glxCtx->xmesaContext = XMesaCreateContext(glxvis, + shareCtx ? shareCtx->xmesaContext : NULL); + if (!glxCtx->xmesaContext) { + FREE(glxCtx); + return NULL; } - return (GLXContext) xmctx; + + glxCtx->xmesaContext->direct = GL_FALSE; + glxCtx->glxContext.isDirect = GL_FALSE; + glxCtx->glxContext.currentDpy = dpy; + glxCtx->glxContext.xid = (XID) glxCtx; /* self pointer */ + + assert((void *) glxCtx == (void *) &(glxCtx->glxContext)); + + return (GLXContext) glxCtx; } +/* XXX these may have to be removed due to thread-safety issues. */ static GLXContext MakeCurrent_PrevContext = 0; static GLXDrawable MakeCurrent_PrevDrawable = 0; static GLXDrawable MakeCurrent_PrevReadable = 0; static XMesaBuffer MakeCurrent_PrevDrawBuffer = 0; static XMesaBuffer MakeCurrent_PrevReadBuffer = 0; + /* GLX 1.3 and later */ static Bool Fake_glXMakeContextCurrent( Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx ) { + struct fake_glx_context *glxCtx = (struct fake_glx_context *) ctx; + if (ctx && draw && read) { XMesaBuffer drawBuffer, readBuffer; - XMesaContext xmctx = (XMesaContext) ctx; + XMesaContext xmctx = glxCtx->xmesaContext; /* Find the XMesaBuffer which corresponds to the GLXDrawable 'draw' */ if (ctx == MakeCurrent_PrevContext @@ -1180,7 +1197,7 @@ Fake_glXMakeContextCurrent( Display *dpy, GLXDrawable draw, } if (!drawBuffer) { /* drawable must be a new window! */ - drawBuffer = XMesaCreateWindowBuffer2( xmctx->xm_visual, draw, (XMesaContext) ctx ); + drawBuffer = XMesaCreateWindowBuffer2( xmctx->xm_visual, draw, xmctx); if (!drawBuffer) { /* Out of memory, or context/drawable depth mismatch */ return False; @@ -1197,7 +1214,8 @@ Fake_glXMakeContextCurrent( Display *dpy, GLXDrawable draw, } if (!readBuffer) { /* drawable must be a new window! */ - readBuffer = XMesaCreateWindowBuffer2( xmctx->xm_visual, read, (XMesaContext) ctx ); + readBuffer = XMesaCreateWindowBuffer2(glxCtx->xmesaContext->xm_visual, + read, xmctx); if (!readBuffer) { /* Out of memory, or context/drawable depth mismatch */ return False; @@ -1211,7 +1229,19 @@ Fake_glXMakeContextCurrent( Display *dpy, GLXDrawable draw, MakeCurrent_PrevReadBuffer = readBuffer; /* Now make current! */ - return (Bool) XMesaMakeCurrent2((XMesaContext) ctx, drawBuffer, readBuffer); + if (XMesaMakeCurrent2(xmctx, drawBuffer, readBuffer)) { + ((__GLXcontext *) ctx)->currentDpy = dpy; + ((__GLXcontext *) ctx)->currentDrawable = draw; +#ifndef GLX_BUILT_IN_XMESA + ((__GLXcontext *) ctx)->currentReadable = read; +#else + __glXSetCurrentContext(ctx); +#endif + return True; + } + else { + return False; + } } else if (!ctx && !draw && !read) { /* release current context w/out assigning new one. */ @@ -1221,6 +1251,9 @@ Fake_glXMakeContextCurrent( Display *dpy, GLXDrawable draw, MakeCurrent_PrevReadable = 0; MakeCurrent_PrevDrawBuffer = 0; MakeCurrent_PrevReadBuffer = 0; +#ifdef GLX_BUILT_IN_XMESA + /* XXX bind dummy context with __glXSetCurrentContext(ctx); */ +#endif return True; } else { @@ -1264,7 +1297,8 @@ Fake_glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo, Pixmap pixmap ) } -#ifdef GLX_MESA_pixmap_colormap +/*** GLX_MESA_pixmap_colormap ***/ + static GLXPixmap Fake_glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo, Pixmap pixmap, Colormap cmap ) @@ -1287,7 +1321,6 @@ Fake_glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo, } return b->frontbuffer; } -#endif static void @@ -1308,10 +1341,12 @@ static void Fake_glXCopyContext( Display *dpy, GLXContext src, GLXContext dst, unsigned long mask ) { - XMesaContext xm_src = (XMesaContext) src; - XMesaContext xm_dst = (XMesaContext) dst; + struct fake_glx_context *fakeSrc = (struct fake_glx_context *) src; + struct fake_glx_context *fakeDst = (struct fake_glx_context *) dst; + XMesaContext xm_src = fakeSrc->xmesaContext; + XMesaContext xm_dst = fakeDst->xmesaContext; (void) dpy; - gl_copy_context( xm_src->gl_ctx, xm_dst->gl_ctx, (GLuint) mask ); + _mesa_copy_context( xm_src->gl_ctx, xm_dst->gl_ctx, (GLuint) mask ); } @@ -1338,13 +1373,14 @@ void _kw_ungrab_all( Display *dpy ) static void Fake_glXDestroyContext( Display *dpy, GLXContext ctx ) { + struct fake_glx_context *glxCtx = (struct fake_glx_context *) ctx; (void) dpy; MakeCurrent_PrevContext = 0; MakeCurrent_PrevDrawable = 0; MakeCurrent_PrevReadable = 0; MakeCurrent_PrevDrawBuffer = 0; MakeCurrent_PrevReadBuffer = 0; - XMesaDestroyContext( (XMesaContext) ctx ); + XMesaDestroyContext( glxCtx->xmesaContext ); XMesaGarbageCollect(); } @@ -1353,8 +1389,9 @@ Fake_glXDestroyContext( Display *dpy, GLXContext ctx ) static Bool Fake_glXIsDirect( Display *dpy, GLXContext ctx ) { + struct fake_glx_context *glxCtx = (struct fake_glx_context *) ctx; (void) dpy; - return ((XMesaContext) ctx)->direct; + return glxCtx->xmesaContext->direct; } @@ -1374,7 +1411,8 @@ Fake_glXSwapBuffers( Display *dpy, GLXDrawable drawable ) -#ifdef GLX_MESA_copy_sub_buffer +/*** GLX_MESA_copy_sub_buffer ***/ + static void Fake_glXCopySubBufferMESA( Display *dpy, GLXDrawable drawable, int x, int y, int width, int height ) @@ -1387,7 +1425,6 @@ Fake_glXCopySubBufferMESA( Display *dpy, GLXDrawable drawable, fprintf(stderr, "Mesa Warning: glXCopySubBufferMESA: invalid drawable\n"); } } -#endif @@ -1441,7 +1478,7 @@ Fake_glXGetConfig( Display *dpy, XVisualInfo *visinfo, *value = glxvis->level; return 0; case GLX_RGBA: - if (glxvis->gl_visual->RGBAflag) { + if (glxvis->mesa_visual.rgbMode) { *value = True; } else { @@ -1449,43 +1486,43 @@ Fake_glXGetConfig( Display *dpy, XVisualInfo *visinfo, } return 0; case GLX_DOUBLEBUFFER: - *value = (int) glxvis->gl_visual->DBflag; + *value = (int) glxvis->mesa_visual.doubleBufferMode; return 0; case GLX_STEREO: - *value = (int) glxvis->gl_visual->StereoFlag; + *value = (int) glxvis->mesa_visual.stereoMode; return 0; case GLX_AUX_BUFFERS: *value = (int) False; return 0; case GLX_RED_SIZE: - *value = glxvis->gl_visual->RedBits; + *value = glxvis->mesa_visual.redBits; return 0; case GLX_GREEN_SIZE: - *value = glxvis->gl_visual->GreenBits; + *value = glxvis->mesa_visual.greenBits; return 0; case GLX_BLUE_SIZE: - *value = glxvis->gl_visual->BlueBits; + *value = glxvis->mesa_visual.blueBits; return 0; case GLX_ALPHA_SIZE: - *value = glxvis->gl_visual->AlphaBits; + *value = glxvis->mesa_visual.alphaBits; return 0; case GLX_DEPTH_SIZE: - *value = glxvis->gl_visual->DepthBits; + *value = glxvis->mesa_visual.depthBits; return 0; case GLX_STENCIL_SIZE: - *value = glxvis->gl_visual->StencilBits; + *value = glxvis->mesa_visual.stencilBits; return 0; case GLX_ACCUM_RED_SIZE: - *value = glxvis->gl_visual->AccumRedBits; + *value = glxvis->mesa_visual.accumRedBits; return 0; case GLX_ACCUM_GREEN_SIZE: - *value = glxvis->gl_visual->AccumGreenBits; + *value = glxvis->mesa_visual.accumGreenBits; return 0; case GLX_ACCUM_BLUE_SIZE: - *value = glxvis->gl_visual->AccumBlueBits; + *value = glxvis->mesa_visual.accumBlueBits; return 0; case GLX_ACCUM_ALPHA_SIZE: - *value = glxvis->gl_visual->AccumAlphaBits; + *value = glxvis->mesa_visual.accumAlphaBits; return 0; /* @@ -1508,7 +1545,7 @@ Fake_glXGetConfig( Display *dpy, XVisualInfo *visinfo, } else if (glxvis->level>0) { /* overlay */ - if (glxvis->gl_visual->RGBAflag) { + if (glxvis->mesa_visual.rgbMode) { *value = GLX_TRANSPARENT_RGB_EXT; } else { @@ -1660,6 +1697,15 @@ Fake_glXGetClientString( Display *dpy, int name ) * GLX 1.3 and later */ +/* XXX Move this when done. + * Create an XMesaBuffer as a Pbuffer. + * New in Mesa 4.0 but untested. + */ +extern XMesaBuffer XMesaCreatePBuffer( XMesaVisual v, XMesaColormap cmap, + unsigned int width, unsigned int height ); + + + static GLXFBConfig * Fake_glXChooseFBConfig( Display *dpy, int screen, const int *attribList, int *nitems ) @@ -1676,11 +1722,158 @@ static int Fake_glXGetFBConfigAttrib( Display *dpy, GLXFBConfig config, int attribute, int *value ) { + XMesaVisual v = NULL; /* XXX Fix this */ (void) dpy; (void) config; (void) attribute; (void) value; - return 0; + + if (!dpy || !config || !value) + return -1; + + switch (attribute) { + case GLX_FBCONFIG_ID: + case GLX_BUFFER_SIZE: + if (v->mesa_visual.rgbMode) + *value = v->mesa_visual.redBits + v->mesa_visual.greenBits + + v->mesa_visual.blueBits + v->mesa_visual.alphaBits; + else + *value = v->mesa_visual.indexBits; + break; + case GLX_LEVEL: + *value = v->level; + break; + case GLX_DOUBLEBUFFER: + *value = v->mesa_visual.doubleBufferMode; + break; + case GLX_STEREO: + *value = v->mesa_visual.stereoMode; + break; + case GLX_AUX_BUFFERS: + *value = v->mesa_visual.numAuxBuffers; + break; + case GLX_RED_SIZE: + *value = v->mesa_visual.redBits; + break; + case GLX_GREEN_SIZE: + *value = v->mesa_visual.greenBits; + break; + case GLX_BLUE_SIZE: + *value = v->mesa_visual.blueBits; + break; + case GLX_ALPHA_SIZE: + *value = v->mesa_visual.alphaBits; + break; + case GLX_DEPTH_SIZE: + *value = v->mesa_visual.depthBits; + break; + case GLX_STENCIL_SIZE: + *value = v->mesa_visual.stencilBits; + break; + case GLX_ACCUM_RED_SIZE: + *value = v->mesa_visual.accumRedBits; + break; + case GLX_ACCUM_GREEN_SIZE: + *value = v->mesa_visual.accumGreenBits; + break; + case GLX_ACCUM_BLUE_SIZE: + *value = v->mesa_visual.accumBlueBits; + break; + case GLX_ACCUM_ALPHA_SIZE: + *value = v->mesa_visual.accumAlphaBits; + break; + case GLX_RENDER_TYPE: + *value = 0; /* XXX ??? */ + break; + case GLX_DRAWABLE_TYPE: + *value = GLX_PBUFFER_BIT; /* XXX fix? */ + break; + case GLX_X_RENDERABLE: + *value = False; /* XXX ??? */ + break; + case GLX_X_VISUAL_TYPE: +#if defined(__cplusplus) || defined(c_plusplus) + switch (v->vishandle->c_class) { +#else + switch (v->vishandle->class) { +#endif + case GrayScale: + *value = GLX_GRAY_SCALE; + break; + case StaticGray: + *value = GLX_STATIC_GRAY; + break; + case StaticColor: + *value = GLX_STATIC_COLOR; + break; + case PseudoColor: + *value = GLX_PSEUDO_COLOR; + break; + case TrueColor: + *value = GLX_TRUE_COLOR; + break; + case DirectColor: + *value = GLX_DIRECT_COLOR; + break; + default: + *value = 0; + } + break; + case GLX_CONFIG_CAVEAT: + *value = 0; /* XXX ??? */ + break; + case GLX_TRANSPARENT_TYPE: + if (v->level == 0) { + /* normal planes */ + *value = GLX_NONE_EXT; + } + else if (v->level > 0) { + /* overlay */ + if (v->mesa_visual.rgbMode) { + *value = GLX_TRANSPARENT_RGB_EXT; + } + else { + *value = GLX_TRANSPARENT_INDEX_EXT; + } + } + else if (v->level < 0) { + /* underlay */ + *value = GLX_NONE_EXT; + } + break; + case GLX_TRANSPARENT_INDEX_VALUE: + *value = transparent_pixel( v ); + break; + case GLX_TRANSPARENT_RED_VALUE: + *value = 0; /* not implemented */ + break; + case GLX_TRANSPARENT_GREEN_VALUE: + *value = 0; /* not implemented */ + break; + case GLX_TRANSPARENT_BLUE_VALUE: + *value = 0; /* not implemented */ + break; + case GLX_TRANSPARENT_ALPHA_VALUE: + *value = 0; /* not implemented */ + break; + case GLX_MAX_PBUFFER_WIDTH: + *value = DisplayWidth(dpy, v->vishandle->screen); + break; + case GLX_MAX_PBUFFER_HEIGHT: + *value = DisplayHeight(dpy, v->vishandle->screen); + break; + case GLX_MAX_PBUFFER_PIXELS: + *value = DisplayWidth(dpy, v->vishandle->screen) * + DisplayHeight(dpy, v->vishandle->screen); + break; + case GLX_VISUAL_ID: + *value = v->vishandle->visualid; + break; + default: + return GLX_BAD_ATTRIBUTE; + } + + return Success; } @@ -1697,9 +1890,13 @@ Fake_glXGetFBConfigs( Display *dpy, int screen, int *nelements ) static XVisualInfo * Fake_glXGetVisualFromFBConfig( Display *dpy, GLXFBConfig config ) { - (void) dpy; - (void) config; - return 0; + if (dpy && config) { + XMesaVisual v = (XMesaVisual) config; + return v->vishandle; + } + else { + return NULL; + } } @@ -1710,38 +1907,66 @@ Fake_glXCreateWindow( Display *dpy, GLXFBConfig config, Window win, (void) dpy; (void) config; (void) win; - (void) attribList; - return 0; + (void) attribList; /* Ignored in GLX 1.3 */ + + return win; /* A hack for now */ } static void Fake_glXDestroyWindow( Display *dpy, GLXWindow window ) { - (void) dpy; - (void) window; - return; + XMesaBuffer b = XMesaFindBuffer(dpy, (XMesaDrawable) window); + if (b) + XMesaDestroyBuffer(b); + /* don't destroy X window */ } +/* XXX untested */ static GLXPixmap Fake_glXCreatePixmap( Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attribList ) { + XMesaVisual v = (XMesaVisual) config; + XVisualInfo *visinfo; + XMesaBuffer b; + (void) dpy; (void) config; (void) pixmap; - (void) attribList; - return 0; + (void) attribList; /* Ignored in GLX 1.3 */ + + if (!dpy || !config || !pixmap) + return 0; + + visinfo = v->vishandle; + + v = find_glx_visual( dpy, visinfo ); + if (!v) { + v = create_glx_visual( dpy, visinfo ); + if (!v) { + /* unusable visual */ + return 0; + } + } + + b = XMesaCreatePixmapBuffer( v, pixmap, 0 ); + if (!b) { + return 0; + } + + return pixmap; } static void Fake_glXDestroyPixmap( Display *dpy, GLXPixmap pixmap ) { - (void) dpy; - (void) pixmap; - return; + XMesaBuffer b = XMesaFindBuffer(dpy, (XMesaDrawable)pixmap); + if (b) + XMesaDestroyBuffer(b); + /* don't destroy X pixmap */ } @@ -1749,9 +1974,36 @@ static GLXPbuffer Fake_glXCreatePbuffer( Display *dpy, GLXFBConfig config, const int *attribList ) { + const int *attrib; + int width = 0, height = 0; + GLboolean useLargest = GL_FALSE, preserveContents = GL_FALSE; + (void) dpy; (void) config; - (void) attribList; + + for (attrib = attribList; attrib; attrib++) { + switch (*attrib) { + case GLX_PBUFFER_WIDTH: + width = *(++attrib); + break; + case GLX_PBUFFER_HEIGHT: + height = *(++attrib); + break; + case GLX_PRESERVED_CONTENTS: + preserveContents = GL_TRUE; /* ignored */ + break; + case GLX_LARGEST_PBUFFER: + useLargest = GL_TRUE; /* ignored */ + break; + default: + return 0; + } + } + + if (width == 0 || height == 0) + return 0; + + return 0; } @@ -1770,8 +2022,18 @@ Fake_glXQueryDrawable( Display *dpy, GLXDrawable draw, int attribute, { (void) dpy; (void) draw; - (void) attribute; - (void) value; + + switch (attribute) { + case GLX_WIDTH: + case GLX_HEIGHT: + case GLX_PRESERVED_CONTENTS: + case GLX_LARGEST_PBUFFER: + case GLX_FBCONFIG_ID: + *value = 0; + return; + default: + return; /* GLX_BAD_ATTRIBUTE? */ + } } @@ -1779,12 +2041,13 @@ static GLXContext Fake_glXCreateNewContext( Display *dpy, GLXFBConfig config, int renderType, GLXContext shareList, Bool direct ) { - (void) dpy; - (void) config; - (void) renderType; - (void) shareList; - (void) direct; - return 0; + XMesaVisual v = (XMesaVisual) config; + + if (!dpy || !config || + (renderType != GLX_RGBA_TYPE && renderType != GLX_COLOR_INDEX_TYPE)) + return 0; + + return Fake_glXCreateContext(dpy, v->vishandle, shareList, direct); } @@ -1793,9 +2056,16 @@ Fake_glXQueryContext( Display *dpy, GLXContext ctx, int attribute, int *value ) { (void) dpy; (void) ctx; - (void) attribute; - (void) value; - return 0; + + switch (attribute) { + case GLX_FBCONFIG_ID: + case GLX_RENDER_TYPE: + case GLX_SCREEN: + *value = 0; + return Success; + default: + return GLX_BAD_ATTRIBUTE; + } } @@ -1819,57 +2089,393 @@ Fake_glXGetSelectedEvent( Display *dpy, GLXDrawable drawable, -#ifdef GLX_MESA_release_buffers -/* - * Release the depth, stencil, accum buffers attached to a GLXDrawable - * (a window or pixmap) prior to destroying the GLXDrawable. - */ +/*** GLX_SGI_swap_control ***/ + +static int +Fake_glXSwapIntervalSGI(int interval) +{ + (void) interval; + return 0; +} + + + +/*** GLX_SGI_video_sync ***/ + +static int +Fake_glXGetVideoSyncSGI(unsigned int *count) +{ + (void) count; + return 0; +} + +static int +Fake_glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count) +{ + (void) divisor; + (void) remainder; + (void) count; + return 0; +} + + + +/*** GLX_SGI_make_current_read ***/ + static Bool -Fake_glXReleaseBuffersMESA( Display *dpy, GLXDrawable d ) +Fake_glXMakeCurrentReadSGI(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx) { - XMesaBuffer b = XMesaFindBuffer(dpy, d); - if (b) { - XMesaDestroyBuffer(b); - return True; - } + (void) dpy; + (void) draw; + (void) read; + (void) ctx; return False; } -#endif + +/* not used +static GLXDrawable +Fake_glXGetCurrentReadDrawableSGI(void) +{ + return 0; +} +*/ +/*** GLX_SGIX_video_source ***/ +#if defined(_VL_H) -#ifdef GLX_MESA_set_3dfx_mode -static GLboolean -Fake_glXSet3DfxModeMESA( GLint mode ) +static GLXVideoSourceSGIX +Fake_glXCreateGLXVideoSourceSGIX(Display *dpy, int screen, VLServer server, VLPath path, int nodeClass, VLNode drainNode) { - return XMesaSetFXmode( mode ); + (void) dpy; + (void) screen; + (void) server; + (void) path; + (void) nodeClass; + (void) drainNode; + return 0; } + +static void +Fake_glXDestroyGLXVideoSourceSGIX(Display *dpy, GLXVideoSourceSGIX src) +{ + (void) dpy; + (void) src; +} + #endif +/*** GLX_EXT_import_context ***/ -/* - * GLX_SGI_video_sync - */ +static void +Fake_glXFreeContextEXT(Display *dpy, GLXContext context) +{ + (void) dpy; + (void) context; +} -#ifdef GLX_SGI_video_sync +static GLXContextID +Fake_glXGetContextIDEXT(const GLXContext context) +{ + (void) context; + return 0; +} + +static GLXContext +Fake_glXImportContextEXT(Display *dpy, GLXContextID contextID) +{ + (void) dpy; + (void) contextID; + return 0; +} static int -Fake_glXGetVideoSyncSGI(unsigned int *count) +Fake_glXQueryContextInfoEXT(Display *dpy, GLXContext context, int attribute, int *value) { + (void) dpy; + (void) context; + (void) attribute; + (void) value; return 0; } + +/*** GLX_SGIX_fbconfig ***/ + static int -Fake_glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count) +Fake_glXGetFBConfigAttribSGIX(Display *dpy, GLXFBConfigSGIX config, int attribute, int *value) +{ + (void) dpy; + (void) config; + (void) attribute; + (void) value; + return 0; +} + +static GLXFBConfigSGIX * +Fake_glXChooseFBConfigSGIX(Display *dpy, int screen, int *attrib_list, int *nelements) +{ + (void) dpy; + (void) screen; + (void) attrib_list; + (void) nelements; + return 0; +} + +static GLXPixmap +Fake_glXCreateGLXPixmapWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, Pixmap pixmap) +{ + (void) dpy; + (void) config; + (void) pixmap; + return 0; +} + +static GLXContext +Fake_glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct) +{ + (void) dpy; + (void) config; + (void) render_type; + (void) share_list; + (void) direct; + return 0; +} + +static XVisualInfo * +Fake_glXGetVisualFromFBConfigSGIX(Display *dpy, GLXFBConfigSGIX config) +{ + (void) dpy; + (void) config; + return NULL; +} + +static GLXFBConfigSGIX +Fake_glXGetFBConfigFromVisualSGIX(Display *dpy, XVisualInfo *vis) +{ + (void) dpy; + (void) vis; + return 0; +} + + + +/*** GLX_SGIX_pbuffer ***/ + +static GLXPbufferSGIX +Fake_glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config, unsigned int width, unsigned int height, int *attrib_list) +{ + (void) dpy; + (void) config; + (void) width; + (void) height; + (void) attrib_list; + return 0; +} + +static void +Fake_glXDestroyGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf) +{ + (void) dpy; + (void) pbuf; +} + +static int +Fake_glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf, int attribute, unsigned int *value) +{ + (void) dpy; + (void) pbuf; + (void) attribute; + (void) value; + return 0; +} + +static void +Fake_glXSelectEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long mask) +{ + (void) dpy; + (void) drawable; + (void) mask; +} + +static void +Fake_glXGetSelectedEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long *mask) +{ + (void) dpy; + (void) drawable; + (void) mask; +} + + + +/*** GLX_SGI_cushion ***/ + +static void +Fake_glXCushionSGI(Display *dpy, Window win, float cushion) +{ + (void) dpy; + (void) win; + (void) cushion; +} + + + +/*** GLX_SGIX_video_resize ***/ + +static int +Fake_glXBindChannelToWindowSGIX(Display *dpy, int screen, int channel , Window window) +{ + (void) dpy; + (void) screen; + (void) channel; + (void) window; + return 0; +} + +static int +Fake_glXChannelRectSGIX(Display *dpy, int screen, int channel, int x, int y, int w, int h) +{ + (void) dpy; + (void) screen; + (void) channel; + (void) x; + (void) y; + (void) w; + (void) h; + return 0; +} + +static int +Fake_glXQueryChannelRectSGIX(Display *dpy, int screen, int channel, int *x, int *y, int *w, int *h) +{ + (void) dpy; + (void) screen; + (void) channel; + (void) x; + (void) y; + (void) w; + (void) h; + return 0; +} + +static int +Fake_glXQueryChannelDeltasSGIX(Display *dpy, int screen, int channel, int *dx, int *dy, int *dw, int *dh) +{ + (void) dpy; + (void) screen; + (void) channel; + (void) dx; + (void) dy; + (void) dw; + (void) dh; + return 0; +} + +static int +Fake_glXChannelRectSyncSGIX(Display *dpy, int screen, int channel, GLenum synctype) { + (void) dpy; + (void) screen; + (void) channel; + (void) synctype; return 0; } + + +/*** GLX_SGIX_dmbuffer **/ + +#if defined(_DM_BUFFER_H_) +static Bool +Fake_glXAssociateDMPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuffer, DMparams *params, DMbuffer dmbuffer) +{ + (void) dpy; + (void) pbuffer; + (void) params; + (void) dmbuffer; + return False; +} #endif +/*** GLX_SGIX_swap_group ***/ + +static void +Fake_glXJoinSwapGroupSGIX(Display *dpy, GLXDrawable drawable, GLXDrawable member) +{ + (void) dpy; + (void) drawable; + (void) member; +} + + + +/*** GLX_SGIX_swap_barrier ***/ + +static void +Fake_glXBindSwapBarrierSGIX(Display *dpy, GLXDrawable drawable, int barrier) +{ + (void) dpy; + (void) drawable; + (void) barrier; +} + +static Bool +Fake_glXQueryMaxSwapBarriersSGIX(Display *dpy, int screen, int *max) +{ + (void) dpy; + (void) screen; + (void) max; + return False; +} + + + +/*** GLX_SUN_get_transparent_index ***/ + +static Status +Fake_glXGetTransparentIndexSUN(Display *dpy, Window overlay, Window underlay, long *pTransparent) +{ + (void) dpy; + (void) overlay; + (void) underlay; + (void) pTransparent; + return 0; +} + + + +/*** GLX_MESA_release_buffers ***/ + +/* + * Release the depth, stencil, accum buffers attached to a GLXDrawable + * (a window or pixmap) prior to destroying the GLXDrawable. + */ +static Bool +Fake_glXReleaseBuffersMESA( Display *dpy, GLXDrawable d ) +{ + XMesaBuffer b = XMesaFindBuffer(dpy, d); + if (b) { + XMesaDestroyBuffer(b); + return True; + } + return False; +} + + + +/*** GLX_MESA_set_3dfx_mode ***/ + +static Bool +Fake_glXSet3DfxModeMESA( int mode ) +{ + return XMesaSetFXmode( mode ); +} + + + extern struct _glxapi_table *_mesa_GetGLXDispatchTable(void); struct _glxapi_table *_mesa_GetGLXDispatchTable(void) @@ -1878,9 +2484,9 @@ struct _glxapi_table *_mesa_GetGLXDispatchTable(void) /* be sure our dispatch table size <= libGL's table */ { - int size = sizeof(struct _glxapi_table) / sizeof(void *); + GLuint size = sizeof(struct _glxapi_table) / sizeof(void *); (void) size; - assert((GLint) _glxapi_get_dispatch_table_size() >= size); + assert(_glxapi_get_dispatch_table_size() >= size); } /* initialize the whole table to no-ops */ @@ -1905,17 +2511,15 @@ struct _glxapi_table *_mesa_GetGLXDispatchTable(void) glx.WaitGL = Fake_glXWaitGL; glx.WaitX = Fake_glXWaitX; -#ifdef GLX_VERSION_1_1 + /*** GLX_VERSION_1_1 ***/ glx.GetClientString = Fake_glXGetClientString; glx.QueryExtensionsString = Fake_glXQueryExtensionsString; glx.QueryServerString = Fake_glXQueryServerString; -#endif -#ifdef GLX_VERSION_1_2 + /*** GLX_VERSION_1_2 ***/ /*glx.GetCurrentDisplay = Fake_glXGetCurrentDisplay;*/ -#endif -#ifdef GLX_VERSION_1_3 + /*** GLX_VERSION_1_3 ***/ glx.ChooseFBConfig = Fake_glXChooseFBConfig; glx.CreateNewContext = Fake_glXCreateNewContext; glx.CreatePbuffer = Fake_glXCreatePbuffer; @@ -1933,28 +2537,82 @@ struct _glxapi_table *_mesa_GetGLXDispatchTable(void) glx.QueryContext = Fake_glXQueryContext; glx.QueryDrawable = Fake_glXQueryDrawable; glx.SelectEvent = Fake_glXSelectEvent; -#endif -#ifdef GLX_SGI_video_sync + /*** GLX_SGI_swap_control ***/ + glx.SwapIntervalSGI = Fake_glXSwapIntervalSGI; + + /*** GLX_SGI_video_sync ***/ glx.GetVideoSyncSGI = Fake_glXGetVideoSyncSGI; glx.WaitVideoSyncSGI = Fake_glXWaitVideoSyncSGI; + + /*** GLX_SGI_make_current_read ***/ + glx.MakeCurrentReadSGI = Fake_glXMakeCurrentReadSGI; + /*glx.GetCurrentReadDrawableSGI = Fake_glXGetCurrentReadDrawableSGI;*/ + +/*** GLX_SGIX_video_source ***/ +#if defined(_VL_H) + glx.CreateGLXVideoSourceSGIX = Fake_glXCreateGLXVideoSourceSGIX; + glx.DestroyGLXVideoSourceSGIX = Fake_glXDestroyGLXVideoSourceSGIX; #endif -#ifdef GLX_MESA_copy_sub_buffer - glx.CopySubBufferMESA = Fake_glXCopySubBufferMESA; + /*** GLX_EXT_import_context ***/ + glx.FreeContextEXT = Fake_glXFreeContextEXT; + glx.GetContextIDEXT = Fake_glXGetContextIDEXT; + /*glx.GetCurrentDisplayEXT = Fake_glXGetCurrentDisplayEXT;*/ + glx.ImportContextEXT = Fake_glXImportContextEXT; + glx.QueryContextInfoEXT = Fake_glXQueryContextInfoEXT; + + /*** GLX_SGIX_fbconfig ***/ + glx.GetFBConfigAttribSGIX = Fake_glXGetFBConfigAttribSGIX; + glx.ChooseFBConfigSGIX = Fake_glXChooseFBConfigSGIX; + glx.CreateGLXPixmapWithConfigSGIX = Fake_glXCreateGLXPixmapWithConfigSGIX; + glx.CreateContextWithConfigSGIX = Fake_glXCreateContextWithConfigSGIX; + glx.GetVisualFromFBConfigSGIX = Fake_glXGetVisualFromFBConfigSGIX; + glx.GetFBConfigFromVisualSGIX = Fake_glXGetFBConfigFromVisualSGIX; + + /*** GLX_SGIX_pbuffer ***/ + glx.CreateGLXPbufferSGIX = Fake_glXCreateGLXPbufferSGIX; + glx.DestroyGLXPbufferSGIX = Fake_glXDestroyGLXPbufferSGIX; + glx.QueryGLXPbufferSGIX = Fake_glXQueryGLXPbufferSGIX; + glx.SelectEventSGIX = Fake_glXSelectEventSGIX; + glx.GetSelectedEventSGIX = Fake_glXGetSelectedEventSGIX; + + /*** GLX_SGI_cushion ***/ + glx.CushionSGI = Fake_glXCushionSGI; + + /*** GLX_SGIX_video_resize ***/ + glx.BindChannelToWindowSGIX = Fake_glXBindChannelToWindowSGIX; + glx.ChannelRectSGIX = Fake_glXChannelRectSGIX; + glx.QueryChannelRectSGIX = Fake_glXQueryChannelRectSGIX; + glx.QueryChannelDeltasSGIX = Fake_glXQueryChannelDeltasSGIX; + glx.ChannelRectSyncSGIX = Fake_glXChannelRectSyncSGIX; + + /*** GLX_SGIX_dmbuffer **/ +#if defined(_DM_BUFFER_H_) + glx.AssociateDMPbufferSGIX = NULL; #endif -#ifdef GLX_MESA_release_buffers + /*** GLX_SGIX_swap_group ***/ + glx.JoinSwapGroupSGIX = Fake_glXJoinSwapGroupSGIX; + + /*** GLX_SGIX_swap_barrier ***/ + glx.BindSwapBarrierSGIX = Fake_glXBindSwapBarrierSGIX; + glx.QueryMaxSwapBarriersSGIX = Fake_glXQueryMaxSwapBarriersSGIX; + + /*** GLX_SUN_get_transparent_index ***/ + glx.GetTransparentIndexSUN = Fake_glXGetTransparentIndexSUN; + + /*** GLX_MESA_copy_sub_buffer ***/ + glx.CopySubBufferMESA = Fake_glXCopySubBufferMESA; + + /*** GLX_MESA_release_buffers ***/ glx.ReleaseBuffersMESA = Fake_glXReleaseBuffersMESA; -#endif -#ifdef GLX_MESA_pixmap_colormap + /*** GLX_MESA_pixmap_colormap ***/ glx.CreateGLXPixmapMESA = Fake_glXCreateGLXPixmapMESA; -#endif -#ifdef GLX_MESA_set_3dfx_mode + /*** GLX_MESA_set_3dfx_mode ***/ glx.Set3DfxModeMESA = Fake_glXSet3DfxModeMESA; -#endif return &glx; } diff --git a/xc/extras/Mesa/src/X/xm_api.c b/xc/extras/Mesa/src/X/xm_api.c new file mode 100644 index 000000000..ea6c5ebf8 --- /dev/null +++ b/xc/extras/Mesa/src/X/xm_api.c @@ -0,0 +1,2639 @@ + +/* + * Mesa 3-D graphics library + * Version: 4.0.3 + * + * Copyright (C) 1999-2002 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +/* $XFree86: xc/extras/Mesa/src/X/xm_api.c,v 1.2 2002/02/26 23:37:31 tsi Exp $ */ + +/* + * This file contains the implementations of all the XMesa* functions. + * + * + * NOTES: + * + * The window coordinate system origin (0,0) is in the lower-left corner + * of the window. X11's window coordinate origin is in the upper-left + * corner of the window. Therefore, most drawing functions in this + * file have to flip Y coordinates. + * + * Define USE_XSHM in the Makefile with -DUSE_XSHM if you want to compile + * in support for the MIT Shared Memory extension. If enabled, when you + * use an Ximage for the back buffer in double buffered mode, the "swap" + * operation will be faster. You must also link with -lXext. + * + * Byte swapping: If the Mesa host and the X display use a different + * byte order then there's some trickiness to be aware of when using + * XImages. The byte ordering used for the XImage is that of the X + * display, not the Mesa host. + * The color-to-pixel encoding for True/DirectColor must be done + * according to the display's visual red_mask, green_mask, and blue_mask. + * If XPutPixel is used to put a pixel into an XImage then XPutPixel will + * do byte swapping if needed. If one wants to directly "poke" the pixel + * into the XImage's buffer then the pixel must be byte swapped first. In + * Mesa, when byte swapping is needed we use the PF_TRUECOLOR pixel format + * and use XPutPixel everywhere except in the implementation of + * glClear(GL_COLOR_BUFFER_BIT). We want this function to be fast so + * instead of using XPutPixel we "poke" our values after byte-swapping + * the clear pixel value if needed. + * + */ + +#ifdef __CYGWIN__ +#undef WIN32 +#undef __WIN32__ +#endif + +#include "glxheader.h" +#include "GL/xmesa.h" +#include "xmesaP.h" +#include "context.h" +#include "extensions.h" +#include "glthread.h" +#include "matrix.h" +#include "mem.h" +#include "mmath.h" +#include "mtypes.h" +#ifdef HAVE_CONFIG_H +#include "conf.h" +#endif +#include "macros.h" +#include "texformat.h" +#include "texstore.h" +#include "swrast/swrast.h" +#include "swrast_setup/swrast_setup.h" +#include "array_cache/acache.h" +#include "tnl/tnl.h" + +#ifndef GLX_NONE_EXT +#define GLX_NONE_EXT 0x8000 +#endif + + +/* + * Global X driver lock + */ +_glthread_Mutex _xmesa_lock; + + + +/* + * Lookup tables for HPCR pixel format: + */ +static short hpcr_rgbTbl[3][256] = { +{ + 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, + 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31, + 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, +112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, +128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, +144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, +160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, +176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, +192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, +208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, +224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239 +}, +{ + 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, + 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31, + 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, +112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, +128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, +144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, +160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, +176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, +192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, +208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, +224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239 +}, +{ + 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39, + 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 47, + 48, 48, 49, 49, 50, 50, 51, 51, 52, 52, 53, 53, 54, 54, 55, 55, + 56, 56, 57, 57, 58, 58, 59, 59, 60, 60, 61, 61, 62, 62, 63, 63, + 64, 64, 65, 65, 66, 66, 67, 67, 68, 68, 69, 69, 70, 70, 71, 71, + 72, 72, 73, 73, 74, 74, 75, 75, 76, 76, 77, 77, 78, 78, 79, 79, + 80, 80, 81, 81, 82, 82, 83, 83, 84, 84, 85, 85, 86, 86, 87, 87, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, +112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, +128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, +144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, +160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, +176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, +192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, +208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223 +} +}; + + + +/**********************************************************************/ +/***** X Utility Functions *****/ +/**********************************************************************/ + + +/* + * X/Mesa error reporting function: + */ +static void error( const char *msg ) +{ + (void)DitherValues; /* Muffle compiler */ + + if (getenv("MESA_DEBUG")) + fprintf( stderr, "X/Mesa error: %s\n", msg ); +} + + +/* + * Return the host's byte order as LSBFirst or MSBFirst ala X. + */ +#ifndef XFree86Server +static int host_byte_order( void ) +{ + int i = 1; + char *cptr = (char *) &i; + return (*cptr==1) ? LSBFirst : MSBFirst; +} +#endif + + +/* + * Error handling. + */ +#ifndef XFree86Server +static int mesaXErrorFlag = 0; + +static int mesaHandleXError( XMesaDisplay *dpy, XErrorEvent *event ) +{ + (void) dpy; + (void) event; + mesaXErrorFlag = 1; + return 0; +} +#endif + + +/* + * Check if the X Shared Memory extension is available. + * Return: 0 = not available + * 1 = shared XImage support available + * 2 = shared Pixmap support available also + */ +#ifndef XFree86Server +static int check_for_xshm( XMesaDisplay *display ) +{ +#ifdef USE_XSHM + int major, minor, ignore; + Bool pixmaps; + + if (XQueryExtension( display, "MIT-SHM", &ignore, &ignore, &ignore )) { + if (XShmQueryVersion( display, &major, &minor, &pixmaps )==True) { + return (pixmaps==True) ? 2 : 1; + } + else { + return 0; + } + } + else { + return 0; + } +#else + /* Can't compile XSHM support */ + return 0; +#endif +} +#endif + + +/* + * Return the width and height of the given drawable. + */ +static void get_drawable_size( XMesaDisplay *dpy, XMesaDrawable d, + unsigned int *width, unsigned int *height) +{ +#ifdef XFree86Server + (void) dpy; + *width = d->width; + *height = d->height; +#else + Window root; + int x, y; + unsigned int bw, depth; + + _glthread_LOCK_MUTEX(_xmesa_lock); + XGetGeometry( dpy, d, &root, &x, &y, width, height, &bw, &depth ); + _glthread_UNLOCK_MUTEX(_xmesa_lock); +#endif +} + + +/* + * Apply gamma correction to an intensity value in [0..max]. Return the + * new intensity value. + */ +static GLint gamma_adjust( GLfloat gamma, GLint value, GLint max ) +{ + if (gamma == 1.0) { + return value; + } + else { + double x = (double) value / (double) max; + return IROUND_POS((GLfloat) max * pow(x, 1.0F/gamma)); + } +} + + + +/* + * Return the true number of bits per pixel for XImages. + * For example, if we request a 24-bit deep visual we may actually need/get + * 32bpp XImages. This function returns the appropriate bpp. + * Input: dpy - the X display + * visinfo - desribes the visual to be used for XImages + * Return: true number of bits per pixel for XImages + */ +#define GET_BITS_PER_PIXEL(xmv) bits_per_pixel(xmv) + +#ifdef XFree86Server + +static int bits_per_pixel( XMesaVisual xmv ) +{ + XMesaVisualInfo visinfo = xmv->visinfo; + const int depth = visinfo->nplanes; + int i; + for (i = 0; i < screenInfo.numPixmapFormats; i++) { + if (screenInfo.formats[i].depth == depth) + return screenInfo.formats[i].bitsPerPixel; + } + return depth; /* should never get here, but this should be safe */ +} + +#else + +static int bits_per_pixel( XMesaVisual xmv ) +{ + XMesaDisplay *dpy = xmv->display; + XMesaVisualInfo visinfo = xmv->visinfo; + XMesaImage *img; + int bitsPerPixel; + /* Create a temporary XImage */ + img = XCreateImage( dpy, visinfo->visual, visinfo->depth, + ZPixmap, 0, /*format, offset*/ + (char*) MALLOC(8), /*data*/ + 1, 1, /*width, height*/ + 32, /*bitmap_pad*/ + 0 /*bytes_per_line*/ + ); + assert(img); + /* grab the bits/pixel value */ + bitsPerPixel = img->bits_per_pixel; + /* free the XImage */ + FREE( img->data ); + img->data = NULL; + XMesaDestroyImage( img ); + return bitsPerPixel; +} +#endif + + + +/* + * Determine if a given X window ID is valid (window exists). + * Do this by calling XGetWindowAttributes() for the window and + * checking if we catch an X error. + * Input: dpy - the display + * win - the window to check for existance + * Return: GL_TRUE - window exists + * GL_FALSE - window doesn't exist + */ +#ifndef XFree86Server +static GLboolean WindowExistsFlag; + +static int window_exists_err_handler( XMesaDisplay* dpy, XErrorEvent* xerr ) +{ + (void) dpy; + if (xerr->error_code == BadWindow) { + WindowExistsFlag = GL_FALSE; + } + return 0; +} + +static GLboolean window_exists( XMesaDisplay *dpy, Window win ) +{ + XWindowAttributes wa; + int (*old_handler)( XMesaDisplay*, XErrorEvent* ); + WindowExistsFlag = GL_TRUE; + old_handler = XSetErrorHandler(window_exists_err_handler); + XGetWindowAttributes( dpy, win, &wa ); /* dummy request */ + XSetErrorHandler(old_handler); + return WindowExistsFlag; +} +#endif + + + +/**********************************************************************/ +/***** Linked list of XMesaBuffers *****/ +/**********************************************************************/ + +static XMesaBuffer XMesaBufferList = NULL; + + +/* Allocate a new XMesaBuffer, add to linked list */ +static XMesaBuffer alloc_xmesa_buffer(void) +{ + XMesaBuffer b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer); + if (b) { + b->Next = XMesaBufferList; + XMesaBufferList = b; + } + return b; +} + + +/* + * Find an XMesaBuffer by matching X display and colormap but NOT matching + * the notThis buffer. + */ +static XMesaBuffer find_xmesa_buffer(XMesaDisplay *dpy, + XMesaColormap cmap, + XMesaBuffer notThis) +{ + XMesaBuffer b; + for (b=XMesaBufferList; b; b=b->Next) { + if (b->display==dpy && b->cmap==cmap && b!=notThis) { + return b; + } + } + return NULL; +} + + +/* + * Free an XMesaBuffer, remove from linked list, perhaps free X colormap + * entries. + */ +static void free_xmesa_buffer(int client, XMesaBuffer buffer) +{ + XMesaBuffer prev = NULL, b; + (void) client; + for (b=XMesaBufferList; b; b=b->Next) { + if (b==buffer) { + /* unlink bufer from list */ + if (prev) + prev->Next = buffer->Next; + else + XMesaBufferList = buffer->Next; + /* Check to free X colors */ + if (buffer->num_alloced>0) { + /* If no other buffer uses this X colormap then free the colors. */ + if (!find_xmesa_buffer(buffer->display, buffer->cmap, buffer)) { +#ifdef XFree86Server + (void)FreeColors(buffer->cmap, client, + buffer->num_alloced, buffer->alloced_colors, + 0); +#else + XFreeColors(buffer->display, buffer->cmap, + buffer->alloced_colors, buffer->num_alloced, 0); +#endif + } + } + + _mesa_free_framebuffer_data(&buffer->mesa_buffer); + FREE(buffer); + + return; + } + /* continue search */ + prev = b; + } + /* buffer not found in XMesaBufferList */ + _mesa_problem(NULL,"free_xmesa_buffer() - buffer not found\n"); +} + + +/* Copy X color table stuff from one XMesaBuffer to another. */ +static void copy_colortable_info(XMesaBuffer dst, const XMesaBuffer src) +{ + MEMCPY(dst->color_table, src->color_table, sizeof(src->color_table)); + MEMCPY(dst->pixel_to_r, src->pixel_to_r, sizeof(src->pixel_to_r)); + MEMCPY(dst->pixel_to_g, src->pixel_to_g, sizeof(src->pixel_to_g)); + MEMCPY(dst->pixel_to_b, src->pixel_to_b, sizeof(src->pixel_to_b)); + dst->num_alloced = src->num_alloced; + MEMCPY(dst->alloced_colors, src->alloced_colors, + sizeof(src->alloced_colors)); +} + + + +/**********************************************************************/ +/***** Misc Private Functions *****/ +/**********************************************************************/ + + +/* + * Return number of bits set in n. + */ +static int bitcount( unsigned long n ) +{ + int bits; + for (bits=0; n>0; n=n>>1) { + if (n&1) { + bits++; + } + } + return bits; +} + + + +/* + * Allocate a shared memory XImage back buffer for the given XMesaBuffer. + * Return: GL_TRUE if success, GL_FALSE if error + */ +#ifndef XFree86Server +static GLboolean alloc_shm_back_buffer( XMesaBuffer b ) +{ +#ifdef USE_XSHM + /* + * We have to do a _lot_ of error checking here to be sure we can + * really use the XSHM extension. It seems different servers trigger + * errors at different points if the extension won't work. Therefore + * we have to be very careful... + */ + GC gc; + int (*old_handler)( XMesaDisplay *, XErrorEvent * ); + + b->backimage = XShmCreateImage( b->xm_visual->display, + b->xm_visual->visinfo->visual, + b->xm_visual->visinfo->depth, + ZPixmap, NULL, &b->shminfo, + b->width, b->height ); + if (b->backimage == NULL) { + error("alloc_back_buffer: Shared memory error (XShmCreateImage), disabling."); + b->shm = 0; + return GL_FALSE; + } + + b->shminfo.shmid = shmget( IPC_PRIVATE, b->backimage->bytes_per_line + * b->backimage->height, IPC_CREAT|0777 ); + if (b->shminfo.shmid < 0) { + if (getenv("MESA_DEBUG")) + perror("alloc_back_buffer"); + XDestroyImage( b->backimage ); + b->backimage = NULL; + error("alloc_back_buffer: Shared memory error (shmget), disabling."); + b->shm = 0; + return GL_FALSE; + } + + b->shminfo.shmaddr = b->backimage->data + = (char*)shmat( b->shminfo.shmid, 0, 0 ); + if (b->shminfo.shmaddr == (char *) -1) { + if (getenv("MESA_DEBUG")) + perror("alloc_back_buffer"); + XDestroyImage( b->backimage ); + shmctl( b->shminfo.shmid, IPC_RMID, 0 ); + b->backimage = NULL; + error("alloc_back_buffer: Shared memory error (shmat), disabling."); + b->shm = 0; + return GL_FALSE; + } + + b->shminfo.readOnly = False; + mesaXErrorFlag = 0; + old_handler = XSetErrorHandler( mesaHandleXError ); + /* This may trigger the X protocol error we're ready to catch: */ + XShmAttach( b->xm_visual->display, &b->shminfo ); + XSync( b->xm_visual->display, False ); + + if (mesaXErrorFlag) { + /* we are on a remote display, this error is normal, don't print it */ + XFlush( b->xm_visual->display ); + mesaXErrorFlag = 0; + XDestroyImage( b->backimage ); + shmdt( b->shminfo.shmaddr ); + shmctl( b->shminfo.shmid, IPC_RMID, 0 ); + b->backimage = NULL; + b->shm = 0; + (void) XSetErrorHandler( old_handler ); + return GL_FALSE; + } + + shmctl( b->shminfo.shmid, IPC_RMID, 0 ); /* nobody else needs it */ + + /* Finally, try an XShmPutImage to be really sure the extension works */ + gc = XCreateGC( b->xm_visual->display, b->frontbuffer, 0, NULL ); + XShmPutImage( b->xm_visual->display, b->frontbuffer, gc, + b->backimage, 0, 0, 0, 0, 1, 1 /*one pixel*/, False ); + XSync( b->xm_visual->display, False ); + XFreeGC( b->xm_visual->display, gc ); + (void) XSetErrorHandler( old_handler ); + if (mesaXErrorFlag) { + XFlush( b->xm_visual->display ); + mesaXErrorFlag = 0; + XDestroyImage( b->backimage ); + shmdt( b->shminfo.shmaddr ); + shmctl( b->shminfo.shmid, IPC_RMID, 0 ); + b->backimage = NULL; + b->shm = 0; + return GL_FALSE; + } + + if (b->backimage) { + int height = b->backimage->height; + /* Needed by PIXELADDR1 macro */ + b->ximage_width1 = b->backimage->bytes_per_line; + b->ximage_origin1 = (GLubyte *) b->backimage->data + + b->ximage_width1 * (height-1); + /* Needed by PIXELADDR2 macro */ + b->ximage_width2 = b->backimage->bytes_per_line / 2; + b->ximage_origin2 = (GLushort *) b->backimage->data + + b->ximage_width2 * (height-1); + /* Needed by PIXELADDR3 macro */ + b->ximage_width3 = b->backimage->bytes_per_line; + b->ximage_origin3 = (GLubyte *) b->backimage->data + + b->ximage_width3 * (height-1); + /* Needed by PIXELADDR4 macro */ + b->ximage_width4 = b->backimage->width; + b->ximage_origin4 = (GLuint *) b->backimage->data + + b->ximage_width4 * (height-1); + } + + return GL_TRUE; +#else + /* Can't compile XSHM support */ + return GL_FALSE; +#endif +} +#endif + + + +/* + * Setup an off-screen pixmap or Ximage to use as the back buffer. + * Input: b - the X/Mesa buffer + */ +void xmesa_alloc_back_buffer( XMesaBuffer b ) +{ + if (b->db_state==BACK_XIMAGE) { + /* Deallocate the old backimage, if any */ + if (b->backimage) { +#if defined(USE_XSHM) && !defined(XFree86Server) + if (b->shm) { + XShmDetach( b->xm_visual->display, &b->shminfo ); + XDestroyImage( b->backimage ); + shmdt( b->shminfo.shmaddr ); + } + else +#endif + XMesaDestroyImage( b->backimage ); + b->backimage = NULL; + } + + /* Allocate new back buffer */ +#ifdef XFree86Server + { + /* Allocate a regular XImage for the back buffer. */ + b->backimage = XMesaCreateImage(b->xm_visual->BitsPerPixel, + b->width, b->height, NULL); +#else + if (b->shm==0 + || alloc_shm_back_buffer(b)==GL_FALSE + ) { + /* Allocate a regular XImage for the back buffer. */ + b->backimage = XCreateImage( b->xm_visual->display, + b->xm_visual->visinfo->visual, + GET_VISUAL_DEPTH(b->xm_visual), + ZPixmap, 0, /* format, offset */ + NULL, b->width, b->height, + 8, 0 ); /* pad, bytes_per_line */ +#endif + if (!b->backimage) { + error("alloc_back_buffer: XCreateImage failed."); + } + b->backimage->data = (char *) MALLOC( b->backimage->height + * b->backimage->bytes_per_line ); + if (!b->backimage->data) { + error("alloc_back_buffer: MALLOC failed."); + XMesaDestroyImage( b->backimage ); + b->backimage = NULL; + } + } + b->backpixmap = None; + } + else if (b->db_state==BACK_PIXMAP) { + XMesaPixmap old_pixmap = b->backpixmap; + /* Free the old back pixmap */ + if (b->backpixmap) { + XMesaFreePixmap( b->xm_visual->display, b->backpixmap ); + } + /* Allocate new back pixmap */ + b->backpixmap = XMesaCreatePixmap( b->xm_visual->display, b->frontbuffer, + b->width, b->height, + GET_VISUAL_DEPTH(b->xm_visual) ); + b->backimage = NULL; + /* update other references to backpixmap */ + if (b->buffer==(XMesaDrawable)old_pixmap) { + b->buffer = (XMesaDrawable)b->backpixmap; + } + } +} + + + +/* + * A replacement for XAllocColor. This function should never + * fail to allocate a color. When XAllocColor fails, we return + * the nearest matching color. If we have to allocate many colors + * this function isn't too efficient; the XQueryColors() could be + * done just once. + * Written by Michael Pichler, Brian Paul, Mark Kilgard + * Input: dpy - X display + * cmap - X colormap + * cmapSize - size of colormap + * In/Out: color - the XColor struct + * Output: exact - 1=exact color match, 0=closest match + * alloced - 1=XAlloc worked, 0=XAlloc failed + */ +static void +noFaultXAllocColor( int client, + XMesaDisplay *dpy, + XMesaColormap cmap, + int cmapSize, + XMesaColor *color, + int *exact, int *alloced ) +{ +#ifdef XFree86Server + Pixel *ppixIn; + xrgb *ctable; +#else + /* we'll try to cache ctable for better remote display performance */ + static Display *prevDisplay = NULL; + static XMesaColormap prevCmap = 0; + static int prevCmapSize = 0; + static XMesaColor *ctable = NULL; +#endif + XMesaColor subColor; + int i, bestmatch; + double mindist; /* 3*2^16^2 exceeds long int precision. */ + + (void) client; + + /* First try just using XAllocColor. */ +#ifdef XFree86Server + if (AllocColor(cmap, + &color->red, &color->green, &color->blue, + &color->pixel, + client) == Success) { +#else + if (XAllocColor(dpy, cmap, color)) { +#endif + *exact = 1; + *alloced = 1; + return; + } + + /* Alloc failed, search for closest match */ + + /* Retrieve color table entries. */ + /* XXX alloca candidate. */ +#ifdef XFree86Server + ppixIn = (Pixel *) MALLOC(cmapSize * sizeof(Pixel)); + ctable = (xrgb *) MALLOC(cmapSize * sizeof(xrgb)); + for (i = 0; i < cmapSize; i++) { + ppixIn[i] = i; + } + QueryColors(cmap, cmapSize, ppixIn, ctable); +#else + if (prevDisplay != dpy || prevCmap != cmap + || prevCmapSize != cmapSize || !ctable) { + /* free previously cached color table */ + if (ctable) + FREE(ctable); + /* Get the color table from X */ + ctable = (XMesaColor *) MALLOC(cmapSize * sizeof(XMesaColor)); + assert(ctable); + for (i = 0; i < cmapSize; i++) { + ctable[i].pixel = i; + } + XQueryColors(dpy, cmap, ctable, cmapSize); + prevDisplay = dpy; + prevCmap = cmap; + prevCmapSize = cmapSize; + } +#endif + + /* Find best match. */ + bestmatch = -1; + mindist = 0.0; + for (i = 0; i < cmapSize; i++) { + double dr = 0.30 * ((double) color->red - (double) ctable[i].red); + double dg = 0.59 * ((double) color->green - (double) ctable[i].green); + double db = 0.11 * ((double) color->blue - (double) ctable[i].blue); + double dist = dr * dr + dg * dg + db * db; + if (bestmatch < 0 || dist < mindist) { + bestmatch = i; + mindist = dist; + } + } + + /* Return result. */ + subColor.red = ctable[bestmatch].red; + subColor.green = ctable[bestmatch].green; + subColor.blue = ctable[bestmatch].blue; + /* Try to allocate the closest match color. This should only + * fail if the cell is read/write. Otherwise, we're incrementing + * the cell's reference count. + */ +#ifdef XFree86Server + if (AllocColor(cmap, + &subColor.red, &subColor.green, &subColor.blue, + &subColor.pixel, + client) == Success) { +#else + if (XAllocColor(dpy, cmap, &subColor)) { +#endif + *alloced = 1; + } + else { + /* do this to work around a problem reported by Frank Ortega */ + subColor.pixel = (unsigned long) bestmatch; + subColor.red = ctable[bestmatch].red; + subColor.green = ctable[bestmatch].green; + subColor.blue = ctable[bestmatch].blue; + subColor.flags = DoRed | DoGreen | DoBlue; + *alloced = 0; + } +#ifdef XFree86Server + FREE(ppixIn); + FREE(ctable); +#else + /* don't free table, save it for next time */ +#endif + + *color = subColor; + *exact = 0; +} + + + + +/* + * Do setup for PF_GRAYSCALE pixel format. + * Note that buffer may be NULL. + */ +static GLboolean setup_grayscale( int client, XMesaVisual v, + XMesaBuffer buffer, XMesaColormap cmap ) +{ + if (GET_VISUAL_DEPTH(v)<4 || GET_VISUAL_DEPTH(v)>16) { + return GL_FALSE; + } + + if (buffer) { + XMesaBuffer prevBuffer; + + if (!cmap) { + return GL_FALSE; + } + + prevBuffer = find_xmesa_buffer(v->display, cmap, buffer); + if (prevBuffer && + (buffer->xm_visual->mesa_visual.rgbMode == + prevBuffer->xm_visual->mesa_visual.rgbMode)) { + /* Copy colormap stuff from previous XMesaBuffer which uses same + * X colormap. Do this to avoid time spent in noFaultXAllocColor. + */ + copy_colortable_info(buffer, prevBuffer); + } + else { + /* Allocate 256 shades of gray */ + int gray; + int colorsfailed = 0; + for (gray=0;gray<256;gray++) { + GLint r = gamma_adjust( v->RedGamma, gray, 255 ); + GLint g = gamma_adjust( v->GreenGamma, gray, 255 ); + GLint b = gamma_adjust( v->BlueGamma, gray, 255 ); + int exact, alloced; + XMesaColor xcol; + xcol.red = (r << 8) | r; + xcol.green = (g << 8) | g; + xcol.blue = (b << 8) | b; + noFaultXAllocColor( client, v->display, + cmap, GET_COLORMAP_SIZE(v), + &xcol, &exact, &alloced ); + if (!exact) { + colorsfailed++; + } + if (alloced) { + assert(buffer->num_alloced<256); + buffer->alloced_colors[buffer->num_alloced] = xcol.pixel; + buffer->num_alloced++; + } + + /*OLD + assert(gray < 576); + buffer->color_table[gray*3+0] = xcol.pixel; + buffer->color_table[gray*3+1] = xcol.pixel; + buffer->color_table[gray*3+2] = xcol.pixel; + assert(xcol.pixel < 65536); + buffer->pixel_to_r[xcol.pixel] = gray * 30 / 100; + buffer->pixel_to_g[xcol.pixel] = gray * 59 / 100; + buffer->pixel_to_b[xcol.pixel] = gray * 11 / 100; + */ + buffer->color_table[gray] = xcol.pixel; + assert(xcol.pixel < 65536); + buffer->pixel_to_r[xcol.pixel] = gray; + buffer->pixel_to_g[xcol.pixel] = gray; + buffer->pixel_to_b[xcol.pixel] = gray; + } + + if (colorsfailed && getenv("MESA_DEBUG")) { + fprintf( stderr, + "Note: %d out of 256 needed colors do not match exactly.\n", + colorsfailed ); + } + } + } + + v->dithered_pf = PF_GRAYSCALE; + v->undithered_pf = PF_GRAYSCALE; + return GL_TRUE; +} + + + +/* + * Setup RGB rendering for a window with a PseudoColor, StaticColor, + * or 8-bit TrueColor visual visual. We try to allocate a palette of 225 + * colors (5 red, 9 green, 5 blue) and dither to approximate a 24-bit RGB + * color. While this function was originally designed just for 8-bit + * visuals, it has also proven to work from 4-bit up to 16-bit visuals. + * Dithering code contributed by Bob Mercier. + */ +static GLboolean setup_dithered_color( int client, XMesaVisual v, + XMesaBuffer buffer, XMesaColormap cmap ) +{ + if (GET_VISUAL_DEPTH(v)<4 || GET_VISUAL_DEPTH(v)>16) { + return GL_FALSE; + } + + if (buffer) { + XMesaBuffer prevBuffer; + + if (!cmap) { + return GL_FALSE; + } + + prevBuffer = find_xmesa_buffer(v->display, cmap, buffer); + if (prevBuffer && + (buffer->xm_visual->mesa_visual.rgbMode == + prevBuffer->xm_visual->mesa_visual.rgbMode)) { + /* Copy colormap stuff from previous, matching XMesaBuffer. + * Do this to avoid time spent in noFaultXAllocColor. + */ + copy_colortable_info(buffer, prevBuffer); + } + else { + /* Allocate X colors and initialize color_table[], red_table[], etc */ + int r, g, b, i; + int colorsfailed = 0; + for (r = 0; r < _R; r++) { + for (g = 0; g < _G; g++) { + for (b = 0; b < _B; b++) { + XMesaColor xcol; + int exact, alloced; + xcol.red =gamma_adjust(v->RedGamma, r*65535/(_R-1),65535); + xcol.green=gamma_adjust(v->GreenGamma, g*65535/(_G-1),65535); + xcol.blue =gamma_adjust(v->BlueGamma, b*65535/(_B-1),65535); + noFaultXAllocColor( client, v->display, + cmap, GET_COLORMAP_SIZE(v), + &xcol, &exact, &alloced ); + if (!exact) { + colorsfailed++; + } + if (alloced) { + assert(buffer->num_alloced<256); + buffer->alloced_colors[buffer->num_alloced] = xcol.pixel; + buffer->num_alloced++; + } + i = _MIX( r, g, b ); + assert(i < 576); + buffer->color_table[i] = xcol.pixel; + assert(xcol.pixel < 65536); + buffer->pixel_to_r[xcol.pixel] = r * 255 / (_R-1); + buffer->pixel_to_g[xcol.pixel] = g * 255 / (_G-1); + buffer->pixel_to_b[xcol.pixel] = b * 255 / (_B-1); + } + } + } + + if (colorsfailed && getenv("MESA_DEBUG")) { + fprintf( stderr, + "Note: %d out of %d needed colors do not match exactly.\n", + colorsfailed, _R*_G*_B ); + } + } + } + + v->dithered_pf = PF_DITHER; + v->undithered_pf = PF_LOOKUP; + return GL_TRUE; +} + + +/* + * Setup for Hewlett Packard Color Recovery 8-bit TrueColor mode. + * HPCR simulates 24-bit color fidelity with an 8-bit frame buffer. + * Special dithering tables have to be initialized. + */ +static void setup_8bit_hpcr( XMesaVisual v ) +{ + /* HP Color Recovery contributed by: Alex De Bruyn (ad@lms.be) + * To work properly, the atom _HP_RGB_SMOOTH_MAP_LIST must be defined + * on the root window AND the colormap obtainable by XGetRGBColormaps + * for that atom must be set on the window. (see also tkInitWindow) + * If that colormap is not set, the output will look stripy. + */ + + /* Setup color tables with gamma correction */ + int i; + double g; + + g = 1.0 / v->RedGamma; + for (i=0; i<256; i++) { + GLint red = IROUND_POS(255.0 * pow( hpcr_rgbTbl[0][i]/255.0, g )); + v->hpcr_rgbTbl[0][i] = CLAMP( red, 16, 239 ); + } + + g = 1.0 / v->GreenGamma; + for (i=0; i<256; i++) { + GLint green = IROUND_POS(255.0 * pow( hpcr_rgbTbl[1][i]/255.0, g )); + v->hpcr_rgbTbl[1][i] = CLAMP( green, 16, 239 ); + } + + g = 1.0 / v->BlueGamma; + for (i=0; i<256; i++) { + GLint blue = IROUND_POS(255.0 * pow( hpcr_rgbTbl[2][i]/255.0, g )); + v->hpcr_rgbTbl[2][i] = CLAMP( blue, 32, 223 ); + } + v->undithered_pf = PF_HPCR; /* can't really disable dithering for now */ + v->dithered_pf = PF_HPCR; + + /* which method should I use to clear */ + /* GL_FALSE: keep the ordinary method */ + /* GL_TRUE : clear with dither pattern */ + v->hpcr_clear_flag = getenv("MESA_HPCR_CLEAR") ? GL_TRUE : GL_FALSE; + + if (v->hpcr_clear_flag) { + v->hpcr_clear_pixmap = XMesaCreatePixmap(v->display, + DefaultRootWindow(v->display), + 16, 2, 8); +#ifndef XFree86Server + v->hpcr_clear_ximage = XGetImage(v->display, v->hpcr_clear_pixmap, + 0, 0, 16, 2, AllPlanes, ZPixmap); +#endif + } +} + + +/* + * Setup RGB rendering for a window with a True/DirectColor visual. + */ +static void setup_truecolor( XMesaVisual v, XMesaBuffer buffer, + XMesaColormap cmap ) +{ + unsigned long rmask, gmask, bmask; + (void) buffer; + (void) cmap; + + /* Compute red multiplier (mask) and bit shift */ + v->rshift = 0; + rmask = GET_REDMASK(v); + while ((rmask & 1)==0) { + v->rshift++; + rmask = rmask >> 1; + } + + /* Compute green multiplier (mask) and bit shift */ + v->gshift = 0; + gmask = GET_GREENMASK(v); + while ((gmask & 1)==0) { + v->gshift++; + gmask = gmask >> 1; + } + + /* Compute blue multiplier (mask) and bit shift */ + v->bshift = 0; + bmask = GET_BLUEMASK(v); + while ((bmask & 1)==0) { + v->bshift++; + bmask = bmask >> 1; + } + + /* + * Compute component-to-pixel lookup tables and dithering kernel + */ + { + static GLubyte kernel[16] = { + 0*16, 8*16, 2*16, 10*16, + 12*16, 4*16, 14*16, 6*16, + 3*16, 11*16, 1*16, 9*16, + 15*16, 7*16, 13*16, 5*16, + }; + GLint rBits = bitcount(rmask); + GLint gBits = bitcount(gmask); + GLint bBits = bitcount(bmask); + GLint maxBits; + GLuint i; + + /* convert pixel components in [0,_mask] to RGB values in [0,255] */ + for (i=0; i<=rmask; i++) + v->PixelToR[i] = (unsigned char) ((i * 255) / rmask); + for (i=0; i<=gmask; i++) + v->PixelToG[i] = (unsigned char) ((i * 255) / gmask); + for (i=0; i<=bmask; i++) + v->PixelToB[i] = (unsigned char) ((i * 255) / bmask); + + /* convert RGB values from [0,255] to pixel components */ + + for (i=0;i<256;i++) { + GLint r = gamma_adjust(v->RedGamma, i, 255); + GLint g = gamma_adjust(v->GreenGamma, i, 255); + GLint b = gamma_adjust(v->BlueGamma, i, 255); + v->RtoPixel[i] = (r >> (8-rBits)) << v->rshift; + v->GtoPixel[i] = (g >> (8-gBits)) << v->gshift; + v->BtoPixel[i] = (b >> (8-bBits)) << v->bshift; + } + /* overflow protection */ + for (i=256;i<512;i++) { + v->RtoPixel[i] = v->RtoPixel[255]; + v->GtoPixel[i] = v->GtoPixel[255]; + v->BtoPixel[i] = v->BtoPixel[255]; + } + + /* setup dithering kernel */ + maxBits = rBits; + if (gBits > maxBits) maxBits = gBits; + if (bBits > maxBits) maxBits = bBits; + for (i=0;i<16;i++) { + v->Kernel[i] = kernel[i] >> maxBits; + } + + v->undithered_pf = PF_TRUECOLOR; + v->dithered_pf = (GET_VISUAL_DEPTH(v)<24) ? PF_TRUEDITHER : PF_TRUECOLOR; + } + + /* + * Now check for TrueColor visuals which we can optimize. + */ + if ( GET_REDMASK(v) ==0x0000ff + && GET_GREENMASK(v)==0x00ff00 + && GET_BLUEMASK(v) ==0xff0000 + && CHECK_BYTE_ORDER(v) + && v->BitsPerPixel==32 + && sizeof(GLuint)==4 + && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) { + /* common 32 bpp config used on SGI, Sun */ + v->undithered_pf = v->dithered_pf = PF_8A8B8G8R; + } + else if (GET_REDMASK(v) ==0xff0000 + && GET_GREENMASK(v)==0x00ff00 + && GET_BLUEMASK(v) ==0x0000ff + && CHECK_BYTE_ORDER(v) + && v->BitsPerPixel==32 + && sizeof(GLuint)==4 + && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) { + /* common 32 bpp config used on Linux, HP, IBM */ + v->undithered_pf = v->dithered_pf = PF_8R8G8B; + } + else if (GET_REDMASK(v) ==0xff0000 + && GET_GREENMASK(v)==0x00ff00 + && GET_BLUEMASK(v) ==0x0000ff + && CHECK_BYTE_ORDER(v) + && v->BitsPerPixel==24 + && sizeof(GLuint)==4 + && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) { + /* common packed 24 bpp config used on Linux */ + v->undithered_pf = v->dithered_pf = PF_8R8G8B24; + } + else if (GET_REDMASK(v) ==0xf800 + && GET_GREENMASK(v)==0x07e0 + && GET_BLUEMASK(v) ==0x001f + && CHECK_BYTE_ORDER(v) + && v->BitsPerPixel==16 + && sizeof(GLushort)==2 + && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) { + /* 5-6-5 color weight on common PC VGA boards */ + v->undithered_pf = PF_5R6G5B; + v->dithered_pf = PF_DITHER_5R6G5B; + } + else if (GET_REDMASK(v) ==0xe0 + && GET_GREENMASK(v)==0x1c + && GET_BLUEMASK(v) ==0x03 + && CHECK_FOR_HPCR(v)) { + setup_8bit_hpcr( v ); + } +} + + + +/* + * Setup RGB rendering for a window with a monochrome visual. + */ +static void setup_monochrome( XMesaVisual v, XMesaBuffer b ) +{ + (void) b; + v->dithered_pf = v->undithered_pf = PF_1BIT; + /* if black=1 then we must flip pixel values */ + v->bitFlip = (GET_BLACK_PIXEL(v) != 0); +} + + + +/* + * When a context is "made current" for the first time, we can finally + * finish initializing the context's visual and buffer information. + * Input: v - the XMesaVisual to initialize + * b - the XMesaBuffer to initialize (may be NULL) + * rgb_flag - TRUE = RGBA mode, FALSE = color index mode + * window - the window/pixmap we're rendering into + * cmap - the colormap associated with the window/pixmap + * Return: GL_TRUE=success, GL_FALSE=failure + */ +static GLboolean initialize_visual_and_buffer( int client, + XMesaVisual v, + XMesaBuffer b, + GLboolean rgb_flag, + XMesaDrawable window, + XMesaColormap cmap + ) +{ +#ifndef XFree86Server + XGCValues gcvalues; +#endif + + if (b) { + assert(b->xm_visual == v); + } + + /* Save true bits/pixel */ + v->BitsPerPixel = GET_BITS_PER_PIXEL(v); + assert(v->BitsPerPixel > 0); + + + if (rgb_flag==GL_FALSE) { + /* COLOR-INDEXED WINDOW: + * Even if the visual is TrueColor or DirectColor we treat it as + * being color indexed. This is weird but might be useful to someone. + */ + v->dithered_pf = v->undithered_pf = PF_INDEX; + v->index_bits = GET_VISUAL_DEPTH(v); + } + else { + /* RGB WINDOW: + * We support RGB rendering into almost any kind of visual. + */ + int xclass; + xclass = GET_VISUAL_CLASS(v); + if (xclass==TrueColor || xclass==DirectColor) { + setup_truecolor( v, b, cmap ); + } + else if (xclass==StaticGray && GET_VISUAL_DEPTH(v)==1) { + setup_monochrome( v, b ); + } + else if (xclass==GrayScale || xclass==StaticGray) { + if (!setup_grayscale( client, v, b, cmap )) { + return GL_FALSE; + } + } + else if ((xclass==PseudoColor || xclass==StaticColor) + && GET_VISUAL_DEPTH(v)>=4 && GET_VISUAL_DEPTH(v)<=16) { + if (!setup_dithered_color( client, v, b, cmap )) { + return GL_FALSE; + } + } + else { + error("XMesa: RGB mode rendering not supported in given visual."); + return GL_FALSE; + } + v->index_bits = 0; + + if (getenv("MESA_NO_DITHER")) { + v->dithered_pf = v->undithered_pf; + } + } + + + /* + * If MESA_INFO env var is set print out some debugging info + * which can help Brian figure out what's going on when a user + * reports bugs. + */ + if (getenv("MESA_INFO")) { + fprintf(stderr, "X/Mesa visual = %p\n", (void *) v); + fprintf(stderr, "X/Mesa dithered pf = %u\n", v->dithered_pf); + fprintf(stderr, "X/Mesa undithered pf = %u\n", v->undithered_pf); + fprintf(stderr, "X/Mesa level = %d\n", v->level); + fprintf(stderr, "X/Mesa depth = %d\n", GET_VISUAL_DEPTH(v)); + fprintf(stderr, "X/Mesa bits per pixel = %d\n", v->BitsPerPixel); + } + + if (b && window) { + /* Do window-specific initializations */ + + /* Window dimensions */ + unsigned int w, h; + get_drawable_size( v->display, window, &w, &h ); + b->width = w; + b->height = h; + + b->frontbuffer = window; + + /* Setup for single/double buffering */ + if (v->mesa_visual.doubleBufferMode) { + /* Double buffered */ +#ifndef XFree86Server + b->shm = check_for_xshm( v->display ); +#endif + xmesa_alloc_back_buffer( b ); + if (b->db_state==BACK_PIXMAP) { + b->buffer = (XMesaDrawable)b->backpixmap; + } + else { + b->buffer = XIMAGE; + } + } + else { + /* Single Buffered */ + b->buffer = b->frontbuffer; + } + + /* X11 graphics contexts */ +#ifdef XFree86Server + b->gc = CreateScratchGC(v->display, window->depth); +#else + b->gc = XCreateGC( v->display, window, 0, NULL ); +#endif + XMesaSetFunction( v->display, b->gc, GXcopy ); + + /* cleargc - for glClear() */ +#ifdef XFree86Server + b->cleargc = CreateScratchGC(v->display, window->depth); +#else + b->cleargc = XCreateGC( v->display, window, 0, NULL ); +#endif + XMesaSetFunction( v->display, b->cleargc, GXcopy ); + + /* + * Don't generate Graphics Expose/NoExpose events in swapbuffers(). + * Patch contributed by Michael Pichler May 15, 1995. + */ +#ifdef XFree86Server + b->swapgc = CreateScratchGC(v->display, window->depth); + { + CARD32 v[1]; + v[0] = FALSE; + dixChangeGC(NullClient, b->swapgc, GCGraphicsExposures, v, NULL); + } +#else + gcvalues.graphics_exposures = False; + b->swapgc = XCreateGC( v->display, window, + GCGraphicsExposures, &gcvalues); +#endif + XMesaSetFunction( v->display, b->swapgc, GXcopy ); + /* + * Set fill style and tile pixmap once for all for HPCR stuff + * (instead of doing it each time in clear_color_HPCR_pixmap()) + * Initialize whole stuff + * Patch contributed by Jacques Leroy March 8, 1998. + */ + if (v->hpcr_clear_flag && b->buffer!=XIMAGE) { + int i; + for (i=0; i<16; i++) + { + XMesaPutPixel(v->hpcr_clear_ximage, i, 0, 0); + XMesaPutPixel(v->hpcr_clear_ximage, i, 1, 0); + } + XMesaPutImage(b->display, (XMesaDrawable)v->hpcr_clear_pixmap, + b->cleargc, v->hpcr_clear_ximage, 0, 0, 0, 0, 16, 2); + XMesaSetFillStyle( v->display, b->cleargc, FillTiled); + XMesaSetTile( v->display, b->cleargc, v->hpcr_clear_pixmap ); + } + + /* Initialize the row buffer XImage for use in write_color_span() */ +#ifdef XFree86Server + b->rowimage = XMesaCreateImage(GET_VISUAL_DEPTH(v), MAX_WIDTH, 1, + (char *)MALLOC(MAX_WIDTH*4)); +#else + b->rowimage = XCreateImage( v->display, + v->visinfo->visual, + v->visinfo->depth, + ZPixmap, 0, /*format, offset*/ + (char*) MALLOC(MAX_WIDTH*4), /*data*/ + MAX_WIDTH, 1, /*width, height*/ + 32, /*bitmap_pad*/ + 0 /*bytes_per_line*/ ); +#endif + } + + return GL_TRUE; +} + + + +/* + * Convert an RGBA color to a pixel value. + */ +unsigned long +xmesa_color_to_pixel( XMesaContext xmesa, GLubyte r, GLubyte g, GLubyte b, GLubyte a, + GLuint pixelFormat) +{ + switch (pixelFormat) { + case PF_INDEX: + return 0; + case PF_TRUECOLOR: + { + unsigned long p; + PACK_TRUECOLOR( p, r, g, b ); + return p; + } + case PF_8A8B8G8R: + return PACK_8A8B8G8R( r, g, b, a ); + case PF_8R8G8B: + /* fall through */ + case PF_8R8G8B24: + return PACK_8R8G8B( r, g, b ); + case PF_5R6G5B: + return PACK_5R6G5B( r, g, b ); + case PF_DITHER: + { + DITHER_SETUP; + return DITHER( 1, 0, r, g, b ); + } + case PF_1BIT: + /* 382 = (3*255)/2 */ + return ((r+g+b) > 382) ^ xmesa->xm_visual->bitFlip; + case PF_HPCR: + return DITHER_HPCR(1, 1, r, g, b); + case PF_LOOKUP: + { + LOOKUP_SETUP; + return LOOKUP( r, g, b ); + } + case PF_GRAYSCALE: + return GRAY_RGB( r, g, b ); + case PF_TRUEDITHER: + /* fall through */ + case PF_DITHER_5R6G5B: + { + unsigned long p; + PACK_TRUEDITHER(p, 1, 0, r, g, b); + return p; + } + default: + _mesa_problem(NULL, "Bad pixel format in xmesa_color_to_pixel"); + } + return 0; +} + + +/**********************************************************************/ +/***** Public Functions *****/ +/**********************************************************************/ + + +/* + * Create a new X/Mesa visual. + * Input: display - X11 display + * visinfo - an XVisualInfo pointer + * rgb_flag - GL_TRUE = RGB mode, + * GL_FALSE = color index mode + * alpha_flag - alpha buffer requested? + * db_flag - GL_TRUE = double-buffered, + * GL_FALSE = single buffered + * stereo_flag - stereo visual? + * ximage_flag - GL_TRUE = use an XImage for back buffer, + * GL_FALSE = use an off-screen pixmap for back buffer + * depth_size - requested bits/depth values, or zero + * stencil_size - requested bits/stencil values, or zero + * accum_red_size - requested bits/red accum values, or zero + * accum_green_size - requested bits/green accum values, or zero + * accum_blue_size - requested bits/blue accum values, or zero + * accum_alpha_size - requested bits/alpha accum values, or zero + * num_samples - number of samples/pixel if multisampling, or zero + * level - visual level, usually 0 + * visualCaveat - ala the GLX extension, usually GLX_NONE_EXT + * Return; a new XMesaVisual or 0 if error. + */ +XMesaVisual XMesaCreateVisual( XMesaDisplay *display, + XMesaVisualInfo visinfo, + GLboolean rgb_flag, + GLboolean alpha_flag, + GLboolean db_flag, + GLboolean stereo_flag, + GLboolean ximage_flag, + GLint depth_size, + GLint stencil_size, + GLint accum_red_size, + GLint accum_green_size, + GLint accum_blue_size, + GLint accum_alpha_size, + GLint num_samples, + GLint level, + GLint visualCaveat ) +{ + char *gamma; + XMesaVisual v; + GLint red_bits, green_bits, blue_bits, alpha_bits; + + /* For debugging only */ + if (getenv("MESA_XSYNC")) { + /* This makes debugging X easier. + * In your debugger, set a breakpoint on _XError to stop when an + * X protocol error is generated. + */ +#ifdef XFree86Server + /* NOT_NEEDED */ +#else + XSynchronize( display, 1 ); +#endif + } + + v = (XMesaVisual) CALLOC_STRUCT(xmesa_visual); + if (!v) { + return NULL; + } + + /* + * In the X server, NULL is passed in for the display. It will have + * to be set before using this visual. See XMesaSetVisualDisplay() + * below. + */ + v->display = display; + + /* Save a copy of the XVisualInfo struct because the user may XFREE() + * the struct but we may need some of the information contained in it + * at a later time. + */ +#ifdef XFree86Server + v->visinfo = visinfo; +#else + v->visinfo = (XVisualInfo *) MALLOC(sizeof(*visinfo)); + if(!v->visinfo) { + FREE(v); + return NULL; + } + MEMCPY(v->visinfo, visinfo, sizeof(*visinfo)); + + /* Save a copy of the pointer now so we can find this visual again + * if we need to search for it in find_glx_visual(). + */ + v->vishandle = visinfo; +#endif + +#ifdef XFree86Server + /* Initialize the depth of the screen */ + { + PixmapFormatRec *format; + + for (format = screenInfo.formats; + format->depth != display->rootDepth; + format++) + ; + v->screen_depth = format->bitsPerPixel; + } +#endif + + /* check for MESA_GAMMA environment variable */ + gamma = getenv("MESA_GAMMA"); + if (gamma) { + v->RedGamma = v->GreenGamma = v->BlueGamma = 0.0; + sscanf( gamma, "%f %f %f", &v->RedGamma, &v->GreenGamma, &v->BlueGamma ); + if (v->RedGamma<=0.0) v->RedGamma = 1.0; + if (v->GreenGamma<=0.0) v->GreenGamma = v->RedGamma; + if (v->BlueGamma<=0.0) v->BlueGamma = v->RedGamma; + } + else { + v->RedGamma = v->GreenGamma = v->BlueGamma = 1.0; + } + + v->ximage_flag = ximage_flag; + v->level = level; + v->VisualCaveat = visualCaveat; + + (void) initialize_visual_and_buffer( 0, v, NULL, rgb_flag, 0, 0 ); + + { + int xclass; + xclass = GET_VISUAL_CLASS(v); + if (xclass==TrueColor || xclass==DirectColor) { + red_bits = bitcount(GET_REDMASK(v)); + green_bits = bitcount(GET_GREENMASK(v)); + blue_bits = bitcount(GET_BLUEMASK(v)); + alpha_bits = 0; + } + else { + /* this is an approximation */ + int depth; + depth = GET_VISUAL_DEPTH(v); + red_bits = depth / 3; + depth -= red_bits; + green_bits = depth / 2; + depth -= green_bits; + blue_bits = depth; + alpha_bits = 0; + assert( red_bits + green_bits + blue_bits == GET_VISUAL_DEPTH(v) ); + } + } + + if (alpha_flag && alpha_bits == 0) + alpha_bits = 8; + + _mesa_initialize_visual( &v->mesa_visual, + rgb_flag, db_flag, stereo_flag, + red_bits, green_bits, + blue_bits, alpha_bits, + v->index_bits, + depth_size, + stencil_size, + accum_red_size, accum_green_size, + accum_blue_size, accum_alpha_size, + 0 ); + return v; +} + + +void XMesaSetVisualDisplay( XMesaDisplay *dpy, XMesaVisual v ) +{ + v->display = dpy; +} + + +void XMesaDestroyVisual( XMesaVisual v ) +{ +#ifndef XFree86Server + FREE(v->visinfo); +#endif + FREE(v); +} + + + +/* + * Create a new XMesaContext. + * Input: v - XMesaVisual + * share_list - another XMesaContext with which to share display + * lists or NULL if no sharing is wanted. + * Return: an XMesaContext or NULL if error. + */ +XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list ) +{ + XMesaContext c; + GLcontext *ctx; + GLboolean direct = GL_TRUE; /* XXXX */ + /* NOT_DONE: should this be GL_FALSE??? */ + static GLboolean firstTime = GL_TRUE; + + if (firstTime) { + _glthread_INIT_MUTEX(_xmesa_lock); + firstTime = GL_FALSE; + } + + c = (XMesaContext) CALLOC_STRUCT(xmesa_context); + if (!c) { + return NULL; + } + + ctx = c->gl_ctx = _mesa_create_context( &v->mesa_visual, + share_list ? share_list->gl_ctx : (GLcontext *) NULL, + (void *) c, direct ); + if (!c->gl_ctx) { + FREE(c); + return NULL; + } + + _mesa_enable_sw_extensions(ctx); + _mesa_enable_1_3_extensions(ctx); + + if (CHECK_BYTE_ORDER(v)) { + c->swapbytes = GL_FALSE; + } + else { + c->swapbytes = GL_TRUE; + } + + c->xm_visual = v; + c->xm_buffer = NULL; /* set later by XMesaMakeCurrent */ + c->display = v->display; + c->pixelformat = v->dithered_pf; /* Dithering is enabled by default */ + + ctx->Driver.UpdateState = xmesa_update_state; + + /* Initialize the software rasterizer and helper modules. + */ + _swrast_CreateContext( ctx ); + _ac_CreateContext( ctx ); + _tnl_CreateContext( ctx ); + _swsetup_CreateContext( ctx ); + + xmesa_register_swrast_functions( ctx ); + + /* Set up some constant pointers: + */ + xmesa_init_pointers( ctx ); + + + /* Run the config file + */ + _mesa_read_config_file( ctx ); + + + return c; +} + + + + +void XMesaDestroyContext( XMesaContext c ) +{ +#ifdef FX + if (c->xm_buffer && c->xm_buffer->FXctx) + fxMesaDestroyContext(c->xm_buffer->FXctx); +#endif + if (c->gl_ctx) { + _swsetup_DestroyContext( c->gl_ctx ); + _swrast_DestroyContext( c->gl_ctx ); + _tnl_DestroyContext( c->gl_ctx ); + _ac_DestroyContext( c->gl_ctx ); + _mesa_destroy_context( c->gl_ctx ); + } + + FREE( c ); +} + + + +/* + * XXX this isn't a public function! It's a hack for the 3Dfx driver. + * Create a new XMesaBuffer from an X window. + * Input: v - the XMesaVisual + * w - the window + * c - the context + * Return: new XMesaBuffer or NULL if error + */ +XMesaBuffer XMesaCreateWindowBuffer2( XMesaVisual v, XMesaWindow w, + XMesaContext c ) +{ +#ifndef XFree86Server + XWindowAttributes attr; +#endif +#ifdef FX + char *fxEnvVar; +#endif + int client = 0; + + XMesaBuffer b = alloc_xmesa_buffer(); + if (!b) { + return NULL; + } + + (void) c; + +#ifdef XFree86Server + client = CLIENT_ID(((XMesaDrawable)w)->id); +#endif + + assert(v); + +#ifdef XFree86Server + if (GET_VISUAL_DEPTH(v) != ((XMesaDrawable)w)->depth) { +#else + XGetWindowAttributes( v->display, w, &attr ); + + if (GET_VISUAL_DEPTH(v) != attr.depth) { +#endif + if (getenv("MESA_DEBUG")) { + fprintf(stderr, "XMesaCreateWindowBuffer: depth mismatch between visual and window!\n"); + } + return NULL; + } + + b->xm_visual = v; + b->pixmap_flag = GL_FALSE; + b->display = v->display; +#ifdef XFree86Server + b->cmap = (ColormapPtr)LookupIDByType(wColormap(w), RT_COLORMAP); +#else + if (attr.colormap) { + b->cmap = attr.colormap; + } + else { + if (getenv("MESA_DEBUG")) { + fprintf(stderr, "Window %u has no colormap!\n", (unsigned int) w); + } + /* this is weird, a window w/out a colormap!? */ + /* OK, let's just allocate a new one and hope for the best */ + b->cmap = XCreateColormap(v->display, w, attr.visual, AllocNone); + } +#endif + + /* determine back buffer implementation */ + if (v->mesa_visual.doubleBufferMode) { + if (v->ximage_flag) { + b->db_state = BACK_XIMAGE; + } + else { + b->db_state = BACK_PIXMAP; + } + } + else { + b->db_state = 0; + } + + _mesa_initialize_framebuffer(&b->mesa_buffer, + &v->mesa_visual, + v->mesa_visual.depthBits > 0, + v->mesa_visual.stencilBits > 0, + v->mesa_visual.accumRedBits > 0, + v->mesa_visual.alphaBits > 0 ); + + if (!initialize_visual_and_buffer( client, v, b, v->mesa_visual.rgbMode, + (XMesaDrawable)w, b->cmap )) { + free_xmesa_buffer(client, b); + return NULL; + } + +#ifdef FX + fxEnvVar = getenv("MESA_GLX_FX"); + if (fxEnvVar) { + if (fxEnvVar[0]!='d') { + int attribs[100]; + int numAttribs = 0; + int hw; + if (v->mesa_visual.depthBits > 0) { + attribs[numAttribs++] = FXMESA_DEPTH_SIZE; + attribs[numAttribs++] = 1; + } + if (v->mesa_visual.doubleBufferMode) { + attribs[numAttribs++] = FXMESA_DOUBLEBUFFER; + } + if (v->mesa_visual.accumRedBits > 0) { + attribs[numAttribs++] = FXMESA_ACCUM_SIZE; + attribs[numAttribs++] = v->mesa_visual.accumRedBits; + } + if (v->mesa_visual.stencilBits > 0) { + attribs[numAttribs++] = FXMESA_STENCIL_SIZE; + attribs[numAttribs++] = v->mesa_visual.stencilBits; + } + if (v->mesa_visual.alphaBits > 0) { + attribs[numAttribs++] = FXMESA_ALPHA_SIZE; + attribs[numAttribs++] = 1; + } + if (c->gl_ctx) { +#define FXMESA_SHARE_CONTEXT 990099 /* keep in sync with fxapi.c! */ + attribs[numAttribs++] = FXMESA_SHARE_CONTEXT; + attribs[numAttribs++] = (int) c->gl_ctx; + } + attribs[numAttribs++] = FXMESA_NONE; + + if ((hw = fxQueryHardware())==GR_SSTTYPE_VOODOO) { + b->FXctx = fxMesaCreateBestContext(0, b->width, b->height, attribs); + if ((v->undithered_pf!=PF_INDEX) && (b->backimage)) { + b->FXisHackUsable = b->FXctx ? GL_TRUE : GL_FALSE; + if (fxEnvVar[0]=='w' || fxEnvVar[0]=='W') + b->FXwindowHack = b->FXctx ? GL_TRUE : GL_FALSE; + else + b->FXwindowHack = GL_FALSE; + } + } + else { + if (fxEnvVar[0]=='w' || fxEnvVar[0]=='W') + b->FXctx = fxMesaCreateContext(w, GR_RESOLUTION_NONE, + GR_REFRESH_75Hz, attribs); + else + b->FXctx = fxMesaCreateBestContext(0, b->width, b->height, attribs); + b->FXisHackUsable = GL_FALSE; + b->FXwindowHack = GL_FALSE; + } + /* + fprintf(stderr, + "voodoo %d, wid %d height %d hack: usable %d active %d\n", + hw, b->width, b->height, b->FXisHackUsable, b->FXwindowHack); + */ + } + } + else { + fprintf(stderr,"WARNING: This Mesa Library includes the Glide driver but\n"); + fprintf(stderr," you have not defined the MESA_GLX_FX env. var.\n"); + fprintf(stderr," (check the README.3DFX file for more information).\n\n"); + fprintf(stderr," you can disable this message with a 'export MESA_GLX_FX=disable'.\n"); + } +#endif + + return b; +} + + +XMesaBuffer XMesaCreateWindowBuffer( XMesaVisual v, XMesaWindow w ) +{ + return XMesaCreateWindowBuffer2( v, w, NULL ); +} + + +/* + * Create a new XMesaBuffer from an X pixmap. + * Input: v - the XMesaVisual + * p - the pixmap + * cmap - the colormap, may be 0 if using a TrueColor or DirectColor + * visual for the pixmap + * Return: new XMesaBuffer or NULL if error + */ +XMesaBuffer XMesaCreatePixmapBuffer( XMesaVisual v, + XMesaPixmap p, XMesaColormap cmap ) +{ + int client = 0; + XMesaBuffer b = alloc_xmesa_buffer(); + if (!b) { + return NULL; + } + + +#ifdef XFree86Server + client = CLIENT_ID(((XMesaDrawable)p)->id); +#endif + + assert(v); + + b->xm_visual = v; + b->pixmap_flag = GL_TRUE; + b->display = v->display; + b->cmap = cmap; + + /* determine back buffer implementation */ + if (v->mesa_visual.doubleBufferMode) { + if (v->ximage_flag) { + b->db_state = BACK_XIMAGE; + } + else { + b->db_state = BACK_PIXMAP; + } + } + else { + b->db_state = 0; + } + + _mesa_initialize_framebuffer(&b->mesa_buffer, + &v->mesa_visual, + v->mesa_visual.depthBits > 0, + v->mesa_visual.stencilBits > 0, + v->mesa_visual.accumRedBits + + v->mesa_visual.accumGreenBits + + v->mesa_visual.accumBlueBits > 0, + v->mesa_visual.alphaBits > 0 ); + + if (!initialize_visual_and_buffer(client, v, b, v->mesa_visual.rgbMode, + (XMesaDrawable)p, cmap)) { + free_xmesa_buffer(client, b); + return NULL; + } + + return b; +} + + + +#if 0 /* not done */ +XMesaBuffer XMesaCreatePBuffer( XMesaVisual v, XMesaColormap cmap, + unsigned int width, unsigned int height ) +{ + int client = 0; + XMesaBuffer b = alloc_xmesa_buffer(); + if (!b) { + return NULL; + } + + b->xm_visual = v; + b->pbuffer_flag = GL_TRUE; + b->display = v->display; + b->cmap = cmap; + + /* determine back buffer implementation */ + if (v->mesa_visual.doubleBufferMode) { + if (v->ximage_flag) { + b->db_state = BACK_XIMAGE; + } + else { + b->db_state = BACK_PIXMAP; + } + } + else { + b->db_state = 0; + } + + _mesa_initialize_framebuffer(&b->mesa_buffer, + &v->mesa_visual, + v->mesa_visual.depthBits > 0, + v->mesa_visual.stencilBits > 0, + v->mesa_visual.accumRedBits + + v->mesa_visual.accumGreenBits + + v->mesa_visual.accumBlueBits > 0, + v->mesa_visual.alphaBits > 0 ); + + if (!initialize_visual_and_buffer(client, v, b, v->mesa_visual.rgbMode, + 0, cmap)) { + free_xmesa_buffer(client, b); + return NULL; + } + + return b; +} +#endif + + + +/* + * Deallocate an XMesaBuffer structure and all related info. + */ +void XMesaDestroyBuffer( XMesaBuffer b ) +{ + int client = 0; + +#ifdef XFree86Server + if (b->frontbuffer) + client = CLIENT_ID(b->frontbuffer->id); +#endif + + if (b->gc) XMesaFreeGC( b->xm_visual->display, b->gc ); + if (b->cleargc) XMesaFreeGC( b->xm_visual->display, b->cleargc ); + if (b->swapgc) XMesaFreeGC( b->xm_visual->display, b->swapgc ); + + if (b->backimage) { +#if defined(USE_XSHM) && !defined(XFree86Server) + if (b->shm) { + XShmDetach( b->xm_visual->display, &b->shminfo ); + XDestroyImage( b->backimage ); + shmdt( b->shminfo.shmaddr ); + } + else +#endif + XMesaDestroyImage( b->backimage ); + } + if (b->backpixmap) { + XMesaFreePixmap( b->xm_visual->display, b->backpixmap ); + if (b->xm_visual->hpcr_clear_flag) { + XMesaFreePixmap( b->xm_visual->display, + b->xm_visual->hpcr_clear_pixmap ); + XMesaDestroyImage( b->xm_visual->hpcr_clear_ximage ); + } + } + if (b->rowimage) { + FREE( b->rowimage->data ); + b->rowimage->data = NULL; + XMesaDestroyImage( b->rowimage ); + } + + free_xmesa_buffer(client, b); +} + + + +/* + * Bind buffer b to context c and make c the current rendering context. + */ +GLboolean XMesaMakeCurrent( XMesaContext c, XMesaBuffer b ) +{ + return XMesaMakeCurrent2( c, b, b ); +} + + +/* + * Bind buffer b to context c and make c the current rendering context. + */ +GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer, + XMesaBuffer readBuffer ) +{ + if (c) { + if (!drawBuffer || !readBuffer) + return GL_FALSE; /* must specify buffers! */ + +#ifdef FX + if (drawBuffer->FXctx) { + fxMesaMakeCurrent(drawBuffer->FXctx); + + c->xm_buffer = drawBuffer; + c->xm_read_buffer = readBuffer; + c->use_read_buffer = (drawBuffer != readBuffer); + + return GL_TRUE; + } +#endif + if (c->gl_ctx == _mesa_get_current_context() + && c->xm_buffer == drawBuffer + && c->xm_read_buffer == readBuffer + && c->xm_buffer->wasCurrent) { + /* same context and buffer, do nothing */ + return GL_TRUE; + } + + c->xm_buffer = drawBuffer; + c->xm_read_buffer = readBuffer; + c->use_read_buffer = (drawBuffer != readBuffer); + + _mesa_make_current2(c->gl_ctx, + &drawBuffer->mesa_buffer, + &readBuffer->mesa_buffer); + + if (c->gl_ctx->Viewport.Width == 0) { + /* initialize viewport to window size */ + _mesa_Viewport( 0, 0, drawBuffer->width, drawBuffer->height ); + c->gl_ctx->Scissor.Width = drawBuffer->width; + c->gl_ctx->Scissor.Height = drawBuffer->height; + } + + if (c->xm_visual->mesa_visual.rgbMode) { + /* + * Must recompute and set these pixel values because colormap + * can be different for different windows. + */ + c->clearpixel = xmesa_color_to_pixel( c, + c->clearcolor[0], + c->clearcolor[1], + c->clearcolor[2], + c->clearcolor[3], + c->xm_visual->undithered_pf); + XMesaSetForeground(c->display, c->xm_buffer->cleargc, c->clearpixel); + } + + /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */ + c->xm_buffer->wasCurrent = GL_TRUE; + } + else { + /* Detach */ + _mesa_make_current2( NULL, NULL, NULL ); + } + return GL_TRUE; +} + + +/* + * Unbind the context c from its buffer. + */ +GLboolean XMesaUnbindContext( XMesaContext c ) +{ + /* A no-op for XFree86 integration purposes */ + return GL_TRUE; +} + + +XMesaContext XMesaGetCurrentContext( void ) +{ + GET_CURRENT_CONTEXT(ctx); + if (ctx) { + XMesaContext xmesa = (XMesaContext) ctx->DriverCtx; + return xmesa; + } + else { + return 0; + } +} + + +XMesaBuffer XMesaGetCurrentBuffer( void ) +{ + GET_CURRENT_CONTEXT(ctx); + if (ctx) { + XMesaContext xmesa = (XMesaContext) ctx->DriverCtx; + return xmesa->xm_buffer; + } + else { + return 0; + } +} + + +/* New in Mesa 3.1 */ +XMesaBuffer XMesaGetCurrentReadBuffer( void ) +{ + GET_CURRENT_CONTEXT(ctx); + if (ctx) { + XMesaContext xmesa = (XMesaContext) ctx->DriverCtx; + return xmesa->xm_buffer; + } + else { + return 0; + } +} + + +GLboolean XMesaForceCurrent(XMesaContext c) +{ + if (c) { + if (c->gl_ctx != _mesa_get_current_context()) { + _mesa_make_current(c->gl_ctx, &c->xm_buffer->mesa_buffer); + } + } + else { + _mesa_make_current(NULL, NULL); + } + return GL_TRUE; +} + + +GLboolean XMesaLoseCurrent(XMesaContext c) +{ + (void) c; + _mesa_make_current(NULL, NULL); + return GL_TRUE; +} + + +/* + * Switch 3Dfx support hack between window and full-screen mode. + */ +GLboolean XMesaSetFXmode( GLint mode ) +{ +#ifdef FX + const char *fx = getenv("MESA_GLX_FX"); + if (fx && fx[0] != 'd') { + GET_CURRENT_CONTEXT(ctx); + GrHwConfiguration hw; + if (!FX_grSstQueryHardware(&hw)) { + /*fprintf(stderr, "!grSstQueryHardware\n");*/ + return GL_FALSE; + } + if (hw.num_sst < 1) { + /*fprintf(stderr, "hw.num_sst < 1\n");*/ + return GL_FALSE; + } + if (ctx) { + XMesaContext xmesa = (XMesaContext) ctx->DriverCtx; + if (mode == XMESA_FX_WINDOW) { + if (xmesa->xm_buffer->FXisHackUsable) { + FX_grSstControl(GR_CONTROL_DEACTIVATE); + xmesa->xm_buffer->FXwindowHack = GL_TRUE; + return GL_TRUE; + } + } + else if (mode == XMESA_FX_FULLSCREEN) { + FX_grSstControl(GR_CONTROL_ACTIVATE); + xmesa->xm_buffer->FXwindowHack = GL_FALSE; + return GL_TRUE; + } + else { + /* Error: Bad mode value */ + } + } + } + /*fprintf(stderr, "fallthrough\n");*/ +#else + (void) mode; +#endif + return GL_FALSE; +} + + + +#ifdef FX +/* + * Read image from VooDoo frame buffer into X/Mesa's back XImage. + */ +static void FXgetImage( XMesaBuffer b ) +{ + GET_CURRENT_CONTEXT(ctx); + static unsigned short pixbuf[MAX_WIDTH]; + GLuint x, y; + int xpos, ypos; + XMesaWindow root; + unsigned int bw, depth, width, height; + XMesaContext xmesa = (XMesaContext) ctx->DriverCtx; + +#ifdef XFree86Server + x = b->frontbuffer->x; + y = b->frontbuffer->y; + width = b->frontbuffer->width; + height = b->frontbuffer->height; + depth = b->frontbuffer->depth; +#else + XGetGeometry( b->xm_visual->display, b->frontbuffer, + &root, &xpos, &ypos, &width, &height, &bw, &depth); +#endif + if (b->width != width || b->height != height) { + b->width = MIN2((int)width, b->FXctx->width); + b->height = MIN2((int)height, b->FXctx->height); + if (b->width & 1) + b->width--; /* prevent odd width */ + xmesa_alloc_back_buffer( b ); + } + + grLfbWriteColorFormat(GR_COLORFORMAT_ARGB); + if (b->xm_visual->undithered_pf==PF_5R6G5B) { + /* Special case: 16bpp RGB */ + grLfbReadRegion( GR_BUFFER_FRONTBUFFER, /* src buffer */ + 0, b->FXctx->height - b->height, /*pos*/ + b->width, b->height, /* size */ + b->width * sizeof(GLushort), /* stride */ + b->backimage->data); /* dest buffer */ + } + else if (b->xm_visual->dithered_pf==PF_DITHER + && GET_VISUAL_DEPTH(b->xm_visual)==8) { + /* Special case: 8bpp RGB */ + for (y=0;y<b->height;y++) { + GLubyte *ptr = (GLubyte*) b->backimage->data + + b->backimage->bytes_per_line * y; + XDITHER_SETUP(y); + + /* read row from 3Dfx frame buffer */ + grLfbReadRegion( GR_BUFFER_FRONTBUFFER, + 0, b->FXctx->height-(b->height-y), + b->width, 1, + 0, + pixbuf ); + + /* write to XImage back buffer */ + for (x=0;x<b->width;x++) { + GLubyte r = (pixbuf[x] & 0xf800) >> 8; + GLubyte g = (pixbuf[x] & 0x07e0) >> 3; + GLubyte b = (pixbuf[x] & 0x001f) << 3; + *ptr++ = XDITHER( x, r, g, b); + } + } + } + else { + /* General case: slow! */ + for (y=0;y<b->height;y++) { + /* read row from 3Dfx frame buffer */ + grLfbReadRegion( GR_BUFFER_FRONTBUFFER, + 0, b->FXctx->height-(b->height-y), + b->width, 1, + 0, + pixbuf ); + + /* write to XImage back buffer */ + for (x=0;x<b->width;x++) { + XMesaPutPixel(b->backimage,x,y, + xmesa_color_to_pixel(xmesa, + (pixbuf[x] & 0xf800) >> 8, + (pixbuf[x] & 0x07e0) >> 3, + (pixbuf[x] & 0x001f) << 3, + 0xff, + b->xm_visual->undithered_pf)); + } + } + } + grLfbWriteColorFormat(GR_COLORFORMAT_ABGR); +} +#endif + + +/* + * Copy the back buffer to the front buffer. If there's no back buffer + * this is a no-op. + */ +void XMesaSwapBuffers( XMesaBuffer b ) +{ + GET_CURRENT_CONTEXT(ctx); + + /* If we're swapping the buffer associated with the current context + * we have to flush any pending rendering commands first. + */ + if (ctx && ctx->DrawBuffer == &(b->mesa_buffer)) + _mesa_swapbuffers(ctx); + + if (b->db_state) { +#ifdef FX + if (b->FXctx) { + fxMesaSwapBuffers(); + + if (b->FXwindowHack) + FXgetImage(b); + else + return; + } +#endif + if (b->backimage) { + /* Copy Ximage from host's memory to server's window */ +#if defined(USE_XSHM) && !defined(XFree86Server) + if (b->shm) { + /*_glthread_LOCK_MUTEX(_xmesa_lock);*/ + XShmPutImage( b->xm_visual->display, b->frontbuffer, + b->swapgc, + b->backimage, 0, 0, + 0, 0, b->width, b->height, False ); + /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/ + } + else +#endif + { + /*_glthread_LOCK_MUTEX(_xmesa_lock);*/ + XMesaPutImage( b->xm_visual->display, b->frontbuffer, + b->swapgc, + b->backimage, 0, 0, + 0, 0, b->width, b->height ); + /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/ + } + } + else { + /* Copy pixmap to window on server */ + /*_glthread_LOCK_MUTEX(_xmesa_lock);*/ + XMesaCopyArea( b->xm_visual->display, + b->backpixmap, /* source drawable */ + b->frontbuffer, /* dest. drawable */ + b->swapgc, + 0, 0, b->width, b->height, /* source region */ + 0, 0 /* dest region */ + ); + /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/ + } + } +#if !defined(XFree86Server) + XSync( b->xm_visual->display, False ); +#endif +} + + + +/* + * Copy sub-region of back buffer to front buffer + */ +void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height ) +{ + GET_CURRENT_CONTEXT(ctx); + + /* If we're swapping the buffer associated with the current context + * we have to flush any pending rendering commands first. + */ + if (ctx && ctx->DrawBuffer == &(b->mesa_buffer)) + _mesa_swapbuffers(ctx); + + if (b->db_state) { + int yTop = b->height - y - height; +#ifdef FX + if (b->FXctx) { + fxMesaSwapBuffers(); + if (b->FXwindowHack) + FXgetImage(b); + else + return; + } +#endif + if (b->backimage) { + /* Copy Ximage from host's memory to server's window */ +#if defined(USE_XSHM) && !defined(XFree86Server) + if (b->shm) { + /* XXX assuming width and height aren't too large! */ + XShmPutImage( b->xm_visual->display, b->frontbuffer, + b->swapgc, + b->backimage, x, yTop, + x, yTop, width, height, False ); + /* wait for finished event??? */ + } + else +#endif + { + /* XXX assuming width and height aren't too large! */ + XMesaPutImage( b->xm_visual->display, b->frontbuffer, + b->swapgc, + b->backimage, x, yTop, + x, yTop, width, height ); + } + } + else { + /* Copy pixmap to window on server */ + XMesaCopyArea( b->xm_visual->display, + b->backpixmap, /* source drawable */ + b->frontbuffer, /* dest. drawable */ + b->swapgc, + x, yTop, width, height, /* source region */ + x, yTop /* dest region */ + ); + } + } +} + + +/* + * Return a pointer to the XMesa backbuffer Pixmap or XImage. This function + * is a way to get "under the hood" of X/Mesa so one can manipulate the + * back buffer directly. + * Output: pixmap - pointer to back buffer's Pixmap, or 0 + * ximage - pointer to back buffer's XImage, or NULL + * Return: GL_TRUE = context is double buffered + * GL_FALSE = context is single buffered + */ +GLboolean XMesaGetBackBuffer( XMesaBuffer b, + XMesaPixmap *pixmap, + XMesaImage **ximage ) +{ + if (b->db_state) { + if (pixmap) *pixmap = b->backpixmap; + if (ximage) *ximage = b->backimage; + return GL_TRUE; + } + else { + *pixmap = 0; + *ximage = NULL; + return GL_FALSE; + } +} + + +/* + * Return the depth buffer associated with an XMesaBuffer. + * Input: b - the XMesa buffer handle + * Output: width, height - size of buffer in pixels + * bytesPerValue - bytes per depth value (2 or 4) + * buffer - pointer to depth buffer values + * Return: GL_TRUE or GL_FALSE to indicate success or failure. + */ +GLboolean XMesaGetDepthBuffer( XMesaBuffer b, GLint *width, GLint *height, + GLint *bytesPerValue, void **buffer ) +{ + if (!b->mesa_buffer.DepthBuffer) { + *width = 0; + *height = 0; + *bytesPerValue = 0; + *buffer = 0; + return GL_FALSE; + } + else { + *width = b->mesa_buffer.Width; + *height = b->mesa_buffer.Height; + *bytesPerValue = sizeof(GLdepth); + *buffer = b->mesa_buffer.DepthBuffer; + return GL_TRUE; + } +} + + +void XMesaFlush( XMesaContext c ) +{ + if (c && c->xm_visual) { +#ifdef XFree86Server + /* NOT_NEEDED */ +#else + XSync( c->xm_visual->display, False ); +#endif + } +} + + + +const char *XMesaGetString( XMesaContext c, int name ) +{ + (void) c; + if (name==XMESA_VERSION) { + return "4.0.3"; + } + else if (name==XMESA_EXTENSIONS) { + return ""; + } + else { + return NULL; + } +} + + + +XMesaBuffer XMesaFindBuffer( XMesaDisplay *dpy, XMesaDrawable d ) +{ + XMesaBuffer b; + for (b=XMesaBufferList; b; b=b->Next) { + if (b->frontbuffer==d && b->display==dpy) { + return b; + } + } + return NULL; +} + + + +/* + * Look for XMesaBuffers whose X window has been destroyed. + * Deallocate any such XMesaBuffers. + */ +void XMesaGarbageCollect( void ) +{ + XMesaBuffer b, next; + for (b=XMesaBufferList; b; b=next) { + next = b->Next; + if (b->display && b->frontbuffer && !b->pixmap_flag) { +#ifdef XFree86Server + /* NOT_NEEDED */ +#else + XSync(b->display, False); + if (!window_exists( b->display, b->frontbuffer )) { + /* found a dead window, free the ancillary info */ + XMesaDestroyBuffer( b ); + } +#endif + } + } +} + + +void XMesaReset( void ) +{ + while (XMesaBufferList) + XMesaDestroyBuffer(XMesaBufferList); + + XMesaBufferList = NULL; +} + + +unsigned long XMesaDitherColor( XMesaContext xmesa, GLint x, GLint y, + GLfloat red, GLfloat green, + GLfloat blue, GLfloat alpha ) +{ + GLint r = (GLint) (red * 255.0F); + GLint g = (GLint) (green * 255.0F); + GLint b = (GLint) (blue * 255.0F); + GLint a = (GLint) (alpha * 255.0F); + + switch (xmesa->pixelformat) { + case PF_INDEX: + return 0; + case PF_TRUECOLOR: + { + unsigned long p; + PACK_TRUECOLOR( p, r, g, b ); + return p; + } + case PF_8A8B8G8R: + return PACK_8A8B8G8R( r, g, b, a ); + case PF_8R8G8B: + return PACK_8R8G8B( r, g, b ); + case PF_5R6G5B: + return PACK_5R6G5B( r, g, b ); + case PF_DITHER: + { + DITHER_SETUP; + return DITHER( x, y, r, g, b ); + } + case PF_1BIT: + /* 382 = (3*255)/2 */ + return ((r+g+b) > 382) ^ xmesa->xm_visual->bitFlip; + case PF_HPCR: + return DITHER_HPCR(x, y, r, g, b); + case PF_LOOKUP: + { + LOOKUP_SETUP; + return LOOKUP( r, g, b ); + } + case PF_GRAYSCALE: + return GRAY_RGB( r, g, b ); + case PF_DITHER_5R6G5B: + /* fall through */ + case PF_TRUEDITHER: + { + unsigned long p; + PACK_TRUEDITHER(p, x, y, r, g, b); + return p; + } + default: + _mesa_problem(NULL, "Bad pixel format in XMesaDitherColor"); + } + return 0; +} + + +/* + * This is typically called when the window size changes and we need + * to reallocate the buffer's back/depth/stencil/accum buffers. + */ +void XMesaResizeBuffers( XMesaBuffer b ) +{ + xmesa_resize_buffers( &(b->mesa_buffer) ); + +} + diff --git a/xc/extras/Mesa/src/X/xm_dd.c b/xc/extras/Mesa/src/X/xm_dd.c index 1d01bcaf0..da7f0e383 100644 --- a/xc/extras/Mesa/src/X/xm_dd.c +++ b/xc/extras/Mesa/src/X/xm_dd.c @@ -60,19 +60,20 @@ get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height ) */ const XMesaBuffer xmBuffer = (XMesaBuffer) buffer; unsigned int winwidth, winheight; -#ifndef XFree86Server +#ifdef XFree86Server + /* XFree86 GLX renderer */ + winwidth = xmBuffer->frontbuffer->width; + winheight = xmBuffer->frontbuffer->height; +#else Window root; int winx, winy; unsigned int bw, d; _glthread_LOCK_MUTEX(_xmesa_lock); + XSync(xmBuffer->xm_visual->display, 0); /* added for Chromium */ XGetGeometry( xmBuffer->xm_visual->display, xmBuffer->frontbuffer, &root, &winx, &winy, &winwidth, &winheight, &bw, &d ); _glthread_UNLOCK_MUTEX(_xmesa_lock); -#else - /* XFree86 GLX renderer */ - winwidth = xmBuffer->frontbuffer->width; - winheight = xmBuffer->frontbuffer->height; #endif (void)kernel8; /* Muffle compiler */ diff --git a/xc/extras/Mesa/src/X/xm_line.c b/xc/extras/Mesa/src/X/xm_line.c index f231fe279..879bd3c51 100644 --- a/xc/extras/Mesa/src/X/xm_line.c +++ b/xc/extras/Mesa/src/X/xm_line.c @@ -1,9 +1,9 @@ /* * Mesa 3-D graphics library - * Version: 3.5 + * Version: 4.0.3 * - * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2002 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), diff --git a/xc/extras/Mesa/src/swrast/s_blend.c b/xc/extras/Mesa/src/swrast/s_blend.c new file mode 100644 index 000000000..c2024fecd --- /dev/null +++ b/xc/extras/Mesa/src/swrast/s_blend.c @@ -0,0 +1,765 @@ + +/* + * Mesa 3-D graphics library + * Version: 4.0.3 + * + * Copyright (C) 1999-2002 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#include "glheader.h" +#include "context.h" +#include "macros.h" + +#include "s_alphabuf.h" +#include "s_blend.h" +#include "s_context.h" +#include "s_pb.h" +#include "s_span.h" + + +#if defined(USE_MMX_ASM) +#include "X86/mmx.h" +#include "X86/common_x86_asm.h" +#define _BLENDAPI _ASMAPI +#else +#define _BLENDAPI +#endif + + +/* + * Special case for glBlendFunc(GL_ZERO, GL_ONE) + */ +static void _BLENDAPI +blend_noop( GLcontext *ctx, GLuint n, const GLubyte mask[], + GLchan rgba[][4], CONST GLchan dest[][4] ) +{ + GLuint i; + ASSERT(ctx->Color.BlendEquation==GL_FUNC_ADD_EXT); + ASSERT(ctx->Color.BlendSrcRGB==GL_ZERO); + ASSERT(ctx->Color.BlendDstRGB==GL_ONE); + (void) ctx; + + for (i = 0; i < n; i++) { + if (mask[i]) { + rgba[i][RCOMP] = dest[i][RCOMP]; + rgba[i][GCOMP] = dest[i][GCOMP]; + rgba[i][BCOMP] = dest[i][BCOMP]; + rgba[i][ACOMP] = dest[i][ACOMP]; + } + } +} + + +/* + * Special case for glBlendFunc(GL_ONE, GL_ZERO) + */ +static void _BLENDAPI +blend_replace( GLcontext *ctx, GLuint n, const GLubyte mask[], + GLchan rgba[][4], CONST GLchan dest[][4] ) +{ + ASSERT(ctx->Color.BlendEquation==GL_FUNC_ADD_EXT); + ASSERT(ctx->Color.BlendSrcRGB==GL_ONE); + ASSERT(ctx->Color.BlendDstRGB==GL_ZERO); + (void) ctx; + (void) n; + (void) mask; + (void) rgba; + (void) dest; +} + + +/* + * Common transparency blending mode. + */ +static void _BLENDAPI +blend_transparency( GLcontext *ctx, GLuint n, const GLubyte mask[], + GLchan rgba[][4], CONST GLchan dest[][4] ) +{ + GLuint i; + ASSERT(ctx->Color.BlendEquation==GL_FUNC_ADD_EXT); + ASSERT(ctx->Color.BlendSrcRGB==GL_SRC_ALPHA); + ASSERT(ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA); + (void) ctx; + + for (i=0;i<n;i++) { + if (mask[i]) { + const GLint t = rgba[i][ACOMP]; /* t in [0, CHAN_MAX] */ + if (t == 0) { + /* 0% alpha */ + rgba[i][RCOMP] = dest[i][RCOMP]; + rgba[i][GCOMP] = dest[i][GCOMP]; + rgba[i][BCOMP] = dest[i][BCOMP]; + rgba[i][ACOMP] = dest[i][ACOMP]; + } + else if (t == CHAN_MAX) { + /* 100% alpha, no-op */ + } + else { +#if 0 + /* This is pretty close, but Glean complains */ + const GLint s = CHAN_MAX - t; + const GLint r = (rgba[i][RCOMP] * t + dest[i][RCOMP] * s + 1) >> 8; + const GLint g = (rgba[i][GCOMP] * t + dest[i][GCOMP] * s + 1) >> 8; + const GLint b = (rgba[i][BCOMP] * t + dest[i][BCOMP] * s + 1) >> 8; + const GLint a = (rgba[i][ACOMP] * t + dest[i][ACOMP] * s + 1) >> 8; +#elif 0 + /* This is slower but satisfies Glean */ + const GLint s = CHAN_MAX - t; + const GLint r = (rgba[i][RCOMP] * t + dest[i][RCOMP] * s) / 255; + const GLint g = (rgba[i][GCOMP] * t + dest[i][GCOMP] * s) / 255; + const GLint b = (rgba[i][BCOMP] * t + dest[i][BCOMP] * s) / 255; + const GLint a = (rgba[i][ACOMP] * t + dest[i][ACOMP] * s) / 255; +#else +#if CHAN_BITS == 8 + /* This satisfies Glean and should be reasonably fast */ + /* Contributed by Nathan Hand */ +#define DIV255(X) (((X) << 8) + (X) + 256) >> 16 + const GLint s = CHAN_MAX - t; + const GLint r = DIV255(rgba[i][RCOMP] * t + dest[i][RCOMP] * s); + const GLint g = DIV255(rgba[i][GCOMP] * t + dest[i][GCOMP] * s); + const GLint b = DIV255(rgba[i][BCOMP] * t + dest[i][BCOMP] * s); + const GLint a = DIV255(rgba[i][ACOMP] * t + dest[i][ACOMP] * s); +#undef DIV255 +#elif CHAN_BITS == 16 + const GLfloat tt = (GLfloat) t / CHAN_MAXF; + const GLfloat s = 1.0 - tt; + const GLint r = (GLint) (rgba[i][RCOMP] * tt + dest[i][RCOMP] * s); + const GLint g = (GLint) (rgba[i][GCOMP] * tt + dest[i][GCOMP] * s); + const GLint b = (GLint) (rgba[i][BCOMP] * tt + dest[i][BCOMP] * s); + const GLint a = (GLint) (rgba[i][ACOMP] * tt + dest[i][ACOMP] * s); +#else /* CHAN_BITS == 32 */ + const GLfloat tt = (GLfloat) t / CHAN_MAXF; + const GLfloat s = 1.0 - tt; + const GLfloat r = rgba[i][RCOMP] * tt + dest[i][RCOMP] * s; + const GLfloat g = rgba[i][GCOMP] * tt + dest[i][GCOMP] * s; + const GLfloat b = rgba[i][BCOMP] * tt + dest[i][BCOMP] * s; + const GLfloat a = rgba[i][ACOMP] * tt + dest[i][ACOMP] * s; +#endif +#endif + ASSERT(r <= CHAN_MAX); + ASSERT(g <= CHAN_MAX); + ASSERT(b <= CHAN_MAX); + ASSERT(a <= CHAN_MAX); + rgba[i][RCOMP] = (GLchan) r; + rgba[i][GCOMP] = (GLchan) g; + rgba[i][BCOMP] = (GLchan) b; + rgba[i][ACOMP] = (GLchan) a; + } + } + } +} + + + +/* + * Add src and dest. + */ +static void _BLENDAPI +blend_add( GLcontext *ctx, GLuint n, const GLubyte mask[], + GLchan rgba[][4], CONST GLchan dest[][4] ) +{ + GLuint i; + ASSERT(ctx->Color.BlendEquation==GL_FUNC_ADD_EXT); + ASSERT(ctx->Color.BlendSrcRGB==GL_ONE); + ASSERT(ctx->Color.BlendDstRGB==GL_ONE); + (void) ctx; + + for (i=0;i<n;i++) { + if (mask[i]) { +#if CHAN_TYPE == GL_FLOAT + GLfloat r = rgba[i][RCOMP] + dest[i][RCOMP]; + GLfloat g = rgba[i][GCOMP] + dest[i][GCOMP]; + GLfloat b = rgba[i][BCOMP] + dest[i][BCOMP]; + GLfloat a = rgba[i][ACOMP] + dest[i][ACOMP]; +#else + GLint r = rgba[i][RCOMP] + dest[i][RCOMP]; + GLint g = rgba[i][GCOMP] + dest[i][GCOMP]; + GLint b = rgba[i][BCOMP] + dest[i][BCOMP]; + GLint a = rgba[i][ACOMP] + dest[i][ACOMP]; +#endif + rgba[i][RCOMP] = (GLchan) MIN2( r, CHAN_MAX ); + rgba[i][GCOMP] = (GLchan) MIN2( g, CHAN_MAX ); + rgba[i][BCOMP] = (GLchan) MIN2( b, CHAN_MAX ); + rgba[i][ACOMP] = (GLchan) MIN2( a, CHAN_MAX ); + } + } +} + + + +/* + * Blend min function (for GL_EXT_blend_minmax) + */ +static void _BLENDAPI +blend_min( GLcontext *ctx, GLuint n, const GLubyte mask[], + GLchan rgba[][4], CONST GLchan dest[][4] ) +{ + GLuint i; + ASSERT(ctx->Color.BlendEquation==GL_MIN_EXT); + (void) ctx; + + for (i=0;i<n;i++) { + if (mask[i]) { + rgba[i][RCOMP] = (GLchan) MIN2( rgba[i][RCOMP], dest[i][RCOMP] ); + rgba[i][GCOMP] = (GLchan) MIN2( rgba[i][GCOMP], dest[i][GCOMP] ); + rgba[i][BCOMP] = (GLchan) MIN2( rgba[i][BCOMP], dest[i][BCOMP] ); + rgba[i][ACOMP] = (GLchan) MIN2( rgba[i][ACOMP], dest[i][ACOMP] ); + } + } +} + + + +/* + * Blend max function (for GL_EXT_blend_minmax) + */ +static void _BLENDAPI +blend_max( GLcontext *ctx, GLuint n, const GLubyte mask[], + GLchan rgba[][4], CONST GLchan dest[][4] ) +{ + GLuint i; + ASSERT(ctx->Color.BlendEquation==GL_MAX_EXT); + (void) ctx; + + for (i=0;i<n;i++) { + if (mask[i]) { + rgba[i][RCOMP] = (GLchan) MAX2( rgba[i][RCOMP], dest[i][RCOMP] ); + rgba[i][GCOMP] = (GLchan) MAX2( rgba[i][GCOMP], dest[i][GCOMP] ); + rgba[i][BCOMP] = (GLchan) MAX2( rgba[i][BCOMP], dest[i][BCOMP] ); + rgba[i][ACOMP] = (GLchan) MAX2( rgba[i][ACOMP], dest[i][ACOMP] ); + } + } +} + + + +/* + * Modulate: result = src * dest + */ +static void _BLENDAPI +blend_modulate( GLcontext *ctx, GLuint n, const GLubyte mask[], + GLchan rgba[][4], CONST GLchan dest[][4] ) +{ + GLuint i; + (void) ctx; + + for (i=0;i<n;i++) { + if (mask[i]) { +#if CHAN_TYPE == GL_FLOAT + rgba[i][RCOMP] = rgba[i][RCOMP] * dest[i][RCOMP]; + rgba[i][GCOMP] = rgba[i][GCOMP] * dest[i][GCOMP]; + rgba[i][BCOMP] = rgba[i][BCOMP] * dest[i][BCOMP]; + rgba[i][ACOMP] = rgba[i][ACOMP] * dest[i][ACOMP]; +#else + GLint r = (rgba[i][RCOMP] * dest[i][RCOMP]) >> 8; + GLint g = (rgba[i][GCOMP] * dest[i][GCOMP]) >> 8; + GLint b = (rgba[i][BCOMP] * dest[i][BCOMP]) >> 8; + GLint a = (rgba[i][ACOMP] * dest[i][ACOMP]) >> 8; + rgba[i][RCOMP] = (GLchan) r; + rgba[i][GCOMP] = (GLchan) g; + rgba[i][BCOMP] = (GLchan) b; + rgba[i][ACOMP] = (GLchan) a; +#endif + } + } +} + + + +/* + * General case blend pixels. + * Input: n - number of pixels + * mask - the usual write mask + * In/Out: rgba - the incoming and modified pixels + * Input: dest - the pixels from the dest color buffer + */ +static void _BLENDAPI +blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[], + GLchan rgba[][4], CONST GLchan dest[][4] ) +{ + GLfloat rscale = 1.0F / CHAN_MAXF; + GLfloat gscale = 1.0F / CHAN_MAXF; + GLfloat bscale = 1.0F / CHAN_MAXF; + GLfloat ascale = 1.0F / CHAN_MAXF; + GLuint i; + + for (i=0;i<n;i++) { + if (mask[i]) { +#if CHAN_TYPE == GL_FLOAT + GLfloat Rs, Gs, Bs, As; /* Source colors */ + GLfloat Rd, Gd, Bd, Ad; /* Dest colors */ +#else + GLint Rs, Gs, Bs, As; /* Source colors */ + GLint Rd, Gd, Bd, Ad; /* Dest colors */ +#endif + GLfloat sR, sG, sB, sA; /* Source scaling */ + GLfloat dR, dG, dB, dA; /* Dest scaling */ + GLfloat r, g, b, a; + + /* Source Color */ + Rs = rgba[i][RCOMP]; + Gs = rgba[i][GCOMP]; + Bs = rgba[i][BCOMP]; + As = rgba[i][ACOMP]; + + /* Frame buffer color */ + Rd = dest[i][RCOMP]; + Gd = dest[i][GCOMP]; + Bd = dest[i][BCOMP]; + Ad = dest[i][ACOMP]; + + /* Source RGB factor */ + switch (ctx->Color.BlendSrcRGB) { + case GL_ZERO: + sR = sG = sB = 0.0F; + break; + case GL_ONE: + sR = sG = sB = 1.0F; + break; + case GL_DST_COLOR: + sR = (GLfloat) Rd * rscale; + sG = (GLfloat) Gd * gscale; + sB = (GLfloat) Bd * bscale; + break; + case GL_ONE_MINUS_DST_COLOR: + sR = 1.0F - (GLfloat) Rd * rscale; + sG = 1.0F - (GLfloat) Gd * gscale; + sB = 1.0F - (GLfloat) Bd * bscale; + break; + case GL_SRC_ALPHA: + sR = sG = sB = (GLfloat) As * ascale; + break; + case GL_ONE_MINUS_SRC_ALPHA: + sR = sG = sB = (GLfloat) 1.0F - (GLfloat) As * ascale; + break; + case GL_DST_ALPHA: + sR = sG = sB = (GLfloat) Ad * ascale; + break; + case GL_ONE_MINUS_DST_ALPHA: + sR = sG = sB = 1.0F - (GLfloat) Ad * ascale; + break; + case GL_SRC_ALPHA_SATURATE: + if (As < CHAN_MAX - Ad) { + sR = sG = sB = (GLfloat) As * ascale; + } + else { + sR = sG = sB = 1.0F - (GLfloat) Ad * ascale; + } + break; + case GL_CONSTANT_COLOR: + sR = ctx->Color.BlendColor[0]; + sG = ctx->Color.BlendColor[1]; + sB = ctx->Color.BlendColor[2]; + break; + case GL_ONE_MINUS_CONSTANT_COLOR: + sR = 1.0F - ctx->Color.BlendColor[0]; + sG = 1.0F - ctx->Color.BlendColor[1]; + sB = 1.0F - ctx->Color.BlendColor[2]; + break; + case GL_CONSTANT_ALPHA: + sR = sG = sB = ctx->Color.BlendColor[3]; + break; + case GL_ONE_MINUS_CONSTANT_ALPHA: + sR = sG = sB = 1.0F - ctx->Color.BlendColor[3]; + break; + case GL_SRC_COLOR: /* GL_NV_blend_square */ + sR = (GLfloat) Rs * rscale; + sG = (GLfloat) Gs * gscale; + sB = (GLfloat) Bs * bscale; + break; + case GL_ONE_MINUS_SRC_COLOR: /* GL_NV_blend_square */ + sR = 1.0F - (GLfloat) Rs * rscale; + sG = 1.0F - (GLfloat) Gs * gscale; + sB = 1.0F - (GLfloat) Bs * bscale; + break; + default: + /* this should never happen */ + _mesa_problem(ctx, "Bad blend source RGB factor in do_blend"); + return; + } + + /* Source Alpha factor */ + switch (ctx->Color.BlendSrcA) { + case GL_ZERO: + sA = 0.0F; + break; + case GL_ONE: + sA = 1.0F; + break; + case GL_DST_COLOR: + sA = (GLfloat) Ad * ascale; + break; + case GL_ONE_MINUS_DST_COLOR: + sA = 1.0F - (GLfloat) Ad * ascale; + break; + case GL_SRC_ALPHA: + sA = (GLfloat) As * ascale; + break; + case GL_ONE_MINUS_SRC_ALPHA: + sA = (GLfloat) 1.0F - (GLfloat) As * ascale; + break; + case GL_DST_ALPHA: + sA =(GLfloat) Ad * ascale; + break; + case GL_ONE_MINUS_DST_ALPHA: + sA = 1.0F - (GLfloat) Ad * ascale; + break; + case GL_SRC_ALPHA_SATURATE: + sA = 1.0; + break; + case GL_CONSTANT_COLOR: + sA = ctx->Color.BlendColor[3]; + break; + case GL_ONE_MINUS_CONSTANT_COLOR: + sA = 1.0F - ctx->Color.BlendColor[3]; + break; + case GL_CONSTANT_ALPHA: + sA = ctx->Color.BlendColor[3]; + break; + case GL_ONE_MINUS_CONSTANT_ALPHA: + sA = 1.0F - ctx->Color.BlendColor[3]; + break; + case GL_SRC_COLOR: /* GL_NV_blend_square */ + sA = (GLfloat) As * ascale; + break; + case GL_ONE_MINUS_SRC_COLOR: /* GL_NV_blend_square */ + sA = 1.0F - (GLfloat) As * ascale; + break; + default: + /* this should never happen */ + sA = 0.0F; + _mesa_problem(ctx, "Bad blend source A factor in do_blend"); + } + + /* Dest RGB factor */ + switch (ctx->Color.BlendDstRGB) { + case GL_ZERO: + dR = dG = dB = 0.0F; + break; + case GL_ONE: + dR = dG = dB = 1.0F; + break; + case GL_SRC_COLOR: + dR = (GLfloat) Rs * rscale; + dG = (GLfloat) Gs * gscale; + dB = (GLfloat) Bs * bscale; + break; + case GL_ONE_MINUS_SRC_COLOR: + dR = 1.0F - (GLfloat) Rs * rscale; + dG = 1.0F - (GLfloat) Gs * gscale; + dB = 1.0F - (GLfloat) Bs * bscale; + break; + case GL_SRC_ALPHA: + dR = dG = dB = (GLfloat) As * ascale; + break; + case GL_ONE_MINUS_SRC_ALPHA: + dR = dG = dB = (GLfloat) 1.0F - (GLfloat) As * ascale; + break; + case GL_DST_ALPHA: + dR = dG = dB = (GLfloat) Ad * ascale; + break; + case GL_ONE_MINUS_DST_ALPHA: + dR = dG = dB = 1.0F - (GLfloat) Ad * ascale; + break; + case GL_CONSTANT_COLOR: + dR = ctx->Color.BlendColor[0]; + dG = ctx->Color.BlendColor[1]; + dB = ctx->Color.BlendColor[2]; + break; + case GL_ONE_MINUS_CONSTANT_COLOR: + dR = 1.0F - ctx->Color.BlendColor[0]; + dG = 1.0F - ctx->Color.BlendColor[1]; + dB = 1.0F - ctx->Color.BlendColor[2]; + break; + case GL_CONSTANT_ALPHA: + dR = dG = dB = ctx->Color.BlendColor[3]; + break; + case GL_ONE_MINUS_CONSTANT_ALPHA: + dR = dG = dB = 1.0F - ctx->Color.BlendColor[3]; + break; + case GL_DST_COLOR: /* GL_NV_blend_square */ + dR = (GLfloat) Rd * rscale; + dG = (GLfloat) Gd * gscale; + dB = (GLfloat) Bd * bscale; + break; + case GL_ONE_MINUS_DST_COLOR: /* GL_NV_blend_square */ + dR = 1.0F - (GLfloat) Rd * rscale; + dG = 1.0F - (GLfloat) Gd * gscale; + dB = 1.0F - (GLfloat) Bd * bscale; + break; + default: + /* this should never happen */ + dR = dG = dB = 0.0F; + _mesa_problem(ctx, "Bad blend dest RGB factor in do_blend"); + } + + /* Dest Alpha factor */ + switch (ctx->Color.BlendDstA) { + case GL_ZERO: + dA = 0.0F; + break; + case GL_ONE: + dA = 1.0F; + break; + case GL_SRC_COLOR: + dA = (GLfloat) As * ascale; + break; + case GL_ONE_MINUS_SRC_COLOR: + dA = 1.0F - (GLfloat) As * ascale; + break; + case GL_SRC_ALPHA: + dA = (GLfloat) As * ascale; + break; + case GL_ONE_MINUS_SRC_ALPHA: + dA = (GLfloat) 1.0F - (GLfloat) As * ascale; + break; + case GL_DST_ALPHA: + dA = (GLfloat) Ad * ascale; + break; + case GL_ONE_MINUS_DST_ALPHA: + dA = 1.0F - (GLfloat) Ad * ascale; + break; + case GL_CONSTANT_COLOR: + dA = ctx->Color.BlendColor[3]; + break; + case GL_ONE_MINUS_CONSTANT_COLOR: + dA = 1.0F - ctx->Color.BlendColor[3]; + break; + case GL_CONSTANT_ALPHA: + dA = ctx->Color.BlendColor[3]; + break; + case GL_ONE_MINUS_CONSTANT_ALPHA: + dA = 1.0F - ctx->Color.BlendColor[3]; + break; + case GL_DST_COLOR: /* GL_NV_blend_square */ + dA = (GLfloat) Ad * ascale; + break; + case GL_ONE_MINUS_DST_COLOR: /* GL_NV_blend_square */ + dA = 1.0F - (GLfloat) Ad * ascale; + break; + default: + /* this should never happen */ + dA = 0.0F; + _mesa_problem(ctx, "Bad blend dest A factor in do_blend"); + return; + } + + /* Due to round-off problems we have to clamp against zero. */ + /* Optimization: we don't have to do this for all src & dst factors */ + if (dA < 0.0F) dA = 0.0F; + if (dR < 0.0F) dR = 0.0F; + if (dG < 0.0F) dG = 0.0F; + if (dB < 0.0F) dB = 0.0F; + if (sA < 0.0F) sA = 0.0F; + if (sR < 0.0F) sR = 0.0F; + if (sG < 0.0F) sG = 0.0F; + if (sB < 0.0F) sB = 0.0F; + + ASSERT( sR <= 1.0 ); + ASSERT( sG <= 1.0 ); + ASSERT( sB <= 1.0 ); + ASSERT( sA <= 1.0 ); + ASSERT( dR <= 1.0 ); + ASSERT( dG <= 1.0 ); + ASSERT( dB <= 1.0 ); + ASSERT( dA <= 1.0 ); + + /* compute blended color */ +#if CHAN_TYPE == GL_FLOAT + if (ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) { + r = Rs * sR + Rd * dR; + g = Gs * sG + Gd * dG; + b = Bs * sB + Bd * dB; + a = As * sA + Ad * dA; + } + else if (ctx->Color.BlendEquation==GL_FUNC_SUBTRACT_EXT) { + r = Rs * sR - Rd * dR; + g = Gs * sG - Gd * dG; + b = Bs * sB - Bd * dB; + a = As * sA - Ad * dA; + } + else if (ctx->Color.BlendEquation==GL_FUNC_REVERSE_SUBTRACT_EXT) { + r = Rd * dR - Rs * sR; + g = Gd * dG - Gs * sG; + b = Bd * dB - Bs * sB; + a = Ad * dA - As * sA; + } + else { + /* should never get here */ + r = g = b = a = 0.0F; /* silence uninitialized var warning */ + _mesa_problem(ctx, "unexpected BlendEquation in blend_general()"); + } + + /* final clamping */ + rgba[i][RCOMP] = CLAMP( r, 0.0F, CHAN_MAXF ); + rgba[i][GCOMP] = CLAMP( g, 0.0F, CHAN_MAXF ); + rgba[i][BCOMP] = CLAMP( b, 0.0F, CHAN_MAXF ); + rgba[i][ACOMP] = CLAMP( a, 0.0F, CHAN_MAXF ); +#else + if (ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) { + r = Rs * sR + Rd * dR + 0.5F; + g = Gs * sG + Gd * dG + 0.5F; + b = Bs * sB + Bd * dB + 0.5F; + a = As * sA + Ad * dA + 0.5F; + } + else if (ctx->Color.BlendEquation==GL_FUNC_SUBTRACT_EXT) { + r = Rs * sR - Rd * dR + 0.5F; + g = Gs * sG - Gd * dG + 0.5F; + b = Bs * sB - Bd * dB + 0.5F; + a = As * sA - Ad * dA + 0.5F; + } + else if (ctx->Color.BlendEquation==GL_FUNC_REVERSE_SUBTRACT_EXT) { + r = Rd * dR - Rs * sR + 0.5F; + g = Gd * dG - Gs * sG + 0.5F; + b = Bd * dB - Bs * sB + 0.5F; + a = Ad * dA - As * sA + 0.5F; + } + else { + /* should never get here */ + r = g = b = a = 0.0F; /* silence uninitialized var warning */ + _mesa_problem(ctx, "unexpected BlendEquation in blend_general()"); + } + + /* final clamping */ + rgba[i][RCOMP] = (GLchan) (GLint) CLAMP( r, 0.0F, CHAN_MAXF ); + rgba[i][GCOMP] = (GLchan) (GLint) CLAMP( g, 0.0F, CHAN_MAXF ); + rgba[i][BCOMP] = (GLchan) (GLint) CLAMP( b, 0.0F, CHAN_MAXF ); + rgba[i][ACOMP] = (GLchan) (GLint) CLAMP( a, 0.0F, CHAN_MAXF ); +#endif + } + } +} + + + + + +/* + * Analyze current blending parameters to pick fastest blending function. + * Result: the ctx->Color.BlendFunc pointer is updated. + */ +void _swrast_choose_blend_func( GLcontext *ctx ) +{ + const GLenum eq = ctx->Color.BlendEquation; + const GLenum srcRGB = ctx->Color.BlendSrcRGB; + const GLenum dstRGB = ctx->Color.BlendDstRGB; + const GLenum srcA = ctx->Color.BlendSrcA; + const GLenum dstA = ctx->Color.BlendDstA; + + if (srcRGB != srcA || dstRGB != dstA) { + SWRAST_CONTEXT(ctx)->BlendFunc = blend_general; + } + else if (eq==GL_FUNC_ADD_EXT && srcRGB==GL_SRC_ALPHA + && dstRGB==GL_ONE_MINUS_SRC_ALPHA) { +#if defined(USE_MMX_ASM) + if ( cpu_has_mmx ) { + SWRAST_CONTEXT(ctx)->BlendFunc = _mesa_mmx_blend_transparency; + } + else +#endif + SWRAST_CONTEXT(ctx)->BlendFunc = blend_transparency; + } + else if (eq==GL_FUNC_ADD_EXT && srcRGB==GL_ONE && dstRGB==GL_ONE) { + SWRAST_CONTEXT(ctx)->BlendFunc = blend_add; + } + else if (((eq==GL_FUNC_ADD_EXT || eq==GL_FUNC_REVERSE_SUBTRACT_EXT) + && (srcRGB==GL_ZERO && dstRGB==GL_SRC_COLOR)) + || + ((eq==GL_FUNC_ADD_EXT || eq==GL_FUNC_SUBTRACT_EXT) + && (srcRGB==GL_DST_COLOR && dstRGB==GL_ZERO))) { + SWRAST_CONTEXT(ctx)->BlendFunc = blend_modulate; + } + else if (eq==GL_MIN_EXT) { + SWRAST_CONTEXT(ctx)->BlendFunc = blend_min; + } + else if (eq==GL_MAX_EXT) { + SWRAST_CONTEXT(ctx)->BlendFunc = blend_max; + } + else if (eq==GL_FUNC_ADD_EXT && srcRGB == GL_ZERO && dstRGB == GL_ONE) { + SWRAST_CONTEXT(ctx)->BlendFunc = blend_noop; + } + else if (eq==GL_FUNC_ADD_EXT && srcRGB == GL_ONE && dstRGB == GL_ZERO) { + SWRAST_CONTEXT(ctx)->BlendFunc = blend_replace; + } + else { + SWRAST_CONTEXT(ctx)->BlendFunc = blend_general; + } +} + + + +/* + * Apply the blending operator to a span of pixels. + * Input: n - number of pixels in span + * x, y - location of leftmost pixel in span in window coords. + * mask - boolean mask indicating which pixels to blend. + * In/Out: rgba - pixel values + */ +void +_mesa_blend_span( GLcontext *ctx, GLuint n, GLint x, GLint y, + GLchan rgba[][4], const GLubyte mask[] ) +{ + GLchan dest[MAX_WIDTH][4]; + + /* Check if device driver can do the work */ + if (ctx->Color.BlendEquation==GL_LOGIC_OP && + !ctx->Color.ColorLogicOpEnabled) { + return; + } + + /* Read span of current frame buffer pixels */ + _mesa_read_rgba_span( ctx, ctx->DrawBuffer, n, x, y, dest ); + + SWRAST_CONTEXT(ctx)->BlendFunc( ctx, n, mask, rgba, + (const GLchan (*)[4]) dest ); +} + + + +/* + * Apply the blending operator to an array of pixels. + * Input: n - number of pixels in span + * x, y - array of pixel locations + * mask - boolean mask indicating which pixels to blend. + * In/Out: rgba - pixel values + */ +void +_mesa_blend_pixels( GLcontext *ctx, + GLuint n, const GLint x[], const GLint y[], + GLchan rgba[][4], const GLubyte mask[] ) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + GLchan dest[PB_SIZE][4]; + + /* Check if device driver can do the work */ + if (ctx->Color.BlendEquation==GL_LOGIC_OP && + !ctx->Color.ColorLogicOpEnabled) { + return; + } + + /* Read pixels from current color buffer */ + (*swrast->Driver.ReadRGBAPixels)( ctx, n, x, y, dest, mask ); + if (swrast->_RasterMask & ALPHABUF_BIT) { + _mesa_read_alpha_pixels( ctx, n, x, y, dest, mask ); + } + + swrast->BlendFunc( ctx, n, mask, rgba, (const GLchan (*)[4])dest ); +} diff --git a/xc/extras/Mesa/src/swrast/s_fog.c b/xc/extras/Mesa/src/swrast/s_fog.c new file mode 100644 index 000000000..5070dddea --- /dev/null +++ b/xc/extras/Mesa/src/swrast/s_fog.c @@ -0,0 +1,302 @@ + +/* + * Mesa 3-D graphics library + * Version: 4.0.3 + * + * Copyright (C) 1999-2002 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#include "glheader.h" +#include "colormac.h" +#include "context.h" +#include "macros.h" +#include "mmath.h" + +#include "s_context.h" +#include "s_fog.h" +#include "s_pb.h" + + + + +/* + * Used to convert current raster distance to a fog factor in [0,1]. + */ +GLfloat +_mesa_z_to_fogfactor(GLcontext *ctx, GLfloat z) +{ + GLfloat d, f; + + switch (ctx->Fog.Mode) { + case GL_LINEAR: + if (ctx->Fog.Start == ctx->Fog.End) + d = 1.0F; + else + d = 1.0F / (ctx->Fog.End - ctx->Fog.Start); + f = (ctx->Fog.End - z) * d; + return CLAMP(f, 0.0F, 1.0F); + case GL_EXP: + d = ctx->Fog.Density; + f = (GLfloat) exp(-d * z); + return f; + case GL_EXP2: + d = ctx->Fog.Density; + f = (GLfloat) exp(-(d * d * z * z)); + return f; + default: + _mesa_problem(ctx, "Bad fog mode in make_fog_coord"); + return 0.0; + } +} + + + +/* + * Apply fog to an array of RGBA pixels. + * Input: n - number of pixels + * fog - array of fog factors in [0,1] + * red, green, blue, alpha - pixel colors + * Output: red, green, blue, alpha - fogged pixel colors + */ +void +_mesa_fog_rgba_pixels( const GLcontext *ctx, + GLuint n, + const GLfloat fog[], + GLchan rgba[][4] ) +{ + GLuint i; + GLchan rFog, gFog, bFog; + + UNCLAMPED_FLOAT_TO_CHAN(rFog, ctx->Fog.Color[RCOMP]); + UNCLAMPED_FLOAT_TO_CHAN(gFog, ctx->Fog.Color[GCOMP]); + UNCLAMPED_FLOAT_TO_CHAN(bFog, ctx->Fog.Color[BCOMP]); + + for (i = 0; i < n; i++) { + const GLfloat f = fog[i]; + const GLfloat g = 1.0F - f; + rgba[i][RCOMP] = (GLchan) (f * rgba[i][RCOMP] + g * rFog); + rgba[i][GCOMP] = (GLchan) (f * rgba[i][GCOMP] + g * gFog); + rgba[i][BCOMP] = (GLchan) (f * rgba[i][BCOMP] + g * bFog); + } +} + + + +/* + * Apply fog to an array of color index pixels. + * Input: n - number of pixels + * fog - array of fog factors in [0,1] + * index - pixel color indexes + * Output: index - fogged pixel color indexes + */ +void +_mesa_fog_ci_pixels( const GLcontext *ctx, + GLuint n, const GLfloat fog[], GLuint index[] ) +{ + GLuint idx = (GLuint) ctx->Fog.Index; + GLuint i; + + for (i = 0; i < n; i++) { + const GLfloat f = CLAMP(fog[i], 0.0F, 1.0F); + index[i] = (GLuint) ((GLfloat) index[i] + (1.0F - f) * idx); + } +} + + + +/* + * Calculate fog factors (in [0,1]) from window z values + * Input: n - number of pixels + * z - array of integer depth values + * red, green, blue, alpha - pixel colors + * Output: red, green, blue, alpha - fogged pixel colors + * + * Use lookup table & interpolation? + */ +static void +compute_fog_factors_from_z( const GLcontext *ctx, + GLuint n, + const GLdepth z[], + GLfloat fogFact[] ) +{ + const GLboolean ortho = (ctx->ProjectionMatrix.m[15] != 0.0F); + const GLfloat p10 = ctx->ProjectionMatrix.m[10]; + const GLfloat p14 = ctx->ProjectionMatrix.m[14]; + const GLfloat tz = ctx->Viewport._WindowMap.m[MAT_TZ]; + GLfloat szInv; + GLuint i; + + if (ctx->Viewport._WindowMap.m[MAT_SZ] == 0.0) + szInv = 1.0F; + else + szInv = 1.0F / ctx->Viewport._WindowMap.m[MAT_SZ]; + + /* + * Note: to compute eyeZ from the ndcZ we have to solve the following: + * + * p[10] * eyeZ + p[14] * eyeW + * ndcZ = --------------------------- + * p[11] * eyeZ + p[15] * eyeW + * + * Thus: + * + * p[14] * eyeW - p[15] * eyeW * ndcZ + * eyeZ = ---------------------------------- + * p[11] * ndcZ - p[10] + * + * If we note: + * a) if using an orthographic projection, p[11] = 0 and p[15] = 1. + * b) if using a perspective projection, p[11] = -1 and p[15] = 0. + * c) we assume eyeW = 1 (not always true- glVertex4) + * + * Then we can simplify the calculation of eyeZ quite a bit. We do + * separate calculations for the orthographic and perspective cases below. + * Note that we drop a negative sign or two since they don't matter. + */ + + switch (ctx->Fog.Mode) { + case GL_LINEAR: + { + GLfloat fogEnd = ctx->Fog.End; + GLfloat fogScale; + if (ctx->Fog.Start == ctx->Fog.End) + fogScale = 1.0; + else + fogScale = 1.0F / (ctx->Fog.End - ctx->Fog.Start); + if (ortho) { + for (i=0;i<n;i++) { + GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv; + GLfloat eyez = (ndcz - p14) / p10; + GLfloat f; + if (eyez < 0.0) + eyez = -eyez; + f = (fogEnd - eyez) * fogScale; + fogFact[i] = CLAMP(f, 0.0F, 1.0F); + } + } + else { + /* perspective */ + for (i=0;i<n;i++) { + GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv; + GLfloat eyez = p14 / (ndcz + p10); + GLfloat f; + if (eyez < 0.0) + eyez = -eyez; + f = (fogEnd - eyez) * fogScale; + fogFact[i] = CLAMP(f, 0.0F, 1.0F); + } + } + } + break; + case GL_EXP: + if (ortho) { + for (i=0;i<n;i++) { + GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv; + GLfloat eyez = (ndcz - p14) / p10; + if (eyez < 0.0) + eyez = -eyez; + fogFact[i] = (GLfloat) exp( -ctx->Fog.Density * eyez ); + } + } + else { + /* perspective */ + for (i=0;i<n;i++) { + GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv; + GLfloat eyez = p14 / (ndcz + p10); + if (eyez < 0.0) + eyez = -eyez; + fogFact[i] = (GLfloat) exp( -ctx->Fog.Density * eyez ); + } + } + break; + case GL_EXP2: + { + GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density; + if (ortho) { + for (i=0;i<n;i++) { + GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv; + GLfloat eyez = (ndcz - p14) / p10; + GLfloat tmp = negDensitySquared * eyez * eyez; +#if defined(__alpha__) || defined(__alpha) + /* XXX this underflow check may be needed for other systems*/ + if (tmp < FLT_MIN_10_EXP) + tmp = FLT_MIN_10_EXP; +#endif + fogFact[i] = (GLfloat) exp( tmp ); + } + } + else { + /* perspective */ + for (i=0;i<n;i++) { + GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv; + GLfloat eyez = p14 / (ndcz + p10); + GLfloat tmp = negDensitySquared * eyez * eyez; +#if defined(__alpha__) || defined(__alpha) + /* XXX this underflow check may be needed for other systems*/ + if (tmp < FLT_MIN_10_EXP) + tmp = FLT_MIN_10_EXP; +#endif + fogFact[i] = (GLfloat) exp( tmp ); + } + } + } + break; + default: + _mesa_problem(ctx, "Bad fog mode in compute_fog_factors_from_z"); + return; + } +} + + +/* + * Apply fog to an array of RGBA pixels. + * Input: n - number of pixels + * z - array of integer depth values + * red, green, blue, alpha - pixel colors + * Output: red, green, blue, alpha - fogged pixel colors + */ +void +_mesa_depth_fog_rgba_pixels( const GLcontext *ctx, + GLuint n, const GLdepth z[], GLchan rgba[][4] ) +{ + GLfloat fogFact[PB_SIZE]; + ASSERT(n <= PB_SIZE); + compute_fog_factors_from_z( ctx, n, z, fogFact ); + _mesa_fog_rgba_pixels( ctx, n, fogFact, rgba ); +} + + +/* + * Apply fog to an array of color index pixels. + * Input: n - number of pixels + * z - array of integer depth values + * index - pixel color indexes + * Output: index - fogged pixel color indexes + */ +void +_mesa_depth_fog_ci_pixels( const GLcontext *ctx, + GLuint n, const GLdepth z[], GLuint index[] ) +{ + GLfloat fogFact[PB_SIZE]; + ASSERT(n <= PB_SIZE); + compute_fog_factors_from_z( ctx, n, z, fogFact ); + _mesa_fog_ci_pixels( ctx, n, fogFact, index ); +} diff --git a/xc/extras/Mesa/src/swrast_setup/ss_context.c b/xc/extras/Mesa/src/swrast_setup/ss_context.c index ed99ea3f1..58d85faa1 100644 --- a/xc/extras/Mesa/src/swrast_setup/ss_context.c +++ b/xc/extras/Mesa/src/swrast_setup/ss_context.c @@ -57,7 +57,7 @@ _swsetup_CreateContext( GLcontext *ctx ) if (!swsetup) return GL_FALSE; - swsetup->verts = (SWvertex *) ALIGN_MALLOC( sizeof(SWvertex) * tnl->vb.Size, + swsetup->verts = (SWvertex *) ALIGN_CALLOC( sizeof(SWvertex) * tnl->vb.Size, 32); if (!swsetup->verts) { FREE(swsetup); diff --git a/xc/extras/Mesa/src/tnl_dd/t_dd_vb.c b/xc/extras/Mesa/src/tnl_dd/t_dd_vb.c index 2a48fedb4..3ba8fb3d8 100644 --- a/xc/extras/Mesa/src/tnl_dd/t_dd_vb.c +++ b/xc/extras/Mesa/src/tnl_dd/t_dd_vb.c @@ -197,6 +197,7 @@ void TAG(print_vertex)( GLcontext *ctx, const VERTEX *v ) fprintf(stderr, "(%x) ", format); switch (format) { +#if HAVE_TINY_VERTICES case TINY_VERTEX_FORMAT: fprintf(stderr, "xyz %.4f,%.4f,%.4f rgba %x:%x:%x:%x\n", v->v.x, v->v.y, v->v.z, @@ -205,6 +206,8 @@ void TAG(print_vertex)( GLcontext *ctx, const VERTEX *v ) v->tv.color.blue, v->tv.color.alpha); break; +#endif +#if HAVE_NOTEX_VERTICES case NOTEX_VERTEX_FORMAT: fprintf(stderr, "xyzw %.4f,%.4f,%.4f,%.4f rgba %x:%x:%x:%x spec %x:%x:%x:%x\n", v->v.x, v->v.y, v->v.z, v->v.w, @@ -217,7 +220,8 @@ void TAG(print_vertex)( GLcontext *ctx, const VERTEX *v ) v->v.specular.blue, v->v.specular.alpha); break; - +#endif +#if HAVE_TEX0_VERTICES case TEX0_VERTEX_FORMAT: fprintf(stderr, "xyzw %.4f,%.4f,%.4f,%.4f rgba %x:%x:%x:%x st %.4f,%.4f\n", v->v.x, v->v.y, v->v.z, v->v.w, @@ -228,7 +232,8 @@ void TAG(print_vertex)( GLcontext *ctx, const VERTEX *v ) v->v.u0, v->v.v0); break; - +#endif +#if HAVE_TEX1_VERTICES case TEX1_VERTEX_FORMAT: fprintf(stderr, "xyzw %.4f,%.4f,%.4f,%.4f rgba %x:%x:%x:%x st %.4f,%.4f st %.4f,%.4f\n", v->v.x, v->v.y, v->v.z, v->v.w, @@ -241,7 +246,8 @@ void TAG(print_vertex)( GLcontext *ctx, const VERTEX *v ) v->v.u1, v->v.u2); break; - +#endif +#if HAVE_PTEX_VERTICES case PROJ_TEX1_VERTEX_FORMAT: fprintf(stderr, "xyzw %.4f,%.4f,%.4f,%.4f rgba %x:%x:%x:%x stq %.4f,%.4f,%.4f stq %.4f,%.4f,%.4f\n", v->v.x, v->v.y, v->v.z, v->v.w, @@ -256,7 +262,7 @@ void TAG(print_vertex)( GLcontext *ctx, const VERTEX *v ) v->pv.v1, v->pv.q1); break; - +#endif default: fprintf(stderr, "???\n"); break; diff --git a/xc/extras/Mesa/src/tnl_dd/t_dd_vbtmp.h b/xc/extras/Mesa/src/tnl_dd/t_dd_vbtmp.h index a46bdae74..a199e47ac 100644 --- a/xc/extras/Mesa/src/tnl_dd/t_dd_vbtmp.h +++ b/xc/extras/Mesa/src/tnl_dd/t_dd_vbtmp.h @@ -60,7 +60,10 @@ * unsigned char ub4[4][16]; * } * - + + * VERTEX: hw vertex type as above + * VERTEX_COLOR: hw color struct type in VERTEX + * * DO_XYZW: Emit xyz and maybe w coordinates. * DO_RGBA: Emit color. * DO_SPEC: Emit specular color. @@ -458,11 +461,11 @@ static void TAG(emit)( GLcontext *ctx, GLuint start, GLuint end, *(GLuint *)&v[3] = LE32_TO_CPU(*(GLuint *)col); } else { - GLubyte *b = (GLubyte *)&v[3]; - b[0] = col[0][2]; - b[1] = col[0][1]; - b[2] = col[0][0]; - b[3] = col[0][3]; + VERTEX_COLOR *c = (VERTEX_COLOR *)&v[3]; + c->blue = col[0][2]; + c->green = col[0][1]; + c->red = col[0][0]; + c->alpha = col[0][3]; } STRIDE_4UB( col, col_stride ); } @@ -482,11 +485,11 @@ static void TAG(emit)( GLcontext *ctx, GLuint start, GLuint end, *(GLuint *)&v[3] = LE32_TO_CPU(*(GLuint *)&col[i]); } else { - GLubyte *b = (GLubyte *)&v[3]; - b[0] = col[i][2]; - b[1] = col[i][1]; - b[2] = col[i][0]; - b[3] = col[i][3]; + VERTEX_COLOR *c = (VERTEX_COLOR *)&v[3]; + c->blue = col[i][2]; + c->green = col[i][1]; + c->red = col[i][0]; + c->alpha = col[i][3]; } } /* fprintf(stderr, "vert %d: %.2f %.2f %.2f %x\n", */ @@ -527,11 +530,11 @@ static void TAG(emit)( GLcontext *ctx, GLuint start, GLuint end, *(GLuint *)v = LE32_TO_CPU(*(GLuint *)col[0]); } else { - GLubyte *b = (GLubyte *)v; - b[0] = col[0][2]; - b[1] = col[0][1]; - b[2] = col[0][0]; - b[3] = col[0][3]; + VERTEX_COLOR *c = (VERTEX_COLOR *)v; + c->blue = col[0][2]; + c->green = col[0][1]; + c->red = col[0][0]; + c->alpha = col[0][3]; } STRIDE_4UB( col, col_stride ); } diff --git a/xc/extras/ogl-sample/main/gfx/lib/glu/libnurbs/nurbtess/quicksort.cc b/xc/extras/ogl-sample/main/gfx/lib/glu/libnurbs/nurbtess/quicksort.cc index 5a9890850..12890df35 100755 --- a/xc/extras/ogl-sample/main/gfx/lib/glu/libnurbs/nurbtess/quicksort.cc +++ b/xc/extras/ogl-sample/main/gfx/lib/glu/libnurbs/nurbtess/quicksort.cc @@ -31,10 +31,10 @@ ** published by SGI, but has not been independently verified as being ** compliant with the OpenGL(R) version 1.2.1 Specification. ** -** $Date: 2002/07/15 20:20:59 $ $Revision: 1.2.6.1 $ +** $Date: 2002/08/26 20:02:11 $ $Revision: 1.2.6.2 $ */ /* -** $Header: /home/ajax/dri-backup/xc/xc/extras/ogl-sample/main/gfx/lib/glu/libnurbs/nurbtess/Attic/quicksort.cc,v 1.2.6.1 2002/07/15 20:20:59 keithw Exp $ +** $Header: /home/ajax/dri-backup/xc/xc/extras/ogl-sample/main/gfx/lib/glu/libnurbs/nurbtess/Attic/quicksort.cc,v 1.2.6.2 2002/08/26 20:02:11 keithw Exp $ */ #include <stdlib.h> diff --git a/xc/lib/GL/glx/glxcmds.c b/xc/lib/GL/glx/glxcmds.c index 1bc886cc1..1c95befe9 100644 --- a/xc/lib/GL/glx/glxcmds.c +++ b/xc/lib/GL/glx/glxcmds.c @@ -1018,6 +1018,7 @@ XVisualInfo *GLX_PREFIX(glXChooseVisual)(Display *dpy, int screen, int *attribLi else score += AuxScore(auxBuffers, val); if (transparentPixel) { + __GLX_GCONF(GLX_TRANSPARENT_TYPE_EXT); if (transparentPixelValue != val) continue; if (transparentPixelValue == GLX_TRANSPARENT_TYPE_EXT) { diff --git a/xc/lib/GL/mesa/src/drv/Imakefile b/xc/lib/GL/mesa/src/drv/Imakefile index 146668d99..8c7068088 100644 --- a/xc/lib/GL/mesa/src/drv/Imakefile +++ b/xc/lib/GL/mesa/src/drv/Imakefile @@ -5,7 +5,7 @@ XCOMM $XFree86: xc/lib/GL/mesa/src/drv/Imakefile,v 1.19 2001/03/23 20:56:33 dawe #define IHaveSubdirs #define PassCDebugFlags -SUBDIRS = common r200 radeon +SUBDIRS = common DriDrivers MakeSubdirs($(SUBDIRS)) DependSubdirs($(SUBDIRS)) diff --git a/xc/lib/GL/mesa/src/drv/ffb/ffb_state.c b/xc/lib/GL/mesa/src/drv/ffb/ffb_state.c index 8a77674ab..748ee2358 100644 --- a/xc/lib/GL/mesa/src/drv/ffb/ffb_state.c +++ b/xc/lib/GL/mesa/src/drv/ffb/ffb_state.c @@ -1,7 +1,7 @@ -/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_state.c,v 1.2 2001/05/24 16:34:49 dawes Exp $ +/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_state.c,v 1.1.4.1 2001/05/24 16:35:38 dawes Exp $ * * GLX Hardware Device Driver for Sun Creator/Creator3D - * Copyright (C) 2000 David S. Miller + * Copyright (C) 2000, 2001 David S. Miller * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -25,8 +25,7 @@ * David S. Miller <davem@redhat.com> */ -#include "types.h" -#include "vbrender.h" +#include "mtypes.h" #include <stdio.h> #include <stdlib.h> @@ -43,11 +42,14 @@ #include "ffb_state.h" #include "ffb_lock.h" #include "extensions.h" -#include "vb.h" -#include "dd.h" #include "enums.h" -#include "pipeline.h" -#include "pb.h" + +#include "swrast/swrast.h" +#include "array_cache/acache.h" +#include "tnl/tnl.h" +#include "swrast_setup/swrast_setup.h" + +#include "tnl/t_pipeline.h" #undef STATE_TRACE @@ -57,7 +59,7 @@ static unsigned int ffbComputeAlphaFunc(GLcontext *ctx) #ifdef STATE_TRACE fprintf(stderr, "ffbDDAlphaFunc: func(%s) ref(%02x)\n", - gl_lookup_enum_by_nr(ctx->Color.AlphaFunc), + _mesa_lookup_enum_by_nr(ctx->Color.AlphaFunc), ctx->Color.AlphaRef & 0xff); #endif @@ -80,7 +82,7 @@ static unsigned int ffbComputeAlphaFunc(GLcontext *ctx) return xclip; } -static void ffbDDAlphaFunc(GLcontext *ctx, GLenum func, GLclampf ref) +static void ffbDDAlphaFunc(GLcontext *ctx, GLenum func, GLchan ref) { ffbContextPtr fmesa = FFB_CONTEXT(ctx); @@ -89,23 +91,18 @@ static void ffbDDAlphaFunc(GLcontext *ctx, GLenum func, GLclampf ref) if (fmesa->xclip != xclip) { fmesa->xclip = xclip; - fmesa->state_dirty |= FFB_STATE_XCLIP; - fmesa->state_fifo_ents += 1; + FFB_MAKE_DIRTY(fmesa, FFB_STATE_XCLIP, 1); } } } static void ffbDDBlendEquation(GLcontext *ctx, GLenum mode) { - ffbContextPtr fmesa = FFB_CONTEXT(ctx); #ifdef STATE_TRACE - fprintf(stderr, "ffbDDBlendEquation: mode(%s)\n", gl_lookup_enum_by_nr(mode)); + fprintf(stderr, "ffbDDBlendEquation: mode(%s)\n", _mesa_lookup_enum_by_nr(mode)); #endif - if (mode != GL_FUNC_ADD_EXT) - fmesa->bad_fragment_attrs |= FFB_BADATTR_BLENDEQN; - else - fmesa->bad_fragment_attrs &= ~FFB_BADATTR_BLENDEQN; + FALLBACK( ctx, (mode != GL_FUNC_ADD_EXT), FFB_BADATTR_BLENDEQN); } static void ffbDDBlendFunc(GLcontext *ctx, GLenum sfactor, GLenum dfactor) @@ -115,7 +112,7 @@ static void ffbDDBlendFunc(GLcontext *ctx, GLenum sfactor, GLenum dfactor) #ifdef STATE_TRACE fprintf(stderr, "ffbDDBlendFunc: sfactor(%s) dfactor(%s)\n", - gl_lookup_enum_by_nr(sfactor), gl_lookup_enum_by_nr(dfactor)); + _mesa_lookup_enum_by_nr(sfactor), _mesa_lookup_enum_by_nr(dfactor)); #endif switch (ctx->Color.BlendSrcRGB) { case GL_ZERO: @@ -136,7 +133,7 @@ static void ffbDDBlendFunc(GLcontext *ctx, GLenum sfactor, GLenum dfactor) default: if (ctx->Color.BlendEnabled) - fmesa->bad_fragment_attrs |= FFB_BADATTR_BLENDFUNC; + FALLBACK( ctx, FFB_BADATTR_BLENDFUNC, GL_TRUE ); return; }; @@ -159,7 +156,7 @@ static void ffbDDBlendFunc(GLcontext *ctx, GLenum sfactor, GLenum dfactor) default: if (ctx->Color.BlendEnabled) - fmesa->bad_fragment_attrs |= FFB_BADATTR_BLENDFUNC; + FALLBACK( ctx, FFB_BADATTR_BLENDFUNC, GL_TRUE ); return; }; @@ -173,17 +170,15 @@ static void ffbDDBlendFunc(GLcontext *ctx, GLenum sfactor, GLenum dfactor) * also it would add more state tracking to a lot * of the code in this file. */ - fmesa->bad_fragment_attrs |= FFB_BADATTR_BLENDROP; + FALLBACK(ctx, FFB_BADATTR_BLENDROP, GL_TRUE); return; } - fmesa->bad_fragment_attrs &= ~(FFB_BADATTR_BLENDFUNC | - FFB_BADATTR_BLENDROP); + FALLBACK( ctx, (FFB_BADATTR_BLENDFUNC|FFB_BADATTR_BLENDROP), GL_FALSE ); if (blendc != fmesa->blendc) { fmesa->blendc = blendc; - fmesa->state_dirty |= FFB_STATE_BLEND; - fmesa->state_fifo_ents += 1; + FFB_MAKE_DIRTY(fmesa, FFB_STATE_BLEND, 1); } } @@ -193,10 +188,10 @@ static void ffbDDBlendFuncSeparate(GLcontext *ctx, GLenum sfactorRGB, { #ifdef STATE_TRACE fprintf(stderr, "ffbDDBlendFuncSeparate: sRGB(%s) dRGB(%s) sA(%s) dA(%s)\n", - gl_lookup_enum_by_nr(sfactorRGB), - gl_lookup_enum_by_nr(dfactorRGB), - gl_lookup_enum_by_nr(sfactorA), - gl_lookup_enum_by_nr(dfactorA)); + _mesa_lookup_enum_by_nr(sfactorRGB), + _mesa_lookup_enum_by_nr(dfactorRGB), + _mesa_lookup_enum_by_nr(sfactorA), + _mesa_lookup_enum_by_nr(dfactorA)); #endif ffbDDBlendFunc(ctx, sfactorRGB, dfactorRGB); @@ -209,7 +204,7 @@ static void ffbDDDepthFunc(GLcontext *ctx, GLenum func) #ifdef STATE_TRACE fprintf(stderr, "ffbDDDepthFunc: func(%s)\n", - gl_lookup_enum_by_nr(func)); + _mesa_lookup_enum_by_nr(func)); #endif switch (func) { @@ -248,8 +243,7 @@ static void ffbDDDepthFunc(GLcontext *ctx, GLenum func) cmp = (fmesa->cmp & ~(0xff<<16)) | cmp; if (cmp != fmesa->cmp) { fmesa->cmp = cmp; - fmesa->state_dirty |= FFB_STATE_CMP; - fmesa->state_fifo_ents += 1; + FFB_MAKE_DIRTY(fmesa, FFB_STATE_CMP, 1); } } @@ -277,8 +271,7 @@ static void ffbDDDepthMask(GLcontext *ctx, GLboolean flag) fbc &= ~FFB_FBC_WB_C; } fmesa->fbc = fbc; - fmesa->state_dirty |= FFB_STATE_FBC; - fmesa->state_fifo_ents += 1; + FFB_MAKE_DIRTY(fmesa, FFB_STATE_FBC, 1); } } @@ -322,8 +315,7 @@ static void ffbDDStencilFunc(GLcontext *ctx, GLenum func, GLint ref, GLuint mask fmesa->stencil = stencil; fmesa->stencilctl = stencilctl; fmesa->consty = consty; - fmesa->state_dirty |= FFB_STATE_STENCIL; - fmesa->state_fifo_ents += 6; + FFB_MAKE_DIRTY(fmesa, FFB_STATE_STENCIL, 6); } } @@ -334,8 +326,7 @@ static void ffbDDStencilMask(GLcontext *ctx, GLuint mask) mask &= 0xf; if (fmesa->ypmask != mask) { fmesa->ypmask = mask; - fmesa->state_dirty |= FFB_STATE_YPMASK; - fmesa->state_fifo_ents += 1; + FFB_MAKE_DIRTY(fmesa, FFB_STATE_YPMASK, 1); } } @@ -391,60 +382,115 @@ static void ffbDDStencilOp(GLcontext *ctx, GLenum fail, GLenum zfail, GLenum zpa if (fmesa->stencilctl != stencilctl) { fmesa->stencilctl = stencilctl; - fmesa->state_dirty |= FFB_STATE_STENCIL; - fmesa->state_fifo_ents += 6; + FFB_MAKE_DIRTY(fmesa, FFB_STATE_STENCIL, 6); } } -void ffbDDScissor(GLcontext *ctx, GLint cx, GLint cy, - GLsizei cw, GLsizei ch) +static void ffbCalcViewportRegs(GLcontext *ctx) { ffbContextPtr fmesa = FFB_CONTEXT(ctx); __DRIdrawablePrivate *dPriv = fmesa->driDrawable; - GLint x, y; + GLuint xmin, xmax, ymin, ymax, zmin, zmax; unsigned int vcmin, vcmax; -#ifdef STATE_TRACE - fprintf(stderr, "ffbDDScissor: x(%x) y(%x) w(%x) h(%x)\n", - cx, cy, cw, ch); -#endif - x = cx + dPriv->x; - y = dPriv->y + (cy - ch); - vcmin = ((y & 0xffff) << 16) | (x & 0xffff); - vcmax = ((((y + ch) & 0xffff) << 16) | - (((x + cw) & 0xffff))); + xmin = ctx->Viewport.X + dPriv->x; + xmax = xmin + ctx->Viewport.Width; + ymax = dPriv->y + dPriv->h - ctx->Viewport.Y; + ymin = ymax - ctx->Viewport.Height; + if (ctx->Scissor.Enabled) { + GLuint sc_xmin, sc_xmax, sc_ymin, sc_ymax; + + sc_xmin = ctx->Viewport.X + dPriv->x; + sc_xmax = sc_xmin + ctx->Viewport.Width; + sc_ymax = dPriv->y + dPriv->h - ctx->Viewport.Y; + sc_ymin = sc_ymax - ctx->Viewport.Height; + if (sc_xmin > xmin) + xmin = sc_xmin; + if (sc_xmax < xmax) + xmax = sc_xmax; + if (sc_ymin > ymin) + ymin = sc_ymin; + if (sc_ymax < ymax) + ymax = sc_ymax; + } + zmin = ((GLdouble)ctx->Viewport.Near * 0x0fffffff); + zmax = ((GLdouble)ctx->Viewport.Far * 0x0fffffff); + + vcmin = ((ymin & 0xffff) << 16) | (xmin & 0xffff); + vcmax = ((ymax & 0xffff) << 16) | (xmax & 0xffff); if (fmesa->vclipmin != vcmin || - fmesa->vclipmax != vcmax) { + fmesa->vclipmax != vcmax || + fmesa->vclipzmin != zmin || + fmesa->vclipzmax != zmax) { fmesa->vclipmin = vcmin; fmesa->vclipmax = vcmax; - fmesa->state_dirty |= FFB_STATE_CLIP; - fmesa->state_fifo_ents += 4 + (4 * 2); + fmesa->vclipzmin = zmin; + fmesa->vclipzmax = zmax; + FFB_MAKE_DIRTY(fmesa, FFB_STATE_CLIP, (4 + (4 * 2))); } } -static GLboolean ffbDDSetDrawBuffer(GLcontext *ctx, GLenum buffer) +void ffbCalcViewport(GLcontext *ctx) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + const GLfloat *v = ctx->Viewport._WindowMap.m; + GLfloat *m = fmesa->hw_viewport; + __DRIdrawablePrivate *dPriv = fmesa->driDrawable; + + m[MAT_SX] = v[MAT_SX]; + m[MAT_TX] = v[MAT_TX] + dPriv->x + SUBPIXEL_X; + m[MAT_SY] = - v[MAT_SY]; + m[MAT_TY] = - v[MAT_TY] + dPriv->h + dPriv->y + SUBPIXEL_Y; + m[MAT_SZ] = v[MAT_SZ] * ((GLdouble)1.0 / (GLdouble)0x0fffffff); + m[MAT_TZ] = v[MAT_TZ] * ((GLdouble)1.0 / (GLdouble)0x0fffffff); + + fmesa->depth_scale = ((GLdouble)1.0 / (GLdouble)0x0fffffff); + + ffbCalcViewportRegs(ctx); + + fmesa->setupnewinputs |= VERT_CLIP; +} + +static void ffbDDViewport(GLcontext *ctx, GLint x, GLint y, + GLsizei width, GLsizei height) +{ + ffbCalcViewport(ctx); +} + +static void ffbDDDepthRange(GLcontext *ctx, GLclampd nearval, GLclampd farval) +{ + ffbCalcViewport(ctx); +} + +static void ffbDDScissor(GLcontext *ctx, GLint cx, GLint cy, + GLsizei cw, GLsizei ch) +{ + ffbCalcViewport(ctx); +} + +static void ffbDDSetDrawBuffer(GLcontext *ctx, GLenum buffer) { ffbContextPtr fmesa = FFB_CONTEXT(ctx); unsigned int fbc = fmesa->fbc; #ifdef STATE_TRACE fprintf(stderr, "ffbDDSetDrawBuffer: mode(%s)\n", - gl_lookup_enum_by_nr(buffer)); + _mesa_lookup_enum_by_nr(buffer)); #endif - fbc &= ~(FFB_FBC_WB_AB); + fbc &= ~(FFB_FBC_WB_AB | FFB_FBC_RB_MASK); switch (buffer) { case GL_FRONT_LEFT: if (fmesa->back_buffer == 0) - fbc |= FFB_FBC_WB_B; + fbc |= FFB_FBC_WB_B | FFB_FBC_RB_B; else - fbc |= FFB_FBC_WB_A; + fbc |= FFB_FBC_WB_A | FFB_FBC_RB_A; break; case GL_BACK_LEFT: if (fmesa->back_buffer == 0) - fbc |= FFB_FBC_WB_A; + fbc |= FFB_FBC_WB_A | FFB_FBC_RB_A; else - fbc |= FFB_FBC_WB_B; + fbc |= FFB_FBC_WB_B | FFB_FBC_RB_B; break; case GL_FRONT_AND_BACK: @@ -452,16 +498,13 @@ static GLboolean ffbDDSetDrawBuffer(GLcontext *ctx, GLenum buffer) break; default: - return GL_FALSE; + return; }; if (fbc != fmesa->fbc) { fmesa->fbc = fbc; - fmesa->state_dirty |= FFB_STATE_FBC; - fmesa->state_fifo_ents += 1; + FFB_MAKE_DIRTY(fmesa, FFB_STATE_FBC, 1); } - - return GL_TRUE; } static void ffbDDSetReadBuffer(GLcontext *ctx, GLframebuffer *colorBuffer, @@ -472,7 +515,7 @@ static void ffbDDSetReadBuffer(GLcontext *ctx, GLframebuffer *colorBuffer, #ifdef STATE_TRACE fprintf(stderr, "ffbDDSetReadBuffer: mode(%s)\n", - gl_lookup_enum_by_nr(buffer)); + _mesa_lookup_enum_by_nr(buffer)); #endif fbc &= ~(FFB_FBC_RB_MASK); switch (buffer) { @@ -496,27 +539,17 @@ static void ffbDDSetReadBuffer(GLcontext *ctx, GLframebuffer *colorBuffer, if (fbc != fmesa->fbc) { fmesa->fbc = fbc; - fmesa->state_dirty |= FFB_STATE_FBC; - fmesa->state_fifo_ents += 1; + FFB_MAKE_DIRTY(fmesa, FFB_STATE_FBC, 1); } } -static void ffbDDSetColor(GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a) -{ - ffbContextPtr fmesa = FFB_CONTEXT(ctx); - - fmesa->MonoColor = ((r << 0) | - (g << 8) | - (b << 16)); -} - -static void ffbDDClearColor(GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a) +static void ffbDDClearColor(GLcontext *ctx, const GLchan color[4]) { ffbContextPtr fmesa = FFB_CONTEXT(ctx); - fmesa->clear_pixel = ((r << 0) | - (g << 8) | - (b << 16)); + fmesa->clear_pixel = ((color[0] << 0) | + (color[1] << 8) | + (color[2] << 16)); } static void ffbDDClearDepth(GLcontext *ctx, GLclampd depth) @@ -533,149 +566,10 @@ static void ffbDDClearStencil(GLcontext *ctx, GLint stencil) fmesa->clear_stencil = stencil & 0xf; } -static void ffbDDReducedPrimitiveChange(GLcontext *ctx, GLenum prim) -{ - ffbContextPtr fmesa = FFB_CONTEXT(ctx); - GLuint drawop, fbc, ppc; - int do_sw = 0; - - drawop = fmesa->drawop; - fbc = fmesa->fbc; - ppc = fmesa->ppc & ~(FFB_PPC_ZS_MASK | FFB_PPC_CS_MASK); - -#ifdef STATE_TRACE - fprintf(stderr, - "ffbDDReducedPrimitiveChange: prim(%d) ", prim); -#endif - switch(prim) { - case GL_POINT: - case GL_POINTS: -#ifdef STATE_TRACE - fprintf(stderr, "GL_POINTS "); -#endif - if (ctx->IndirectTriangles & DD_POINT_SW_RASTERIZE) { - do_sw = 1; - break; - } - - if (ctx->TriangleCaps & DD_POINT_SIZE) { - ppc |= FFB_PPC_ZS_CONST | FFB_PPC_CS_CONST; - drawop = FFB_DRAWOP_TRIANGLE; - } else { - if (ctx->Point.SmoothFlag) { - ppc |= (FFB_PPC_ZS_VAR | FFB_PPC_CS_CONST); - drawop = FFB_DRAWOP_AADOT; - } else { - ppc |= (FFB_PPC_ZS_CONST | FFB_PPC_CS_CONST); - drawop = FFB_DRAWOP_DOT; - } - } - break; - - case GL_LINE: - case GL_LINES: -#ifdef STATE_TRACE - fprintf(stderr, "GL_LINES "); -#endif - if (ctx->IndirectTriangles & DD_LINE_SW_RASTERIZE) { - do_sw = 1; - break; - } - - if (ctx->TriangleCaps & DD_FLATSHADE) { - ppc |= FFB_PPC_ZS_VAR | FFB_PPC_CS_CONST; - } else { - ppc |= FFB_PPC_ZS_VAR | FFB_PPC_CS_VAR; - } - if (ctx->TriangleCaps & DD_LINE_WIDTH) { - drawop = FFB_DRAWOP_TRIANGLE; - } else { - if (ctx->Line.SmoothFlag) - drawop = FFB_DRAWOP_AALINE; - else - drawop = FFB_DRAWOP_DDLINE; - } - break; - - case GL_POLYGON: -#ifdef STATE_TRACE - fprintf(stderr, "GL_POLYGON "); -#endif - if (ctx->IndirectTriangles & DD_TRI_SW_RASTERIZE) { - do_sw = 1; - break; - } - - ppc &= ~FFB_PPC_APE_MASK; - if (ctx->Polygon.StippleFlag) - ppc |= FFB_PPC_APE_ENABLE; - else - ppc |= FFB_PPC_APE_DISABLE; - - if (ctx->TriangleCaps & DD_FLATSHADE) { - ppc |= FFB_PPC_ZS_VAR | FFB_PPC_CS_CONST; - } else { - ppc |= FFB_PPC_ZS_VAR | FFB_PPC_CS_VAR; - } - drawop = FFB_DRAWOP_TRIANGLE; - break; - - default: -#ifdef STATE_TRACE - fprintf(stderr, "unknown %d!\n", prim); -#endif - return; - }; - -#ifdef STATE_TRACE - fprintf(stderr, "do_sw(%d) ", do_sw); -#endif - if (do_sw != 0) { - fbc &= ~(FFB_FBC_WB_C); - fbc &= ~(FFB_FBC_ZE_MASK | FFB_FBC_RGBE_MASK); - fbc |= FFB_FBC_ZE_OFF | FFB_FBC_RGBE_MASK; - ppc &= ~(FFB_PPC_XS_MASK | FFB_PPC_ABE_MASK | - FFB_PPC_DCE_MASK | FFB_PPC_APE_MASK); - ppc |= (FFB_PPC_ZS_VAR | FFB_PPC_CS_VAR | FFB_PPC_XS_WID | - FFB_PPC_ABE_DISABLE | FFB_PPC_DCE_DISABLE | - FFB_PPC_APE_DISABLE); - } else { - fbc |= FFB_FBC_WB_C; - fbc &= ~(FFB_FBC_RGBE_MASK); - fbc |= FFB_FBC_RGBE_MASK; - ppc &= ~(FFB_PPC_ABE_MASK | FFB_PPC_XS_MASK); - if (ctx->Color.BlendEnabled) { - ppc |= FFB_PPC_ABE_ENABLE | FFB_PPC_XS_VAR; - } else { - ppc |= FFB_PPC_ABE_DISABLE | FFB_PPC_XS_WID; - } - } -#ifdef STATE_TRACE - fprintf(stderr, "fbc(%08x) ppc(%08x)\n", fbc, ppc); -#endif - - FFBFifo(fmesa, 4); - if (fmesa->drawop != drawop) - fmesa->regs->drawop = fmesa->drawop = drawop; - if (fmesa->fbc != fbc) - fmesa->regs->fbc = fmesa->fbc = fbc; - if (fmesa->ppc != ppc) - fmesa->regs->ppc = fmesa->ppc = ppc; - if (do_sw != 0) { - fmesa->regs->cmp = - (fmesa->cmp & ~(0xff<<16)) | (0x80 << 16); - } else - fmesa->regs->cmp = fmesa->cmp; - - /* Flush the vertex cache. */ - fmesa->vtx_cache[0] = fmesa->vtx_cache[1] = - fmesa->vtx_cache[2] = fmesa->vtx_cache[3] = NULL; -} - /* XXX Actually, should I be using FBC controls for this? -DaveM */ -static GLboolean ffbDDColorMask(GLcontext *ctx, - GLboolean r, GLboolean g, - GLboolean b, GLboolean a) +static void ffbDDColorMask(GLcontext *ctx, + GLboolean r, GLboolean g, + GLboolean b, GLboolean a) { ffbContextPtr fmesa = FFB_CONTEXT(ctx); unsigned int new_pmask = 0x0; @@ -693,21 +587,18 @@ static GLboolean ffbDDColorMask(GLcontext *ctx, if (fmesa->pmask != new_pmask) { fmesa->pmask = new_pmask; - fmesa->state_dirty |= FFB_STATE_PMASK; - fmesa->state_fifo_ents += 1; + FFB_MAKE_DIRTY(fmesa, FFB_STATE_PMASK, 1); } - - return GL_TRUE; } -static GLboolean ffbDDLogicOp(GLcontext *ctx, GLenum op) +static void ffbDDLogicOp(GLcontext *ctx, GLenum op) { ffbContextPtr fmesa = FFB_CONTEXT(ctx); unsigned int rop; #ifdef STATE_TRACE fprintf(stderr, "ffbDDLogicOp: op(%s)\n", - gl_lookup_enum_by_nr(op)); + _mesa_lookup_enum_by_nr(op)); #endif switch (op) { case GL_CLEAR: rop = FFB_ROP_ZERO; break; @@ -728,20 +619,17 @@ static GLboolean ffbDDLogicOp(GLcontext *ctx, GLenum op) case GL_OR_INVERTED: rop = FFB_ROP_NNEW_OR_OLD; break; default: - return GL_FALSE; + return; }; rop |= fmesa->rop & ~0xff; if (rop != fmesa->rop) { fmesa->rop = rop; - fmesa->state_dirty |= FFB_STATE_ROP; - fmesa->state_fifo_ents += 1; + FFB_MAKE_DIRTY(fmesa, FFB_STATE_ROP, 1); if (op == GL_COPY) - fmesa->bad_fragment_attrs &= ~FFB_BADATTR_BLENDROP; + FALLBACK( ctx, FFB_BADATTR_BLENDROP, GL_FALSE ); } - - return GL_TRUE; } #if 0 @@ -824,7 +712,7 @@ static void ffb_fog_linear(GLcontext *ctx, ffbContextPtr fmesa) static void ffbDDFogfv(GLcontext *ctx, GLenum pname, const GLfloat *param) { #ifdef STATE_TRACE - fprintf(stderr, "ffbDDFogfv: pname(%s)\n", gl_lookup_enum_by_nr(pname)); + fprintf(stderr, "ffbDDFogfv: pname(%s)\n", _mesa_lookup_enum_by_nr(pname)); #endif } @@ -839,11 +727,9 @@ static void ffbDDLineStipple(GLcontext *ctx, GLint factor, GLushort pattern) if (ctx->Line.StippleFlag) { factor = ctx->Line.StippleFactor; pattern = ctx->Line.StipplePattern; - if ((GLuint) factor > 15) { - ctx->Driver.TriangleCaps &= ~DD_LINE_STIPPLE; + if ((GLuint) factor > 15) { fmesa->lpat = FFB_LPAT_BAD; } else { - ctx->Driver.TriangleCaps |= DD_LINE_STIPPLE; fmesa->lpat = ((factor << FFB_LPAT_SCALEVAL_SHIFT) | (0 << FFB_LPAT_PATLEN_SHIFT) | ((pattern & 0xffff) << FFB_LPAT_PATTERN_SHIFT)); @@ -874,8 +760,7 @@ void ffbXformAreaPattern(ffbContextPtr fmesa, const GLubyte *mask) mask += 4; } - fmesa->state_dirty |= FFB_STATE_APAT; - fmesa->state_fifo_ents += 32; + FFB_MAKE_DIRTY(fmesa, FFB_STATE_APAT, 32); } static void ffbDDPolygonStipple(GLcontext *ctx, const GLubyte *mask) @@ -886,11 +771,6 @@ static void ffbDDPolygonStipple(GLcontext *ctx, const GLubyte *mask) fprintf(stderr, "ffbDDPolygonStipple: state(%d)\n", ctx->Polygon.StippleFlag); #endif - if (ctx->Polygon.StippleFlag) { - ctx->Driver.TriangleCaps |= DD_TRI_STIPPLE; - } else { - ctx->Driver.TriangleCaps &= ~DD_TRI_STIPPLE; - } ffbXformAreaPattern(fmesa, mask); } @@ -901,7 +781,7 @@ static void ffbDDEnable(GLcontext *ctx, GLenum cap, GLboolean state) #ifdef STATE_TRACE fprintf(stderr, "ffbDDEnable: %s state(%d)\n", - gl_lookup_enum_by_nr(cap), state); + _mesa_lookup_enum_by_nr(cap), state); #endif switch (cap) { case GL_ALPHA_TEST: @@ -912,8 +792,7 @@ static void ffbDDEnable(GLcontext *ctx, GLenum cap, GLboolean state) if (tmp != fmesa->xclip) { fmesa->xclip = tmp; - fmesa->state_dirty |= FFB_STATE_XCLIP; - fmesa->state_fifo_ents += 1; + FFB_MAKE_DIRTY(fmesa, FFB_STATE_XCLIP, 1); } break; @@ -926,8 +805,7 @@ static void ffbDDEnable(GLcontext *ctx, GLenum cap, GLboolean state) } if (fmesa->ppc != tmp) { fmesa->ppc = tmp; - fmesa->state_dirty |= FFB_STATE_PPC; - fmesa->state_fifo_ents += 1; + FFB_MAKE_DIRTY(fmesa, FFB_STATE_PPC, 1); ffbDDBlendFunc(ctx, 0, 0); } break; @@ -947,29 +825,18 @@ static void ffbDDEnable(GLcontext *ctx, GLenum cap, GLboolean state) fmesa->fbc = fbc; ffbDDDepthFunc(ctx, ctx->Depth.Func); fmesa->magnc = tmp; - fmesa->state_dirty |= FFB_STATE_MAGNC | FFB_STATE_FBC; - fmesa->state_fifo_ents += 2; + FFB_MAKE_DIRTY(fmesa, (FFB_STATE_MAGNC | FFB_STATE_FBC), 2); } break; case GL_SCISSOR_TEST: - tmp = fmesa->ppc & ~FFB_PPC_VCE_MASK; - if (state) { - ffbDDScissor(ctx, ctx->Scissor.X, ctx->Scissor.Y, - ctx->Scissor.Width, ctx->Scissor.Height); - tmp |= FFB_PPC_VCE_2D; - } else { - tmp |= FFB_PPC_VCE_DISABLE; - } + ffbDDScissor(ctx, ctx->Scissor.X, ctx->Scissor.Y, + ctx->Scissor.Width, ctx->Scissor.Height); break; case GL_STENCIL_TEST: if (!(fmesa->ffb_sarea->flags & FFB_DRI_FFB2PLUS)) { - if (state) - fmesa->bad_fragment_attrs |= FFB_BADATTR_STENCIL; - else - fmesa->bad_fragment_attrs &= ~FFB_BADATTR_STENCIL; - break; + FALLBACK( ctx, FFB_BADATTR_STENCIL, state ); } tmp = fmesa->fbc & ~FFB_FBC_YE_MASK; @@ -987,23 +854,18 @@ static void ffbDDEnable(GLcontext *ctx, GLenum cap, GLboolean state) } else { fmesa->stencil = 0xf0000000; fmesa->stencilctl = 0x33300000; - fmesa->state_dirty |= FFB_STATE_STENCIL; - fmesa->state_fifo_ents += 6; + FFB_MAKE_DIRTY(fmesa, FFB_STATE_STENCIL, 6); tmp |= FFB_FBC_YE_OFF; } if (tmp != fmesa->fbc) { fmesa->fbc = tmp; - fmesa->state_dirty |= FFB_STATE_FBC; - fmesa->state_fifo_ents += 1; + FFB_MAKE_DIRTY(fmesa, FFB_STATE_FBC, 1); } break; case GL_FOG: /* Until I implement the fog support... */ - if (state) - fmesa->bad_fragment_attrs |= FFB_BADATTR_FOG; - else - fmesa->bad_fragment_attrs &= ~FFB_BADATTR_FOG; + FALLBACK( ctx, FFB_BADATTR_FOG, state ); break; case GL_LINE_STIPPLE: @@ -1137,59 +999,36 @@ void ffbSyncHardware(ffbContextPtr fmesa) fmesa->ffbScreen->rp_active = 1; } -static void ffbDDRenderStart(GLcontext *ctx) -{ - ffbContextPtr fmesa = FFB_CONTEXT(ctx); - - LOCK_HARDWARE(fmesa); - fmesa->hw_locked = 1; - - if (fmesa->state_dirty != 0) - ffbSyncHardware(fmesa); -} - -static void ffbDDRenderFinish(GLcontext *ctx) +static void ffbDDUpdateState(GLcontext *ctx, GLuint newstate) { ffbContextPtr fmesa = FFB_CONTEXT(ctx); - UNLOCK_HARDWARE(fmesa); - fmesa->hw_locked = 0; -} + /* When we are hw rendering, changing certain kinds of + * state does not require flushing all of our context. + */ + if (fmesa->bad_fragment_attrs == 0 && + (newstate & ~_NEW_COLOR) == 0) + return; -#define INTERESTED (~(NEW_MODELVIEW|NEW_PROJECTION|\ - NEW_TEXTURE_MATRIX|\ - NEW_USER_CLIP|NEW_CLIENT_STATE|\ - NEW_TEXTURE_ENABLE)) + _swrast_InvalidateState( ctx, newstate ); + _swsetup_InvalidateState( ctx, newstate ); + _ac_InvalidateState( ctx, newstate ); + _tnl_InvalidateState( ctx, newstate ); -static void ffbDDUpdateState(GLcontext *ctx) -{ - ffbContextPtr fmesa = FFB_CONTEXT(ctx); - unsigned int flags; - - if (ctx->NewState & INTERESTED) { - if (fmesa->SWrender || - fmesa->bad_fragment_attrs != 0) { - /* Force SW rendering. */ - fmesa->PointsFunc = NULL; - fmesa->LineFunc = NULL; - fmesa->TriangleFunc = NULL; - fmesa->QuadFunc = NULL; - } else { - ffbDDChooseTriRenderState(ctx); - ffbDDChooseLineRenderState(ctx); - ffbDDChoosePointRenderState(ctx); - } + if (newstate & _NEW_TEXTURE) + FALLBACK( ctx, FFB_BADATTR_TEXTURE, + (ctx->Texture._ReallyEnabled != 0)); - if (0) - gl_print_tri_caps("tricaps", ctx->TriangleCaps); +#ifdef STATE_TRACE + fprintf(stderr, "ffbDDUpdateState: newstate(%08x)\n", newstate); +#endif - ffbChooseRasterSetupFunc(ctx); + fmesa->new_gl_state |= newstate; - /* Force a reduced primitive change next rendering - * pass. - */ - ctx->PB->primitive = GL_POLYGON + 1; - } + /* Force a reduced primitive change next rendering + * pass. + */ + fmesa->raster_primitive = GL_POLYGON + 1; #if 0 /* When the modelview matrix changes, this changes what @@ -1198,45 +1037,18 @@ static void ffbDDUpdateState(GLcontext *ctx) * * XXX DD_HAVE_HARDWARE_FOG. */ - if (ctx->Fog.Enabled && (ctx->NewState & NEW_MODELVIEW)) + if (ctx->Fog.Enabled && (newstate & _NEW_MODELVIEW)) ffb_update_fog(); #endif - - /* XXX It may be possible to eliminate all of Mesa's sw clip - * XXX processing using the hw clip registers we have. If - * XXX this is correct, it is just a matter of verifying the - * XXX FFB coordinate overflow rules in ffb_vb.c and if they - * XXX are not violated we clear CLIP_MASK_ACTIVE in - * XXX VB->CullMode. - * XXX - * XXX We would specify the xyz min/max values in the primary - * XXX viewport clip registers, and the user specified - * XXX scissor clip can go into one of the auxilliary viewport - * XXX clips. - */ - flags = ctx->IndirectTriangles; - if (fmesa->PointsFunc != NULL) { - ctx->Driver.PointsFunc = fmesa->PointsFunc; - flags &= ~DD_POINT_SW_RASTERIZE; - } - if (fmesa->LineFunc != NULL) { - ctx->Driver.LineFunc = fmesa->LineFunc; - flags &= ~DD_LINE_SW_RASTERIZE; - } - if (fmesa->TriangleFunc != NULL) { - ctx->Driver.TriangleFunc = fmesa->TriangleFunc; - ctx->Driver.QuadFunc = fmesa->QuadFunc; - flags &= ~(DD_TRI_SW_RASTERIZE | - DD_QUAD_SW_RASTERIZE); - } - ctx->IndirectTriangles = flags; } + void ffbDDInitStateFuncs(GLcontext *ctx) { ffbContextPtr fmesa = FFB_CONTEXT(ctx); ctx->Driver.UpdateState = ffbDDUpdateState; + ctx->Driver.Enable = ffbDDEnable; ctx->Driver.LightModelfv = NULL; ctx->Driver.AlphaFunc = ffbDDAlphaFunc; @@ -1252,10 +1064,9 @@ void ffbDDInitStateFuncs(GLcontext *ctx) ctx->Driver.CullFace = NULL; ctx->Driver.FrontFace = NULL; ctx->Driver.ColorMask = ffbDDColorMask; - ctx->Driver.LogicOp = ffbDDLogicOp; - ctx->Driver.ReducedPrimitiveChange = ffbDDReducedPrimitiveChange; - ctx->Driver.RenderStart = ffbDDRenderStart; - ctx->Driver.RenderFinish = ffbDDRenderFinish; + ctx->Driver.LogicOpcode = ffbDDLogicOp; + ctx->Driver.Viewport = ffbDDViewport; + ctx->Driver.DepthRange = ffbDDDepthRange; if (fmesa->ffb_sarea->flags & FFB_DRI_FFB2PLUS) { ctx->Driver.StencilFunc = ffbDDStencilFunc; @@ -1268,17 +1079,38 @@ void ffbDDInitStateFuncs(GLcontext *ctx) } ctx->Driver.SetDrawBuffer = ffbDDSetDrawBuffer; - ctx->Driver.SetReadBuffer = ffbDDSetReadBuffer; - ctx->Driver.Color = ffbDDSetColor; ctx->Driver.ClearColor = ffbDDClearColor; ctx->Driver.ClearDepth = ffbDDClearDepth; ctx->Driver.ClearStencil = ffbDDClearStencil; - ctx->Driver.Dither = NULL; /* We will support color index modes later... -DaveM */ - ctx->Driver.Index = 0; ctx->Driver.ClearIndex = 0; ctx->Driver.IndexMask = 0; + + + + /* Pixel path fallbacks. + */ + ctx->Driver.Accum = _swrast_Accum; + ctx->Driver.CopyPixels = _swrast_CopyPixels; + ctx->Driver.DrawPixels = _swrast_DrawPixels; + ctx->Driver.ReadPixels = _swrast_ReadPixels; + ctx->Driver.ResizeBuffers = _swrast_alloc_buffers; + + /* Swrast hooks for imaging extensions: + */ + ctx->Driver.CopyColorTable = _swrast_CopyColorTable; + ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable; + ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D; + ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D; + + { + struct swrast_device_driver *swdd = + _swrast_GetDeviceDriverReference(ctx); + swdd->SetReadBuffer = ffbDDSetReadBuffer; + } + + } void ffbDDInitContextHwState(GLcontext *ctx) @@ -1291,13 +1123,14 @@ void ffbDDInitContextHwState(GLcontext *ctx) fmesa->bad_fragment_attrs = 0; fmesa->state_dirty = FFB_STATE_ALL; + fmesa->new_gl_state = ~0; fifo_count = 1; fmesa->fbc = (FFB_FBC_WE_FORCEON | FFB_FBC_WM_COMBINED | FFB_FBC_SB_BOTH | FFB_FBC_ZE_MASK | FFB_FBC_YE_OFF | FFB_FBC_XE_OFF | FFB_FBC_RGBE_MASK); - if (ctx->Visual->DBflag) { + if (ctx->Visual.doubleBufferMode) { /* Buffer B is the initial back buffer. */ fmesa->back_buffer = 1; fmesa->fbc |= FFB_FBC_WB_BC | FFB_FBC_RB_B; @@ -1308,7 +1141,7 @@ void ffbDDInitContextHwState(GLcontext *ctx) fifo_count += 1; fmesa->ppc = (FFB_PPC_ACE_DISABLE | FFB_PPC_DCE_DISABLE | - FFB_PPC_ABE_DISABLE | FFB_PPC_VCE_DISABLE | + FFB_PPC_ABE_DISABLE | FFB_PPC_VCE_3D | FFB_PPC_APE_DISABLE | FFB_PPC_TBE_OPAQUE | FFB_PPC_ZS_CONST | FFB_PPC_YS_CONST | FFB_PPC_XS_WID | FFB_PPC_CS_VAR); @@ -1378,9 +1211,9 @@ void ffbDDInitContextHwState(GLcontext *ctx) /* ViewPort clip state. */ fifo_count += 4 + (4 * 2); fmesa->vclipmin = 0x00000000; - fmesa->vclipmax = 0x00000000; + fmesa->vclipmax = 0xffffffff; fmesa->vclipzmin = 0x00000000; - fmesa->vclipzmax = 0x00000000; + fmesa->vclipzmax = 0x0fffffff; for (i = 0; i < 4; i++) { fmesa->aux_clips[0].min = 0x00000000; fmesa->aux_clips[0].max = 0x00000000; diff --git a/xc/lib/GL/mesa/src/drv/gamma/gamma_state.c b/xc/lib/GL/mesa/src/drv/gamma/gamma_state.c new file mode 100644 index 000000000..9c6d23481 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/gamma/gamma_state.c @@ -0,0 +1,1731 @@ +/* + * Copyright 2001 by Alan Hourihane. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Alan Hourihane not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Alan Hourihane makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk> + * + * 3DLabs Gamma driver + */ + +#include <X11/Xlibint.h> +#include "gamma_context.h" +#include "gamma_macros.h" +#include "macros.h" +#include "glint_dri.h" +#include "colormac.h" +#include "swrast/swrast.h" +#include "swrast_setup/swrast_setup.h" +#include "array_cache/acache.h" +#include "tnl/tnl.h" + +#define ENABLELIGHTING 0 + +/* ============================================================= + * Alpha blending + */ + +static void gammaUpdateAlphaMode( GLcontext *ctx ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + CARD32 a = gmesa->AlphaTestMode; + CARD32 b = gmesa->AlphaBlendMode; + CARD32 f = gmesa->AB_FBReadMode_Save = 0; + + a &= ~(AT_CompareMask | AT_RefValueMask); + b &= ~(AB_SrcBlendMask | AB_DstBlendMask); + + a |= ctx->Color.AlphaRef << 4; + + switch ( ctx->Color.AlphaFunc ) { + case GL_NEVER: + a |= AT_Never; + break; + case GL_LESS: + a |= AT_Less; + break; + case GL_EQUAL: + a |= AT_Equal; + break; + case GL_LEQUAL: + a |= AT_LessEqual; + break; + case GL_GEQUAL: + a |= AT_GreaterEqual; + break; + case GL_GREATER: + a |= AT_Greater; + break; + case GL_NOTEQUAL: + a |= AT_NotEqual; + break; + case GL_ALWAYS: + a |= AT_Always; + break; + } + + if ( ctx->Color.AlphaEnabled ) { + f |= FBReadDstEnable; + a |= AlphaTestModeEnable; + } else { + a &= ~AlphaTestModeEnable; + } + + switch ( ctx->Color.BlendSrcRGB ) { + case GL_ZERO: + b |= AB_Src_Zero; + break; + case GL_ONE: + b |= AB_Src_One; + break; + case GL_DST_COLOR: + b |= AB_Src_DstColor; + break; + case GL_ONE_MINUS_DST_COLOR: + b |= AB_Src_OneMinusDstColor; + break; + case GL_SRC_ALPHA: + b |= AB_Src_SrcAlpha; + break; + case GL_ONE_MINUS_SRC_ALPHA: + b |= AB_Src_OneMinusSrcAlpha; + break; + case GL_DST_ALPHA: + b |= AB_Src_DstAlpha; + f |= FBReadSrcEnable; + break; + case GL_ONE_MINUS_DST_ALPHA: + b |= AB_Src_OneMinusDstAlpha; + f |= FBReadSrcEnable; + break; + case GL_SRC_ALPHA_SATURATE: + b |= AB_Src_SrcAlphaSaturate; + break; + } + + switch ( ctx->Color.BlendDstRGB ) { + case GL_ZERO: + b |= AB_Dst_Zero; + break; + case GL_ONE: + b |= AB_Dst_One; + break; + case GL_SRC_COLOR: + b |= AB_Dst_SrcColor; + break; + case GL_ONE_MINUS_SRC_COLOR: + b |= AB_Dst_OneMinusSrcColor; + break; + case GL_SRC_ALPHA: + b |= AB_Dst_SrcAlpha; + break; + case GL_ONE_MINUS_SRC_ALPHA: + b |= AB_Dst_OneMinusSrcAlpha; + break; + case GL_DST_ALPHA: + b |= AB_Dst_DstAlpha; + f |= FBReadSrcEnable; + break; + case GL_ONE_MINUS_DST_ALPHA: + b |= AB_Dst_OneMinusDstAlpha; + f |= FBReadSrcEnable; + break; + } + + if ( ctx->Color.BlendEnabled ) { + f |= FBReadDstEnable; + b |= AlphaBlendModeEnable; + } else { + b &= ~AlphaBlendModeEnable; + } + + if ( gmesa->AlphaTestMode != a ) { + gmesa->AlphaTestMode = a; + gmesa->dirty |= GAMMA_UPLOAD_ALPHA; + } + if ( gmesa->AlphaBlendMode != b) { + gmesa->AlphaBlendMode = b; + gmesa->dirty |= GAMMA_UPLOAD_BLEND; + } + gmesa->AB_FBReadMode_Save = f; +} + +static void gammaDDAlphaFunc( GLcontext *ctx, GLenum func, GLchan ref ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + FLUSH_BATCH( gmesa ); + + gmesa->new_state |= GAMMA_NEW_ALPHA; +} + +static void gammaDDBlendEquation( GLcontext *ctx, GLenum mode ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + FLUSH_BATCH( gmesa ); + + gmesa->new_state |= GAMMA_NEW_ALPHA; +} + +static void gammaDDBlendFunc( GLcontext *ctx, GLenum sfactor, GLenum dfactor ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + FLUSH_BATCH( gmesa ); + + gmesa->new_state |= GAMMA_NEW_ALPHA; +} + +static void gammaDDBlendFuncSeparate( GLcontext *ctx, + GLenum sfactorRGB, GLenum dfactorRGB, + GLenum sfactorA, GLenum dfactorA ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + FLUSH_BATCH( gmesa ); + + gmesa->new_state |= GAMMA_NEW_ALPHA; +} + + +/* ================================================================ + * Buffer clear + */ + +static void gammaDDClear( GLcontext *ctx, GLbitfield mask, GLboolean all, + GLint cx, GLint cy, GLint cw, GLint ch ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + GLINTDRIPtr gDRIPriv = (GLINTDRIPtr)gmesa->driScreen->pDevPriv; + GLuint temp = 0; + + FLUSH_BATCH( gmesa ); + + /* Update and emit any new state. We need to do this here to catch + * changes to the masks. + * FIXME: Just update the masks? + */ + if ( gmesa->new_state ) + gammaDDUpdateHWState( ctx ); + +#ifdef DO_VALIDATE + /* Flush any partially filled buffers */ + FLUSH_DMA_BUFFER(gmesa); + + DRM_SPINLOCK(&gmesa->driScreen->pSAREA->drawable_lock, + gmesa->driScreen->drawLockID); + VALIDATE_DRAWABLE_INFO_NO_LOCK(gmesa); +#endif + + if (mask & DD_DEPTH_BIT) { + /* Turn off writes the FB */ + CHECK_DMA_BUFFER(gmesa, 1); + WRITE(gmesa->buf, FBWriteMode, FBWriteModeDisable); + + mask &= ~DD_DEPTH_BIT; + + /* + * Turn Rectangle2DControl off when the window is not clipped + * (i.e., the GID tests are not necessary). This dramatically + * increases the performance of the depth clears. + */ + if (!gmesa->NotClipped) { + CHECK_DMA_BUFFER(gmesa, 1); + WRITE(gmesa->buf, Rectangle2DControl, 1); + } + + temp = (gmesa->LBReadMode & LBPartialProdMask) | LBWindowOriginBot; + if (gDRIPriv->numMultiDevices == 2) temp |= LBScanLineInt2; + + CHECK_DMA_BUFFER(gmesa, 5); + WRITE(gmesa->buf, LBReadMode, temp); + WRITE(gmesa->buf, DeltaMode, DM_DepthEnable); + WRITE(gmesa->buf, DepthMode, (DepthModeEnable | + DM_Always | + DM_SourceDepthRegister | + DM_WriteMask)); + WRITE(gmesa->buf, GLINTDepth, gmesa->ClearDepth); + + /* Increment the frame count */ + gmesa->FrameCount++; +#ifdef FAST_CLEAR_4 + gmesa->FrameCount &= 0x0f; +#else + gmesa->FrameCount &= 0xff; +#endif + + /* Force FCP to be written */ + WRITE(gmesa->buf, GLINTWindow, (WindowEnable | + W_PassIfEqual | + (gmesa->Window & W_GIDMask) | + W_DepthFCP | + W_LBUpdateFromRegisters | + W_OverrideWriteFiltering | + (gmesa->FrameCount << 9))); + + /* Clear part of the depth and FCP buffers */ + { + int y = gmesa->driScreen->fbHeight - gmesa->driDrawable->y - gmesa->driDrawable->h; + int x = gmesa->driDrawable->x; + int w = gmesa->driDrawable->w; + int h = gmesa->driDrawable->h; +#ifndef TURN_OFF_FCP + float hsub = h; + + if (gmesa->WindowChanged) { + gmesa->WindowChanged = GL_FALSE; + } else { +#ifdef FAST_CLEAR_4 + hsub /= 16; +#else + hsub /= 256; +#endif + + /* Handle the case where the height < # of FCPs */ + if (hsub < 1.0) { + if (gmesa->FrameCount > h) + gmesa->FrameCount = 0; + h = 1; + y += gmesa->FrameCount; + } else { + h = (gmesa->FrameCount+1)*hsub; + h -= (int)(gmesa->FrameCount*hsub); + y += gmesa->FrameCount*hsub; + } + } +#endif + if (h && w) { +#if 0 + CHECK_DMA_BUFFER(gmesa, 2); + WRITE(gmesa->buf, Rectangle2DMode, ((h & 0xfff)<<12) | + (w & 0xfff) ); + WRITE(gmesa->buf, DrawRectangle2D, ((y & 0xffff)<<16) | + (x & 0xffff) ); +#else + CHECK_DMA_BUFFER(gmesa, 8); + WRITE(gmesa->buf, StartXDom, x<<16); + WRITE(gmesa->buf, StartY, y<<16); + WRITE(gmesa->buf, StartXSub, (x+w)<<16); + WRITE(gmesa->buf, GLINTCount, h); + WRITE(gmesa->buf, dY, 1<<16); + WRITE(gmesa->buf, dXDom, 0<<16); + WRITE(gmesa->buf, dXSub, 0<<16); + WRITE(gmesa->buf, Render, 0x00000040); /* NOT_DONE */ +#endif + } + } + + CHECK_DMA_BUFFER(gmesa, 6); + WRITE(gmesa->buf, DepthMode, gmesa->DepthMode); + WRITE(gmesa->buf, DeltaMode, gmesa->DeltaMode); + WRITE(gmesa->buf, LBReadMode, gmesa->LBReadMode); + WRITE(gmesa->buf, GLINTWindow, gmesa->Window); + WRITE(gmesa->buf, FastClearDepth, gmesa->ClearDepth); + WRITE(gmesa->buf, FBWriteMode, FBWriteModeEnable); + + /* Turn on Depth FCP */ + if (gmesa->Window & W_DepthFCP) { + CHECK_DMA_BUFFER(gmesa, 1); + WRITE(gmesa->buf, WindowOr, (gmesa->FrameCount << 9)); + } + + /* Turn off GID clipping if window is not clipped */ + if (gmesa->NotClipped) { + CHECK_DMA_BUFFER(gmesa, 1); + WRITE(gmesa->buf, Rectangle2DControl, 0); + } + } + + if (mask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT)) { + int y = gmesa->driScreen->fbHeight - gmesa->driDrawable->y - gmesa->driDrawable->h; + int x = gmesa->driDrawable->x; + int w = gmesa->driDrawable->w; + int h = gmesa->driDrawable->h; + + mask &= ~(DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT); + + if (x < 0) { w -= -x; x = 0; } + + /* Turn on GID clipping if window is clipped */ + if (!gmesa->NotClipped) { + CHECK_DMA_BUFFER(gmesa, 1); + WRITE(gmesa->buf, Rectangle2DControl, 1); + } + + CHECK_DMA_BUFFER(gmesa, 18); + WRITE(gmesa->buf, FBBlockColor, gmesa->ClearColor); + WRITE(gmesa->buf, ColorDDAMode, ColorDDADisable); + WRITE(gmesa->buf, FBWriteMode, FBWriteModeEnable); + WRITE(gmesa->buf, DepthMode, 0); + WRITE(gmesa->buf, DeltaMode, 0); + WRITE(gmesa->buf, AlphaBlendMode, 0); +#if 1 + WRITE(gmesa->buf, dY, 1<<16); + WRITE(gmesa->buf, dXDom, 0<<16); + WRITE(gmesa->buf, dXSub, 0<<16); + WRITE(gmesa->buf, StartXSub, (x+w)<<16); + WRITE(gmesa->buf, GLINTCount, h); + WRITE(gmesa->buf, StartXDom, x<<16); + WRITE(gmesa->buf, StartY, y<<16); + WRITE(gmesa->buf, Render, 0x00000048); /* NOT_DONE */ +#else + WRITE(gmesa->buf, Rectangle2DMode, (((h & 0xfff)<<12) | + (w & 0xfff))); + WRITE(gmesa->buf, DrawRectangle2D, (((y & 0xffff)<<16) | + (x & 0xffff))); +#endif + WRITE(gmesa->buf, DepthMode, gmesa->DepthMode); + WRITE(gmesa->buf, DeltaMode, gmesa->DeltaMode); + WRITE(gmesa->buf, AlphaBlendMode, gmesa->AlphaBlendMode); + WRITE(gmesa->buf, ColorDDAMode, gmesa->ColorDDAMode); + + /* Turn off GID clipping if window is clipped */ + if (gmesa->NotClipped) { + CHECK_DMA_BUFFER(gmesa, 1); + WRITE(gmesa->buf, Rectangle2DControl, 0); + } + } + +#ifdef DO_VALIDATE + PROCESS_DMA_BUFFER_TOP_HALF(gmesa); + + DRM_SPINUNLOCK(&gmesa->driScreen->pSAREA->drawable_lock, + gmesa->driScreen->drawLockID); + VALIDATE_DRAWABLE_INFO_NO_LOCK_POST(gmesa); + + PROCESS_DMA_BUFFER_BOTTOM_HALF(gmesa); +#endif + + if ( mask ) + _swrast_Clear( ctx, mask, all, cx, cy, cw, ch ); +} + +/* ============================================================= + * Depth testing + */ + +static void gammaUpdateZMode( GLcontext *ctx ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + CARD32 z = gmesa->DepthMode; + CARD32 delta = gmesa->DeltaMode; + CARD32 window = gmesa->Window; + CARD32 lbread = gmesa->LBReadMode; + + z &= ~DM_CompareMask; + + switch ( ctx->Depth.Func ) { + case GL_NEVER: + z |= DM_Never; + break; + case GL_ALWAYS: + z |= DM_Always; + break; + case GL_LESS: + z |= DM_Less; + break; + case GL_LEQUAL: + z |= DM_LessEqual; + break; + case GL_EQUAL: + z |= DM_Equal; + break; + case GL_GEQUAL: + z |= DM_GreaterEqual; + break; + case GL_GREATER: + z |= DM_Greater; + break; + case GL_NOTEQUAL: + z |= DM_NotEqual; + break; + } + + if ( ctx->Depth.Test ) { + z |= DepthModeEnable; + delta |= DM_DepthEnable; + window |= W_DepthFCP; + lbread |= LBReadDstEnable; + } else { + z &= ~DepthModeEnable; + delta &= ~DM_DepthEnable; + window &= ~W_DepthFCP; + lbread &= ~LBReadDstEnable; + } + + if ( ctx->Depth.Mask ) { + z |= DM_WriteMask; + } else { + z &= ~DM_WriteMask; + } + +#if 0 + if ( gmesa->DepthMode != z ){ +#endif + gmesa->DepthMode = z; + gmesa->DeltaMode = delta; + gmesa->Window = window; + gmesa->LBReadMode = lbread; + gmesa->dirty |= GAMMA_UPLOAD_DEPTH; +#if 0 + } +#endif +} + +static void gammaDDDepthFunc( GLcontext *ctx, GLenum func ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + FLUSH_BATCH( gmesa ); + gmesa->new_state |= GAMMA_NEW_DEPTH; +} + +static void gammaDDDepthMask( GLcontext *ctx, GLboolean flag ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + FLUSH_BATCH( gmesa ); + gmesa->new_state |= GAMMA_NEW_DEPTH; +} + +static void gammaDDClearDepth( GLcontext *ctx, GLclampd d ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + switch ( gmesa->DepthSize ) { + case 16: + gmesa->ClearDepth = d * 0x0000ffff; + break; + case 24: + gmesa->ClearDepth = d * 0x00ffffff; + break; + case 32: + gmesa->ClearDepth = d * 0xffffffff; + break; + } +} + +static void gammaDDFinish( GLcontext *ctx ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + FLUSH_DMA_BUFFER(gmesa); +} + +static void gammaDDFlush( GLcontext *ctx ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + FLUSH_DMA_BUFFER(gmesa); +} + +/* ============================================================= + * Fog + */ + +static void gammaUpdateFogAttrib( GLcontext *ctx ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + CARD32 f = gmesa->FogMode; + CARD32 g = gmesa->GeometryMode; + CARD32 d = gmesa->DeltaMode; + + if (ctx->Fog.Enabled) { + f |= FogModeEnable; + g |= GM_FogEnable; + d |= DM_FogEnable; + } else { + f &= ~FogModeEnable; + g &= ~GM_FogEnable; + d &= ~DM_FogEnable; + } + + g &= ~GM_FogMask; + + switch (ctx->Fog.Mode) { + case GL_LINEAR: + g |= GM_FogLinear; + break; + case GL_EXP: + g |= GM_FogExp; + break; + case GL_EXP2: + g |= GM_FogExpSquared; + break; + } + + if ( gmesa->FogMode != f ) { + gmesa->FogMode = f; + gmesa->dirty |= GAMMA_UPLOAD_FOG; + } + + if ( gmesa->GeometryMode != g ) { + gmesa->GeometryMode = g; + gmesa->dirty |= GAMMA_UPLOAD_GEOMETRY; + } + + if ( gmesa->DeltaMode != d ) { + gmesa->DeltaMode = d; + gmesa->dirty |= GAMMA_UPLOAD_DEPTH; + } +} + +static void gammaDDFogfv( GLcontext *ctx, GLenum pname, const GLfloat *param ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + FLUSH_BATCH( gmesa ); + gmesa->new_state |= GAMMA_NEW_FOG; +} + +/* ============================================================= + * Lines + */ +static void gammaDDLineWidth( GLcontext *ctx, GLfloat width ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + CHECK_DMA_BUFFER(gmesa, 3); + WRITE(gmesa->buf, LineWidth, (GLuint)width); + WRITEF(gmesa->buf, AAlineWidth, width); + WRITE(gmesa->buf, LineWidthOffset, (GLuint)(width-1)/2); +} + +static void gammaDDLineStipple( GLcontext *ctx, GLint factor, GLushort pattern ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + gmesa->LineMode &= ~(LM_StippleMask | LM_RepeatFactorMask); + gmesa->LineMode |= ((GLuint)(factor - 1) << 1) | ((GLuint)pattern << 10); + + gmesa->dirty |= GAMMA_UPLOAD_LINEMODE; +} + + + +/* ============================================================= + * Points + */ +static void gammaDDPointSize( GLcontext *ctx, GLfloat size ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + CHECK_DMA_BUFFER(gmesa, 2); + WRITE(gmesa->buf, PointSize, (GLuint)size); + WRITEF(gmesa->buf, AApointSize, size); +} + +/* ============================================================= + * Polygon + */ + +static void gammaUpdatePolygon( GLcontext *ctx ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + CARD32 g = gmesa->GeometryMode; + + g &= ~(GM_PolyOffsetFillEnable | GM_PolyOffsetPointEnable | + GM_PolyOffsetLineEnable); + + if (ctx->Polygon.OffsetFill) g |= GM_PolyOffsetFillEnable; + if (ctx->Polygon.OffsetPoint) g |= GM_PolyOffsetPointEnable; + if (ctx->Polygon.OffsetLine) g |= GM_PolyOffsetLineEnable; + + g &= ~GM_FB_PolyMask; + + switch (ctx->Polygon.FrontMode) { + case GL_FILL: + g |= GM_FrontPolyFill; + break; + case GL_LINE: + g |= GM_FrontPolyLine; + break; + case GL_POINT: + g |= GM_FrontPolyPoint; + break; + } + + switch (ctx->Polygon.BackMode) { + case GL_FILL: + g |= GM_BackPolyFill; + break; + case GL_LINE: + g |= GM_BackPolyLine; + break; + case GL_POINT: + g |= GM_BackPolyPoint; + break; + } + + if ( gmesa->GeometryMode != g ) { + gmesa->GeometryMode = g; + gmesa->dirty |= GAMMA_UPLOAD_GEOMETRY; + } + + gmesa->dirty |= GAMMA_UPLOAD_POLYGON; +} + +static void gammaDDPolygonMode( GLcontext *ctx, GLenum face, GLenum mode) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + FLUSH_BATCH( gmesa ); + + gmesa->new_state |= GAMMA_NEW_POLYGON; +} + +static void gammaUpdateStipple( GLcontext *ctx ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + FLUSH_BATCH( gmesa ); + + if (ctx->Polygon.StippleFlag) { + gmesa->AreaStippleMode |= AreaStippleModeEnable/* | ASM_X32 | ASM_Y32*/; + } else { + gmesa->AreaStippleMode &= ~AreaStippleModeEnable; + } + + gmesa->dirty |= GAMMA_UPLOAD_STIPPLE; +} + +static void gammaDDPolygonStipple( GLcontext *ctx, const GLubyte *mask) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + FLUSH_BATCH( gmesa ); + gmesa->new_state |= GAMMA_NEW_STIPPLE; +} + +/* ============================================================= + * Clipping + */ + +static void gammaUpdateClipping( GLcontext *ctx ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + GLint x1, y1, x2, y2; + + if ( gmesa->driDrawable ) { + x1 = gmesa->driDrawable->x + ctx->Scissor.X; + y1 = gmesa->driScreen->fbHeight - + (gmesa->driDrawable->y + + gmesa->driDrawable->h) + ctx->Scissor.Y; + x2 = x1 + ctx->Scissor.Width; + y2 = y1 + ctx->Scissor.Height; + + gmesa->ScissorMinXY = x1 | (y1 << 16); + gmesa->ScissorMaxXY = x2 | (y2 << 16); + if (ctx->Scissor.Enabled) + gmesa->ScissorMode |= UserScissorEnable; + else + gmesa->ScissorMode &= ~UserScissorEnable; + + gmesa->dirty |= GAMMA_UPLOAD_CLIP; + } +} + +static void gammaDDScissor( GLcontext *ctx, + GLint x, GLint y, GLsizei w, GLsizei h ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + FLUSH_BATCH( gmesa ); + gmesa->new_state |= GAMMA_NEW_CLIP; +} + +/* ============================================================= + * Culling + */ + +static void gammaUpdateCull( GLcontext *ctx ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + CARD32 g = gmesa->GeometryMode; + + g &= ~(GM_PolyCullMask | GM_FFMask); + + if (ctx->Polygon.FrontFace == GL_CCW) { + g |= GM_FrontFaceCCW; + } else { + g |= GM_FrontFaceCW; + } + + switch ( ctx->Polygon.CullFaceMode ) { + case GL_FRONT: + g |= GM_PolyCullFront; + break; + case GL_BACK: + g |= GM_PolyCullBack; + break; + case GL_FRONT_AND_BACK: + g |= GM_PolyCullBoth; + break; + } + + if ( ctx->Polygon.CullFlag ) { + g |= GM_PolyCullEnable; + } else { + g &= ~GM_PolyCullEnable; + } + + if ( gmesa->GeometryMode != g ) { + gmesa->GeometryMode = g; + gmesa->dirty |= GAMMA_UPLOAD_GEOMETRY; + } +} + +static void gammaDDCullFace( GLcontext *ctx, GLenum mode ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + FLUSH_BATCH( gmesa ); + gmesa->new_state |= GAMMA_NEW_CULL; +} + +static void gammaDDFrontFace( GLcontext *ctx, GLenum mode ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + FLUSH_BATCH( gmesa ); + gmesa->new_state |= GAMMA_NEW_CULL; +} + +/* ============================================================= + * Masks + */ + +static void gammaUpdateMasks( GLcontext *ctx ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + + GLuint mask = gammaPackColor( gmesa->gammaScreen->cpp, + ctx->Color.ColorMask[RCOMP], + ctx->Color.ColorMask[GCOMP], + ctx->Color.ColorMask[BCOMP], + ctx->Color.ColorMask[ACOMP] ); + + if (gmesa->gammaScreen->cpp == 2) mask |= mask << 16; + + if ( gmesa->FBHardwareWriteMask != mask ) { + gmesa->FBHardwareWriteMask = mask; + gmesa->dirty |= GAMMA_UPLOAD_MASKS; + } +} + +static void gammaDDColorMask( GLcontext *ctx, GLboolean r, GLboolean g, + GLboolean b, GLboolean a) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + FLUSH_BATCH( gmesa ); + gmesa->new_state |= GAMMA_NEW_MASKS; +} + +/* ============================================================= + * Rendering attributes + * + * We really don't want to recalculate all this every time we bind a + * texture. These things shouldn't change all that often, so it makes + * sense to break them out of the core texture state update routines. + */ + +static void gammaDDLightfv(GLcontext *ctx, GLenum light, GLenum pname, + const GLfloat *params, GLint nParams) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + GLfloat l,x,y,z,w; + + switch(light) { + case GL_LIGHT0: + switch (pname) { + case GL_AMBIENT: + CHECK_DMA_BUFFER(gmesa, 3); + /* We don't do alpha */ + WRITEF(gmesa->buf, Light0AmbientIntensityBlue, params[2]); + WRITEF(gmesa->buf, Light0AmbientIntensityGreen, params[1]); + WRITEF(gmesa->buf, Light0AmbientIntensityRed, params[0]); + break; + case GL_DIFFUSE: + CHECK_DMA_BUFFER(gmesa, 3); + /* We don't do alpha */ + WRITEF(gmesa->buf, Light0DiffuseIntensityBlue, params[2]); + WRITEF(gmesa->buf, Light0DiffuseIntensityGreen, params[1]); + WRITEF(gmesa->buf, Light0DiffuseIntensityRed, params[0]); + break; + case GL_SPECULAR: + CHECK_DMA_BUFFER(gmesa, 3); + /* We don't do alpha */ + WRITEF(gmesa->buf, Light0SpecularIntensityBlue, params[2]); + WRITEF(gmesa->buf, Light0SpecularIntensityGreen, params[1]); + WRITEF(gmesa->buf, Light0SpecularIntensityRed, params[0]); + break; + case GL_POSITION: + /* Normalize <x,y,z> */ + x = params[0]; y = params[1]; z = params[2]; w = params[3]; + l = sqrt(x*x + y*y + z*z + w*w); + w /= l; + x /= l; + y /= l; + z /= l; + if (params[3] != 0.0) { + gmesa->Light0Mode |= Light0ModeAttenuation; + gmesa->Light0Mode |= Light0ModeLocal; + } else { + gmesa->Light0Mode &= ~Light0ModeAttenuation; + gmesa->Light0Mode &= ~Light0ModeLocal; + } + CHECK_DMA_BUFFER(gmesa, 5); + WRITE(gmesa->buf, Light0Mode, gmesa->Light0Mode); + WRITEF(gmesa->buf, Light0PositionW, w); + WRITEF(gmesa->buf, Light0PositionZ, z); + WRITEF(gmesa->buf, Light0PositionY, y); + WRITEF(gmesa->buf, Light0PositionX, x); + break; + case GL_SPOT_DIRECTION: + CHECK_DMA_BUFFER(gmesa, 3); + /* WRITEF(gmesa->buf, Light0SpotlightDirectionW, params[3]); */ + WRITEF(gmesa->buf, Light0SpotlightDirectionZ, params[2]); + WRITEF(gmesa->buf, Light0SpotlightDirectionY, params[1]); + WRITEF(gmesa->buf, Light0SpotlightDirectionX, params[0]); + break; + case GL_SPOT_EXPONENT: + CHECK_DMA_BUFFER(gmesa, 1); + WRITEF(gmesa->buf, Light0SpotlightExponent, params[0]); + break; + case GL_SPOT_CUTOFF: + if (params[0] != 180.0) + gmesa->Light0Mode |= Light0ModeSpotLight; + else + gmesa->Light0Mode &= ~Light0ModeSpotLight; + CHECK_DMA_BUFFER(gmesa, 2); + WRITE(gmesa->buf, Light0Mode, gmesa->Light0Mode); + WRITEF(gmesa->buf, Light0CosSpotlightCutoffAngle, cos(params[0]*DEG2RAD)); + break; + case GL_CONSTANT_ATTENUATION: + CHECK_DMA_BUFFER(gmesa, 1); + WRITEF(gmesa->buf, Light0ConstantAttenuation, params[0]); + break; + case GL_LINEAR_ATTENUATION: + CHECK_DMA_BUFFER(gmesa, 1); + WRITEF(gmesa->buf, Light0LinearAttenuation, params[0]); + break; + case GL_QUADRATIC_ATTENUATION: + CHECK_DMA_BUFFER(gmesa, 1); + WRITEF(gmesa->buf, Light0QuadraticAttenuation, params[0]); + break; + } + break; + } +} + +static void gammaDDLightModelfv( GLcontext *ctx, GLenum pname, + const GLfloat *params ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + switch (pname) { + case GL_LIGHT_MODEL_AMBIENT: + CHECK_DMA_BUFFER(gmesa, 3); + /* We don't do alpha */ + WRITEF(gmesa->buf, SceneAmbientColorBlue, params[2]); + WRITEF(gmesa->buf, SceneAmbientColorGreen, params[1]); + WRITEF(gmesa->buf, SceneAmbientColorRed, params[0]); + break; + case GL_LIGHT_MODEL_LOCAL_VIEWER: + if (params[0] != 0.0) + gmesa->LightingMode |= LightingModeLocalViewer; + else + gmesa->LightingMode &= ~LightingModeLocalViewer; + CHECK_DMA_BUFFER(gmesa, 1); + WRITE(gmesa->buf, LightingMode, gmesa->LightingMode); + break; + case GL_LIGHT_MODEL_TWO_SIDE: + if (params[0] == 1.0f) { + gmesa->LightingMode |= LightingModeTwoSides; + gmesa->MaterialMode |= MaterialModeTwoSides; + } else { + gmesa->LightingMode &= ~LightingModeTwoSides; + gmesa->MaterialMode &= ~MaterialModeTwoSides; + } + CHECK_DMA_BUFFER(gmesa, 2); + WRITE(gmesa->buf, LightingMode, gmesa->LightingMode); + WRITE(gmesa->buf, MaterialMode, gmesa->MaterialMode); + break; + } +} + +static void gammaDDShadeModel( GLcontext *ctx, GLenum mode ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + CARD32 g = gmesa->GeometryMode; + CARD32 c = gmesa->ColorDDAMode; + + g &= ~GM_ShadingMask; + c &= ~ColorDDAShadingMask; + + switch ( mode ) { + case GL_FLAT: + g |= GM_FlatShading; + c |= ColorDDAFlat; + break; + case GL_SMOOTH: + g |= GM_GouraudShading; + c |= ColorDDAGouraud; + break; + default: + return; + } + + if ( gmesa->ColorDDAMode != c ) { + FLUSH_BATCH( gmesa ); + gmesa->ColorDDAMode = c; + + gmesa->dirty |= GAMMA_UPLOAD_SHADE; + } + + if ( gmesa->GeometryMode != g ) { + FLUSH_BATCH( gmesa ); + gmesa->GeometryMode = g; + + gmesa->dirty |= GAMMA_UPLOAD_GEOMETRY; + } +} + +/* ============================================================= + * Miscellaneous + */ + +static void gammaDDClearColor( GLcontext *ctx, const GLchan color[4]) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + gmesa->ClearColor = gammaPackColor( gmesa->gammaScreen->cpp, + color[0], color[1], color[2], color[3] ); + + if (gmesa->gammaScreen->cpp == 2) gmesa->ClearColor |= gmesa->ClearColor<<16; +} + + +static void gammaDDLogicalOpcode( GLcontext *ctx, GLenum opcode ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + FLUSH_BATCH( gmesa ); + + if ( ctx->Color.ColorLogicOpEnabled ) { + gmesa->LogicalOpMode = opcode << 1 | LogicalOpModeEnable; + } else { + gmesa->LogicalOpMode = LogicalOpModeDisable; + } + + gmesa->dirty |= GAMMA_UPLOAD_LOGICOP; +} + +static GLboolean gammaDDSetDrawBuffer( GLcontext *ctx, GLenum mode ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + FLUSH_BATCH( gmesa ); + + switch ( mode ) { + case GL_FRONT_LEFT: + gmesa->drawOffset = gmesa->readOffset = 0; + break; + case GL_BACK_LEFT: + gmesa->drawOffset = gmesa->readOffset = gmesa->driScreen->fbHeight * gmesa->driScreen->fbWidth * gmesa->gammaScreen->cpp; + break; + } + + return GL_TRUE; +} + +/* ============================================================= + * Window position and viewport transformation + */ + +void gammaUpdateWindow( GLcontext *ctx ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + __DRIdrawablePrivate *dPriv = gmesa->driDrawable; + GLfloat xoffset = (GLfloat)dPriv->x; + GLfloat yoffset = gmesa->driScreen->fbHeight - (GLfloat)dPriv->y - dPriv->h; + const GLfloat *v = ctx->Viewport._WindowMap.m; + + GLfloat sx = v[MAT_SX]; + GLfloat tx = v[MAT_TX] + xoffset; + GLfloat sy = v[MAT_SY]; + GLfloat ty = v[MAT_TY] + yoffset; + GLfloat sz = v[MAT_SZ] * gmesa->depth_scale; + GLfloat tz = v[MAT_TZ] * gmesa->depth_scale; + + gmesa->dirty |= GAMMA_UPLOAD_VIEWPORT; + + gmesa->ViewportScaleX = sx; + gmesa->ViewportScaleY = sy; + gmesa->ViewportScaleZ = sz; + gmesa->ViewportOffsetX = tx; + gmesa->ViewportOffsetY = ty; + gmesa->ViewportOffsetZ = tz; +} + + + +static void gammaDDViewport( GLcontext *ctx, GLint x, GLint y, + GLsizei width, GLsizei height ) +{ + gammaUpdateWindow( ctx ); +} + +static void gammaDDDepthRange( GLcontext *ctx, GLclampd nearval, + GLclampd farval ) +{ + gammaUpdateWindow( ctx ); +} + +void gammaUpdateViewportOffset( GLcontext *ctx ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + __DRIdrawablePrivate *dPriv = gmesa->driDrawable; + GLfloat xoffset = (GLfloat)dPriv->x; + GLfloat yoffset = gmesa->driScreen->fbHeight - (GLfloat)dPriv->y - dPriv->h; + const GLfloat *v = ctx->Viewport._WindowMap.m; + + GLfloat tx = v[MAT_TX] + xoffset; + GLfloat ty = v[MAT_TY] + yoffset; + + if ( gmesa->ViewportOffsetX != tx || + gmesa->ViewportOffsetY != ty ) + { + gmesa->ViewportOffsetX = tx; + gmesa->ViewportOffsetY = ty; + + gmesa->new_state |= GAMMA_NEW_WINDOW; + } + + gmesa->new_state |= GAMMA_NEW_CLIP; +} + +/* + * Matrix + */ + +static void gammaLoadHWMatrix(GLcontext *ctx) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + gmesa->TransformMode &= ~XM_XformTexture; + + switch (ctx->Transform.MatrixMode) { + case GL_MODELVIEW: + gmesa->TransformMode |= XM_UseModelViewMatrix; + CHECK_DMA_BUFFER(gmesa, 16); + WRITEF(gmesa->buf, ModelViewMatrix0, ctx->ModelView.m[0]); + WRITEF(gmesa->buf, ModelViewMatrix1, ctx->ModelView.m[1]); + WRITEF(gmesa->buf, ModelViewMatrix2, ctx->ModelView.m[2]); + WRITEF(gmesa->buf, ModelViewMatrix3, ctx->ModelView.m[3]); + WRITEF(gmesa->buf, ModelViewMatrix4, ctx->ModelView.m[4]); + WRITEF(gmesa->buf, ModelViewMatrix5, ctx->ModelView.m[5]); + WRITEF(gmesa->buf, ModelViewMatrix6, ctx->ModelView.m[6]); + WRITEF(gmesa->buf, ModelViewMatrix7, ctx->ModelView.m[7]); + WRITEF(gmesa->buf, ModelViewMatrix8, ctx->ModelView.m[8]); + WRITEF(gmesa->buf, ModelViewMatrix9, ctx->ModelView.m[9]); + WRITEF(gmesa->buf, ModelViewMatrix10, ctx->ModelView.m[10]); + WRITEF(gmesa->buf, ModelViewMatrix11, ctx->ModelView.m[11]); + WRITEF(gmesa->buf, ModelViewMatrix12, ctx->ModelView.m[12]); + WRITEF(gmesa->buf, ModelViewMatrix13, ctx->ModelView.m[13]); + WRITEF(gmesa->buf, ModelViewMatrix14, ctx->ModelView.m[14]); + WRITEF(gmesa->buf, ModelViewMatrix15, ctx->ModelView.m[15]); + break; + case GL_PROJECTION: + CHECK_DMA_BUFFER(gmesa, 16); + WRITEF(gmesa->buf, ModelViewProjectionMatrix0, + ctx->ProjectionMatrix.m[0]); + WRITEF(gmesa->buf, ModelViewProjectionMatrix1, + ctx->ProjectionMatrix.m[1]); + WRITEF(gmesa->buf, ModelViewProjectionMatrix2, + ctx->ProjectionMatrix.m[2]); + WRITEF(gmesa->buf, ModelViewProjectionMatrix3, + ctx->ProjectionMatrix.m[3]); + WRITEF(gmesa->buf, ModelViewProjectionMatrix4, + ctx->ProjectionMatrix.m[4]); + WRITEF(gmesa->buf, ModelViewProjectionMatrix5, + ctx->ProjectionMatrix.m[5]); + WRITEF(gmesa->buf, ModelViewProjectionMatrix6, + ctx->ProjectionMatrix.m[6]); + WRITEF(gmesa->buf, ModelViewProjectionMatrix7, + ctx->ProjectionMatrix.m[7]); + WRITEF(gmesa->buf, ModelViewProjectionMatrix8, + ctx->ProjectionMatrix.m[8]); + WRITEF(gmesa->buf, ModelViewProjectionMatrix9, + ctx->ProjectionMatrix.m[9]); + WRITEF(gmesa->buf, ModelViewProjectionMatrix10, + ctx->ProjectionMatrix.m[10]); + WRITEF(gmesa->buf, ModelViewProjectionMatrix11, + ctx->ProjectionMatrix.m[11]); + WRITEF(gmesa->buf, ModelViewProjectionMatrix12, + ctx->ProjectionMatrix.m[12]); + WRITEF(gmesa->buf, ModelViewProjectionMatrix13, + ctx->ProjectionMatrix.m[13]); + WRITEF(gmesa->buf, ModelViewProjectionMatrix14, + ctx->ProjectionMatrix.m[14]); + WRITEF(gmesa->buf, ModelViewProjectionMatrix15, + ctx->ProjectionMatrix.m[15]); + break; + case GL_TEXTURE: + CHECK_DMA_BUFFER(gmesa, 16); + gmesa->TransformMode |= XM_XformTexture; + WRITEF(gmesa->buf, TextureMatrix0, ctx->TextureMatrix[0].m[0]); + WRITEF(gmesa->buf, TextureMatrix1, ctx->TextureMatrix[0].m[1]); + WRITEF(gmesa->buf, TextureMatrix2, ctx->TextureMatrix[0].m[2]); + WRITEF(gmesa->buf, TextureMatrix3, ctx->TextureMatrix[0].m[3]); + WRITEF(gmesa->buf, TextureMatrix4, ctx->TextureMatrix[0].m[4]); + WRITEF(gmesa->buf, TextureMatrix5, ctx->TextureMatrix[0].m[5]); + WRITEF(gmesa->buf, TextureMatrix6, ctx->TextureMatrix[0].m[6]); + WRITEF(gmesa->buf, TextureMatrix7, ctx->TextureMatrix[0].m[7]); + WRITEF(gmesa->buf, TextureMatrix8, ctx->TextureMatrix[0].m[8]); + WRITEF(gmesa->buf, TextureMatrix9, ctx->TextureMatrix[0].m[9]); + WRITEF(gmesa->buf, TextureMatrix10, ctx->TextureMatrix[0].m[10]); + WRITEF(gmesa->buf, TextureMatrix11, ctx->TextureMatrix[0].m[11]); + WRITEF(gmesa->buf, TextureMatrix12, ctx->TextureMatrix[0].m[12]); + WRITEF(gmesa->buf, TextureMatrix13, ctx->TextureMatrix[0].m[13]); + WRITEF(gmesa->buf, TextureMatrix14, ctx->TextureMatrix[0].m[14]); + WRITEF(gmesa->buf, TextureMatrix15, ctx->TextureMatrix[0].m[15]); + break; + + default: + /* ERROR!!! -- how did this happen? */ + break; + } + + gmesa->dirty |= GAMMA_UPLOAD_TRANSFORM; +} + +/* ============================================================= + * State enable/disable + */ + +static void gammaDDEnable( GLcontext *ctx, GLenum cap, GLboolean state ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + switch ( cap ) { + case GL_ALPHA_TEST: + case GL_BLEND: + FLUSH_BATCH( gmesa ); + gmesa->new_state |= GAMMA_NEW_ALPHA; + break; + + case GL_CULL_FACE: + FLUSH_BATCH( gmesa ); + gmesa->new_state |= GAMMA_NEW_CULL; + break; + + case GL_DEPTH_TEST: + FLUSH_BATCH( gmesa ); + gmesa->new_state |= GAMMA_NEW_DEPTH; + break; + + case GL_DITHER: + do { + CARD32 d = gmesa->DitherMode; + FLUSH_BATCH( gmesa ); + + if ( state ) { + d |= DM_DitherEnable; + } else { + d &= ~DM_DitherEnable; + } + + if ( gmesa->DitherMode != d ) { + gmesa->DitherMode = d; + gmesa->dirty |= GAMMA_UPLOAD_DITHER; + } + } while (0); + break; + +#if 0 + case GL_FOG: + FLUSH_BATCH( gmesa ); + gmesa->new_state |= GAMMA_NEW_FOG; + break; +#endif + + case GL_INDEX_LOGIC_OP: + case GL_COLOR_LOGIC_OP: + FLUSH_BATCH( gmesa ); + gmesa->new_state |= GAMMA_NEW_LOGICOP; + break; + +#if ENABLELIGHTING + case GL_LIGHTING: + do { + CARD32 l = gmesa->LightingMode; + FLUSH_BATCH( gmesa ); + + if ( state ) { + l |= LightingModeEnable; + } else { + l &= ~LightingModeEnable; + } + + if ( gmesa->LightingMode != l ) { + gmesa->LightingMode = l; + gmesa->dirty |= GAMMA_UPLOAD_LIGHT; + } + } while (0); + break; + + case GL_COLOR_MATERIAL: + do { + CARD32 m = gmesa->MaterialMode; + FLUSH_BATCH( gmesa ); + + if ( state ) { + m |= MaterialModeEnable; + } else { + m &= ~MaterialModeEnable; + } + + if ( gmesa->MaterialMode != m ) { + gmesa->MaterialMode = m; + gmesa->dirty |= GAMMA_UPLOAD_LIGHT; + } + } while (0); + break; +#endif + + case GL_LINE_SMOOTH: + FLUSH_BATCH( gmesa ); + if ( state ) { + gmesa->AntialiasMode |= AntialiasModeEnable; + gmesa->LineMode |= LM_AntialiasEnable; + } else { + gmesa->AntialiasMode &= ~AntialiasModeEnable; + gmesa->LineMode &= ~LM_AntialiasEnable; + } + gmesa->dirty |= GAMMA_UPLOAD_LINEMODE; + break; + + case GL_POINT_SMOOTH: + FLUSH_BATCH( gmesa ); + if ( state ) { + gmesa->AntialiasMode |= AntialiasModeEnable; + gmesa->PointMode |= PM_AntialiasEnable; + } else { + gmesa->AntialiasMode &= ~AntialiasModeEnable; + gmesa->PointMode &= ~PM_AntialiasEnable; + } + gmesa->dirty |= GAMMA_UPLOAD_POINTMODE; + break; + + case GL_POLYGON_SMOOTH: + FLUSH_BATCH( gmesa ); + if ( state ) { + gmesa->AntialiasMode |= AntialiasModeEnable; + gmesa->TriangleMode |= TM_AntialiasEnable; + } else { + gmesa->AntialiasMode &= ~AntialiasModeEnable; + gmesa->TriangleMode &= ~TM_AntialiasEnable; + } + gmesa->dirty |= GAMMA_UPLOAD_TRIMODE; + break; + + case GL_SCISSOR_TEST: + FLUSH_BATCH( gmesa ); + gmesa->new_state |= GAMMA_NEW_CLIP; + break; + + case GL_POLYGON_OFFSET_FILL: + case GL_POLYGON_OFFSET_POINT: + case GL_POLYGON_OFFSET_LINE: + FLUSH_BATCH( gmesa ); + gmesa->new_state |= GAMMA_NEW_POLYGON; + break; + + case GL_LINE_STIPPLE: + FLUSH_BATCH( gmesa ); + if ( state ) + gmesa->LineMode |= LM_StippleEnable; + else + gmesa->LineMode &= ~LM_StippleEnable; + gmesa->dirty |= GAMMA_UPLOAD_LINEMODE; + break; + + case GL_POLYGON_STIPPLE: + FLUSH_BATCH( gmesa ); + gmesa->new_state |= GAMMA_NEW_STIPPLE; + break; + + default: + return; + } +} + +/* ============================================================= + * State initialization, management + */ + + +/* + * Load the current context's state into the hardware. + * + * NOTE: Be VERY careful about ensuring the context state is marked for + * upload, the only place it shouldn't be uploaded is when the setup + * state has changed in ReducedPrimitiveChange as this comes right after + * a state update. + * + * Blits of any type should always upload the context and masks after + * they are done. + */ +void gammaEmitHwState( gammaContextPtr gmesa ) +{ + if (!gmesa->driDrawable) return; + + if (!gmesa->dirty) return; + +#ifdef DO_VALIDATE + /* Flush any partially filled buffers */ + FLUSH_DMA_BUFFER(gmesa); + + DRM_SPINLOCK(&gmesa->driScreen->pSAREA->drawable_lock, + gmesa->driScreen->drawLockID); + VALIDATE_DRAWABLE_INFO_NO_LOCK(gmesa); +#endif + + if (gmesa->dirty & GAMMA_UPLOAD_VIEWPORT) { + gmesa->dirty &= ~GAMMA_UPLOAD_VIEWPORT; + CHECK_DMA_BUFFER(gmesa, 6); + WRITEF(gmesa->buf, ViewPortOffsetX, gmesa->ViewportOffsetX); + WRITEF(gmesa->buf, ViewPortOffsetY, gmesa->ViewportOffsetY); + WRITEF(gmesa->buf, ViewPortOffsetZ, gmesa->ViewportOffsetZ); + WRITEF(gmesa->buf, ViewPortScaleX, gmesa->ViewportScaleX); + WRITEF(gmesa->buf, ViewPortScaleY, gmesa->ViewportScaleY); + WRITEF(gmesa->buf, ViewPortScaleZ, gmesa->ViewportScaleZ); + } + if ( (gmesa->dirty & GAMMA_UPLOAD_POINTMODE) || + (gmesa->dirty & GAMMA_UPLOAD_LINEMODE) || + (gmesa->dirty & GAMMA_UPLOAD_TRIMODE) ) { + CHECK_DMA_BUFFER(gmesa, 1); + WRITE(gmesa->buf, AntialiasMode, gmesa->AntialiasMode); + } + if (gmesa->dirty & GAMMA_UPLOAD_POINTMODE) { + gmesa->dirty &= ~GAMMA_UPLOAD_POINTMODE; + CHECK_DMA_BUFFER(gmesa, 1); + WRITE(gmesa->buf, PointMode, gmesa->PointMode); + } + if (gmesa->dirty & GAMMA_UPLOAD_LINEMODE) { + gmesa->dirty &= ~GAMMA_UPLOAD_LINEMODE; + CHECK_DMA_BUFFER(gmesa, 2); + WRITE(gmesa->buf, LineMode, gmesa->LineMode); + WRITE(gmesa->buf, LineStippleMode, gmesa->LineMode); + } + if (gmesa->dirty & GAMMA_UPLOAD_TRIMODE) { + gmesa->dirty &= ~GAMMA_UPLOAD_TRIMODE; + CHECK_DMA_BUFFER(gmesa, 1); + WRITE(gmesa->buf, TriangleMode, gmesa->TriangleMode); + } + if (gmesa->dirty & GAMMA_UPLOAD_FOG) { + GLchan c[3], col; + UNCLAMPED_FLOAT_TO_RGB_CHAN( c, gmesa->glCtx->Fog.Color ); + col = gammaPackColor(4, c[0], c[1], c[2], 0); + gmesa->dirty &= ~GAMMA_UPLOAD_FOG; + CHECK_DMA_BUFFER(gmesa, 5); +#if 0 + WRITE(gmesa->buf, FogMode, gmesa->FogMode); + WRITE(gmesa->buf, FogColor, col); + WRITEF(gmesa->buf, FStart, gmesa->glCtx->Fog.Start); +#endif + WRITEF(gmesa->buf, FogEnd, gmesa->glCtx->Fog.End); + WRITEF(gmesa->buf, FogDensity, gmesa->glCtx->Fog.Density); + WRITEF(gmesa->buf, FogScale, + 1.0f/(gmesa->glCtx->Fog.End - gmesa->glCtx->Fog.Start)); + } + if (gmesa->dirty & GAMMA_UPLOAD_DITHER) { + gmesa->dirty &= ~GAMMA_UPLOAD_DITHER; + CHECK_DMA_BUFFER(gmesa, 1); + WRITE(gmesa->buf, DitherMode, gmesa->DitherMode); + } + if (gmesa->dirty & GAMMA_UPLOAD_LOGICOP) { + gmesa->dirty &= ~GAMMA_UPLOAD_LOGICOP; + CHECK_DMA_BUFFER(gmesa, 1); + WRITE(gmesa->buf, LogicalOpMode, gmesa->LogicalOpMode); + } + if (gmesa->dirty & GAMMA_UPLOAD_CLIP) { + gmesa->dirty &= ~GAMMA_UPLOAD_CLIP; + CHECK_DMA_BUFFER(gmesa, 3); + WRITE(gmesa->buf, ScissorMinXY, gmesa->ScissorMinXY); + WRITE(gmesa->buf, ScissorMaxXY, gmesa->ScissorMaxXY); + WRITE(gmesa->buf, ScissorMode, gmesa->ScissorMode); + } + if (gmesa->dirty & GAMMA_UPLOAD_MASKS) { + gmesa->dirty &= ~GAMMA_UPLOAD_MASKS; + CHECK_DMA_BUFFER(gmesa, 1); + WRITE(gmesa->buf, FBHardwareWriteMask, gmesa->FBHardwareWriteMask); + } + if (gmesa->dirty & GAMMA_UPLOAD_ALPHA) { + gmesa->dirty &= ~GAMMA_UPLOAD_ALPHA; + CHECK_DMA_BUFFER(gmesa, 1); + WRITE(gmesa->buf, AlphaTestMode, gmesa->AlphaTestMode); + } + if (gmesa->dirty & GAMMA_UPLOAD_BLEND) { + gmesa->dirty &= ~GAMMA_UPLOAD_BLEND; + CHECK_DMA_BUFFER(gmesa, 1); + WRITE(gmesa->buf, AlphaBlendMode, gmesa->AlphaBlendMode); + } + CHECK_DMA_BUFFER(gmesa, 1); + if (gmesa->glCtx->Color.BlendEnabled || gmesa->glCtx->Color.AlphaEnabled) { + WRITE(gmesa->buf, FBReadMode, gmesa->FBReadMode | gmesa->AB_FBReadMode_Save); + } else { + WRITE(gmesa->buf, FBReadMode, gmesa->FBReadMode); + } + if (gmesa->dirty & GAMMA_UPLOAD_LIGHT) { + gmesa->dirty &= ~GAMMA_UPLOAD_LIGHT; + CHECK_DMA_BUFFER(gmesa, 2); + WRITE(gmesa->buf, LightingMode, gmesa->LightingMode); + WRITE(gmesa->buf, MaterialMode, gmesa->MaterialMode); + } + if (gmesa->dirty & GAMMA_UPLOAD_SHADE) { + gmesa->dirty &= ~GAMMA_UPLOAD_SHADE; + CHECK_DMA_BUFFER(gmesa, 1); + WRITE(gmesa->buf, ColorDDAMode, gmesa->ColorDDAMode); + } + if (gmesa->dirty & GAMMA_UPLOAD_POLYGON) { + gmesa->dirty &= ~GAMMA_UPLOAD_POLYGON; + CHECK_DMA_BUFFER(gmesa, 2); + WRITEF(gmesa->buf, PolygonOffsetBias, gmesa->glCtx->Polygon.OffsetUnits); + WRITEF(gmesa->buf, PolygonOffsetFactor, gmesa->glCtx->Polygon.OffsetFactor); + } + if (gmesa->dirty & GAMMA_UPLOAD_STIPPLE) { + gmesa->dirty &= ~GAMMA_UPLOAD_STIPPLE; + CHECK_DMA_BUFFER(gmesa, 33); + WRITE(gmesa->buf, AreaStippleMode, gmesa->AreaStippleMode); + WRITE(gmesa->buf, AreaStipplePattern0, gmesa->glCtx->PolygonStipple[0]); + WRITE(gmesa->buf, AreaStipplePattern1, gmesa->glCtx->PolygonStipple[1]); + WRITE(gmesa->buf, AreaStipplePattern2, gmesa->glCtx->PolygonStipple[2]); + WRITE(gmesa->buf, AreaStipplePattern3, gmesa->glCtx->PolygonStipple[3]); + WRITE(gmesa->buf, AreaStipplePattern4, gmesa->glCtx->PolygonStipple[4]); + WRITE(gmesa->buf, AreaStipplePattern5, gmesa->glCtx->PolygonStipple[5]); + WRITE(gmesa->buf, AreaStipplePattern6, gmesa->glCtx->PolygonStipple[6]); + WRITE(gmesa->buf, AreaStipplePattern7, gmesa->glCtx->PolygonStipple[7]); + WRITE(gmesa->buf, AreaStipplePattern8, gmesa->glCtx->PolygonStipple[8]); + WRITE(gmesa->buf, AreaStipplePattern9, gmesa->glCtx->PolygonStipple[9]); + WRITE(gmesa->buf, AreaStipplePattern10, gmesa->glCtx->PolygonStipple[10]); + WRITE(gmesa->buf, AreaStipplePattern11, gmesa->glCtx->PolygonStipple[11]); + WRITE(gmesa->buf, AreaStipplePattern12, gmesa->glCtx->PolygonStipple[12]); + WRITE(gmesa->buf, AreaStipplePattern13, gmesa->glCtx->PolygonStipple[13]); + WRITE(gmesa->buf, AreaStipplePattern14, gmesa->glCtx->PolygonStipple[14]); + WRITE(gmesa->buf, AreaStipplePattern15, gmesa->glCtx->PolygonStipple[15]); + WRITE(gmesa->buf, AreaStipplePattern16, gmesa->glCtx->PolygonStipple[16]); + WRITE(gmesa->buf, AreaStipplePattern17, gmesa->glCtx->PolygonStipple[17]); + WRITE(gmesa->buf, AreaStipplePattern18, gmesa->glCtx->PolygonStipple[18]); + WRITE(gmesa->buf, AreaStipplePattern19, gmesa->glCtx->PolygonStipple[19]); + WRITE(gmesa->buf, AreaStipplePattern20, gmesa->glCtx->PolygonStipple[20]); + WRITE(gmesa->buf, AreaStipplePattern21, gmesa->glCtx->PolygonStipple[21]); + WRITE(gmesa->buf, AreaStipplePattern22, gmesa->glCtx->PolygonStipple[22]); + WRITE(gmesa->buf, AreaStipplePattern23, gmesa->glCtx->PolygonStipple[23]); + WRITE(gmesa->buf, AreaStipplePattern24, gmesa->glCtx->PolygonStipple[24]); + WRITE(gmesa->buf, AreaStipplePattern25, gmesa->glCtx->PolygonStipple[25]); + WRITE(gmesa->buf, AreaStipplePattern26, gmesa->glCtx->PolygonStipple[26]); + WRITE(gmesa->buf, AreaStipplePattern27, gmesa->glCtx->PolygonStipple[27]); + WRITE(gmesa->buf, AreaStipplePattern28, gmesa->glCtx->PolygonStipple[28]); + WRITE(gmesa->buf, AreaStipplePattern29, gmesa->glCtx->PolygonStipple[29]); + WRITE(gmesa->buf, AreaStipplePattern30, gmesa->glCtx->PolygonStipple[30]); + WRITE(gmesa->buf, AreaStipplePattern31, gmesa->glCtx->PolygonStipple[31]); + } + if (gmesa->dirty & GAMMA_UPLOAD_DEPTH) { + gmesa->dirty &= ~GAMMA_UPLOAD_DEPTH; + CHECK_DMA_BUFFER(gmesa, 4); + WRITE(gmesa->buf, DepthMode, gmesa->DepthMode); + WRITE(gmesa->buf, DeltaMode, gmesa->DeltaMode); + WRITE(gmesa->buf, GLINTWindow,gmesa->Window | (gmesa->FrameCount << 9)); + WRITE(gmesa->buf, LBReadMode, gmesa->LBReadMode); + } + if (gmesa->dirty & GAMMA_UPLOAD_GEOMETRY) { + gmesa->dirty &= ~GAMMA_UPLOAD_GEOMETRY; + CHECK_DMA_BUFFER(gmesa, 1); + WRITE(gmesa->buf, GeometryMode, gmesa->GeometryMode); + } + if (gmesa->dirty & GAMMA_UPLOAD_TRANSFORM) { + gmesa->dirty &= ~GAMMA_UPLOAD_TRANSFORM; + CHECK_DMA_BUFFER(gmesa, 1); + WRITE(gmesa->buf, TransformMode, gmesa->TransformMode); + } + if (gmesa->dirty & GAMMA_UPLOAD_TEX0) { + gammaTextureObjectPtr curTex = gmesa->CurrentTexObj[0]; + gmesa->dirty &= ~GAMMA_UPLOAD_TEX0; + if (curTex) { + CHECK_DMA_BUFFER(gmesa, 21); + WRITE(gmesa->buf, GeometryMode, gmesa->GeometryMode | GM_TextureEnable); + WRITE(gmesa->buf, DeltaMode, gmesa->DeltaMode | DM_TextureEnable); + WRITE(gmesa->buf, TextureAddressMode, curTex->TextureAddressMode); + WRITE(gmesa->buf, TextureReadMode, curTex->TextureReadMode); + WRITE(gmesa->buf, TextureColorMode, curTex->TextureColorMode); + WRITE(gmesa->buf, TextureFilterMode, curTex->TextureFilterMode); + WRITE(gmesa->buf, TextureFormat, curTex->TextureFormat); + WRITE(gmesa->buf, GLINTBorderColor, curTex->TextureBorderColor); + WRITE(gmesa->buf, TxBaseAddr0, curTex->TextureBaseAddr[0]); + WRITE(gmesa->buf, TxBaseAddr1, curTex->TextureBaseAddr[1]); + WRITE(gmesa->buf, TxBaseAddr2, curTex->TextureBaseAddr[2]); + WRITE(gmesa->buf, TxBaseAddr3, curTex->TextureBaseAddr[3]); + WRITE(gmesa->buf, TxBaseAddr4, curTex->TextureBaseAddr[4]); + WRITE(gmesa->buf, TxBaseAddr5, curTex->TextureBaseAddr[5]); + WRITE(gmesa->buf, TxBaseAddr6, curTex->TextureBaseAddr[6]); + WRITE(gmesa->buf, TxBaseAddr7, curTex->TextureBaseAddr[7]); + WRITE(gmesa->buf, TxBaseAddr8, curTex->TextureBaseAddr[8]); + WRITE(gmesa->buf, TxBaseAddr9, curTex->TextureBaseAddr[9]); + WRITE(gmesa->buf, TxBaseAddr10, curTex->TextureBaseAddr[10]); + WRITE(gmesa->buf, TxBaseAddr11, curTex->TextureBaseAddr[11]); + WRITE(gmesa->buf, TxBaseAddr12, curTex->TextureBaseAddr[12]); + WRITE(gmesa->buf, TextureCacheControl, (TCC_Enable | TCC_Invalidate)); + } else { + CHECK_DMA_BUFFER(gmesa, 6); + WRITE(gmesa->buf, GeometryMode, gmesa->GeometryMode); + WRITE(gmesa->buf, DeltaMode, gmesa->DeltaMode); + WRITE(gmesa->buf, TextureAddressMode, TextureAddressModeDisable); + WRITE(gmesa->buf, TextureReadMode, TextureReadModeDisable); + WRITE(gmesa->buf, TextureFilterMode, TextureFilterModeDisable); + WRITE(gmesa->buf, TextureColorMode, TextureColorModeDisable); + } + } +#ifdef DO_VALIDATE + PROCESS_DMA_BUFFER_TOP_HALF(gmesa); + + DRM_SPINUNLOCK(&gmesa->driScreen->pSAREA->drawable_lock, + gmesa->driScreen->drawLockID); + VALIDATE_DRAWABLE_INFO_NO_LOCK_POST(gmesa); + + PROCESS_DMA_BUFFER_BOTTOM_HALF(gmesa); +#endif +} + +void gammaDDUpdateHWState( GLcontext *ctx ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + int new_state = gmesa->new_state; + + if ( new_state ) + { + FLUSH_BATCH( gmesa ); + + gmesa->new_state = 0; + + /* Update the various parts of the context's state. + */ + if ( new_state & GAMMA_NEW_ALPHA ) + gammaUpdateAlphaMode( ctx ); + + if ( new_state & GAMMA_NEW_DEPTH ) + gammaUpdateZMode( ctx ); + + if ( new_state & GAMMA_NEW_FOG ) + gammaUpdateFogAttrib( ctx ); + + if ( new_state & GAMMA_NEW_CLIP ) + gammaUpdateClipping( ctx ); + + if ( new_state & GAMMA_NEW_POLYGON ) + gammaUpdatePolygon( ctx ); + + if ( new_state & GAMMA_NEW_CULL ) + gammaUpdateCull( ctx ); + + if ( new_state & GAMMA_NEW_MASKS ) + gammaUpdateMasks( ctx ); + + if ( new_state & GAMMA_NEW_WINDOW ) + gammaUpdateWindow( ctx ); + + if ( new_state & GAMMA_NEW_STIPPLE ) + gammaUpdateStipple( ctx ); + } + + /* HACK ! */ + + gammaEmitHwState( gmesa ); +} + + +void gammaDDUpdateState( GLcontext *ctx, GLuint new_state ) +{ + _swrast_InvalidateState( ctx, new_state ); + _swsetup_InvalidateState( ctx, new_state ); + _ac_InvalidateState( ctx, new_state ); + _tnl_InvalidateState( ctx, new_state ); + GAMMA_CONTEXT(ctx)->new_gl_state |= new_state; +} + + +/* Initialize the context's hardware state. + */ +void gammaDDInitState( gammaContextPtr gmesa ) +{ + gmesa->new_state = 0; +} + +/* Initialize the driver's state functions. + */ +void gammaDDInitStateFuncs( GLcontext *ctx ) +{ + ctx->Driver.UpdateState = gammaDDUpdateState; + + ctx->Driver.Clear = gammaDDClear; + ctx->Driver.ClearIndex = NULL; + ctx->Driver.ClearColor = gammaDDClearColor; + ctx->Driver.SetDrawBuffer = gammaDDSetDrawBuffer; + + ctx->Driver.IndexMask = NULL; + ctx->Driver.ColorMask = gammaDDColorMask; + + ctx->Driver.AlphaFunc = gammaDDAlphaFunc; + ctx->Driver.BlendEquation = gammaDDBlendEquation; + ctx->Driver.BlendFunc = gammaDDBlendFunc; + ctx->Driver.BlendFuncSeparate = gammaDDBlendFuncSeparate; + ctx->Driver.ClearDepth = gammaDDClearDepth; + ctx->Driver.CullFace = gammaDDCullFace; + ctx->Driver.FrontFace = gammaDDFrontFace; + ctx->Driver.DepthFunc = gammaDDDepthFunc; + ctx->Driver.DepthMask = gammaDDDepthMask; + ctx->Driver.DepthRange = gammaDDDepthRange; + ctx->Driver.Enable = gammaDDEnable; + ctx->Driver.Finish = gammaDDFinish; + ctx->Driver.Flush = gammaDDFlush; +#if 0 + ctx->Driver.Fogfv = gammaDDFogfv; +#endif + ctx->Driver.Hint = NULL; + ctx->Driver.LineWidth = gammaDDLineWidth; + ctx->Driver.LineStipple = gammaDDLineStipple; +#if ENABLELIGHTING + ctx->Driver.Lightfv = gammaDDLightfv; + ctx->Driver.LightModelfv = gammaDDLightModelfv; +#endif + ctx->Driver.LogicOpcode = gammaDDLogicalOpcode; + ctx->Driver.PointSize = gammaDDPointSize; + ctx->Driver.PolygonMode = gammaDDPolygonMode; + ctx->Driver.PolygonStipple = gammaDDPolygonStipple; + ctx->Driver.Scissor = gammaDDScissor; + ctx->Driver.ShadeModel = gammaDDShadeModel; + ctx->Driver.ClearStencil = NULL; + ctx->Driver.StencilFunc = NULL; + ctx->Driver.StencilMask = NULL; + ctx->Driver.StencilOp = NULL; + ctx->Driver.Viewport = gammaDDViewport; +} diff --git a/xc/lib/GL/mesa/src/drv/gamma/gamma_vb.c b/xc/lib/GL/mesa/src/drv/gamma/gamma_vb.c new file mode 100644 index 000000000..13462b9aa --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/gamma/gamma_vb.c @@ -0,0 +1,380 @@ +/* + * Copyright 2001 by Alan Hourihane. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Alan Hourihane not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Alan Hourihane makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk> + * Keith Whitwell, <keithw@valinux.com> + * + * 3DLabs Gamma driver. + */ + +#include "glheader.h" +#include "mtypes.h" +#include "mem.h" +#include "macros.h" +#include "colormac.h" +#include "mmath.h" + +#include "swrast_setup/swrast_setup.h" +#include "tnl/t_context.h" +#include "tnl/tnl.h" + +#include "gamma_context.h" +#include "gamma_vb.h" +#include "gamma_tris.h" + + +#define GAMMA_TEX0_BIT 0x1 +#define GAMMA_RGBA_BIT 0x2 +#define GAMMA_XYZW_BIT 0x4 +#define GAMMA_PTEX_BIT 0x8 +#define GAMMA_FOG_BIT 0x10 +#define GAMMA_SPEC_BIT 0x20 +#define GAMMA_MAX_SETUP 0x40 + +static struct { + void (*emit)( GLcontext *, GLuint, GLuint, void *, GLuint ); + interp_func interp; + copy_pv_func copy_pv; + GLboolean (*check_tex_sizes)( GLcontext *ctx ); + GLuint vertex_size; + GLuint vertex_stride_shift; + GLuint vertex_format; +} setup_tab[GAMMA_MAX_SETUP]; + +#define TINY_VERTEX_FORMAT 1 +#define NOTEX_VERTEX_FORMAT 2 +#define TEX0_VERTEX_FORMAT 3 +#define TEX1_VERTEX_FORMAT 0 +#define PROJ_TEX1_VERTEX_FORMAT 0 +#define TEX2_VERTEX_FORMAT 0 +#define TEX3_VERTEX_FORMAT 0 +#define PROJ_TEX3_VERTEX_FORMAT 0 + +#define DO_XYZW (IND & GAMMA_XYZW_BIT) +#define DO_RGBA (IND & GAMMA_RGBA_BIT) +#define DO_SPEC (IND & GAMMA_SPEC_BIT) +#define DO_FOG (IND & GAMMA_FOG_BIT) +#define DO_TEX0 (IND & GAMMA_TEX0_BIT) +#define DO_TEX1 0 +#define DO_TEX2 0 +#define DO_TEX3 0 +#define DO_PTEX (IND & GAMMA_PTEX_BIT) + +#define VERTEX gammaVertex +#define VERTEX_COLOR gamma_color_t +#define GET_VIEWPORT_MAT() 0 +#define GET_TEXSOURCE(n) n +#define GET_VERTEX_FORMAT() GAMMA_CONTEXT(ctx)->vertex_format +#define GET_VERTEX_STORE() GAMMA_CONTEXT(ctx)->verts +#define GET_VERTEX_STRIDE_SHIFT() GAMMA_CONTEXT(ctx)->vertex_stride_shift +#define INVALIDATE_STORED_VERTICES() +#define GET_UBYTE_COLOR_STORE() &GAMMA_CONTEXT(ctx)->UbyteColor +#define GET_UBYTE_SPEC_COLOR_STORE() &GAMMA_CONTEXT(ctx)->UbyteSecondaryColor + +#define HAVE_HW_VIEWPORT 1 +#define HAVE_HW_DIVIDE 1 +#define HAVE_RGBA_COLOR 0 /* we're BGRA */ +#define HAVE_TINY_VERTICES 1 +#define HAVE_NOTEX_VERTICES 1 +#define HAVE_TEX0_VERTICES 1 +#define HAVE_TEX1_VERTICES 0 +#define HAVE_TEX2_VERTICES 0 +#define HAVE_TEX3_VERTICES 0 +#define HAVE_PTEX_VERTICES 1 + +#define PTEX_FALLBACK() /* never needed */ + +#define IMPORT_QUALIFIER +#define IMPORT_FLOAT_COLORS gamma_import_float_colors +#define IMPORT_FLOAT_SPEC_COLORS gamma_import_float_spec_colors + +#define INTERP_VERTEX setup_tab[GAMMA_CONTEXT(ctx)->SetupIndex].interp +#define COPY_PV_VERTEX setup_tab[GAMMA_CONTEXT(ctx)->SetupIndex].copy_pv + + + +/*********************************************************************** + * Generate pv-copying and translation functions * + ***********************************************************************/ + +#define TAG(x) gamma_##x +#include "tnl_dd/t_dd_vb.c" + +/*********************************************************************** + * Generate vertex emit and interp functions * + ***********************************************************************/ + +#define IND (GAMMA_XYZW_BIT|GAMMA_RGBA_BIT) +#define TAG(x) x##_wg +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (GAMMA_XYZW_BIT|GAMMA_RGBA_BIT|GAMMA_SPEC_BIT) +#define TAG(x) x##_wgs +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (GAMMA_XYZW_BIT|GAMMA_RGBA_BIT|GAMMA_TEX0_BIT) +#define TAG(x) x##_wgt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (GAMMA_XYZW_BIT|GAMMA_RGBA_BIT|GAMMA_TEX0_BIT|GAMMA_PTEX_BIT) +#define TAG(x) x##_wgpt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (GAMMA_XYZW_BIT|GAMMA_RGBA_BIT|GAMMA_SPEC_BIT|GAMMA_TEX0_BIT) +#define TAG(x) x##_wgst0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (GAMMA_XYZW_BIT|GAMMA_RGBA_BIT|GAMMA_SPEC_BIT|GAMMA_TEX0_BIT|\ + GAMMA_PTEX_BIT) +#define TAG(x) x##_wgspt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (GAMMA_XYZW_BIT|GAMMA_RGBA_BIT|GAMMA_FOG_BIT) +#define TAG(x) x##_wgf +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (GAMMA_XYZW_BIT|GAMMA_RGBA_BIT|GAMMA_FOG_BIT|GAMMA_SPEC_BIT) +#define TAG(x) x##_wgfs +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (GAMMA_XYZW_BIT|GAMMA_RGBA_BIT|GAMMA_FOG_BIT|GAMMA_TEX0_BIT) +#define TAG(x) x##_wgft0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (GAMMA_XYZW_BIT|GAMMA_RGBA_BIT|GAMMA_FOG_BIT|GAMMA_TEX0_BIT|\ + GAMMA_PTEX_BIT) +#define TAG(x) x##_wgfpt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (GAMMA_XYZW_BIT|GAMMA_RGBA_BIT|GAMMA_FOG_BIT|GAMMA_SPEC_BIT|\ + GAMMA_TEX0_BIT) +#define TAG(x) x##_wgfst0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (GAMMA_XYZW_BIT|GAMMA_RGBA_BIT|GAMMA_FOG_BIT|GAMMA_SPEC_BIT|\ + GAMMA_TEX0_BIT|GAMMA_PTEX_BIT) +#define TAG(x) x##_wgfspt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (GAMMA_TEX0_BIT) +#define TAG(x) x##_t0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (GAMMA_FOG_BIT) +#define TAG(x) x##_f +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (GAMMA_FOG_BIT|GAMMA_TEX0_BIT) +#define TAG(x) x##_ft0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (GAMMA_RGBA_BIT) +#define TAG(x) x##_g +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (GAMMA_RGBA_BIT|GAMMA_SPEC_BIT) +#define TAG(x) x##_gs +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (GAMMA_RGBA_BIT|GAMMA_TEX0_BIT) +#define TAG(x) x##_gt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (GAMMA_RGBA_BIT|GAMMA_SPEC_BIT|GAMMA_TEX0_BIT) +#define TAG(x) x##_gst0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (GAMMA_RGBA_BIT|GAMMA_FOG_BIT) +#define TAG(x) x##_gf +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (GAMMA_RGBA_BIT|GAMMA_FOG_BIT|GAMMA_SPEC_BIT) +#define TAG(x) x##_gfs +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (GAMMA_RGBA_BIT|GAMMA_FOG_BIT|GAMMA_TEX0_BIT) +#define TAG(x) x##_gft0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (GAMMA_RGBA_BIT|GAMMA_FOG_BIT|GAMMA_SPEC_BIT|GAMMA_TEX0_BIT) +#define TAG(x) x##_gfst0 +#include "tnl_dd/t_dd_vbtmp.h" + +static void init_setup_tab( void ) +{ + init_wg(); + init_wgs(); + init_wgt0(); + init_wgpt0(); + init_wgst0(); + init_wgspt0(); + init_wgf(); + init_wgfs(); + init_wgft0(); + init_wgfpt0(); + init_wgfst0(); + init_wgfspt0(); + init_t0(); + init_f(); + init_ft0(); + init_g(); + init_gs(); + init_gt0(); + init_gst0(); + init_gf(); + init_gfs(); + init_gft0(); + init_gfst0(); +} + +void gammaCheckTexSizes( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + gammaContextPtr gmesa = GAMMA_CONTEXT( ctx ); + + if (!setup_tab[gmesa->SetupIndex].check_tex_sizes(ctx)) { + /* Invalidate stored verts + */ + gmesa->SetupNewInputs = ~0; + gmesa->SetupIndex |= GAMMA_PTEX_BIT; + + if (!(ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) { + tnl->Driver.Render.Interp = setup_tab[gmesa->SetupIndex].interp; + tnl->Driver.Render.CopyPV = setup_tab[gmesa->SetupIndex].copy_pv; + } + } +} + +void gammaBuildVertices( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint newinputs ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT( ctx ); + GLubyte *v = ((GLubyte *)gmesa->verts + (start<<gmesa->vertex_stride_shift)); + GLuint stride = 1<<gmesa->vertex_stride_shift; + + newinputs |= gmesa->SetupNewInputs; + gmesa->SetupNewInputs = 0; + + if (!newinputs) + return; + + if (newinputs & VERT_CLIP) { + setup_tab[gmesa->SetupIndex].emit( ctx, start, count, v, stride ); + } else { + GLuint ind = 0; + + if (newinputs & VERT_RGBA) + ind |= GAMMA_RGBA_BIT; + + if (newinputs & VERT_SPEC_RGB) + ind |= GAMMA_SPEC_BIT; + + if (newinputs & VERT_TEX0) + ind |= GAMMA_TEX0_BIT; + + if (newinputs & VERT_FOG_COORD) + ind |= GAMMA_FOG_BIT; + + if (gmesa->SetupIndex & GAMMA_PTEX_BIT) + ind = ~0; + + ind &= gmesa->SetupIndex; + + if (ind) { + setup_tab[ind].emit( ctx, start, count, v, stride ); + } + } +} + +void gammaChooseVertexState( GLcontext *ctx ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT( ctx ); + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLuint ind = GAMMA_XYZW_BIT|GAMMA_RGBA_BIT; + + if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) + ind |= GAMMA_SPEC_BIT; + + if (ctx->Fog.Enabled) + ind |= GAMMA_FOG_BIT; + + if (ctx->Texture._ReallyEnabled) { + _tnl_need_projected_coords( ctx, GL_FALSE ); + ind |= GAMMA_TEX0_BIT; + } else + _tnl_need_projected_coords( ctx, GL_FALSE ); + + gmesa->SetupIndex = ind; + + if (setup_tab[ind].vertex_format != gmesa->vertex_format) { + gmesa->vertex_format = setup_tab[ind].vertex_format; + gmesa->vertex_size = setup_tab[ind].vertex_size; + gmesa->vertex_stride_shift = setup_tab[ind].vertex_stride_shift; + } + + if (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED)) { + tnl->Driver.Render.Interp = gamma_interp_extras; + tnl->Driver.Render.CopyPV = gamma_copy_pv_extras; + } else { + tnl->Driver.Render.Interp = setup_tab[ind].interp; + tnl->Driver.Render.CopyPV = setup_tab[ind].copy_pv; + } +} + + +void gammaInitVB( GLcontext *ctx ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + GLuint size = TNL_CONTEXT(ctx)->vb.Size; + + gmesa->verts = (char *)ALIGN_MALLOC(size * 4 * 16, 32); + + { + static int firsttime = 1; + if (firsttime) { + init_setup_tab(); + firsttime = 0; + gmesa->vertex_stride_shift = 6; /* FIXME - only one vertex setup */ + } + } +} + + +void gammaFreeVB( GLcontext *ctx ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + if (gmesa->verts) { + ALIGN_FREE(gmesa->verts); + gmesa->verts = 0; + } + + if (gmesa->UbyteSecondaryColor.Ptr) { + ALIGN_FREE(gmesa->UbyteSecondaryColor.Ptr); + gmesa->UbyteSecondaryColor.Ptr = 0; + } + + if (gmesa->UbyteColor.Ptr) { + ALIGN_FREE(gmesa->UbyteColor.Ptr); + gmesa->UbyteColor.Ptr = 0; + } +} diff --git a/xc/lib/GL/mesa/src/drv/i810/i810tris.c b/xc/lib/GL/mesa/src/drv/i810/i810tris.c index e97e7e644..94b4980c6 100644 --- a/xc/lib/GL/mesa/src/drv/i810/i810tris.c +++ b/xc/lib/GL/mesa/src/drv/i810/i810tris.c @@ -1,166 +1,807 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 2001 VA Linux Systems Inc., Fremont, California. + +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 +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + /* - * GLX Hardware Device Driver for Intel i810 - * Copyright (C) 1999 Keith Whitwell - * - * 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 - * KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS 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. - * - * + * Authors: + * Keith Whitwell <keithw@valinux.com> */ -/* $XFree86: xc/lib/GL/mesa/src/drv/i810/i810tris.c,v 1.5 2000/09/24 13:51:04 alanh Exp $ */ #include <stdio.h> #include <math.h> -#include "types.h" -#include "vb.h" -#include "pipeline.h" +#include "glheader.h" +#include "mtypes.h" +#include "macros.h" +#include "colormac.h" + +#include "swrast/swrast.h" +#include "swrast_setup/swrast_setup.h" +#include "tnl/t_context.h" +#include "tnl/t_pipeline.h" + +#include "i810screen.h" +#include "i810_dri.h" -#include "mm.h" #include "i810tris.h" +#include "i810state.h" #include "i810vb.h" -#include "i810log.h" +#include "i810ioctl.h" -/* Used in i810tritmp.h - */ -#define I810_COLOR(to, from) { \ - (to)[0] = (from)[2]; \ - (to)[1] = (from)[1]; \ - (to)[2] = (from)[0]; \ - (to)[3] = (from)[3]; \ +static void i810RenderPrimitive( GLcontext *ctx, GLenum prim ); + +/*********************************************************************** + * Emit primitives as inline vertices * + ***********************************************************************/ + +#if defined(USE_X86_ASM) +#define COPY_DWORDS( j, vb, vertsize, v ) \ +do { \ + int __tmp; \ + __asm__ __volatile__( "rep ; movsl" \ + : "=%c" (j), "=D" (vb), "=S" (__tmp) \ + : "0" (vertsize), \ + "D" ((long)vb), \ + "S" ((long)v) ); \ +} while (0) +#else +#define COPY_DWORDS( j, vb, vertsize, v ) \ +do { \ + for ( j = 0 ; j < vertsize ; j++ ) \ + vb[j] = ((GLuint *)v)[j]; \ + vb += vertsize; \ +} while (0) +#endif + +static void __inline__ i810_draw_triangle( i810ContextPtr imesa, + i810VertexPtr v0, + i810VertexPtr v1, + i810VertexPtr v2 ) +{ + GLuint vertsize = imesa->vertex_size; + GLuint *vb = i810AllocDmaLow( imesa, 3 * 4 * vertsize ); + int j; + + COPY_DWORDS( j, vb, vertsize, v0 ); + COPY_DWORDS( j, vb, vertsize, v1 ); + COPY_DWORDS( j, vb, vertsize, v2 ); } -static triangle_func tri_tab[0x10]; -static quad_func quad_tab[0x10]; -static line_func line_tab[0x10]; -static points_func points_tab[0x10]; -#define IND (0) +static void __inline__ i810_draw_quad( i810ContextPtr imesa, + i810VertexPtr v0, + i810VertexPtr v1, + i810VertexPtr v2, + i810VertexPtr v3 ) +{ + GLuint vertsize = imesa->vertex_size; + GLuint *vb = i810AllocDmaLow( imesa, 6 * 4 * vertsize ); + int j; + + COPY_DWORDS( j, vb, vertsize, v0 ); + COPY_DWORDS( j, vb, vertsize, v1 ); + COPY_DWORDS( j, vb, vertsize, v3 ); + COPY_DWORDS( j, vb, vertsize, v1 ); + COPY_DWORDS( j, vb, vertsize, v2 ); + COPY_DWORDS( j, vb, vertsize, v3 ); +} + + +static __inline__ void i810_draw_point( i810ContextPtr imesa, + i810VertexPtr tmp ) +{ + GLfloat sz = imesa->glCtx->Point._Size * .5; + int vertsize = imesa->vertex_size; + GLuint *vb = i810AllocDmaLow( imesa, 2 * 4 * vertsize ); + int j; + + /* Draw a point as a horizontal line. + */ + *(float *)&vb[0] = tmp->v.x - sz + 0.125; + for (j = 1 ; j < vertsize ; j++) + vb[j] = tmp->ui[j]; + vb += vertsize; + + *(float *)&vb[0] = tmp->v.x + sz + 0.125; + for (j = 1 ; j < vertsize ; j++) + vb[j] = tmp->ui[j]; + vb += vertsize; +} + + +static __inline__ void i810_draw_line( i810ContextPtr imesa, + i810VertexPtr v0, + i810VertexPtr v1 ) +{ + GLuint vertsize = imesa->vertex_size; + GLuint *vb = i810AllocDmaLow( imesa, 2 * 4 * vertsize ); + int j; + + COPY_DWORDS( j, vb, vertsize, v0 ); + COPY_DWORDS( j, vb, vertsize, v1 ); +} + + + +/*********************************************************************** + * Macros for t_dd_tritmp.h to draw basic primitives * + ***********************************************************************/ + +#define TRI( a, b, c ) \ +do { \ + if (0) fprintf(stderr, "hw TRI\n"); \ + if (DO_FALLBACK) \ + imesa->draw_tri( imesa, a, b, c ); \ + else \ + i810_draw_triangle( imesa, a, b, c ); \ +} while (0) + +#define QUAD( a, b, c, d ) \ +do { \ + if (0) fprintf(stderr, "hw QUAD\n"); \ + if (DO_FALLBACK) { \ + imesa->draw_tri( imesa, a, b, d ); \ + imesa->draw_tri( imesa, b, c, d ); \ + } else \ + i810_draw_quad( imesa, a, b, c, d ); \ +} while (0) + +#define LINE( v0, v1 ) \ +do { \ + if (0) fprintf(stderr, "hw LINE\n"); \ + if (DO_FALLBACK) \ + imesa->draw_line( imesa, v0, v1 ); \ + else \ + i810_draw_line( imesa, v0, v1 ); \ +} while (0) + +#define POINT( v0 ) \ +do { \ + if (0) fprintf(stderr, "hw POINT\n"); \ + if (DO_FALLBACK) \ + imesa->draw_point( imesa, v0 ); \ + else \ + i810_draw_point( imesa, v0 ); \ +} while (0) + + +/*********************************************************************** + * Build render functions from dd templates * + ***********************************************************************/ + +#define I810_OFFSET_BIT 0x01 +#define I810_TWOSIDE_BIT 0x02 +#define I810_UNFILLED_BIT 0x04 +#define I810_FALLBACK_BIT 0x08 +#define I810_MAX_TRIFUNC 0x10 + + +static struct { + points_func points; + line_func line; + triangle_func triangle; + quad_func quad; +} rast_tab[I810_MAX_TRIFUNC]; + + +#define DO_FALLBACK (IND & I810_FALLBACK_BIT) +#define DO_OFFSET (IND & I810_OFFSET_BIT) +#define DO_UNFILLED (IND & I810_UNFILLED_BIT) +#define DO_TWOSIDE (IND & I810_TWOSIDE_BIT) +#define DO_FLAT 0 +#define DO_TRI 1 +#define DO_QUAD 1 +#define DO_LINE 1 +#define DO_POINTS 1 +#define DO_FULL_QUAD 1 + +#define HAVE_RGBA 1 +#define HAVE_SPEC 1 +#define HAVE_BACK_COLORS 0 +#define HAVE_HW_FLATSHADE 1 +#define VERTEX i810Vertex +#define TAB rast_tab + +/* Only used to pull back colors into vertices (ie, we know color is + * floating point). + */ +#define I810_COLOR( dst, src ) \ +do { \ + dst[0] = src[2]; \ + dst[1] = src[1]; \ + dst[2] = src[0]; \ + dst[3] = src[3]; \ +} while (0) + +#define I810_SPEC( dst, src ) \ +do { \ + dst[0] = src[2]; \ + dst[1] = src[1]; \ + dst[2] = src[0]; \ +} while (0) + + +#define DEPTH_SCALE (1.0/0xffff) +#define UNFILLED_TRI unfilled_tri +#define UNFILLED_QUAD unfilled_quad +#define VERT_X(_v) _v->v.x +#define VERT_Y(_v) _v->v.y +#define VERT_Z(_v) _v->v.z +#define AREA_IS_CCW( a ) (a > 0) +#define GET_VERTEX(e) (imesa->verts + (e<<imesa->vertex_stride_shift)) + +#define VERT_SET_RGBA( v, c ) I810_COLOR( v->ub4[coloroffset], c ) +#define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset] +#define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset] +#define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx] + +#define VERT_SET_SPEC( v, c ) if (havespec) I810_SPEC( v->ub4[5], c ) +#define VERT_COPY_SPEC( v0, v1 ) if (havespec) COPY_3V(v0->ub4[5], v1->ub4[5]) +#define VERT_SAVE_SPEC( idx ) if (havespec) spec[idx] = v[idx]->ui[5] +#define VERT_RESTORE_SPEC( idx ) if (havespec) v[idx]->ui[5] = spec[idx] + +#define LOCAL_VARS(n) \ + i810ContextPtr imesa = I810_CONTEXT(ctx); \ + GLuint color[n], spec[n]; \ + GLuint coloroffset = (imesa->vertex_size == 4 ? 3 : 4); \ + GLboolean havespec = (imesa->vertex_size > 4); \ + (void) color; (void) spec; (void) coloroffset; (void) havespec; + + +/*********************************************************************** + * Helpers for rendering unfilled primitives * + ***********************************************************************/ + +static const GLuint hw_prim[GL_POLYGON+1] = { + PR_LINES, + PR_LINES, + PR_LINES, + PR_LINES, + PR_TRIANGLES, + PR_TRIANGLES, + PR_TRIANGLES, + PR_TRIANGLES, + PR_TRIANGLES, + PR_TRIANGLES +}; + +#define RASTERIZE(x) if (imesa->hw_primitive != hw_prim[x]) \ + i810RasterPrimitive( ctx, x, hw_prim[x] ) +#define RENDER_PRIMITIVE imesa->render_primitive #define TAG(x) x -#include "i810tritmp.h" +#define IND I810_FALLBACK_BIT +#include "tnl_dd/t_dd_unfilled.h" +#undef IND -#define IND (I810_FLAT_BIT) -#define TAG(x) x##_flat -#include "i810tritmp.h" +/*********************************************************************** + * Generate GL render functions * + ***********************************************************************/ -#define IND (I810_OFFSET_BIT) -#define TAG(x) x##_offset -#include "i810tritmp.h" +#define IND (0) +#define TAG(x) x +#include "tnl_dd/t_dd_tritmp.h" -#define IND (I810_OFFSET_BIT|I810_FLAT_BIT) -#define TAG(x) x##_offset_flat -#include "i810tritmp.h" +#define IND (I810_OFFSET_BIT) +#define TAG(x) x##_offset +#include "tnl_dd/t_dd_tritmp.h" -#define IND (I810_TWOSIDE_BIT) +#define IND (I810_TWOSIDE_BIT) #define TAG(x) x##_twoside -#include "i810tritmp.h" +#include "tnl_dd/t_dd_tritmp.h" -#define IND (I810_TWOSIDE_BIT|I810_FLAT_BIT) -#define TAG(x) x##_twoside_flat -#include "i810tritmp.h" - -#define IND (I810_TWOSIDE_BIT|I810_OFFSET_BIT) +#define IND (I810_TWOSIDE_BIT|I810_OFFSET_BIT) #define TAG(x) x##_twoside_offset -#include "i810tritmp.h" +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (I810_UNFILLED_BIT) +#define TAG(x) x##_unfilled +#include "tnl_dd/t_dd_tritmp.h" -#define IND (I810_TWOSIDE_BIT|I810_OFFSET_BIT|I810_FLAT_BIT) -#define TAG(x) x##_twoside_offset_flat -#include "i810tritmp.h" +#define IND (I810_OFFSET_BIT|I810_UNFILLED_BIT) +#define TAG(x) x##_offset_unfilled +#include "tnl_dd/t_dd_tritmp.h" +#define IND (I810_TWOSIDE_BIT|I810_UNFILLED_BIT) +#define TAG(x) x##_twoside_unfilled +#include "tnl_dd/t_dd_tritmp.h" +#define IND (I810_TWOSIDE_BIT|I810_OFFSET_BIT|I810_UNFILLED_BIT) +#define TAG(x) x##_twoside_offset_unfilled +#include "tnl_dd/t_dd_tritmp.h" -void i810DDTrifuncInit() +#define IND (I810_FALLBACK_BIT) +#define TAG(x) x##_fallback +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (I810_OFFSET_BIT|I810_FALLBACK_BIT) +#define TAG(x) x##_offset_fallback +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (I810_TWOSIDE_BIT|I810_FALLBACK_BIT) +#define TAG(x) x##_twoside_fallback +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (I810_TWOSIDE_BIT|I810_OFFSET_BIT|I810_FALLBACK_BIT) +#define TAG(x) x##_twoside_offset_fallback +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (I810_UNFILLED_BIT|I810_FALLBACK_BIT) +#define TAG(x) x##_unfilled_fallback +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (I810_OFFSET_BIT|I810_UNFILLED_BIT|I810_FALLBACK_BIT) +#define TAG(x) x##_offset_unfilled_fallback +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (I810_TWOSIDE_BIT|I810_UNFILLED_BIT|I810_FALLBACK_BIT) +#define TAG(x) x##_twoside_unfilled_fallback +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (I810_TWOSIDE_BIT|I810_OFFSET_BIT|I810_UNFILLED_BIT| \ + I810_FALLBACK_BIT) +#define TAG(x) x##_twoside_offset_unfilled_fallback +#include "tnl_dd/t_dd_tritmp.h" + + +static void init_rast_tab( void ) { init(); - init_flat(); init_offset(); - init_offset_flat(); init_twoside(); - init_twoside_flat(); init_twoside_offset(); - init_twoside_offset_flat(); -} - - - -#define ALL_FALLBACK (DD_MULTIDRAW | DD_SELECT | DD_FEEDBACK | DD_STENCIL) -#define POINT_FALLBACK (ALL_FALLBACK) -#define LINE_FALLBACK (ALL_FALLBACK | DD_LINE_STIPPLE) -#define TRI_FALLBACK (ALL_FALLBACK | DD_TRI_UNFILLED) -#define ANY_FALLBACK (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK|DD_TRI_STIPPLE) -#define ANY_RASTER_FLAGS (DD_FLATSHADE|DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET) - -void i810DDChooseRenderState(GLcontext *ctx) -{ - i810ContextPtr imesa = I810_CONTEXT(ctx); - GLuint flags = ctx->TriangleCaps; - CARD32 index = 0; - - if (imesa->Fallback) { - imesa->renderindex = I810_FALLBACK_BIT; - return; - } - - if (flags & ANY_RASTER_FLAGS) { - if (flags & DD_FLATSHADE) index |= I810_FLAT_BIT; - if (flags & DD_TRI_LIGHT_TWOSIDE) index |= I810_TWOSIDE_BIT; - if (flags & DD_TRI_OFFSET) index |= I810_OFFSET_BIT; - } - - imesa->PointsFunc = points_tab[index]; - imesa->LineFunc = line_tab[index]; - imesa->TriangleFunc = tri_tab[index]; - imesa->QuadFunc = quad_tab[index]; - imesa->renderindex = index; - imesa->IndirectTriangles = 0; - - if (flags & ANY_FALLBACK) { - if (flags & POINT_FALLBACK) { - imesa->renderindex |= I810_FALLBACK_BIT; - imesa->PointsFunc = 0; - imesa->IndirectTriangles |= DD_POINT_SW_RASTERIZE; - } - - if (flags & LINE_FALLBACK) { - imesa->renderindex |= I810_FALLBACK_BIT; - imesa->LineFunc = 0; - imesa->IndirectTriangles |= DD_LINE_SW_RASTERIZE; - } - - if (flags & TRI_FALLBACK) { - imesa->renderindex |= I810_FALLBACK_BIT; - imesa->TriangleFunc = 0; - imesa->QuadFunc = 0; - imesa->IndirectTriangles |= (DD_TRI_SW_RASTERIZE | - DD_QUAD_SW_RASTERIZE); - } - /* Special cases: - */ - if ((flags & DD_TRI_STIPPLE) && - (ctx->IndirectTriangles & DD_TRI_STIPPLE)) { - imesa->renderindex |= I810_FALLBACK_BIT; - imesa->TriangleFunc = 0; - imesa->QuadFunc = 0; - imesa->IndirectTriangles |= (DD_TRI_SW_RASTERIZE | - DD_QUAD_SW_RASTERIZE); - } - } + init_unfilled(); + init_offset_unfilled(); + init_twoside_unfilled(); + init_twoside_offset_unfilled(); + init_fallback(); + init_offset_fallback(); + init_twoside_fallback(); + init_twoside_offset_fallback(); + init_unfilled_fallback(); + init_offset_unfilled_fallback(); + init_twoside_unfilled_fallback(); + init_twoside_offset_unfilled_fallback(); +} + + +/*********************************************************************** + * Rasterization fallback helpers * + ***********************************************************************/ + + +/* This code is hit only when a mix of accelerated and unaccelerated + * primitives are being drawn, and only for the unaccelerated + * primitives. + */ +static void +i810_fallback_tri( i810ContextPtr imesa, + i810Vertex *v0, + i810Vertex *v1, + i810Vertex *v2 ) +{ + GLcontext *ctx = imesa->glCtx; + SWvertex v[3]; + i810_translate_vertex( ctx, v0, &v[0] ); + i810_translate_vertex( ctx, v1, &v[1] ); + i810_translate_vertex( ctx, v2, &v[2] ); + _swrast_Triangle( ctx, &v[0], &v[1], &v[2] ); } +static void +i810_fallback_line( i810ContextPtr imesa, + i810Vertex *v0, + i810Vertex *v1 ) +{ + GLcontext *ctx = imesa->glCtx; + SWvertex v[2]; + i810_translate_vertex( ctx, v0, &v[0] ); + i810_translate_vertex( ctx, v1, &v[1] ); + _swrast_Line( ctx, &v[0], &v[1] ); +} + + +static void +i810_fallback_point( i810ContextPtr imesa, + i810Vertex *v0 ) +{ + GLcontext *ctx = imesa->glCtx; + SWvertex v[1]; + i810_translate_vertex( ctx, v0, &v[0] ); + _swrast_Point( ctx, &v[0] ); +} + + +/**********************************************************************/ +/* Render unclipped begin/end objects */ +/**********************************************************************/ + +#define IND 0 +#define V(x) (i810Vertex *)(vertptr + ((x)<<vertshift)) +#define RENDER_POINTS( start, count ) \ + for ( ; start < count ; start++) POINT( V(ELT(start)) ); +#define RENDER_LINE( v0, v1 ) LINE( V(v0), V(v1) ) +#define RENDER_TRI( v0, v1, v2 ) TRI( V(v0), V(v1), V(v2) ) +#define RENDER_QUAD( v0, v1, v2, v3 ) QUAD( V(v0), V(v1), V(v2), V(v3) ) +#define INIT(x) i810RenderPrimitive( ctx, x ) +#undef LOCAL_VARS +#define LOCAL_VARS \ + i810ContextPtr imesa = I810_CONTEXT(ctx); \ + GLubyte *vertptr = (GLubyte *)imesa->verts; \ + const GLuint vertshift = imesa->vertex_stride_shift; \ + const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \ + (void) elt; +#define RESET_STIPPLE +#define RESET_OCCLUSION +#define PRESERVE_VB_DEFS +#define ELT(x) x +#define TAG(x) i810_##x##_verts +#include "tnl/t_vb_rendertmp.h" +#undef ELT +#undef TAG +#define TAG(x) i810_##x##_elts +#define ELT(x) elt[x] +#include "tnl/t_vb_rendertmp.h" + +/**********************************************************************/ +/* Render clipped primitives */ +/**********************************************************************/ + + + +static void i810RenderClippedPoly( GLcontext *ctx, const GLuint *elts, + GLuint n ) +{ + i810ContextPtr imesa = I810_CONTEXT(ctx); + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; + GLuint prim = imesa->render_primitive; + + /* Render the new vertices as an unclipped polygon. + */ + { + GLuint *tmp = VB->Elts; + VB->Elts = (GLuint *)elts; + tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, + PRIM_BEGIN|PRIM_END ); + VB->Elts = tmp; + } + + /* Restore the render primitive + */ + if (prim != GL_POLYGON) + tnl->Driver.Render.PrimitiveNotify( ctx, prim ); +} + +static void i810RenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + tnl->Driver.Render.Line( ctx, ii, jj ); +} + +static void i810FastRenderClippedPoly( GLcontext *ctx, const GLuint *elts, + GLuint n ) +{ + i810ContextPtr imesa = I810_CONTEXT( ctx ); + GLuint vertsize = imesa->vertex_size; + GLuint *vb = i810AllocDmaLow( imesa, (n-2) * 3 * 4 * vertsize ); + GLubyte *vertptr = (GLubyte *)imesa->verts; + const GLuint vertshift = imesa->vertex_stride_shift; + const GLuint *start = (const GLuint *)V(elts[0]); + int i,j; + + for (i = 2 ; i < n ; i++) { + COPY_DWORDS( j, vb, vertsize, V(elts[i-1]) ); + COPY_DWORDS( j, vb, vertsize, V(elts[i]) ); + COPY_DWORDS( j, vb, vertsize, start ); + } +} + +/**********************************************************************/ +/* Choose render functions */ +/**********************************************************************/ + + + +#define _I810_NEW_RENDERSTATE (_DD_NEW_LINE_STIPPLE | \ + _DD_NEW_TRI_UNFILLED | \ + _DD_NEW_TRI_LIGHT_TWOSIDE | \ + _DD_NEW_TRI_OFFSET | \ + _DD_NEW_TRI_STIPPLE | \ + _NEW_POLYGONSTIPPLE) + +#define POINT_FALLBACK (0) +#define LINE_FALLBACK (DD_LINE_STIPPLE) +#define TRI_FALLBACK (0) +#define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK|\ + DD_TRI_STIPPLE) +#define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED) + +static void i810ChooseRenderState(GLcontext *ctx) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + i810ContextPtr imesa = I810_CONTEXT(ctx); + GLuint flags = ctx->_TriangleCaps; + GLuint index = 0; + + if (flags & (ANY_FALLBACK_FLAGS|ANY_RASTER_FLAGS)) { + if (flags & ANY_RASTER_FLAGS) { + if (flags & DD_TRI_LIGHT_TWOSIDE) index |= I810_TWOSIDE_BIT; + if (flags & DD_TRI_OFFSET) index |= I810_OFFSET_BIT; + if (flags & DD_TRI_UNFILLED) index |= I810_UNFILLED_BIT; + } + + imesa->draw_point = i810_draw_point; + imesa->draw_line = i810_draw_line; + imesa->draw_tri = i810_draw_triangle; + + /* Hook in fallbacks for specific primitives. + */ + if (flags & ANY_FALLBACK_FLAGS) + { + if (flags & POINT_FALLBACK) + imesa->draw_point = i810_fallback_point; + + if (flags & LINE_FALLBACK) + imesa->draw_line = i810_fallback_line; + + if (flags & TRI_FALLBACK) + imesa->draw_tri = i810_fallback_tri; + + if ((flags & DD_TRI_STIPPLE) && !imesa->stipple_in_hw) + imesa->draw_tri = i810_fallback_tri; + + index |= I810_FALLBACK_BIT; + } + } + + if (imesa->RenderIndex != index) { + imesa->RenderIndex = index; + + tnl->Driver.Render.Points = rast_tab[index].points; + tnl->Driver.Render.Line = rast_tab[index].line; + tnl->Driver.Render.Triangle = rast_tab[index].triangle; + tnl->Driver.Render.Quad = rast_tab[index].quad; + + if (index == 0) { + tnl->Driver.Render.PrimTabVerts = i810_render_tab_verts; + tnl->Driver.Render.PrimTabElts = i810_render_tab_elts; + tnl->Driver.Render.ClippedLine = line; /* from tritmp.h */ + tnl->Driver.Render.ClippedPolygon = i810FastRenderClippedPoly; + } else { + tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts; + tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts; + tnl->Driver.Render.ClippedLine = i810RenderClippedLine; + tnl->Driver.Render.ClippedPolygon = i810RenderClippedPoly; + } + } +} + +static const GLenum reduced_prim[GL_POLYGON+1] = { + GL_POINTS, + GL_LINES, + GL_LINES, + GL_LINES, + GL_TRIANGLES, + GL_TRIANGLES, + GL_TRIANGLES, + GL_TRIANGLES, + GL_TRIANGLES, + GL_TRIANGLES +}; + + +/**********************************************************************/ +/* High level hooks for t_vb_render.c */ +/**********************************************************************/ + + + +/* Determine the rasterized primitive when not drawing unfilled + * polygons. + * + * Used only for the default render stage which always decomposes + * primitives to trianges/lines/points. For the accelerated stage, + * which renders strips as strips, the equivalent calculations are + * performed in i810render.c. + */ +static void i810RenderPrimitive( GLcontext *ctx, GLenum prim ) +{ + i810ContextPtr imesa = I810_CONTEXT(ctx); + GLuint rprim = reduced_prim[prim]; + + imesa->render_primitive = prim; + + if (rprim == GL_TRIANGLES && (ctx->_TriangleCaps & DD_TRI_UNFILLED)) + return; + + if (imesa->reduced_primitive != rprim || + hw_prim[prim] != imesa->hw_primitive) { + i810RasterPrimitive( ctx, rprim, hw_prim[prim] ); + } +} + +static void i810RunPipeline( GLcontext *ctx ) +{ + i810ContextPtr imesa = I810_CONTEXT(ctx); + + if (imesa->new_state) { + if (imesa->new_state & _NEW_TEXTURE) + i810UpdateTextureState( ctx ); /* may modify imesa->new_state */ + + if (!imesa->Fallback) { + if (imesa->new_state & _I810_NEW_VERTEX) + i810ChooseVertexState( ctx ); + + if (imesa->new_state & _I810_NEW_RENDERSTATE) + i810ChooseRenderState( ctx ); + } + + imesa->new_state = 0; + } + + _tnl_run_pipeline( ctx ); +} + +static void i810RenderStart( GLcontext *ctx ) +{ + /* Check for projective textureing. Make sure all texcoord + * pointers point to something. (fix in mesa?) + */ + i810CheckTexSizes( ctx ); +} + +static void i810RenderFinish( GLcontext *ctx ) +{ + if (I810_CONTEXT(ctx)->RenderIndex & I810_FALLBACK_BIT) + _swrast_flush( ctx ); +} + + + + +/* System to flush dma and emit state changes based on the rasterized + * primitive. + */ +void i810RasterPrimitive( GLcontext *ctx, + GLenum rprim, + GLuint hwprim ) +{ + i810ContextPtr imesa = I810_CONTEXT(ctx); + GLuint st1 = imesa->Setup[I810_CTXREG_ST1]; + GLuint aa = imesa->Setup[I810_CTXREG_AA]; + GLuint lcs = imesa->Setup[I810_CTXREG_LCS]; + + st1 &= ~ST1_ENABLE; + aa &= ~AA_ENABLE; + + switch (rprim) { + case GL_TRIANGLES: + if (ctx->Polygon.StippleFlag) + st1 |= ST1_ENABLE; + if (ctx->Polygon.SmoothFlag) + aa |= AA_ENABLE; + break; + case GL_LINES: + lcs &= ~(LCS_LINEWIDTH_3_0|LCS_LINEWIDTH_0_5); + lcs |= imesa->LcsLineWidth; + if (ctx->Line.SmoothFlag) { + aa |= AA_ENABLE; + lcs |= LCS_LINEWIDTH_0_5; + } + break; + case GL_POINTS: + lcs &= ~(LCS_LINEWIDTH_3_0|LCS_LINEWIDTH_0_5); + lcs |= imesa->LcsPointSize; + if (ctx->Point.SmoothFlag) { + aa |= AA_ENABLE; + lcs |= LCS_LINEWIDTH_0_5; + } + break; + default: + return; + } + + imesa->reduced_primitive = rprim; + + if (st1 != imesa->Setup[I810_CTXREG_ST1] || + aa != imesa->Setup[I810_CTXREG_AA] || + lcs != imesa->Setup[I810_CTXREG_LCS]) + { + I810_STATECHANGE(imesa, I810_UPLOAD_CTX); + imesa->hw_primitive = hwprim; + imesa->Setup[I810_CTXREG_LCS] = lcs; + imesa->Setup[I810_CTXREG_ST1] = st1; + imesa->Setup[I810_CTXREG_AA] = aa; + } + else if (hwprim != imesa->hw_primitive) { + I810_STATECHANGE(imesa, 0); + imesa->hw_primitive = hwprim; + } +} + +/**********************************************************************/ +/* Transition to/from hardware rasterization. */ +/**********************************************************************/ + + +void i810Fallback( i810ContextPtr imesa, GLuint bit, GLboolean mode ) +{ + GLcontext *ctx = imesa->glCtx; + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLuint oldfallback = imesa->Fallback; + + if (0) fprintf(stderr, "%s old %x bit %x mode %d\n", __FUNCTION__, + imesa->Fallback, bit, mode ); + + if (mode) { + imesa->Fallback |= bit; + if (oldfallback == 0) { + if (0) fprintf(stderr, "ENTER FALLBACK\n"); + I810_FIREVERTICES(imesa); + _swsetup_Wakeup( ctx ); + imesa->RenderIndex = ~0; + } + } + else { + imesa->Fallback &= ~bit; + if (oldfallback == bit) { + if (0) fprintf(stderr, "LEAVE FALLBACK\n"); + _swrast_flush( ctx ); + tnl->Driver.Render.Start = i810RenderStart; + tnl->Driver.Render.PrimitiveNotify = i810RenderPrimitive; + tnl->Driver.Render.Finish = i810RenderFinish; + tnl->Driver.Render.BuildVertices = i810BuildVertices; + imesa->new_state |= (_I810_NEW_RENDERSTATE|_I810_NEW_VERTEX); + } + } +} + + +/**********************************************************************/ +/* Initialization. */ +/**********************************************************************/ + + +void i810InitTriFuncs( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + static int firsttime = 1; + + if (firsttime) { + init_rast_tab(); + firsttime = 0; + } + + tnl->Driver.RunPipeline = i810RunPipeline; + tnl->Driver.Render.Start = i810RenderStart; + tnl->Driver.Render.Finish = i810RenderFinish; + tnl->Driver.Render.PrimitiveNotify = i810RenderPrimitive; + tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple; + tnl->Driver.Render.BuildVertices = i810BuildVertices; +} diff --git a/xc/lib/GL/mesa/src/drv/i810/i810vb.c b/xc/lib/GL/mesa/src/drv/i810/i810vb.c index 802c56dc2..d6b3f163a 100644 --- a/xc/lib/GL/mesa/src/drv/i810/i810vb.c +++ b/xc/lib/GL/mesa/src/drv/i810/i810vb.c @@ -15,454 +15,483 @@ * 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 - * KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS 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 + * KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS 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. * * */ -/* $XFree86: xc/lib/GL/mesa/src/drv/i810/i810vb.c,v 1.8 2001/03/21 16:14:21 dawes Exp $ */ - -#include <stdio.h> -#include <stdlib.h> -#include "i810context.h" -#include "i810vb.h" -#include "i810log.h" +/* $XFree86: xc/lib/GL/mesa/src/drv/i810/i810vb.c,v 1.7 2000/11/08 05:02:43 dawes Exp $ */ + +#include "glheader.h" +#include "mtypes.h" #include "mem.h" -#include "stages.h" +#include "macros.h" +#include "colormac.h" +#include "mmath.h" +#include "swrast_setup/swrast_setup.h" +#include "tnl/t_context.h" +#include "i810screen.h" +#include "i810_dri.h" -#define TEX0 { \ - v->v.tu0 = tc0[i][0]; \ - v->v.tv0 = tc0[i][1]; \ -} +#include "i810context.h" +#include "i810vb.h" +#include "i810ioctl.h" +#include "i810tris.h" +#include "i810state.h" + + +#define I810_TEX1_BIT 0x1 +#define I810_TEX0_BIT 0x2 +#define I810_RGBA_BIT 0x4 +#define I810_SPEC_BIT 0x8 +#define I810_FOG_BIT 0x10 +#define I810_XYZW_BIT 0x20 +#define I810_PTEX_BIT 0x40 +#define I810_MAX_SETUP 0x80 + +static struct { + void (*emit)( GLcontext *, GLuint, GLuint, void *, GLuint ); + interp_func interp; + copy_pv_func copy_pv; + GLboolean (*check_tex_sizes)( GLcontext *ctx ); + GLuint vertex_size; + GLuint vertex_stride_shift; + GLuint vertex_format; +} setup_tab[I810_MAX_SETUP]; + +#define TINY_VERTEX_FORMAT (GFX_OP_VERTEX_FMT | \ + VF_TEXCOORD_COUNT_0 | \ + VF_RGBA_ENABLE | \ + VF_XYZ) + +#define NOTEX_VERTEX_FORMAT (GFX_OP_VERTEX_FMT | \ + VF_TEXCOORD_COUNT_0 | \ + VF_SPEC_FOG_ENABLE | \ + VF_RGBA_ENABLE | \ + VF_XYZW) + +#define TEX0_VERTEX_FORMAT (GFX_OP_VERTEX_FMT | \ + VF_TEXCOORD_COUNT_1 | \ + VF_SPEC_FOG_ENABLE | \ + VF_RGBA_ENABLE | \ + VF_XYZW) + +#define TEX1_VERTEX_FORMAT (GFX_OP_VERTEX_FMT | \ + VF_TEXCOORD_COUNT_2 | \ + VF_SPEC_FOG_ENABLE | \ + VF_RGBA_ENABLE | \ + VF_XYZW) + +#define PROJ_TEX1_VERTEX_FORMAT 0 +#define TEX2_VERTEX_FORMAT 0 +#define TEX3_VERTEX_FORMAT 0 +#define PROJ_TEX3_VERTEX_FORMAT 0 + +#define DO_XYZW (IND & I810_XYZW_BIT) +#define DO_RGBA (IND & I810_RGBA_BIT) +#define DO_SPEC (IND & I810_SPEC_BIT) +#define DO_FOG (IND & I810_FOG_BIT) +#define DO_TEX0 (IND & I810_TEX0_BIT) +#define DO_TEX1 (IND & I810_TEX1_BIT) +#define DO_TEX2 0 +#define DO_TEX3 0 +#define DO_PTEX (IND & I810_PTEX_BIT) + +#define VERTEX i810Vertex +#define VERTEX_COLOR i810_color_t +#define GET_VIEWPORT_MAT() I810_CONTEXT(ctx)->ViewportMatrix.m +#define GET_TEXSOURCE(n) n +#define GET_VERTEX_FORMAT() I810_CONTEXT(ctx)->Setup[I810_CTXREG_VF] +#define GET_VERTEX_STORE() I810_CONTEXT(ctx)->verts +#define GET_VERTEX_STRIDE_SHIFT() I810_CONTEXT(ctx)->vertex_stride_shift +#define GET_UBYTE_COLOR_STORE() &I810_CONTEXT(ctx)->UbyteColor +#define GET_UBYTE_SPEC_COLOR_STORE() &I810_CONTEXT(ctx)->UbyteSecondaryColor +#define INVALIDATE_STORED_VERTICES() + +#define HAVE_HW_VIEWPORT 0 +#define HAVE_HW_DIVIDE 0 +#define HAVE_RGBA_COLOR 0 +#define HAVE_TINY_VERTICES 1 +#define HAVE_NOTEX_VERTICES 1 +#define HAVE_TEX0_VERTICES 1 +#define HAVE_TEX1_VERTICES 1 +#define HAVE_TEX2_VERTICES 0 +#define HAVE_TEX3_VERTICES 0 +#define HAVE_PTEX_VERTICES 0 + +#define UNVIEWPORT_VARS GLfloat h = I810_CONTEXT(ctx)->driDrawable->h +#define UNVIEWPORT_X(x) x - SUBPIXEL_X +#define UNVIEWPORT_Y(y) - y + h + SUBPIXEL_Y +#define UNVIEWPORT_Z(z) z * (float)0xffff + +#define PTEX_FALLBACK() FALLBACK(I810_CONTEXT(ctx), I810_FALLBACK_TEXTURE, 1) + +#define IMPORT_FLOAT_COLORS i810_import_float_colors +#define IMPORT_FLOAT_SPEC_COLORS i810_import_float_spec_colors + +#define INTERP_VERTEX setup_tab[I810_CONTEXT(ctx)->SetupIndex].interp +#define COPY_PV_VERTEX setup_tab[I810_CONTEXT(ctx)->SetupIndex].copy_pv + + +/*********************************************************************** + * Generate pv-copying and translation functions * + ***********************************************************************/ + +#define TAG(x) i810_##x +#include "tnl_dd/t_dd_vb.c" + +/*********************************************************************** + * Generate vertex emit and interp functions * + ***********************************************************************/ + + +#define IND (I810_XYZW_BIT|I810_RGBA_BIT) +#define TAG(x) x##_wg +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I810_XYZW_BIT|I810_RGBA_BIT|I810_SPEC_BIT) +#define TAG(x) x##_wgs +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I810_XYZW_BIT|I810_RGBA_BIT|I810_TEX0_BIT) +#define TAG(x) x##_wgt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I810_XYZW_BIT|I810_RGBA_BIT|I810_TEX0_BIT|I810_TEX1_BIT) +#define TAG(x) x##_wgt0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I810_XYZW_BIT|I810_RGBA_BIT|I810_TEX0_BIT|I810_PTEX_BIT) +#define TAG(x) x##_wgpt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I810_XYZW_BIT|I810_RGBA_BIT|I810_SPEC_BIT|I810_TEX0_BIT) +#define TAG(x) x##_wgst0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I810_XYZW_BIT|I810_RGBA_BIT|I810_SPEC_BIT|I810_TEX0_BIT|\ + I810_TEX1_BIT) +#define TAG(x) x##_wgst0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I810_XYZW_BIT|I810_RGBA_BIT|I810_SPEC_BIT|I810_TEX0_BIT|\ + I810_PTEX_BIT) +#define TAG(x) x##_wgspt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I810_XYZW_BIT|I810_RGBA_BIT|I810_FOG_BIT) +#define TAG(x) x##_wgf +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I810_XYZW_BIT|I810_RGBA_BIT|I810_FOG_BIT|I810_SPEC_BIT) +#define TAG(x) x##_wgfs +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I810_XYZW_BIT|I810_RGBA_BIT|I810_FOG_BIT|I810_TEX0_BIT) +#define TAG(x) x##_wgft0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I810_XYZW_BIT|I810_RGBA_BIT|I810_FOG_BIT|I810_TEX0_BIT|\ + I810_TEX1_BIT) +#define TAG(x) x##_wgft0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I810_XYZW_BIT|I810_RGBA_BIT|I810_FOG_BIT|I810_TEX0_BIT|\ + I810_PTEX_BIT) +#define TAG(x) x##_wgfpt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I810_XYZW_BIT|I810_RGBA_BIT|I810_FOG_BIT|I810_SPEC_BIT|\ + I810_TEX0_BIT) +#define TAG(x) x##_wgfst0 +#include "tnl_dd/t_dd_vbtmp.h" -#define TEX1 { \ - v->v.tu1 = tc1[i][0]; \ - v->v.tv1 = tc1[i][1]; \ -} +#define IND (I810_XYZW_BIT|I810_RGBA_BIT|I810_FOG_BIT|I810_SPEC_BIT|\ + I810_TEX0_BIT|I810_TEX1_BIT) +#define TAG(x) x##_wgfst0t1 +#include "tnl_dd/t_dd_vbtmp.h" -/* Doesn't seem to work very well (golly). - */ -#define SPC { \ - GLubyte *spec = &(VB->Spec[0][i][0]); \ - v->v.specular.red = spec[0]; \ - v->v.specular.green = spec[1]; \ - v->v.specular.blue = spec[2]; \ -} +#define IND (I810_XYZW_BIT|I810_RGBA_BIT|I810_FOG_BIT|I810_SPEC_BIT|\ + I810_TEX0_BIT|I810_PTEX_BIT) +#define TAG(x) x##_wgfspt0 +#include "tnl_dd/t_dd_vbtmp.h" -#define FOG { \ - GLubyte *spec = &(VB->Spec[0][i][0]); \ - v->v.specular.alpha = spec[3]; \ -} +#define IND (I810_TEX0_BIT) +#define TAG(x) x##_t0 +#include "tnl_dd/t_dd_vbtmp.h" -#define COL { \ - GLubyte *col = &(VB->Color[0]->data[i][0]); \ - v->v.color.blue = col[2]; \ - v->v.color.green = col[1]; \ - v->v.color.red = col[0]; \ - v->v.color.alpha = col[3]; \ -} +#define IND (I810_TEX0_BIT|I810_TEX1_BIT) +#define TAG(x) x##_t0t1 +#include "tnl_dd/t_dd_vbtmp.h" -/* The vertex formats we have don't seem to support projective texturing - * in the multitexture case. (Would require another 1/w value for the - * second set of texcoords). - */ -#define TEX0_4 \ - if (VB->TexCoordPtr[0]->size == 4) \ - { \ - GLfloat (*tc)[4] = VB->TexCoordPtr[0]->data; \ - v = &(I810_DRIVER_DATA(VB)->verts[start]); \ - imesa->setupdone &= ~I810_WIN_BIT; \ - for (i=start; i < end; i++, v++) { \ - float oow = 1.0 / tc[i][3]; \ - v->v.oow *= tc[i][3]; \ - v->v.tu0 *= oow; \ - v->v.tv0 *= oow; \ - } \ - } - - -#define COORD \ - GLfloat *win = VB->Win.data[i]; \ - v->v.x = xoffset + win[0]; \ - v->v.y = yoffset - win[1]; \ - v->v.z = (1.0/0x10000) * win[2]; \ - v->v.oow = win[3]; - - - -#define NOP - -#define SUBPIXEL_X -0.5 -#define SUBPIXEL_Y -0.375 - - -#define SETUPFUNC(name,win,col,tex0,tex1,tex0_4,spec,fog) \ -static void name(struct vertex_buffer *VB, GLuint start, GLuint end) \ -{ \ - i810ContextPtr imesa = I810_CONTEXT( VB->ctx ); \ - __DRIdrawablePrivate *dPriv = imesa->driDrawable; \ - i810VertexPtr v; \ - GLfloat (*tc0)[4]; \ - GLfloat (*tc1)[4]; \ - const GLfloat xoffset = SUBPIXEL_X; \ - const GLfloat yoffset = dPriv->h + SUBPIXEL_Y; \ - int i; \ - (void) xoffset; \ - (void) yoffset; \ - (void) imesa; \ - \ - \ - gl_import_client_data( VB, VB->ctx->RenderFlags, \ - (VB->ClipOrMask \ - ? VEC_WRITABLE|VEC_GOOD_STRIDE \ - : VEC_GOOD_STRIDE)); \ - \ - tc0 = VB->TexCoordPtr[0]->data; \ - tc1 = VB->TexCoordPtr[1]->data; \ - \ - v = &(I810_DRIVER_DATA(VB)->verts[start]); \ - \ - if (VB->ClipOrMask == 0) \ - for (i=start; i < end; i++, v++) { \ - win; \ - col; \ - spec; \ - fog; \ - tex0; \ - tex1; \ - } \ - else \ - for (i=start; i < end; i++, v++) { \ - if (VB->ClipMask[i] == 0) { \ - win; \ - spec; \ - fog; \ - tex0; \ - tex1; \ - } \ - col; \ - } \ - tex0_4; \ -} +#define IND (I810_FOG_BIT) +#define TAG(x) x##_f +#include "tnl_dd/t_dd_vbtmp.h" +#define IND (I810_FOG_BIT|I810_TEX0_BIT) +#define TAG(x) x##_ft0 +#include "tnl_dd/t_dd_vbtmp.h" +#define IND (I810_FOG_BIT|I810_TEX0_BIT|I810_TEX1_BIT) +#define TAG(x) x##_ft0t1 +#include "tnl_dd/t_dd_vbtmp.h" - -SETUPFUNC(rs_wt0, COORD,NOP,TEX0,NOP,TEX0_4,NOP,NOP) -SETUPFUNC(rs_wt0t1, COORD,NOP,TEX0,TEX1,TEX0_4,NOP,NOP) -SETUPFUNC(rs_wft0, COORD,NOP,TEX0,NOP,TEX0_4,NOP,FOG) -SETUPFUNC(rs_wft0t1, COORD,NOP,TEX0,TEX1,TEX0_4,NOP,FOG) -SETUPFUNC(rs_wg, COORD,COL,NOP,NOP,NOP,NOP,NOP) -SETUPFUNC(rs_wgs, COORD,COL,NOP,NOP,NOP,SPC,NOP) -SETUPFUNC(rs_wgt0, COORD,COL,TEX0,NOP,TEX0_4,NOP,NOP) -SETUPFUNC(rs_wgt0t1, COORD,COL,TEX0,TEX1,TEX0_4,NOP,NOP) -SETUPFUNC(rs_wgst0, COORD,COL,TEX0,NOP,TEX0_4,SPC,NOP) -SETUPFUNC(rs_wgst0t1, COORD,COL,TEX0,TEX1,TEX0_4,SPC,NOP) -SETUPFUNC(rs_wgf, COORD,COL,NOP,NOP,NOP,NOP,FOG) -SETUPFUNC(rs_wgfs, COORD,COL,NOP,NOP,NOP,SPC,FOG) -SETUPFUNC(rs_wgft0, COORD,COL,TEX0,NOP,TEX0_4,NOP,FOG) -SETUPFUNC(rs_wgft0t1, COORD,COL,TEX0,TEX1,TEX0_4,NOP,FOG) -SETUPFUNC(rs_wgfst0, COORD,COL,TEX0,NOP,TEX0_4,SPC,FOG) -SETUPFUNC(rs_wgfst0t1, COORD,COL,TEX0,TEX1,TEX0_4,SPC,FOG) - -SETUPFUNC(rs_t0, NOP,NOP,TEX0,NOP,TEX0_4,NOP,NOP) -SETUPFUNC(rs_t0t1, NOP,NOP,TEX0,TEX1,TEX0_4,NOP,NOP) -SETUPFUNC(rs_f, NOP,NOP,NOP,NOP,NOP,NOP,FOG) -SETUPFUNC(rs_ft0, NOP,NOP,TEX0,NOP,TEX0_4,NOP,FOG) -SETUPFUNC(rs_ft0t1, NOP,NOP,TEX0,TEX1,TEX0_4,NOP,FOG) -SETUPFUNC(rs_g, NOP,COL,NOP,NOP,NOP,NOP,NOP) -SETUPFUNC(rs_gs, NOP,COL,NOP,NOP,NOP,SPC,NOP) -SETUPFUNC(rs_gt0, NOP,COL,TEX0,NOP,TEX0_4,NOP,NOP) -SETUPFUNC(rs_gt0t1, NOP,COL,TEX0,TEX1,TEX0_4,NOP,NOP) -SETUPFUNC(rs_gst0, NOP,COL,TEX0,NOP,TEX0_4,SPC,NOP) -SETUPFUNC(rs_gst0t1, NOP,COL,TEX0,TEX1,TEX0_4,SPC,NOP) -SETUPFUNC(rs_gf, NOP,COL,NOP,NOP,NOP,NOP,FOG) -SETUPFUNC(rs_gfs, NOP,COL,NOP,NOP,NOP,SPC,FOG) -SETUPFUNC(rs_gft0, NOP,COL,TEX0,NOP,TEX0_4,NOP,FOG) -SETUPFUNC(rs_gft0t1, NOP,COL,TEX0,TEX1,TEX0_4,NOP,FOG) -SETUPFUNC(rs_gfst0, NOP,COL,TEX0,NOP,TEX0_4,SPC,FOG) -SETUPFUNC(rs_gfst0t1, NOP,COL,TEX0,TEX1,TEX0_4,SPC,FOG) - - - -static void rs_invalid(struct vertex_buffer *VB, GLuint start, GLuint end) -{ - - fprintf(stderr, "i810RasterSetup(): invalid setup function\n"); -} +#define IND (I810_RGBA_BIT) +#define TAG(x) x##_g +#include "tnl_dd/t_dd_vbtmp.h" -typedef void (*setupFunc)(struct vertex_buffer *,GLuint,GLuint); +#define IND (I810_RGBA_BIT|I810_SPEC_BIT) +#define TAG(x) x##_gs +#include "tnl_dd/t_dd_vbtmp.h" -static setupFunc setup_func[0x80]; +#define IND (I810_RGBA_BIT|I810_TEX0_BIT) +#define TAG(x) x##_gt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I810_RGBA_BIT|I810_TEX0_BIT|I810_TEX1_BIT) +#define TAG(x) x##_gt0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I810_RGBA_BIT|I810_SPEC_BIT|I810_TEX0_BIT) +#define TAG(x) x##_gst0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I810_RGBA_BIT|I810_SPEC_BIT|I810_TEX0_BIT|I810_TEX1_BIT) +#define TAG(x) x##_gst0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I810_RGBA_BIT|I810_FOG_BIT) +#define TAG(x) x##_gf +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I810_RGBA_BIT|I810_FOG_BIT|I810_SPEC_BIT) +#define TAG(x) x##_gfs +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I810_RGBA_BIT|I810_FOG_BIT|I810_TEX0_BIT) +#define TAG(x) x##_gft0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I810_RGBA_BIT|I810_FOG_BIT|I810_TEX0_BIT|I810_TEX1_BIT) +#define TAG(x) x##_gft0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I810_RGBA_BIT|I810_FOG_BIT|I810_SPEC_BIT|I810_TEX0_BIT) +#define TAG(x) x##_gfst0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I810_RGBA_BIT|I810_FOG_BIT|I810_SPEC_BIT|I810_TEX0_BIT|\ + I810_TEX1_BIT) +#define TAG(x) x##_gfst0t1 +#include "tnl_dd/t_dd_vbtmp.h" -void i810DDSetupInit( void ) -{ - int i; - - for (i = 0 ; i < 0x80 ; i++) - setup_func[i] = rs_invalid; - - /* Functions to build vert's from scratch */ - setup_func[I810_WIN_BIT|I810_TEX0_BIT] = rs_wt0; - setup_func[I810_WIN_BIT|I810_TEX0_BIT|I810_TEX1_BIT] = rs_wt0t1; - setup_func[I810_WIN_BIT|I810_FOG_BIT|I810_TEX0_BIT] = rs_wft0; - setup_func[I810_WIN_BIT|I810_FOG_BIT|I810_TEX0_BIT|I810_TEX1_BIT] = rs_wft0t1; - setup_func[I810_WIN_BIT|I810_RGBA_BIT] = rs_wg; - setup_func[I810_WIN_BIT|I810_RGBA_BIT|I810_SPEC_BIT] = rs_wgs; - setup_func[I810_WIN_BIT|I810_RGBA_BIT|I810_TEX0_BIT] = rs_wgt0; - setup_func[I810_WIN_BIT|I810_RGBA_BIT|I810_TEX0_BIT|I810_TEX1_BIT] = rs_wgt0t1; - setup_func[I810_WIN_BIT|I810_RGBA_BIT|I810_SPEC_BIT|I810_TEX0_BIT] = rs_wgst0; - setup_func[I810_WIN_BIT|I810_RGBA_BIT|I810_SPEC_BIT|I810_TEX0_BIT|I810_TEX1_BIT] = rs_wgst0t1; - setup_func[I810_WIN_BIT|I810_RGBA_BIT|I810_FOG_BIT] = rs_wgf; - setup_func[I810_WIN_BIT|I810_RGBA_BIT|I810_FOG_BIT|I810_SPEC_BIT] = rs_wgfs; - setup_func[I810_WIN_BIT|I810_RGBA_BIT|I810_FOG_BIT|I810_TEX0_BIT] = rs_wgft0; - setup_func[I810_WIN_BIT|I810_RGBA_BIT|I810_FOG_BIT|I810_TEX0_BIT|I810_TEX1_BIT] = rs_wgft0t1; - setup_func[I810_WIN_BIT|I810_RGBA_BIT|I810_FOG_BIT|I810_SPEC_BIT|I810_TEX0_BIT] = rs_wgfst0; - setup_func[I810_WIN_BIT|I810_RGBA_BIT|I810_FOG_BIT|I810_SPEC_BIT|I810_TEX0_BIT|I810_TEX1_BIT] = rs_wgfst0t1; - - /* Repair functions */ - setup_func[I810_TEX0_BIT] = rs_t0; - setup_func[I810_TEX0_BIT|I810_TEX1_BIT] = rs_t0t1; - setup_func[I810_FOG_BIT] = rs_f; - setup_func[I810_FOG_BIT|I810_TEX0_BIT] = rs_ft0; - setup_func[I810_FOG_BIT|I810_TEX0_BIT|I810_TEX1_BIT] = rs_ft0t1; - setup_func[I810_RGBA_BIT] = rs_g; - setup_func[I810_RGBA_BIT|I810_SPEC_BIT] = rs_gs; - setup_func[I810_RGBA_BIT|I810_TEX0_BIT] = rs_gt0; - setup_func[I810_RGBA_BIT|I810_TEX0_BIT|I810_TEX1_BIT] = rs_gt0t1; - setup_func[I810_RGBA_BIT|I810_SPEC_BIT|I810_TEX0_BIT] = rs_gst0; - setup_func[I810_RGBA_BIT|I810_SPEC_BIT|I810_TEX0_BIT|I810_TEX1_BIT] = rs_gst0t1; - setup_func[I810_RGBA_BIT|I810_FOG_BIT] = rs_gf; - setup_func[I810_RGBA_BIT|I810_FOG_BIT|I810_SPEC_BIT] = rs_gfs; - setup_func[I810_RGBA_BIT|I810_FOG_BIT|I810_TEX0_BIT] = rs_gft0; - setup_func[I810_RGBA_BIT|I810_FOG_BIT|I810_TEX0_BIT|I810_TEX1_BIT] = rs_gft0t1; - setup_func[I810_RGBA_BIT|I810_FOG_BIT|I810_SPEC_BIT|I810_TEX0_BIT] = rs_gfst0; - setup_func[I810_RGBA_BIT|I810_FOG_BIT|I810_SPEC_BIT|I810_TEX0_BIT|I810_TEX1_BIT] = rs_gfst0t1; +static void init_setup_tab( void ) +{ + init_wg(); + init_wgs(); + init_wgt0(); + init_wgt0t1(); + init_wgpt0(); + init_wgst0(); + init_wgst0t1(); + init_wgspt0(); + init_wgf(); + init_wgfs(); + init_wgft0(); + init_wgft0t1(); + init_wgfpt0(); + init_wgfst0(); + init_wgfst0t1(); + init_wgfspt0(); + init_t0(); + init_t0t1(); + init_f(); + init_ft0(); + init_ft0t1(); + init_g(); + init_gs(); + init_gt0(); + init_gt0t1(); + init_gst0(); + init_gst0t1(); + init_gf(); + init_gfs(); + init_gft0(); + init_gft0t1(); + init_gfst0(); + init_gfst0t1(); } + void i810PrintSetupFlags(char *msg, GLuint flags ) { - fprintf(stderr, "%s: %d %s%s%s%s%s%s%s\n", + fprintf(stderr, "%s(%x): %s%s%s%s%s%s\n", msg, (int)flags, - (flags & I810_WIN_BIT) ? " xyzw," : "", + (flags & I810_XYZW_BIT) ? " xyzw," : "", (flags & I810_RGBA_BIT) ? " rgba," : "", (flags & I810_SPEC_BIT) ? " spec," : "", (flags & I810_FOG_BIT) ? " fog," : "", (flags & I810_TEX0_BIT) ? " tex-0," : "", - (flags & I810_TEX1_BIT) ? " tex-1," : "", - (flags & I810_ALPHA_BIT) ? " alpha," : ""); + (flags & I810_TEX1_BIT) ? " tex-1," : ""); } - -void i810ChooseRasterSetupFunc(GLcontext *ctx) +void i810CheckTexSizes( GLcontext *ctx ) { - i810ContextPtr imesa = I810_CONTEXT( ctx ); - int funcindex = (I810_WIN_BIT | I810_RGBA_BIT); - - imesa->vertsize = 8; - imesa->Setup[I810_CTXREG_VF] = I810_VFMT_T0; - - if (ctx->Texture.ReallyEnabled & 0xf) - funcindex |= I810_TEX0_BIT; - - if (ctx->Texture.ReallyEnabled & 0xf0) { - funcindex |= (I810_TEX0_BIT | I810_TEX1_BIT); - imesa->vertsize = 10; - imesa->Setup[I810_CTXREG_VF] = I810_VFMT_T0T1; - } - - if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) - funcindex |= I810_SPEC_BIT; - - if (ctx->FogMode == FOG_FRAGMENT) - funcindex |= I810_FOG_BIT; - - if (MESA_VERBOSE) - i810PrintSetupFlags("xsmesa: full setup function", funcindex); - - imesa->setupindex = funcindex; - ctx->Driver.RasterSetup = setup_func[funcindex]; -} - + TNLcontext *tnl = TNL_CONTEXT(ctx); + i810ContextPtr imesa = I810_CONTEXT( ctx ); + if (!setup_tab[imesa->SetupIndex].check_tex_sizes(ctx)) { + /* Invalidate stored verts + */ + imesa->SetupNewInputs = ~0; + imesa->SetupIndex |= I810_PTEX_BIT; + if (!imesa->Fallback && + !(ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) { + tnl->Driver.Render.Interp = setup_tab[imesa->SetupIndex].interp; + tnl->Driver.Render.CopyPV = setup_tab[imesa->SetupIndex].copy_pv; + } + } +} -void i810DDCheckPartialRasterSetup( GLcontext *ctx, - struct gl_pipeline_stage *d ) +void i810BuildVertices( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint newinputs ) { i810ContextPtr imesa = I810_CONTEXT( ctx ); - GLuint tmp = imesa->setupdone; + GLubyte *v = ((GLubyte *)imesa->verts + (start<<imesa->vertex_stride_shift)); + GLuint stride = 1<<imesa->vertex_stride_shift; - d->type = 0; - imesa->setupdone = 0; /* cleared if we return */ + if (0) fprintf(stderr, "%s\n", __FUNCTION__); - if ((ctx->Array.Summary & VERT_OBJ_ANY) == 0) - return; + newinputs |= imesa->SetupNewInputs; + imesa->SetupNewInputs = 0; - if (ctx->IndirectTriangles) + if (!newinputs) return; - imesa->setupdone = tmp; + if (newinputs & VERT_CLIP) { + setup_tab[imesa->SetupIndex].emit( ctx, start, count, v, stride ); + } else { + GLuint ind = 0; - /* disabled until we have a merge&render op */ - /* d->inputs = available; */ - /* d->outputs = VERT_RAST_SETUP_PART; */ - /* d->type = PIPE_PRECALC; */ -} + if (newinputs & VERT_RGBA) + ind |= I810_RGBA_BIT; + if (newinputs & VERT_SPEC_RGB) + ind |= I810_SPEC_BIT; -/* Repair existing precalculated vertices with new data. - */ -void i810DDPartialRasterSetup( struct vertex_buffer *VB ) -{ - i810ContextPtr imesa = I810_CONTEXT( VB->ctx ); - GLuint new = VB->pipeline->new_outputs; - GLuint available = VB->pipeline->outputs; - GLuint ind = 0; - - if (new & VERT_WIN) { - new = available; - ind |= I810_WIN_BIT | I810_FOG_BIT; - } + if (newinputs & VERT_TEX0) + ind |= I810_TEX0_BIT; - if (new & VERT_RGBA) - ind |= I810_RGBA_BIT | I810_SPEC_BIT; + if (newinputs & VERT_TEX1) + ind |= I810_TEX1_BIT; - if (new & VERT_TEX0_ANY) - ind |= I810_TEX0_BIT; + if (newinputs & VERT_FOG_COORD) + ind |= I810_FOG_BIT; - if (new & VERT_TEX1_ANY) - ind |= I810_TEX1_BIT; + if (imesa->SetupIndex & I810_PTEX_BIT) + ind = ~0; - if (new & VERT_FOG_COORD) - ind |= I810_FOG_BIT; - - imesa->setupdone &= ~ind; - ind &= imesa->setupindex; - imesa->setupdone |= ind; + ind &= imesa->SetupIndex; - if (0) i810PrintSetupFlags("xsmesa: partial setup function", ind); - - if (ind) - setup_func[ind&~I810_ALPHA_BIT]( VB, VB->Start, VB->Count ); + if (ind) { + setup_tab[ind].emit( ctx, start, count, v, stride ); + } + } } - -void i810DDDoRasterSetup( struct vertex_buffer *VB ) +void i810ChooseVertexState( GLcontext *ctx ) { - GLcontext *ctx = VB->ctx; - - if (VB->Type == VB_CVA_PRECALC) - i810DDPartialRasterSetup( VB ); - else if (ctx->Driver.RasterSetup) - ctx->Driver.RasterSetup( VB, VB->CopyStart, VB->Count ); -} - + TNLcontext *tnl = TNL_CONTEXT(ctx); + i810ContextPtr imesa = I810_CONTEXT( ctx ); + GLuint ind = I810_XYZW_BIT|I810_RGBA_BIT; + if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) + ind |= I810_SPEC_BIT; + if (ctx->Fog.Enabled) + ind |= I810_FOG_BIT; -void i810DDResizeVB( struct vertex_buffer *VB, GLuint size ) -{ - i810VertexBufferPtr mvb = I810_DRIVER_DATA(VB); + if (ctx->Texture._ReallyEnabled & TEXTURE1_ANY) + ind |= I810_TEX1_BIT|I810_TEX0_BIT; + else if (ctx->Texture._ReallyEnabled & TEXTURE0_ANY) + ind |= I810_TEX0_BIT; - while (mvb->size < size) - mvb->size *= 2; + imesa->SetupIndex = ind; - free( mvb->vert_store ); - mvb->vert_store = malloc( sizeof(i810Vertex) * mvb->size + 31); - if (!mvb->vert_store) { - fprintf(stderr, "i810-glx: out of memory !\n"); - exit(1); + if (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED)) { + tnl->Driver.Render.Interp = i810_interp_extras; + tnl->Driver.Render.CopyPV = i810_copy_pv_extras; + } else { + tnl->Driver.Render.Interp = setup_tab[ind].interp; + tnl->Driver.Render.CopyPV = setup_tab[ind].copy_pv; } - mvb->verts = (i810VertexPtr)(((unsigned long)mvb->vert_store + 31) & ~31); - - gl_vector1ui_free( &mvb->clipped_elements ); - gl_vector1ui_alloc( &mvb->clipped_elements, VEC_WRITABLE, mvb->size, 32 ); - if (!mvb->clipped_elements.start) { - fprintf(stderr, "i810-glx: out of memory !\n"); - exit(1); + if (setup_tab[ind].vertex_format != imesa->Setup[I810_CTXREG_VF]) { + I810_STATECHANGE(imesa, I810_UPLOAD_CTX); + imesa->Setup[I810_CTXREG_VF] = setup_tab[ind].vertex_format; + imesa->vertex_size = setup_tab[ind].vertex_size; + imesa->vertex_stride_shift = setup_tab[ind].vertex_stride_shift; } +} - ALIGN_FREE( VB->ClipMask ); - VB->ClipMask = (GLubyte *) ALIGN_MALLOC(sizeof(GLubyte) * mvb->size, 4); - if (!VB->ClipMask) { - fprintf(stderr, "i810-glx: out of memory !\n"); - exit(1); - } - if (VB->Type == VB_IMMEDIATE) { - free( mvb->primitive ); - free( mvb->next_primitive ); - mvb->primitive = (GLuint *)malloc( sizeof(GLuint) * mvb->size ); - mvb->next_primitive = (GLuint *)malloc( sizeof(GLuint) * mvb->size ); - if (!mvb->primitive || !mvb->next_primitive) { - fprintf(stderr, "i810-glx: out of memory !\n"); - exit(1); - } - } +void i810_emit_contiguous_verts( GLcontext *ctx, + GLuint start, + GLuint count ) +{ + i810ContextPtr imesa = I810_CONTEXT(ctx); + GLuint vertex_size = imesa->vertex_size * 4; + GLuint *dest = i810AllocDmaLow( imesa, (count-start) * vertex_size); + setup_tab[imesa->SetupIndex].emit( ctx, start, count, dest, vertex_size ); } -void i810DDRegisterVB( struct vertex_buffer *VB ) + +void i810InitVB( GLcontext *ctx ) { - i810VertexBufferPtr mvb; + i810ContextPtr imesa = I810_CONTEXT(ctx); + GLuint size = TNL_CONTEXT(ctx)->vb.Size; - mvb = (i810VertexBufferPtr)calloc( 1, sizeof(*mvb) ); + imesa->verts = (char *)ALIGN_MALLOC(size * 4 * 16, 32); - mvb->size = VB->Size * 2; - mvb->vert_store = malloc( sizeof(i810Vertex) * mvb->size + 31); - if (!mvb->vert_store) { - fprintf(stderr, "i810-glx: out of memory !\n"); - exit(1); + { + static int firsttime = 1; + if (firsttime) { + init_setup_tab(); + firsttime = 0; + } } - - mvb->verts = (i810VertexPtr)(((unsigned long)mvb->vert_store + 31) & ~31); +} - gl_vector1ui_alloc( &mvb->clipped_elements, VEC_WRITABLE, mvb->size, 32 ); - if (!mvb->clipped_elements.start) { - fprintf(stderr, "i810-glx: out of memory !\n"); - exit(1); - } - - ALIGN_FREE( VB->ClipMask ); - VB->ClipMask = (GLubyte *) ALIGN_MALLOC(sizeof(GLubyte) * mvb->size, 4); - if (!VB->ClipMask) { - fprintf(stderr, "i810-glx: out of memory !\n"); - exit(1); - } - mvb->primitive = (GLuint *)malloc( sizeof(GLuint) * mvb->size ); - mvb->next_primitive = (GLuint *)malloc( sizeof(GLuint) * mvb->size ); - if (!mvb->primitive || !mvb->next_primitive) { - fprintf(stderr, "i810-glx: out of memory !\n"); - exit(1); +void i810FreeVB( GLcontext *ctx ) +{ + i810ContextPtr imesa = I810_CONTEXT(ctx); + if (imesa->verts) { + ALIGN_FREE(imesa->verts); + imesa->verts = 0; } - VB->driver_data = mvb; -} - + if (imesa->UbyteSecondaryColor.Ptr) { + ALIGN_FREE(imesa->UbyteSecondaryColor.Ptr); + imesa->UbyteSecondaryColor.Ptr = 0; + } -void i810DDUnregisterVB( struct vertex_buffer *VB ) -{ - i810VertexBufferPtr mvb = I810_DRIVER_DATA(VB); - - if (mvb) { - if (mvb->vert_store) free(mvb->vert_store); - if (mvb->primitive) free(mvb->primitive); - if (mvb->next_primitive) free(mvb->next_primitive); - gl_vector1ui_free( &mvb->clipped_elements ); - free(mvb); - VB->driver_data = 0; - } + if (imesa->UbyteColor.Ptr) { + ALIGN_FREE(imesa->UbyteColor.Ptr); + imesa->UbyteColor.Ptr = 0; + } } diff --git a/xc/lib/GL/mesa/src/drv/i830/i830_render.c b/xc/lib/GL/mesa/src/drv/i830/i830_render.c index a82651c4d..8acf24f2f 100644 --- a/xc/lib/GL/mesa/src/drv/i830/i830_render.c +++ b/xc/lib/GL/mesa/src/drv/i830/i830_render.c @@ -1,4 +1,3 @@ -/* $Id: i830_render.c,v 1.2.2.1 2002/07/15 20:21:01 keithw Exp $ */ /* * Intel i810 DRI driver for Mesa 3.5 diff --git a/xc/lib/GL/mesa/src/drv/i830/i830_tris.c b/xc/lib/GL/mesa/src/drv/i830/i830_tris.c index d9a547a56..a5f230e25 100644 --- a/xc/lib/GL/mesa/src/drv/i830/i830_tris.c +++ b/xc/lib/GL/mesa/src/drv/i830/i830_tris.c @@ -1,3 +1,4 @@ +/* $XFree86$ */ /************************************************************************** Copyright 2001 VA Linux Systems Inc., Fremont, California. @@ -25,159 +26,820 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. **************************************************************************/ -/* $XFree86: xc/lib/GL/mesa/src/drv/i830/i830_tris.c,v 1.1 2001/10/04 18:28:21 alanh Exp $ */ - /* - * Author: - * Jeff Hartmann <jhartmann@valinux.com> - * - * Heavily based on the I810 driver, which was written by: - * Keith Whitwell <keithw@valinux.com> + * Original Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * Adapted for use on the I830M: + * Jeff Hartmann <jhartmann@2d3d.com> */ #include <stdio.h> #include <math.h> -#include "types.h" -#include "vb.h" -#include "pipeline.h" +#include "glheader.h" +#include "context.h" +#include "macros.h" +#include "enums.h" +#include "dd.h" -#include "mm.h" +#include "swrast/swrast.h" +#include "swrast_setup/swrast_setup.h" +#include "tnl/t_context.h" +#include "tnl/t_pipeline.h" + +#include "i830_screen.h" +#include "i830_dri.h" -#include "i830_drv.h" #include "i830_tris.h" +#include "i830_state.h" +#include "i830_vb.h" +#include "i830_ioctl.h" + +static void i830RenderPrimitive( GLcontext *ctx, GLenum prim ); + +/*********************************************************************** + * Emit primitives as inline vertices * + ***********************************************************************/ + +#if defined(USE_X86_ASM) +#define COPY_DWORDS( j, vb, vertsize, v ) \ +do { \ + int __tmp; \ + __asm__ __volatile__( "rep ; movsl" \ + : "=%c" (j), "=D" (vb), "=S" (__tmp) \ + : "0" (vertsize), \ + "D" ((long)vb), \ + "S" ((long)v) ); \ +} while (0) +#else +#define COPY_DWORDS( j, vb, vertsize, v ) \ +do { \ + for ( j = 0 ; j < vertsize ; j++ ) \ + vb[j] = ((GLuint *)v)[j]; \ + vb += vertsize; \ +} while (0) +#endif + +static void __inline__ i830_draw_triangle( i830ContextPtr imesa, + i830VertexPtr v0, + i830VertexPtr v1, + i830VertexPtr v2 ) +{ + GLuint vertsize = imesa->vertex_size; + GLuint *vb = i830AllocDmaLow( imesa, 3 * 4 * vertsize ); + int j; -/* Used in i830tritmp.h - */ -#define I830_COLOR(to, from) { \ - (to)[0] = (from)[2]; \ - (to)[1] = (from)[1]; \ - (to)[2] = (from)[0]; \ - (to)[3] = (from)[3]; \ + COPY_DWORDS( j, vb, vertsize, v0 ); + COPY_DWORDS( j, vb, vertsize, v1 ); + COPY_DWORDS( j, vb, vertsize, v2 ); } -#define I830_COLOR3(to, from) { \ - (to)[0] = (from)[2]; \ - (to)[1] = (from)[1]; \ - (to)[2] = (from)[0]; \ + +static void __inline__ i830_draw_quad( i830ContextPtr imesa, + i830VertexPtr v0, + i830VertexPtr v1, + i830VertexPtr v2, + i830VertexPtr v3 ) +{ + GLuint vertsize = imesa->vertex_size; + GLuint *vb = i830AllocDmaLow( imesa, 6 * 4 * vertsize ); + int j; + + COPY_DWORDS( j, vb, vertsize, v0 ); + COPY_DWORDS( j, vb, vertsize, v1 ); + COPY_DWORDS( j, vb, vertsize, v3 ); + COPY_DWORDS( j, vb, vertsize, v1 ); + COPY_DWORDS( j, vb, vertsize, v2 ); + COPY_DWORDS( j, vb, vertsize, v3 ); } -static triangle_func tri_tab[0x10]; -static quad_func quad_tab[0x10]; -static line_func line_tab[0x10]; -static points_func points_tab[0x10]; -#define IND (0) +static __inline__ void i830_draw_point( i830ContextPtr imesa, + i830VertexPtr tmp ) +{ + GLuint vertsize = imesa->vertex_size; + GLuint *vb = i830AllocDmaLow( imesa, 4 * vertsize ); + int j; + + /* Adjust for sub pixel position */ + *(float *)&vb[0] = tmp->v.x - 0.125; + *(float *)&vb[1] = tmp->v.y - 0.125; + for (j = 2 ; j < vertsize ; j++) + vb[j] = tmp->ui[j]; +} + + +static __inline__ void i830_draw_line( i830ContextPtr imesa, + i830VertexPtr v0, + i830VertexPtr v1 ) +{ + GLuint vertsize = imesa->vertex_size; + GLuint *vb = i830AllocDmaLow( imesa, 2 * 4 * vertsize ); + int j; + + COPY_DWORDS( j, vb, vertsize, v0 ); + COPY_DWORDS( j, vb, vertsize, v1 ); +} + + + +/*********************************************************************** + * Macros for t_dd_tritmp.h to draw basic primitives * + ***********************************************************************/ + +#define TRI( a, b, c ) \ +do { \ + if (DO_FALLBACK) \ + imesa->draw_tri( imesa, a, b, c ); \ + else \ + i830_draw_triangle( imesa, a, b, c ); \ +} while (0) + +#define QUAD( a, b, c, d ) \ +do { \ + if (DO_FALLBACK) { \ + imesa->draw_tri( imesa, a, b, d ); \ + imesa->draw_tri( imesa, b, c, d ); \ + } else \ + i830_draw_quad( imesa, a, b, c, d ); \ +} while (0) + +#define LINE( v0, v1 ) \ +do { \ + if (DO_FALLBACK) \ + imesa->draw_line( imesa, v0, v1 ); \ + else \ + i830_draw_line( imesa, v0, v1 ); \ +} while (0) + +#define POINT( v0 ) \ +do { \ + if (DO_FALLBACK) \ + imesa->draw_point( imesa, v0 ); \ + else \ + i830_draw_point( imesa, v0 ); \ +} while (0) + + +/*********************************************************************** + * Build render functions from dd templates * + ***********************************************************************/ + +#define I830_OFFSET_BIT 0x01 +#define I830_TWOSIDE_BIT 0x02 +#define I830_UNFILLED_BIT 0x04 +#define I830_FALLBACK_BIT 0x08 +#define I830_MAX_TRIFUNC 0x10 + + +static struct { + points_func points; + line_func line; + triangle_func triangle; + quad_func quad; +} rast_tab[I830_MAX_TRIFUNC]; + + +#define DO_FALLBACK (IND & I830_FALLBACK_BIT) +#define DO_OFFSET (IND & I830_OFFSET_BIT) +#define DO_UNFILLED (IND & I830_UNFILLED_BIT) +#define DO_TWOSIDE (IND & I830_TWOSIDE_BIT) +#define DO_FLAT 0 +#define DO_TRI 1 +#define DO_QUAD 1 +#define DO_LINE 1 +#define DO_POINTS 1 +#define DO_FULL_QUAD 1 + +#define HAVE_RGBA 1 +#define HAVE_SPEC 1 +#define HAVE_BACK_COLORS 0 +#define HAVE_HW_FLATSHADE 1 +#define VERTEX i830Vertex +#define TAB rast_tab + +/* Only used to pull back colors into vertices (ie, we know color is + * floating point). + */ +#define I830_COLOR( dst, src ) \ +do { \ + dst[0] = src[2]; \ + dst[1] = src[1]; \ + dst[2] = src[0]; \ + dst[3] = src[3]; \ +} while (0) + +#define I830_SPEC( dst, src ) \ +do { \ + dst[0] = src[2]; \ + dst[1] = src[1]; \ + dst[2] = src[0]; \ +} while (0) + + +#define DEPTH_SCALE (imesa->depth_scale) +#define UNFILLED_TRI unfilled_tri +#define UNFILLED_QUAD unfilled_quad +#define VERT_X(_v) _v->v.x +#define VERT_Y(_v) _v->v.y +#define VERT_Z(_v) _v->v.z +#define AREA_IS_CCW( a ) (a > 0) +#define GET_VERTEX(e) (imesa->verts + (e<<imesa->vertex_stride_shift)) + +#define VERT_SET_RGBA( v, c ) I830_COLOR( v->ub4[coloroffset], c ) +#define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset] +#define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset] +#define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx] + +#define VERT_SET_SPEC( v, c ) if (havespec) I830_SPEC( v->ub4[5], c ) +#define VERT_COPY_SPEC( v0, v1 ) if (havespec) COPY_3V(v0->ub4[5], v1->ub4[5]) +#define VERT_SAVE_SPEC( idx ) if (havespec) spec[idx] = v[idx]->ui[5] +#define VERT_RESTORE_SPEC( idx ) if (havespec) v[idx]->ui[5] = spec[idx] + +#define LOCAL_VARS(n) \ + i830ContextPtr imesa = I830_CONTEXT(ctx); \ + GLuint color[n], spec[n]; \ + GLuint coloroffset = (imesa->vertex_size == 4 ? 3 : 4); \ + GLboolean havespec = (imesa->vertex_size > 4); \ + (void) color; (void) spec; (void) coloroffset; (void) havespec; + + +/*********************************************************************** + * Helpers for rendering unfilled primitives * + ***********************************************************************/ + +static const GLuint hw_prim[GL_POLYGON+1] = { + PRIM3D_POINTLIST, + PRIM3D_LINELIST, + PRIM3D_LINELIST, + PRIM3D_LINELIST, + PRIM3D_TRILIST, + PRIM3D_TRILIST, + PRIM3D_TRILIST, + PRIM3D_TRILIST, + PRIM3D_TRILIST, + PRIM3D_TRILIST +}; + +#define RASTERIZE(x) if (imesa->hw_primitive != hw_prim[x]) \ + i830RasterPrimitive( ctx, x, hw_prim[x] ) +#define RENDER_PRIMITIVE imesa->render_primitive #define TAG(x) x -#include "i830_tritmp.h" +#define IND I830_FALLBACK_BIT +#include "tnl_dd/t_dd_unfilled.h" +#undef IND -#define IND (I830_FLAT_BIT) -#define TAG(x) x##_flat -#include "i830_tritmp.h" +/*********************************************************************** + * Generate GL render functions * + ***********************************************************************/ -#define IND (I830_OFFSET_BIT) -#define TAG(x) x##_offset -#include "i830_tritmp.h" +#define IND (0) +#define TAG(x) x +#include "tnl_dd/t_dd_tritmp.h" -#define IND (I830_OFFSET_BIT|I830_FLAT_BIT) -#define TAG(x) x##_offset_flat -#include "i830_tritmp.h" +#define IND (I830_OFFSET_BIT) +#define TAG(x) x##_offset +#include "tnl_dd/t_dd_tritmp.h" -#define IND (I830_TWOSIDE_BIT) +#define IND (I830_TWOSIDE_BIT) #define TAG(x) x##_twoside -#include "i830_tritmp.h" - -#define IND (I830_TWOSIDE_BIT|I830_FLAT_BIT) -#define TAG(x) x##_twoside_flat -#include "i830_tritmp.h" +#include "tnl_dd/t_dd_tritmp.h" -#define IND (I830_TWOSIDE_BIT|I830_OFFSET_BIT) +#define IND (I830_TWOSIDE_BIT|I830_OFFSET_BIT) #define TAG(x) x##_twoside_offset -#include "i830_tritmp.h" +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (I830_UNFILLED_BIT) +#define TAG(x) x##_unfilled +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (I830_OFFSET_BIT|I830_UNFILLED_BIT) +#define TAG(x) x##_offset_unfilled +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (I830_TWOSIDE_BIT|I830_UNFILLED_BIT) +#define TAG(x) x##_twoside_unfilled +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (I830_TWOSIDE_BIT|I830_OFFSET_BIT|I830_UNFILLED_BIT) +#define TAG(x) x##_twoside_offset_unfilled +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (I830_FALLBACK_BIT) +#define TAG(x) x##_fallback +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (I830_OFFSET_BIT|I830_FALLBACK_BIT) +#define TAG(x) x##_offset_fallback +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (I830_TWOSIDE_BIT|I830_FALLBACK_BIT) +#define TAG(x) x##_twoside_fallback +#include "tnl_dd/t_dd_tritmp.h" -#define IND (I830_TWOSIDE_BIT|I830_OFFSET_BIT|I830_FLAT_BIT) -#define TAG(x) x##_twoside_offset_flat -#include "i830_tritmp.h" +#define IND (I830_TWOSIDE_BIT|I830_OFFSET_BIT|I830_FALLBACK_BIT) +#define TAG(x) x##_twoside_offset_fallback +#include "tnl_dd/t_dd_tritmp.h" +#define IND (I830_UNFILLED_BIT|I830_FALLBACK_BIT) +#define TAG(x) x##_unfilled_fallback +#include "tnl_dd/t_dd_tritmp.h" +#define IND (I830_OFFSET_BIT|I830_UNFILLED_BIT|I830_FALLBACK_BIT) +#define TAG(x) x##_offset_unfilled_fallback +#include "tnl_dd/t_dd_tritmp.h" -void i830DDTrifuncInit() +#define IND (I830_TWOSIDE_BIT|I830_UNFILLED_BIT|I830_FALLBACK_BIT) +#define TAG(x) x##_twoside_unfilled_fallback +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (I830_TWOSIDE_BIT|I830_OFFSET_BIT|I830_UNFILLED_BIT| \ + I830_FALLBACK_BIT) +#define TAG(x) x##_twoside_offset_unfilled_fallback +#include "tnl_dd/t_dd_tritmp.h" + + +static void init_rast_tab( void ) { init(); - init_flat(); init_offset(); - init_offset_flat(); init_twoside(); - init_twoside_flat(); init_twoside_offset(); - init_twoside_offset_flat(); -} - - - -#define ALL_FALLBACK (DD_SELECT | DD_FEEDBACK) -#define POINT_FALLBACK (ALL_FALLBACK | DD_POINT_SMOOTH | DD_POINT_ATTEN) -#define LINE_FALLBACK (ALL_FALLBACK | DD_LINE_STIPPLE) -#define TRI_FALLBACK (ALL_FALLBACK | DD_TRI_UNFILLED | DD_TRI_STIPPLE | DD_TRI_SMOOTH) -#define ANY_FALLBACK (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK|DD_TRI_STIPPLE) -#define ANY_RASTER_FLAGS (DD_FLATSHADE|DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET) - -void i830DDChooseRenderState(GLcontext *ctx) -{ - i830ContextPtr imesa = I830_CONTEXT(ctx); - GLuint flags = ctx->TriangleCaps; - CARD32 index = 0; - - if (imesa->Fallback) { - imesa->renderindex = I830_FALLBACK_BIT; - return; - } - - if (flags & ANY_RASTER_FLAGS) { - if (flags & DD_FLATSHADE) index |= I830_FLAT_BIT; - if (flags & DD_TRI_LIGHT_TWOSIDE) index |= I830_TWOSIDE_BIT; - if (flags & DD_TRI_OFFSET) index |= I830_OFFSET_BIT; - } - - imesa->PointsFunc = points_tab[index]; - imesa->LineFunc = line_tab[index]; - imesa->TriangleFunc = tri_tab[index]; - imesa->QuadFunc = quad_tab[index]; - imesa->renderindex = index; - imesa->IndirectTriangles = 0; - - if (flags & ANY_FALLBACK) { - if (flags & POINT_FALLBACK) { - imesa->renderindex |= I830_FALLBACK_BIT; - imesa->PointsFunc = 0; - imesa->IndirectTriangles |= DD_POINT_SW_RASTERIZE; - } - - if (flags & LINE_FALLBACK) { - imesa->renderindex |= I830_FALLBACK_BIT; - imesa->LineFunc = 0; - imesa->IndirectTriangles |= DD_LINE_SW_RASTERIZE; - } - - if (flags & TRI_FALLBACK) { - imesa->renderindex |= I830_FALLBACK_BIT; - imesa->TriangleFunc = 0; - imesa->QuadFunc = 0; - imesa->IndirectTriangles |= (DD_TRI_SW_RASTERIZE | - DD_QUAD_SW_RASTERIZE); - } - /* Special cases: - */ - if ((flags & DD_TRI_STIPPLE) && - (ctx->IndirectTriangles & DD_TRI_STIPPLE)) { - imesa->renderindex |= I830_FALLBACK_BIT; - imesa->TriangleFunc = 0; - imesa->QuadFunc = 0; - imesa->IndirectTriangles |= (DD_TRI_SW_RASTERIZE | - DD_QUAD_SW_RASTERIZE); - } - } + init_unfilled(); + init_offset_unfilled(); + init_twoside_unfilled(); + init_twoside_offset_unfilled(); + init_fallback(); + init_offset_fallback(); + init_twoside_fallback(); + init_twoside_offset_fallback(); + init_unfilled_fallback(); + init_offset_unfilled_fallback(); + init_twoside_unfilled_fallback(); + init_twoside_offset_unfilled_fallback(); +} + + +/*********************************************************************** + * Rasterization fallback helpers * + ***********************************************************************/ + + +/* This code is hit only when a mix of accelerated and unaccelerated + * primitives are being drawn, and only for the unaccelerated + * primitives. + */ +static void +i830_fallback_tri( i830ContextPtr imesa, + i830Vertex *v0, + i830Vertex *v1, + i830Vertex *v2 ) +{ + GLcontext *ctx = imesa->glCtx; + SWvertex v[3]; + + if (DEBUGGING) + fprintf(stderr, "\n%s\n", __FUNCTION__); + + i830_translate_vertex( ctx, v0, &v[0] ); + i830_translate_vertex( ctx, v1, &v[1] ); + i830_translate_vertex( ctx, v2, &v[2] ); + _swrast_Triangle( ctx, &v[0], &v[1], &v[2] ); +} + + +static void +i830_fallback_line( i830ContextPtr imesa, + i830Vertex *v0, + i830Vertex *v1 ) +{ + GLcontext *ctx = imesa->glCtx; + SWvertex v[2]; + + if (DEBUGGING) + fprintf(stderr, "\n%s\n", __FUNCTION__); + + i830_translate_vertex( ctx, v0, &v[0] ); + i830_translate_vertex( ctx, v1, &v[1] ); + _swrast_Line( ctx, &v[0], &v[1] ); } +static void +i830_fallback_point( i830ContextPtr imesa, + i830Vertex *v0 ) +{ + GLcontext *ctx = imesa->glCtx; + SWvertex v[1]; + + if (DEBUGGING) + fprintf(stderr, "\n%s\n", __FUNCTION__); + + i830_translate_vertex( ctx, v0, &v[0] ); + _swrast_Point( ctx, &v[0] ); +} + + + +/**********************************************************************/ +/* Render unclipped begin/end objects */ +/**********************************************************************/ + +#define IND 0 +#define V(x) (i830Vertex *)(vertptr + ((x)<<vertshift)) +#define RENDER_POINTS( start, count ) \ + for ( ; start < count ; start++) POINT( V(ELT(start)) ); +#define RENDER_LINE( v0, v1 ) LINE( V(v0), V(v1) ) +#define RENDER_TRI( v0, v1, v2 ) TRI( V(v0), V(v1), V(v2) ) +#define RENDER_QUAD( v0, v1, v2, v3 ) QUAD( V(v0), V(v1), V(v2), V(v3) ) +#define INIT(x) i830RenderPrimitive( ctx, x ) +#undef LOCAL_VARS +#define LOCAL_VARS \ + i830ContextPtr imesa = I830_CONTEXT(ctx); \ + GLubyte *vertptr = (GLubyte *)imesa->verts; \ + const GLuint vertshift = imesa->vertex_stride_shift; \ + const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \ + (void) elt; +#define RESET_STIPPLE +#define RESET_OCCLUSION +#define PRESERVE_VB_DEFS +#define ELT(x) x +#define TAG(x) i830_##x##_verts +#include "tnl/t_vb_rendertmp.h" +#undef ELT +#undef TAG +#define TAG(x) i830_##x##_elts +#define ELT(x) elt[x] +#include "tnl/t_vb_rendertmp.h" + +/**********************************************************************/ +/* Render clipped primitives */ +/**********************************************************************/ + + + +static void i830RenderClippedPoly( GLcontext *ctx, const GLuint *elts, + GLuint n ) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; + GLuint prim = imesa->render_primitive; + + if (DEBUGGING) + fprintf(stderr, "\n%s\n", __FUNCTION__); + + /* Render the new vertices as an unclipped polygon. + */ + { + GLuint *tmp = VB->Elts; + VB->Elts = (GLuint *)elts; + tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, + PRIM_BEGIN|PRIM_END ); + VB->Elts = tmp; + } + + /* Restore the render primitive + */ + if (prim != GL_POLYGON) + tnl->Driver.Render.PrimitiveNotify( ctx, prim ); +} + +static void i830RenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + + if (DEBUGGING) + fprintf(stderr, "\n%s\n", __FUNCTION__); + tnl->Driver.Render.Line( ctx, ii, jj ); +} + +static void i830FastRenderClippedPoly( GLcontext *ctx, const GLuint *elts, + GLuint n ) +{ + i830ContextPtr imesa = I830_CONTEXT( ctx ); + GLuint vertsize = imesa->vertex_size; + GLuint *vb = i830AllocDmaLow( imesa, (n-2) * 3 * 4 * vertsize ); + GLubyte *vertptr = (GLubyte *)imesa->verts; + const GLuint vertshift = imesa->vertex_stride_shift; + const GLuint *start = (const GLuint *)V(elts[0]); + int i,j; + + if (DEBUGGING) + fprintf(stderr, "\n%s\n", __FUNCTION__); + + for (i = 2 ; i < n ; i++) { + COPY_DWORDS( j, vb, vertsize, V(elts[i-1]) ); + COPY_DWORDS( j, vb, vertsize, V(elts[i]) ); + COPY_DWORDS( j, vb, vertsize, start ); + } +} + +/**********************************************************************/ +/* Choose render functions */ +/**********************************************************************/ + + + +#define _I830_NEW_RENDERSTATE (_DD_NEW_LINE_STIPPLE | \ + _DD_NEW_TRI_UNFILLED | \ + _DD_NEW_TRI_LIGHT_TWOSIDE | \ + _DD_NEW_TRI_OFFSET | \ + _DD_NEW_TRI_STIPPLE | \ + _NEW_POLYGONSTIPPLE) + +#define POINT_FALLBACK (0) +#define LINE_FALLBACK (DD_LINE_STIPPLE) +#define TRI_FALLBACK (DD_TRI_STIPPLE) +#define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK|\ + DD_TRI_STIPPLE) +#define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED) + +static void i830ChooseRenderState(GLcontext *ctx) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + i830ContextPtr imesa = I830_CONTEXT(ctx); + GLuint flags = ctx->_TriangleCaps; + GLuint index = 0; + if (DEBUGGING) + fprintf(stderr,"\n%s\n",__FUNCTION__); + + if (flags & (ANY_FALLBACK_FLAGS|ANY_RASTER_FLAGS)) { + if (flags & ANY_RASTER_FLAGS) { + if (flags & DD_TRI_LIGHT_TWOSIDE) index |= I830_TWOSIDE_BIT; + if (flags & DD_TRI_OFFSET) index |= I830_OFFSET_BIT; + if (flags & DD_TRI_UNFILLED) index |= I830_UNFILLED_BIT; + } + + imesa->draw_point = i830_draw_point; + imesa->draw_line = i830_draw_line; + imesa->draw_tri = i830_draw_triangle; + + /* Hook in fallbacks for specific primitives. + */ + if (flags & ANY_FALLBACK_FLAGS) + { + if (flags & POINT_FALLBACK) + imesa->draw_point = i830_fallback_point; + + if (flags & LINE_FALLBACK) + imesa->draw_line = i830_fallback_line; + + if (flags & TRI_FALLBACK) + imesa->draw_tri = i830_fallback_tri; + + if (flags & DD_TRI_STIPPLE) + imesa->draw_tri = i830_fallback_tri; + + index |= I830_FALLBACK_BIT; + } + } + + if (imesa->RenderIndex != index) { + imesa->RenderIndex = index; + + tnl->Driver.Render.Points = rast_tab[index].points; + tnl->Driver.Render.Line = rast_tab[index].line; + tnl->Driver.Render.Triangle = rast_tab[index].triangle; + tnl->Driver.Render.Quad = rast_tab[index].quad; + + if (index == 0) { + tnl->Driver.Render.PrimTabVerts = i830_render_tab_verts; + tnl->Driver.Render.PrimTabElts = i830_render_tab_elts; + tnl->Driver.Render.ClippedLine = line; /* from tritmp.h */ + tnl->Driver.Render.ClippedPolygon = i830FastRenderClippedPoly; + } else { + tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts; + tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts; + tnl->Driver.Render.ClippedLine = i830RenderClippedLine; + tnl->Driver.Render.ClippedPolygon = i830RenderClippedPoly; + } + } +} + +static const GLenum reduced_prim[GL_POLYGON+1] = { + GL_POINTS, + GL_LINES, + GL_LINES, + GL_LINES, + GL_TRIANGLES, + GL_TRIANGLES, + GL_TRIANGLES, + GL_TRIANGLES, + GL_TRIANGLES, + GL_TRIANGLES +}; + + +/**********************************************************************/ +/* High level hooks for t_vb_render.c */ +/**********************************************************************/ + + + +/* Determine the rasterized primitive when not drawing unfilled + * polygons. + * + * Used only for the default render stage which always decomposes + * primitives to trianges/lines/points. For the accelerated stage, + * which renders strips as strips, the equivalent calculations are + * performed in i810render.c. + */ +static void i830RenderPrimitive( GLcontext *ctx, GLenum prim ) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + GLuint rprim = reduced_prim[prim]; + + imesa->render_primitive = prim; + + if (rprim == GL_TRIANGLES && (ctx->_TriangleCaps & DD_TRI_UNFILLED)) + return; + + if (imesa->reduced_primitive != rprim || + hw_prim[prim] != imesa->hw_primitive) { + i830RasterPrimitive( ctx, rprim, hw_prim[prim] ); + } +} + +static void i830RunPipeline( GLcontext *ctx ) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + + if (imesa->new_state) { + if (imesa->new_state & _NEW_TEXTURE) + i830UpdateTextureState( ctx ); /* may modify imesa->new_state */ + + if (!imesa->Fallback) { + if (imesa->new_state & _I830_NEW_VERTEX) + i830ChooseVertexState( ctx ); + + if (imesa->new_state & _I830_NEW_RENDERSTATE) + i830ChooseRenderState( ctx ); + } + + imesa->new_state = 0; + } + + _tnl_run_pipeline( ctx ); +} + +static void i830RenderStart( GLcontext *ctx ) +{ + /* Check for projective textureing. Make sure all texcoord + * pointers point to something. (fix in mesa?) + */ + + i830CheckTexSizes( ctx ); +} + +static void i830RenderFinish( GLcontext *ctx ) +{ + if (I830_CONTEXT(ctx)->RenderIndex & I830_FALLBACK_BIT) + _swrast_flush( ctx ); +} + + + + +/* System to flush dma and emit state changes based on the rasterized + * primitive. + */ +void i830RasterPrimitive( GLcontext *ctx, + GLenum rprim, + GLuint hwprim ) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + GLuint aa = imesa->Setup[I830_CTXREG_AA]; + + aa &= ~AA_LINE_ENABLE; + + if (0) { + /* Prints reduced prim, and hw prim */ + char *prim_name = "Unknown"; + + switch(hwprim) { + case PRIM3D_POINTLIST: + prim_name = "PointList"; + break; + case PRIM3D_LINELIST: + prim_name = "LineList"; + break; + case PRIM3D_LINESTRIP: + prim_name = "LineStrip"; + break; + case PRIM3D_TRILIST: + prim_name = "TriList"; + break; + case PRIM3D_TRISTRIP: + prim_name = "TriStrip"; + break; + case PRIM3D_TRIFAN: + prim_name = "TriFan"; + break; + case PRIM3D_POLY: + prim_name = "Polygons"; + break; + default: + break; + } + + fprintf(stderr, "%s : rprim(%s), hwprim(%s)\n", + __FUNCTION__, + _mesa_lookup_enum_by_nr(rprim), + prim_name); + } + + switch (rprim) { + case GL_TRIANGLES: + aa |= AA_LINE_DISABLE; + break; + case GL_LINES: + if (ctx->Line.SmoothFlag) { + aa |= AA_LINE_ENABLE; + } else { + aa |= AA_LINE_DISABLE; + } + break; + case GL_POINTS: + aa |= AA_LINE_DISABLE; + break; + default: + return; + } + + imesa->reduced_primitive = rprim; + + if (aa != imesa->Setup[I830_CTXREG_AA]) { + I830_STATECHANGE(imesa, I830_UPLOAD_CTX); + imesa->hw_primitive = hwprim; + imesa->Setup[I830_CTXREG_AA] = aa; + } + else if (hwprim != imesa->hw_primitive) { + I830_STATECHANGE(imesa, 0); + imesa->hw_primitive = hwprim; + } +} + +/**********************************************************************/ +/* Transition to/from hardware rasterization. */ +/**********************************************************************/ + + +void i830Fallback( i830ContextPtr imesa, GLuint bit, GLboolean mode ) +{ + GLcontext *ctx = imesa->glCtx; + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLuint oldfallback = imesa->Fallback; + + if (0) fprintf(stderr, "%s old %x bit %x mode %d\n", __FUNCTION__, + imesa->Fallback, bit, mode ); + + if (mode) { + imesa->Fallback |= bit; + if (oldfallback == 0) { + if (0) fprintf(stderr, "ENTER FALLBACK\n"); + I830_FIREVERTICES(imesa); + _swsetup_Wakeup( ctx ); + imesa->RenderIndex = ~0; + } + } + else { + imesa->Fallback &= ~bit; + if (oldfallback == bit) { + if (0) fprintf(stderr, "LEAVE FALLBACK\n"); + _swrast_flush( ctx ); + tnl->Driver.Render.Start = i830RenderStart; + tnl->Driver.Render.PrimitiveNotify = i830RenderPrimitive; + tnl->Driver.Render.Finish = i830RenderFinish; + tnl->Driver.Render.BuildVertices = i830BuildVertices; + imesa->new_state |= (_I830_NEW_RENDERSTATE|_I830_NEW_VERTEX); + } + } +} + + + + +/**********************************************************************/ +/* Initialization. */ +/**********************************************************************/ + + +void i830InitTriFuncs( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + static int firsttime = 1; + + if (firsttime) { + init_rast_tab(); + firsttime = 0; + } + + tnl->Driver.RunPipeline = i830RunPipeline; + tnl->Driver.Render.Start = i830RenderStart; + tnl->Driver.Render.Finish = i830RenderFinish; + tnl->Driver.Render.PrimitiveNotify = i830RenderPrimitive; + tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple; + tnl->Driver.Render.BuildVertices = i830BuildVertices; +} diff --git a/xc/lib/GL/mesa/src/drv/i830/i830_vb.c b/xc/lib/GL/mesa/src/drv/i830/i830_vb.c index dad88fa2f..007fe0a45 100644 --- a/xc/lib/GL/mesa/src/drv/i830/i830_vb.c +++ b/xc/lib/GL/mesa/src/drv/i830/i830_vb.c @@ -1,480 +1,593 @@ -/************************************************************************** - -Copyright 2001 VA Linux Systems Inc., Fremont, California. - -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 -on the rights to use, copy, modify, merge, publish, distribute, sub -license, and/or sell copies of the Software, and to permit persons to whom -the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice (including the next -paragraph) shall be included in all copies or substantial portions of the -Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL -ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -USE OR OTHER DEALINGS IN THE SOFTWARE. - -**************************************************************************/ - -/* $XFree86: xc/lib/GL/mesa/src/drv/i830/i830_vb.c,v 1.1 2001/10/04 18:28:21 alanh Exp $ */ - /* - * Author: - * Jeff Hartmann <jhartmann@valinux.com> + * GLX Hardware Device Driver for Intel i810 + * Copyright (C) 1999 Keith Whitwell + * + * 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. * - * Heavily based on the I810 driver, which was written by: - * Keith Whitwell <keithw@valinux.com> + * 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 + * KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS 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. + * + * Adapted for use on the I830M: + * Jeff Hartmann <jhartmann@2d3d.com> */ - -#include <stdio.h> -#include <stdlib.h> +/* $XFree86$ */ -#include "i830_drv.h" +#include "glheader.h" +#include "mtypes.h" #include "mem.h" -#include "stages.h" +#include "macros.h" +#include "colormac.h" +#include "mmath.h" -#define TEX0 { \ - v->v.tu0 = tc0[i][0]; \ - v->v.tv0 = tc0[i][1]; \ -} - -#define TEX1 { \ - v->v.tu1 = tc1[i][0]; \ - v->v.tv1 = tc1[i][1]; \ -} +#include "swrast_setup/swrast_setup.h" +#include "tnl/t_context.h" -/* Doesn't seem to work very well (golly). - */ -#define SPC { \ - GLubyte *spec = &(VB->Spec[0][i][0]); \ - v->v.specular.red = spec[0]; \ - v->v.specular.green = spec[1]; \ - v->v.specular.blue = spec[2]; \ -} - -#define FOG { \ - GLubyte *spec = &(VB->Spec[0][i][0]); \ - v->v.specular.alpha = spec[3]; \ -} +#include "i830_screen.h" +#include "i830_dri.h" -#define COL { \ - GLubyte *col = &(VB->Color[0]->data[i][0]); \ - v->v.color.blue = col[2]; \ - v->v.color.green = col[1]; \ - v->v.color.red = col[0]; \ - v->v.color.alpha = col[3]; \ -} +#include "i830_context.h" +#include "i830_vb.h" +#include "i830_ioctl.h" +#include "i830_tris.h" +#include "i830_state.h" +#include "i830_drv.h" -/* The vertex formats we have don't seem to support projective texturing - * in the multitexture case. (Would require another 1/w value for the - * second set of texcoords). - * XXX grantham - i830 does q coordinate, haven't spent time to figure out - * how to implement dynamic HOMOGENOUS coord; plus need to copy tc[i][2] - * for cube maps, not tc[i][3] +#define I830_TEX1_BIT 0x1 +#define I830_TEX0_BIT 0x2 +#define I830_RGBA_BIT 0x4 +#define I830_SPEC_BIT 0x8 +#define I830_FOG_BIT 0x10 +#define I830_XYZW_BIT 0x20 +#define I830_PTEX_BIT 0x40 +#define I830_MAX_SETUP 0x80 + +static struct { + void (*emit)( GLcontext *, GLuint, GLuint, void *, GLuint ); + interp_func interp; + copy_pv_func copy_pv; + GLboolean (*check_tex_sizes)( GLcontext *ctx ); + GLuint vertex_size; + GLuint vertex_stride_shift; + GLuint vertex_format; +} setup_tab[I830_MAX_SETUP]; + +#define TINY_VERTEX_FORMAT (STATE3D_VERTEX_FORMAT_CMD | \ + VRTX_TEX_COORD_COUNT(0) | \ + VRTX_HAS_DIFFUSE | \ + VRTX_HAS_XYZ) + +#define NOTEX_VERTEX_FORMAT (STATE3D_VERTEX_FORMAT_CMD | \ + VRTX_TEX_COORD_COUNT(0) | \ + VRTX_HAS_DIFFUSE | \ + VRTX_HAS_SPEC | \ + VRTX_HAS_XYZW) + +#define TEX0_VERTEX_FORMAT (STATE3D_VERTEX_FORMAT_CMD | \ + VRTX_TEX_COORD_COUNT(1) | \ + VRTX_HAS_DIFFUSE | \ + VRTX_HAS_SPEC | \ + VRTX_HAS_XYZW) + +#define TEX1_VERTEX_FORMAT (STATE3D_VERTEX_FORMAT_CMD | \ + VRTX_TEX_COORD_COUNT(2) | \ + VRTX_HAS_DIFFUSE | \ + VRTX_HAS_SPEC | \ + VRTX_HAS_XYZW) + + +/* I'm cheating here hardcore : if bit 31 is set I know to emit + * a vf2 state == TEXCOORDFMT_3D. We never mix 2d/3d texcoords, + * so this solution works for now. */ -#define TEX0_4 \ - if (VB->TexCoordPtr[0]->size == 4) \ - { \ - GLfloat (*tc)[4] = VB->TexCoordPtr[0]->data; \ - v = &(I830_DRIVER_DATA(VB)->verts[start]); \ - imesa->setupdone &= ~I830_WIN_BIT; \ - for (i=start; i < end; i++, v++) { \ - float oow = 1.0 / tc[i][3]; \ - v->v.oow *= tc[i][3]; \ - v->v.tu0 *= oow; \ - v->v.tv0 *= oow; \ - } \ - } - -#define COORD \ - GLfloat *win = VB->Win.data[i]; \ - v->v.x = xoffset + win[0]; \ - v->v.y = yoffset - win[1]; \ - v->v.z = depth_scale * win[2]; \ - v->v.oow = win[3]; - - -#define NOP -#define SUBPIXEL_X 0.125 -#define SUBPIXEL_Y 0.125 - -#define SETUPFUNC(name,win,col,tex0,tex1,tex0_4,spec,fog) \ -static void name(struct vertex_buffer *VB, GLuint start, GLuint end) \ -{ \ - i830ContextPtr imesa = I830_CONTEXT( VB->ctx ); \ - __DRIdrawablePrivate *dPriv = imesa->driDrawable; \ - i830VertexPtr v; \ - GLfloat (*tc0)[4]; \ - GLfloat (*tc1)[4]; \ - const GLfloat depth_scale = imesa->depth_scale; \ - const GLfloat xoffset = SUBPIXEL_X; \ - const GLfloat yoffset = dPriv->h + SUBPIXEL_Y; \ - int i; \ - (void) xoffset; \ - (void) yoffset; \ - (void) imesa; \ - (void) depth_scale; \ - \ - \ - gl_import_client_data( VB, VB->ctx->RenderFlags, \ - (VB->ClipOrMask \ - ? VEC_WRITABLE|VEC_GOOD_STRIDE \ - : VEC_GOOD_STRIDE)); \ - \ - tc0 = VB->TexCoordPtr[0]->data; \ - tc1 = VB->TexCoordPtr[1]->data; \ - \ - v = &(I830_DRIVER_DATA(VB)->verts[start]); \ - \ - if (VB->ClipOrMask == 0) \ - for (i=start; i < end; i++, v++) { \ - win; \ - col; \ - spec; \ - fog; \ - tex0; \ - tex1; \ - } \ - else \ - for (i=start; i < end; i++, v++) { \ - if (VB->ClipMask[i] == 0) { \ - win; \ - spec; \ - fog; \ - tex0; \ - tex1; \ - } \ - col; \ - } \ - tex0_4; \ - /* tex1_4; */ \ - /* tex2_4; */ \ - /* tex3_4; */ \ -} - -SETUPFUNC(rs_wt0, COORD,NOP,TEX0,NOP,TEX0_4,NOP,NOP) -SETUPFUNC(rs_wt0t1, COORD,NOP,TEX0,TEX1,TEX0_4,NOP,NOP) -SETUPFUNC(rs_wft0, COORD,NOP,TEX0,NOP,TEX0_4,NOP,FOG) -SETUPFUNC(rs_wft0t1, COORD,NOP,TEX0,TEX1,TEX0_4,NOP,FOG) -SETUPFUNC(rs_wg, COORD,COL,NOP,NOP,NOP,NOP,NOP) -SETUPFUNC(rs_wgs, COORD,COL,NOP,NOP,NOP,SPC,NOP) -SETUPFUNC(rs_wgt0, COORD,COL,TEX0,NOP,TEX0_4,NOP,NOP) -SETUPFUNC(rs_wgt0t1, COORD,COL,TEX0,TEX1,TEX0_4,NOP,NOP) -SETUPFUNC(rs_wgst0, COORD,COL,TEX0,NOP,TEX0_4,SPC,NOP) -SETUPFUNC(rs_wgst0t1, COORD,COL,TEX0,TEX1,TEX0_4,SPC,NOP) -SETUPFUNC(rs_wgf, COORD,COL,NOP,NOP,NOP,NOP,FOG) -SETUPFUNC(rs_wgfs, COORD,COL,NOP,NOP,NOP,SPC,FOG) -SETUPFUNC(rs_wgft0, COORD,COL,TEX0,NOP,TEX0_4,NOP,FOG) -SETUPFUNC(rs_wgft0t1, COORD,COL,TEX0,TEX1,TEX0_4,NOP,FOG) -SETUPFUNC(rs_wgfst0, COORD,COL,TEX0,NOP,TEX0_4,SPC,FOG) -SETUPFUNC(rs_wgfst0t1, COORD,COL,TEX0,TEX1,TEX0_4,SPC,FOG) - -SETUPFUNC(rs_t0, NOP,NOP,TEX0,NOP,TEX0_4,NOP,NOP) -SETUPFUNC(rs_t0t1, NOP,NOP,TEX0,TEX1,TEX0_4,NOP,NOP) -SETUPFUNC(rs_f, NOP,NOP,NOP,NOP,NOP,NOP,FOG) -SETUPFUNC(rs_ft0, NOP,NOP,TEX0,NOP,TEX0_4,NOP,FOG) -SETUPFUNC(rs_ft0t1, NOP,NOP,TEX0,TEX1,TEX0_4,NOP,FOG) -SETUPFUNC(rs_g, NOP,COL,NOP,NOP,NOP,NOP,NOP) -SETUPFUNC(rs_gs, NOP,COL,NOP,NOP,NOP,SPC,NOP) -SETUPFUNC(rs_gt0, NOP,COL,TEX0,NOP,TEX0_4,NOP,NOP) -SETUPFUNC(rs_gt0t1, NOP,COL,TEX0,TEX1,TEX0_4,NOP,NOP) -SETUPFUNC(rs_gst0, NOP,COL,TEX0,NOP,TEX0_4,SPC,NOP) -SETUPFUNC(rs_gst0t1, NOP,COL,TEX0,TEX1,TEX0_4,SPC,NOP) -SETUPFUNC(rs_gf, NOP,COL,NOP,NOP,NOP,NOP,FOG) -SETUPFUNC(rs_gfs, NOP,COL,NOP,NOP,NOP,SPC,FOG) -SETUPFUNC(rs_gft0, NOP,COL,TEX0,NOP,TEX0_4,NOP,FOG) -SETUPFUNC(rs_gft0t1, NOP,COL,TEX0,TEX1,TEX0_4,NOP,FOG) -SETUPFUNC(rs_gfst0, NOP,COL,TEX0,NOP,TEX0_4,SPC,FOG) -SETUPFUNC(rs_gfst0t1, NOP,COL,TEX0,TEX1,TEX0_4,SPC,FOG) - - - -static void rs_invalid(struct vertex_buffer *VB, GLuint start, GLuint end) -{ - - fprintf(stderr, "i830RasterSetup(): invalid setup function\n"); -} +#define PROJ_TEX1_VERTEX_FORMAT ((1<<31) | \ + STATE3D_VERTEX_FORMAT_CMD | \ + VRTX_TEX_COORD_COUNT(2) | \ + VRTX_HAS_DIFFUSE | \ + VRTX_HAS_SPEC | \ + VRTX_HAS_XYZW) + +/* Might want to do these later */ +#define TEX2_VERTEX_FORMAT 0 +#define TEX3_VERTEX_FORMAT 0 +#define PROJ_TEX3_VERTEX_FORMAT 0 + +#define DO_XYZW (IND & I830_XYZW_BIT) +#define DO_RGBA (IND & I830_RGBA_BIT) +#define DO_SPEC (IND & I830_SPEC_BIT) +#define DO_FOG (IND & I830_FOG_BIT) +#define DO_TEX0 (IND & I830_TEX0_BIT) +#define DO_TEX1 (IND & I830_TEX1_BIT) +#define DO_TEX2 0 +#define DO_TEX3 0 +#define DO_PTEX (IND & I830_PTEX_BIT) + +#define VERTEX i830Vertex +#define VERTEX_COLOR i830_color_t +#define GET_VIEWPORT_MAT() I830_CONTEXT(ctx)->ViewportMatrix.m +#define GET_TEXSOURCE(n) n +#define GET_VERTEX_FORMAT() I830_CONTEXT(ctx)->vertex_format +#define GET_VERTEX_STORE() I830_CONTEXT(ctx)->verts +#define GET_VERTEX_STRIDE_SHIFT() I830_CONTEXT(ctx)->vertex_stride_shift +#define GET_UBYTE_COLOR_STORE() &I830_CONTEXT(ctx)->UbyteColor +#define GET_UBYTE_SPEC_COLOR_STORE() &I830_CONTEXT(ctx)->UbyteSecondaryColor +#define INVALIDATE_STORED_VERTICES() + +#define HAVE_HW_VIEWPORT 0 +#define HAVE_HW_DIVIDE 0 +#define HAVE_RGBA_COLOR 0 +#define HAVE_TINY_VERTICES 1 +#define HAVE_NOTEX_VERTICES 1 +#define HAVE_TEX0_VERTICES 1 +#define HAVE_TEX1_VERTICES 1 +#define HAVE_TEX2_VERTICES 0 +#define HAVE_TEX3_VERTICES 0 +#define HAVE_PTEX_VERTICES 1 + +#define UNVIEWPORT_VARS GLfloat h = I830_CONTEXT(ctx)->driDrawable->h +#define UNVIEWPORT_X(x) x - SUBPIXEL_X +#define UNVIEWPORT_Y(y) - y + h + SUBPIXEL_Y +#define UNVIEWPORT_Z(z) z * (float)I830_CONTEXT(ctx)->ClearDepth + +#define PTEX_FALLBACK() FALLBACK(I830_CONTEXT(ctx), I830_FALLBACK_TEXTURE, 1) + +#define IMPORT_FLOAT_COLORS i830_import_float_colors +#define IMPORT_FLOAT_SPEC_COLORS i830_import_float_spec_colors + +#define INTERP_VERTEX setup_tab[I830_CONTEXT(ctx)->SetupIndex].interp +#define COPY_PV_VERTEX setup_tab[I830_CONTEXT(ctx)->SetupIndex].copy_pv + + +/*********************************************************************** + * Generate pv-copying and translation functions * + ***********************************************************************/ + +#define TAG(x) i830_##x +#include "tnl_dd/t_dd_vb.c" + +/*********************************************************************** + * Generate vertex emit and interp functions * + ***********************************************************************/ + +#define IND (I830_XYZW_BIT|I830_RGBA_BIT) +#define TAG(x) x##_wg +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_XYZW_BIT|I830_RGBA_BIT|I830_SPEC_BIT) +#define TAG(x) x##_wgs +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_XYZW_BIT|I830_RGBA_BIT|I830_TEX0_BIT) +#define TAG(x) x##_wgt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_XYZW_BIT|I830_RGBA_BIT|I830_TEX0_BIT|I830_TEX1_BIT) +#define TAG(x) x##_wgt0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_XYZW_BIT|I830_RGBA_BIT|I830_TEX0_BIT|I830_PTEX_BIT) +#define TAG(x) x##_wgpt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_XYZW_BIT|I830_RGBA_BIT|I830_SPEC_BIT|I830_TEX0_BIT) +#define TAG(x) x##_wgst0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_XYZW_BIT|I830_RGBA_BIT|I830_SPEC_BIT|I830_TEX0_BIT|\ + I830_TEX1_BIT) +#define TAG(x) x##_wgst0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_XYZW_BIT|I830_RGBA_BIT|I830_SPEC_BIT|I830_TEX0_BIT|\ + I830_PTEX_BIT) +#define TAG(x) x##_wgspt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_XYZW_BIT|I830_RGBA_BIT|I830_FOG_BIT) +#define TAG(x) x##_wgf +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_XYZW_BIT|I830_RGBA_BIT|I830_FOG_BIT|I830_SPEC_BIT) +#define TAG(x) x##_wgfs +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_XYZW_BIT|I830_RGBA_BIT|I830_FOG_BIT|I830_TEX0_BIT) +#define TAG(x) x##_wgft0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_XYZW_BIT|I830_RGBA_BIT|I830_FOG_BIT|I830_TEX0_BIT|\ + I830_TEX1_BIT) +#define TAG(x) x##_wgft0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_XYZW_BIT|I830_RGBA_BIT|I830_FOG_BIT|I830_TEX0_BIT|\ + I830_PTEX_BIT) +#define TAG(x) x##_wgfpt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_XYZW_BIT|I830_RGBA_BIT|I830_FOG_BIT|I830_SPEC_BIT|\ + I830_TEX0_BIT) +#define TAG(x) x##_wgfst0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_XYZW_BIT|I830_RGBA_BIT|I830_FOG_BIT|I830_SPEC_BIT|\ + I830_TEX0_BIT|I830_TEX1_BIT) +#define TAG(x) x##_wgfst0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_XYZW_BIT|I830_RGBA_BIT|I830_FOG_BIT|I830_SPEC_BIT|\ + I830_TEX0_BIT|I830_PTEX_BIT) +#define TAG(x) x##_wgfspt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_TEX0_BIT) +#define TAG(x) x##_t0 +#include "tnl_dd/t_dd_vbtmp.h" -typedef void (*setupFunc)(struct vertex_buffer *,GLuint,GLuint); +#define IND (I830_TEX0_BIT|I830_TEX1_BIT) +#define TAG(x) x##_t0t1 +#include "tnl_dd/t_dd_vbtmp.h" -static setupFunc setup_func[0x80]; +#define IND (I830_FOG_BIT) +#define TAG(x) x##_f +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_FOG_BIT|I830_TEX0_BIT) +#define TAG(x) x##_ft0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_FOG_BIT|I830_TEX0_BIT|I830_TEX1_BIT) +#define TAG(x) x##_ft0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_RGBA_BIT) +#define TAG(x) x##_g +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_RGBA_BIT|I830_SPEC_BIT) +#define TAG(x) x##_gs +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_RGBA_BIT|I830_TEX0_BIT) +#define TAG(x) x##_gt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_RGBA_BIT|I830_TEX0_BIT|I830_TEX1_BIT) +#define TAG(x) x##_gt0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_RGBA_BIT|I830_SPEC_BIT|I830_TEX0_BIT) +#define TAG(x) x##_gst0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_RGBA_BIT|I830_SPEC_BIT|I830_TEX0_BIT|I830_TEX1_BIT) +#define TAG(x) x##_gst0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_RGBA_BIT|I830_FOG_BIT) +#define TAG(x) x##_gf +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_RGBA_BIT|I830_FOG_BIT|I830_SPEC_BIT) +#define TAG(x) x##_gfs +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_RGBA_BIT|I830_FOG_BIT|I830_TEX0_BIT) +#define TAG(x) x##_gft0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_RGBA_BIT|I830_FOG_BIT|I830_TEX0_BIT|I830_TEX1_BIT) +#define TAG(x) x##_gft0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_RGBA_BIT|I830_FOG_BIT|I830_SPEC_BIT|I830_TEX0_BIT) +#define TAG(x) x##_gfst0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_RGBA_BIT|I830_FOG_BIT|I830_SPEC_BIT|I830_TEX0_BIT|\ + I830_TEX1_BIT) +#define TAG(x) x##_gfst0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +/* Add functions for proj texturing for t0 and t1 */ +#define IND (I830_XYZW_BIT|I830_RGBA_BIT|I830_TEX0_BIT|I830_TEX1_BIT|\ + I830_PTEX_BIT) +#define TAG(x) x##_wgpt0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_XYZW_BIT|I830_RGBA_BIT|I830_SPEC_BIT|I830_TEX0_BIT|\ + I830_TEX1_BIT|I830_PTEX_BIT) +#define TAG(x) x##_wgspt0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_XYZW_BIT|I830_RGBA_BIT|I830_FOG_BIT|I830_TEX0_BIT|\ + I830_TEX1_BIT|I830_PTEX_BIT) +#define TAG(x) x##_wgfpt0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_XYZW_BIT|I830_RGBA_BIT|I830_FOG_BIT|I830_SPEC_BIT|\ + I830_TEX1_BIT|I830_TEX0_BIT|I830_PTEX_BIT) +#define TAG(x) x##_wgfspt0t1 +#include "tnl_dd/t_dd_vbtmp.h" -void i830DDSetupInit( void ) + +static void init_setup_tab( void ) { - int i; - - for (i = 0 ; i < 0x80 ; i++) - setup_func[i] = rs_invalid; - - /* Functions to build vert's from scratch */ - setup_func[I830_WIN_BIT|I830_TEX0_BIT] = rs_wt0; - setup_func[I830_WIN_BIT|I830_TEX0_BIT|I830_TEX1_BIT] = rs_wt0t1; - setup_func[I830_WIN_BIT|I830_FOG_BIT|I830_TEX0_BIT] = rs_wft0; - setup_func[I830_WIN_BIT|I830_FOG_BIT|I830_TEX0_BIT|I830_TEX1_BIT] = rs_wft0t1; - setup_func[I830_WIN_BIT|I830_RGBA_BIT] = rs_wg; - setup_func[I830_WIN_BIT|I830_RGBA_BIT|I830_SPEC_BIT] = rs_wgs; - setup_func[I830_WIN_BIT|I830_RGBA_BIT|I830_TEX0_BIT] = rs_wgt0; - setup_func[I830_WIN_BIT|I830_RGBA_BIT|I830_TEX0_BIT|I830_TEX1_BIT] = rs_wgt0t1; - setup_func[I830_WIN_BIT|I830_RGBA_BIT|I830_SPEC_BIT|I830_TEX0_BIT] = rs_wgst0; - setup_func[I830_WIN_BIT|I830_RGBA_BIT|I830_SPEC_BIT|I830_TEX0_BIT|I830_TEX1_BIT] = rs_wgst0t1; - setup_func[I830_WIN_BIT|I830_RGBA_BIT|I830_FOG_BIT] = rs_wgf; - setup_func[I830_WIN_BIT|I830_RGBA_BIT|I830_FOG_BIT|I830_SPEC_BIT] = rs_wgfs; - setup_func[I830_WIN_BIT|I830_RGBA_BIT|I830_FOG_BIT|I830_TEX0_BIT] = rs_wgft0; - setup_func[I830_WIN_BIT|I830_RGBA_BIT|I830_FOG_BIT|I830_TEX0_BIT|I830_TEX1_BIT] = rs_wgft0t1; - setup_func[I830_WIN_BIT|I830_RGBA_BIT|I830_FOG_BIT|I830_SPEC_BIT|I830_TEX0_BIT] = rs_wgfst0; - setup_func[I830_WIN_BIT|I830_RGBA_BIT|I830_FOG_BIT|I830_SPEC_BIT|I830_TEX0_BIT|I830_TEX1_BIT] = rs_wgfst0t1; - - /* Repair functions */ - setup_func[I830_TEX0_BIT] = rs_t0; - setup_func[I830_TEX0_BIT|I830_TEX1_BIT] = rs_t0t1; - setup_func[I830_FOG_BIT] = rs_f; - setup_func[I830_FOG_BIT|I830_TEX0_BIT] = rs_ft0; - setup_func[I830_FOG_BIT|I830_TEX0_BIT|I830_TEX1_BIT] = rs_ft0t1; - setup_func[I830_RGBA_BIT] = rs_g; - setup_func[I830_RGBA_BIT|I830_SPEC_BIT] = rs_gs; - setup_func[I830_RGBA_BIT|I830_TEX0_BIT] = rs_gt0; - setup_func[I830_RGBA_BIT|I830_TEX0_BIT|I830_TEX1_BIT] = rs_gt0t1; - setup_func[I830_RGBA_BIT|I830_SPEC_BIT|I830_TEX0_BIT] = rs_gst0; - setup_func[I830_RGBA_BIT|I830_SPEC_BIT|I830_TEX0_BIT|I830_TEX1_BIT] = rs_gst0t1; - setup_func[I830_RGBA_BIT|I830_FOG_BIT] = rs_gf; - setup_func[I830_RGBA_BIT|I830_FOG_BIT|I830_SPEC_BIT] = rs_gfs; - setup_func[I830_RGBA_BIT|I830_FOG_BIT|I830_TEX0_BIT] = rs_gft0; - setup_func[I830_RGBA_BIT|I830_FOG_BIT|I830_TEX0_BIT|I830_TEX1_BIT] = rs_gft0t1; - setup_func[I830_RGBA_BIT|I830_FOG_BIT|I830_SPEC_BIT|I830_TEX0_BIT] = rs_gfst0; - setup_func[I830_RGBA_BIT|I830_FOG_BIT|I830_SPEC_BIT|I830_TEX0_BIT|I830_TEX1_BIT] = rs_gfst0t1; - + init_wg(); + init_wgs(); + init_wgt0(); + init_wgt0t1(); + init_wgpt0(); + init_wgst0(); + init_wgst0t1(); + init_wgspt0(); + init_wgf(); + init_wgfs(); + init_wgft0(); + init_wgft0t1(); + init_wgfpt0(); + init_wgfst0(); + init_wgfst0t1(); + init_wgfspt0(); + init_t0(); + init_t0t1(); + init_f(); + init_ft0(); + init_ft0t1(); + init_g(); + init_gs(); + init_gt0(); + init_gt0t1(); + init_gst0(); + init_gst0t1(); + init_gf(); + init_gfs(); + init_gft0(); + init_gft0t1(); + init_gfst0(); + init_gfst0t1(); + /* Add proj texturing on t1 */ + init_wgpt0t1(); + init_wgspt0t1(); + init_wgfpt0t1(); + init_wgfspt0t1(); } + void i830PrintSetupFlags(char *msg, GLuint flags ) { - fprintf(stderr, "%s: %d %s%s%s%s%s%s%s\n", + fprintf(stderr, "%s(%x): %s%s%s%s%s%s%s\n", msg, (int)flags, - (flags & I830_WIN_BIT) ? " xyzw," : "", + (flags & I830_XYZW_BIT) ? " xyzw," : "", (flags & I830_RGBA_BIT) ? " rgba," : "", (flags & I830_SPEC_BIT) ? " spec," : "", (flags & I830_FOG_BIT) ? " fog," : "", (flags & I830_TEX0_BIT) ? " tex-0," : "", (flags & I830_TEX1_BIT) ? " tex-1," : "", - (flags & I830_ALPHA_BIT) ? " alpha," : ""); + (flags & I830_PTEX_BIT) ? " ptex," : ""); } - -void i830ChooseRasterSetupFunc(GLcontext *ctx) +void i830CheckTexSizes( GLcontext *ctx ) { - i830ContextPtr imesa = I830_CONTEXT( ctx ); - int funcindex = (I830_WIN_BIT | I830_RGBA_BIT); - - if(I830_DEBUG&DEBUG_VERBOSE_TRACE) - fprintf(stderr, "%s\n", __FUNCTION__); - - imesa->vertsize = 8; - imesa->Setup[I830_CTXREG_VF] = VRTX_FORMAT_NTEX(1); - - if (ctx->Texture.ReallyEnabled & 0xf) - funcindex |= I830_TEX0_BIT; - - if (ctx->Texture.ReallyEnabled & 0xf0) { - funcindex |= (I830_TEX0_BIT | I830_TEX1_BIT); - imesa->vertsize = 10; - imesa->Setup[I830_CTXREG_VF] = VRTX_FORMAT_NTEX(2); - } - - if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) - funcindex |= I830_SPEC_BIT; - - if (ctx->FogMode == FOG_FRAGMENT) - funcindex |= I830_FOG_BIT; - - if (MESA_VERBOSE) - i830PrintSetupFlags("xsmesa: full setup function", funcindex); - - imesa->setupindex = funcindex; - ctx->Driver.RasterSetup = setup_func[funcindex]; - if(0) fprintf(stderr, "funcindex : 0x%x\n", funcindex); -} - + TNLcontext *tnl = TNL_CONTEXT(ctx); + i830ContextPtr imesa = I830_CONTEXT( ctx ); + if (!setup_tab[imesa->SetupIndex].check_tex_sizes(ctx)) { + int ind = imesa->SetupIndex |= I830_PTEX_BIT; + + if(setup_tab[ind].vertex_format != imesa->vertex_format) { + int vfmt = setup_tab[ind].vertex_format; + + I830_STATECHANGE(imesa, I830_UPLOAD_CTX); + imesa->Setup[I830_CTXREG_VF] = ~(1<<31) & vfmt; + + if (vfmt & (1<<31)) { + /* Proj texturing */ + imesa->Setup[I830_CTXREG_VF2] = (STATE3D_VERTEX_FORMAT_2_CMD | + VRTX_TEX_SET_0_FMT(TEXCOORDFMT_3D) | + VRTX_TEX_SET_1_FMT(TEXCOORDFMT_3D) | + VRTX_TEX_SET_2_FMT(TEXCOORDFMT_3D) | + VRTX_TEX_SET_3_FMT(TEXCOORDFMT_3D)); + i830UpdateTexUnitProj( ctx, 0, GL_TRUE ); + i830UpdateTexUnitProj( ctx, 1, GL_TRUE ); + + } else { + /* Normal texturing */ + imesa->Setup[I830_CTXREG_VF2] = (STATE3D_VERTEX_FORMAT_2_CMD | + VRTX_TEX_SET_0_FMT(TEXCOORDFMT_2D) | + VRTX_TEX_SET_1_FMT(TEXCOORDFMT_2D) | + VRTX_TEX_SET_2_FMT(TEXCOORDFMT_2D) | + VRTX_TEX_SET_3_FMT(TEXCOORDFMT_2D)); + i830UpdateTexUnitProj( ctx, 0, GL_FALSE ); + i830UpdateTexUnitProj( ctx, 1, GL_FALSE ); + } + imesa->vertex_format = vfmt; + imesa->vertex_size = setup_tab[ind].vertex_size; + imesa->vertex_stride_shift = setup_tab[ind].vertex_stride_shift; + } + if (!imesa->Fallback && + !(ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) { + tnl->Driver.Render.Interp = setup_tab[imesa->SetupIndex].interp; + tnl->Driver.Render.CopyPV = setup_tab[imesa->SetupIndex].copy_pv; + } + } +} -void i830DDCheckPartialRasterSetup( GLcontext *ctx, - struct gl_pipeline_stage *d ) +void i830BuildVertices( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint newinputs ) { i830ContextPtr imesa = I830_CONTEXT( ctx ); - GLuint tmp = imesa->setupdone; + GLubyte *v = ((GLubyte *) + imesa->verts + (start<<imesa->vertex_stride_shift)); + GLuint stride = 1<<imesa->vertex_stride_shift; - d->type = 0; - imesa->setupdone = 0; /* cleared if we return */ + if (0) fprintf(stderr, "%s\n", __FUNCTION__); - if ((ctx->Array.Summary & VERT_OBJ_ANY) == 0) - return; + newinputs |= imesa->SetupNewInputs; + imesa->SetupNewInputs = 0; - if (ctx->IndirectTriangles) + if (!newinputs) return; - imesa->setupdone = tmp; + if (newinputs & VERT_CLIP) { + setup_tab[imesa->SetupIndex].emit( ctx, start, count, v, stride ); + } else { + GLuint ind = 0; - /* disabled until we have a merge&render op */ - /* d->inputs = available; */ - /* d->outputs = VERT_RAST_SETUP_PART; */ - /* d->type = PIPE_PRECALC; */ -} - - -/* Repair existing precalculated vertices with new data. - */ -void i830DDPartialRasterSetup( struct vertex_buffer *VB ) -{ - i830ContextPtr imesa = I830_CONTEXT( VB->ctx ); - GLuint new = VB->pipeline->new_outputs; - GLuint available = VB->pipeline->outputs; - GLuint ind = 0; - - if (new & VERT_WIN) { - new = available; - ind |= I830_WIN_BIT | I830_FOG_BIT; - } + if (newinputs & VERT_RGBA) + ind |= I830_RGBA_BIT; - if (new & VERT_RGBA) - ind |= I830_RGBA_BIT | I830_SPEC_BIT; + if (newinputs & VERT_SPEC_RGB) + ind |= I830_SPEC_BIT; - if (new & VERT_TEX0_ANY) - ind |= I830_TEX0_BIT; + if (newinputs & VERT_TEX0) + ind |= I830_TEX0_BIT; - if (new & VERT_TEX1_ANY) - ind |= I830_TEX1_BIT; + if (newinputs & VERT_TEX1) + ind |= I830_TEX1_BIT; - if (new & VERT_FOG_COORD) - ind |= I830_FOG_BIT; + if (newinputs & VERT_FOG_COORD) + ind |= I830_FOG_BIT; - imesa->setupdone &= ~ind; - ind &= imesa->setupindex; - imesa->setupdone |= ind; +#if 0 + if (imesa->SetupIndex & I830_PTEX_BIT) + ind = ~0; +#endif - if (0) i830PrintSetupFlags("xsmesa: partial setup function", ind); + ind &= imesa->SetupIndex; - if (ind) - setup_func[ind&~I830_ALPHA_BIT]( VB, VB->Start, VB->Count ); + if (ind) { + setup_tab[ind].emit( ctx, start, count, v, stride ); + } + } } - -void i830DDDoRasterSetup( struct vertex_buffer *VB ) +void i830ChooseVertexState( GLcontext *ctx ) { - GLcontext *ctx = VB->ctx; - - if (VB->Type == VB_CVA_PRECALC) - i830DDPartialRasterSetup( VB ); - else if (ctx->Driver.RasterSetup) - ctx->Driver.RasterSetup( VB, VB->CopyStart, VB->Count ); -} + TNLcontext *tnl = TNL_CONTEXT(ctx); + i830ContextPtr imesa = I830_CONTEXT( ctx ); + GLuint ind = I830_XYZW_BIT|I830_RGBA_BIT; + if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) + ind |= I830_SPEC_BIT; + if (ctx->Fog.Enabled) + ind |= I830_FOG_BIT; + if (ctx->Texture._ReallyEnabled & TEXTURE1_ANY) + ind |= I830_TEX1_BIT|I830_TEX0_BIT; + else if (ctx->Texture._ReallyEnabled & TEXTURE0_ANY) + ind |= I830_TEX0_BIT; -void i830DDResizeVB( struct vertex_buffer *VB, GLuint size ) -{ - i830VertexBufferPtr mvb = I830_DRIVER_DATA(VB); + imesa->SetupIndex = ind; - while (mvb->size < size) - mvb->size *= 2; + if (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED)) { + tnl->Driver.Render.Interp = i830_interp_extras; + tnl->Driver.Render.CopyPV = i830_copy_pv_extras; + } else { + tnl->Driver.Render.Interp = setup_tab[ind].interp; + tnl->Driver.Render.CopyPV = setup_tab[ind].copy_pv; + } - free( mvb->vert_store ); - mvb->vert_store = malloc( sizeof(i830Vertex) * mvb->size + 31); - if (!mvb->vert_store) { - fprintf(stderr, "i830glx: out of memory !\n"); - exit(1); + if (setup_tab[ind].vertex_format != imesa->vertex_format) { + int vfmt = setup_tab[ind].vertex_format; + + I830_STATECHANGE(imesa, I830_UPLOAD_CTX); + imesa->Setup[I830_CTXREG_VF] = ~(1<<31) & vfmt; + + if (vfmt & (1<<31)) { + /* Proj texturing */ + imesa->Setup[I830_CTXREG_VF2] = (STATE3D_VERTEX_FORMAT_2_CMD | + VRTX_TEX_SET_0_FMT(TEXCOORDFMT_3D) | + VRTX_TEX_SET_1_FMT(TEXCOORDFMT_3D) | + VRTX_TEX_SET_2_FMT(TEXCOORDFMT_3D) | + VRTX_TEX_SET_3_FMT(TEXCOORDFMT_3D)); + i830UpdateTexUnitProj( ctx, 0, GL_TRUE ); + i830UpdateTexUnitProj( ctx, 1, GL_TRUE ); + } else { + /* Normal texturing */ + imesa->Setup[I830_CTXREG_VF2] = (STATE3D_VERTEX_FORMAT_2_CMD | + VRTX_TEX_SET_0_FMT(TEXCOORDFMT_2D) | + VRTX_TEX_SET_1_FMT(TEXCOORDFMT_2D) | + VRTX_TEX_SET_2_FMT(TEXCOORDFMT_2D) | + VRTX_TEX_SET_3_FMT(TEXCOORDFMT_2D)); + i830UpdateTexUnitProj( ctx, 0, GL_FALSE ); + i830UpdateTexUnitProj( ctx, 1, GL_FALSE ); + } + imesa->vertex_format = vfmt; + imesa->vertex_size = setup_tab[ind].vertex_size; + imesa->vertex_stride_shift = setup_tab[ind].vertex_stride_shift; } +} - mvb->verts = (i830VertexPtr)(((unsigned long)mvb->vert_store + 31) & ~31); - gl_vector1ui_free( &mvb->clipped_elements ); - gl_vector1ui_alloc( &mvb->clipped_elements, VEC_WRITABLE, mvb->size, 32 ); - if (!mvb->clipped_elements.start) { - fprintf(stderr, "i830glx: out of memory !\n"); - exit(1); - } - ALIGN_FREE( VB->ClipMask ); - VB->ClipMask = (GLubyte *) ALIGN_MALLOC(sizeof(GLubyte) * mvb->size, 4); - if (!VB->ClipMask) { - fprintf(stderr, "i830glx: out of memory !\n"); - exit(1); - } +void i830_emit_contiguous_verts( GLcontext *ctx, + GLuint start, + GLuint count ) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + GLuint vertex_size = imesa->vertex_size * 4; + GLuint *dest = i830AllocDmaLow( imesa, (count-start) * vertex_size); + setup_tab[imesa->SetupIndex].emit( ctx, start, count, dest, vertex_size ); +} - if (VB->Type == VB_IMMEDIATE) { - free( mvb->primitive ); - free( mvb->next_primitive ); - mvb->primitive = (GLuint *)malloc( sizeof(GLuint) * mvb->size ); - mvb->next_primitive = (GLuint *)malloc( sizeof(GLuint) * mvb->size ); - if (!mvb->primitive || !mvb->next_primitive) { - fprintf(stderr, "i830glx: out of memory !\n"); - exit(1); + +void i830InitVB( GLcontext *ctx ) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + GLuint size = TNL_CONTEXT(ctx)->vb.Size; + if (DEBUGGING) + fprintf (stderr,"\n%s\n",__FUNCTION__); + + imesa->verts = (char *)ALIGN_MALLOC(size * 4 * 16, 32); + + { + static int firsttime = 1; + if (firsttime) { + init_setup_tab(); + firsttime = 0; } } + if (DEBUGGING) + fprintf(stderr,"\nFinished InitVB\n"); } -void i830DDRegisterVB( struct vertex_buffer *VB ) +void i830FreeVB( GLcontext *ctx ) { - i830VertexBufferPtr mvb; - - mvb = (i830VertexBufferPtr)calloc( 1, sizeof(*mvb) ); - - mvb->size = VB->Size * 2; - mvb->vert_store = malloc( sizeof(i830Vertex) * mvb->size + 31); - if (!mvb->vert_store) { - fprintf(stderr, "i830glx: out of memory !\n"); - exit(1); + i830ContextPtr imesa = I830_CONTEXT(ctx); + if (imesa->verts) { + ALIGN_FREE(imesa->verts); + imesa->verts = 0; } - - mvb->verts = (i830VertexPtr)(((unsigned long)mvb->vert_store + 31) & ~31); - gl_vector1ui_alloc( &mvb->clipped_elements, VEC_WRITABLE, mvb->size, 32 ); - if (!mvb->clipped_elements.start) { - fprintf(stderr, "i830glx: out of memory !\n"); - exit(1); - } - - ALIGN_FREE( VB->ClipMask ); - VB->ClipMask = (GLubyte *) ALIGN_MALLOC(sizeof(GLubyte) * mvb->size, 4); - if (!VB->ClipMask) { - fprintf(stderr, "i830glx: out of memory !\n"); - exit(1); + if (imesa->UbyteSecondaryColor.Ptr) { + ALIGN_FREE(imesa->UbyteSecondaryColor.Ptr); + imesa->UbyteSecondaryColor.Ptr = 0; } - mvb->primitive = (GLuint *)malloc( sizeof(GLuint) * mvb->size ); - mvb->next_primitive = (GLuint *)malloc( sizeof(GLuint) * mvb->size ); - if (!mvb->primitive || !mvb->next_primitive) { - fprintf(stderr, "i830glx: out of memory !\n"); - exit(1); + if (imesa->UbyteColor.Ptr) { + ALIGN_FREE(imesa->UbyteColor.Ptr); + imesa->UbyteColor.Ptr = 0; } - - VB->driver_data = mvb; -} - - -void i830DDUnregisterVB( struct vertex_buffer *VB ) -{ - i830VertexBufferPtr mvb = I830_DRIVER_DATA(VB); - - if (mvb) { - if (mvb->vert_store) free(mvb->vert_store); - if (mvb->primitive) free(mvb->primitive); - if (mvb->next_primitive) free(mvb->next_primitive); - gl_vector1ui_free( &mvb->clipped_elements ); - free(mvb); - VB->driver_data = 0; - } } diff --git a/xc/lib/GL/mesa/src/drv/mga/mgatris.c b/xc/lib/GL/mesa/src/drv/mga/mgatris.c index cd9da5a0e..ece5dd753 100644 --- a/xc/lib/GL/mesa/src/drv/mga/mgatris.c +++ b/xc/lib/GL/mesa/src/drv/mga/mgatris.c @@ -29,153 +29,887 @@ #include <stdio.h> #include <math.h> -#include "types.h" -#include "vb.h" -#include "pipeline.h" +#include "mtypes.h" +#include "macros.h" +#include "colormac.h" +#include "swrast/swrast.h" +#include "swrast_setup/swrast_setup.h" +#include "tnl/t_context.h" +#include "tnl/t_pipeline.h" #include "mm.h" #include "mgacontext.h" +#include "mgaioctl.h" #include "mgatris.h" #include "mgavb.h" +#include "mgastate.h" -#define MGA_COLOR(to, from) { \ - (to)[0] = (from)[2]; \ - (to)[1] = (from)[1]; \ - (to)[2] = (from)[0]; \ - (to)[3] = (from)[3]; \ +static void mgaRenderPrimitive( GLcontext *ctx, GLenum prim ); + +/*********************************************************************** + * Functions to draw basic primitives * + ***********************************************************************/ + + +#if defined (USE_X86_ASM) +#define EMIT_VERT( j, vb, vertex_size, v ) \ +do { int __tmp; \ + __asm__ __volatile__( "rep ; movsl" \ + : "=%c" (j), "=D" (vb), "=S" (__tmp) \ + : "0" (vertex_size), \ + "D" ((long)vb), \ + "S" ((long)v)); \ +} while (0) +#else +#define EMIT_VERT( j, vb, vertex_size, v ) \ +do { \ + for ( j = 0 ; j < vertex_size ; j++ ) \ + vb[j] = (v)->ui[j]; \ + vb += vertex_size; \ +} while (0) +#endif + +static void __inline__ mga_draw_triangle( mgaContextPtr mmesa, + mgaVertexPtr v0, + mgaVertexPtr v1, + mgaVertexPtr v2 ) +{ + GLuint vertex_size = mmesa->vertex_size; + GLuint *vb = mgaAllocDmaLow( mmesa, 3 * 4 * vertex_size ); + int j; + + EMIT_VERT( j, vb, vertex_size, v0 ); + EMIT_VERT( j, vb, vertex_size, v1 ); + EMIT_VERT( j, vb, vertex_size, v2 ); } -#define MGA_COLOR3(to, from) { \ - (to)[0] = (from)[2]; \ - (to)[1] = (from)[1]; \ - (to)[2] = (from)[0]; \ + +static void __inline__ mga_draw_quad( mgaContextPtr mmesa, + mgaVertexPtr v0, + mgaVertexPtr v1, + mgaVertexPtr v2, + mgaVertexPtr v3 ) +{ + GLuint vertex_size = mmesa->vertex_size; + GLuint *vb = mgaAllocDmaLow( mmesa, 6 * 4 * vertex_size ); + int j; + + EMIT_VERT( j, vb, vertex_size, v0 ); + EMIT_VERT( j, vb, vertex_size, v1 ); + EMIT_VERT( j, vb, vertex_size, v3 ); + EMIT_VERT( j, vb, vertex_size, v1 ); + EMIT_VERT( j, vb, vertex_size, v2 ); + EMIT_VERT( j, vb, vertex_size, v3 ); } +static __inline__ void mga_draw_point( mgaContextPtr mmesa, + mgaVertexPtr tmp ) +{ + GLfloat sz = mmesa->glCtx->Point._Size * .5; + int vertex_size = mmesa->vertex_size; + GLuint *vb = mgaAllocDmaLow( mmesa, 6 * 4 * vertex_size ); + int j; + +#if 0 + v0->v.x += PNT_X_OFFSET - TRI_X_OFFSET; + v0->v.y += PNT_Y_OFFSET - TRI_Y_OFFSET; +#endif -static triangle_func tri_tab[0x10]; -static quad_func quad_tab[0x10]; -static line_func line_tab[0x10]; -static points_func points_tab[0x10]; + /* Draw a point as two triangles. + */ + *(float *)&vb[0] = tmp->v.x - sz; + *(float *)&vb[1] = tmp->v.y - sz; + for (j = 2 ; j < vertex_size ; j++) + vb[j] = tmp->ui[j]; + vb += vertex_size; -#define IND (0) + *(float *)&vb[0] = tmp->v.x + sz; + *(float *)&vb[1] = tmp->v.y - sz; + for (j = 2 ; j < vertex_size ; j++) + vb[j] = tmp->ui[j]; + vb += vertex_size; + + *(float *)&vb[0] = tmp->v.x + sz; + *(float *)&vb[1] = tmp->v.y + sz; + for (j = 2 ; j < vertex_size ; j++) + vb[j] = tmp->ui[j]; + vb += vertex_size; + + *(float *)&vb[0] = tmp->v.x + sz; + *(float *)&vb[1] = tmp->v.y + sz; + for (j = 2 ; j < vertex_size ; j++) + vb[j] = tmp->ui[j]; + vb += vertex_size; + + *(float *)&vb[0] = tmp->v.x - sz; + *(float *)&vb[1] = tmp->v.y + sz; + for (j = 2 ; j < vertex_size ; j++) + vb[j] = tmp->ui[j]; + vb += vertex_size; + + *(float *)&vb[0] = tmp->v.x - sz; + *(float *)&vb[1] = tmp->v.y - sz; + for (j = 2 ; j < vertex_size ; j++) + vb[j] = tmp->ui[j]; + +#if 0 + v0->v.x -= PNT_X_OFFSET - TRI_X_OFFSET; + v0->v.y -= PNT_Y_OFFSET - TRI_Y_OFFSET; +#endif +} + + +static __inline__ void mga_draw_line( mgaContextPtr mmesa, + mgaVertexPtr v0, + mgaVertexPtr v1 ) +{ + GLuint vertex_size = mmesa->vertex_size; + GLuint *vb = mgaAllocDmaLow( mmesa, 6 * 4 * vertex_size ); + GLfloat dx, dy, ix, iy; + GLfloat width = mmesa->glCtx->Line._Width; + GLint j; + +#if 0 + v0->v.x += LINE_X_OFFSET - TRI_X_OFFSET; + v0->v.y += LINE_Y_OFFSET - TRI_Y_OFFSET; + v1->v.x += LINE_X_OFFSET - TRI_X_OFFSET; + v1->v.y += LINE_Y_OFFSET - TRI_Y_OFFSET; +#endif + + dx = v0->v.x - v1->v.x; + dy = v0->v.y - v1->v.y; + + ix = width * .5; iy = 0; + if (dx * dx > dy * dy) { + iy = ix; ix = 0; + } + + *(float *)&vb[0] = v0->v.x - ix; + *(float *)&vb[1] = v0->v.y - iy; + for (j = 2 ; j < vertex_size ; j++) + vb[j] = v0->ui[j]; + vb += vertex_size; + + *(float *)&vb[0] = v1->v.x + ix; + *(float *)&vb[1] = v1->v.y + iy; + for (j = 2 ; j < vertex_size ; j++) + vb[j] = v1->ui[j]; + vb += vertex_size; + + *(float *)&vb[0] = v0->v.x + ix; + *(float *)&vb[1] = v0->v.y + iy; + for (j = 2 ; j < vertex_size ; j++) + vb[j] = v0->ui[j]; + vb += vertex_size; + + *(float *)&vb[0] = v0->v.x - ix; + *(float *)&vb[1] = v0->v.y - iy; + for (j = 2 ; j < vertex_size ; j++) + vb[j] = v0->ui[j]; + vb += vertex_size; + + *(float *)&vb[0] = v1->v.x - ix; + *(float *)&vb[1] = v1->v.y - iy; + for (j = 2 ; j < vertex_size ; j++) + vb[j] = v1->ui[j]; + vb += vertex_size; + + *(float *)&vb[0] = v1->v.x + ix; + *(float *)&vb[1] = v1->v.y + iy; + for (j = 2 ; j < vertex_size ; j++) + vb[j] = v1->ui[j]; + vb += vertex_size; + +#if 0 + v0->v.x -= LINE_X_OFFSET - TRI_X_OFFSET; + v0->v.y -= LINE_Y_OFFSET - TRI_Y_OFFSET; + v1->v.x -= LINE_X_OFFSET - TRI_X_OFFSET; + v1->v.y -= LINE_Y_OFFSET - TRI_Y_OFFSET; +#endif +} + +/*********************************************************************** + * Macros for t_dd_tritmp.h to draw basic primitives * + ***********************************************************************/ + +#define TRI( a, b, c ) \ +do { \ + if (DO_FALLBACK) \ + mmesa->draw_tri( mmesa, a, b, c ); \ + else \ + mga_draw_triangle( mmesa, a, b, c ); \ +} while (0) + +#define QUAD( a, b, c, d ) \ +do { \ + if (DO_FALLBACK) { \ + mmesa->draw_tri( mmesa, a, b, d ); \ + mmesa->draw_tri( mmesa, b, c, d ); \ + } else { \ + mga_draw_quad( mmesa, a, b, c, d ); \ + } \ +} while (0) + +#define LINE( v0, v1 ) \ +do { \ + if (DO_FALLBACK) \ + mmesa->draw_line( mmesa, v0, v1 ); \ + else { \ + mga_draw_line( mmesa, v0, v1 ); \ + } \ +} while (0) + +#define POINT( v0 ) \ +do { \ + if (DO_FALLBACK) \ + mmesa->draw_point( mmesa, v0 ); \ + else { \ + mga_draw_point( mmesa, v0 ); \ + } \ +} while (0) + + +/*********************************************************************** + * Fallback to swrast for basic primitives * + ***********************************************************************/ + +/* This code is hit only when a mix of accelerated and unaccelerated + * primitives are being drawn, and only for the unaccelerated + * primitives. + */ + +static void +mga_fallback_tri( mgaContextPtr mmesa, + mgaVertex *v0, + mgaVertex *v1, + mgaVertex *v2 ) +{ + GLcontext *ctx = mmesa->glCtx; + SWvertex v[3]; + mga_translate_vertex( ctx, v0, &v[0] ); + mga_translate_vertex( ctx, v1, &v[1] ); + mga_translate_vertex( ctx, v2, &v[2] ); + _swrast_Triangle( ctx, &v[0], &v[1], &v[2] ); +} + + +static void +mga_fallback_line( mgaContextPtr mmesa, + mgaVertex *v0, + mgaVertex *v1 ) +{ + GLcontext *ctx = mmesa->glCtx; + SWvertex v[2]; + mga_translate_vertex( ctx, v0, &v[0] ); + mga_translate_vertex( ctx, v1, &v[1] ); + _swrast_Line( ctx, &v[0], &v[1] ); +} + + +static void +mga_fallback_point( mgaContextPtr mmesa, + mgaVertex *v0 ) +{ + GLcontext *ctx = mmesa->glCtx; + SWvertex v[1]; + mga_translate_vertex( ctx, v0, &v[0] ); + _swrast_Point( ctx, &v[0] ); +} + +/*********************************************************************** + * Build render functions from dd templates * + ***********************************************************************/ + + +#define MGA_UNFILLED_BIT 0x1 +#define MGA_OFFSET_BIT 0x2 +#define MGA_TWOSIDE_BIT 0x4 +#define MGA_FLAT_BIT 0x8 /* mga can't flatshade? */ +#define MGA_FALLBACK_BIT 0x10 +#define MGA_MAX_TRIFUNC 0x20 + +static struct { + points_func points; + line_func line; + triangle_func triangle; + quad_func quad; +} rast_tab[MGA_MAX_TRIFUNC]; + +#define DO_FALLBACK (IND & MGA_FALLBACK_BIT) +#define DO_OFFSET (IND & MGA_OFFSET_BIT) +#define DO_UNFILLED (IND & MGA_UNFILLED_BIT) +#define DO_TWOSIDE (IND & MGA_TWOSIDE_BIT) +#define DO_FLAT (IND & MGA_FLAT_BIT) +#define DO_TRI 1 +#define DO_QUAD 1 +#define DO_LINE 1 +#define DO_POINTS 1 +#define DO_FULL_QUAD 1 + +#define HAVE_RGBA 1 +#define HAVE_BACK_COLORS 0 +#define HAVE_SPEC 1 +#define HAVE_HW_FLATSHADE 0 +#define VERTEX mgaVertex +#define TAB rast_tab + +#define MGA_COLOR( dst, src ) \ +do { \ + dst[0] = src[2]; \ + dst[1] = src[1]; \ + dst[2] = src[0]; \ + dst[3] = src[3]; \ +} while (0) + +#define MGA_SPEC( dst, src ) \ +do { \ + dst[0] = src[2]; \ + dst[1] = src[1]; \ + dst[2] = src[0]; \ +} while (0) + +#define DEPTH_SCALE mmesa->depth_scale +#define UNFILLED_TRI unfilled_tri +#define UNFILLED_QUAD unfilled_quad +#define VERT_X(_v) _v->v.x +#define VERT_Y(_v) _v->v.y +#define VERT_Z(_v) _v->v.z +#define AREA_IS_CCW( a ) (a > 0) +#define GET_VERTEX(e) (mmesa->verts + (e<<mmesa->vertex_stride_shift)) + +#define VERT_SET_RGBA( v, c ) MGA_COLOR( v->ub4[4], c ) +#define VERT_COPY_RGBA( v0, v1 ) v0->ui[4] = v1->ui[4] +#define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[4] +#define VERT_RESTORE_RGBA( idx ) v[idx]->ui[4] = color[idx] + +#define VERT_SET_SPEC( v, c ) MGA_SPEC( v->ub4[5], c ) +#define VERT_COPY_SPEC( v0, v1 ) COPY_3V(v0->ub4[5], v1->ub4[5]) +#define VERT_SAVE_SPEC( idx ) spec[idx] = v[idx]->ui[5] +#define VERT_RESTORE_SPEC( idx ) v[idx]->ui[5] = spec[idx] + +#define LOCAL_VARS(n) \ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); \ + GLuint color[n], spec[n]; \ + (void) color; (void) spec; + + + +/*********************************************************************** + * Functions to draw basic unfilled primitives * + ***********************************************************************/ + +#define RASTERIZE(x) if (mmesa->raster_primitive != x) \ + mgaRasterPrimitive( ctx, x, MGA_WA_TRIANGLES ) +#define RENDER_PRIMITIVE mmesa->render_primitive +#define IND MGA_FALLBACK_BIT #define TAG(x) x -#include "mgatritmp.h" +#include "tnl_dd/t_dd_unfilled.h" +#undef IND -#define IND (MGA_FLAT_BIT) -#define TAG(x) x##_flat -#include "mgatritmp.h" +/*********************************************************************** + * Functions to draw GL primitives * + ***********************************************************************/ + +#define IND (0) +#define TAG(x) x +#include "tnl_dd/t_dd_tritmp.h" #define IND (MGA_OFFSET_BIT) #define TAG(x) x##_offset -#include "mgatritmp.h" - -#define IND (MGA_OFFSET_BIT|MGA_FLAT_BIT) -#define TAG(x) x##_offset_flat -#include "mgatritmp.h" +#include "tnl_dd/t_dd_tritmp.h" #define IND (MGA_TWOSIDE_BIT) #define TAG(x) x##_twoside -#include "mgatritmp.h" - -#define IND (MGA_TWOSIDE_BIT|MGA_FLAT_BIT) -#define TAG(x) x##_twoside_flat -#include "mgatritmp.h" +#include "tnl_dd/t_dd_tritmp.h" #define IND (MGA_TWOSIDE_BIT|MGA_OFFSET_BIT) #define TAG(x) x##_twoside_offset -#include "mgatritmp.h" +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_UNFILLED_BIT) +#define TAG(x) x##_unfilled +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_OFFSET_BIT|MGA_UNFILLED_BIT) +#define TAG(x) x##_offset_unfilled +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_TWOSIDE_BIT|MGA_UNFILLED_BIT) +#define TAG(x) x##_twoside_unfilled +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_TWOSIDE_BIT|MGA_OFFSET_BIT|MGA_UNFILLED_BIT) +#define TAG(x) x##_twoside_offset_unfilled +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_FALLBACK_BIT) +#define TAG(x) x##_fallback +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_OFFSET_BIT|MGA_FALLBACK_BIT) +#define TAG(x) x##_offset_fallback +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_TWOSIDE_BIT|MGA_FALLBACK_BIT) +#define TAG(x) x##_twoside_fallback +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_TWOSIDE_BIT|MGA_OFFSET_BIT|MGA_FALLBACK_BIT) +#define TAG(x) x##_twoside_offset_fallback +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_UNFILLED_BIT|MGA_FALLBACK_BIT) +#define TAG(x) x##_unfilled_fallback +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_OFFSET_BIT|MGA_UNFILLED_BIT|MGA_FALLBACK_BIT) +#define TAG(x) x##_offset_unfilled_fallback +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_TWOSIDE_BIT|MGA_UNFILLED_BIT|MGA_FALLBACK_BIT) +#define TAG(x) x##_twoside_unfilled_fallback +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_TWOSIDE_BIT|MGA_OFFSET_BIT|MGA_UNFILLED_BIT| \ + MGA_FALLBACK_BIT) +#define TAG(x) x##_twoside_offset_unfilled_fallback +#include "tnl_dd/t_dd_tritmp.h" + + +/* Mga doesn't support provoking-vertex flat-shading? + */ +#define IND (MGA_FLAT_BIT) +#define TAG(x) x##_flat +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_OFFSET_BIT|MGA_FLAT_BIT) +#define TAG(x) x##_offset_flat +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_TWOSIDE_BIT|MGA_FLAT_BIT) +#define TAG(x) x##_twoside_flat +#include "tnl_dd/t_dd_tritmp.h" #define IND (MGA_TWOSIDE_BIT|MGA_OFFSET_BIT|MGA_FLAT_BIT) #define TAG(x) x##_twoside_offset_flat -#include "mgatritmp.h" +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_UNFILLED_BIT|MGA_FLAT_BIT) +#define TAG(x) x##_unfilled_flat +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_OFFSET_BIT|MGA_UNFILLED_BIT|MGA_FLAT_BIT) +#define TAG(x) x##_offset_unfilled_flat +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_TWOSIDE_BIT|MGA_UNFILLED_BIT|MGA_FLAT_BIT) +#define TAG(x) x##_twoside_unfilled_flat +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_TWOSIDE_BIT|MGA_OFFSET_BIT|MGA_UNFILLED_BIT|MGA_FLAT_BIT) +#define TAG(x) x##_twoside_offset_unfilled_flat +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_FALLBACK_BIT|MGA_FLAT_BIT) +#define TAG(x) x##_fallback_flat +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_OFFSET_BIT|MGA_FALLBACK_BIT|MGA_FLAT_BIT) +#define TAG(x) x##_offset_fallback_flat +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_TWOSIDE_BIT|MGA_FALLBACK_BIT|MGA_FLAT_BIT) +#define TAG(x) x##_twoside_fallback_flat +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_TWOSIDE_BIT|MGA_OFFSET_BIT|MGA_FALLBACK_BIT|MGA_FLAT_BIT) +#define TAG(x) x##_twoside_offset_fallback_flat +#include "tnl_dd/t_dd_tritmp.h" +#define IND (MGA_UNFILLED_BIT|MGA_FALLBACK_BIT|MGA_FLAT_BIT) +#define TAG(x) x##_unfilled_fallback_flat +#include "tnl_dd/t_dd_tritmp.h" -void mgaDDTrifuncInit() +#define IND (MGA_OFFSET_BIT|MGA_UNFILLED_BIT|MGA_FALLBACK_BIT|MGA_FLAT_BIT) +#define TAG(x) x##_offset_unfilled_fallback_flat +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_TWOSIDE_BIT|MGA_UNFILLED_BIT|MGA_FALLBACK_BIT|MGA_FLAT_BIT) +#define TAG(x) x##_twoside_unfilled_fallback_flat +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (MGA_TWOSIDE_BIT|MGA_OFFSET_BIT|MGA_UNFILLED_BIT| \ + MGA_FALLBACK_BIT|MGA_FLAT_BIT) +#define TAG(x) x##_twoside_offset_unfilled_fallback_flat +#include "tnl_dd/t_dd_tritmp.h" + + +static void init_rast_tab( void ) { init(); - init_flat(); init_offset(); - init_offset_flat(); init_twoside(); - init_twoside_flat(); init_twoside_offset(); + init_unfilled(); + init_offset_unfilled(); + init_twoside_unfilled(); + init_twoside_offset_unfilled(); + init_fallback(); + init_offset_fallback(); + init_twoside_fallback(); + init_twoside_offset_fallback(); + init_unfilled_fallback(); + init_offset_unfilled_fallback(); + init_twoside_unfilled_fallback(); + init_twoside_offset_unfilled_fallback(); + + init_flat(); + init_offset_flat(); + init_twoside_flat(); init_twoside_offset_flat(); + init_unfilled_flat(); + init_offset_unfilled_flat(); + init_twoside_unfilled_flat(); + init_twoside_offset_unfilled_flat(); + init_fallback_flat(); + init_offset_fallback_flat(); + init_twoside_fallback_flat(); + init_twoside_offset_fallback_flat(); + init_unfilled_fallback_flat(); + init_offset_unfilled_fallback_flat(); + init_twoside_unfilled_fallback_flat(); + init_twoside_offset_unfilled_fallback_flat(); +} + +/**********************************************************************/ +/* Render whole begin/end objects */ +/**********************************************************************/ + + +#define VERT(x) (mgaVertex *)(vertptr + ((x)<<vertshift)) +#define RENDER_POINTS( start, count ) \ + for ( ; start < count ; start++) \ + mga_draw_point( mmesa, VERT(ELT(start)) ); +#define RENDER_LINE( v0, v1 ) \ + mga_draw_line( mmesa, VERT(v0), VERT(v1) ) +#define RENDER_TRI( v0, v1, v2 ) \ + mga_draw_triangle( mmesa, VERT(v0), VERT(v1), VERT(v2) ) +#define RENDER_QUAD( v0, v1, v2, v3 ) \ + mga_draw_quad( mmesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) ) +#define INIT(x) mgaRenderPrimitive( ctx, x ) +#undef LOCAL_VARS +#define LOCAL_VARS \ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); \ + GLubyte *vertptr = (GLubyte *)mmesa->verts; \ + const GLuint vertshift = mmesa->vertex_stride_shift; \ + const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \ + (void) elt; +#define RESET_STIPPLE +#define RESET_OCCLUSION +#define PRESERVE_VB_DEFS +#define ELT(x) x +#define TAG(x) mga_##x##_verts +#include "tnl/t_vb_rendertmp.h" +#undef ELT +#undef TAG +#define TAG(x) mga_##x##_elts +#define ELT(x) elt[x] +#include "tnl/t_vb_rendertmp.h" + + +/**********************************************************************/ +/* Render clipped primitives */ +/**********************************************************************/ + + + +static void mgaRenderClippedPoly( GLcontext *ctx, const GLuint *elts, GLuint n ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; + GLuint prim = mmesa->render_primitive; + + /* Render the new vertices as an unclipped polygon. + */ + { + GLuint *tmp = VB->Elts; + VB->Elts = (GLuint *)elts; + tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, PRIM_BEGIN|PRIM_END ); + VB->Elts = tmp; + } + + /* Restore the render primitive + */ + if (prim != GL_POLYGON) + tnl->Driver.Render.PrimitiveNotify( ctx, prim ); +} + +static void mgaRenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + tnl->Driver.Render.Line( ctx, ii, jj ); +} + +static void mgaFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts, + GLuint n ) +{ + mgaContextPtr mmesa = MGA_CONTEXT( ctx ); + GLuint vertex_size = mmesa->vertex_size; + GLuint *vb = mgaAllocDmaLow( mmesa, (n-2) * 3 * 4 * vertex_size ); + GLubyte *vertptr = (GLubyte *)mmesa->verts; + const GLuint vertshift = mmesa->vertex_stride_shift; + const GLuint *start = (const GLuint *)VERT(elts[0]); + int i,j; + + for (i = 2 ; i < n ; i++) { + EMIT_VERT( j, vb, vertex_size, (mgaVertexPtr) VERT(elts[i-1]) ); + EMIT_VERT( j, vb, vertex_size, (mgaVertexPtr) VERT(elts[i]) ); + EMIT_VERT( j, vb, vertex_size, (mgaVertexPtr) start ); + } } +/**********************************************************************/ +/* Choose render functions */ +/**********************************************************************/ -#define ALL_FALLBACK (DD_SELECT | DD_FEEDBACK) -#define POINT_FALLBACK (ALL_FALLBACK | DD_POINT_SMOOTH) -#define LINE_FALLBACK (ALL_FALLBACK | DD_LINE_SMOOTH | DD_LINE_STIPPLE) -#define TRI_FALLBACK (ALL_FALLBACK | DD_TRI_SMOOTH | DD_TRI_UNFILLED) -#define ANY_FALLBACK (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK|DD_TRI_STIPPLE) -#define ANY_RASTER_FLAGS (DD_FLATSHADE|DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET) - -/* Setup the Point, Line, Triangle and Quad functions based on the - current rendering state. Wherever possible, use the hardware to - render the primitive. Otherwise, fallback to software rendering. */ -void mgaDDChooseRenderState(GLcontext *ctx) -{ - mgaContextPtr mmesa = MGA_CONTEXT(ctx); - GLuint flags = ctx->TriangleCaps; - GLuint index = 0; - - if (mmesa->Fallback) { - mmesa->renderindex = MGA_FALLBACK_BIT; - if (flags & DD_TRI_LIGHT_TWOSIDE) { - mmesa->IndirectTriangles = DD_TRI_LIGHT_TWOSIDE; - } - return; - } - - if (flags & ANY_RASTER_FLAGS) { - if (flags & DD_FLATSHADE) index |= MGA_FLAT_BIT; - if (flags & DD_TRI_LIGHT_TWOSIDE) index |= MGA_TWOSIDE_BIT; - if (flags & DD_TRI_OFFSET) index |= MGA_OFFSET_BIT; - } - - mmesa->PointsFunc = points_tab[index]; - mmesa->LineFunc = line_tab[index]; - mmesa->TriangleFunc = tri_tab[index]; - mmesa->QuadFunc = quad_tab[index]; - - mmesa->renderindex = index; - mmesa->IndirectTriangles = 0; - - if (flags & ANY_FALLBACK) { - if (flags & POINT_FALLBACK) { - mmesa->renderindex |= MGA_FALLBACK_BIT; - mmesa->PointsFunc = 0; - mmesa->IndirectTriangles |= DD_POINT_SW_RASTERIZE; - } - - if (flags & LINE_FALLBACK) { - mmesa->renderindex |= MGA_FALLBACK_BIT; - mmesa->LineFunc = 0; - mmesa->IndirectTriangles |= DD_LINE_SW_RASTERIZE; - } - - if (flags & TRI_FALLBACK) { - mmesa->renderindex |= MGA_FALLBACK_BIT; - mmesa->TriangleFunc = 0; - mmesa->QuadFunc = 0; - mmesa->IndirectTriangles |= (DD_TRI_SW_RASTERIZE | - DD_QUAD_SW_RASTERIZE); - } - /* Special cases: - */ - if ((flags & DD_TRI_STIPPLE) && - (ctx->IndirectTriangles & DD_TRI_STIPPLE)) { - mmesa->renderindex |= MGA_FALLBACK_BIT; - mmesa->TriangleFunc = 0; - mmesa->QuadFunc = 0; - mmesa->IndirectTriangles |= (DD_TRI_SW_RASTERIZE | - DD_QUAD_SW_RASTERIZE); - if (flags & DD_TRI_LIGHT_TWOSIDE) { - mmesa->IndirectTriangles |= DD_TRI_LIGHT_TWOSIDE; - } - } - } + +#define _MGA_NEW_RENDERSTATE (_DD_NEW_LINE_STIPPLE | \ + _DD_NEW_TRI_UNFILLED | \ + _DD_NEW_TRI_LIGHT_TWOSIDE | \ + _DD_NEW_TRI_OFFSET | \ + _DD_NEW_TRI_STIPPLE | \ + _NEW_POLYGONSTIPPLE) + + +#define POINT_FALLBACK (DD_POINT_SMOOTH) +#define LINE_FALLBACK (DD_LINE_SMOOTH | DD_LINE_STIPPLE) +#define TRI_FALLBACK (DD_TRI_SMOOTH | DD_TRI_UNFILLED) +#define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK| \ + DD_TRI_STIPPLE) +#define ANY_RASTER_FLAGS (DD_FLATSHADE|DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET| \ + DD_TRI_UNFILLED) + +static void mgaChooseRenderState(GLcontext *ctx) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + GLuint flags = ctx->_TriangleCaps; + GLuint index = 0; + + if (flags & (ANY_FALLBACK_FLAGS|ANY_RASTER_FLAGS)) { + if (flags & ANY_RASTER_FLAGS) { + if (flags & DD_TRI_LIGHT_TWOSIDE) index |= MGA_TWOSIDE_BIT; + if (flags & DD_TRI_OFFSET) index |= MGA_OFFSET_BIT; + if (flags & DD_TRI_UNFILLED) index |= MGA_UNFILLED_BIT; + if (flags & DD_FLATSHADE) index |= MGA_FLAT_BIT; + } + + mmesa->draw_point = mga_draw_point; + mmesa->draw_line = mga_draw_line; + mmesa->draw_tri = mga_draw_triangle; + + /* Hook in fallbacks for specific primitives. + */ + if (flags & ANY_FALLBACK_FLAGS) + { + if (flags & POINT_FALLBACK) + mmesa->draw_point = mga_fallback_point; + + if (flags & LINE_FALLBACK) + mmesa->draw_line = mga_fallback_line; + + if (flags & TRI_FALLBACK) + mmesa->draw_tri = mga_fallback_tri; + + if ((flags & DD_TRI_STIPPLE) && !mmesa->haveHwStipple) + mmesa->draw_tri = mga_fallback_tri; + + index |= MGA_FALLBACK_BIT; + } + } + + if (mmesa->RenderIndex != index) { + mmesa->RenderIndex = index; + + tnl->Driver.Render.Points = rast_tab[index].points; + tnl->Driver.Render.Line = rast_tab[index].line; + tnl->Driver.Render.Triangle = rast_tab[index].triangle; + tnl->Driver.Render.Quad = rast_tab[index].quad; + + if (index == 0) { + tnl->Driver.Render.PrimTabVerts = mga_render_tab_verts; + tnl->Driver.Render.PrimTabElts = mga_render_tab_elts; + tnl->Driver.Render.ClippedLine = line; /* from tritmp.h */ + tnl->Driver.Render.ClippedPolygon = mgaFastRenderClippedPoly; + } else { + tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts; + tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts; + tnl->Driver.Render.ClippedLine = mgaRenderClippedLine; + tnl->Driver.Render.ClippedPolygon = mgaRenderClippedPoly; + } + } +} + +/**********************************************************************/ +/* Runtime render state and callbacks */ +/**********************************************************************/ + + +static void mgaRunPipeline( GLcontext *ctx ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + + if (mmesa->new_state) { + mgaDDUpdateHwState( ctx ); + } + + if (!mmesa->Fallback && mmesa->new_gl_state) { + if (mmesa->new_gl_state & _MGA_NEW_RASTERSETUP) + mgaChooseVertexState( ctx ); + + if (mmesa->new_gl_state & _MGA_NEW_RENDERSTATE) + mgaChooseRenderState( ctx ); + + mmesa->new_gl_state = 0; + + /* Circularity: mgaDDUpdateHwState can affect mmesa->Fallback, + * but mgaChooseVertexState can affect mmesa->new_state. Hence + * the second check. (Fix this...) + */ + if (mmesa->new_state) { + mgaDDUpdateHwState( ctx ); + } + } + + _tnl_run_pipeline( ctx ); +} + + +static GLenum reduced_prim[GL_POLYGON+1] = { + GL_POINTS, + GL_LINES, + GL_LINES, + GL_LINES, + GL_TRIANGLES, + GL_TRIANGLES, + GL_TRIANGLES, + GL_TRIANGLES, + GL_TRIANGLES, + GL_TRIANGLES +}; + + + +/* Always called between RenderStart and RenderFinish --> We already + * hold the lock. + */ +void mgaRasterPrimitive( GLcontext *ctx, GLenum prim, GLuint hwprim ) +{ + mgaContextPtr mmesa = MGA_CONTEXT( ctx ); + + FLUSH_BATCH( mmesa ); + mmesa->raster_primitive = prim; +/* mmesa->hw_primitive = hwprim; */ + mmesa->hw_primitive = MGA_WA_TRIANGLES; /* disable mgarender.c for now */ + mgaUpdateCull(ctx); + + if (ctx->Polygon.StippleFlag && mmesa->haveHwStipple) + { + mmesa->dirty |= MGA_UPLOAD_CONTEXT; + if (mmesa->raster_primitive == GL_TRIANGLES) + mmesa->setup.dwgctl |= mmesa->poly_stipple; + else + mmesa->setup.dwgctl &= ~(0xf<<20); + } +} + + + +/* Determine the rasterized primitive when not drawing unfilled + * polygons. + * + * Used only for the default render stage which always decomposes + * primitives to trianges/lines/points. For the accelerated stage, + * which renders strips as strips, the equivalent calculations are + * performed in mgarender.c. + */ +static void mgaRenderPrimitive( GLcontext *ctx, GLenum prim ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + GLuint rprim = reduced_prim[prim]; + + mmesa->render_primitive = prim; + + if (rprim == GL_TRIANGLES && (ctx->_TriangleCaps & DD_TRI_UNFILLED)) + return; + + if (mmesa->raster_primitive != rprim) { + mgaRasterPrimitive( ctx, rprim, MGA_WA_TRIANGLES ); + } +} + +static void mgaRenderFinish( GLcontext *ctx ) +{ + if (MGA_CONTEXT(ctx)->RenderIndex & MGA_FALLBACK_BIT) + _swrast_flush( ctx ); +} + + + +/**********************************************************************/ +/* Manage total rasterization fallbacks */ +/**********************************************************************/ + +void mgaFallback( GLcontext *ctx, GLuint bit, GLboolean mode ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + GLuint oldfallback = mmesa->Fallback; + + if (mode) { + mmesa->Fallback |= bit; + if (oldfallback == 0) { + FLUSH_BATCH(mmesa); + _swsetup_Wakeup( ctx ); + mmesa->RenderIndex = ~0; + } + } + else { + mmesa->Fallback &= ~bit; + if (oldfallback == bit) { + _swrast_flush( ctx ); + tnl->Driver.Render.Start = mgaCheckTexSizes; + tnl->Driver.Render.PrimitiveNotify = mgaRenderPrimitive; + tnl->Driver.Render.Finish = mgaRenderFinish; + tnl->Driver.Render.BuildVertices = mgaBuildVertices; + mmesa->new_gl_state |= (_MGA_NEW_RENDERSTATE | + _MGA_NEW_RASTERSETUP); + } + } +} + + +void mgaDDInitTriFuncs( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + static int firsttime = 1; + if (firsttime) { + init_rast_tab(); + firsttime = 0; + } + + mmesa->RenderIndex = ~0; + + tnl->Driver.RunPipeline = mgaRunPipeline; + tnl->Driver.Render.Start = mgaCheckTexSizes; + tnl->Driver.Render.Finish = mgaRenderFinish; + tnl->Driver.Render.PrimitiveNotify = mgaRenderPrimitive; + tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple; + tnl->Driver.Render.BuildVertices = mgaBuildVertices; + tnl->Driver.Render.Multipass = NULL; } diff --git a/xc/lib/GL/mesa/src/drv/mga/mgavb.c b/xc/lib/GL/mesa/src/drv/mga/mgavb.c index 574bf82d7..b4bb582b9 100644 --- a/xc/lib/GL/mesa/src/drv/mga/mgavb.c +++ b/xc/lib/GL/mesa/src/drv/mga/mgavb.c @@ -28,483 +28,470 @@ #include "mgacontext.h" #include "mgavb.h" +#include "mgatris.h" +#include "mgaioctl.h" #include "mga_xmesa.h" -#include "stages.h" +#include "glheader.h" +#include "mtypes.h" #include "mem.h" +#include "macros.h" +#include "colormac.h" +#include "mmath.h" + +#include "tnl/t_context.h" +#include "swrast_setup/swrast_setup.h" +#include "swrast/swrast.h" #include <stdio.h> #include <stdlib.h> -#define TEX0 { \ - v->v.tu0 = tc0[i][0]; \ - v->v.tv0 = tc0[i][1]; \ -} -#define TEX1 { \ - v->v.tu1 = tc1[i][0]; \ - v->v.tv1 = tc1[i][1]; \ -} +#define MGA_TEX1_BIT 0x1 +#define MGA_TEX0_BIT 0x2 +#define MGA_RGBA_BIT 0x4 +#define MGA_SPEC_BIT 0x8 +#define MGA_FOG_BIT 0x10 +#define MGA_XYZW_BIT 0x20 +#define MGA_PTEX_BIT 0x40 +#define MGA_MAX_SETUP 0x80 + +static struct { + void (*emit)( GLcontext *, GLuint, GLuint, void *, GLuint ); + interp_func interp; + copy_pv_func copy_pv; + GLboolean (*check_tex_sizes)( GLcontext *ctx ); + GLuint vertex_size; + GLuint vertex_stride_shift; + GLuint vertex_format; +} setup_tab[MGA_MAX_SETUP]; + + +#define TINY_VERTEX_FORMAT 0 +#define NOTEX_VERTEX_FORMAT 0 +#define TEX0_VERTEX_FORMAT (MGA_A|MGA_S|MGA_F) +#define TEX1_VERTEX_FORMAT (MGA_A|MGA_S|MGA_F|MGA_T2) +#define PROJ_TEX1_VERTEX_FORMAT 0 +#define TEX2_VERTEX_FORMAT 0 +#define TEX3_VERTEX_FORMAT 0 +#define PROJ_TEX3_VERTEX_FORMAT 0 + +#define DO_XYZW (IND & MGA_XYZW_BIT) +#define DO_RGBA (IND & MGA_RGBA_BIT) +#define DO_SPEC (IND & MGA_SPEC_BIT) +#define DO_FOG (IND & MGA_FOG_BIT) +#define DO_TEX0 (IND & MGA_TEX0_BIT) +#define DO_TEX1 (IND & MGA_TEX1_BIT) +#define DO_TEX2 0 +#define DO_TEX3 0 +#define DO_PTEX (IND & MGA_PTEX_BIT) + + +#define VERTEX mgaVertex +#define VERTEX_COLOR mga_color_t +#define LOCALVARS mgaContextPtr mmesa = MGA_CONTEXT(ctx); +#define GET_VIEWPORT_MAT() mmesa->hw_viewport +#define GET_TEXSOURCE(n) mmesa->tmu_source[n] +#define GET_VERTEX_FORMAT() mmesa->vertex_format +#define GET_VERTEX_STORE() mmesa->verts +#define GET_VERTEX_STRIDE_SHIFT() mmesa->vertex_stride_shift +#define GET_UBYTE_COLOR_STORE() &mmesa->UbyteColor +#define GET_UBYTE_SPEC_COLOR_STORE() &mmesa->UbyteSecondaryColor + +#define HAVE_HW_VIEWPORT 0 +#define HAVE_HW_DIVIDE 0 +#define HAVE_RGBA_COLOR 0 +#define HAVE_TINY_VERTICES 0 +#define HAVE_NOTEX_VERTICES 0 +#define HAVE_TEX0_VERTICES 1 +#define HAVE_TEX1_VERTICES 1 +#define HAVE_TEX2_VERTICES 0 +#define HAVE_TEX3_VERTICES 0 +#define HAVE_PTEX_VERTICES 0 + +#define UNVIEWPORT_VARS \ + const GLfloat dx = - mmesa->drawX - SUBPIXEL_X; \ + const GLfloat dy = (mmesa->driDrawable->h + \ + mmesa->drawY + SUBPIXEL_Y); \ + const GLfloat sz = 1.0 / mmesa->depth_scale + +#define UNVIEWPORT_X(x) x + dx; +#define UNVIEWPORT_Y(y) - y + dy; +#define UNVIEWPORT_Z(z) z * sz; + +#define PTEX_FALLBACK() FALLBACK(ctx, MGA_FALLBACK_TEXTURE, 1) + + +#define IMPORT_FLOAT_COLORS mga_import_float_colors +#define IMPORT_FLOAT_SPEC_COLORS mga_import_float_spec_colors + +#define INTERP_VERTEX setup_tab[MGA_CONTEXT(ctx)->SetupIndex].interp +#define COPY_PV_VERTEX setup_tab[MGA_CONTEXT(ctx)->SetupIndex].copy_pv + + +/*********************************************************************** + * Generate pv-copying and translation functions * + ***********************************************************************/ + +#define TAG(x) mga_##x +#include "tnl_dd/t_dd_vb.c" + +/*********************************************************************** + * Generate vertex emit and interp functions * + ***********************************************************************/ + + +#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT) +#define TAG(x) x##_wg +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_SPEC_BIT) +#define TAG(x) x##_wgs +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_TEX0_BIT) +#define TAG(x) x##_wgt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT) +#define TAG(x) x##_wgt0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_TEX0_BIT|MGA_PTEX_BIT) +#define TAG(x) x##_wgpt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_SPEC_BIT|MGA_TEX0_BIT) +#define TAG(x) x##_wgst0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_SPEC_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT) +#define TAG(x) x##_wgst0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_SPEC_BIT|MGA_TEX0_BIT|MGA_PTEX_BIT) +#define TAG(x) x##_wgspt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_FOG_BIT) +#define TAG(x) x##_wgf +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_FOG_BIT|MGA_SPEC_BIT) +#define TAG(x) x##_wgfs +#include "tnl_dd/t_dd_vbtmp.h" -#define SPC { \ - GLubyte *spec = &(VB->Spec[0][i][0]); \ - v->v.specular.red = spec[0]; \ - v->v.specular.green = spec[1]; \ - v->v.specular.blue = spec[2]; \ -} +#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_FOG_BIT|MGA_TEX0_BIT) +#define TAG(x) x##_wgft0 +#include "tnl_dd/t_dd_vbtmp.h" -#define FOG { \ - GLubyte *spec = &(VB->Spec[0][i][0]); \ - v->v.specular.alpha = spec[3]; \ -} +#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_FOG_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT) +#define TAG(x) x##_wgft0t1 +#include "tnl_dd/t_dd_vbtmp.h" -#define COL { \ - GLubyte *col = &(VB->Color[0]->data[i][0]); \ - v->v.color.blue = col[2]; \ - v->v.color.green = col[1]; \ - v->v.color.red = col[0]; \ - v->v.color.alpha = col[3]; \ -} +#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_FOG_BIT|MGA_TEX0_BIT|MGA_PTEX_BIT) +#define TAG(x) x##_wgfpt0 +#include "tnl_dd/t_dd_vbtmp.h" -/* The v code we have doesn't seem to support projective texturing - * in the multitexture case. (Would require another 1/w value for the - * second set of texcoords). This may be a problem for the g400. - */ -#define TEX0_4 \ - if (VB->TexCoordPtr[0]->size == 4) { \ - GLfloat (*tc)[4] = VB->TexCoordPtr[0]->data; \ - v = &(MGA_DRIVER_DATA(VB)->verts[start]); \ - mmesa->setupdone &= ~MGA_WIN_BIT; \ - for (i = start; i < end; i++, v++) { \ - GLfloat oow = 1.0 / tc[i][3]; \ - v->v.rhw *= tc[i][3]; \ - v->v.tu0 *= oow; \ - v->v.tv0 *= oow; \ - } \ - } - - -#define COORD \ - GLfloat *win = VB->Win.data[i]; \ - v->v.rhw = win[3]; \ - v->v.z = depth_scale * win[2]; \ - v->v.x = win[0] + xoffset; \ - v->v.y = - win[1] + yoffset; - - -#define NOP - - - - -#define SETUPFUNC(name,win,col,tex0,tex1,tex0_4,spec,fog) \ -static void name(struct vertex_buffer *VB, GLuint start, GLuint end) \ -{ \ - mgaContextPtr mmesa = MGA_CONTEXT( VB->ctx ); \ - mgaVertexPtr v; \ - GLfloat (*tc0)[4]; \ - GLfloat (*tc1)[4]; \ - const GLfloat depth_scale = mmesa->depth_scale; \ - const GLfloat xoffset = mmesa->drawX + SUBPIXEL_X; \ - const GLfloat yoffset = mmesa->driDrawable->h + mmesa->drawY + \ - SUBPIXEL_Y; \ - int i; \ - (void) xoffset; (void) yoffset; (void) depth_scale; \ - gl_import_client_data( VB, VB->ctx->RenderFlags, \ - (VB->ClipOrMask \ - ? VEC_WRITABLE|VEC_GOOD_STRIDE \ - : VEC_GOOD_STRIDE)); \ - \ - tc0 = VB->TexCoordPtr[mmesa->tmu_source[0]]->data; \ - tc1 = VB->TexCoordPtr[mmesa->tmu_source[1]]->data; \ - \ - v = &(MGA_DRIVER_DATA(VB)->verts[start]); \ - \ - if (VB->ClipOrMask == 0) \ - for (i=start; i < end; i++, v++) { \ - win; \ - col; \ - tex0; \ - tex1; \ - spec; \ - fog; \ - } \ - else \ - for (i=start; i < end; i++, v++) { \ - if (VB->ClipMask[i] == 0) { \ - win; \ - tex0; \ - tex1; \ - spec; \ - fog; \ - } \ - col; \ - } \ - tex0_4; \ -} +#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_FOG_BIT|MGA_SPEC_BIT|MGA_TEX0_BIT) +#define TAG(x) x##_wgfst0 +#include "tnl_dd/t_dd_vbtmp.h" +#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_FOG_BIT|MGA_SPEC_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT) +#define TAG(x) x##_wgfst0t1 +#include "tnl_dd/t_dd_vbtmp.h" +#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_FOG_BIT|MGA_SPEC_BIT|MGA_TEX0_BIT|MGA_PTEX_BIT) +#define TAG(x) x##_wgfspt0 +#include "tnl_dd/t_dd_vbtmp.h" -SETUPFUNC(rs_wt0, COORD,NOP,TEX0,NOP,TEX0_4,NOP,NOP) -SETUPFUNC(rs_wt0t1, COORD,NOP,TEX0,TEX1,TEX0_4,NOP,NOP) -SETUPFUNC(rs_wft0, COORD,NOP,TEX0,NOP,TEX0_4,NOP,FOG) -SETUPFUNC(rs_wft0t1, COORD,NOP,TEX0,TEX1,TEX0_4,NOP,FOG) -SETUPFUNC(rs_wg, COORD,COL,NOP,NOP,NOP,NOP,NOP) -SETUPFUNC(rs_wgs, COORD,COL,NOP,NOP,NOP,SPC,NOP) -SETUPFUNC(rs_wgt0, COORD,COL,TEX0,NOP,TEX0_4,NOP,NOP) -SETUPFUNC(rs_wgt0t1, COORD,COL,TEX0,TEX1,TEX0_4,NOP,NOP) -SETUPFUNC(rs_wgst0, COORD,COL,TEX0,NOP,TEX0_4,SPC,NOP) -SETUPFUNC(rs_wgst0t1, COORD,COL,TEX0,TEX1,TEX0_4,SPC,NOP) -SETUPFUNC(rs_wgf, COORD,COL,NOP,NOP,NOP,NOP,FOG) -SETUPFUNC(rs_wgfs, COORD,COL,NOP,NOP,NOP,SPC,FOG) -SETUPFUNC(rs_wgft0, COORD,COL,TEX0,NOP,TEX0_4,NOP,FOG) -SETUPFUNC(rs_wgft0t1, COORD,COL,TEX0,TEX1,TEX0_4,NOP,FOG) -SETUPFUNC(rs_wgfst0, COORD,COL,TEX0,NOP,TEX0_4,SPC,FOG) -SETUPFUNC(rs_wgfst0t1, COORD,COL,TEX0,TEX1,TEX0_4,SPC,FOG) - -SETUPFUNC(rs_t0, NOP,NOP,TEX0,NOP,TEX0_4,NOP,NOP) -SETUPFUNC(rs_t0t1, NOP,NOP,TEX0,TEX1,TEX0_4,NOP,NOP) -SETUPFUNC(rs_f, NOP,NOP,NOP,NOP,NOP,NOP,FOG) -SETUPFUNC(rs_ft0, NOP,NOP,TEX0,NOP,TEX0_4,NOP,FOG) -SETUPFUNC(rs_ft0t1, NOP,NOP,TEX0,TEX1,TEX0_4,NOP,FOG) -SETUPFUNC(rs_g, NOP,COL,NOP,NOP,NOP,NOP,NOP) -SETUPFUNC(rs_gs, NOP,COL,NOP,NOP,NOP,SPC,NOP) -SETUPFUNC(rs_gt0, NOP,COL,TEX0,NOP,TEX0_4,NOP,NOP) -SETUPFUNC(rs_gt0t1, NOP,COL,TEX0,TEX1,TEX0_4,NOP,NOP) -SETUPFUNC(rs_gst0, NOP,COL,TEX0,NOP,TEX0_4,SPC,NOP) -SETUPFUNC(rs_gst0t1, NOP,COL,TEX0,TEX1,TEX0_4,SPC,NOP) -SETUPFUNC(rs_gf, NOP,COL,NOP,NOP,NOP,NOP,FOG) -SETUPFUNC(rs_gfs, NOP,COL,NOP,NOP,NOP,SPC,FOG) -SETUPFUNC(rs_gft0, NOP,COL,TEX0,NOP,TEX0_4,NOP,FOG) -SETUPFUNC(rs_gft0t1, NOP,COL,TEX0,TEX1,TEX0_4,NOP,FOG) -SETUPFUNC(rs_gfst0, NOP,COL,TEX0,NOP,TEX0_4,SPC,FOG) -SETUPFUNC(rs_gfst0t1, NOP,COL,TEX0,TEX1,TEX0_4,SPC,FOG) - - -static void rs_invalid(struct vertex_buffer *VB, GLuint start, GLuint end) -{ - fprintf(stderr, "mgaRasterSetup(): invalid combination\n"); -} +#define IND (MGA_TEX0_BIT) +#define TAG(x) x##_t0 +#include "tnl_dd/t_dd_vbtmp.h" -typedef void (*setupFunc)(struct vertex_buffer *,GLuint,GLuint); +#define IND (MGA_TEX0_BIT|MGA_TEX1_BIT) +#define TAG(x) x##_t0t1 +#include "tnl_dd/t_dd_vbtmp.h" -static setupFunc setup_func[0x80]; +#define IND (MGA_FOG_BIT) +#define TAG(x) x##_f +#include "tnl_dd/t_dd_vbtmp.h" -void mgaDDSetupInit( void ) -{ - int i; - - for (i = 0 ; i < 0x80 ; i++) - setup_func[i] = rs_invalid; - - /* Functions to build vert's from scratch */ - setup_func[MGA_WIN_BIT|MGA_TEX0_BIT] = rs_wt0; - setup_func[MGA_WIN_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT] = rs_wt0t1; - setup_func[MGA_WIN_BIT|MGA_FOG_BIT|MGA_TEX0_BIT] = rs_wft0; - setup_func[MGA_WIN_BIT|MGA_FOG_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT] = rs_wft0t1; - setup_func[MGA_WIN_BIT|MGA_RGBA_BIT] = rs_wg; - setup_func[MGA_WIN_BIT|MGA_RGBA_BIT|MGA_SPEC_BIT] = rs_wgs; - setup_func[MGA_WIN_BIT|MGA_RGBA_BIT|MGA_TEX0_BIT] = rs_wgt0; - setup_func[MGA_WIN_BIT|MGA_RGBA_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT] = rs_wgt0t1; - setup_func[MGA_WIN_BIT|MGA_RGBA_BIT|MGA_SPEC_BIT|MGA_TEX0_BIT] = rs_wgst0; - setup_func[MGA_WIN_BIT|MGA_RGBA_BIT|MGA_SPEC_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT] = rs_wgst0t1; - setup_func[MGA_WIN_BIT|MGA_RGBA_BIT|MGA_FOG_BIT] = rs_wgf; - setup_func[MGA_WIN_BIT|MGA_RGBA_BIT|MGA_FOG_BIT|MGA_SPEC_BIT] = rs_wgfs; - setup_func[MGA_WIN_BIT|MGA_RGBA_BIT|MGA_FOG_BIT|MGA_TEX0_BIT] = rs_wgft0; - setup_func[MGA_WIN_BIT|MGA_RGBA_BIT|MGA_FOG_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT] = rs_wgft0t1; - setup_func[MGA_WIN_BIT|MGA_RGBA_BIT|MGA_FOG_BIT|MGA_SPEC_BIT|MGA_TEX0_BIT] = rs_wgfst0; - setup_func[MGA_WIN_BIT|MGA_RGBA_BIT|MGA_FOG_BIT|MGA_SPEC_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT] = rs_wgfst0t1; - - /* Repair functions */ - setup_func[MGA_TEX0_BIT] = rs_t0; - setup_func[MGA_TEX0_BIT|MGA_TEX1_BIT] = rs_t0t1; - setup_func[MGA_FOG_BIT] = rs_f; - setup_func[MGA_FOG_BIT|MGA_TEX0_BIT] = rs_ft0; - setup_func[MGA_FOG_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT] = rs_ft0t1; - setup_func[MGA_RGBA_BIT] = rs_g; - setup_func[MGA_RGBA_BIT|MGA_SPEC_BIT] = rs_gs; - setup_func[MGA_RGBA_BIT|MGA_TEX0_BIT] = rs_gt0; - setup_func[MGA_RGBA_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT] = rs_gt0t1; - setup_func[MGA_RGBA_BIT|MGA_SPEC_BIT|MGA_TEX0_BIT] = rs_gst0; - setup_func[MGA_RGBA_BIT|MGA_SPEC_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT] = rs_gst0t1; - setup_func[MGA_RGBA_BIT|MGA_FOG_BIT] = rs_gf; - setup_func[MGA_RGBA_BIT|MGA_FOG_BIT|MGA_SPEC_BIT] = rs_gfs; - setup_func[MGA_RGBA_BIT|MGA_FOG_BIT|MGA_TEX0_BIT] = rs_gft0; - setup_func[MGA_RGBA_BIT|MGA_FOG_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT] = rs_gft0t1; - setup_func[MGA_RGBA_BIT|MGA_FOG_BIT|MGA_SPEC_BIT|MGA_TEX0_BIT] = rs_gfst0; - setup_func[MGA_RGBA_BIT|MGA_FOG_BIT|MGA_SPEC_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT] = rs_gfst0t1; - -} - - -void mgaPrintSetupFlags(char *msg, GLuint flags ) -{ - fprintf(stderr, "%s: %d %s%s%s%s%s%s%s\n", - msg, - (int)flags, - (flags & MGA_WIN_BIT) ? " xyzw," : "", - (flags & MGA_RGBA_BIT) ? " rgba," : "", - (flags & MGA_SPEC_BIT) ? " spec," : "", - (flags & MGA_FOG_BIT) ? " fog," : "", - (flags & MGA_TEX0_BIT) ? " tex-0," : "", - (flags & MGA_TEX1_BIT) ? " tex-1," : "", - (flags & MGA_ALPHA_BIT) ? " alpha," : ""); -} +#define IND (MGA_FOG_BIT|MGA_TEX0_BIT) +#define TAG(x) x##_ft0 +#include "tnl_dd/t_dd_vbtmp.h" +#define IND (MGA_FOG_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT) +#define TAG(x) x##_ft0t1 +#include "tnl_dd/t_dd_vbtmp.h" +#define IND (MGA_RGBA_BIT) +#define TAG(x) x##_g +#include "tnl_dd/t_dd_vbtmp.h" +#define IND (MGA_RGBA_BIT|MGA_SPEC_BIT) +#define TAG(x) x##_gs +#include "tnl_dd/t_dd_vbtmp.h" -void mgaChooseRasterSetupFunc(GLcontext *ctx) -{ - mgaContextPtr mmesa = MGA_CONTEXT( ctx ); - int funcindex = (MGA_WIN_BIT | MGA_RGBA_BIT); - int multi = mmesa->multitex; - - mmesa->vertsize = 8; - mmesa->tmu_source[0] = 0; - mmesa->tmu_source[1] = 1; - mmesa->tex_dest[0] = MGA_TEX0_BIT; - mmesa->tex_dest[1] = MGA_TEX1_BIT; - mmesa->multitex = 0; - mmesa->blend_flags &= ~MGA_BLEND_MULTITEX; - - if (ctx->Texture.ReallyEnabled & 0xf) { - /* This doesn't work for non-RGBA textures - if (ctx->Texture.Unit[0].EnvMode == GL_REPLACE) - funcindex &= ~MGA_RGBA_BIT; - */ - if (ctx->Texture.Unit[0].EnvMode == GL_BLEND && - mmesa->envcolor) - { - mmesa->multitex = 1; - mmesa->vertsize = 10; - mmesa->tmu_source[1] = 0; - funcindex |= MGA_TEX1_BIT; - } +#define IND (MGA_RGBA_BIT|MGA_TEX0_BIT) +#define TAG(x) x##_gt0 +#include "tnl_dd/t_dd_vbtmp.h" - funcindex |= MGA_TEX0_BIT; - } +#define IND (MGA_RGBA_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT) +#define TAG(x) x##_gt0t1 +#include "tnl_dd/t_dd_vbtmp.h" - if (ctx->Texture.ReallyEnabled & 0xf0) { - if (ctx->Texture.ReallyEnabled & 0xf) { - mmesa->multitex = 1; - mmesa->vertsize = 10; - mmesa->blend_flags |= MGA_BLEND_MULTITEX; - funcindex |= MGA_TEX1_BIT; - } else { - /* Just a funny way of doing single texturing - */ - mmesa->tmu_source[0] = 1; - mmesa->tex_dest[1] = MGA_TEX0_BIT; - - if (ctx->Texture.Unit[0].EnvMode == GL_BLEND && - mmesa->envcolor) - { - mmesa->multitex = 1; - mmesa->vertsize = 10; - mmesa->tmu_source[1] = 1; - funcindex |= MGA_TEX1_BIT; - } - - funcindex |= MGA_TEX0_BIT; - } - } +#define IND (MGA_RGBA_BIT|MGA_SPEC_BIT|MGA_TEX0_BIT) +#define TAG(x) x##_gst0 +#include "tnl_dd/t_dd_vbtmp.h" - if (multi != mmesa->multitex) - mmesa->new_state |= MGA_NEW_WARP; +#define IND (MGA_RGBA_BIT|MGA_SPEC_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT) +#define TAG(x) x##_gst0t1 +#include "tnl_dd/t_dd_vbtmp.h" +#define IND (MGA_RGBA_BIT|MGA_FOG_BIT) +#define TAG(x) x##_gf +#include "tnl_dd/t_dd_vbtmp.h" - /* Not really a good place to do this - need to make the mga state - * management code more event-driven so this can be calculated for - * free. - */ +#define IND (MGA_RGBA_BIT|MGA_FOG_BIT|MGA_SPEC_BIT) +#define TAG(x) x##_gfs +#include "tnl_dd/t_dd_vbtmp.h" - if (ctx->Color.BlendEnabled) - funcindex |= MGA_ALPHA_BIT; +#define IND (MGA_RGBA_BIT|MGA_FOG_BIT|MGA_TEX0_BIT) +#define TAG(x) x##_gft0 +#include "tnl_dd/t_dd_vbtmp.h" - if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) - funcindex |= MGA_SPEC_BIT; +#define IND (MGA_RGBA_BIT|MGA_FOG_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT) +#define TAG(x) x##_gft0t1 +#include "tnl_dd/t_dd_vbtmp.h" - if (ctx->Fog.Enabled) - funcindex |= MGA_FOG_BIT; +#define IND (MGA_RGBA_BIT|MGA_FOG_BIT|MGA_SPEC_BIT|MGA_TEX0_BIT) +#define TAG(x) x##_gfst0 +#include "tnl_dd/t_dd_vbtmp.h" - if (0) - mgaPrintSetupFlags("xsmesa: full setup function", funcindex); +#define IND (MGA_RGBA_BIT|MGA_FOG_BIT|MGA_SPEC_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT) +#define TAG(x) x##_gfst0t1 +#include "tnl_dd/t_dd_vbtmp.h" - mmesa->dirty |= MGA_UPLOAD_PIPE; - mmesa->setupindex = funcindex; - /* Called by mesa's clip functons: - */ - ctx->Driver.RasterSetup = setup_func[funcindex & ~MGA_ALPHA_BIT]; +static void init_setup_tab( void ) +{ + init_wg(); + init_wgs(); + init_wgt0(); + init_wgt0t1(); + init_wgpt0(); + init_wgst0(); + init_wgst0t1(); + init_wgspt0(); + init_wgf(); + init_wgfs(); + init_wgft0(); + init_wgft0t1(); + init_wgfpt0(); + init_wgfst0(); + init_wgfst0t1(); + init_wgfspt0(); + init_t0(); + init_t0t1(); + init_f(); + init_ft0(); + init_ft0t1(); + init_g(); + init_gs(); + init_gt0(); + init_gt0t1(); + init_gst0(); + init_gst0t1(); + init_gf(); + init_gfs(); + init_gft0(); + init_gft0t1(); + init_gfst0(); + init_gfst0t1(); } -void mgaDDCheckPartialRasterSetup( GLcontext *ctx, struct gl_pipeline_stage *d ) +void mgaPrintSetupFlags(char *msg, GLuint flags ) { - mgaContextPtr mmesa = MGA_CONTEXT( ctx ); - GLuint tmp = mmesa->setupdone; + fprintf(stderr, "%s: %d %s%s%s%s%s%s\n", + msg, + (int)flags, + (flags & MGA_XYZW_BIT) ? " xyzw," : "", + (flags & MGA_RGBA_BIT) ? " rgba," : "", + (flags & MGA_SPEC_BIT) ? " spec," : "", + (flags & MGA_FOG_BIT) ? " fog," : "", + (flags & MGA_TEX0_BIT) ? " tex-0," : "", + (flags & MGA_TEX1_BIT) ? " tex-1," : ""); +} - d->type = 0; - mmesa->setupdone = 0; /* cleared if we return */ - if ((ctx->Array.Summary & VERT_OBJ_ANY) == 0) - return; +void mgaCheckTexSizes( GLcontext *ctx ) +{ + mgaContextPtr mmesa = MGA_CONTEXT( ctx ); + TNLcontext *tnl = TNL_CONTEXT(ctx); - if (ctx->IndirectTriangles) - return; + /*fprintf(stderr, "%s\n", __FUNCTION__);*/ - mmesa->setupdone = tmp; + if (!setup_tab[mmesa->SetupIndex].check_tex_sizes(ctx)) { + mmesa->SetupIndex |= MGA_PTEX_BIT; + mmesa->SetupNewInputs = ~0; - /* disabled until we have a merge&render op */ - /* d->inputs = available; */ - /* d->outputs = VERT_RAST_SETUP_PART; */ - /* d->type = PIPE_PRECALC; */ + if (!mmesa->Fallback && + !(ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) { + tnl->Driver.Render.Interp = setup_tab[mmesa->SetupIndex].interp; + tnl->Driver.Render.CopyPV = setup_tab[mmesa->SetupIndex].copy_pv; + } + } } -/* Repair existing precalculated vertices with new data. - */ -void mgaDDPartialRasterSetup( struct vertex_buffer *VB ) +void mgaBuildVertices( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint newinputs ) { - mgaContextPtr mmesa = MGA_CONTEXT( VB->ctx ); - GLuint new = VB->pipeline->new_outputs; - GLuint available = VB->pipeline->outputs; - GLuint ind = 0; - - if (new & VERT_WIN) { - new = available; - ind |= MGA_WIN_BIT | MGA_FOG_BIT; - } + mgaContextPtr mmesa = MGA_CONTEXT( ctx ); + GLubyte *v = ((GLubyte *)mmesa->verts + (start<<mmesa->vertex_stride_shift)); + GLuint stride = 1<<mmesa->vertex_stride_shift; - if (new & VERT_RGBA) - ind |= MGA_RGBA_BIT | MGA_SPEC_BIT; + newinputs |= mmesa->SetupNewInputs; + mmesa->SetupNewInputs = 0; - if (new & VERT_TEX0_ANY) - ind |= MGA_TEX0_BIT; + if (!newinputs) + return; - if (new & VERT_TEX1_ANY) - ind |= mmesa->tex_dest[1]; + if (newinputs & VERT_CLIP) { + setup_tab[mmesa->SetupIndex].emit( ctx, start, count, v, stride ); + } else { + GLuint ind = 0; - if (new & VERT_FOG_COORD) - ind |= MGA_FOG_BIT; + if (newinputs & VERT_RGBA) + ind |= MGA_RGBA_BIT; + + if (newinputs & VERT_SPEC_RGB) + ind |= MGA_SPEC_BIT; - mmesa->setupdone &= ~ind; - ind &= mmesa->setupindex; - mmesa->setupdone |= ind; + if (newinputs & VERT_TEX0) + ind |= MGA_TEX0_BIT; - if (0) - mgaPrintSetupFlags("xsmesa: partial setup function", ind); - - if (ind) - setup_func[ind&~MGA_ALPHA_BIT]( VB, VB->Start, VB->Count ); -} + if (newinputs & VERT_TEX1) + ind |= MGA_TEX0_BIT|MGA_TEX1_BIT; + if (newinputs & VERT_FOG_COORD) + ind |= MGA_FOG_BIT; -void mgaDDDoRasterSetup( struct vertex_buffer *VB ) -{ - GLcontext *ctx = VB->ctx; -/* mgaContextPtr mmesa = MGA_CONTEXT( ctx ); */ + if (mmesa->SetupIndex & MGA_PTEX_BIT) + ind = ~0; - /* Can't lock, won't lock - */ -/* REFRESH_DRAWABLE_INFO( mmesa ); */ + ind &= mmesa->SetupIndex; - if (VB->Type == VB_CVA_PRECALC) - mgaDDPartialRasterSetup( VB ); - else if (ctx->Driver.RasterSetup) - ctx->Driver.RasterSetup( VB, VB->CopyStart, VB->Count ); + if (ind) { + setup_tab[ind].emit( ctx, start, count, v, stride ); + } + } } -static void FatalError( char *s ) + +void mgaChooseVertexState( GLcontext *ctx ) { - fprintf(stderr, s); - exit(1); -} + mgaContextPtr mmesa = MGA_CONTEXT( ctx ); + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLuint ind = MGA_XYZW_BIT|MGA_RGBA_BIT; + if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) + ind |= MGA_SPEC_BIT; -void mgaDDResizeVB( struct vertex_buffer *VB, GLuint size ) -{ - mgaVertexBufferPtr mvb = MGA_DRIVER_DATA(VB); - - while (mvb->size < size) - mvb->size *= 2; - - FREE( mvb->vert_store ); - mvb->vert_store = MALLOC( sizeof(mgaVertex) * mvb->size + 31); - if (!mvb->vert_store) - FatalError("mga-glx: out of memory !\n"); - - mvb->verts = (mgaVertexPtr)(((unsigned long)mvb->vert_store + 31) & ~31); - - gl_vector1ui_free( &mvb->clipped_elements ); - gl_vector1ui_alloc( &mvb->clipped_elements, VEC_WRITABLE, mvb->size, 32 ); - if (!mvb->clipped_elements.start) - FatalError("mga-glx: out of memory !\n"); - - ALIGN_FREE( VB->ClipMask ); - VB->ClipMask = (GLubyte *)ALIGN_MALLOC(sizeof(GLubyte) * mvb->size, 32); - if (!VB->ClipMask) - FatalError("mga-glx: out of memory !\n"); - - if (VB->Type == VB_IMMEDIATE) { - FREE( mvb->primitive ); - FREE( mvb->next_primitive ); - mvb->primitive = (GLuint *)MALLOC( sizeof(GLuint) * mvb->size ); - mvb->next_primitive = (GLuint *)MALLOC( sizeof(GLuint) * mvb->size ); - if (!mvb->primitive || !mvb->next_primitive) - FatalError("mga-glx: out of memory!"); + if (ctx->Fog.Enabled) + ind |= MGA_FOG_BIT; + + if (ctx->Texture._ReallyEnabled & TEXTURE1_ANY) { + if (ctx->Texture._ReallyEnabled & TEXTURE0_ANY) { + ind |= MGA_TEX1_BIT|MGA_TEX0_BIT; + } + else { + ind |= MGA_TEX0_BIT; + } + } + else if (ctx->Texture._ReallyEnabled & TEXTURE0_ANY) { + ind |= MGA_TEX0_BIT; + } + + mmesa->SetupIndex = ind; + + if (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED)) { + tnl->Driver.Render.Interp = mga_interp_extras; + tnl->Driver.Render.CopyPV = mga_copy_pv_extras; + } else { + tnl->Driver.Render.Interp = setup_tab[ind].interp; + tnl->Driver.Render.CopyPV = setup_tab[ind].copy_pv; } -} + if (setup_tab[ind].vertex_format != mmesa->vertex_format) { + FLUSH_BATCH(mmesa); + mmesa->new_state |= MGA_NEW_WARP; + mmesa->dirty |= MGA_UPLOAD_PIPE; + mmesa->vertex_format = setup_tab[ind].vertex_format; + mmesa->vertex_size = setup_tab[ind].vertex_size; + mmesa->vertex_stride_shift = setup_tab[ind].vertex_stride_shift; + } +} -void mgaDDRegisterVB( struct vertex_buffer *VB ) -{ - mgaVertexBufferPtr mvb; - mvb = (mgaVertexBufferPtr)MALLOC( sizeof(*mvb) ); - /* This looks like it allocates a lot of memory, but it basically - * just sets an upper limit on how much can be used - nothing like - * this amount will ever be turned into 'real' memory. - */ - mvb->size = VB->Size * 5; - mvb->vert_store = MALLOC( sizeof(mgaVertex) * mvb->size + 31); - if (!mvb->vert_store) - FatalError("mga-glx: out of memory !\n"); +void mga_emit_contiguous_verts( GLcontext *ctx, + GLuint start, + GLuint count ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + GLuint vertex_size = mmesa->vertex_size * 4; + GLuint *dest = mgaAllocDmaLow( mmesa, (count-start) * vertex_size); + setup_tab[mmesa->SetupIndex].emit( ctx, start, count, dest, vertex_size ); +} + - mvb->verts = (mgaVertexPtr)(((unsigned long)mvb->vert_store + 31) & ~31); - gl_vector1ui_alloc( &mvb->clipped_elements, VEC_WRITABLE, mvb->size, 32 ); - if (!mvb->clipped_elements.start) - FatalError("mga-glx: out of memory !\n"); +void mgaInitVB( GLcontext *ctx ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + GLuint size = TNL_CONTEXT(ctx)->vb.Size; - ALIGN_FREE( VB->ClipMask ); - VB->ClipMask = (GLubyte *)ALIGN_MALLOC(sizeof(GLubyte) * mvb->size, 32); - if (!VB->ClipMask) - FatalError("mga-glx: out of memory !\n"); + mmesa->verts = (char *)ALIGN_MALLOC(size * sizeof(mgaVertex), 32); - mvb->primitive = (GLuint *)MALLOC( sizeof(GLuint) * mvb->size ); - mvb->next_primitive = (GLuint *)MALLOC( sizeof(GLuint) * mvb->size ); - if (!mvb->primitive || !mvb->next_primitive) - FatalError("mga-glx: out of memory!"); + { + static int firsttime = 1; + if (firsttime) { + init_setup_tab(); + firsttime = 0; + } + } - VB->driver_data = mvb; + mmesa->new_state |= MGA_NEW_WARP; + mmesa->dirty |= MGA_UPLOAD_PIPE; + mmesa->vertex_format = setup_tab[0].vertex_format; + mmesa->vertex_size = setup_tab[0].vertex_size; + mmesa->vertex_stride_shift = setup_tab[0].vertex_stride_shift; } -void mgaDDUnregisterVB( struct vertex_buffer *VB ) +void mgaFreeVB( GLcontext *ctx ) { - mgaVertexBufferPtr mvb = MGA_DRIVER_DATA(VB); - - if (mvb) { - if (mvb->vert_store) FREE(mvb->vert_store); - if (mvb->primitive) FREE(mvb->primitive); - if (mvb->next_primitive) FREE(mvb->next_primitive); - gl_vector1ui_free( &mvb->clipped_elements ); - FREE(mvb); - VB->driver_data = 0; + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + if (mmesa->verts) { + ALIGN_FREE(mmesa->verts); + mmesa->verts = 0; + } + + if (mmesa->UbyteSecondaryColor.Ptr) { + ALIGN_FREE(mmesa->UbyteSecondaryColor.Ptr); + mmesa->UbyteSecondaryColor.Ptr = 0; + } + + if (mmesa->UbyteColor.Ptr) { + ALIGN_FREE(mmesa->UbyteColor.Ptr); + mmesa->UbyteColor.Ptr = 0; } } + diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_ioctl.c b/xc/lib/GL/mesa/src/drv/r128/r128_ioctl.c index a82cfe8c2..84c1a0aa2 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_ioctl.c +++ b/xc/lib/GL/mesa/src/drv/r128/r128_ioctl.c @@ -37,8 +37,12 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "r128_ioctl.h" #include "mem.h" +#include "macros.h" + +#include "swrast/swrast.h" #define R128_TIMEOUT 2048 +#define R128_IDLE_RETRY 32 /* ============================================================= @@ -83,7 +87,7 @@ drmBufPtr r128GetBufferLocked( r128ContextPtr rmesa ) } if ( !buf ) { - drmR128EngineReset( fd ); + drmCommandNone( fd, DRM_R128_CCE_RESET); UNLOCK_HARDWARE( rmesa ); fprintf( stderr, "Error: Could not get new VB... exiting\n" ); exit( -1 ); @@ -98,8 +102,9 @@ void r128FlushVerticesLocked( r128ContextPtr rmesa ) int nbox = rmesa->numClipRects; drmBufPtr buffer = rmesa->vert_buf; int count = rmesa->num_verts; - int prim = R128_TRIANGLES; + int prim = rmesa->hw_primitive; int fd = rmesa->driScreen->fd; + drmR128Vertex vertex; int i; rmesa->num_verts = 0; @@ -125,7 +130,11 @@ void r128FlushVerticesLocked( r128ContextPtr rmesa ) rmesa->sarea->nbox = nbox; } - drmR128FlushVertexBuffer( fd, prim, buffer->idx, count, 1 ); + vertex.prim = prim; + vertex.idx = buffer->idx; + vertex.count = count; + vertex.discard = 1; + drmCommandWrite( fd, DRM_R128_VERTEX, &vertex, sizeof(drmR128Vertex) ); } else { @@ -146,121 +155,21 @@ void r128FlushVerticesLocked( r128ContextPtr rmesa ) } rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS; - drmR128FlushVertexBuffer( fd, prim, buffer->idx, count, discard ); - } - } - - rmesa->dirty &= ~R128_UPLOAD_CLIPRECTS; -} - - - -/* ================================================================ - * Indexed vertex buffer handling - */ - -void r128GetEltBufLocked( r128ContextPtr rmesa ) -{ - rmesa->elt_buf = r128GetBufferLocked( rmesa ); -} - -void r128FireEltsLocked( r128ContextPtr rmesa, - GLuint start, GLuint end, - GLuint discard ) -{ - XF86DRIClipRectPtr pbox = rmesa->pClipRects; - int nbox = rmesa->numClipRects; - drmBufPtr buffer = rmesa->elt_buf; - int prim = R128_TRIANGLES; - int fd = rmesa->driScreen->fd; - int i; - - if ( !buffer ) - return; - - if ( rmesa->dirty & ~R128_UPLOAD_CLIPRECTS ) - r128EmitHwStateLocked( rmesa ); - - if ( !nbox ) - end = start; - - if ( nbox >= R128_NR_SAREA_CLIPRECTS ) - rmesa->dirty |= R128_UPLOAD_CLIPRECTS; - if ( start == end || !(rmesa->dirty & R128_UPLOAD_CLIPRECTS) ) - { - if ( nbox < 3 ) { - rmesa->sarea->nbox = 0; - } else { - rmesa->sarea->nbox = nbox; + vertex.prim = prim; + vertex.idx = buffer->idx; + vertex.count = count; + vertex.discard = discard; + drmCommandWrite( fd, DRM_R128_VERTEX, &vertex, sizeof(drmR128Vertex) ); } - - drmR128FlushIndices( fd, prim, buffer->idx, start, end, discard ); - } - else - { - for ( i = 0 ; i < nbox ; ) { - int nr = MIN2( i + R128_NR_SAREA_CLIPRECTS, nbox ); - XF86DRIClipRectPtr b = rmesa->sarea->boxes; - int d = 0; - - rmesa->sarea->nbox = nr - i; - for ( ; i < nr ; i++ ) { - *b++ = pbox[i]; - } - - /* Finished with the buffer? - */ - if ( nr == nbox ) { - d = discard; - } - - rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS; - drmR128FlushIndices( fd, prim, buffer->idx, start, end, d ); - } - } - - if ( R128_DEBUG & DEBUG_ALWAYS_SYNC ) { - drmR128WaitForIdleCCE( rmesa->driFd ); } rmesa->dirty &= ~R128_UPLOAD_CLIPRECTS; } -void r128FlushEltsLocked( r128ContextPtr rmesa ) -{ - if ( rmesa->first_elt != rmesa->next_elt ) { - r128FireEltsLocked( rmesa, - ((char *)rmesa->first_elt - - (char *)rmesa->elt_buf->address), - ((char *)rmesa->next_elt - - (char *)rmesa->elt_buf->address), - 0 ); - ALIGN_NEXT_ELT( rmesa ); - rmesa->first_elt = rmesa->next_elt; - } -} - -void r128ReleaseBufLocked( r128ContextPtr rmesa, drmBufPtr buffer ) -{ - int fd = rmesa->driScreen->fd; - - if ( !buffer ) - return; - - drmR128FlushVertexBuffer( fd, R128_TRIANGLES, buffer->idx, 0, 1 ); -} -/* Allocate some space in the current vertex buffer. If the current - * buffer is full, flush it and grab another one. - */ -CARD32 *r128AllocVertices( r128ContextPtr rmesa, int count ) -{ - return r128AllocVerticesInline( rmesa, count ); -} - /* ================================================================ * Texture uploads @@ -270,15 +179,24 @@ void r128FireBlitLocked( r128ContextPtr rmesa, drmBufPtr buffer, GLint offset, GLint pitch, GLint format, GLint x, GLint y, GLint width, GLint height ) { + drmR128Blit blit; GLint ret; - ret = drmR128TextureBlit( rmesa->driFd, buffer->idx, - offset, pitch, format, - x, y, width, height ); + blit.idx = buffer->idx; + blit.offset = offset; + blit.pitch = pitch; + blit.format = format; + blit.x = x; + blit.y = y; + blit.width = width; + blit.height = height; + + ret = drmCommandWrite( rmesa->driFd, DRM_R128_BLIT, + &blit, sizeof(drmR128Blit) ); if ( ret ) { UNLOCK_HARDWARE( rmesa ); - fprintf( stderr, "drmR128TextureBlit: return = %d\n", ret ); + fprintf( stderr, "DRM_R128_BLIT: return = %d\n", ret ); exit( 1 ); } } @@ -308,19 +226,7 @@ static int r128WaitForFrameCompletion( r128ContextPtr rmesa ) int wait = 0; while ( 1 ) { -#if defined(__alpha__) - /* necessary to preserve the Alpha paradigm */ - /* NOTE: this will not work on SPARSE machines */ - mem_barrier(); - frame = *(volatile CARD32 *)(void *)(R128MMIO + R128_LAST_FRAME_REG); -#else frame = INREG( R128_LAST_FRAME_REG ); -#endif - - if ( 0 ) - fprintf( stderr, " last=0x%08x frame=0x%08lx\n", - rmesa->sarea->last_frame, (long)frame ); - if ( rmesa->sarea->last_frame - frame <= R128_MAX_OUTSTANDING ) { break; } @@ -337,11 +243,16 @@ static int r128WaitForFrameCompletion( r128ContextPtr rmesa ) /* Copy the back color buffer to the front color buffer. */ -void r128SwapBuffers( r128ContextPtr rmesa ) +void r128CopyBuffer( const __DRIdrawablePrivate *dPriv ) { - GLint nbox; - GLint i; - GLint ret; + r128ContextPtr rmesa; + GLint nbox, i, ret; + + assert(dPriv); + assert(dPriv->driContextPriv); + assert(dPriv->driContextPriv->driverPrivate); + + rmesa = (r128ContextPtr) dPriv->driContextPriv->driverPrivate; if ( R128_DEBUG & DEBUG_VERBOSE_API ) { fprintf( stderr, "\n********************************\n" ); @@ -365,6 +276,8 @@ void r128SwapBuffers( r128ContextPtr rmesa ) rmesa->hardwareWentIdle = 0; } + nbox = dPriv->numClipRects; + for ( i = 0 ; i < nbox ; ) { GLint nr = MIN2( i + R128_NR_SAREA_CLIPRECTS , nbox ); XF86DRIClipRectPtr box = rmesa->pClipRects; @@ -377,17 +290,20 @@ void r128SwapBuffers( r128ContextPtr rmesa ) } rmesa->sarea->nbox = n; - ret = drmR128SwapBuffers( rmesa->driFd ); + ret = drmCommandNone( rmesa->driFd, DRM_R128_SWAP ); if ( ret ) { UNLOCK_HARDWARE( rmesa ); - fprintf( stderr, "drmR128SwapBuffers: return = %d\n", ret ); + fprintf( stderr, "DRM_R128_SWAP: return = %d\n", ret ); exit( 1 ); } } if ( R128_DEBUG & DEBUG_ALWAYS_SYNC ) { - drmR128WaitForIdleCCE( rmesa->driFd ); + i = 0; + do { + ret = drmCommandNone(rmesa->driFd, DRM_R128_CCE_IDLE); + } while ( ret && errno == EBUSY && i++ < R128_IDLE_RETRY ); } UNLOCK_HARDWARE( rmesa ); @@ -403,10 +319,17 @@ void r128SwapBuffers( r128ContextPtr rmesa ) #endif } -void r128PageFlip( r128ContextPtr rmesa ) +void r128PageFlip( const __DRIdrawablePrivate *dPriv ) { + r128ContextPtr rmesa; GLint ret; + assert(dPriv); + assert(dPriv->driContextPriv); + assert(dPriv->driContextPriv->driverPrivate); + + rmesa = (r128ContextPtr) dPriv->driContextPriv->driverPrivate; + if ( R128_DEBUG & DEBUG_VERBOSE_API ) { fprintf( stderr, "\n%s( %p ): page=%d\n\n", __FUNCTION__, rmesa->glCtx, rmesa->currentPage ); @@ -428,12 +351,12 @@ void r128PageFlip( r128ContextPtr rmesa ) /* The kernel will have been initialized to perform page flipping * on a swapbuffers ioctl. */ - ret = drmR128SwapBuffers( rmesa->driFd ); + ret = drmCommandNone( rmesa->driFd, DRM_R128_SWAP ); UNLOCK_HARDWARE( rmesa ); if ( ret ) { - fprintf( stderr, "drmR128SwapBuffers: return = %d\n", ret ); + fprintf( stderr, "DRM_R128_SWAP: return = %d\n", ret ); exit( 1 ); } @@ -468,14 +391,13 @@ void r128PageFlip( r128ContextPtr rmesa ) * Buffer clear */ -static GLbitfield r128DDClear( GLcontext *ctx, GLbitfield mask, GLboolean all, - GLint cx, GLint cy, GLint cw, GLint ch ) +static void r128DDClear( GLcontext *ctx, GLbitfield mask, GLboolean all, + GLint cx, GLint cy, GLint cw, GLint ch ) { r128ContextPtr rmesa = R128_CONTEXT(ctx); __DRIdrawablePrivate *dPriv = rmesa->driDrawable; + drmR128Clear clear; GLuint flags = 0; - GLuint color_mask = 0; - GLuint depth_mask = 0; GLint i; GLint ret; @@ -485,109 +407,121 @@ static GLbitfield r128DDClear( GLcontext *ctx, GLbitfield mask, GLboolean all, FLUSH_BATCH( rmesa ); - /* Update and emit any new state. We need to do this here to catch - * changes to the masks. - * FIXME: Just update the masks? + /* The only state change we care about here is the RGBA colormask + * We'll just update that state, if needed. If we do more then + * there's some strange side-effects that the conformance tests find. */ - if ( rmesa->new_state ) + if ( rmesa->new_state & R128_NEW_MASKS) { + const GLuint save_state = rmesa->new_state; + rmesa->new_state = R128_NEW_MASKS; r128DDUpdateHWState( ctx ); + rmesa->new_state = save_state & ~R128_NEW_MASKS; + } if ( mask & DD_FRONT_LEFT_BIT ) { - flags |= DRM_R128_FRONT; - color_mask = rmesa->setup.plane_3d_mask_c; + flags |= DRM_R128_FRONT_BUFFER; mask &= ~DD_FRONT_LEFT_BIT; } if ( mask & DD_BACK_LEFT_BIT ) { - flags |= DRM_R128_BACK; - color_mask = rmesa->setup.plane_3d_mask_c; + flags |= DRM_R128_BACK_BUFFER; mask &= ~DD_BACK_LEFT_BIT; } if ( ( mask & DD_DEPTH_BIT ) && ctx->Depth.Mask ) { - flags |= DRM_R128_DEPTH; - depth_mask |= rmesa->DepthMask; + flags |= DRM_R128_DEPTH_BUFFER; mask &= ~DD_DEPTH_BIT; } #if 0 /* FIXME: Add stencil support */ if ( mask & DD_STENCIL_BIT ) { - flags |= DRM_R128_DEPTH; - depth_mask |= rmesa->StencilMask; + flags |= DRM_R128_DEPTH_BUFFER; mask &= ~DD_STENCIL_BIT; } #endif - if ( !flags ) - return mask; + if ( flags ) { - /* Flip top to bottom */ - cx += dPriv->x; - cy = dPriv->y + dPriv->h - cy - ch; + /* Flip top to bottom */ + cx += dPriv->x; + cy = dPriv->y + dPriv->h - cy - ch; - LOCK_HARDWARE( rmesa ); + LOCK_HARDWARE( rmesa ); - for ( i = 0 ; i < rmesa->numClipRects ; ) { - GLint nr = MIN2( i + R128_NR_SAREA_CLIPRECTS , rmesa->numClipRects ); - XF86DRIClipRectPtr box = rmesa->pClipRects; - XF86DRIClipRectPtr b = rmesa->sarea->boxes; - GLint n = 0; + /* FIXME: Do we actually need this? + */ + if ( rmesa->dirty & ~R128_UPLOAD_CLIPRECTS ) { + r128EmitHwStateLocked( rmesa ); + } - if ( !all ) { - for ( ; i < nr ; i++ ) { - GLint x = box[i].x1; - GLint y = box[i].y1; - GLint w = box[i].x2 - x; - GLint h = box[i].y2 - y; - - if ( x < cx ) w -= cx - x, x = cx; - if ( y < cy ) h -= cy - y, y = cy; - if ( x + w > cx + cw ) w = cx + cw - x; - if ( y + h > cy + ch ) h = cy + ch - y; - if ( w <= 0 ) continue; - if ( h <= 0 ) continue; - - b->x1 = x; - b->y1 = y; - b->x2 = x + w; - b->y2 = y + h; - b++; - n++; - } - } else { - for ( ; i < nr ; i++ ) { - *b++ = *(XF86DRIClipRectRec *)&box[i]; - n++; + for ( i = 0 ; i < rmesa->numClipRects ; ) { + GLint nr = MIN2( i + R128_NR_SAREA_CLIPRECTS , rmesa->numClipRects ); + XF86DRIClipRectPtr box = rmesa->pClipRects; + XF86DRIClipRectPtr b = rmesa->sarea->boxes; + GLint n = 0; + + if ( !all ) { + for ( ; i < nr ; i++ ) { + GLint x = box[i].x1; + GLint y = box[i].y1; + GLint w = box[i].x2 - x; + GLint h = box[i].y2 - y; + + if ( x < cx ) w -= cx - x, x = cx; + if ( y < cy ) h -= cy - y, y = cy; + if ( x + w > cx + cw ) w = cx + cw - x; + if ( y + h > cy + ch ) h = cy + ch - y; + if ( w <= 0 ) continue; + if ( h <= 0 ) continue; + + b->x1 = x; + b->y1 = y; + b->x2 = x + w; + b->y2 = y + h; + b++; + n++; + } + } else { + for ( ; i < nr ; i++ ) { + *b++ = *(XF86DRIClipRectPtr)&box[i]; + n++; + } } - } - rmesa->sarea->nbox = n; + rmesa->sarea->nbox = n; - if ( R128_DEBUG & DEBUG_VERBOSE_IOCTL ) { - fprintf( stderr, - "drmR128Clear: flag 0x%x color %x depth %x nbox %d\n", - flags, - (GLuint)rmesa->ClearColor, - (GLuint)rmesa->ClearDepth, - rmesa->sarea->nbox ); - } + if ( R128_DEBUG & DEBUG_VERBOSE_IOCTL ) { + fprintf( stderr, + "DRM_R128_CLEAR: flag 0x%x color %x depth %x nbox %d\n", + flags, + (GLuint)rmesa->ClearColor, + (GLuint)rmesa->ClearDepth, + rmesa->sarea->nbox ); + } - ret = drmR128Clear( rmesa->driFd, flags, - rmesa->ClearColor, rmesa->ClearDepth, - color_mask, depth_mask ); + clear.flags = flags; + clear.clear_color = rmesa->ClearColor; + clear.clear_depth = rmesa->ClearDepth; + clear.color_mask = rmesa->setup.plane_3d_mask_c; + clear.depth_mask = ~0; - if ( ret ) { - UNLOCK_HARDWARE( rmesa ); - fprintf( stderr, "drmR128Clear: return = %d\n", ret ); - exit( 1 ); + ret = drmCommandWrite( rmesa->driFd, DRM_R128_CLEAR, + &clear, sizeof(drmR128Clear) ); + + if ( ret ) { + UNLOCK_HARDWARE( rmesa ); + fprintf( stderr, "DRM_R128_CLEAR: return = %d\n", ret ); + exit( 1 ); + } } - } - UNLOCK_HARDWARE( rmesa ); + UNLOCK_HARDWARE( rmesa ); - rmesa->dirty |= R128_UPLOAD_CLIPRECTS; + rmesa->dirty |= R128_UPLOAD_CLIPRECTS; + } - return mask; + if ( mask ) + _swrast_Clear( ctx, mask, all, cx, cy, cw, ch ); } @@ -601,6 +535,7 @@ void r128WriteDepthSpanLocked( r128ContextPtr rmesa, const GLubyte mask[] ) { XF86DRIClipRectPtr pbox = rmesa->pClipRects; + drmR128Depth d; int nbox = rmesa->numClipRects; int fd = rmesa->driScreen->fd; int i; @@ -620,7 +555,15 @@ void r128WriteDepthSpanLocked( r128ContextPtr rmesa, rmesa->sarea->nbox = nbox; } - drmR128WriteDepthSpan( fd, n, x, y, depth, mask ); + d.func = DRM_R128_WRITE_SPAN; + d.n = n; + d.x = (int*)&x; + d.y = (int*)&y; + d.buffer = (unsigned int *)depth; + d.mask = (unsigned char *)mask; + + drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth)); + } else { @@ -634,7 +577,15 @@ void r128WriteDepthSpanLocked( r128ContextPtr rmesa, } rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS; - drmR128WriteDepthSpan( fd, n, x, y, depth, mask ); + + d.func = DRM_R128_WRITE_SPAN; + d.n = n; + d.x = (int*)&x; + d.y = (int*)&y; + d.buffer = (unsigned int *)depth; + d.mask = (unsigned char *)mask; + + drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth)); } } @@ -647,6 +598,7 @@ void r128WriteDepthPixelsLocked( r128ContextPtr rmesa, GLuint n, const GLubyte mask[] ) { XF86DRIClipRectPtr pbox = rmesa->pClipRects; + drmR128Depth d; int nbox = rmesa->numClipRects; int fd = rmesa->driScreen->fd; int i; @@ -666,7 +618,14 @@ void r128WriteDepthPixelsLocked( r128ContextPtr rmesa, GLuint n, rmesa->sarea->nbox = nbox; } - drmR128WriteDepthPixels( fd, n, x, y, depth, mask ); + d.func = DRM_R128_WRITE_PIXELS; + d.n = n; + d.x = (int*)&x; + d.y = (int*)&y; + d.buffer = (unsigned int *)depth; + d.mask = (unsigned char *)mask; + + drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth)); } else { @@ -680,7 +639,15 @@ void r128WriteDepthPixelsLocked( r128ContextPtr rmesa, GLuint n, } rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS; - drmR128WriteDepthPixels( fd, n, x, y, depth, mask ); + + d.func = DRM_R128_WRITE_PIXELS; + d.n = n; + d.x = (int*)&x; + d.y = (int*)&y; + d.buffer = (unsigned int *)depth; + d.mask = (unsigned char *)mask; + + drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth)); } } @@ -691,6 +658,7 @@ void r128ReadDepthSpanLocked( r128ContextPtr rmesa, GLuint n, GLint x, GLint y ) { XF86DRIClipRectPtr pbox = rmesa->pClipRects; + drmR128Depth d; int nbox = rmesa->numClipRects; int fd = rmesa->driScreen->fd; int i; @@ -710,7 +678,14 @@ void r128ReadDepthSpanLocked( r128ContextPtr rmesa, rmesa->sarea->nbox = nbox; } - drmR128ReadDepthSpan( fd, n, x, y ); + d.func = DRM_R128_READ_SPAN; + d.n = n; + d.x = (int*)&x; + d.y = (int*)&y; + d.buffer = NULL; + d.mask = NULL; + + drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth)); } else { @@ -724,7 +699,15 @@ void r128ReadDepthSpanLocked( r128ContextPtr rmesa, } rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS; - drmR128ReadDepthSpan( fd, n, x, y ); + + d.func = DRM_R128_READ_SPAN; + d.n = n; + d.x = (int*)&x; + d.y = (int*)&y; + d.buffer = NULL; + d.mask = NULL; + + drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth)); } } @@ -735,6 +718,7 @@ void r128ReadDepthPixelsLocked( r128ContextPtr rmesa, GLuint n, const GLint x[], const GLint y[] ) { XF86DRIClipRectPtr pbox = rmesa->pClipRects; + drmR128Depth d; int nbox = rmesa->numClipRects; int fd = rmesa->driScreen->fd; int i; @@ -754,7 +738,14 @@ void r128ReadDepthPixelsLocked( r128ContextPtr rmesa, GLuint n, rmesa->sarea->nbox = nbox; } - drmR128ReadDepthPixels( fd, n, x, y ); + d.func = DRM_R128_READ_PIXELS; + d.n = n; + d.x = (int*)&x; + d.y = (int*)&y; + d.buffer = NULL; + d.mask = NULL; + + drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth)); } else { @@ -768,7 +759,15 @@ void r128ReadDepthPixelsLocked( r128ContextPtr rmesa, GLuint n, } rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS; - drmR128ReadDepthPixels( fd, n, x, y ); + + d.func = DRM_R128_READ_PIXELS; + d.n = n; + d.x = (int*)&x; + d.y = (int*)&y; + d.buffer = NULL; + d.mask = NULL; + + drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth)); } } @@ -780,14 +779,17 @@ void r128WaitForIdleLocked( r128ContextPtr rmesa ) { int fd = rmesa->r128Screen->driScreen->fd; int to = 0; - int ret; + int ret, i; do { - ret = drmR128WaitForIdleCCE( fd ); + i = 0; + do { + ret = drmCommandNone( fd, DRM_R128_CCE_IDLE); + } while ( ret && errno == EBUSY && i++ < R128_IDLE_RETRY ); } while ( ( ret == -EBUSY ) && ( to++ < R128_TIMEOUT ) ); if ( ret < 0 ) { - drmR128EngineReset( fd ); + drmCommandNone( fd, DRM_R128_CCE_RESET); UNLOCK_HARDWARE( rmesa ); fprintf( stderr, "Error: Rage 128 timed out... exiting\n" ); exit( -1 ); diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_state.c b/xc/lib/GL/mesa/src/drv/r128/r128_state.c index 8244696aa..ef5579b36 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_state.c +++ b/xc/lib/GL/mesa/src/drv/r128/r128_state.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_state.c,v 1.8 2001/03/21 16:14:23 dawes Exp $ */ +/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_state.c,v 1.7 2001/01/08 01:07:21 martin Exp $ */ /************************************************************************** Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., @@ -43,9 +43,15 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "context.h" #include "mmath.h" -#include "pb.h" #include "enums.h" +#include "swrast/swrast.h" +#include "array_cache/acache.h" +#include "tnl/tnl.h" +#include "swrast_setup/swrast_setup.h" + +#include "tnl/t_pipeline.h" + /* ============================================================= * Alpha blending @@ -95,6 +101,8 @@ static void r128UpdateAlphaMode( GLcontext *ctx ) t &= ~R128_ALPHA_TEST_ENABLE; } + FALLBACK( rmesa, R128_FALLBACK_BLEND_FUNC, GL_FALSE ); + if ( ctx->Color.BlendEnabled ) { a &= ~(R128_ALPHA_BLEND_SRC_MASK | R128_ALPHA_BLEND_DST_MASK); @@ -126,6 +134,8 @@ static void r128UpdateAlphaMode( GLcontext *ctx ) case GL_SRC_ALPHA_SATURATE: a |= R128_ALPHA_BLEND_SRC_SRCALPHASAT; break; + default: + FALLBACK( rmesa, R128_FALLBACK_BLEND_FUNC, GL_TRUE ); } switch ( ctx->Color.BlendDstRGB ) { @@ -153,6 +163,8 @@ static void r128UpdateAlphaMode( GLcontext *ctx ) case GL_ONE_MINUS_DST_ALPHA: a |= R128_ALPHA_BLEND_DST_INVDESTALPHA; break; + default: + FALLBACK( rmesa, R128_FALLBACK_BLEND_FUNC, GL_TRUE ); } t |= R128_ALPHA_ENABLE; @@ -170,7 +182,7 @@ static void r128UpdateAlphaMode( GLcontext *ctx ) } } -static void r128DDAlphaFunc( GLcontext *ctx, GLenum func, GLclampf ref ) +static void r128DDAlphaFunc( GLcontext *ctx, GLenum func, GLchan ref ) { r128ContextPtr rmesa = R128_CONTEXT(ctx); @@ -183,13 +195,19 @@ static void r128DDBlendEquation( GLcontext *ctx, GLenum mode ) r128ContextPtr rmesa = R128_CONTEXT(ctx); FLUSH_BATCH( rmesa ); - rmesa->new_state |= R128_NEW_ALPHA; - if ( ctx->Color.ColorLogicOpEnabled && ctx->Color.LogicOp != GL_COPY ) { - rmesa->Fallback |= R128_FALLBACK_LOGICOP; - } else { - rmesa->Fallback &= ~R128_FALLBACK_LOGICOP; - } + /* BlendEquation sets ColorLogicOpEnabled in an unexpected + * manner. + */ + FALLBACK( R128_CONTEXT(ctx), R128_FALLBACK_LOGICOP, + (ctx->Color.ColorLogicOpEnabled && + ctx->Color.LogicOp != GL_COPY)); + + /* Can only do blend addition, not min, max, subtract, etc. */ + FALLBACK( R128_CONTEXT(ctx), R128_FALLBACK_BLEND_EQ, + mode != GL_FUNC_ADD_EXT); + + rmesa->new_state |= R128_NEW_ALPHA; } static void r128DDBlendFunc( GLcontext *ctx, GLenum sfactor, GLenum dfactor ) @@ -317,13 +335,16 @@ static void r128UpdateFogAttrib( GLcontext *ctx ) GLubyte c[4]; GLuint col; - if ( ctx->FogMode == FOG_FRAGMENT ) { + if ( ctx->Fog.Enabled ) { t |= R128_FOG_ENABLE; } else { t &= ~R128_FOG_ENABLE; } - FLOAT_RGB_TO_UBYTE_RGB( c, ctx->Fog.Color ); + c[0] = FLOAT_TO_UBYTE( ctx->Fog.Color[0] ); + c[1] = FLOAT_TO_UBYTE( ctx->Fog.Color[1] ); + c[2] = FLOAT_TO_UBYTE( ctx->Fog.Color[2] ); + col = r128PackColor( 4, c[0], c[1], c[2], 0 ); if ( rmesa->setup.fog_color_c != col ) { @@ -419,7 +440,7 @@ static void r128UpdateCull( GLcontext *ctx ) f |= R128_BACKFACE_SOLID | R128_FRONTFACE_SOLID; - if ( ctx->Polygon.CullFlag && ctx->PB->primitive == GL_POLYGON ) { + if ( ctx->Polygon.CullFlag ) { switch ( ctx->Polygon.CullFaceMode ) { case GL_FRONT: f &= ~R128_FRONTFACE_SOLID; @@ -434,7 +455,7 @@ static void r128UpdateCull( GLcontext *ctx ) } } - if ( rmesa->setup.pm4_vc_fpu_setup != f ) { + if ( 1 || rmesa->setup.pm4_vc_fpu_setup != f ) { rmesa->setup.pm4_vc_fpu_setup = f; rmesa->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_SETUP; } @@ -477,17 +498,14 @@ static void r128UpdateMasks( GLcontext *ctx ) } } -static GLboolean r128DDColorMask( GLcontext *ctx, - GLboolean r, GLboolean g, - GLboolean b, GLboolean a ) +static void r128DDColorMask( GLcontext *ctx, + GLboolean r, GLboolean g, + GLboolean b, GLboolean a ) { r128ContextPtr rmesa = R128_CONTEXT(ctx); FLUSH_BATCH( rmesa ); rmesa->new_state |= R128_NEW_MASKS; - - return GL_FALSE; /* This forces the software paths to do colormasking. */ - /* This function will return void when we use Mesa 3.5 */ } @@ -499,26 +517,58 @@ static GLboolean r128DDColorMask( GLcontext *ctx, * sense to break them out of the core texture state update routines. */ +static void updateSpecularLighting( GLcontext *ctx ) +{ + r128ContextPtr rmesa = R128_CONTEXT(ctx); + GLuint t = rmesa->setup.tex_cntl_c; + + if ( ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR && + ctx->Light.Enabled) { + /* XXX separate specular color just doesn't seem to work as it should. + * For now, we fall back to s/w rendering whenever separate specular + * is enabled. + */ +#if 0 + if (ctx->Light.ShadeModel == GL_FLAT) { + /* R128 can't do flat-shaded separate specular */ + t &= ~R128_SPEC_LIGHT_ENABLE; + FALLBACK( rmesa, R128_FALLBACK_SEP_SPECULAR, GL_TRUE ); + /*printf("%s fallback sep spec\n", __FUNCTION__);*/ + } + else { + t |= R128_SPEC_LIGHT_ENABLE; + FALLBACK( rmesa, R128_FALLBACK_SEP_SPECULAR, GL_FALSE ); + /*printf("%s enable sep spec\n", __FUNCTION__);*/ + } +#else + t &= ~R128_SPEC_LIGHT_ENABLE; + FALLBACK( rmesa, R128_FALLBACK_SEP_SPECULAR, GL_TRUE ); + /*printf("%s fallback sep spec\n", __FUNCTION__);*/ +#endif + } + else { + t &= ~R128_SPEC_LIGHT_ENABLE; + FALLBACK( rmesa, R128_FALLBACK_SEP_SPECULAR, GL_FALSE ); + /*printf("%s disable sep spec\n", __FUNCTION__);*/ + } + + if ( rmesa->setup.tex_cntl_c != t ) { + rmesa->setup.tex_cntl_c = t; + rmesa->dirty |= R128_UPLOAD_CONTEXT; + rmesa->dirty |= R128_UPLOAD_SETUP; + rmesa->new_state |= R128_NEW_CONTEXT; + } +} + + static void r128DDLightModelfv( GLcontext *ctx, GLenum pname, const GLfloat *param ) { r128ContextPtr rmesa = R128_CONTEXT(ctx); if ( pname == GL_LIGHT_MODEL_COLOR_CONTROL ) { - GLuint t = rmesa->setup.tex_cntl_c; - FLUSH_BATCH( rmesa ); - - if ( ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR ) { - t |= R128_SPEC_LIGHT_ENABLE; - } else { - t &= ~R128_SPEC_LIGHT_ENABLE; - } - - if ( rmesa->setup.tex_cntl_c != t ) { - rmesa->setup.tex_cntl_c = t; - rmesa->dirty |= R128_UPLOAD_CONTEXT; - } + updateSpecularLighting(ctx); } } @@ -540,6 +590,8 @@ static void r128DDShadeModel( GLcontext *ctx, GLenum mode ) return; } + updateSpecularLighting(ctx); + if ( rmesa->setup.pm4_vc_fpu_setup != s ) { FLUSH_BATCH( rmesa ); rmesa->setup.pm4_vc_fpu_setup = s; @@ -566,27 +618,53 @@ void r128UpdateWindow( GLcontext *ctx ) rmesa->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_WINDOW; } - /* ============================================================= - * Miscellaneous + * Viewport */ -static void r128DDClearColor( GLcontext *ctx, - GLubyte r, GLubyte g, GLubyte b, GLubyte a ) + +static void r128CalcViewport( GLcontext *ctx ) { r128ContextPtr rmesa = R128_CONTEXT(ctx); + const GLfloat *v = ctx->Viewport._WindowMap.m; + GLfloat *m = rmesa->hw_viewport; - rmesa->ClearColor = r128PackColor( rmesa->r128Screen->cpp, - r, g, b, a ); + /* See also r128_translate_vertex. + */ + m[MAT_SX] = v[MAT_SX]; + m[MAT_TX] = v[MAT_TX] + SUBPIXEL_X; + m[MAT_SY] = - v[MAT_SY]; + m[MAT_TY] = - v[MAT_TY] + rmesa->driDrawable->h + SUBPIXEL_Y; + m[MAT_SZ] = v[MAT_SZ] * rmesa->depth_scale; + m[MAT_TZ] = v[MAT_TZ] * rmesa->depth_scale; } -static void r128DDColor( GLcontext *ctx, - GLubyte r, GLubyte g, GLubyte b, GLubyte a ) +static void r128Viewport( GLcontext *ctx, + GLint x, GLint y, + GLsizei width, GLsizei height ) +{ + r128CalcViewport( ctx ); +} + +static void r128DepthRange( GLcontext *ctx, + GLclampd nearval, GLclampd farval ) +{ + r128CalcViewport( ctx ); +} + + +/* ============================================================= + * Miscellaneous + */ + +static void r128DDClearColor( GLcontext *ctx, + const GLchan color[4] ) { r128ContextPtr rmesa = R128_CONTEXT(ctx); - rmesa->Color = r128PackColor( rmesa->r128Screen->cpp, - r, g, b, a ); + rmesa->ClearColor = r128PackColor( rmesa->r128Screen->cpp, + color[0], color[1], + color[2], color[3] ); } static void r128DDLogicOpCode( GLcontext *ctx, GLenum opcode ) @@ -596,39 +674,32 @@ static void r128DDLogicOpCode( GLcontext *ctx, GLenum opcode ) if ( ctx->Color.ColorLogicOpEnabled ) { FLUSH_BATCH( rmesa ); - if ( opcode == GL_COPY ) { - rmesa->Fallback &= ~R128_FALLBACK_LOGICOP; - } else { - rmesa->Fallback |= R128_FALLBACK_LOGICOP; - } - } else { - rmesa->Fallback &= ~R128_FALLBACK_LOGICOP; + FALLBACK( rmesa, R128_FALLBACK_LOGICOP, opcode != GL_COPY ); } } -static GLboolean r128DDSetDrawBuffer( GLcontext *ctx, GLenum mode ) +static void r128DDSetDrawBuffer( GLcontext *ctx, GLenum mode ) { r128ContextPtr rmesa = R128_CONTEXT(ctx); - int found = GL_TRUE; FLUSH_BATCH( rmesa ); if ( rmesa->DrawBuffer != mode ) { rmesa->DrawBuffer = mode; - rmesa->Fallback &= ~R128_FALLBACK_DRAW_BUFFER; switch ( mode ) { case GL_FRONT_LEFT: - rmesa->drawOffset = rmesa->r128Screen->frontOffset; - rmesa->drawPitch = rmesa->r128Screen->frontPitch; + rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->frontOffset; + rmesa->drawPitch = rmesa->readPitch = rmesa->r128Screen->frontPitch; + FALLBACK( rmesa, R128_FALLBACK_DRAW_BUFFER, GL_FALSE ); break; case GL_BACK_LEFT: - rmesa->drawOffset = rmesa->r128Screen->backOffset; - rmesa->drawPitch = rmesa->r128Screen->backPitch; + rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->backOffset; + rmesa->drawPitch = rmesa->readPitch = rmesa->r128Screen->backPitch; + FALLBACK( rmesa, R128_FALLBACK_DRAW_BUFFER, GL_FALSE ); break; default: - rmesa->Fallback |= R128_FALLBACK_DRAW_BUFFER; - found = GL_FALSE; + FALLBACK( rmesa, R128_FALLBACK_DRAW_BUFFER, GL_TRUE ); break; } @@ -636,31 +707,6 @@ static GLboolean r128DDSetDrawBuffer( GLcontext *ctx, GLenum mode ) (rmesa->drawOffset >> 5)); rmesa->new_state |= R128_NEW_WINDOW; } - - return found; -} - -static void r128DDSetReadBuffer( GLcontext *ctx, - GLframebuffer *colorBuffer, - GLenum mode ) -{ - r128ContextPtr rmesa = R128_CONTEXT(ctx); - - rmesa->Fallback &= ~R128_FALLBACK_READ_BUFFER; - - switch ( mode ) { - case GL_FRONT_LEFT: - rmesa->readOffset = rmesa->r128Screen->frontOffset; - rmesa->readPitch = rmesa->r128Screen->frontPitch; - break; - case GL_BACK_LEFT: - rmesa->readOffset = rmesa->r128Screen->backOffset; - rmesa->readPitch = rmesa->r128Screen->backPitch; - break; - default: - rmesa->Fallback |= R128_FALLBACK_READ_BUFFER; - break; - } } @@ -671,21 +717,22 @@ static void r128DDSetReadBuffer( GLcontext *ctx, static void r128DDPolygonStipple( GLcontext *ctx, const GLubyte *mask ) { r128ContextPtr rmesa = R128_CONTEXT(ctx); - GLuint *stipple = (GLuint *)mask; - - FLUSH_BATCH( rmesa ); - - rmesa->setup.dp_gui_master_cntl_c &= ~R128_GMC_BRUSH_NONE; - - if ( ctx->Polygon.StippleFlag && ctx->PB->primitive == GL_POLYGON ) { - rmesa->setup.dp_gui_master_cntl_c |= R128_GMC_BRUSH_32x32_MONO_FG_LA; - } else { - rmesa->setup.dp_gui_master_cntl_c |= R128_GMC_BRUSH_SOLID_COLOR; + GLuint stipple[32], i; + drmR128Stipple stippleRec; + + for (i = 0; i < 32; i++) { + stipple[31 - i] = ((mask[i*4+0] << 24) | + (mask[i*4+1] << 16) | + (mask[i*4+2] << 8) | + (mask[i*4+3])); } + FLUSH_BATCH( rmesa ); LOCK_HARDWARE( rmesa ); - drmR128PolygonStipple( rmesa->driFd, stipple ); + stippleRec.mask = stipple; + drmCommandWrite( rmesa->driFd, DRM_R128_STIPPLE, + &stippleRec, sizeof(drmR128Stipple) ); UNLOCK_HARDWARE( rmesa ); @@ -695,6 +742,18 @@ static void r128DDPolygonStipple( GLcontext *ctx, const GLubyte *mask ) /* ============================================================= + * Render mode + */ + +static void r128DDRenderMode( GLcontext *ctx, GLenum mode ) +{ + r128ContextPtr rmesa = R128_CONTEXT(ctx); + FALLBACK( rmesa, R128_FALLBACK_RENDER_MODE, (mode != GL_RENDER) ); +} + + + +/* ============================================================= * State enable/disable */ @@ -704,7 +763,7 @@ static void r128DDEnable( GLcontext *ctx, GLenum cap, GLboolean state ) if ( R128_DEBUG & DEBUG_VERBOSE_API ) { fprintf( stderr, "%s( %s = %s )\n", - __FUNCTION__, gl_lookup_enum_by_nr( cap ), + __FUNCTION__, _mesa_lookup_enum_by_nr( cap ), state ? "GL_TRUE" : "GL_FALSE" ); } @@ -718,11 +777,11 @@ static void r128DDEnable( GLcontext *ctx, GLenum cap, GLboolean state ) FLUSH_BATCH( rmesa ); rmesa->new_state |= R128_NEW_ALPHA; - if ( ctx->Color.ColorLogicOpEnabled && ctx->Color.LogicOp != GL_COPY ) { - rmesa->Fallback |= R128_FALLBACK_LOGICOP; - } else { - rmesa->Fallback &= ~R128_FALLBACK_LOGICOP; - } + /* For some reason enable(GL_BLEND) affects ColorLogicOpEnabled. + */ + FALLBACK( rmesa, R128_FALLBACK_LOGICOP, + (ctx->Color.ColorLogicOpEnabled && + ctx->Color.LogicOp != GL_COPY)); break; case GL_CULL_FACE: @@ -760,11 +819,12 @@ static void r128DDEnable( GLcontext *ctx, GLenum cap, GLboolean state ) case GL_COLOR_LOGIC_OP: FLUSH_BATCH( rmesa ); - if ( state && ctx->Color.LogicOp != GL_COPY ) { - rmesa->Fallback |= R128_FALLBACK_LOGICOP; - } else { - rmesa->Fallback &= ~R128_FALLBACK_LOGICOP; - } + FALLBACK( rmesa, R128_FALLBACK_LOGICOP, + state && ctx->Color.LogicOp != GL_COPY ); + break; + + case GL_LIGHTING: + updateSpecularLighting(ctx); break; case GL_SCISSOR_TEST: @@ -773,6 +833,11 @@ static void r128DDEnable( GLcontext *ctx, GLenum cap, GLboolean state ) rmesa->new_state |= R128_NEW_CLIP; break; + case GL_STENCIL_TEST: + FLUSH_BATCH( rmesa ); + FALLBACK( rmesa, R128_FALLBACK_STENCIL, state ); + break; + case GL_TEXTURE_1D: case GL_TEXTURE_2D: case GL_TEXTURE_3D: @@ -781,9 +846,7 @@ static void r128DDEnable( GLcontext *ctx, GLenum cap, GLboolean state ) break; case GL_POLYGON_STIPPLE: - if ( (ctx->Driver.TriangleCaps & DD_TRI_STIPPLE) && - ctx->PB->primitive == GL_POLYGON ) - { + if ( rmesa->render_primitive == GL_TRIANGLES ) { FLUSH_BATCH( rmesa ); rmesa->setup.dp_gui_master_cntl_c &= ~R128_GMC_BRUSH_NONE; if ( state ) { @@ -842,8 +905,8 @@ void r128EmitHwStateLocked( r128ContextPtr rmesa ) { R128SAREAPrivPtr sarea = rmesa->sarea; r128_context_regs_t *regs = &(rmesa->setup); - r128TexObjPtr t0 = rmesa->CurrentTexObj[0]; - r128TexObjPtr t1 = rmesa->CurrentTexObj[1]; + const r128TexObjPtr t0 = rmesa->CurrentTexObj[0]; + const r128TexObjPtr t1 = rmesa->CurrentTexObj[1]; if ( R128_DEBUG & DEBUG_VERBOSE_MSG ) { r128DDPrintDirty( "r128EmitHwStateLocked", rmesa->dirty ); @@ -889,8 +952,8 @@ void r128EmitHwStateLocked( r128ContextPtr rmesa ) tex->tex_border_color = t1->setup.tex_border_color; } - sarea->vertsize = rmesa->vertsize; - sarea->vc_format = rmesa->vc_format; + sarea->vertsize = rmesa->vertex_size; + sarea->vc_format = rmesa->vertex_format; /* Turn off the texture cache flushing */ rmesa->setup.tex_cntl_c &= ~R128_TEX_CACHE_FLUSH; @@ -958,82 +1021,18 @@ void r128DDUpdateHWState( GLcontext *ctx ) } } -/* This is called when Mesa switches between rendering triangle - * primitives (such as GL_POLYGON, GL_QUADS, GL_TRIANGLE_STRIP, etc), - * and lines, points and bitmaps. - * - * As the r128 uses triangles to render lines and points, it is - * necessary to turn off hardware culling when rendering these - * primitives. - */ -static void r128DDReducedPrimitiveChange( GLcontext *ctx, GLenum prim ) -{ - r128ContextPtr rmesa = R128_CONTEXT(ctx); - GLuint f = rmesa->setup.pm4_vc_fpu_setup; - - f |= R128_BACKFACE_SOLID | R128_FRONTFACE_SOLID; - - if ( ctx->Polygon.CullFlag && ctx->PB->primitive == GL_POLYGON ) { - switch ( ctx->Polygon.CullFaceMode ) { - case GL_FRONT: - f &= ~R128_FRONTFACE_SOLID; - break; - case GL_BACK: - f &= ~R128_BACKFACE_SOLID; - break; - case GL_FRONT_AND_BACK: - f &= ~(R128_BACKFACE_SOLID | - R128_FRONTFACE_SOLID); - break; - } - } - - if ( rmesa->setup.pm4_vc_fpu_setup != f ) { - FLUSH_BATCH( rmesa ); - rmesa->setup.pm4_vc_fpu_setup = f; - - /* NOTE: Only upload the setup state, everything else has been - * uploaded by the usual means already. - */ - rmesa->dirty |= R128_UPLOAD_SETUP; - } -} - -#define INTERESTED (~(NEW_MODELVIEW | \ - NEW_PROJECTION | \ - NEW_TEXTURE_MATRIX | \ - NEW_USER_CLIP | \ - NEW_CLIENT_STATE)) - -void r128DDUpdateState( GLcontext *ctx ) +static void r128DDInvalidateState( GLcontext *ctx, GLuint new_state ) { - r128ContextPtr rmesa = R128_CONTEXT(ctx); - - if ( ctx->NewState & INTERESTED ) { - r128DDChooseRenderState( ctx ); - r128DDChooseRasterSetupFunc( ctx ); - } - - /* Need to do this here to detect texture fallbacks before - * setting triangle functions. - */ - if ( rmesa->new_state & R128_NEW_TEXTURE ) { - r128DDUpdateHWState( ctx ); - } - - if ( !rmesa->Fallback ) { - ctx->IndirectTriangles &= ~DD_SW_RASTERIZE; - ctx->IndirectTriangles |= rmesa->IndirectTriangles; - - ctx->Driver.PointsFunc = rmesa->PointsFunc; - ctx->Driver.LineFunc = rmesa->LineFunc; - ctx->Driver.TriangleFunc = rmesa->TriangleFunc; - ctx->Driver.QuadFunc = rmesa->QuadFunc; - } + _swrast_InvalidateState( ctx, new_state ); + _swsetup_InvalidateState( ctx, new_state ); + _ac_InvalidateState( ctx, new_state ); + _tnl_InvalidateState( ctx, new_state ); + R128_CONTEXT(ctx)->NewGLState |= new_state; } + /* Initialize the context's hardware state. */ void r128DDInitState( r128ContextPtr rmesa ) @@ -1054,35 +1053,26 @@ void r128DDInitState( r128ContextPtr rmesa ) rmesa->ClearColor = 0x00000000; - switch ( rmesa->glCtx->Visual->DepthBits ) { + switch ( rmesa->glCtx->Visual.depthBits ) { case 16: rmesa->ClearDepth = 0x0000ffff; - rmesa->DepthMask = 0xffffffff; depth_bpp = R128_Z_PIX_WIDTH_16; rmesa->depth_scale = 1.0 / (GLfloat)0xffff; break; case 24: rmesa->ClearDepth = 0x00ffffff; - rmesa->DepthMask = 0x00ffffff; depth_bpp = R128_Z_PIX_WIDTH_24; rmesa->depth_scale = 1.0 / (GLfloat)0xffffff; break; default: fprintf( stderr, "Error: Unsupported depth %d... exiting\n", - rmesa->glCtx->Visual->DepthBits ); + rmesa->glCtx->Visual.depthBits ); exit( -1 ); } - rmesa->RenderIndex = R128_FALLBACK_BIT; - rmesa->PointsFunc = NULL; - rmesa->LineFunc = NULL; - rmesa->TriangleFunc = NULL; - rmesa->QuadFunc = NULL; - - rmesa->IndirectTriangles = 0; rmesa->Fallback = 0; - if ( rmesa->glCtx->Visual->DBflag ) { + if ( rmesa->glCtx->Visual.doubleBufferMode ) { rmesa->DrawBuffer = GL_BACK_LEFT; rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->backOffset; rmesa->drawPitch = rmesa->readPitch = rmesa->r128Screen->backPitch; @@ -1198,33 +1188,14 @@ void r128DDInitState( r128ContextPtr rmesa ) */ void r128DDInitStateFuncs( GLcontext *ctx ) { - ctx->Driver.UpdateState = r128DDUpdateState; + ctx->Driver.UpdateState = r128DDInvalidateState; ctx->Driver.ClearIndex = NULL; ctx->Driver.ClearColor = r128DDClearColor; - ctx->Driver.Index = NULL; - ctx->Driver.Color = r128DDColor; ctx->Driver.SetDrawBuffer = r128DDSetDrawBuffer; - ctx->Driver.SetReadBuffer = r128DDSetReadBuffer; ctx->Driver.IndexMask = NULL; ctx->Driver.ColorMask = r128DDColorMask; - ctx->Driver.LogicOp = NULL; - ctx->Driver.Dither = NULL; - - ctx->Driver.NearFar = NULL; - - ctx->Driver.RenderStart = r128DDUpdateHWState; - ctx->Driver.RenderFinish = NULL; - ctx->Driver.RasterSetup = NULL; - - ctx->Driver.RenderVBClippedTab = NULL; - ctx->Driver.RenderVBCulledTab = NULL; - ctx->Driver.RenderVBRawTab = NULL; - - ctx->Driver.ReducedPrimitiveChange = r128DDReducedPrimitiveChange; - ctx->Driver.MultipassFunc = NULL; - ctx->Driver.AlphaFunc = r128DDAlphaFunc; ctx->Driver.BlendEquation = r128DDBlendEquation; ctx->Driver.BlendFunc = r128DDBlendFunc; @@ -1234,7 +1205,6 @@ void r128DDInitStateFuncs( GLcontext *ctx ) ctx->Driver.FrontFace = r128DDFrontFace; ctx->Driver.DepthFunc = r128DDDepthFunc; ctx->Driver.DepthMask = r128DDDepthMask; - ctx->Driver.DepthRange = NULL; ctx->Driver.Enable = r128DDEnable; ctx->Driver.Fogfv = r128DDFogfv; ctx->Driver.Hint = NULL; @@ -1243,11 +1213,29 @@ void r128DDInitStateFuncs( GLcontext *ctx ) ctx->Driver.LogicOpcode = r128DDLogicOpCode; ctx->Driver.PolygonMode = NULL; ctx->Driver.PolygonStipple = r128DDPolygonStipple; + ctx->Driver.RenderMode = r128DDRenderMode; ctx->Driver.Scissor = r128DDScissor; ctx->Driver.ShadeModel = r128DDShadeModel; ctx->Driver.ClearStencil = NULL; ctx->Driver.StencilFunc = NULL; ctx->Driver.StencilMask = NULL; ctx->Driver.StencilOp = NULL; - ctx->Driver.Viewport = NULL; + + ctx->Driver.DepthRange = r128DepthRange; + ctx->Driver.Viewport = r128Viewport; + + /* Pixel path fallbacks. + */ + ctx->Driver.Accum = _swrast_Accum; + ctx->Driver.Bitmap = _swrast_Bitmap; + ctx->Driver.CopyPixels = _swrast_CopyPixels; + ctx->Driver.DrawPixels = _swrast_DrawPixels; + ctx->Driver.ReadPixels = _swrast_ReadPixels; + + /* Swrast hooks for imaging extensions: + */ + ctx->Driver.CopyColorTable = _swrast_CopyColorTable; + ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable; + ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D; + ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D; } diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_tris.c b/xc/lib/GL/mesa/src/drv/r128/r128_tris.c index 261142d75..619e061fc 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_tris.c +++ b/xc/lib/GL/mesa/src/drv/r128/r128_tris.c @@ -1,8 +1,9 @@ -/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_tris.c,v 1.6 2001/04/10 17:53:07 dawes Exp $ */ /* -*- c-basic-offset: 3 -*- */ +/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_tris.c,v 1.4 2001/01/08 01:07:24 martin Exp $ */ /* -*- c-basic-offset: 3 -*- */ /************************************************************************** -Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., - Cedar Park, Texas. +Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and + VA Linux Systems Inc., Fremont, California. + All Rights Reserved. Permission is hereby granted, free of charge, to any person obtaining a @@ -19,7 +20,7 @@ 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 -ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -28,194 +29,693 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. /* * Authors: - * Gareth Hughes <gareth@valinux.com> - * Kevin E. Martin <martin@valinux.com> - * Michel Dänzer <michdaen@iiic.ethz.ch> + * Keith Whitwell <keithw@valinux.com> * */ -#include "r128_context.h" -#include "r128_ioctl.h" -#include "r128_vb.h" -#include "r128_tris.h" -#include "r128_state.h" +#include <stdio.h> +#include <math.h> -#include "pipeline.h" -#include "vbindirect.h" +#include "glheader.h" +#include "mtypes.h" +#include "colormac.h" +#include "macros.h" -static struct { - points_func points; - line_func line; - triangle_func triangle; - quad_func quad; -} rast_tab[R128_MAX_TRIFUNC]; +#include "swrast/swrast.h" +#include "swrast_setup/swrast_setup.h" +#include "tnl/tnl.h" +#include "tnl/t_context.h" +#include "tnl/t_pipeline.h" -#if X_BYTE_ORDER == X_LITTLE_ENDIAN -#define R128_COLOR( to, from ) \ +#include "r128_tris.h" +#include "r128_state.h" +#include "r128_tex.h" +#include "r128_vb.h" +#include "r128_ioctl.h" + +static const GLuint hw_prim[GL_POLYGON+1] = { + R128_CCE_VC_CNTL_PRIM_TYPE_POINT, + R128_CCE_VC_CNTL_PRIM_TYPE_LINE, + R128_CCE_VC_CNTL_PRIM_TYPE_LINE, + R128_CCE_VC_CNTL_PRIM_TYPE_LINE, + R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST, + R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST, + R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST, + R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST, + R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST, + R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST, +}; + +static void r128RasterPrimitive( GLcontext *ctx, GLuint hwprim ); +static void r128RenderPrimitive( GLcontext *ctx, GLenum prim ); + + +/*********************************************************************** + * Emit primitives as inline vertices * + ***********************************************************************/ + +#if defined(USE_X86_ASM) +#define COPY_DWORDS( j, vb, vertsize, v ) \ do { \ - (to)[0] = (from)[2]; \ - (to)[1] = (from)[1]; \ - (to)[2] = (from)[0]; \ - (to)[3] = (from)[3]; \ + int __tmp; \ + __asm__ __volatile__( "rep ; movsl" \ + : "=%c" (j), "=D" (vb), "=S" (__tmp) \ + : "0" (vertsize), \ + "D" ((long)vb), \ + "S" ((long)v) ); \ } while (0) #else -#define R128_COLOR( to, from ) \ +#define COPY_DWORDS( j, vb, vertsize, v ) \ do { \ - (to)[0] = (from)[3]; \ - (to)[1] = (from)[0]; \ - (to)[2] = (from)[1]; \ - (to)[3] = (from)[2]; \ + for ( j = 0 ; j < vertsize ; j++ ) \ + vb[j] = CPU_TO_LE32(((GLuint *)v)[j]); \ + vb += vertsize; \ } while (0) #endif - -static void r128_null_quad( GLcontext *ctx, GLuint v0, - GLuint v1, GLuint v2, GLuint v3, GLuint pv ) -{ -} -static void r128_null_triangle( GLcontext *ctx, GLuint v0, - GLuint v1, GLuint v2, GLuint pv ) +static __inline void r128_draw_quad( r128ContextPtr rmesa, + r128VertexPtr v0, + r128VertexPtr v1, + r128VertexPtr v2, + r128VertexPtr v3 ) { + GLuint vertsize = rmesa->vertex_size; + GLuint *vb = (GLuint *)r128AllocDmaLow( rmesa, 6 * vertsize * 4 ); + GLuint j; + + rmesa->num_verts += 6; + COPY_DWORDS( j, vb, vertsize, v0 ); + COPY_DWORDS( j, vb, vertsize, v1 ); + COPY_DWORDS( j, vb, vertsize, v3 ); + COPY_DWORDS( j, vb, vertsize, v1 ); + COPY_DWORDS( j, vb, vertsize, v2 ); + COPY_DWORDS( j, vb, vertsize, v3 ); } -static void r128_null_line( GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv ) + + +static __inline void r128_draw_triangle( r128ContextPtr rmesa, + r128VertexPtr v0, + r128VertexPtr v1, + r128VertexPtr v2 ) { + GLuint vertsize = rmesa->vertex_size; + GLuint *vb = (GLuint *)r128AllocDmaLow( rmesa, 3 * vertsize * 4 ); + GLuint j; + + rmesa->num_verts += 3; + COPY_DWORDS( j, vb, vertsize, v0 ); + COPY_DWORDS( j, vb, vertsize, v1 ); + COPY_DWORDS( j, vb, vertsize, v2 ); } -static void r128_null_points( GLcontext *ctx, GLuint first, GLuint last ) + +static __inline void r128_draw_line( r128ContextPtr rmesa, + r128VertexPtr v0, + r128VertexPtr v1 ) { + GLuint vertsize = rmesa->vertex_size; + GLuint *vb = (GLuint *)r128AllocDmaLow( rmesa, 2 * vertsize * 4 ); + GLuint j; + + rmesa->num_verts += 2; + COPY_DWORDS( j, vb, vertsize, v0 ); + COPY_DWORDS( j, vb, vertsize, v1 ); } -static void r128PrintRenderState( const char *msg, GLuint state ) +static __inline void r128_draw_point( r128ContextPtr rmesa, + r128VertexPtr v0 ) { - fprintf( stderr, "%s: (0x%x) %s%s%s%s%s\n", - msg, state, - (state & R128_FLAT_BIT) ? "flat, " : "", - (state & R128_OFFSET_BIT) ? "offset, " : "", - (state & R128_TWOSIDE_BIT) ? "twoside, " : "", - (state & R128_NODRAW_BIT) ? "no-draw, " : "", - (state & R128_FALLBACK_BIT) ? "fallback" : "" ); + int vertsize = rmesa->vertex_size; + GLuint *vb = (GLuint *)r128AllocDmaLow( rmesa, vertsize * 4 ); + int j; + + rmesa->num_verts += 1; + COPY_DWORDS( j, vb, vertsize, v0 ); } -#define IND (0) +/*********************************************************************** + * Macros for t_dd_tritmp.h to draw basic primitives * + ***********************************************************************/ + +#define TRI( a, b, c ) \ +do { \ + if (DO_FALLBACK) \ + rmesa->draw_tri( rmesa, a, b, c ); \ + else \ + r128_draw_triangle( rmesa, a, b, c ); \ +} while (0) + +#define QUAD( a, b, c, d ) \ +do { \ + if (DO_FALLBACK) { \ + rmesa->draw_tri( rmesa, a, b, d ); \ + rmesa->draw_tri( rmesa, b, c, d ); \ + } else \ + r128_draw_quad( rmesa, a, b, c, d ); \ +} while (0) + +#define LINE( v0, v1 ) \ +do { \ + if (DO_FALLBACK) \ + rmesa->draw_line( rmesa, v0, v1 ); \ + else \ + r128_draw_line( rmesa, v0, v1 ); \ +} while (0) + +#define POINT( v0 ) \ +do { \ + if (DO_FALLBACK) \ + rmesa->draw_point( rmesa, v0 ); \ + else \ + r128_draw_point( rmesa, v0 ); \ +} while (0) + + +/*********************************************************************** + * Build render functions from dd templates * + ***********************************************************************/ + +#define R128_OFFSET_BIT 0x01 +#define R128_TWOSIDE_BIT 0x02 +#define R128_UNFILLED_BIT 0x04 +#define R128_FALLBACK_BIT 0x08 +#define R128_MAX_TRIFUNC 0x10 + + +static struct { + points_func points; + line_func line; + triangle_func triangle; + quad_func quad; +} rast_tab[R128_MAX_TRIFUNC]; + + +#define DO_FALLBACK (IND & R128_FALLBACK_BIT) +#define DO_OFFSET (IND & R128_OFFSET_BIT) +#define DO_UNFILLED (IND & R128_UNFILLED_BIT) +#define DO_TWOSIDE (IND & R128_TWOSIDE_BIT) +#define DO_FLAT 0 +#define DO_TRI 1 +#define DO_QUAD 1 +#define DO_LINE 1 +#define DO_POINTS 1 +#define DO_FULL_QUAD 1 + +#define HAVE_RGBA 1 +#define HAVE_SPEC 1 +#define HAVE_BACK_COLORS 0 +#define HAVE_HW_FLATSHADE 1 +#define VERTEX r128Vertex +#define TAB rast_tab + +#define DEPTH_SCALE 1.0 +#define UNFILLED_TRI unfilled_tri +#define UNFILLED_QUAD unfilled_quad +#define VERT_X(_v) _v->v.x +#define VERT_Y(_v) _v->v.y +#define VERT_Z(_v) _v->v.z +#define AREA_IS_CCW( a ) (a > 0) +#define GET_VERTEX(e) (rmesa->verts + (e<<rmesa->vertex_stride_shift)) + +#define VERT_SET_RGBA( v, c ) do { \ + r128_color_t *vc = (r128_color_t *)&(v)->ui[coloroffset]; \ + vc->blue = (c)[2]; \ + vc->green = (c)[1]; \ + vc->red = (c)[0]; \ + vc->alpha = (c)[3]; \ + } while (0) +#define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset] +#define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset] +#define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx] + +#define VERT_SET_SPEC( v0, c ) if (havespec) { \ + (v0)->v.specular.red = (c)[0];\ + (v0)->v.specular.green = (c)[1];\ + (v0)->v.specular.blue = (c)[2]; } +#define VERT_COPY_SPEC( v0, v1 ) if (havespec) { \ + (v0)->v.specular.red = v1->v.specular.red; \ + (v0)->v.specular.green = v1->v.specular.green; \ + (v0)->v.specular.blue = v1->v.specular.blue; } + +#define VERT_SAVE_SPEC( idx ) if (havespec) spec[idx] = v[idx]->ui[5] +#define VERT_RESTORE_SPEC( idx ) if (havespec) v[idx]->ui[5] = spec[idx] + +#define LOCAL_VARS(n) \ + r128ContextPtr rmesa = R128_CONTEXT(ctx); \ + GLuint color[n], spec[n]; \ + GLuint coloroffset = (rmesa->vertex_size == 4 ? 3 : 4); \ + GLboolean havespec = (rmesa->vertex_size == 4 ? 0 : 1); \ + (void) color; (void) spec; (void) coloroffset; (void) havespec; + +/*********************************************************************** + * Helpers for rendering unfilled primitives * + ***********************************************************************/ + +#define RASTERIZE(x) if (rmesa->hw_primitive != hw_prim[x]) \ + r128RasterPrimitive( ctx, hw_prim[x] ) +#define RENDER_PRIMITIVE rmesa->render_primitive +#define IND R128_FALLBACK_BIT #define TAG(x) x -#include "r128_tritmp.h" +#include "tnl_dd/t_dd_unfilled.h" +#undef IND + -#define IND (R128_FLAT_BIT) -#define TAG(x) x##_flat -#include "r128_tritmp.h" +/*********************************************************************** + * Generate GL render functions * + ***********************************************************************/ + + +#define IND (0) +#define TAG(x) x +#include "tnl_dd/t_dd_tritmp.h" #define IND (R128_OFFSET_BIT) #define TAG(x) x##_offset -#include "r128_tritmp.h" - -#define IND (R128_OFFSET_BIT | R128_FLAT_BIT) -#define TAG(x) x##_offset_flat -#include "r128_tritmp.h" +#include "tnl_dd/t_dd_tritmp.h" #define IND (R128_TWOSIDE_BIT) #define TAG(x) x##_twoside -#include "r128_tritmp.h" +#include "tnl_dd/t_dd_tritmp.h" -#define IND (R128_TWOSIDE_BIT | R128_FLAT_BIT) -#define TAG(x) x##_twoside_flat -#include "r128_tritmp.h" - -#define IND (R128_TWOSIDE_BIT | R128_OFFSET_BIT) +#define IND (R128_TWOSIDE_BIT|R128_OFFSET_BIT) #define TAG(x) x##_twoside_offset -#include "r128_tritmp.h" +#include "tnl_dd/t_dd_tritmp.h" -#define IND (R128_TWOSIDE_BIT | R128_OFFSET_BIT | R128_FLAT_BIT) -#define TAG(x) x##_twoside_offset_flat -#include "r128_tritmp.h" +#define IND (R128_UNFILLED_BIT) +#define TAG(x) x##_unfilled +#include "tnl_dd/t_dd_tritmp.h" +#define IND (R128_OFFSET_BIT|R128_UNFILLED_BIT) +#define TAG(x) x##_offset_unfilled +#include "tnl_dd/t_dd_tritmp.h" -void r128DDTriangleFuncsInit( void ) -{ - GLint i; +#define IND (R128_TWOSIDE_BIT|R128_UNFILLED_BIT) +#define TAG(x) x##_twoside_unfilled +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (R128_TWOSIDE_BIT|R128_OFFSET_BIT|R128_UNFILLED_BIT) +#define TAG(x) x##_twoside_offset_unfilled +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (R128_FALLBACK_BIT) +#define TAG(x) x##_fallback +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (R128_OFFSET_BIT|R128_FALLBACK_BIT) +#define TAG(x) x##_offset_fallback +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (R128_TWOSIDE_BIT|R128_FALLBACK_BIT) +#define TAG(x) x##_twoside_fallback +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (R128_TWOSIDE_BIT|R128_OFFSET_BIT|R128_FALLBACK_BIT) +#define TAG(x) x##_twoside_offset_fallback +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (R128_UNFILLED_BIT|R128_FALLBACK_BIT) +#define TAG(x) x##_unfilled_fallback +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (R128_OFFSET_BIT|R128_UNFILLED_BIT|R128_FALLBACK_BIT) +#define TAG(x) x##_offset_unfilled_fallback +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (R128_TWOSIDE_BIT|R128_UNFILLED_BIT|R128_FALLBACK_BIT) +#define TAG(x) x##_twoside_unfilled_fallback +#include "tnl_dd/t_dd_tritmp.h" +#define IND (R128_TWOSIDE_BIT|R128_OFFSET_BIT|R128_UNFILLED_BIT| \ + R128_FALLBACK_BIT) +#define TAG(x) x##_twoside_offset_unfilled_fallback +#include "tnl_dd/t_dd_tritmp.h" + + +static void init_rast_tab( void ) +{ init(); - init_flat(); init_offset(); - init_offset_flat(); init_twoside(); - init_twoside_flat(); init_twoside_offset(); - init_twoside_offset_flat(); - - for ( i = 0 ; i < R128_MAX_TRIFUNC ; i++ ) { - if ( i & R128_NODRAW_BIT ) { - rast_tab[i].points = r128_null_points; - rast_tab[i].line = r128_null_line; - rast_tab[i].triangle = r128_null_triangle; - rast_tab[i].quad = r128_null_quad; + init_unfilled(); + init_offset_unfilled(); + init_twoside_unfilled(); + init_twoside_offset_unfilled(); + init_fallback(); + init_offset_fallback(); + init_twoside_fallback(); + init_twoside_offset_fallback(); + init_unfilled_fallback(); + init_offset_unfilled_fallback(); + init_twoside_unfilled_fallback(); + init_twoside_offset_unfilled_fallback(); +} + + + +/*********************************************************************** + * Rasterization fallback helpers * + ***********************************************************************/ + + +/* This code is hit only when a mix of accelerated and unaccelerated + * primitives are being drawn, and only for the unaccelerated + * primitives. + */ +static void +r128_fallback_tri( r128ContextPtr rmesa, + r128Vertex *v0, + r128Vertex *v1, + r128Vertex *v2 ) +{ + GLcontext *ctx = rmesa->glCtx; + SWvertex v[3]; + r128_translate_vertex( ctx, v0, &v[0] ); + r128_translate_vertex( ctx, v1, &v[1] ); + r128_translate_vertex( ctx, v2, &v[2] ); + _swrast_Triangle( ctx, &v[0], &v[1], &v[2] ); +} + + +static void +r128_fallback_line( r128ContextPtr rmesa, + r128Vertex *v0, + r128Vertex *v1 ) +{ + GLcontext *ctx = rmesa->glCtx; + SWvertex v[2]; + r128_translate_vertex( ctx, v0, &v[0] ); + r128_translate_vertex( ctx, v1, &v[1] ); + _swrast_Line( ctx, &v[0], &v[1] ); +} + + +static void +r128_fallback_point( r128ContextPtr rmesa, + r128Vertex *v0 ) +{ + GLcontext *ctx = rmesa->glCtx; + SWvertex v[1]; + r128_translate_vertex( ctx, v0, &v[0] ); + _swrast_Point( ctx, &v[0] ); +} + + + +/**********************************************************************/ +/* Render unclipped begin/end objects */ +/**********************************************************************/ + +#define VERT(x) (r128Vertex *)(r128verts + (x << shift)) +#define RENDER_POINTS( start, count ) \ + for ( ; start < count ; start++) \ + r128_draw_point( rmesa, VERT(start) ) +#define RENDER_LINE( v0, v1 ) \ + r128_draw_line( rmesa, VERT(v0), VERT(v1) ) +#define RENDER_TRI( v0, v1, v2 ) \ + r128_draw_triangle( rmesa, VERT(v0), VERT(v1), VERT(v2) ) +#define RENDER_QUAD( v0, v1, v2, v3 ) \ + r128_draw_quad( rmesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) ) +#define INIT(x) do { \ + if (0) fprintf(stderr, "%s\n", __FUNCTION__); \ + r128RenderPrimitive( ctx, x ); \ +} while (0) +#undef LOCAL_VARS +#define LOCAL_VARS \ + r128ContextPtr rmesa = R128_CONTEXT(ctx); \ + const GLuint shift = rmesa->vertex_stride_shift; \ + const char *r128verts = (char *)rmesa->verts; \ + const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \ + (void) elt; +#define RESET_STIPPLE +#define RESET_OCCLUSION +#define PRESERVE_VB_DEFS +#define ELT(x) (x) +#define TAG(x) r128_##x##_verts +#include "tnl/t_vb_rendertmp.h" +#undef ELT +#undef TAG +#define TAG(x) r128_##x##_elts +#define ELT(x) elt[x] +#include "tnl/t_vb_rendertmp.h" + + +/**********************************************************************/ +/* Render clipped primitives */ +/**********************************************************************/ + +static void r128RenderClippedPoly( GLcontext *ctx, const GLuint *elts, + GLuint n ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; + + /* Render the new vertices as an unclipped polygon. + */ + { + GLuint *tmp = VB->Elts; + VB->Elts = (GLuint *)elts; + tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, PRIM_BEGIN|PRIM_END ); + VB->Elts = tmp; + } +} + +static void r128RenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + tnl->Driver.Render.Line( ctx, ii, jj ); +} + +static void r128FastRenderClippedPoly( GLcontext *ctx, const GLuint *elts, + GLuint n ) +{ + r128ContextPtr rmesa = R128_CONTEXT( ctx ); + GLuint vertsize = rmesa->vertex_size; + GLuint *vb = r128AllocDmaLow( rmesa, (n-2) * 3 * 4 * vertsize ); + GLubyte *r128verts = (GLubyte *)rmesa->verts; + const GLuint shift = rmesa->vertex_stride_shift; + const GLuint *start = (const GLuint *)VERT(elts[0]); + int i,j; + + rmesa->num_verts += (n-2) * 3; + + for (i = 2 ; i < n ; i++) { + COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) VERT(elts[i-1]) ); + COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) VERT(elts[i]) ); + COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) start ); + } +} + + + + +/**********************************************************************/ +/* Choose render functions */ +/**********************************************************************/ + +#define _R128_NEW_RENDER_STATE (_DD_NEW_LINE_STIPPLE | \ + _DD_NEW_LINE_SMOOTH | \ + _DD_NEW_POINT_SMOOTH | \ + _DD_NEW_TRI_SMOOTH | \ + _DD_NEW_TRI_UNFILLED | \ + _DD_NEW_TRI_LIGHT_TWOSIDE | \ + _DD_NEW_TRI_OFFSET) \ + + +#define POINT_FALLBACK (DD_POINT_SMOOTH) +#define LINE_FALLBACK (DD_LINE_STIPPLE|DD_LINE_SMOOTH) +#define TRI_FALLBACK (DD_TRI_SMOOTH) +#define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK) +#define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED) + + +static void r128ChooseRenderState(GLcontext *ctx) +{ + r128ContextPtr rmesa = R128_CONTEXT(ctx); + GLuint flags = ctx->_TriangleCaps; + GLuint index = 0; + + if (flags & (ANY_RASTER_FLAGS|ANY_FALLBACK_FLAGS)) { + rmesa->draw_point = r128_draw_point; + rmesa->draw_line = r128_draw_line; + rmesa->draw_tri = r128_draw_triangle; + + if (flags & ANY_RASTER_FLAGS) { + if (flags & DD_TRI_LIGHT_TWOSIDE) index |= R128_TWOSIDE_BIT; + if (flags & DD_TRI_OFFSET) index |= R128_OFFSET_BIT; + if (flags & DD_TRI_UNFILLED) index |= R128_UNFILLED_BIT; } + + /* Hook in fallbacks for specific primitives. + */ + if (flags & (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)) { + if (flags & POINT_FALLBACK) rmesa->draw_point = r128_fallback_point; + if (flags & LINE_FALLBACK) rmesa->draw_line = r128_fallback_line; + if (flags & TRI_FALLBACK) rmesa->draw_tri = r128_fallback_tri; + index |= R128_FALLBACK_BIT; + } + } + + if (index != rmesa->RenderIndex) { + TNLcontext *tnl = TNL_CONTEXT(ctx); + tnl->Driver.Render.Points = rast_tab[index].points; + tnl->Driver.Render.Line = rast_tab[index].line; + tnl->Driver.Render.Triangle = rast_tab[index].triangle; + tnl->Driver.Render.Quad = rast_tab[index].quad; + + if (index == 0) { + tnl->Driver.Render.PrimTabVerts = r128_render_tab_verts; + tnl->Driver.Render.PrimTabElts = r128_render_tab_elts; + tnl->Driver.Render.ClippedLine = rast_tab[index].line; + tnl->Driver.Render.ClippedPolygon = r128FastRenderClippedPoly; + } else { + tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts; + tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts; + tnl->Driver.Render.ClippedLine = r128RenderClippedLine; + tnl->Driver.Render.ClippedPolygon = r128RenderClippedPoly; + } + + rmesa->RenderIndex = index; } } +/**********************************************************************/ +/* Validate state at pipeline start */ +/**********************************************************************/ -/* FIXME: Only enable software fallback for stencil in 16 bpp mode after - * we have hardware stencil support. - */ -#define ALL_FALLBACK (DD_MULTIDRAW | DD_SELECT | DD_FEEDBACK | DD_STENCIL) -#define POINT_FALLBACK (ALL_FALLBACK | DD_POINT_SMOOTH | DD_POINT_ATTEN) -#define LINE_FALLBACK (ALL_FALLBACK | DD_LINE_SMOOTH | DD_LINE_STIPPLE) -#define TRI_FALLBACK (ALL_FALLBACK | DD_TRI_SMOOTH | DD_TRI_STIPPLE | DD_TRI_UNFILLED) -#define ANY_FALLBACK (POINT_FALLBACK | LINE_FALLBACK | TRI_FALLBACK) -#define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE | DD_TRI_OFFSET | DD_Z_NEVER) - -/* Setup the Point, Line, Triangle and Quad functions based on the - * current rendering state. Wherever possible, use the hardware to - * render the primitive. Otherwise, fallback to software rendering. +static void r128RunPipeline( GLcontext *ctx ) +{ + r128ContextPtr rmesa = R128_CONTEXT(ctx); + + if (rmesa->new_state) + r128DDUpdateHWState( ctx ); + + if (!rmesa->Fallback && rmesa->NewGLState) { + if (rmesa->NewGLState & _R128_NEW_VERTEX_STATE) + r128ChooseVertexState( ctx ); + + if (rmesa->NewGLState & _R128_NEW_RENDER_STATE) + r128ChooseRenderState( ctx ); + + rmesa->NewGLState = 0; + } + + _tnl_run_pipeline( ctx ); +} + +/**********************************************************************/ +/* High level hooks for t_vb_render.c */ +/**********************************************************************/ + +/* This is called when Mesa switches between rendering triangle + * primitives (such as GL_POLYGON, GL_QUADS, GL_TRIANGLE_STRIP, etc), + * and lines, points and bitmaps. + * + * As the r128 uses triangles to render lines and points, it is + * necessary to turn off hardware culling when rendering these + * primitives. */ -void r128DDChooseRenderState( GLcontext *ctx ) + +static void r128RasterPrimitive( GLcontext *ctx, GLuint hwprim ) { r128ContextPtr rmesa = R128_CONTEXT(ctx); - GLuint flags = ctx->TriangleCaps; - GLuint index = 0; - if ( rmesa->Fallback ) { - rmesa->RenderIndex = R128_FALLBACK_BIT; - return; + rmesa->setup.dp_gui_master_cntl_c &= ~R128_GMC_BRUSH_NONE; + + if ( ctx->Polygon.StippleFlag && hwprim == GL_TRIANGLES ) { + rmesa->setup.dp_gui_master_cntl_c |= R128_GMC_BRUSH_32x32_MONO_FG_LA; } + else { + rmesa->setup.dp_gui_master_cntl_c |= R128_GMC_BRUSH_SOLID_COLOR; + } + + rmesa->new_state |= R128_NEW_CONTEXT; + rmesa->dirty |= R128_UPLOAD_CONTEXT; - if ( flags & ANY_RASTER_FLAGS ) { - if ( flags & DD_FLATSHADE ) index |= R128_FLAT_BIT; - if ( flags & DD_TRI_LIGHT_TWOSIDE ) index |= R128_TWOSIDE_BIT; - if ( flags & DD_TRI_OFFSET ) index |= R128_OFFSET_BIT; - if ( flags & DD_Z_NEVER ) index |= R128_NODRAW_BIT; + if (rmesa->hw_primitive != hwprim) { + FLUSH_BATCH( rmesa ); + rmesa->hw_primitive = hwprim; } +} - rmesa->PointsFunc = rast_tab[index].points; - rmesa->LineFunc = rast_tab[index].line; - rmesa->TriangleFunc = rast_tab[index].triangle; - rmesa->QuadFunc = rast_tab[index].quad; +static void r128RenderPrimitive( GLcontext *ctx, GLenum prim ) +{ + r128ContextPtr rmesa = R128_CONTEXT(ctx); + GLuint hw = hw_prim[prim]; + rmesa->render_primitive = prim; + if (prim >= GL_TRIANGLES && (ctx->_TriangleCaps & DD_TRI_UNFILLED)) + return; + r128RasterPrimitive( ctx, hw ); +} - rmesa->RenderIndex = index; - rmesa->IndirectTriangles = 0; - if ( flags & ANY_FALLBACK ) { - if ( flags & POINT_FALLBACK ) { - rmesa->RenderIndex |= R128_FALLBACK_BIT; - rmesa->PointsFunc = 0; - rmesa->IndirectTriangles |= DD_POINT_SW_RASTERIZE; - } +static void r128RenderStart( GLcontext *ctx ) +{ + /* Check for projective texturing. Make sure all texcoord + * pointers point to something. (fix in mesa?) + */ + r128CheckTexSizes( ctx ); +} - if ( flags & LINE_FALLBACK ) { - rmesa->RenderIndex |= R128_FALLBACK_BIT; - rmesa->LineFunc = 0; - rmesa->IndirectTriangles |= DD_LINE_SW_RASTERIZE; - } +static void r128RenderFinish( GLcontext *ctx ) +{ + if (R128_CONTEXT(ctx)->RenderIndex & R128_FALLBACK_BIT) + _swrast_flush( ctx ); +} + + +/**********************************************************************/ +/* Transition to/from hardware rasterization. */ +/**********************************************************************/ - if ( flags & TRI_FALLBACK ) { - rmesa->RenderIndex |= R128_FALLBACK_BIT; - rmesa->TriangleFunc = 0; - rmesa->QuadFunc = 0; - rmesa->IndirectTriangles |= (DD_TRI_SW_RASTERIZE | - DD_QUAD_SW_RASTERIZE); +void r128Fallback( GLcontext *ctx, GLuint bit, GLboolean mode ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + r128ContextPtr rmesa = R128_CONTEXT(ctx); + GLuint oldfallback = rmesa->Fallback; + + if (mode) { + rmesa->Fallback |= bit; + if (oldfallback == 0) { + FLUSH_BATCH( rmesa ); + _swsetup_Wakeup( ctx ); + rmesa->RenderIndex = ~0; } } + else { + rmesa->Fallback &= ~bit; + if (oldfallback == bit) { + _swrast_flush( ctx ); + tnl->Driver.Render.Start = r128RenderStart; + tnl->Driver.Render.PrimitiveNotify = r128RenderPrimitive; + tnl->Driver.Render.Finish = r128RenderFinish; + tnl->Driver.Render.BuildVertices = r128BuildVertices; + rmesa->NewGLState |= (_R128_NEW_RENDER_STATE| + _R128_NEW_VERTEX_STATE); + } + } +} + + +/**********************************************************************/ +/* Initialization. */ +/**********************************************************************/ - if ( 0 ) { - gl_print_tri_caps( "tricaps", ctx->TriangleCaps ); - r128PrintRenderState( "r128 render state", rmesa->RenderIndex ); +void r128InitTriFuncs( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + static int firsttime = 1; + + if (firsttime) { + init_rast_tab(); + firsttime = 0; } + + tnl->Driver.RunPipeline = r128RunPipeline; + tnl->Driver.Render.Start = r128RenderStart; + tnl->Driver.Render.Finish = r128RenderFinish; + tnl->Driver.Render.PrimitiveNotify = r128RenderPrimitive; + tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple; + tnl->Driver.Render.BuildVertices = r128BuildVertices; + +/* r128Fallback( ctx, 0x100000, 1 ); */ } diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_vb.c b/xc/lib/GL/mesa/src/drv/r128/r128_vb.c index 06a63e152..d3935a6d7 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_vb.c +++ b/xc/lib/GL/mesa/src/drv/r128/r128_vb.c @@ -1,8 +1,9 @@ /* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_vb.c,v 1.11 2001/01/08 01:07:24 martin Exp $ */ /************************************************************************** -Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., - Cedar Park, Texas. +Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and + VA Linux Systems Inc., Fremont, California. + All Rights Reserved. Permission is hereby granted, free of charge, to any person obtaining a @@ -19,7 +20,7 @@ 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 -ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -28,487 +29,495 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. /* * Authors: - * Gareth Hughes <gareth@valinux.com> - * Kevin E. Martin <martin@valinux.com> + * Keith Whitwell <keithw@valinux.com> * */ +#include "glheader.h" +#include "mtypes.h" +#include "mem.h" +#include "macros.h" +#include "colormac.h" +#include "mmath.h" + +#include "swrast_setup/swrast_setup.h" +#include "tnl/t_context.h" + #include "r128_context.h" +#include "r128_vb.h" #include "r128_ioctl.h" +#include "r128_tris.h" #include "r128_state.h" -#include "r128_vb.h" -#include "mem.h" -#include "stages.h" - -#define TEX0 \ -do { \ - v->v.tu0 = tc0[i][0]; \ - v->v.tv0 = tc0[i][1]; \ -} while (0) - -#define TEX1 \ -do { \ - v->v.tu1 = tc1[i][0]; \ - v->v.tv1 = tc1[i][1]; \ -} while (0) - -#define SPC \ -do { \ - GLubyte *spec = &(VB->Spec[0][i][0]); \ - v->v.specular.blue = spec[2]; \ - v->v.specular.green = spec[1]; \ - v->v.specular.red = spec[0]; \ -} while (0) - -#define FOG \ -do { \ - GLubyte *spec = &(VB->Spec[0][i][0]); \ - v->v.specular.alpha = spec[3]; \ -} while (0) - -#define COL \ -do { \ - GLubyte *col = &(VB->Color[0]->data[i][0]); \ - v->v.color.blue = col[2]; \ - v->v.color.green = col[1]; \ - v->v.color.red = col[0]; \ - v->v.color.alpha = col[3]; \ -} while (0) - -#define TEX0_4 \ -do { \ - if ( VB->TexCoordPtr[0]->size == 4 ) { \ - GLfloat (*tc)[4] = VB->TexCoordPtr[0]->data; \ - v = &(R128_DRIVER_DATA(VB)->verts[start]); \ - for ( i = start ; i < end ; i++, v++ ) { \ - float oow = 1.0 / tc[i][3]; \ - v->v.rhw *= tc[i][3]; \ - v->v.tu0 *= oow; \ - v->v.tv0 *= oow; \ - } \ - } \ -} while (0) - -#ifdef USE_RHW2 - -#define TEX1_4 \ -do { \ - if ( VB->TexCoordPtr[1]->size == 4 ) { \ - GLfloat (*tc)[4] = VB->TexCoordPtr[1]->data; \ - v = &(R128_DRIVER_DATA(VB)->verts[start]); \ - for ( i = start ; i < end ; i++, v++ ) { \ - float oow = 1.0 / tc[i][3]; \ - v->v.rhw2 *= tc[i][3]; \ - v->v.tu1 *= oow; \ - v->v.tv1 *= oow; \ - } \ - } \ -} while (0) - -#define COORD \ -do { \ - GLfloat *win = VB->Win.data[i]; \ - v->v.x = win[0] + xoffset; \ - v->v.y = - win[1] + yoffset; \ - v->v.z = depth_scale * win[2]; \ - v->v.rhw = v->v.rhw2 = win[3]; \ -} while (0) - -#else /* USE_RHW2 */ - -#define TEX1_4 - -#define COORD \ -do { \ - GLfloat *win = VB->Win.data[i]; \ - v->v.x = win[0] + xoffset; \ - v->v.y = - win[1] + yoffset; \ - v->v.z = depth_scale * win[2]; \ - v->v.rhw = win[3]; \ -} while (0) - -#endif /* USE_RHW2 */ - -#define NOP - - -#define SETUPFUNC(name,win,col,tex0,tex1,tex0_4,tex1_4,spec,fog) \ -static void name( struct vertex_buffer *VB, GLuint start, GLuint end ) \ -{ \ - r128ContextPtr rmesa = R128_CONTEXT(VB->ctx); \ - __DRIdrawablePrivate *dPriv = rmesa->driDrawable; \ - r128VertexPtr v; \ - GLfloat (*tc0)[4]; \ - GLfloat (*tc1)[4]; \ - const GLfloat depth_scale = rmesa->depth_scale; \ - const GLfloat xoffset = SUBPIXEL_X; \ - const GLfloat yoffset = dPriv->h + SUBPIXEL_Y; \ - GLint i; \ - \ - (void) xoffset; (void) yoffset; (void) depth_scale; \ - \ - gl_import_client_data( VB, VB->ctx->RenderFlags, \ - (VB->ClipOrMask \ - ? VEC_WRITABLE | VEC_GOOD_STRIDE \ - : VEC_GOOD_STRIDE) ); \ - \ - tc0 = VB->TexCoordPtr[rmesa->tmu_source[0]]->data; \ - tc1 = VB->TexCoordPtr[rmesa->tmu_source[1]]->data; \ - \ - v = &(R128_DRIVER_DATA(VB)->verts[start]); \ - \ - if ( VB->ClipOrMask == 0 ) { \ - for ( i = start ; i < end ; i++, v++ ) { \ - win; \ - col; \ - spec; \ - fog; \ - tex0; \ - tex1; \ - } \ - } else { \ - for ( i = start ; i < end ; i++, v++ ) { \ - if ( VB->ClipMask[i] == 0 ) { \ - win; \ - spec; \ - fog; \ - tex0; \ - tex1; \ - } \ - col; \ - } \ - } \ - tex0_4; \ - tex1_4; \ -} +#define R128_TEX1_BIT 0x1 +#define R128_TEX0_BIT 0x2 +#define R128_RGBA_BIT 0x4 +#define R128_SPEC_BIT 0x8 +#define R128_FOG_BIT 0x10 +#define R128_XYZW_BIT 0x20 +#define R128_PTEX_BIT 0x40 +#define R128_MAX_SETUP 0x80 + +static struct { + void (*emit)( GLcontext *, GLuint, GLuint, void *, GLuint ); + interp_func interp; + copy_pv_func copy_pv; + GLboolean (*check_tex_sizes)( GLcontext *ctx ); + GLuint vertex_size; + GLuint vertex_stride_shift; + GLuint vertex_format; +} setup_tab[R128_MAX_SETUP]; + +#define TINY_VERTEX_FORMAT (R128_CCE_VC_FRMT_DIFFUSE_ARGB) + +#define NOTEX_VERTEX_FORMAT (R128_CCE_VC_FRMT_RHW | \ + R128_CCE_VC_FRMT_DIFFUSE_ARGB |\ + R128_CCE_VC_FRMT_SPEC_FRGB) + +#define TEX0_VERTEX_FORMAT (R128_CCE_VC_FRMT_RHW | \ + R128_CCE_VC_FRMT_DIFFUSE_ARGB |\ + R128_CCE_VC_FRMT_SPEC_FRGB | \ + R128_CCE_VC_FRMT_S_T) + +#define TEX1_VERTEX_FORMAT (R128_CCE_VC_FRMT_RHW | \ + R128_CCE_VC_FRMT_DIFFUSE_ARGB |\ + R128_CCE_VC_FRMT_SPEC_FRGB | \ + R128_CCE_VC_FRMT_S_T | \ + R128_CCE_VC_FRMT_S2_T2) + + +#define PROJ_TEX1_VERTEX_FORMAT 0 +#define TEX2_VERTEX_FORMAT 0 +#define TEX3_VERTEX_FORMAT 0 +#define PROJ_TEX3_VERTEX_FORMAT 0 + +#define DO_XYZW (IND & R128_XYZW_BIT) +#define DO_RGBA (IND & R128_RGBA_BIT) +#define DO_SPEC (IND & R128_SPEC_BIT) +#define DO_FOG (IND & R128_FOG_BIT) +#define DO_TEX0 (IND & R128_TEX0_BIT) +#define DO_TEX1 (IND & R128_TEX1_BIT) +#define DO_TEX2 0 +#define DO_TEX3 0 +#define DO_PTEX (IND & R128_PTEX_BIT) + +#define VERTEX r128Vertex +#define VERTEX_COLOR r128_color_t +#define LOCALVARS r128ContextPtr rmesa = R128_CONTEXT(ctx); +#define GET_VIEWPORT_MAT() rmesa->hw_viewport +#define GET_TEXSOURCE(n) rmesa->tmu_source[n] +#define GET_VERTEX_FORMAT() rmesa->vertex_format +#define GET_VERTEX_STORE() rmesa->verts +#define GET_VERTEX_STRIDE_SHIFT() rmesa->vertex_stride_shift +#define INVALIDATE_STORED_VERTICES() +#define GET_UBYTE_COLOR_STORE() &rmesa->UbyteColor +#define GET_UBYTE_SPEC_COLOR_STORE() &rmesa->UbyteSecondaryColor + +#define HAVE_HW_VIEWPORT 0 +#define HAVE_HW_DIVIDE 0 +#define HAVE_RGBA_COLOR 0 +#define HAVE_TINY_VERTICES 1 +#define HAVE_NOTEX_VERTICES 1 +#define HAVE_TEX0_VERTICES 1 +#define HAVE_TEX1_VERTICES 1 +#define HAVE_TEX2_VERTICES 0 +#define HAVE_TEX3_VERTICES 0 +#define HAVE_PTEX_VERTICES 0 /* r128 rhw2 not supported by template */ + +#define UNVIEWPORT_VARS GLfloat h = R128_CONTEXT(ctx)->driDrawable->h +#define UNVIEWPORT_X(x) x - SUBPIXEL_X +#define UNVIEWPORT_Y(y) - y + h + SUBPIXEL_Y +#define UNVIEWPORT_Z(z) z / rmesa->depth_scale + +#define PTEX_FALLBACK() FALLBACK(R128_CONTEXT(ctx), R128_FALLBACK_TEXTURE, 1) + +#define IMPORT_FLOAT_COLORS r128_import_float_colors +#define IMPORT_FLOAT_SPEC_COLORS r128_import_float_spec_colors + +#define INTERP_VERTEX setup_tab[rmesa->SetupIndex].interp +#define COPY_PV_VERTEX setup_tab[rmesa->SetupIndex].copy_pv + +/*********************************************************************** + * Generate pv-copying and translation functions * + ***********************************************************************/ + +#define TAG(x) r128_##x +#include "tnl_dd/t_dd_vb.c" + +/*********************************************************************** + * Generate vertex emit and interp functions * + ***********************************************************************/ + + +#define IND (R128_XYZW_BIT|R128_RGBA_BIT) +#define TAG(x) x##_wg +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_SPEC_BIT) +#define TAG(x) x##_wgs +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_TEX0_BIT) +#define TAG(x) x##_wgt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_TEX0_BIT|R128_TEX1_BIT) +#define TAG(x) x##_wgt0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_TEX0_BIT|R128_PTEX_BIT) +#define TAG(x) x##_wgpt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_SPEC_BIT|R128_TEX0_BIT) +#define TAG(x) x##_wgst0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_SPEC_BIT|R128_TEX0_BIT|\ + R128_TEX1_BIT) +#define TAG(x) x##_wgst0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_SPEC_BIT|R128_TEX0_BIT|\ + R128_PTEX_BIT) +#define TAG(x) x##_wgspt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_FOG_BIT) +#define TAG(x) x##_wgf +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT) +#define TAG(x) x##_wgfs +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_TEX0_BIT) +#define TAG(x) x##_wgft0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_TEX0_BIT|\ + R128_TEX1_BIT) +#define TAG(x) x##_wgft0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_TEX0_BIT|\ + R128_PTEX_BIT) +#define TAG(x) x##_wgfpt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT|\ + R128_TEX0_BIT) +#define TAG(x) x##_wgfst0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT|\ + R128_TEX0_BIT|R128_TEX1_BIT) +#define TAG(x) x##_wgfst0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT|\ + R128_TEX0_BIT|R128_PTEX_BIT) +#define TAG(x) x##_wgfspt0 +#include "tnl_dd/t_dd_vbtmp.h" -SETUPFUNC(rs_wt0, COORD, NOP, TEX0, NOP, TEX0_4, NOP, NOP, NOP) -SETUPFUNC(rs_wt0t1, COORD, NOP, TEX0, TEX1, TEX0_4, TEX1_4, NOP, NOP) -SETUPFUNC(rs_wft0, COORD, NOP, TEX0, NOP, TEX0_4, NOP, NOP, FOG) -SETUPFUNC(rs_wft0t1, COORD, NOP, TEX0, TEX1, TEX0_4, TEX1_4, NOP, FOG) -SETUPFUNC(rs_wg, COORD, COL, NOP, NOP, NOP, NOP, NOP, NOP) -SETUPFUNC(rs_wgs, COORD, COL, NOP, NOP, NOP, NOP, SPC, NOP) -SETUPFUNC(rs_wgt0, COORD, COL, TEX0, NOP, TEX0_4, NOP, NOP, NOP) -SETUPFUNC(rs_wgt0t1, COORD, COL, TEX0, TEX1, TEX0_4, TEX1_4, NOP, NOP) -SETUPFUNC(rs_wgst0, COORD, COL, TEX0, NOP, TEX0_4, NOP, SPC, NOP) -SETUPFUNC(rs_wgst0t1, COORD, COL, TEX0, TEX1, TEX0_4, TEX1_4, SPC, NOP) -SETUPFUNC(rs_wgf, COORD, COL, NOP, NOP, NOP, NOP, NOP, FOG) -SETUPFUNC(rs_wgfs, COORD, COL, NOP, NOP, NOP, NOP, SPC, FOG) -SETUPFUNC(rs_wgft0, COORD, COL, TEX0, NOP, TEX0_4, NOP, NOP, FOG) -SETUPFUNC(rs_wgft0t1, COORD, COL, TEX0, TEX1, TEX0_4, TEX1_4, NOP, FOG) -SETUPFUNC(rs_wgfst0, COORD, COL, TEX0, NOP, TEX0_4, NOP, SPC, FOG) -SETUPFUNC(rs_wgfst0t1, COORD, COL, TEX0, TEX1, TEX0_4, TEX1_4, SPC, FOG) - -SETUPFUNC(rs_t0, NOP, NOP, TEX0, NOP, TEX0_4, NOP, NOP, NOP) -SETUPFUNC(rs_t0t1, NOP, NOP, TEX0, TEX1, TEX0_4, TEX1_4, NOP, NOP) -SETUPFUNC(rs_f, NOP, NOP, NOP, NOP, NOP, NOP, NOP, FOG) -SETUPFUNC(rs_ft0, NOP, NOP, TEX0, NOP, TEX0_4, NOP, NOP, FOG) -SETUPFUNC(rs_ft0t1, NOP, NOP, TEX0, TEX1, TEX0_4, TEX1_4, NOP, FOG) -SETUPFUNC(rs_g, NOP, COL, NOP, NOP, NOP, NOP, NOP, NOP) -SETUPFUNC(rs_gs, NOP, COL, NOP, NOP, NOP, NOP, SPC, NOP) -SETUPFUNC(rs_gt0, NOP, COL, TEX0, NOP, TEX0_4, NOP, NOP, NOP) -SETUPFUNC(rs_gt0t1, NOP, COL, TEX0, TEX1, TEX0_4, TEX1_4, NOP, NOP) -SETUPFUNC(rs_gst0, NOP, COL, TEX0, NOP, TEX0_4, NOP, SPC, NOP) -SETUPFUNC(rs_gst0t1, NOP, COL, TEX0, TEX1, TEX0_4, TEX1_4, SPC, NOP) -SETUPFUNC(rs_gf, NOP, COL, NOP, NOP, NOP, NOP, NOP, FOG) -SETUPFUNC(rs_gfs, NOP, COL, NOP, NOP, NOP, NOP, SPC, FOG) -SETUPFUNC(rs_gft0, NOP, COL, TEX0, NOP, TEX0_4, NOP, NOP, FOG) -SETUPFUNC(rs_gft0t1, NOP, COL, TEX0, TEX1, TEX0_4, TEX1_4, NOP, FOG) -SETUPFUNC(rs_gfst0, NOP, COL, TEX0, NOP, TEX0_4, NOP, SPC, FOG) -SETUPFUNC(rs_gfst0t1, NOP, COL, TEX0, TEX1, TEX0_4, TEX1_4, SPC, FOG) - - -static void rs_invalid( struct vertex_buffer *VB, GLuint start, GLuint end ) -{ - fprintf( stderr, "r128RasterSetup(): invalid setup function\n" ); -} +#define IND (R128_TEX0_BIT) +#define TAG(x) x##_t0 +#include "tnl_dd/t_dd_vbtmp.h" -typedef void (*setupFunc)( struct vertex_buffer *, GLuint, GLuint ); -static setupFunc setup_func[R128_MAX_SETUPFUNC]; +#define IND (R128_TEX0_BIT|R128_TEX1_BIT) +#define TAG(x) x##_t0t1 +#include "tnl_dd/t_dd_vbtmp.h" +#define IND (R128_FOG_BIT) +#define TAG(x) x##_f +#include "tnl_dd/t_dd_vbtmp.h" -void r128DDSetupInit( void ) -{ - GLint i; +#define IND (R128_FOG_BIT|R128_TEX0_BIT) +#define TAG(x) x##_ft0 +#include "tnl_dd/t_dd_vbtmp.h" - for ( i = 0 ; i < R128_MAX_SETUPFUNC ; i++ ) { - setup_func[i] = rs_invalid; - } +#define IND (R128_FOG_BIT|R128_TEX0_BIT|R128_TEX1_BIT) +#define TAG(x) x##_ft0t1 +#include "tnl_dd/t_dd_vbtmp.h" - /* Functions to build vertices from scratch - */ - setup_func[R128_WIN_BIT|R128_TEX0_BIT] = rs_wt0; - setup_func[R128_WIN_BIT|R128_TEX0_BIT|R128_TEX1_BIT] = rs_wt0t1; - setup_func[R128_WIN_BIT|R128_FOG_BIT|R128_TEX0_BIT] = rs_wft0; - setup_func[R128_WIN_BIT|R128_FOG_BIT|R128_TEX0_BIT|R128_TEX1_BIT] = rs_wft0t1; - setup_func[R128_WIN_BIT|R128_RGBA_BIT] = rs_wg; - setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_SPEC_BIT] = rs_wgs; - setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_TEX0_BIT] = rs_wgt0; - setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_TEX0_BIT|R128_TEX1_BIT] = rs_wgt0t1; - setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_SPEC_BIT|R128_TEX0_BIT] = rs_wgst0; - setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_SPEC_BIT|R128_TEX0_BIT|R128_TEX1_BIT] = rs_wgst0t1; - setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_FOG_BIT] = rs_wgf; - setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT] = rs_wgfs; - setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_TEX0_BIT] = rs_wgft0; - setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_TEX0_BIT|R128_TEX1_BIT] = rs_wgft0t1; - setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT|R128_TEX0_BIT] = rs_wgfst0; - setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT|R128_TEX0_BIT|R128_TEX1_BIT] = rs_wgfst0t1; - - /* Repair functions - */ - setup_func[R128_TEX0_BIT] = rs_t0; - setup_func[R128_TEX0_BIT|R128_TEX1_BIT] = rs_t0t1; - setup_func[R128_FOG_BIT] = rs_f; - setup_func[R128_FOG_BIT|R128_TEX0_BIT] = rs_ft0; - setup_func[R128_FOG_BIT|R128_TEX0_BIT|R128_TEX1_BIT] = rs_ft0t1; - setup_func[R128_RGBA_BIT] = rs_g; - setup_func[R128_RGBA_BIT|R128_SPEC_BIT] = rs_gs; - setup_func[R128_RGBA_BIT|R128_TEX0_BIT] = rs_gt0; - setup_func[R128_RGBA_BIT|R128_TEX0_BIT|R128_TEX1_BIT] = rs_gt0t1; - setup_func[R128_RGBA_BIT|R128_SPEC_BIT|R128_TEX0_BIT] = rs_gst0; - setup_func[R128_RGBA_BIT|R128_SPEC_BIT|R128_TEX0_BIT|R128_TEX1_BIT] = rs_gst0t1; - setup_func[R128_RGBA_BIT|R128_FOG_BIT] = rs_gf; - setup_func[R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT] = rs_gfs; - setup_func[R128_RGBA_BIT|R128_FOG_BIT|R128_TEX0_BIT] = rs_gft0; - setup_func[R128_RGBA_BIT|R128_FOG_BIT|R128_TEX0_BIT|R128_TEX1_BIT] = rs_gft0t1; - setup_func[R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT|R128_TEX0_BIT] = rs_gfst0; - setup_func[R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT|R128_TEX0_BIT|R128_TEX1_BIT] = rs_gfst0t1; -} +#define IND (R128_RGBA_BIT) +#define TAG(x) x##_g +#include "tnl_dd/t_dd_vbtmp.h" +#define IND (R128_RGBA_BIT|R128_SPEC_BIT) +#define TAG(x) x##_gs +#include "tnl_dd/t_dd_vbtmp.h" -void r128PrintSetupFlags( char *msg, GLuint flags ) +#define IND (R128_RGBA_BIT|R128_TEX0_BIT) +#define TAG(x) x##_gt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (R128_RGBA_BIT|R128_TEX0_BIT|R128_TEX1_BIT) +#define TAG(x) x##_gt0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (R128_RGBA_BIT|R128_SPEC_BIT|R128_TEX0_BIT) +#define TAG(x) x##_gst0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (R128_RGBA_BIT|R128_SPEC_BIT|R128_TEX0_BIT|R128_TEX1_BIT) +#define TAG(x) x##_gst0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (R128_RGBA_BIT|R128_FOG_BIT) +#define TAG(x) x##_gf +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT) +#define TAG(x) x##_gfs +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (R128_RGBA_BIT|R128_FOG_BIT|R128_TEX0_BIT) +#define TAG(x) x##_gft0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (R128_RGBA_BIT|R128_FOG_BIT|R128_TEX0_BIT|R128_TEX1_BIT) +#define TAG(x) x##_gft0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT|R128_TEX0_BIT) +#define TAG(x) x##_gfst0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT|R128_TEX0_BIT|\ + R128_TEX1_BIT) +#define TAG(x) x##_gfst0t1 +#include "tnl_dd/t_dd_vbtmp.h" + + +static void init_setup_tab( void ) { - fprintf( stderr, "%s: %d %s%s%s%s%s%s\n", - msg, - (int)flags, - (flags & R128_WIN_BIT) ? " xyzw," : "", - (flags & R128_RGBA_BIT) ? " rgba," : "", - (flags & R128_SPEC_BIT) ? " spec," : "", - (flags & R128_FOG_BIT) ? " fog," : "", - (flags & R128_TEX0_BIT) ? " tex-0," : "", - (flags & R128_TEX1_BIT) ? " tex-1," : "" ); + init_wg(); + init_wgs(); + init_wgt0(); + init_wgt0t1(); + init_wgpt0(); + init_wgst0(); + init_wgst0t1(); + init_wgspt0(); + init_wgf(); + init_wgfs(); + init_wgft0(); + init_wgft0t1(); + init_wgfpt0(); + init_wgfst0(); + init_wgfst0t1(); + init_wgfspt0(); + init_t0(); + init_t0t1(); + init_f(); + init_ft0(); + init_ft0t1(); + init_g(); + init_gs(); + init_gt0(); + init_gt0t1(); + init_gst0(); + init_gst0t1(); + init_gf(); + init_gfs(); + init_gft0(); + init_gft0t1(); + init_gfst0(); + init_gfst0t1(); } -/* Initialize the vertex buffer setup functions based on the current - * rendering state. - */ -void r128DDChooseRasterSetupFunc( GLcontext *ctx ) -{ - r128ContextPtr rmesa = R128_CONTEXT(ctx); - GLint index = R128_WIN_BIT | R128_RGBA_BIT; - - rmesa->multitex = 0; - rmesa->vertsize = 8; - rmesa->vc_format = R128_TEX0_VERTEX_FORMAT; - rmesa->tmu_source[0] = 0; - rmesa->tmu_source[1] = 1; - rmesa->tex_dest[0] = R128_TEX0_BIT; - rmesa->tex_dest[1] = R128_TEX1_BIT; - rmesa->blend_flags &= ~R128_BLEND_MULTITEX; - - if ( ctx->Texture.ReallyEnabled & ENABLE_TEX0 ) { - if ( R128_IS_PLAIN( rmesa ) && /* Pro/M3 support GL_BLEND */ - ctx->Texture.Unit[0].EnvMode == GL_BLEND && rmesa->env_color ) { - rmesa->multitex = 1; - rmesa->vertsize = 10; - rmesa->vc_format = R128_TEX1_VERTEX_FORMAT; - rmesa->tmu_source[1] = 0; - index |= R128_TEX1_BIT; - } - index |= R128_TEX0_BIT; - } +void r128PrintSetupFlags(char *msg, GLuint flags ) +{ + fprintf(stderr, "%s(%x): %s%s%s%s%s%s\n", + msg, + (int)flags, + (flags & R128_XYZW_BIT) ? " xyzw," : "", + (flags & R128_RGBA_BIT) ? " rgba," : "", + (flags & R128_SPEC_BIT) ? " spec," : "", + (flags & R128_FOG_BIT) ? " fog," : "", + (flags & R128_TEX0_BIT) ? " tex-0," : "", + (flags & R128_TEX1_BIT) ? " tex-1," : ""); +} - if ( ctx->Texture.ReallyEnabled & ENABLE_TEX1 ) { - if ( ctx->Texture.ReallyEnabled & ENABLE_TEX0 ) { - rmesa->multitex = 1; - rmesa->vertsize = 10; - rmesa->vc_format = R128_TEX1_VERTEX_FORMAT; - if ( R128_IS_PLAIN( rmesa ) ) /* Pro/M3 support GL_BLEND */ - rmesa->blend_flags |= R128_BLEND_MULTITEX; - index |= R128_TEX1_BIT; - } else { - /* Just a funny way of doing single texturing. - */ - rmesa->tmu_source[0] = 1; - rmesa->tex_dest[1] = R128_TEX0_BIT; - - if ( R128_IS_PLAIN( rmesa ) && /* Pro/M3 support GL_BLEND */ - ctx->Texture.Unit[1].EnvMode == GL_BLEND && rmesa->env_color ) { - rmesa->multitex = 1; - rmesa->vertsize = 10; - rmesa->vc_format = R128_TEX1_VERTEX_FORMAT; - rmesa->tmu_source[1] = 1; - index |= R128_TEX1_BIT; - } - - index |= R128_TEX0_BIT; - } - } - if ( ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR ) - index |= R128_SPEC_BIT; - if ( ctx->Fog.Enabled ) - index |= R128_FOG_BIT; +void r128CheckTexSizes( GLcontext *ctx ) +{ + r128ContextPtr rmesa = R128_CONTEXT( ctx ); - if ( R128_DEBUG & DEBUG_VERBOSE_MSG ) { - fprintf( stderr, "\n" ); - r128PrintSetupFlags( "full setup function", index ); - } + if (!setup_tab[rmesa->SetupIndex].check_tex_sizes(ctx)) { + TNLcontext *tnl = TNL_CONTEXT(ctx); - rmesa->new_state |= R128_NEW_TEXTURE; - rmesa->SetupIndex = index; + /* Invalidate stored verts + */ + rmesa->SetupNewInputs = ~0; + rmesa->SetupIndex |= R128_PTEX_BIT; - ctx->Driver.RasterSetup = setup_func[index]; + if (!rmesa->Fallback && + !(ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) { + tnl->Driver.Render.Interp = setup_tab[rmesa->SetupIndex].interp; + tnl->Driver.Render.CopyPV = setup_tab[rmesa->SetupIndex].copy_pv; + } + } } -/* Check to see if any updates of the vertex buffer entries are needed. - */ -void r128DDCheckPartialRasterSetup( GLcontext *ctx, - struct gl_pipeline_stage *s ) +void r128BuildVertices( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint newinputs ) { r128ContextPtr rmesa = R128_CONTEXT( ctx ); - GLint tmp = rmesa->SetupDone; - - s->type = 0; - rmesa->SetupDone = 0; + GLubyte *v = ((GLubyte *)rmesa->verts + (start<<rmesa->vertex_stride_shift)); + GLuint stride = 1<<rmesa->vertex_stride_shift; - if ( (ctx->Array.Summary & VERT_OBJ_ANY) == 0 ) - return; + newinputs |= rmesa->SetupNewInputs; + rmesa->SetupNewInputs = 0; - if ( ctx->IndirectTriangles ) + if (!newinputs) return; - rmesa->SetupDone = tmp; -} + if (newinputs & VERT_CLIP) { + setup_tab[rmesa->SetupIndex].emit( ctx, start, count, v, stride ); + } else { + GLuint ind = 0; -/* Repair existing precalculated vertices with new data. - */ -void r128DDPartialRasterSetup( struct vertex_buffer *VB ) -{ - r128ContextPtr rmesa = R128_CONTEXT(VB->ctx); - GLuint new = VB->pipeline->new_outputs; - GLuint available = VB->pipeline->outputs; - GLuint index = 0; - - if ( new & VERT_WIN ) { - new = available; - index |= R128_WIN_BIT | R128_FOG_BIT; - } + if (newinputs & VERT_RGBA) + ind |= R128_RGBA_BIT; - if ( new & VERT_RGBA ) - index |= R128_RGBA_BIT | R128_SPEC_BIT; + if (newinputs & VERT_SPEC_RGB) + ind |= R128_SPEC_BIT; - if ( new & VERT_TEX0_ANY ) - index |= R128_TEX0_BIT; + if (newinputs & VERT_TEX0) + ind |= R128_TEX0_BIT; - if ( new & VERT_TEX1_ANY ) - index |= rmesa->tex_dest[1]; + if (newinputs & VERT_TEX1) + ind |= R128_TEX1_BIT; - if ( new & VERT_FOG_COORD ) - index |= R128_FOG_BIT; + if (newinputs & VERT_FOG_COORD) + ind |= R128_FOG_BIT; - rmesa->SetupDone &= ~index; - index &= rmesa->SetupIndex; - rmesa->SetupDone |= index; + if (rmesa->SetupIndex & R128_PTEX_BIT) + ind = ~0; - if ( R128_DEBUG & DEBUG_VERBOSE_MSG ) - r128PrintSetupFlags( "partial setup function", index ); + ind &= rmesa->SetupIndex; - if ( index ) - setup_func[index]( VB, VB->Start, VB->Count ); + if (ind) { + setup_tab[ind].emit( ctx, start, count, v, stride ); + } + } } -void r128DDDoRasterSetup( struct vertex_buffer *VB ) +void r128ChooseVertexState( GLcontext *ctx ) { - GLcontext *ctx = VB->ctx; + TNLcontext *tnl = TNL_CONTEXT(ctx); + r128ContextPtr rmesa = R128_CONTEXT( ctx ); + GLuint ind = R128_XYZW_BIT|R128_RGBA_BIT; + + if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) + ind |= R128_SPEC_BIT; - if ( VB->Type == VB_CVA_PRECALC ) { - r128DDPartialRasterSetup( VB ); - } else if ( ctx->Driver.RasterSetup ) { - ctx->Driver.RasterSetup( VB, VB->CopyStart, VB->Count ); + if (ctx->Fog.Enabled) + ind |= R128_FOG_BIT; + + if (ctx->Texture._ReallyEnabled) { + ind |= R128_TEX0_BIT; + if (ctx->Texture.Unit[0]._ReallyEnabled && + ctx->Texture.Unit[1]._ReallyEnabled) + ind |= R128_TEX1_BIT; + } + + rmesa->SetupIndex = ind; + + if (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED)) { + tnl->Driver.Render.Interp = r128_interp_extras; + tnl->Driver.Render.CopyPV = r128_copy_pv_extras; + } else { + tnl->Driver.Render.Interp = setup_tab[ind].interp; + tnl->Driver.Render.CopyPV = setup_tab[ind].copy_pv; + } + + if (setup_tab[ind].vertex_format != rmesa->vertex_format) { + FLUSH_BATCH(rmesa); + rmesa->vertex_format = setup_tab[ind].vertex_format; + rmesa->vertex_size = setup_tab[ind].vertex_size; + rmesa->vertex_stride_shift = setup_tab[ind].vertex_stride_shift; } } -/* ================================================================ - * Hardware-format vertex buffers - */ -void r128DDResizeVB( struct vertex_buffer *VB, GLuint size ) +void r128_emit_contiguous_verts( GLcontext *ctx, + GLuint start, + GLuint count ) { - r128VertexBufferPtr rvb = R128_DRIVER_DATA(VB); + r128ContextPtr rmesa = R128_CONTEXT(ctx); + GLuint vertex_size = rmesa->vertex_size * 4; + GLuint *dest = r128AllocDmaLow( rmesa, (count-start) * vertex_size); + setup_tab[rmesa->SetupIndex].emit( ctx, start, count, dest, vertex_size ); +} - while ( rvb->size < size ) - rvb->size *= 2; - ALIGN_FREE( rvb->vert_store ); - rvb->vert_store = ALIGN_MALLOC( sizeof(r128Vertex) * rvb->size, 32 ); - if ( !rvb->vert_store ) { - fprintf( stderr, "Cannot allocate vertex store! Exiting...\n" ); - exit( 1 ); - } +#if 0 +void r128_emit_indexed_verts( GLcontext *ctx, GLuint start, GLuint count ) +{ + r128ContextPtr rmesa = R128_CONTEXT(ctx); + GLuint vertex_size = rmesa->vertex_size * 4; + GLuint bufsz = (count-start) * vertex_size; + CARD32 *dest; - rvb->verts = (r128VertexPtr)rvb->vert_store; + rmesa->vertex_low = (rmesa->vertex_low + 63) & ~63; /* alignment */ + rmesa->vertex_last_prim = rmesa->vertex_low; - gl_vector1ui_free( &rvb->clipped_elements ); - gl_vector1ui_alloc( &rvb->clipped_elements, VEC_WRITABLE, rvb->size, 32 ); - if ( !rvb->clipped_elements.start ) { - fprintf( stderr, "Cannot allocate clipped elements! Exiting...\n" ); - exit( 1 ); - } + dest = r128AllocDmaLow( rmesa, bufsz, __FUNCTION__); + setup_tab[rmesa->SetupIndex].emit( ctx, start, count, dest, vertex_size ); - ALIGN_FREE( VB->ClipMask ); - VB->ClipMask = (GLubyte *)ALIGN_MALLOC( sizeof(GLubyte) * rvb->size, 32 ); - if ( !VB->ClipMask ) { - fprintf( stderr, "Cannot allocate clipmask! Exiting...\n" ); - exit( 1 ); - } + rmesa->retained_buffer = rmesa->vertex_buffer; + rmesa->vb_offset = (rmesa->vertex_buffer->idx * R128_BUFFER_SIZE + + rmesa->vertex_low - bufsz); + + rmesa->vertex_low = (rmesa->vertex_low + 0x7) & ~0x7; /* alignment */ + rmesa->vertex_last_prim = rmesa->vertex_low; } +#endif + -void r128DDRegisterVB( struct vertex_buffer *VB ) +void r128InitVB( GLcontext *ctx ) { - r128VertexBufferPtr rvb; + r128ContextPtr rmesa = R128_CONTEXT(ctx); + GLuint size = TNL_CONTEXT(ctx)->vb.Size; - rvb = (r128VertexBufferPtr)CALLOC( sizeof(*rvb) ); + rmesa->verts = (char *)ALIGN_MALLOC(size * 4 * 16, 32); - rvb->size = VB->Size * 2; - rvb->vert_store = ALIGN_MALLOC( sizeof(r128Vertex) * rvb->size, 32 ); - if ( !rvb->vert_store ) { - fprintf( stderr, "Cannot allocate vertex store! Exiting...\n" ); - exit( 1 ); + { + static int firsttime = 1; + if (firsttime) { + init_setup_tab(); + firsttime = 0; + } } +} - rvb->verts = (r128VertexPtr)rvb->vert_store; - - gl_vector1ui_alloc( &rvb->clipped_elements, VEC_WRITABLE, rvb->size, 32 ); - if ( !rvb->clipped_elements.start ) { - fprintf( stderr, "Cannot allocate clipped elements! Exiting...\n" ); - exit( 1 ); - } - ALIGN_FREE( VB->ClipMask ); - VB->ClipMask = (GLubyte *)ALIGN_MALLOC( sizeof(GLubyte) * rvb->size, 32 ); - if ( !VB->ClipMask ) { - fprintf( stderr, "Cannot allocate clipmask! Exiting...\n" ); - exit( 1 ); +void r128FreeVB( GLcontext *ctx ) +{ + r128ContextPtr rmesa = R128_CONTEXT(ctx); + if (rmesa->verts) { + ALIGN_FREE(rmesa->verts); + rmesa->verts = 0; } - VB->driver_data = rvb; -} -void r128DDUnregisterVB( struct vertex_buffer *VB ) -{ - r128VertexBufferPtr rvb = R128_DRIVER_DATA(VB); + if (rmesa->UbyteSecondaryColor.Ptr) { + ALIGN_FREE(rmesa->UbyteSecondaryColor.Ptr); + rmesa->UbyteSecondaryColor.Ptr = 0; + } - if ( rvb ) { - if ( rvb->vert_store ) ALIGN_FREE( rvb->vert_store ); - gl_vector1ui_free( &rvb->clipped_elements ); - FREE( rvb ); - VB->driver_data = 0; + if (rmesa->UbyteColor.Ptr) { + ALIGN_FREE(rmesa->UbyteColor.Ptr); + rmesa->UbyteColor.Ptr = 0; } } diff --git a/xc/lib/GL/mesa/src/drv/r200/r200_context.c b/xc/lib/GL/mesa/src/drv/r200/r200_context.c index ec5418430..a29f597fa 100644 --- a/xc/lib/GL/mesa/src/drv/r200/r200_context.c +++ b/xc/lib/GL/mesa/src/drv/r200/r200_context.c @@ -647,7 +647,7 @@ r200MakeCurrent( __DRIcontextPrivate *driContextPriv, } else { if (R200_DEBUG & DEBUG_DRI) - fprintf(stderr, "%s ctx %p\n", __FUNCTION__, NULL); + fprintf(stderr, "%s ctx is null\n", __FUNCTION__); _mesa_make_current( 0, 0 ); } diff --git a/xc/lib/GL/mesa/src/drv/r200/r200_swtcl.c b/xc/lib/GL/mesa/src/drv/r200/r200_swtcl.c index 3c6e53979..ec26785bd 100644 --- a/xc/lib/GL/mesa/src/drv/r200/r200_swtcl.c +++ b/xc/lib/GL/mesa/src/drv/r200/r200_swtcl.c @@ -141,6 +141,7 @@ static int se_vtx_fmt_1[] = { #define DO_PTEX (IND & R200_PTEX_BIT) #define VERTEX r200Vertex +#define VERTEX_COLOR r200_color_t #define GET_VIEWPORT_MAT() 0 #define GET_TEXSOURCE(n) n #define GET_VERTEX_FORMAT() R200_CONTEXT(ctx)->swtcl.vertex_format @@ -848,6 +849,10 @@ static struct { #define VERT_SAVE_SPEC( idx ) if (havespec) spec[idx] = v[idx]->ui[5] #define VERT_RESTORE_SPEC( idx ) if (havespec) v[idx]->ui[5] = spec[idx] +#undef LOCAL_VARS +#undef TAG +#undef INIT + #define LOCAL_VARS(n) \ r200ContextPtr rmesa = R200_CONTEXT(ctx); \ GLuint color[n], spec[n]; \ diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_context.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_context.c index 55ac23d0b..7674d5089 100644 --- a/xc/lib/GL/mesa/src/drv/radeon/radeon_context.c +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_context.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_context.c,v 1.2 2001/03/21 16:14:24 dawes Exp $ */ +/* $XFree86$ */ /************************************************************************** Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and @@ -31,6 +31,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. * Authors: * Kevin E. Martin <martin@valinux.com> * Gareth Hughes <gareth@valinux.com> + * Keith Whitwell <keith@tungstengraphics.com> * */ @@ -38,199 +39,529 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "radeon_context.h" #include "radeon_ioctl.h" -#include "radeon_dd.h" #include "radeon_state.h" #include "radeon_span.h" #include "radeon_tex.h" -#include "radeon_vb.h" -#include "radeon_pipeline.h" +#include "radeon_swtcl.h" +#include "radeon_tcl.h" +#include "radeon_vtxfmt.h" +#include "radeon_maos.h" +#include "swrast/swrast.h" +#include "swrast_setup/swrast_setup.h" +#include "array_cache/acache.h" + +#include "tnl/tnl.h" +#include "tnl/t_pipeline.h" + +#include "attrib.h" +#include "api_arrayelt.h" #include "context.h" #include "simple_list.h" #include "mem.h" +#include "matrix.h" +#include "extensions.h" +#if defined(USE_X86_ASM) +#include "X86/common_x86_asm.h" +#endif + +#define RADEON_DATE "20020611" #ifndef RADEON_DEBUG -int RADEON_DEBUG = (0 -/* | DEBUG_ALWAYS_SYNC */ -/* | DEBUG_VERBOSE_API */ -/* | DEBUG_VERBOSE_MSG */ -/* | DEBUG_VERBOSE_LRU */ -/* | DEBUG_VERBOSE_DRI */ -/* | DEBUG_VERBOSE_IOCTL */ -/* | DEBUG_VERBOSE_2D */ -/* | DEBUG_VERBOSE_TEXTURE */ - ); +int RADEON_DEBUG = (0); #endif -#ifdef PER_CONTEXT_SAREA -char *radeonGetPerContextSAREA(int fd, - drmContext hHWContext, - drmSize size) + + +/* Return the width and height of the given buffer. + */ +static void radeonGetBufferSize( GLframebuffer *buffer, + GLuint *width, GLuint *height ) { - drmHandle handle; - drmAddress address; + GET_CURRENT_CONTEXT(ctx); + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - if(drmGetContextPrivateMapping(fd, hHWContext, &handle) < 0) { - return NULL; - } - if(drmMap(fd, handle, size, &address) < 0) { + LOCK_HARDWARE( rmesa ); + *width = rmesa->dri.drawable->w; + *height = rmesa->dri.drawable->h; + UNLOCK_HARDWARE( rmesa ); +} + +/* Return various strings for glGetString(). + */ +static const GLubyte *radeonGetString( GLcontext *ctx, GLenum name ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + static char buffer[128]; + + switch ( name ) { + case GL_VENDOR: + return (GLubyte *)"Tungsten Graphics, Inc."; + + case GL_RENDERER: + sprintf( buffer, "Mesa DRI Radeon " RADEON_DATE); + + /* Append any chipset-specific information. None yet. + */ + + /* Append any AGP-specific information. + */ + switch ( rmesa->radeonScreen->AGPMode ) { + case 1: + strncat( buffer, " AGP 1x", 7 ); + break; + case 2: + strncat( buffer, " AGP 2x", 7 ); + break; + case 4: + strncat( buffer, " AGP 4x", 7 ); + break; + } + + /* Append any CPU-specific information. + */ +#ifdef USE_X86_ASM + if ( _mesa_x86_cpu_features ) { + strncat( buffer, " x86", 4 ); + } +#ifdef USE_MMX_ASM + if ( cpu_has_mmx ) { + strncat( buffer, "/MMX", 4 ); + } +#endif +#ifdef USE_3DNOW_ASM + if ( cpu_has_3dnow ) { + strncat( buffer, "/3DNow!", 7 ); + } +#endif +#ifdef USE_SSE_ASM + if ( cpu_has_xmm ) { + strncat( buffer, "/SSE", 4 ); + } +#endif +#endif + + if ( rmesa->dri.drmMinor < RADEON_DRM_CURRENT ) { + strncat( buffer, " DRM-COMPAT", 11 ); + } + + if ( !(rmesa->TclFallback & RADEON_TCL_FALLBACK_TCL_DISABLE) ) { + strncat( buffer, " TCL", 4 ); + } + else { + strncat( buffer, " NO-TCL", 7 ); + } + + return (GLubyte *)buffer; + + default: return NULL; } - - return address; } -#endif -/* Create the device specific context. + + +/* Initialize the extensions supported by this driver. */ -GLboolean radeonCreateContext( Display *dpy, GLvisual *glVisual, - __DRIcontextPrivate *driContextPriv ) +static void radeonInitExtensions( GLcontext *ctx ) { - GLcontext *ctx = driContextPriv->mesaContext; - __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv; - radeonContextPtr rmesa; - radeonScreenPtr radeonScreen; - int i; + _mesa_enable_imaging_extensions( ctx ); + + _mesa_enable_extension( ctx, "GL_ARB_multitexture" ); + _mesa_enable_extension( ctx, "GL_ARB_texture_env_add" ); + _mesa_enable_extension( ctx, "GL_ARB_texture_env_combine" ); + + _mesa_enable_extension( ctx, "GL_EXT_blend_logic_op" ); + _mesa_enable_extension( ctx, "GL_EXT_texture_env_add" ); + _mesa_enable_extension( ctx, "GL_EXT_texture_env_combine" ); + _mesa_enable_extension( ctx, "GL_EXT_texture_env_dot3" ); + _mesa_enable_extension( ctx, "GL_EXT_texture_filter_anisotropic" ); + _mesa_enable_extension( ctx, "GL_EXT_texture_lod_bias" ); + +/* _mesa_enable_extension( ctx, "GL_EXT_fog_coord" ); */ + _mesa_enable_extension( ctx, "GL_EXT_secondary_color" ); + _mesa_enable_extension( ctx, "GL_EXT_blend_subtract" ); +} - rmesa = (radeonContextPtr) CALLOC( sizeof(*rmesa) ); - if ( !rmesa ) return GL_FALSE; +extern const struct gl_pipeline_stage _radeon_render_stage; +extern const struct gl_pipeline_stage _radeon_tcl_stage; - rmesa->glCtx = ctx; - rmesa->display = dpy; +static const struct gl_pipeline_stage *radeon_pipeline[] = { - rmesa->driContext = driContextPriv; - rmesa->driScreen = sPriv; - rmesa->driDrawable = NULL; /* Set by XMesaMakeCurrent */ + /* Try and go straight to t&l + */ + &_radeon_tcl_stage, + + /* Catch any t&l fallbacks + */ + &_tnl_vertex_transform_stage, + &_tnl_normal_transform_stage, + &_tnl_lighting_stage, + &_tnl_fog_coordinate_stage, + &_tnl_texgen_stage, + &_tnl_texture_transform_stage, + + /* Try again to go to tcl? + * - no good for asymmetric-twoside (do with multipass) + * - no good for asymmetric-unfilled (do with multipass) + * - good for material + * - good for texgen + * - need to manipulate a bit of state + * + * - worth it/not worth it? + */ + + /* Else do them here. + */ + &_radeon_render_stage, + &_tnl_render_stage, /* FALLBACK: */ + 0, +}; - rmesa->hHWContext = driContextPriv->hHWContext; - rmesa->driHwLock = &sPriv->pSAREA->lock; - rmesa->driFd = sPriv->fd; - radeonScreen = rmesa->radeonScreen = (radeonScreenPtr)(sPriv->private); - rmesa->sarea = (RADEONSAREAPrivPtr)((char *)sPriv->pSAREA + - radeonScreen->sarea_priv_offset); +/* Initialize the driver's misc functions. + */ +static void radeonInitDriverFuncs( GLcontext *ctx ) +{ + ctx->Driver.GetBufferSize = radeonGetBufferSize; + ctx->Driver.ResizeBuffers = _swrast_alloc_buffers; + ctx->Driver.GetString = radeonGetString; -#ifdef PER_CONTEXT_SAREA - rmesa->private_sarea = radeonGetPerContextSAREA(rmesa->driFd, - rmesa->hHWContext, - radeonScreen->private_sarea_size); - if(!rmesa->private_sarea) { - fprintf(stderr, "Can't map private SAREA\n"); - FREE( rmesa ); + ctx->Driver.Error = NULL; + ctx->Driver.DrawPixels = NULL; + ctx->Driver.Bitmap = NULL; +} + + + +/* Create the device specific context. + */ +static GLboolean +radeonCreateContext( Display *dpy, const __GLcontextModes *glVisual, + __DRIcontextPrivate *driContextPriv, + void *sharedContextPrivate) +{ + __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv; + radeonScreenPtr radeonScreen = (radeonScreenPtr)(sPriv->private); + radeonContextPtr rmesa; + GLcontext *ctx, *shareCtx; + int i; + + assert(dpy); + assert(glVisual); + assert(driContextPriv); + assert(radeonScreen); + + /* Allocate the Radeon context */ + rmesa = (radeonContextPtr) CALLOC( sizeof(*rmesa) ); + if ( !rmesa ) return GL_FALSE; - } -#endif - rmesa->tmp_matrix = (GLfloat *) ALIGN_MALLOC( 16 * sizeof(GLfloat), 16 ); - if ( !rmesa->tmp_matrix ) { - FREE( rmesa ); + /* Allocate the Mesa context */ + if (sharedContextPrivate) + shareCtx = ((radeonContextPtr) sharedContextPrivate)->glCtx; + else + shareCtx = NULL; + rmesa->glCtx = _mesa_create_context(glVisual, shareCtx, rmesa, GL_TRUE); + if (!rmesa->glCtx) { + FREE(rmesa); return GL_FALSE; } + driContextPriv->driverPrivate = rmesa; + + /* Init radeon context data */ + rmesa->dri.display = dpy; + rmesa->dri.context = driContextPriv; + rmesa->dri.screen = sPriv; + rmesa->dri.drawable = NULL; /* Set by XMesaMakeCurrent */ + rmesa->dri.hwContext = driContextPriv->hHWContext; + rmesa->dri.hwLock = &sPriv->pSAREA->lock; + rmesa->dri.fd = sPriv->fd; + + /* If we don't have 1.3, fallback to the 1.1 interfaces. + */ + if (getenv("RADEON_COMPAT") || sPriv->drmMinor < RADEON_DRM_CURRENT) + rmesa->dri.drmMinor = 1; + else + rmesa->dri.drmMinor = sPriv->drmMinor; + + rmesa->radeonScreen = radeonScreen; + rmesa->sarea = (RADEONSAREAPrivPtr)((GLubyte *)sPriv->pSAREA + + radeonScreen->sarea_priv_offset); + - make_empty_list( &rmesa->SwappedOut ); + rmesa->dma.buf0_address = rmesa->radeonScreen->buffers->list[0].address; for ( i = 0 ; i < radeonScreen->numTexHeaps ; i++ ) { - rmesa->CurrentTexObj[i] = NULL; - make_empty_list( &rmesa->TexObjList[i] ); - rmesa->texHeap[i] = mmInit( 0, radeonScreen->texSize[i] ); - rmesa->lastTexAge[i] = -1; + make_empty_list( &rmesa->texture.objects[i] ); + rmesa->texture.heap[i] = mmInit( 0, radeonScreen->texSize[i] ); + rmesa->texture.age[i] = -1; } - rmesa->lastTexHeap = radeonScreen->numTexHeaps; - - rmesa->RenderIndex = -1; /* Impossible value */ - rmesa->OnFastPath = 0; + rmesa->texture.numHeaps = radeonScreen->numTexHeaps; + make_empty_list( &rmesa->texture.swapped ); - rmesa->vert_buf = NULL; - rmesa->num_verts = 0; - - rmesa->elt_buf = NULL; - rmesa->retained_buf = NULL; - rmesa->vert_heap = radeonScreen->buffers->list->address; + rmesa->swtcl.RenderIndex = ~0; + rmesa->lost_context = 1; /* KW: Set the maximum texture size small enough that we can * guarentee that both texture units can bind a maximal texture - * and have them both in on-card memory at once. (Kevin or - * Gareth: Please check these numbers are OK) + * and have them both in on-card memory at once. + * Test for 2 textures * 4 bytes/texel * size * size. */ - if ( radeonScreen->texSize[0] < 2*1024*1024 ) { - ctx->Const.MaxTextureLevels = 9; - ctx->Const.MaxTextureSize = (1 << 8); - } else if ( radeonScreen->texSize[0] < 8*1024*1024 ) { - ctx->Const.MaxTextureLevels = 10; - ctx->Const.MaxTextureSize = (1 << 9); - } else { - ctx->Const.MaxTextureLevels = 11; - ctx->Const.MaxTextureSize = (1 << 10); + ctx = rmesa->glCtx; + if (radeonScreen->texSize[RADEON_CARD_HEAP] >= 2 * 4 * 2048 * 2048) { + ctx->Const.MaxTextureLevels = 12; /* 2048x2048 */ + } + else if (radeonScreen->texSize[RADEON_CARD_HEAP] >= 2 * 4 * 1024 * 1024) { + ctx->Const.MaxTextureLevels = 11; /* 1024x1024 */ + } + else if (radeonScreen->texSize[RADEON_CARD_HEAP] >= 2 * 4 * 512 * 512) { + ctx->Const.MaxTextureLevels = 10; /* 512x512 */ + } + else { + ctx->Const.MaxTextureLevels = 9; /* 256x256 */ } ctx->Const.MaxTextureUnits = 2; + ctx->Const.MaxTextureMaxAnisotropy = 16.0; + + /* No wide points. + */ + ctx->Const.MinPointSize = 1.0; + ctx->Const.MinPointSizeAA = 1.0; + ctx->Const.MaxPointSize = 1.0; + ctx->Const.MaxPointSizeAA = 1.0; + + ctx->Const.MinLineWidth = 1.0; + ctx->Const.MinLineWidthAA = 1.0; + ctx->Const.MaxLineWidth = 10.0; + ctx->Const.MaxLineWidthAA = 10.0; + ctx->Const.LineWidthGranularity = 0.0625; + + /* Set maxlocksize (and hence vb size) small enough to avoid + * fallbacks in radeon_tcl.c. ie. guarentee that all vertices can + * fit in a single dma buffer for indexed rendering of quad strips, + * etc. + */ +/* ctx->Const.MaxArrayLockSize = */ +/* MIN2( ctx->Const.MaxArrayLockSize, */ +/* RADEON_BUFFER_SIZE / RADEON_MAX_TCL_VERTSIZE ); */ + + if (getenv("LIBGL_PERFORMANCE_BOXES")) + rmesa->boxes = 1; + else + rmesa->boxes = 0; - ctx->DriverCtx = (void *)rmesa; - radeonDDInitExtensions( ctx ); + /* Initialize the software rasterizer and helper modules. + */ + _swrast_CreateContext( ctx ); + _ac_CreateContext( ctx ); + _tnl_CreateContext( ctx ); + _swsetup_CreateContext( ctx ); + _ae_create_context( ctx ); + + /* Install the customized pipeline: + */ + _tnl_destroy_pipeline( ctx ); + _tnl_install_pipeline( ctx, radeon_pipeline ); + + /* Try and keep materials and vertices separate: + */ + _tnl_isolate_materials( ctx, GL_TRUE ); - radeonDDInitDriverFuncs( ctx ); - radeonDDInitIoctlFuncs( ctx ); - radeonDDInitStateFuncs( ctx ); - radeonDDInitSpanFuncs( ctx ); - radeonDDInitTextureFuncs( ctx ); - ctx->Driver.TriangleCaps = (DD_TRI_CULL | - DD_TRI_LIGHT_TWOSIDE | - DD_TRI_STIPPLE | - DD_TRI_OFFSET); +/* _mesa_allow_light_in_model( ctx, GL_FALSE ); */ - /* Ask Mesa to clip fog coordinates for us. + /* Configure swrast to match hardware characteristics: */ - ctx->TriangleCaps |= DD_CLIP_FOG_COORD; + _swrast_allow_pixel_fog( ctx, GL_FALSE ); + _swrast_allow_vertex_fog( ctx, GL_TRUE ); + + + _math_matrix_ctr( &rmesa->TexGenMatrix[0] ); + _math_matrix_ctr( &rmesa->TexGenMatrix[1] ); + _math_matrix_ctr( &rmesa->tmpmat ); + _math_matrix_set_identity( &rmesa->TexGenMatrix[0] ); + _math_matrix_set_identity( &rmesa->TexGenMatrix[1] ); + _math_matrix_set_identity( &rmesa->tmpmat ); + + radeonInitExtensions( ctx ); + radeonInitDriverFuncs( ctx ); + radeonInitIoctlFuncs( ctx ); + radeonInitStateFuncs( ctx ); + radeonInitSpanFuncs( ctx ); + radeonInitTextureFuncs( ctx ); + radeonInitState( rmesa ); + radeonInitSwtcl( ctx ); + + + +#if DO_DEBUG + if (getenv("RADEON_DEBUG_FALLBACKS")) + RADEON_DEBUG |= DEBUG_FALLBACKS; + + if (getenv("RADEON_DEBUG_TEXTURE")) + RADEON_DEBUG |= DEBUG_TEXTURE; + + if (getenv("RADEON_DEBUG_IOCTL")) + RADEON_DEBUG |= DEBUG_IOCTL; + + if (getenv("RADEON_DEBUG_PRIMS")) + RADEON_DEBUG |= DEBUG_PRIMS; + + if (getenv("RADEON_DEBUG_VERTS")) + RADEON_DEBUG |= DEBUG_VERTS; + + if (getenv("RADEON_DEBUG_STATE")) + RADEON_DEBUG |= DEBUG_STATE; + + if (getenv("RADEON_DEBUG_CODEGEN")) + RADEON_DEBUG |= DEBUG_CODEGEN; + + if (getenv("RADEON_DEBUG_VTXFMT")) + RADEON_DEBUG |= DEBUG_VFMT; - if ( ctx->VB ) - radeonDDRegisterVB( ctx->VB ); + if (getenv("RADEON_DEBUG_VERBOSE")) + RADEON_DEBUG |= DEBUG_VERBOSE; - if ( ctx->NrPipelineStages ) { - ctx->NrPipelineStages = - radeonDDRegisterPipelineStages( ctx->PipelineStage, - ctx->PipelineStage, - ctx->NrPipelineStages ); + if (getenv("RADEON_DEBUG_DRI")) + RADEON_DEBUG |= DEBUG_DRI; + + if (getenv("RADEON_DEBUG_DMA")) + RADEON_DEBUG |= DEBUG_DMA; + + if (getenv("RADEON_DEBUG_SANITY")) + RADEON_DEBUG |= DEBUG_SANITY; + + if (getenv("RADEON_DEBUG")) + { + const char *debug = getenv("RADEON_DEBUG"); + if (strstr(debug, "fall")) + RADEON_DEBUG |= DEBUG_FALLBACKS; + + if (strstr(debug, "tex")) + RADEON_DEBUG |= DEBUG_TEXTURE; + + if (strstr(debug, "ioctl")) + RADEON_DEBUG |= DEBUG_IOCTL; + + if (strstr(debug, "prim")) + RADEON_DEBUG |= DEBUG_PRIMS; + + if (strstr(debug, "vert")) + RADEON_DEBUG |= DEBUG_VERTS; + + if (strstr(debug, "state")) + RADEON_DEBUG |= DEBUG_STATE; + + if (strstr(debug, "code")) + RADEON_DEBUG |= DEBUG_CODEGEN; + + if (strstr(debug, "vfmt") || strstr(debug, "vtxf")) + RADEON_DEBUG |= DEBUG_VFMT; + + if (strstr(debug, "verb")) + RADEON_DEBUG |= DEBUG_VERBOSE; + + if (strstr(debug, "dri")) + RADEON_DEBUG |= DEBUG_DRI; + + if (strstr(debug, "dma")) + RADEON_DEBUG |= DEBUG_DMA; + + if (strstr(debug, "san")) + RADEON_DEBUG |= DEBUG_SANITY; } - radeonDDInitState( rmesa ); - driContextPriv->driverPrivate = (void *)rmesa; +#endif + + if (getenv("RADEON_NO_RAST")) { + fprintf(stderr, "disabling 3D acceleration\n"); + FALLBACK(rmesa, RADEON_FALLBACK_DISABLE, 1); + } + else if (getenv("RADEON_NO_TCL") || + rmesa->radeonScreen->chipset == RADEON_CHIPSET_MOBILITY || + rmesa->dri.drmMinor < RADEON_DRM_CURRENT) { + fprintf(stderr, "disabling TCL support\n"); + TCL_FALLBACK(rmesa->glCtx, RADEON_TCL_FALLBACK_TCL_DISABLE, 1); + } + else { + if (!getenv("RADEON_NO_VTXFMT")) + radeonVtxfmtInit( ctx ); + _tnl_need_dlist_norm_lengths( ctx, GL_FALSE ); + } return GL_TRUE; } + /* Destroy the device specific context. */ -void radeonDestroyContext( radeonContextPtr rmesa ) +/* Destroy the Mesa and driver specific context data. + */ +static void +radeonDestroyContext( __DRIcontextPrivate *driContextPriv ) { + GET_CURRENT_CONTEXT(ctx); + radeonContextPtr rmesa = (radeonContextPtr) driContextPriv->driverPrivate; + radeonContextPtr current = ctx ? RADEON_CONTEXT(ctx) : NULL; + + /* check if we're deleting the currently bound context */ + if (rmesa == current) { + _mesa_make_current2(NULL, NULL, NULL); + } + + /* Free radeon context resources */ + assert(rmesa); /* should never be null */ if ( rmesa ) { - radeonScreenPtr radeonScreen = rmesa->radeonScreen; - radeonTexObjPtr t, next_t; - int i; - -#ifdef PER_CONTEXT_SAREA - if ( rmesa->private_sarea ) { - drmUnmap( (drmAddress)rmesa->private_sarea, - radeonScreen->private_sarea_size ); - rmesa->private_sarea = NULL; + if (rmesa->glCtx->Shared->RefCount == 1) { + /* This share group is about to go away, free our private + * texture object data. + */ + radeonTexObjPtr t, next_t; + int i; + + for ( i = 0 ; i < rmesa->texture.numHeaps ; i++ ) { + foreach_s ( t, next_t, &rmesa->texture.objects[i] ) { + radeonDestroyTexObj( rmesa, t ); + } + mmDestroy( rmesa->texture.heap[i] ); + } + + foreach_s ( t, next_t, &rmesa->texture.swapped ) { + radeonDestroyTexObj( rmesa, t ); + } } -#endif - for ( i = 0 ; i < radeonScreen->numTexHeaps ; i++ ) { - foreach_s ( t, next_t, &rmesa->TexObjList[i] ) { - radeonDestroyTexObj( rmesa, t ); - } - mmDestroy( rmesa->texHeap[i] ); - } + _swsetup_DestroyContext( rmesa->glCtx ); + _tnl_DestroyContext( rmesa->glCtx ); + _ac_DestroyContext( rmesa->glCtx ); + _swrast_DestroyContext( rmesa->glCtx ); + + radeonDestroySwtcl( rmesa->glCtx ); + + radeonReleaseArrays( rmesa->glCtx, ~0 ); + if (rmesa->dma.current.buf) + radeonReleaseDmaRegion( rmesa, &rmesa->dma.current, __FUNCTION__ ); + + RADEON_FIREVERTICES( rmesa ); + + if (!rmesa->TclFallback & RADEON_TCL_FALLBACK_TCL_DISABLE) + if (!getenv("RADEON_NO_VTXFMT")) + radeonVtxfmtDestroy( rmesa->glCtx ); - foreach_s ( t, next_t, &rmesa->SwappedOut ) { - radeonDestroyTexObj( rmesa, t ); + /* free the Mesa context */ + rmesa->glCtx->DriverCtx = NULL; + _mesa_destroy_context( rmesa->glCtx ); + + if (rmesa->state.scissor.pClipRects) { + FREE(rmesa->state.scissor.pClipRects); + rmesa->state.scissor.pClipRects = 0; } - ALIGN_FREE( rmesa->tmp_matrix ); FREE( rmesa ); } @@ -240,27 +571,196 @@ void radeonDestroyContext( radeonContextPtr rmesa ) #endif } -/* Load the device specific context into the hardware. The actual - * setting of the hardware state is done in the radeonUpdateHWState(). + +/* Initialize the driver specific screen private data. + */ +static GLboolean +radeonInitDriver( __DRIscreenPrivate *sPriv ) +{ + sPriv->private = (void *) radeonCreateScreen( sPriv ); + if ( !sPriv->private ) { + radeonDestroyScreen( sPriv ); + return GL_FALSE; + } + + return GL_TRUE; +} + + +/* Create and initialize the Mesa and driver specific pixmap buffer + * data. + */ +static GLboolean +radeonCreateBuffer( Display *dpy, + __DRIscreenPrivate *driScrnPriv, + __DRIdrawablePrivate *driDrawPriv, + const __GLcontextModes *mesaVis, + GLboolean isPixmap ) +{ + if (isPixmap) { + return GL_FALSE; /* not implemented */ + } + else { + const GLboolean swDepth = GL_FALSE; + const GLboolean swAlpha = GL_FALSE; + const GLboolean swAccum = mesaVis->accumRedBits > 0; + const GLboolean swStencil = mesaVis->stencilBits > 0 && + mesaVis->depthBits != 24; + driDrawPriv->driverPrivate = (void *) + _mesa_create_framebuffer( mesaVis, + swDepth, + swStencil, + swAccum, + swAlpha ); + return (driDrawPriv->driverPrivate != NULL); + } +} + + +static void +radeonDestroyBuffer(__DRIdrawablePrivate *driDrawPriv) +{ + _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate)); +} + + + +static void +radeonSwapBuffers(Display *dpy, void *drawablePrivate) +{ + __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePrivate; + (void) dpy; + + if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) { + radeonContextPtr rmesa; + GLcontext *ctx; + rmesa = (radeonContextPtr) dPriv->driContextPriv->driverPrivate; + ctx = rmesa->glCtx; + if (ctx->Visual.doubleBufferMode) { + _mesa_swapbuffers( ctx ); /* flush pending rendering comands */ + if ( rmesa->doPageFlip ) { + radeonPageFlip( dPriv ); + } + else { + radeonCopyBuffer( dPriv ); + } + } + } + else { + /* XXX this shouldn't be an error but we can't handle it for now */ + _mesa_problem(NULL, "radeonSwapBuffers: drawable has no context!\n"); + } +} + + +/* Force the context `c' to be the current context and associate with it + * buffer `b'. */ -radeonContextPtr radeonMakeCurrent( radeonContextPtr oldCtx, - radeonContextPtr newCtx, - __DRIdrawablePrivate *dPriv ) +static GLboolean +radeonMakeCurrent( __DRIcontextPrivate *driContextPriv, + __DRIdrawablePrivate *driDrawPriv, + __DRIdrawablePrivate *driReadPriv ) { - if ( oldCtx ) { - if ( oldCtx != newCtx ) { - newCtx->new_state |= RADEON_NEW_CONTEXT; - newCtx->dirty = RADEON_UPLOAD_ALL; + if ( driContextPriv ) { + radeonContextPtr newRadeonCtx = + (radeonContextPtr) driContextPriv->driverPrivate; + + if (RADEON_DEBUG & DEBUG_DRI) + fprintf(stderr, "%s ctx %p\n", __FUNCTION__, newRadeonCtx->glCtx); + + if ( newRadeonCtx->dri.drawable != driDrawPriv ) { + newRadeonCtx->dri.drawable = driDrawPriv; + radeonUpdateWindow( newRadeonCtx->glCtx ); + radeonUpdateViewportOffset( newRadeonCtx->glCtx ); } - if ( oldCtx->driDrawable != dPriv ) { - newCtx->new_state |= RADEON_NEW_WINDOW | RADEON_NEW_CLIP; + + _mesa_make_current2( newRadeonCtx->glCtx, + (GLframebuffer *) driDrawPriv->driverPrivate, + (GLframebuffer *) driReadPriv->driverPrivate ); + + if ( !newRadeonCtx->glCtx->Viewport.Width ) { + _mesa_set_viewport( newRadeonCtx->glCtx, 0, 0, + driDrawPriv->w, driDrawPriv->h ); } + + if (newRadeonCtx->vb.enabled) + radeonVtxfmtMakeCurrent( newRadeonCtx->glCtx ); + } else { - newCtx->new_state |= RADEON_NEW_CONTEXT; - newCtx->dirty = RADEON_UPLOAD_ALL; + if (RADEON_DEBUG & DEBUG_DRI) + fprintf(stderr, "%s ctx %p\n", __FUNCTION__, NULL); + _mesa_make_current( 0, 0 ); } - newCtx->driDrawable = dPriv; + if (RADEON_DEBUG & DEBUG_DRI) + fprintf(stderr, "End %s\n", __FUNCTION__); + return GL_TRUE; +} + +/* Force the context `c' to be unbound from its buffer. + */ +static GLboolean +radeonUnbindContext( __DRIcontextPrivate *driContextPriv ) +{ + radeonContextPtr rmesa = (radeonContextPtr) driContextPriv->driverPrivate; - return newCtx; + if (RADEON_DEBUG & DEBUG_DRI) + fprintf(stderr, "%s ctx %p\n", __FUNCTION__, rmesa->glCtx); + + radeonVtxfmtUnbindContext( rmesa->glCtx ); + return GL_TRUE; +} + +/* Fullscreen mode isn't used for much -- could be a way to shrink + * front/back buffers & get more texture memory if the client has + * changed the video resolution. + * + * Pageflipping is now done automatically whenever there is a single + * 3d client. + */ +static GLboolean +radeonOpenCloseFullScreen( __DRIcontextPrivate *driContextPriv ) +{ + return GL_TRUE; +} + + + +/* This function is called by libGL.so as soon as libGL.so is loaded. + * This is where we'd register new extension functions with the dispatcher. + */ +void +__driRegisterExtensions( void ) +{ +} + + + +static struct __DriverAPIRec radeonAPI = { + radeonInitDriver, + radeonDestroyScreen, + radeonCreateContext, + radeonDestroyContext, + radeonCreateBuffer, + radeonDestroyBuffer, + radeonSwapBuffers, + radeonMakeCurrent, + radeonUnbindContext, + radeonOpenCloseFullScreen, + radeonOpenCloseFullScreen +}; + + + +/* + * This is the bootstrap function for the driver. + * The __driCreateScreen name is the symbol that libGL.so fetches. + * Return: pointer to a __DRIscreenPrivate. + */ +void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc, + int numConfigs, __GLXvisualConfig *config) +{ + __DRIscreenPrivate *psp; + psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &radeonAPI); + return (void *) psp; } diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.c index 9fda13b76..1d777ce00 100644 --- a/xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.c +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.c @@ -614,13 +614,18 @@ static int radeonWaitForFrameCompletion( radeonContextPtr rmesa ) int i; while ( 1 ) { - drmRadeonGetParam gp; int ret; - gp.param = RADEON_PARAM_LAST_FRAME; - gp.value = (int *)&frame; - ret = drmCommandWriteRead( rmesa->dri.fd, - DRM_RADEON_GETPARAM, &gp, sizeof(gp) ); + if (rmesa->dri.screen->drmMinor >= 4) { + drmRadeonGetParam gp; + + gp.param = RADEON_PARAM_LAST_FRAME; + gp.value = (int *)&frame; + ret = drmCommandWriteRead( rmesa->dri.fd, + DRM_RADEON_GETPARAM, &gp, sizeof(gp) ); + } else + ret = -EINVAL; + if ( ret == -EINVAL ) { frame = INREG( RADEON_LAST_FRAME_REG ); } else if ( ret ) { @@ -835,13 +840,18 @@ static void radeonClear( GLcontext *ctx, GLbitfield mask, GLboolean all, /* Throttle the number of clear ioctls we do. */ while ( 1 ) { - drmRadeonGetParam gp; int ret; - gp.param = RADEON_PARAM_LAST_CLEAR; - gp.value = (int *)&clear; - ret = drmCommandWriteRead( rmesa->dri.fd, - DRM_RADEON_GETPARAM, &gp, sizeof(gp) ); + if (rmesa->dri.screen->drmMinor >= 4) { + drmRadeonGetParam gp; + + gp.param = RADEON_PARAM_LAST_CLEAR; + gp.value = (int *)&clear; + ret = drmCommandWriteRead( rmesa->dri.fd, + DRM_RADEON_GETPARAM, &gp, sizeof(gp) ); + } else + ret = -EINVAL; + if ( ret == -EINVAL ) { clear = INREG( RADEON_LAST_CLEAR_REG ); } else if ( ret ) { diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_span.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_span.c index 917f8aa1d..77fb7c6a9 100644 --- a/xc/lib/GL/mesa/src/drv/radeon/radeon_span.c +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_span.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_span.c,v 1.4 2001/04/10 16:07:53 dawes Exp $ */ +/* $XFree86$ */ /************************************************************************** Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and @@ -31,7 +31,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. * Authors: * Kevin E. Martin <martin@valinux.com> * Gareth Hughes <gareth@valinux.com> - * Keith Whitwell <keithw@valinux.com> + * Keith Whitwell <keith@tungstengraphics.com> * */ @@ -39,22 +39,25 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "radeon_ioctl.h" #include "radeon_state.h" #include "radeon_span.h" +#include "radeon_tex.h" + +#include "swrast/swrast.h" #define DBG 0 #define LOCAL_VARS \ radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \ radeonScreenPtr radeonScreen = rmesa->radeonScreen; \ - __DRIscreenPrivate *sPriv = rmesa->driScreen; \ - __DRIdrawablePrivate *dPriv = rmesa->driDrawable; \ + __DRIscreenPrivate *sPriv = rmesa->dri.screen; \ + __DRIdrawablePrivate *dPriv = rmesa->dri.drawable; \ GLuint pitch = radeonScreen->frontPitch * radeonScreen->cpp; \ GLuint height = dPriv->h; \ char *buf = (char *)(sPriv->pFB + \ - rmesa->drawOffset + \ + rmesa->state.color.drawOffset + \ (dPriv->x * radeonScreen->cpp) + \ (dPriv->y * pitch)); \ char *read_buf = (char *)(sPriv->pFB + \ - rmesa->readOffset + \ + rmesa->state.pixel.readOffset + \ (dPriv->x * radeonScreen->cpp) + \ (dPriv->y * pitch)); \ GLuint p; \ @@ -63,8 +66,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define LOCAL_DEPTH_VARS \ radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \ radeonScreenPtr radeonScreen = rmesa->radeonScreen; \ - __DRIscreenPrivate *sPriv = rmesa->driScreen; \ - __DRIdrawablePrivate *dPriv = rmesa->driDrawable; \ + __DRIscreenPrivate *sPriv = rmesa->dri.screen; \ + __DRIdrawablePrivate *dPriv = rmesa->dri.drawable; \ GLuint height = dPriv->h; \ GLuint xo = dPriv->x; \ GLuint yo = dPriv->y; \ @@ -73,7 +76,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS -#define INIT_MONO_PIXEL( p ) p = rmesa->Color #define CLIPPIXEL( _x, _y ) \ ((_x >= minx) && (_x < maxx) && (_y >= miny) && (_y < maxy)) @@ -92,15 +94,11 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define Y_FLIP( _y ) (height - _y - 1) -#define HW_LOCK() \ - radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \ - FLUSH_BATCH( rmesa ); \ - LOCK_HARDWARE( rmesa ); \ - radeonWaitForIdleLocked( rmesa ); +#define HW_LOCK() #define HW_CLIPLOOP() \ do { \ - __DRIdrawablePrivate *dPriv = rmesa->driDrawable; \ + __DRIdrawablePrivate *dPriv = rmesa->dri.drawable; \ int _nc = dPriv->numClipRects; \ \ while ( _nc-- ) { \ @@ -113,8 +111,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. } \ } while (0) -#define HW_UNLOCK() \ - UNLOCK_HARDWARE( rmesa ) +#define HW_UNLOCK() @@ -124,6 +121,9 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. /* 16 bit, RGB565 color spanline and pixel functions */ +#define INIT_MONO_PIXEL(p, color) \ + p = PACK_COLOR_565( color[0], color[1], color[2] ) + #define WRITE_RGBA( _x, _y, r, g, b, a ) \ *(GLushort *)(buf + _x*2 + _y*pitch) = ((((int)r & 0xf8) << 8) | \ (((int)g & 0xfc) << 3) | \ @@ -135,13 +135,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define READ_RGBA( rgba, _x, _y ) \ do { \ GLushort p = *(GLushort *)(read_buf + _x*2 + _y*pitch); \ - rgba[0] = (p >> 8) & 0xf8; \ - rgba[1] = (p >> 3) & 0xfc; \ - rgba[2] = (p << 3) & 0xf8; \ + rgba[0] = ((p >> 8) & 0xf8) * 255 / 0xf8; \ + rgba[1] = ((p >> 3) & 0xfc) * 255 / 0xfc; \ + rgba[2] = ((p << 3) & 0xf8) * 255 / 0xf8; \ rgba[3] = 0xff; \ - if ( rgba[0] & 0x08 ) rgba[0] |= 0x07; \ - if ( rgba[1] & 0x04 ) rgba[1] |= 0x03; \ - if ( rgba[2] & 0x08 ) rgba[2] |= 0x07; \ } while (0) #define TAG(x) radeon##x##_RGB565 @@ -149,6 +146,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. /* 32 bit, ARGB8888 color spanline and pixel functions */ +#undef INIT_MONO_PIXEL +#define INIT_MONO_PIXEL(p, color) \ + p = PACK_COLOR_8888( color[3], color[0], color[1], color[2] ) + #define WRITE_RGBA( _x, _y, r, g, b, a ) \ *(GLuint *)(buf + _x*4 + _y*pitch) = ((b << 0) | \ (g << 8) | \ @@ -260,7 +261,6 @@ do { \ * Stencil buffer */ -#if 0 /* 24 bit depth, 8 bit stencil depthbuffer functions */ #define WRITE_STENCIL( _x, _y, d ) \ @@ -282,69 +282,115 @@ do { \ #define TAG(x) radeon##x##_24_8 #include "stenciltmp.h" -#endif -void radeonDDInitSpanFuncs( GLcontext *ctx ) +static void radeonSetReadBuffer( GLcontext *ctx, + GLframebuffer *colorBuffer, + GLenum mode ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + + switch ( mode ) { + case GL_FRONT_LEFT: + if ( rmesa->sarea->pfCurrentPage == 1 ) { + rmesa->state.pixel.readOffset = rmesa->radeonScreen->backOffset; + rmesa->state.pixel.readPitch = rmesa->radeonScreen->backPitch; + } else { + rmesa->state.pixel.readOffset = rmesa->radeonScreen->frontOffset; + rmesa->state.pixel.readPitch = rmesa->radeonScreen->frontPitch; + } + break; + case GL_BACK_LEFT: + if ( rmesa->sarea->pfCurrentPage == 1 ) { + rmesa->state.pixel.readOffset = rmesa->radeonScreen->frontOffset; + rmesa->state.pixel.readPitch = rmesa->radeonScreen->frontPitch; + } else { + rmesa->state.pixel.readOffset = rmesa->radeonScreen->backOffset; + rmesa->state.pixel.readPitch = rmesa->radeonScreen->backPitch; + } + break; + default: + assert(0); + break; + } +} + +/* Move locking out to get reasonable span performance (10x better + * than doing this in HW_LOCK above). WaitForIdle() is the main + * culprit. + */ + +static void radeonSpanRenderStart( GLcontext *ctx ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); + RADEON_FIREVERTICES( rmesa ); + LOCK_HARDWARE( rmesa ); + radeonWaitForIdleLocked( rmesa ); +} + +static void radeonSpanRenderFinish( GLcontext *ctx ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); + _swrast_flush( ctx ); + UNLOCK_HARDWARE( rmesa ); +} + +void radeonInitSpanFuncs( GLcontext *ctx ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx); + + swdd->SetReadBuffer = radeonSetReadBuffer; switch ( rmesa->radeonScreen->cpp ) { case 2: - ctx->Driver.WriteRGBASpan = radeonWriteRGBASpan_RGB565; - ctx->Driver.WriteRGBSpan = radeonWriteRGBSpan_RGB565; - ctx->Driver.WriteMonoRGBASpan = radeonWriteMonoRGBASpan_RGB565; - ctx->Driver.WriteRGBAPixels = radeonWriteRGBAPixels_RGB565; - ctx->Driver.WriteMonoRGBAPixels = radeonWriteMonoRGBAPixels_RGB565; - ctx->Driver.ReadRGBASpan = radeonReadRGBASpan_RGB565; - ctx->Driver.ReadRGBAPixels = radeonReadRGBAPixels_RGB565; + swdd->WriteRGBASpan = radeonWriteRGBASpan_RGB565; + swdd->WriteRGBSpan = radeonWriteRGBSpan_RGB565; + swdd->WriteMonoRGBASpan = radeonWriteMonoRGBASpan_RGB565; + swdd->WriteRGBAPixels = radeonWriteRGBAPixels_RGB565; + swdd->WriteMonoRGBAPixels = radeonWriteMonoRGBAPixels_RGB565; + swdd->ReadRGBASpan = radeonReadRGBASpan_RGB565; + swdd->ReadRGBAPixels = radeonReadRGBAPixels_RGB565; break; case 4: - ctx->Driver.WriteRGBASpan = radeonWriteRGBASpan_ARGB8888; - ctx->Driver.WriteRGBSpan = radeonWriteRGBSpan_ARGB8888; - ctx->Driver.WriteMonoRGBASpan = radeonWriteMonoRGBASpan_ARGB8888; - ctx->Driver.WriteRGBAPixels = radeonWriteRGBAPixels_ARGB8888; - ctx->Driver.WriteMonoRGBAPixels = radeonWriteMonoRGBAPixels_ARGB8888; - ctx->Driver.ReadRGBASpan = radeonReadRGBASpan_ARGB8888; - ctx->Driver.ReadRGBAPixels = radeonReadRGBAPixels_ARGB8888; + swdd->WriteRGBASpan = radeonWriteRGBASpan_ARGB8888; + swdd->WriteRGBSpan = radeonWriteRGBSpan_ARGB8888; + swdd->WriteMonoRGBASpan = radeonWriteMonoRGBASpan_ARGB8888; + swdd->WriteRGBAPixels = radeonWriteRGBAPixels_ARGB8888; + swdd->WriteMonoRGBAPixels = radeonWriteMonoRGBAPixels_ARGB8888; + swdd->ReadRGBASpan = radeonReadRGBASpan_ARGB8888; + swdd->ReadRGBAPixels = radeonReadRGBAPixels_ARGB8888; break; default: break; } - switch ( rmesa->glCtx->Visual->DepthBits ) { + switch ( rmesa->glCtx->Visual.depthBits ) { case 16: - ctx->Driver.ReadDepthSpan = radeonReadDepthSpan_16; - ctx->Driver.WriteDepthSpan = radeonWriteDepthSpan_16; - ctx->Driver.ReadDepthPixels = radeonReadDepthPixels_16; - ctx->Driver.WriteDepthPixels = radeonWriteDepthPixels_16; + swdd->ReadDepthSpan = radeonReadDepthSpan_16; + swdd->WriteDepthSpan = radeonWriteDepthSpan_16; + swdd->ReadDepthPixels = radeonReadDepthPixels_16; + swdd->WriteDepthPixels = radeonWriteDepthPixels_16; + break; + + case 24: + swdd->ReadDepthSpan = radeonReadDepthSpan_24_8; + swdd->WriteDepthSpan = radeonWriteDepthSpan_24_8; + swdd->ReadDepthPixels = radeonReadDepthPixels_24_8; + swdd->WriteDepthPixels = radeonWriteDepthPixels_24_8; + + swdd->ReadStencilSpan = radeonReadStencilSpan_24_8; + swdd->WriteStencilSpan = radeonWriteStencilSpan_24_8; + swdd->ReadStencilPixels = radeonReadStencilPixels_24_8; + swdd->WriteStencilPixels = radeonWriteStencilPixels_24_8; break; - case 24: - ctx->Driver.ReadDepthSpan = radeonReadDepthSpan_24_8; - ctx->Driver.WriteDepthSpan = radeonWriteDepthSpan_24_8; - ctx->Driver.ReadDepthPixels = radeonReadDepthPixels_24_8; - ctx->Driver.WriteDepthPixels = radeonWriteDepthPixels_24_8; - -#if 0 /* only need these for hardware stencil buffers */ - ctx->Driver.ReadStencilSpan = radeonReadStencilSpan_24_8; - ctx->Driver.WriteStencilSpan = radeonWriteStencilSpan_24_8; - ctx->Driver.ReadStencilPixels = radeonReadStencilPixels_24_8; - ctx->Driver.WriteStencilPixels = radeonWriteStencilPixels_24_8; -#endif - break; - - default: - break; - } - - ctx->Driver.WriteCI8Span = NULL; - ctx->Driver.WriteCI32Span = NULL; - ctx->Driver.WriteMonoCISpan = NULL; - ctx->Driver.WriteCI32Pixels = NULL; - ctx->Driver.WriteMonoCIPixels = NULL; - ctx->Driver.ReadCI32Span = NULL; - ctx->Driver.ReadCI32Pixels = NULL; + default: + break; + } + + swdd->SpanRenderStart = radeonSpanRenderStart; + swdd->SpanRenderFinish = radeonSpanRenderFinish; } diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_state.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_state.c index 0a4fd5391..676235910 100644 --- a/xc/lib/GL/mesa/src/drv/radeon/radeon_state.c +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_state.c @@ -1545,24 +1545,28 @@ static void radeonSetDrawBuffer( GLcontext *ctx, GLenum mode ) switch ( mode ) { case GL_FRONT_LEFT: FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_FALSE ); - if ( rmesa->doPageFlip && rmesa->sarea->pfCurrentPage == 1 ) { + if ( rmesa->sarea->pfCurrentPage == 1 ) { rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset; rmesa->state.color.drawPitch = rmesa->radeonScreen->backPitch; } else { rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset; rmesa->state.color.drawPitch = rmesa->radeonScreen->frontPitch; } + rmesa->state.pixel.readOffset = rmesa->state.color.drawOffset; + rmesa->state.pixel.readPitch = rmesa->state.color.drawPitch; radeonSetCliprects( rmesa, GL_FRONT_LEFT ); break; case GL_BACK_LEFT: FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_FALSE ); - if ( rmesa->doPageFlip && rmesa->sarea->pfCurrentPage == 1 ) { + if ( rmesa->sarea->pfCurrentPage == 1 ) { rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset; rmesa->state.color.drawPitch = rmesa->radeonScreen->frontPitch; } else { rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset; rmesa->state.color.drawPitch = rmesa->radeonScreen->backPitch; } + rmesa->state.pixel.readOffset = rmesa->state.color.drawOffset; + rmesa->state.pixel.readPitch = rmesa->state.color.drawPitch; radeonSetCliprects( rmesa, GL_BACK_LEFT ); break; default: diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_swtcl.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_swtcl.c index 2ac4d222a..a5676d90d 100644 --- a/xc/lib/GL/mesa/src/drv/radeon/radeon_swtcl.c +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_swtcl.c @@ -130,6 +130,7 @@ static struct { #define DO_PTEX (IND & RADEON_PTEX_BIT) #define VERTEX radeonVertex +#define VERTEX_COLOR radeon_color_t #define GET_VIEWPORT_MAT() 0 #define GET_TEXSOURCE(n) n #define GET_VERTEX_FORMAT() RADEON_CONTEXT(ctx)->swtcl.vertex_format diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_tex.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_tex.c index 83c22f878..22ff01aea 100644 --- a/xc/lib/GL/mesa/src/drv/radeon/radeon_tex.c +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_tex.c @@ -1,52 +1,56 @@ -/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_tex.c,v 1.4 2001/05/21 21:43:52 dawes Exp $ */ -/************************************************************************** - -Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and - VA Linux Systems Inc., Fremont, California. - -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 -on the rights to use, copy, modify, merge, publish, distribute, sub -license, and/or sell copies of the Software, and to permit persons to whom -the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice (including the next -paragraph) shall be included in all copies or substantial portions of the -Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL -ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -USE OR OTHER DEALINGS IN THE SOFTWARE. - -**************************************************************************/ - +/* $XFree86$ */ /* - * Authors: - * Kevin E. Martin <martin@valinux.com> - * Gareth Hughes <gareth@valinux.com> + * Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and + * VA Linux Systems Inc., Fremont, California. * + * 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 + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Gareth Hughes <gareth@valinux.com> + * Brian Paul <brianp@valinux.com> */ #include "radeon_context.h" #include "radeon_state.h" #include "radeon_ioctl.h" -#include "radeon_vb.h" +#include "radeon_swtcl.h" #include "radeon_tex.h" -#include "mmath.h" -#include "simple_list.h" +#include "colormac.h" +#include "context.h" #include "enums.h" +#include "image.h" #include "mem.h" +#include "mmath.h" +#include "simple_list.h" +#include "texformat.h" +#include "texstore.h" #include "texutil.h" +/* ============================================================= + * Utility functions: + */ + static void radeonSetTexWrap( radeonTexObjPtr t, GLenum swrap, GLenum twrap ) { t->pp_txfilter &= ~(RADEON_CLAMP_S_MASK | RADEON_CLAMP_T_MASK); @@ -76,29 +80,67 @@ static void radeonSetTexWrap( radeonTexObjPtr t, GLenum swrap, GLenum twrap ) } } +static void radeonSetTexMaxAnisotropy( radeonTexObjPtr t, GLfloat max ) +{ + t->pp_txfilter &= ~RADEON_MAX_ANISO_MASK; + + if ( max == 1.0 ) { + t->pp_txfilter |= RADEON_MAX_ANISO_1_TO_1; + } else if ( max <= 2.0 ) { + t->pp_txfilter |= RADEON_MAX_ANISO_2_TO_1; + } else if ( max <= 4.0 ) { + t->pp_txfilter |= RADEON_MAX_ANISO_4_TO_1; + } else if ( max <= 8.0 ) { + t->pp_txfilter |= RADEON_MAX_ANISO_8_TO_1; + } else { + t->pp_txfilter |= RADEON_MAX_ANISO_16_TO_1; + } +} + static void radeonSetTexFilter( radeonTexObjPtr t, GLenum minf, GLenum magf ) { + GLuint anisotropy = (t->pp_txfilter & RADEON_MAX_ANISO_MASK); + t->pp_txfilter &= ~(RADEON_MIN_FILTER_MASK | RADEON_MAG_FILTER_MASK); - switch ( minf ) { - case GL_NEAREST: - t->pp_txfilter |= RADEON_MIN_FILTER_NEAREST; - break; - case GL_LINEAR: - t->pp_txfilter |= RADEON_MIN_FILTER_LINEAR; - break; - case GL_NEAREST_MIPMAP_NEAREST: - t->pp_txfilter |= RADEON_MIN_FILTER_NEAREST_MIP_NEAREST; - break; - case GL_NEAREST_MIPMAP_LINEAR: - t->pp_txfilter |= RADEON_MIN_FILTER_LINEAR_MIP_NEAREST; - break; - case GL_LINEAR_MIPMAP_NEAREST: - t->pp_txfilter |= RADEON_MIN_FILTER_NEAREST_MIP_LINEAR; - break; - case GL_LINEAR_MIPMAP_LINEAR: - t->pp_txfilter |= RADEON_MIN_FILTER_LINEAR_MIP_LINEAR; - break; + if ( anisotropy == RADEON_MAX_ANISO_1_TO_1 ) { + switch ( minf ) { + case GL_NEAREST: + t->pp_txfilter |= RADEON_MIN_FILTER_NEAREST; + break; + case GL_LINEAR: + t->pp_txfilter |= RADEON_MIN_FILTER_LINEAR; + break; + case GL_NEAREST_MIPMAP_NEAREST: + t->pp_txfilter |= RADEON_MIN_FILTER_NEAREST_MIP_NEAREST; + break; + case GL_NEAREST_MIPMAP_LINEAR: + t->pp_txfilter |= RADEON_MIN_FILTER_LINEAR_MIP_NEAREST; + break; + case GL_LINEAR_MIPMAP_NEAREST: + t->pp_txfilter |= RADEON_MIN_FILTER_NEAREST_MIP_LINEAR; + break; + case GL_LINEAR_MIPMAP_LINEAR: + t->pp_txfilter |= RADEON_MIN_FILTER_LINEAR_MIP_LINEAR; + break; + } + } else { + switch ( minf ) { + case GL_NEAREST: + t->pp_txfilter |= RADEON_MIN_FILTER_ANISO_NEAREST; + break; + case GL_LINEAR: + t->pp_txfilter |= RADEON_MIN_FILTER_ANISO_LINEAR; + break; + case GL_NEAREST_MIPMAP_NEAREST: + case GL_LINEAR_MIPMAP_NEAREST: + t->pp_txfilter |= RADEON_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST; + break; + case GL_NEAREST_MIPMAP_LINEAR: + case GL_LINEAR_MIPMAP_LINEAR: + t->pp_txfilter |= RADEON_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR; + break; + } } switch ( magf ) { @@ -116,143 +158,92 @@ static void radeonSetTexBorderColor( radeonTexObjPtr t, GLubyte c[4] ) t->pp_border_color = radeonPackColor( 4, c[0], c[1], c[2], c[3] ); } + static radeonTexObjPtr radeonAllocTexObj( struct gl_texture_object *texObj ) { radeonTexObjPtr t; t = CALLOC_STRUCT( radeon_tex_obj ); + if (!t) + return NULL; - if ( RADEON_DEBUG & DEBUG_VERBOSE_API ) { - fprintf( stderr, "%s( %p, %p )\n", __FUNCTION__, texObj, t ); + if ( RADEON_DEBUG & DEBUG_TEXTURE ) { + fprintf( stderr, __FUNCTION__"( %p, %p )\n", texObj, t ); } - /* Initialize non-image-dependent parts of the state: - */ t->tObj = texObj; -#if 0 - t->dirty_images = ~0; -#endif - t->pp_txfilter = RADEON_BORDER_MODE_OGL; - t->pp_txformat = (RADEON_TXFORMAT_ENDIAN_NO_SWAP | - RADEON_TXFORMAT_PERSPECTIVE_ENABLE); - make_empty_list( t ); + /* Initialize non-image-dependent parts of the state: + */ radeonSetTexWrap( t, texObj->WrapS, texObj->WrapT ); + radeonSetTexMaxAnisotropy( t, texObj->MaxAnisotropy ); radeonSetTexFilter( t, texObj->MinFilter, texObj->MagFilter ); radeonSetTexBorderColor( t, texObj->BorderColor ); - return t; } -static GLint radeonChooseTexFormat( radeonContextPtr rmesa, - struct gl_texture_image *texImage, - GLenum format, GLenum type ) +static const struct gl_texture_format * +radeonChooseTextureFormat( GLcontext *ctx, GLint internalFormat, + GLenum format, GLenum type ) { + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); const GLboolean do32bpt = ( rmesa->radeonScreen->cpp == 4 ); - const struct gl_texture_format *texFormat; - GLint ret; - - if ( 0 ) - fprintf( stderr, "internal=%s format=%s type=%s\n", - texImage->IntFormat == 3 ? "GL_RGB (3)" : - texImage->IntFormat == 4 ? "GL_RGBA (4)" : - gl_lookup_enum_by_nr( texImage->IntFormat ), - gl_lookup_enum_by_nr( format ), - gl_lookup_enum_by_nr( type ) ); - -#define SET_FORMAT( r, gl ) \ - do { \ - ret = (r); \ - texFormat = &(gl); \ - } while (0) - -#define SET_FORMAT_32BPT( r32, gl32, r16, gl16 ) \ - do { \ - if ( do32bpt ) { \ - ret = (r32); \ - texFormat = &(gl32); \ - } else { \ - ret = (r16); \ - texFormat = &(gl16); \ - } \ - } while (0) - - switch ( texImage->IntFormat ) { - /* GH: Bias towards GL_RGB, GL_RGBA texture formats. This has - * got to be better than sticking them way down the end of this - * huge list. - */ - case GL_RGBA: + + switch ( internalFormat ) { case 4: + case GL_RGBA: if ( format == GL_BGRA ) { if ( type == GL_UNSIGNED_INT_8_8_8_8_REV ) { - SET_FORMAT( RADEON_TXFORMAT_ARGB8888, _mesa_texformat_argb8888 ); - break; - } else if ( type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) { - SET_FORMAT( RADEON_TXFORMAT_ARGB4444, _mesa_texformat_argb4444 ); - break; - } else if ( type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) { - SET_FORMAT( RADEON_TXFORMAT_ARGB1555, _mesa_texformat_argb1555 ); - break; + return &_mesa_texformat_argb8888; + } + else if ( type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) { + return &_mesa_texformat_argb4444; + } + else if ( type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) { + return &_mesa_texformat_argb1555; } } - SET_FORMAT_32BPT( RADEON_TXFORMAT_RGBA8888, _mesa_texformat_rgba8888, - RADEON_TXFORMAT_ARGB4444, _mesa_texformat_argb4444 ); - break; + return do32bpt ? &_mesa_texformat_rgba8888 : &_mesa_texformat_argb4444; - case GL_RGB: case 3: + case GL_RGB: if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) { - SET_FORMAT( RADEON_TXFORMAT_RGB565, _mesa_texformat_rgb565 ); - break; + return &_mesa_texformat_rgb565; } - SET_FORMAT_32BPT( RADEON_TXFORMAT_RGBA8888, _mesa_texformat_rgba8888, - RADEON_TXFORMAT_RGB565, _mesa_texformat_rgb565 ); - break; + return do32bpt ? &_mesa_texformat_rgba8888 : &_mesa_texformat_rgb565; - /* GH: Okay, keep checking as normal. Still test for GL_RGB, - * GL_RGBA formats first. - */ case GL_RGBA8: case GL_RGB10_A2: case GL_RGBA12: case GL_RGBA16: - SET_FORMAT_32BPT( RADEON_TXFORMAT_RGBA8888, _mesa_texformat_rgba8888, - RADEON_TXFORMAT_ARGB4444, _mesa_texformat_argb4444 ); - break; + return do32bpt ? &_mesa_texformat_rgba8888 : &_mesa_texformat_argb4444; case GL_RGBA4: case GL_RGBA2: - SET_FORMAT( RADEON_TXFORMAT_ARGB4444, _mesa_texformat_argb4444 ); - break; + return &_mesa_texformat_argb4444; case GL_RGB5_A1: - SET_FORMAT( RADEON_TXFORMAT_ARGB1555, _mesa_texformat_argb1555 ); - break; + return &_mesa_texformat_argb1555; case GL_RGB8: case GL_RGB10: case GL_RGB12: case GL_RGB16: - SET_FORMAT_32BPT( RADEON_TXFORMAT_RGBA8888, _mesa_texformat_rgba8888, - RADEON_TXFORMAT_RGB565, _mesa_texformat_rgb565 ); - break; + return do32bpt ? &_mesa_texformat_rgba8888 : &_mesa_texformat_rgb565; case GL_RGB5: case GL_RGB4: case GL_R3_G3_B2: - SET_FORMAT( RADEON_TXFORMAT_RGB565, _mesa_texformat_rgb565 ); - break; + return &_mesa_texformat_rgb565; case GL_ALPHA: case GL_ALPHA4: case GL_ALPHA8: case GL_ALPHA12: case GL_ALPHA16: - SET_FORMAT( RADEON_TXFORMAT_AI88, _mesa_texformat_al88 ); - break; + return &_mesa_texformat_al88; case 1: case GL_LUMINANCE: @@ -260,8 +251,7 @@ static GLint radeonChooseTexFormat( radeonContextPtr rmesa, case GL_LUMINANCE8: case GL_LUMINANCE12: case GL_LUMINANCE16: - SET_FORMAT( RADEON_TXFORMAT_AI88, _mesa_texformat_al88 ); - break; + return &_mesa_texformat_al88; case 2: case GL_LUMINANCE_ALPHA: @@ -271,550 +261,230 @@ static GLint radeonChooseTexFormat( radeonContextPtr rmesa, case GL_LUMINANCE12_ALPHA4: case GL_LUMINANCE12_ALPHA12: case GL_LUMINANCE16_ALPHA16: - SET_FORMAT( RADEON_TXFORMAT_AI88, _mesa_texformat_al88 ); - break; + return &_mesa_texformat_al88; case GL_INTENSITY: case GL_INTENSITY4: case GL_INTENSITY8: case GL_INTENSITY12: case GL_INTENSITY16: - SET_FORMAT( RADEON_TXFORMAT_I8, _mesa_texformat_i8 ); - break; + return &_mesa_texformat_i8; - case GL_COLOR_INDEX: - case GL_COLOR_INDEX1_EXT: - case GL_COLOR_INDEX2_EXT: - case GL_COLOR_INDEX4_EXT: - case GL_COLOR_INDEX8_EXT: - case GL_COLOR_INDEX12_EXT: - case GL_COLOR_INDEX16_EXT: default: - fprintf( stderr, "bad texture format in radeonChooseTexFormat() %d", - texImage->IntFormat ); - return -1; + _mesa_problem(ctx, "unexpected texture format in radeonChoosTexFormat"); + return NULL; } - texImage->TexFormat = texFormat; - - return ret; + return NULL; /* never get here */ } -/* ================================================================ - * Texture image callbacks - */ - -static GLboolean -radeonDDTexImage1D( GLcontext *ctx, GLenum target, GLint level, - GLenum format, GLenum type, const GLvoid *pixels, - const struct gl_pixelstore_attrib *packing, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage, - GLboolean *retainInternalCopy ) +static void radeonTexImage1D( GLcontext *ctx, GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint border, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - radeonTexObjPtr t = (radeonTexObjPtr)texObj->DriverData; - const struct gl_texture_format *texFormat; - GLuint texSize; - GLint txformat; - GLubyte *data; - - if ( target != GL_TEXTURE_1D ) - return GL_FALSE; - - if ( RADEON_DEBUG & DEBUG_VERBOSE_API ) { - fprintf( stderr, "%s( %p, %d )\n", __FUNCTION__, texObj, level ); - } + radeonTexObjPtr t = (radeonTexObjPtr) texObj->DriverData; if ( t ) { - if ( t->bound ) FLUSH_BATCH( rmesa ); radeonSwapOutTexObj( rmesa, t ); - } else { + } + else { t = radeonAllocTexObj( texObj ); + if (!t) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D"); + return; + } texObj->DriverData = t; } - txformat = radeonChooseTexFormat( rmesa, texImage, format, type ); - if ( txformat < 0 ) - return GL_FALSE; - - texFormat = texImage->TexFormat; - texSize = texImage->Width * texFormat->TexelBytes; - - /* We really shouldn't have to keep the texture image, it should be - * hung from the main texImage structure. - */ - if ( t->image[level].data ) { - FREE( t->image[level].data ); - t->image[level].data = NULL; - } - - data = (GLubyte *) MALLOC( texSize ); - if ( !data ) - return GL_FALSE; - - if ( !_mesa_convert_texsubimage1d( texFormat->IntFormat, - 0, texImage->Width, - format, type, packing, - pixels, data ) ) { - /*fprintf( stderr, " *** convert failed!\n" );*/ - FREE( data ); - return GL_FALSE; - } + /* Note, this will call radeonChooseTextureFormat */ + _mesa_store_teximage1d(ctx, target, level, internalFormat, + width, border, format, type, pixels, + &ctx->Unpack, texObj, texImage); - t->image[level].data = data; t->dirty_images |= (1 << level); - - /* Format-specific hardware state: - */ - t->pp_txformat &= ~(RADEON_TXFORMAT_FORMAT_MASK | - RADEON_TXFORMAT_ALPHA_IN_MAP); - t->pp_txformat |= txformat; - - if ( txformat == RADEON_TXFORMAT_RGBA8888 || - txformat == RADEON_TXFORMAT_ARGB4444 || - txformat == RADEON_TXFORMAT_ARGB1555 || - txformat == RADEON_TXFORMAT_AI88 ) { - t->pp_txformat |= RADEON_TXFORMAT_ALPHA_IN_MAP; - } - - ASSERT( t->image[level].data ); - - rmesa->new_state |= RADEON_NEW_TEXTURE; - - *retainInternalCopy = GL_FALSE; - return GL_TRUE; } -static GLboolean -radeonDDTexImage2D( GLcontext *ctx, GLenum target, GLint level, - GLenum format, GLenum type, const GLvoid *pixels, - const struct gl_pixelstore_attrib *packing, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage, - GLboolean *retainInternalCopy ) + +static void radeonTexSubImage1D( GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, + GLsizei width, + GLenum format, GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); radeonTexObjPtr t = (radeonTexObjPtr)texObj->DriverData; - const struct gl_texture_format *texFormat; - GLuint texSize; - GLint txformat; - GLubyte *data; - - if ( target != GL_TEXTURE_2D ) - return GL_FALSE; - - if ( RADEON_DEBUG & DEBUG_VERBOSE_API ) { - fprintf( stderr, "%s( %p, %d )\n", __FUNCTION__, texObj, level ); - } + assert( t ); /* this _should_ be true */ if ( t ) { - if ( t->bound ) FLUSH_BATCH( rmesa ); - if ( t->image[level].data ) radeonSwapOutTexObj( rmesa, t ); - } else { - t = radeonAllocTexObj( texObj ); - texObj->DriverData = t; + radeonSwapOutTexObj( rmesa, t ); + t->dirty_images |= (1 << level); } - - txformat = radeonChooseTexFormat( rmesa, texImage, format, type ); - if ( txformat < 0 ) - return GL_FALSE; - - texFormat = texImage->TexFormat; - texSize = texImage->Width * texImage->Height * texFormat->TexelBytes; - - /* We really shouldn't have to keep the texture image, it should be - * hung from the main texImage structure. - */ - if ( t->image[level].data ) { - FREE( t->image[level].data ); - t->image[level].data = NULL; + else { + t = radeonAllocTexObj(texObj); + if (!t) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D"); + return; + } + texObj->DriverData = t; } - data = (GLubyte *) MALLOC( texSize ); - if ( !data ) - return GL_FALSE; - - if ( !_mesa_convert_texsubimage2d( texFormat->IntFormat, - 0, 0, texImage->Width, texImage->Height, - texImage->Width, format, type, packing, - pixels, data ) ) { - if ( 0 ) - fprintf( stderr, " *** convert failed! %s/%s-> %s\n", - gl_lookup_enum_by_nr( format ), - gl_lookup_enum_by_nr( type ), - gl_lookup_enum_by_nr( texImage->IntFormat ) ); - FREE( data ); - return GL_FALSE; - } + _mesa_store_texsubimage1d(ctx, target, level, xoffset, width, + format, type, pixels, packing, texObj, + texImage); - t->image[level].data = data; t->dirty_images |= (1 << level); - - /* Format-specific hardware state: - */ - t->pp_txformat &= ~(RADEON_TXFORMAT_FORMAT_MASK | - RADEON_TXFORMAT_ALPHA_IN_MAP); - t->pp_txformat |= txformat; - - if ( txformat == RADEON_TXFORMAT_RGBA8888 || - txformat == RADEON_TXFORMAT_ARGB4444 || - txformat == RADEON_TXFORMAT_ARGB1555 || - txformat == RADEON_TXFORMAT_AI88 ) { - t->pp_txformat |= RADEON_TXFORMAT_ALPHA_IN_MAP; - } - - ASSERT( t->image[level].data ); - - rmesa->new_state |= RADEON_NEW_TEXTURE; - - *retainInternalCopy = GL_FALSE; - return GL_TRUE; } -/* GH: This is undoubtedly broken... - */ -static GLboolean -radeonDDTexImage3D( GLcontext *ctx, GLenum target, GLint level, - GLenum format, GLenum type, const GLvoid *pixels, - const struct gl_pixelstore_attrib *packing, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage, - GLboolean *retainInternalCopy ) + +static void radeonTexImage2D( GLcontext *ctx, GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint height, GLint border, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); radeonTexObjPtr t = (radeonTexObjPtr)texObj->DriverData; - const struct gl_texture_format *texFormat; - GLuint texSize; - GLint txformat; - GLubyte *data; - if ( target != GL_TEXTURE_3D ) - return GL_FALSE; +/* fprintf(stderr, "%s\n", __FUNCTION__); */ if ( t ) { - if ( t->bound ) FLUSH_BATCH( rmesa ); radeonSwapOutTexObj( rmesa, t ); - } else { + } + else { t = radeonAllocTexObj( texObj ); + if (!t) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); + return; + } texObj->DriverData = t; } - txformat = radeonChooseTexFormat( rmesa, texImage, format, type ); - if ( txformat < 0 ) - return GL_FALSE; + /* Note, this will call radeonChooseTextureFormat */ + _mesa_store_teximage2d(ctx, target, level, internalFormat, + width, height, border, format, type, pixels, + &ctx->Unpack, texObj, texImage); - texFormat = texImage->TexFormat; - texSize = (texImage->Width * texImage->Height * - texImage->Depth * texFormat->TexelBytes); - - /* We really shouldn't have to keep the texture image, it should be - * hung from the main texImage structure. - */ - if ( t->image[level].data ) { - FREE( t->image[level].data ); - t->image[level].data = NULL; - } - - data = (GLubyte *) MALLOC( texSize ); - if ( !data ) - return GL_FALSE; - - if ( !_mesa_convert_texsubimage3d( texFormat->IntFormat, - 0, 0, 0, texImage->Width, - texImage->Height, texImage->Depth, - texImage->Width, texImage->Height, - format, type, packing, - pixels, data ) ) { - FREE( data ); - return GL_FALSE; - } - - t->image[level].data = data; t->dirty_images |= (1 << level); - - ASSERT( t->image[level].data ); - - rmesa->new_state |= RADEON_NEW_TEXTURE; - - *retainInternalCopy = GL_FALSE; - return GL_TRUE; } -/* ================================================================ - * Texture subimage callbacks - */ - -static GLboolean -radeonDDTexSubImage1D( GLcontext *ctx, GLenum target, GLint level, - GLint xoffset, GLsizei width, - GLenum format, GLenum type, - const GLvoid *pixels, - const struct gl_pixelstore_attrib *packing, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage ) +static void radeonTexSubImage2D( GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - radeonTexObjPtr t = (radeonTexObjPtr)texObj->DriverData; - const struct gl_texture_format *texFormat; - - if ( target != GL_TEXTURE_1D ) - return GL_FALSE; - - /* FIXME: Can this ever be NULL??? - */ - ASSERT( t ); - ASSERT( t->image[level].data ); + radeonTexObjPtr t = (radeonTexObjPtr) texObj->DriverData; - if ( t->bound ) - FLUSH_BATCH( rmesa ); - - texFormat = texImage->TexFormat; - - if ( !_mesa_convert_texsubimage1d( texFormat->IntFormat, - xoffset, width, format, type, packing, - pixels, t->image[level].data ) ) { - /*fprintf( stderr, " *** convert failed!\n" );*/ - return GL_FALSE; - } - - t->dirty_images |= (1 << level); - rmesa->new_state |= RADEON_NEW_TEXTURE; - - return GL_TRUE; -} +/* fprintf(stderr, "%s\n", __FUNCTION__); */ -static GLboolean -radeonDDTexSubImage2D( GLcontext *ctx, GLenum target, GLint level, - GLint xoffset, GLint yoffset, - GLsizei width, GLsizei height, - GLenum format, GLenum type, - const GLvoid *pixels, - const struct gl_pixelstore_attrib *packing, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage ) -{ - radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - radeonTexObjPtr t = (radeonTexObjPtr)texObj->DriverData; - const struct gl_texture_format *texFormat; - - if ( target != GL_TEXTURE_2D ) - return GL_FALSE; - - if ( RADEON_DEBUG & DEBUG_VERBOSE_API ) { - fprintf( stderr, "%s( %p, %d )\n", __FUNCTION__, texObj, level ); + assert( t ); /* this _should_ be true */ + if ( t ) { + radeonSwapOutTexObj( rmesa, t ); } - - /* FIXME: Can this ever be NULL??? - */ - ASSERT( t ); - ASSERT( t->image[level].data ); - - if ( t->bound ) - FLUSH_BATCH( rmesa ); - - texFormat = texImage->TexFormat; - - if ( !_mesa_convert_texsubimage2d( texFormat->IntFormat, - xoffset, yoffset, width, height, - texImage->Width, format, type, packing, - pixels, t->image[level].data ) ) { - /*fprintf( stderr, " *** convert failed!\n" );*/ - return GL_FALSE; + else { + t = radeonAllocTexObj(texObj); + if (!t) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D"); + return; + } + texObj->DriverData = t; } - t->dirty_images |= (1 << level); - rmesa->new_state |= RADEON_NEW_TEXTURE; - - return GL_TRUE; -} - -/* GH: This is undoubtedly broken... - */ -static GLboolean -radeonDDTexSubImage3D( GLcontext *ctx, GLenum target, GLint level, - GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLint depth, - GLenum format, GLenum type, - const GLvoid *pixels, - const struct gl_pixelstore_attrib *packing, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage ) -{ - radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - radeonTexObjPtr t = (radeonTexObjPtr)texObj->DriverData; - const struct gl_texture_format *texFormat; - - if ( target != GL_TEXTURE_3D ) - return GL_FALSE; - - /* FIXME: Can this ever be NULL??? - */ - ASSERT( t ); - ASSERT( t->image[level].data ); - - if ( t->bound ) - FLUSH_BATCH( rmesa ); - - texFormat = texImage->TexFormat; - - if ( !_mesa_convert_texsubimage3d( texFormat->IntFormat, - xoffset, yoffset, zoffset, - width, height, depth, - texImage->Width, texImage->Height, - format, type, packing, - pixels, t->image[level].data ) ) { - /*fprintf( stderr, " *** convert failed!\n" );*/ - return GL_FALSE; - } + _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width, + height, format, type, pixels, packing, texObj, + texImage); t->dirty_images |= (1 << level); - rmesa->new_state |= RADEON_NEW_TEXTURE; - - return GL_TRUE; } -/* ================================================================ - * DEPRECATED... - */ - -static GLvoid *radeonDDGetTexImage( GLcontext *ctx, GLenum target, GLint level, - const struct gl_texture_object *texObj, - GLenum *formatOut, GLenum *typeOut, - GLboolean *freeImageOut ) -{ - const struct gl_texture_image *texImage = texObj->Image[level]; - const struct gl_texture_format *texFormat = texImage->TexFormat; - radeonTexObjPtr t = (radeonTexObjPtr)texObj->DriverData; - GLubyte *data; - - if ( !t || !t->image[level].data ) - return NULL; - - data = (GLubyte *) MALLOC( texImage->Width * texImage->Height * 4 ); - if ( !data ) - return NULL; - - if ( 0 ) - fprintf( stderr, " in=%d out=%s\n", - texFormat->IntFormat, - gl_lookup_enum_by_nr( texImage->Format ) ); - - switch ( target ) { - case GL_TEXTURE_1D: - _mesa_unconvert_teximage1d( texFormat->IntFormat, texImage->Format, - texImage->Width, - t->image[level].data, data ); - break; - case GL_TEXTURE_2D: - _mesa_unconvert_teximage2d( texFormat->IntFormat, texImage->Format, - texImage->Width, texImage->Height, - t->image[level].data, data ); - break; - default: - return NULL; - } - - *formatOut = texImage->Format; - *typeOut = GL_UNSIGNED_BYTE; - *freeImageOut = GL_TRUE; - - return data; -} - - -/* ================================================================ - * Texture state callbacks - */ #define SCALED_FLOAT_TO_BYTE( x, scale ) \ - ((((GLint)((256.0F / scale) * (x))) - 1) / 2) + (((GLuint)((255.0F / scale) * (x))) / 2) -static void radeonDDTexEnv( GLcontext *ctx, GLenum target, - GLenum pname, const GLfloat *param ) +static void radeonTexEnv( GLcontext *ctx, GLenum target, + GLenum pname, const GLfloat *param ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - struct gl_texture_unit *texUnit; - GLuint source; - GLubyte c[4]; - GLuint col; - GLfloat bias; - GLubyte b; - - if ( RADEON_DEBUG & DEBUG_VERBOSE_API ) { + GLuint unit = ctx->Texture.CurrentUnit; + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + + if ( RADEON_DEBUG & DEBUG_STATE ) { fprintf( stderr, "%s( %s )\n", - __FUNCTION__, gl_lookup_enum_by_nr( pname ) ); + __FUNCTION__, _mesa_lookup_enum_by_nr( pname ) ); } switch ( pname ) { - case GL_TEXTURE_ENV_MODE: - FLUSH_BATCH( rmesa ); - rmesa->new_state |= RADEON_NEW_TEXTURE | RADEON_NEW_ALPHA; - break; - - case GL_TEXTURE_ENV_COLOR: - source = rmesa->tmu_source[ctx->Texture.CurrentUnit]; - texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; - FLOAT_RGBA_TO_UBYTE_RGBA( c, texUnit->EnvColor ); - col = radeonPackColor( 4, c[0], c[1], c[2], c[3] ); - if ( rmesa->env_color[source] != col ) { - FLUSH_BATCH( rmesa ); - rmesa->env_color[source] = col; - - rmesa->new_state |= RADEON_NEW_TEXTURE; + case GL_TEXTURE_ENV_COLOR: { + GLubyte c[4]; + GLuint envColor; + UNCLAMPED_FLOAT_TO_RGBA_CHAN( c, texUnit->EnvColor ); + envColor = radeonPackColor( 4, c[0], c[1], c[2], c[3] ); + if ( rmesa->hw.tex[unit].cmd[TEX_PP_TFACTOR] != envColor ) { + RADEON_STATECHANGE( rmesa, tex[unit] ); + rmesa->hw.tex[unit].cmd[TEX_PP_TFACTOR] = envColor; } break; + } + + case GL_TEXTURE_LOD_BIAS_EXT: { + GLfloat bias; + GLuint b; - case GL_TEXTURE_LOD_BIAS_EXT: /* The Radeon's LOD bias is a signed 2's complement value with a * range of -1.0 <= bias < 4.0. We break this into two linear * functions, one mapping [-1.0,0.0] to [-128,0] and one mapping * [0.0,4.0] to [0,127]. */ - source = rmesa->tmu_source[ctx->Texture.CurrentUnit]; bias = CLAMP( *param, -1.0, 4.0 ); if ( bias == 0 ) { b = 0; } else if ( bias > 0 ) { - b = (GLubyte) SCALED_FLOAT_TO_BYTE( bias, 4.0 ); + b = ((GLuint)SCALED_FLOAT_TO_BYTE( bias, 4.0 )) << RADEON_LOD_BIAS_SHIFT; } else { - b = (GLubyte) SCALED_FLOAT_TO_BYTE( bias, 1.0 ); + b = ((GLuint)SCALED_FLOAT_TO_BYTE( bias, 1.0 )) << RADEON_LOD_BIAS_SHIFT; } - if ( rmesa->lod_bias[source] != (GLuint)b ) { - FLUSH_BATCH( rmesa ); - rmesa->lod_bias[source] = (GLuint)b; - - rmesa->new_state |= RADEON_NEW_TEXTURE; + if ( (rmesa->hw.tex[unit].cmd[TEX_PP_TXFILTER] & RADEON_LOD_BIAS_MASK) != b ) { + RADEON_STATECHANGE( rmesa, tex[unit] ); + rmesa->hw.tex[unit].cmd[TEX_PP_TXFILTER] &= ~RADEON_LOD_BIAS_MASK; + rmesa->hw.tex[unit].cmd[TEX_PP_TXFILTER] |= (b & RADEON_LOD_BIAS_MASK); } break; + } default: return; } } -static void radeonDDTexParameter( GLcontext *ctx, GLenum target, - struct gl_texture_object *tObj, - GLenum pname, const GLfloat *params ) +static void radeonTexParameter( GLcontext *ctx, GLenum target, + struct gl_texture_object *texObj, + GLenum pname, const GLfloat *params ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - radeonTexObjPtr t = (radeonTexObjPtr)tObj->DriverData; + radeonTexObjPtr t = (radeonTexObjPtr) texObj->DriverData; - if ( RADEON_DEBUG & DEBUG_VERBOSE_API ) { - fprintf( stderr, "%s( %s )\n", - __FUNCTION__, gl_lookup_enum_by_nr( pname ) ); + if ( RADEON_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) { + fprintf( stderr, __FUNCTION__"( %s )\n", + _mesa_lookup_enum_by_nr( pname ) ); } - /* If we don't have a hardware texture, it will be automatically - * created with current state before it is used, so we don't have - * to do anything now. - */ - if ( !t ) - return; - if ( ( target != GL_TEXTURE_2D ) && ( target != GL_TEXTURE_1D ) ) return; @@ -822,94 +492,90 @@ static void radeonDDTexParameter( GLcontext *ctx, GLenum target, switch ( pname ) { case GL_TEXTURE_MIN_FILTER: case GL_TEXTURE_MAG_FILTER: - if ( t->bound ) FLUSH_BATCH( rmesa ); - radeonSetTexFilter( t, tObj->MinFilter, tObj->MagFilter ); + case GL_TEXTURE_MAX_ANISOTROPY_EXT: + radeonSetTexMaxAnisotropy( t, texObj->MaxAnisotropy ); + radeonSetTexFilter( t, texObj->MinFilter, texObj->MagFilter ); break; case GL_TEXTURE_WRAP_S: case GL_TEXTURE_WRAP_T: - if ( t->bound ) FLUSH_BATCH( rmesa ); - radeonSetTexWrap( t, tObj->WrapS, tObj->WrapT ); + radeonSetTexWrap( t, texObj->WrapS, texObj->WrapT ); break; case GL_TEXTURE_BORDER_COLOR: - if ( t->bound ) FLUSH_BATCH( rmesa ); - radeonSetTexBorderColor( t, tObj->BorderColor ); + radeonSetTexBorderColor( t, texObj->BorderColor ); + break; + + case GL_TEXTURE_BASE_LEVEL: + case GL_TEXTURE_MAX_LEVEL: + case GL_TEXTURE_MIN_LOD: + case GL_TEXTURE_MAX_LOD: + /* This isn't the most efficient solution but there doesn't appear to + * be a nice alternative for Radeon. Since there's no LOD clamping, + * we just have to rely on loading the right subset of mipmap levels + * to simulate a clamped LOD. + */ + radeonSwapOutTexObj( rmesa, t ); break; default: return; } - rmesa->new_state |= RADEON_NEW_TEXTURE; + /* Mark this texobj as dirty (one bit per tex unit) + */ + t->dirty_state = TEX_ALL; } -static void radeonDDBindTexture( GLcontext *ctx, GLenum target, - struct gl_texture_object *tObj ) -{ - radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - radeonTexObjPtr t = (radeonTexObjPtr) tObj->DriverData; - GLuint unit = ctx->Texture.CurrentUnit; - if ( RADEON_DEBUG & DEBUG_VERBOSE_API ) { - fprintf( stderr, "%s( %p ) unit=%d\n", - __FUNCTION__, tObj, unit ); - } - FLUSH_BATCH( rmesa ); +static void radeonBindTexture( GLcontext *ctx, GLenum target, + struct gl_texture_object *texObj ) +{ + radeonTexObjPtr t = (radeonTexObjPtr) texObj->DriverData; + GLuint unit = ctx->Texture.CurrentUnit; - if ( !t ) { - t = radeonAllocTexObj( tObj ); - tObj->DriverData = t; + if ( RADEON_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) { + fprintf( stderr, __FUNCTION__"( %p ) unit=%d\n", texObj, unit ); } - /* Unbind a currently bound texture. - */ - if ( rmesa->CurrentTexObj[unit] ) { - rmesa->CurrentTexObj[unit]->bound &= ~(unit + 1); - rmesa->CurrentTexObj[unit] = NULL; + if ( target == GL_TEXTURE_2D || target == GL_TEXTURE_1D ) { + if ( !t ) { + t = radeonAllocTexObj( texObj ); + texObj->DriverData = t; + } } - - /* Bind to the given texture unit. - */ - rmesa->CurrentTexObj[unit] = t; - t->bound |= unit + 1; - - rmesa->new_state |= RADEON_NEW_TEXTURE; } -static void radeonDDDeleteTexture( GLcontext *ctx, - struct gl_texture_object *tObj ) +static void radeonDeleteTexture( GLcontext *ctx, + struct gl_texture_object *texObj ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - radeonTexObjPtr t = (radeonTexObjPtr)tObj->DriverData; + radeonTexObjPtr t = (radeonTexObjPtr) texObj->DriverData; - if ( RADEON_DEBUG & DEBUG_VERBOSE_API ) { - fprintf( stderr, __FUNCTION__ "( %p )\n", tObj ); + if ( RADEON_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) { + fprintf( stderr, __FUNCTION__"( %p )\n", texObj ); } if ( t ) { - if ( t->bound ) { - FLUSH_BATCH( rmesa ); - if ( t->bound & TEX_0 ) rmesa->CurrentTexObj[0] = NULL; - if ( t->bound & TEX_1 ) rmesa->CurrentTexObj[1] = NULL; - rmesa->new_state |= RADEON_NEW_TEXTURE; + if ( rmesa ) { + RADEON_FIREVERTICES( rmesa ); } - radeonDestroyTexObj( rmesa, t ); - tObj->DriverData = NULL; + texObj->DriverData = NULL; } } -static GLboolean radeonDDIsTextureResident( GLcontext *ctx, - struct gl_texture_object *tObj ) +static GLboolean radeonIsTextureResident( GLcontext *ctx, + struct gl_texture_object *texObj ) { - radeonTexObjPtr t = (radeonTexObjPtr)tObj->DriverData; + radeonTexObjPtr t = (radeonTexObjPtr) texObj->DriverData; return ( t && t->memBlock ); } -static void radeonDDInitTextureObjects( GLcontext *ctx ) + +static void radeonInitTextureObjects( GLcontext *ctx ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); struct gl_texture_object *texObj; @@ -917,44 +583,79 @@ static void radeonDDInitTextureObjects( GLcontext *ctx ) ctx->Texture.CurrentUnit = 0; - texObj = ctx->Texture.Unit[0].CurrentD[1]; - radeonDDBindTexture( ctx, GL_TEXTURE_1D, texObj ); - move_to_tail( &rmesa->SwappedOut, (radeonTexObjPtr)texObj->DriverData ); + texObj = ctx->Texture.Unit[0].Current1D; + radeonBindTexture( ctx, GL_TEXTURE_1D, texObj ); + move_to_tail( &rmesa->texture.swapped, + (radeonTexObjPtr)texObj->DriverData ); - texObj = ctx->Texture.Unit[0].CurrentD[2]; - radeonDDBindTexture( ctx, GL_TEXTURE_2D, texObj ); - move_to_tail( &rmesa->SwappedOut, (radeonTexObjPtr)texObj->DriverData ); + texObj = ctx->Texture.Unit[0].Current2D; + radeonBindTexture( ctx, GL_TEXTURE_2D, texObj ); + move_to_tail( &rmesa->texture.swapped, + (radeonTexObjPtr)texObj->DriverData ); ctx->Texture.CurrentUnit = 1; - texObj = ctx->Texture.Unit[1].CurrentD[1]; - radeonDDBindTexture( ctx, GL_TEXTURE_1D, texObj ); - move_to_tail( &rmesa->SwappedOut, (radeonTexObjPtr)texObj->DriverData ); + texObj = ctx->Texture.Unit[1].Current1D; + radeonBindTexture( ctx, GL_TEXTURE_1D, texObj ); + move_to_tail( &rmesa->texture.swapped, + (radeonTexObjPtr)texObj->DriverData ); - texObj = ctx->Texture.Unit[1].CurrentD[2]; - radeonDDBindTexture( ctx, GL_TEXTURE_2D, texObj ); - move_to_tail( &rmesa->SwappedOut, (radeonTexObjPtr)texObj->DriverData ); + texObj = ctx->Texture.Unit[1].Current2D; + radeonBindTexture( ctx, GL_TEXTURE_2D, texObj ); + move_to_tail( &rmesa->texture.swapped, + (radeonTexObjPtr)texObj->DriverData ); ctx->Texture.CurrentUnit = tmp; } -void radeonDDInitTextureFuncs( GLcontext *ctx ) +/* Need: + * - Same GEN_MODE for all active bits + * - Same EyePlane/ObjPlane for all active bits when using Eye/Obj + * - STRQ presumably all supported (matrix means incoming R values + * can end up in STQ, this has implications for vertex support, + * presumably ok if maos is used, though?) + * + * Basically impossible to do this on the fly - just collect some + * basic info & do the checks from ValidateState(). + */ +static void radeonTexGen( GLcontext *ctx, + GLenum coord, + GLenum pname, + const GLfloat *params ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + GLuint unit = ctx->Texture.CurrentUnit; + rmesa->recheck_texgen[unit] = GL_TRUE; +} + + +void radeonInitTextureFuncs( GLcontext *ctx ) { - ctx->Driver.TexImage1D = radeonDDTexImage1D; - ctx->Driver.TexImage2D = radeonDDTexImage2D; - ctx->Driver.TexImage3D = NULL; (void) radeonDDTexImage3D; - ctx->Driver.TexSubImage1D = radeonDDTexSubImage1D; - ctx->Driver.TexSubImage2D = radeonDDTexSubImage2D; - ctx->Driver.TexSubImage3D = NULL; (void) radeonDDTexSubImage3D; - ctx->Driver.GetTexImage = radeonDDGetTexImage; - ctx->Driver.TexEnv = radeonDDTexEnv; - ctx->Driver.TexParameter = radeonDDTexParameter; - ctx->Driver.BindTexture = radeonDDBindTexture; - ctx->Driver.DeleteTexture = radeonDDDeleteTexture; - ctx->Driver.IsTextureResident = radeonDDIsTextureResident; + ctx->Driver.ChooseTextureFormat = radeonChooseTextureFormat; + ctx->Driver.TexImage1D = radeonTexImage1D; + ctx->Driver.TexImage2D = radeonTexImage2D; + ctx->Driver.TexImage3D = _mesa_store_teximage3d; + ctx->Driver.TexSubImage1D = radeonTexSubImage1D; + ctx->Driver.TexSubImage2D = radeonTexSubImage2D; + ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d; + ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d; + ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d; + ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d; + ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d; + ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d; + ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage; + + ctx->Driver.BindTexture = radeonBindTexture; + ctx->Driver.CreateTexture = NULL; /* FIXME: Is this used??? */ + ctx->Driver.DeleteTexture = radeonDeleteTexture; + ctx->Driver.IsTextureResident = radeonIsTextureResident; ctx->Driver.PrioritizeTexture = NULL; ctx->Driver.ActiveTexture = NULL; ctx->Driver.UpdateTexturePalette = NULL; - radeonDDInitTextureObjects( ctx ); + ctx->Driver.TexEnv = radeonTexEnv; + ctx->Driver.TexParameter = radeonTexParameter; + ctx->Driver.TexGen = radeonTexGen; + + radeonInitTextureObjects( ctx ); } diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_texstate.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_texstate.c index fb78e2a1f..65d9cb89b 100644 --- a/xc/lib/GL/mesa/src/drv/radeon/radeon_texstate.c +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_texstate.c @@ -875,12 +875,13 @@ static void radeonUpdateTextureEnv( GLcontext *ctx, int unit ) break; case GL_MODULATE: case GL_ADD: - case GL_ADD_SIGNED_EXT: + case GL_ADD_SIGNED: + case GL_SUBTRACT: case GL_DOT3_RGB_EXT: case GL_DOT3_RGBA_EXT: numColorArgs = 2; break; - case GL_INTERPOLATE_EXT: + case GL_INTERPOLATE: numColorArgs = 3; break; default: @@ -893,10 +894,11 @@ static void radeonUpdateTextureEnv( GLcontext *ctx, int unit ) break; case GL_MODULATE: case GL_ADD: - case GL_ADD_SIGNED_EXT: + case GL_ADD_SIGNED: + case GL_SUBTRACT: numAlphaArgs = 2; break; - case GL_INTERPOLATE_EXT: + case GL_INTERPOLATE: numAlphaArgs = 3; break; default: @@ -914,13 +916,13 @@ static void radeonUpdateTextureEnv( GLcontext *ctx, int unit ) case GL_TEXTURE: color_arg[i] = radeon_texture_color[op][unit]; break; - case GL_CONSTANT_EXT: + case GL_CONSTANT: color_arg[i] = radeon_tfactor_color[op]; break; - case GL_PRIMARY_COLOR_EXT: + case GL_PRIMARY_COLOR: color_arg[i] = radeon_primary_color[op]; break; - case GL_PREVIOUS_EXT: + case GL_PREVIOUS: color_arg[i] = radeon_previous_color[op]; break; default: @@ -936,13 +938,13 @@ static void radeonUpdateTextureEnv( GLcontext *ctx, int unit ) case GL_TEXTURE: alpha_arg[i] = radeon_texture_alpha[op][unit]; break; - case GL_CONSTANT_EXT: + case GL_CONSTANT: alpha_arg[i] = radeon_tfactor_alpha[op]; break; - case GL_PRIMARY_COLOR_EXT: + case GL_PRIMARY_COLOR: alpha_arg[i] = radeon_primary_alpha[op]; break; - case GL_PREVIOUS_EXT: + case GL_PREVIOUS: alpha_arg[i] = radeon_previous_alpha[op]; break; default: @@ -976,7 +978,7 @@ static void radeonUpdateTextureEnv( GLcontext *ctx, int unit ) RADEON_COLOR_ARG( 0, A ); RADEON_COLOR_ARG( 1, C ); break; - case GL_ADD_SIGNED_EXT: + case GL_ADD_SIGNED: color_combine = (RADEON_COLOR_ARG_B_ZERO | RADEON_COMP_ARG_B | RADEON_BLEND_CTL_ADDSIGNED | @@ -984,7 +986,15 @@ static void radeonUpdateTextureEnv( GLcontext *ctx, int unit ) RADEON_COLOR_ARG( 0, A ); RADEON_COLOR_ARG( 1, C ); break; - case GL_INTERPOLATE_EXT: + case GL_SUBTRACT: + color_combine = (RADEON_COLOR_ARG_B_ZERO | + RADEON_COMP_ARG_B | + RADEON_BLEND_CTL_SUBTRACT | + RADEON_CLAMP_TX); + RADEON_COLOR_ARG( 0, A ); + RADEON_COLOR_ARG( 1, C ); + break; + case GL_INTERPOLATE: color_combine = (RADEON_BLEND_CTL_BLEND | RADEON_CLAMP_TX); RADEON_COLOR_ARG( 0, B ); @@ -1026,7 +1036,7 @@ static void radeonUpdateTextureEnv( GLcontext *ctx, int unit ) RADEON_ALPHA_ARG( 0, A ); RADEON_ALPHA_ARG( 1, C ); break; - case GL_ADD_SIGNED_EXT: + case GL_ADD_SIGNED: alpha_combine = (RADEON_ALPHA_ARG_B_ZERO | RADEON_COMP_ARG_B | RADEON_BLEND_CTL_ADDSIGNED | @@ -1034,7 +1044,15 @@ static void radeonUpdateTextureEnv( GLcontext *ctx, int unit ) RADEON_ALPHA_ARG( 0, A ); RADEON_ALPHA_ARG( 1, C ); break; - case GL_INTERPOLATE_EXT: + case GL_SUBTRACT: + alpha_combine = (RADEON_COLOR_ARG_B_ZERO | + RADEON_COMP_ARG_B | + RADEON_BLEND_CTL_SUBTRACT | + RADEON_CLAMP_TX); + RADEON_ALPHA_ARG( 0, A ); + RADEON_ALPHA_ARG( 1, C ); + break; + case GL_INTERPOLATE: alpha_combine = (RADEON_BLEND_CTL_BLEND | RADEON_CLAMP_TX); RADEON_ALPHA_ARG( 0, B ); diff --git a/xc/lib/GL/mesa/src/drv/tdfx/tdfx_state.c b/xc/lib/GL/mesa/src/drv/tdfx/tdfx_state.c index 7485f6ea1..53e7920ee 100644 --- a/xc/lib/GL/mesa/src/drv/tdfx/tdfx_state.c +++ b/xc/lib/GL/mesa/src/drv/tdfx/tdfx_state.c @@ -32,19 +32,26 @@ * Authors: * Gareth Hughes <gareth@valinux.com> * Brian Paul <brianp@valinux.com> + * Keith Whitwell <keithw@valinux.com> (port to 3.5) * */ -#include "types.h" -#include "pb.h" +#include "mtypes.h" +#include "texformat.h" +#include "texstore.h" -#include "dri_glide.h" +#include "swrast/swrast.h" +#include "array_cache/acache.h" +#include "tnl/tnl.h" +#include "tnl/t_pipeline.h" +#include "swrast_setup/swrast_setup.h" #include "tdfx_context.h" #include "tdfx_state.h" #include "tdfx_vb.h" #include "tdfx_tex.h" #include "tdfx_texman.h" +#include "tdfx_texstate.h" #include "tdfx_tris.h" #include "tdfx_render.h" @@ -60,7 +67,6 @@ static void tdfxUpdateAlphaMode( GLcontext *ctx ) GrCmpFnc_t func; GrAlphaBlendFnc_t srcRGB, dstRGB, srcA, dstA; GrAlpha_t ref = ctx->Color.AlphaRef; - const int hasAlpha = ctx->Visual->AlphaBits > 0; if ( TDFX_DEBUG & DEBUG_VERBOSE_API ) { fprintf( stderr, "%s()\n", __FUNCTION__ ); @@ -120,13 +126,13 @@ static void tdfxUpdateAlphaMode( GLcontext *ctx ) srcRGB = GR_BLEND_ONE_MINUS_SRC_ALPHA; break; case GL_DST_ALPHA: - srcRGB = hasAlpha ? GR_BLEND_DST_ALPHA : GR_BLEND_ONE; + srcRGB = GR_BLEND_DST_ALPHA; break; case GL_ONE_MINUS_DST_ALPHA: - srcRGB = hasAlpha ? GR_BLEND_ONE_MINUS_DST_ALPHA : GR_BLEND_ZERO; + srcRGB = GR_BLEND_ONE_MINUS_DST_ALPHA; break; case GL_SRC_ALPHA_SATURATE: - srcRGB = hasAlpha ? GR_BLEND_ALPHA_SATURATE : GR_BLEND_ZERO; + srcRGB = GR_BLEND_ALPHA_SATURATE; break; default: srcRGB = GR_BLEND_ONE; @@ -139,23 +145,23 @@ static void tdfxUpdateAlphaMode( GLcontext *ctx ) case GL_ONE: srcA = GR_BLEND_ONE; break; - case GL_DST_COLOR: /* Napalm only */ - srcA = hasAlpha ? GR_BLEND_DST_ALPHA : GR_BLEND_ONE; + case GL_DST_COLOR: + srcA = GR_BLEND_DST_ALPHA; /* Napalm only */ break; - case GL_ONE_MINUS_DST_COLOR: /* Napalm only */ - srcA = hasAlpha ? GR_BLEND_ONE_MINUS_DST_ALPHA : GR_BLEND_ZERO; + case GL_ONE_MINUS_DST_COLOR: + srcA = GR_BLEND_ONE_MINUS_DST_ALPHA; /* Napalm only */ break; - case GL_SRC_ALPHA: /* Napalm only */ - srcA = GR_BLEND_SRC_ALPHA; + case GL_SRC_ALPHA: + srcA = GR_BLEND_SRC_ALPHA; /* Napalm only */ break; - case GL_ONE_MINUS_SRC_ALPHA: /* Napalm only */ - srcA = GR_BLEND_ONE_MINUS_SRC_ALPHA; + case GL_ONE_MINUS_SRC_ALPHA: + srcA = GR_BLEND_ONE_MINUS_SRC_ALPHA; /* Napalm only */ break; - case GL_DST_ALPHA: /* Napalm only */ - srcA = hasAlpha ? GR_BLEND_DST_ALPHA : GR_BLEND_ONE; + case GL_DST_ALPHA: + srcA = GR_BLEND_DST_ALPHA; /* Napalm only */ break; - case GL_ONE_MINUS_DST_ALPHA: /* Napalm only */ - srcA = hasAlpha ? GR_BLEND_ONE_MINUS_DST_ALPHA : GR_BLEND_ZERO; + case GL_ONE_MINUS_DST_ALPHA: + srcA = GR_BLEND_ONE_MINUS_DST_ALPHA; /* Napalm only */ break; case GL_SRC_ALPHA_SATURATE: srcA = GR_BLEND_ONE; @@ -184,10 +190,10 @@ static void tdfxUpdateAlphaMode( GLcontext *ctx ) dstRGB = GR_BLEND_ONE_MINUS_SRC_ALPHA; break; case GL_DST_ALPHA: - dstRGB = hasAlpha ? GR_BLEND_DST_ALPHA : GR_BLEND_ONE; + dstRGB = GR_BLEND_DST_ALPHA; break; case GL_ONE_MINUS_DST_ALPHA: - dstRGB = hasAlpha ? GR_BLEND_ONE_MINUS_DST_ALPHA : GR_BLEND_ZERO; + dstRGB = GR_BLEND_ONE_MINUS_DST_ALPHA; break; default: dstRGB = GR_BLEND_ZERO; @@ -200,23 +206,23 @@ static void tdfxUpdateAlphaMode( GLcontext *ctx ) case GL_ONE: dstA = GR_BLEND_ONE; break; - case GL_SRC_COLOR: /* Napalm only */ - dstA = GR_BLEND_SRC_ALPHA; + case GL_SRC_COLOR: + dstA = GR_BLEND_SRC_ALPHA; /* Napalm only */ break; - case GL_ONE_MINUS_SRC_COLOR: /* Napalm only */ - dstA = GR_BLEND_ONE_MINUS_SRC_ALPHA; + case GL_ONE_MINUS_SRC_COLOR: + dstA = GR_BLEND_ONE_MINUS_SRC_ALPHA; /* Napalm only */ break; - case GL_SRC_ALPHA: /* Napalm only */ - dstA = GR_BLEND_SRC_ALPHA; + case GL_SRC_ALPHA: + dstA = GR_BLEND_SRC_ALPHA; /* Napalm only */ break; - case GL_ONE_MINUS_SRC_ALPHA: /* Napalm only */ - dstA = GR_BLEND_ONE_MINUS_SRC_ALPHA; + case GL_ONE_MINUS_SRC_ALPHA: + dstA = GR_BLEND_ONE_MINUS_SRC_ALPHA; /* Napalm only */ break; - case GL_DST_ALPHA: /* Napalm only */ - dstA = hasAlpha ? GR_BLEND_DST_ALPHA : GR_BLEND_ONE; + case GL_DST_ALPHA: + dstA = GR_BLEND_DST_ALPHA; /* Napalm only */ break; - case GL_ONE_MINUS_DST_ALPHA: /* Napalm only */ - dstA = hasAlpha ? GR_BLEND_ONE_MINUS_DST_ALPHA : GR_BLEND_ZERO; + case GL_ONE_MINUS_DST_ALPHA: + dstA = GR_BLEND_ONE_MINUS_DST_ALPHA; /* Napalm only */ break; default: dstA = GR_BLEND_ZERO; @@ -251,7 +257,7 @@ static void tdfxUpdateAlphaMode( GLcontext *ctx ) } } -static void tdfxDDAlphaFunc( GLcontext *ctx, GLenum func, GLclampf ref ) +static void tdfxDDAlphaFunc( GLcontext *ctx, GLenum func, GLchan ref ) { tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx ); @@ -265,11 +271,6 @@ static void tdfxDDBlendEquation( GLcontext *ctx, GLenum mode ) FLUSH_BATCH( fxMesa ); fxMesa->new_state |= TDFX_NEW_ALPHA; - - if (ctx->Color.ColorLogicOpEnabled && ctx->Color.LogicOp != GL_COPY) - fxMesa->Fallback |= TDFX_FALLBACK_LOGICOP; - else - fxMesa->Fallback &= ~TDFX_FALLBACK_LOGICOP; } static void tdfxDDBlendFunc( GLcontext *ctx, GLenum sfactor, GLenum dfactor ) @@ -300,7 +301,7 @@ static void tdfxDDBlendFuncSeparate( GLcontext *ctx, * Stipple */ -static void tdfxUpdateStipple( GLcontext *ctx ) +void tdfxUpdateStipple( GLcontext *ctx ) { tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx ); GrStippleMode_t mode = GR_STIPPLE_DISABLE; @@ -333,9 +334,9 @@ static void tdfxUpdateZMode( GLcontext *ctx ) FxI32 bias; FxBool mask; - if ( TDFX_DEBUG & DEBUG_VERBOSE_API ) { + if ( TDFX_DEBUG & DEBUG_VERBOSE_API ) fprintf( stderr, "%s()\n", __FUNCTION__ ); - } + bias = (FxI32) (ctx->Polygon.OffsetUnits * TDFX_DEPTH_BIAS_SCALE); @@ -381,7 +382,7 @@ static void tdfxUpdateZMode( GLcontext *ctx ) mask = FXFALSE; /* zbuffer is not touched */ } - fxMesa->Depth.Clear = (FxU32) (((1 << fxMesa->glVis->DepthBits) - 1) + fxMesa->Depth.Clear = (FxU32) (((1 << fxMesa->glCtx->Visual.depthBits) - 1) * ctx->Depth.Clear); if ( fxMesa->Depth.Bias != bias ) { @@ -451,7 +452,7 @@ static GrStencil_t convertGLStencilOp( GLenum op ) case GL_DECR_WRAP_EXT: return GR_STENCILOP_DECR_WRAP; default: - gl_problem( NULL, "bad stencil op in convertGLStencilOp" ); + _mesa_problem( NULL, "bad stencil op in convertGLStencilOp" ); } return GR_STENCILOP_KEEP; /* never get, silence compiler warning */ } @@ -547,14 +548,14 @@ static void tdfxUpdateFogAttrib( GLcontext *ctx ) { switch( ctx->Fog.Mode ) { case GL_EXP: - fxMesa->Glide.guFogGenerateExp(fxMesa->Fog.Table, ctx->Fog.Density); + fxMesa->Glide.guFogGenerateExp( fxMesa->Fog.Table, ctx->Fog.Density ); break; case GL_EXP2: - fxMesa->Glide.guFogGenerateExp2(fxMesa->Fog.Table, ctx->Fog.Density); + fxMesa->Glide.guFogGenerateExp2( fxMesa->Fog.Table, ctx->Fog.Density); break; case GL_LINEAR: - fxMesa->Glide.guFogGenerateLinear(fxMesa->Fog.Table, - ctx->Fog.Start, ctx->Fog.End); + fxMesa->Glide.guFogGenerateLinear( fxMesa->Fog.Table, + ctx->Fog.Start, ctx->Fog.End ); break; } @@ -619,6 +620,7 @@ void tdfxUpdateClipping( GLcontext *ctx ) fxMesa->height = dPriv->h; fxMesa->y_delta = fxMesa->screen_height - fxMesa->y_offset - fxMesa->height; + tdfxUpdateViewport( ctx ); } if (fxMesa->scissoredClipRects && fxMesa->pClipRects) { @@ -678,18 +680,15 @@ void tdfxUpdateClipping( GLcontext *ctx ) * Culling */ -static void tdfxUpdateCull( GLcontext *ctx ) +void tdfxUpdateCull( GLcontext *ctx ) { tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); GrCullMode_t mode = GR_CULL_DISABLE; - if ( TDFX_DEBUG & DEBUG_VERBOSE_API ) { - fprintf( stderr, "%s()\n", __FUNCTION__ ); - } - - if ( ctx->Polygon.CullFlag && - (ctx->PB->primitive == GL_POLYGON || - ctx->PB->primitive == GL_BITMAP) ) { + /* KW: don't need to check raster_primitive here as we don't + * attempt to draw lines or points with triangles. + */ + if ( ctx->Polygon.CullFlag ) { switch ( ctx->Polygon.CullFaceMode ) { case GL_FRONT: if ( ctx->Polygon.FrontFace == GL_CCW ) { @@ -708,8 +707,11 @@ static void tdfxUpdateCull( GLcontext *ctx ) break; case GL_FRONT_AND_BACK: + /* Handled as a fallback on triangles in tdfx_tris.c */ + return; + default: - mode = GR_CULL_DISABLE; + ASSERT(0); break; } } @@ -762,32 +764,13 @@ static void tdfxDDLineWidth( GLcontext *ctx, GLfloat width ) } - /* ============================================================= * Color Attributes */ -static void tdfxDDLogicOp( GLcontext *ctx, GLenum opcode ) -{ - tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); - - if (ctx->Color.ColorLogicOpEnabled) - { - FLUSH_BATCH( fxMesa ); - - if (opcode == GL_COPY) - fxMesa->Fallback &= ~TDFX_FALLBACK_LOGICOP; - else - fxMesa->Fallback |= TDFX_FALLBACK_LOGICOP; - } - else - fxMesa->Fallback &= ~TDFX_FALLBACK_LOGICOP; -} - - -static GLboolean tdfxDDColorMask( GLcontext *ctx, - GLboolean r, GLboolean g, - GLboolean b, GLboolean a ) +static void tdfxDDColorMask( GLcontext *ctx, + GLboolean r, GLboolean g, + GLboolean b, GLboolean a ) { tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); @@ -803,48 +786,22 @@ static GLboolean tdfxDDColorMask( GLcontext *ctx, fxMesa->Color.ColorMask[ACOMP] = a; fxMesa->dirty |= TDFX_UPLOAD_COLOR_MASK; - if (ctx->Visual->RedBits < 8) { + if (ctx->Visual.redBits < 8) { /* Can't do RGB colormasking in 16bpp mode. */ /* We can completely ignore the alpha mask. */ - if (r != g || g != b) { - fxMesa->Fallback |= TDFX_FALLBACK_COLORMASK; - } - else { - fxMesa->Fallback &= ~TDFX_FALLBACK_COLORMASK; - } + FALLBACK( fxMesa, TDFX_FALLBACK_COLORMASK, (r != g || g != b) ); } } - - return GL_FALSE; /* This forces the software paths to do colormasking. */ - /* This function will return void when we use Mesa 3.5 */ } -static void tdfxDDColor( GLcontext *ctx, - GLubyte r, GLubyte g, GLubyte b, GLubyte a ) -{ - tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); - GrColor_t color; - - FLUSH_BATCH( fxMesa ); - - color = tdfxPackColor( fxMesa->fxScreen->cpp, r, g, b, a ); - - if ( fxMesa->Color.MonoColor != color ) { - fxMesa->Color.MonoColor = color; - fxMesa->dirty |= TDFX_UPLOAD_CONSTANT_COLOR; - } -} static void tdfxDDClearColor( GLcontext *ctx, - GLubyte red, GLubyte green, - GLubyte blue, GLubyte alpha ) + const GLchan color[4] ) { tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); - FLUSH_BATCH( fxMesa ); - - fxMesa->Color.ClearColor = TDFXPACKCOLOR888( red, green, blue ); - fxMesa->Color.ClearAlpha = alpha; + fxMesa->Color.ClearColor = TDFXPACKCOLOR888( color[0], color[1], color[2] ); + fxMesa->Color.ClearAlpha = color[3]; } @@ -858,14 +815,9 @@ static void tdfxDDLightModelfv( GLcontext *ctx, GLenum pname, tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); if ( pname == GL_LIGHT_MODEL_COLOR_CONTROL ) { - FLUSH_BATCH( fxMesa ); - - fxMesa->Fallback &= ~TDFX_FALLBACK_SPECULAR; - - if ( ctx->Light.Enabled && - ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR ) { - fxMesa->Fallback |= TDFX_FALLBACK_SPECULAR; - } + FALLBACK( fxMesa, TDFX_FALLBACK_SPECULAR, + (ctx->Light.Enabled && + ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR )); } } @@ -906,12 +858,20 @@ static void tdfxUpdateRenderAttrib( GLcontext *ctx ) * Viewport */ -static void tdfxUpdateViewport( GLcontext *ctx ) +void tdfxUpdateViewport( GLcontext *ctx ) { - /* XXX: Implement this when we're doing clip coordinates */ - if ( TDFX_DEBUG & DEBUG_VERBOSE_API ) { - fprintf( stderr, "%s()\n", __FUNCTION__ ); - } + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); + const GLfloat *v = ctx->Viewport._WindowMap.m; + GLfloat *m = fxMesa->hw_viewport; + + m[MAT_SX] = v[MAT_SX]; + m[MAT_TX] = v[MAT_TX] + fxMesa->x_offset + TRI_X_OFFSET; + m[MAT_SY] = v[MAT_SY]; + m[MAT_TY] = v[MAT_TY] + fxMesa->y_delta + TRI_Y_OFFSET; + m[MAT_SZ] = v[MAT_SZ]; + m[MAT_TZ] = v[MAT_TZ]; + + fxMesa->SetupNewInputs |= VERT_CLIP; } @@ -924,7 +884,7 @@ static void tdfxDDViewport( GLcontext *ctx, GLint x, GLint y, } -static void tdfxDDNearFar( GLcontext *ctx, GLfloat nearVal, GLfloat farVal ) +static void tdfxDDDepthRange( GLcontext *ctx, GLclampd nearVal, GLclampd farVal ) { tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); FLUSH_BATCH( fxMesa ); @@ -949,11 +909,9 @@ static void tdfxDDEnable( GLcontext *ctx, GLenum cap, GLboolean state ) case GL_BLEND: FLUSH_BATCH( fxMesa ); fxMesa->new_state |= TDFX_NEW_ALPHA; - - if (ctx->Color.ColorLogicOpEnabled && ctx->Color.LogicOp != GL_COPY) - fxMesa->Fallback |= TDFX_FALLBACK_LOGICOP; - else - fxMesa->Fallback &= ~TDFX_FALLBACK_LOGICOP; + FALLBACK( fxMesa, TDFX_FALLBACK_LOGICOP, + (ctx->Color.ColorLogicOpEnabled && + ctx->Color.LogicOp != GL_COPY)); break; case GL_CULL_FACE: @@ -982,12 +940,15 @@ static void tdfxDDEnable( GLcontext *ctx, GLenum cap, GLboolean state ) break; case GL_COLOR_LOGIC_OP: - FLUSH_BATCH( fxMesa ); - if ( state && ctx->Color.LogicOp != GL_COPY ) { - fxMesa->Fallback |= TDFX_FALLBACK_LOGICOP; - } else { - fxMesa->Fallback &= ~TDFX_FALLBACK_LOGICOP; - } + FALLBACK( fxMesa, TDFX_FALLBACK_LOGICOP, + (ctx->Color.ColorLogicOpEnabled && + ctx->Color.LogicOp != GL_COPY)); + break; + + case GL_LIGHTING: + FALLBACK( fxMesa, TDFX_FALLBACK_SPECULAR, + (ctx->Light.Enabled && + ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR )); break; case GL_LINE_SMOOTH: @@ -995,6 +956,10 @@ static void tdfxDDEnable( GLcontext *ctx, GLenum cap, GLboolean state ) fxMesa->new_state |= TDFX_NEW_LINE; break; + case GL_LINE_STIPPLE: + FALLBACK(fxMesa, TDFX_FALLBACK_LINE_STIPPLE, state); + break; + case GL_POLYGON_STIPPLE: FLUSH_BATCH(fxMesa); fxMesa->new_state |= TDFX_NEW_STIPPLE; @@ -1007,20 +972,13 @@ static void tdfxDDEnable( GLcontext *ctx, GLenum cap, GLboolean state ) case GL_STENCIL_TEST: FLUSH_BATCH( fxMesa ); - if (fxMesa->haveHwStencil) - fxMesa->new_state |= TDFX_NEW_STENCIL; - else if (state) - fxMesa->Fallback |= TDFX_FALLBACK_STENCIL; - else - fxMesa->Fallback &= ~TDFX_FALLBACK_STENCIL; + FALLBACK( fxMesa, TDFX_FALLBACK_STENCIL, state && !fxMesa->haveHwStencil); break; case GL_TEXTURE_1D: case GL_TEXTURE_3D: - if (state) - fxMesa->Fallback |= TDFX_FALLBACK_TEXTURE; - else - fxMesa->Fallback &= ~TDFX_FALLBACK_TEXTURE; + FLUSH_BATCH( fxMesa ); + FALLBACK( fxMesa, TDFX_FALLBACK_TEXTURE_1D_3D, state); /* wrong */ fxMesa->new_state |= TDFX_NEW_TEXTURE; break; @@ -1038,7 +996,7 @@ static void tdfxDDEnable( GLcontext *ctx, GLenum cap, GLboolean state ) /* Set the buffer used for drawing */ /* XXX support for separate read/draw buffers hasn't been tested */ -static GLboolean tdfxDDSetDrawBuffer( GLcontext *ctx, GLenum mode ) +static void tdfxDDSetDrawBuffer( GLcontext *ctx, GLenum mode ) { tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); @@ -1048,57 +1006,32 @@ static GLboolean tdfxDDSetDrawBuffer( GLcontext *ctx, GLenum mode ) FLUSH_BATCH( fxMesa ); - fxMesa->Fallback &= ~TDFX_FALLBACK_BUFFER; - - switch ( mode ) { + switch( mode) { case GL_FRONT_LEFT: - fxMesa->DrawBuffer = GR_BUFFER_FRONTBUFFER; + fxMesa->DrawBuffer = fxMesa->ReadBuffer = GR_BUFFER_FRONTBUFFER; fxMesa->new_state |= TDFX_NEW_RENDER; - return GL_TRUE; + FALLBACK( fxMesa, TDFX_FALLBACK_DRAW_BUFFER, GL_FALSE ); + break; case GL_BACK_LEFT: - fxMesa->DrawBuffer = GR_BUFFER_BACKBUFFER; + fxMesa->DrawBuffer = fxMesa->ReadBuffer = GR_BUFFER_BACKBUFFER; fxMesa->new_state |= TDFX_NEW_RENDER; - return GL_TRUE; + FALLBACK( fxMesa, TDFX_FALLBACK_DRAW_BUFFER, GL_FALSE ); + break; case GL_NONE: FX_grColorMaskv( ctx, false4 ); - return GL_TRUE; - - default: - fxMesa->Fallback |= TDFX_FALLBACK_BUFFER; - return GL_FALSE; - } -} - - -/* Set the buffer used for reading */ -/* XXX support for separate read/draw buffers hasn't been tested */ -static void tdfxDDSetReadBuffer( GLcontext *ctx, - GLframebuffer *buffer, GLenum mode ) -{ - tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); - (void) buffer; - - FLUSH_BATCH( fxMesa ); - - fxMesa->Fallback &= ~TDFX_FALLBACK_BUFFER; - - switch ( mode ) { - case GL_FRONT_LEFT: - fxMesa->ReadBuffer = GR_BUFFER_FRONTBUFFER; - break; - - case GL_BACK_LEFT: - fxMesa->ReadBuffer = GR_BUFFER_BACKBUFFER; + FALLBACK( fxMesa, TDFX_FALLBACK_DRAW_BUFFER, GL_FALSE ); break; default: - fxMesa->Fallback |= TDFX_FALLBACK_BUFFER; + FALLBACK( fxMesa, TDFX_FALLBACK_DRAW_BUFFER, GL_TRUE ); break; } } + + /* ============================================================= * Polygon stipple */ @@ -1109,12 +1042,30 @@ static void tdfxDDPolygonStipple( GLcontext *ctx, const GLubyte *mask ) const GLubyte *m = mask; GLubyte q[4]; int i,j,k; - int active = (ctx->Polygon.StippleFlag && ctx->PB->primitive == GL_POLYGON); + GLboolean allBitsSet; + +/* int active = (ctx->Polygon.StippleFlag && */ +/* fxMesa->reduced_prim == GL_TRIANGLES); */ FLUSH_BATCH(fxMesa); + fxMesa->Stipple.Pattern = 0xffffffff; + fxMesa->dirty |= TDFX_UPLOAD_STIPPLE; + fxMesa->new_state |= TDFX_NEW_STIPPLE; - if (active) { - ctx->Driver.TriangleCaps |= DD_TRI_STIPPLE; + /* Check if the stipple pattern is fully opaque. If so, use software + * rendering. This basically a trick to make sure the OpenGL conformance + * test passes. + */ + allBitsSet = GL_TRUE; + for (i = 0; i < 32; i++) { + if (((GLuint *) mask)[i] != 0xffffffff) { + allBitsSet = GL_FALSE; + break; + } + } + if (allBitsSet) { + fxMesa->haveHwStipple = GL_FALSE; + return; } q[0] = mask[0]; @@ -1126,43 +1077,24 @@ static void tdfxDDPolygonStipple( GLcontext *ctx, const GLubyte *mask ) for (j = 0 ; j < 4; j++) for (i = 0 ; i < 4 ; i++,m++) { if (*m != q[j]) { - ctx->Driver.TriangleCaps &= ~DD_TRI_STIPPLE; - fxMesa->Stipple.Pattern = 0xffffffff; /* ensure all pixels on */ + fxMesa->haveHwStipple = GL_FALSE; return; } } - /* We can do it, so flag an upload of the stipple pattern */ + fxMesa->haveHwStipple = GL_TRUE; fxMesa->Stipple.Pattern = ( (q[0] << 0) | (q[1] << 8) | (q[2] << 16) | (q[3] << 24) ); - fxMesa->dirty |= TDFX_UPLOAD_STIPPLE; } -/* Always called between RenderStart and RenderFinish --> We already - * hold the lock. - */ -static void tdfxDDReducedPrimitiveChange( GLcontext *ctx, GLenum prim ) -{ - tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx ); - - FLUSH_BATCH( fxMesa ); - tdfxUpdateCull(ctx); - if ( fxMesa->dirty & TDFX_UPLOAD_CULL ) { - fxMesa->Glide.grCullMode( fxMesa->CullMode ); - fxMesa->dirty &= ~TDFX_UPLOAD_CULL; - } -#if defined(__linux__) || defined(__FreeBSD__) - tdfxUpdateStipple(ctx); - if ( fxMesa->dirty & TDFX_UPLOAD_STIPPLE ) { - fxMesa->Glide.grStipplePattern ( fxMesa->Stipple.Pattern ); - fxMesa->Glide.grStippleMode ( fxMesa->Stipple.Mode ); - fxMesa->dirty &= ~TDFX_UPLOAD_STIPPLE; - } -#endif /* __linux__ || __FreeBSD__ */ +static void tdfxDDRenderMode( GLcontext *ctx, GLenum mode ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); + FALLBACK( fxMesa, TDFX_FALLBACK_RENDER_MODE, (mode != GL_RENDER) ); } @@ -1266,65 +1198,13 @@ void tdfxDDUpdateHwState( GLcontext *ctx ) } -static void tdfxDDRenderStart( GLcontext *ctx ) +static void tdfxDDInvalidateState( GLcontext *ctx, GLuint new_state ) { - tdfxDDUpdateHwState( ctx ); - LOCK_HARDWARE( TDFX_CONTEXT(ctx) ); -} - -static void tdfxDDRenderFinish( GLcontext *ctx ) -{ - UNLOCK_HARDWARE( TDFX_CONTEXT(ctx) ); -} - -#define INTERESTED (~(NEW_MODELVIEW | \ - NEW_PROJECTION | \ - NEW_TEXTURE_MATRIX | \ - NEW_USER_CLIP | \ - NEW_CLIENT_STATE | \ - NEW_TEXTURE_ENABLE)) - -static void tdfxDDUpdateState( GLcontext *ctx ) -{ - tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); - - if ( TDFX_DEBUG & DEBUG_VERBOSE_API ) { - fprintf( stderr, "%s()\n", __FUNCTION__ ); - } - - /* Have to do this here to detect texture, line fallbacks in time: - */ - if ( fxMesa->new_state & (TDFX_NEW_TEXTURE | TDFX_NEW_LINE) ) - tdfxDDUpdateHwState( ctx ); - - if ( ctx->NewState & INTERESTED ) { - tdfxDDChooseRenderState( ctx ); - } - - /* The choise of vertex setup function only depends on whether fog - * and/or texturing is enabled. - */ - if ( ctx->NewState & (NEW_FOG | NEW_TEXTURE_ENABLE | NEW_TEXTURING)) { - tdfxDDChooseRasterSetupFunc( ctx ); - } - - if ( 0 ) - fprintf( stderr, "fallback %x indirect %x\n", - fxMesa->Fallback, fxMesa->IndirectTriangles ); - - if ( fxMesa->Fallback ) { - ctx->IndirectTriangles |= ctx->TriangleCaps; - } - else { - ctx->IndirectTriangles &= ~DD_SW_RASTERIZE; - ctx->IndirectTriangles |= fxMesa->IndirectTriangles; - - ctx->Driver.PointsFunc = fxMesa->PointsFunc; - ctx->Driver.LineFunc = fxMesa->LineFunc; - ctx->Driver.TriangleFunc = fxMesa->TriangleFunc; - ctx->Driver.QuadFunc = fxMesa->QuadFunc; - ctx->Driver.RenderVBRawTab = fxMesa->RenderVBRawTab; - } + _swrast_InvalidateState( ctx, new_state ); + _swsetup_InvalidateState( ctx, new_state ); + _ac_InvalidateState( ctx, new_state ); + _tnl_InvalidateState( ctx, new_state ); + TDFX_CONTEXT(ctx)->new_gl_state |= new_state; } @@ -1405,7 +1285,7 @@ void tdfxInitState( tdfxContextPtr fxMesa ) fxMesa->TexState.Enabled = 0; } - if ( ctx->Visual->DBflag) { + if ( ctx->Visual.doubleBufferMode) { fxMesa->DrawBuffer = GR_BUFFER_BACKBUFFER; fxMesa->ReadBuffer = GR_BUFFER_BACKBUFFER; } else { @@ -1430,7 +1310,7 @@ void tdfxInitState( tdfxContextPtr fxMesa ) fxMesa->Color.Dither = GR_DITHER_2x2; - if ( fxMesa->glVis->DepthBits > 0 ) { + if ( fxMesa->glCtx->Visual.depthBits > 0 ) { fxMesa->Depth.Mode = GR_DEPTHBUFFER_ZBUFFER; } else { fxMesa->Depth.Mode = GR_DEPTHBUFFER_DISABLE; @@ -1486,31 +1366,18 @@ void tdfxDDInitStateFuncs( GLcontext *ctx ) { tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); - ctx->Driver.UpdateState = tdfxDDUpdateState; + ctx->Driver.UpdateState = tdfxDDInvalidateState; + + /* State notification callbacks: + */ ctx->Driver.ClearIndex = NULL; ctx->Driver.ClearColor = tdfxDDClearColor; - ctx->Driver.Index = NULL; - ctx->Driver.Color = tdfxDDColor; ctx->Driver.SetDrawBuffer = tdfxDDSetDrawBuffer; - ctx->Driver.SetReadBuffer = tdfxDDSetReadBuffer; ctx->Driver.IndexMask = NULL; ctx->Driver.ColorMask = tdfxDDColorMask; - ctx->Driver.NearFar = tdfxDDNearFar; - - ctx->Driver.RenderStart = tdfxDDRenderStart; - ctx->Driver.RenderFinish = tdfxDDRenderFinish; - ctx->Driver.RasterSetup = NULL; - - ctx->Driver.RenderVBClippedTab = NULL; - ctx->Driver.RenderVBCulledTab = NULL; - ctx->Driver.RenderVBRawTab = NULL; - - ctx->Driver.ReducedPrimitiveChange = tdfxDDReducedPrimitiveChange; - ctx->Driver.MultipassFunc = NULL; - ctx->Driver.AlphaFunc = tdfxDDAlphaFunc; ctx->Driver.BlendEquation = tdfxDDBlendEquation; ctx->Driver.BlendFunc = tdfxDDBlendFunc; @@ -1521,7 +1388,7 @@ void tdfxDDInitStateFuncs( GLcontext *ctx ) ctx->Driver.FrontFace = tdfxDDFrontFace; ctx->Driver.DepthFunc = tdfxDDDepthFunc; ctx->Driver.DepthMask = tdfxDDDepthMask; - ctx->Driver.DepthRange = NULL; + ctx->Driver.DepthRange = tdfxDDDepthRange; ctx->Driver.Enable = tdfxDDEnable; ctx->Driver.Fogfv = tdfxDDFogfv; ctx->Driver.Hint = NULL; @@ -1529,14 +1396,37 @@ void tdfxDDInitStateFuncs( GLcontext *ctx ) ctx->Driver.LightModelfv = tdfxDDLightModelfv; ctx->Driver.LineStipple = NULL; ctx->Driver.LineWidth = tdfxDDLineWidth; - ctx->Driver.LogicOpcode = tdfxDDLogicOp; -#if 0 - ctx->Driver.PolygonMode = NULL; -#endif ctx->Driver.PolygonStipple = tdfxDDPolygonStipple; + ctx->Driver.RenderMode = tdfxDDRenderMode; ctx->Driver.Scissor = tdfxDDScissor; ctx->Driver.ShadeModel = tdfxDDShadeModel; + ctx->Driver.BindTexture = tdfxDDBindTexture; + ctx->Driver.DeleteTexture = tdfxDDDeleteTexture; + ctx->Driver.TexEnv = tdfxDDTexEnv; + ctx->Driver.TexParameter = tdfxDDTexParameter; + ctx->Driver.ChooseTextureFormat = tdfxDDChooseTextureFormat; + ctx->Driver.TexImage2D = tdfxDDTexImage2D; + ctx->Driver.TexSubImage2D = tdfxDDTexSubImage2D; + /* + ctx->Driver.TexImage2D = _mesa_store_teximage2d; + ctx->Driver.TexSubImage2D = _mesa_store_texsubimage2d; + */ + + ctx->Driver.TexImage1D = _mesa_store_teximage1d; + ctx->Driver.TexImage3D = _mesa_store_teximage3d; + ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d; + ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d; + ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d; + ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d; + ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d; + ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d; + ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d; + ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage; + +/* ctx->Driver.GetTexImage = tdfxDDGetTexImage; */ + ctx->Driver.UpdateTexturePalette = tdfxDDTexturePalette; + if ( fxMesa->haveHwStencil ) { ctx->Driver.StencilFunc = tdfxDDStencilFunc; ctx->Driver.StencilMask = tdfxDDStencilMask; @@ -1548,4 +1438,12 @@ void tdfxDDInitStateFuncs( GLcontext *ctx ) } ctx->Driver.Viewport = tdfxDDViewport; + + + /* Swrast hooks for imaging extensions: + */ + ctx->Driver.CopyColorTable = _swrast_CopyColorTable; + ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable; + ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D; + ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D; } diff --git a/xc/programs/Xserver/GL/dri/dri.c b/xc/programs/Xserver/GL/dri/dri.c index 8b23df2fe..333e02d89 100644 --- a/xc/programs/Xserver/GL/dri/dri.c +++ b/xc/programs/Xserver/GL/dri/dri.c @@ -426,27 +426,27 @@ DRICloseScreen(ScreenPtr pScreen) pDRIInfo = pDRIPriv->pDriverInfo; /* Unwrap DRI Functions */ - if (pDRIPriv->wrap.ValidateTree) { + if (pDRIInfo->wrap.ValidateTree) { pScreen->ValidateTree = pDRIPriv->wrap.ValidateTree; pDRIPriv->wrap.ValidateTree = NULL; } - if (pDRIPriv->wrap.PostValidateTree) { + if (pDRIInfo->wrap.PostValidateTree) { pScreen->PostValidateTree = pDRIPriv->wrap.PostValidateTree; pDRIPriv->wrap.PostValidateTree = NULL; } - if (pDRIPriv->wrap.WindowExposures) { + if (pDRIInfo->wrap.WindowExposures) { pScreen->WindowExposures = pDRIPriv->wrap.WindowExposures; pDRIPriv->wrap.WindowExposures = NULL; } - if (pDRIPriv->wrap.CopyWindow) { + if (pDRIInfo->wrap.CopyWindow) { pScreen->CopyWindow = pDRIPriv->wrap.CopyWindow; pDRIPriv->wrap.CopyWindow = NULL; } - if (pDRIPriv->wrap.ClipNotify) { + if (pDRIInfo->wrap.ClipNotify) { pScreen->ClipNotify = pDRIPriv->wrap.ClipNotify; pDRIPriv->wrap.ClipNotify = NULL; } - if (pDRIPriv->wrap.AdjustFrame) { + if (pDRIInfo->wrap.AdjustFrame) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; pScrn->AdjustFrame = pDRIPriv->wrap.AdjustFrame; pDRIPriv->wrap.AdjustFrame = NULL; diff --git a/xc/programs/Xserver/dix/globals.c b/xc/programs/Xserver/dix/globals.c index fd0866b25..1601922a6 100644 --- a/xc/programs/Xserver/dix/globals.c +++ b/xc/programs/Xserver/dix/globals.c @@ -126,6 +126,7 @@ FontPtr defaultFont; /* not declared in dix.h to avoid including font.h in every compilation of dix code */ Bool loadableFonts = FALSE; CursorPtr rootCursor; +Bool blackRoot=FALSE; ClientPtr requestingClient; /* XXX this should be obsolete now, remove? */ TimeStamp currentTime; diff --git a/xc/programs/Xserver/dix/window.c b/xc/programs/Xserver/dix/window.c index 0313b43ef..df059c241 100644 --- a/xc/programs/Xserver/dix/window.c +++ b/xc/programs/Xserver/dix/window.c @@ -101,6 +101,7 @@ SOFTWARE. #endif extern Bool permitOldBugs; +extern Bool blackRoot; #if defined(NEED_SCREEN_REGIONS) #define REGION_PTR(pScreen,pWin) \ @@ -345,6 +346,9 @@ MakeRootTile(pWin) for (j = len; j > 0; j--) *to++ = *from; + if (blackRoot) + bzero(back, sizeof(back)); + (*pGC->ops->PutImage)((DrawablePtr)pWin->background.pixmap, pGC, 1, 0, 0, len, 4, 0, XYBitmap, (char *)back); diff --git a/xc/programs/Xserver/hw/xfree86/drivers/ati/r128_accel.c b/xc/programs/Xserver/hw/xfree86/drivers/ati/r128_accel.c index 1b7b0218e..23d65b487 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/ati/r128_accel.c +++ b/xc/programs/Xserver/hw/xfree86/drivers/ati/r128_accel.c @@ -1048,11 +1048,15 @@ void R128EngineInit(ScrnInfoPtr pScrn) R128WaitForFifo(pScrn, 1); #if X_BYTE_ORDER == X_BIG_ENDIAN - OUTREGP(R128_DP_DATATYPE, - R128_HOST_BIG_ENDIAN_EN, ~R128_HOST_BIG_ENDIAN_EN); -#else - OUTREGP(R128_DP_DATATYPE, 0, ~R128_HOST_BIG_ENDIAN_EN); + /* FIXME: this is a kludge for texture uploads in the 3D driver. Look at + * how the radeon driver handles HOST_DATA_SWAP if you want to implement + * CCE ImageWrite acceleration or anything needing this bit */ + if (!info->directRenderingEnabled) + OUTREGP(R128_DP_DATATYPE, + R128_HOST_BIG_ENDIAN_EN, ~R128_HOST_BIG_ENDIAN_EN); + else #endif + OUTREGP(R128_DP_DATATYPE, 0, ~R128_HOST_BIG_ENDIAN_EN); #ifdef XF86DRI info->sc_left = 0x00000000; diff --git a/xc/programs/Xserver/hw/xfree86/drivers/ati/r128_driver.c b/xc/programs/Xserver/hw/xfree86/drivers/ati/r128_driver.c index 2156a4203..fe8518bc9 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/ati/r128_driver.c +++ b/xc/programs/Xserver/hw/xfree86/drivers/ati/r128_driver.c @@ -277,18 +277,16 @@ static const char *drmSymbols[] = { "drmAgpUnbind", "drmAgpVendorId", "drmAvailable", + "drmCommandNone", + "drmCommandRead", + "drmCommandWrite", + "drmCommandWriteRead", "drmFreeVersion", + "drmGetLibVersion", "drmGetVersion", "drmMap", "drmMapBufs", "drmDMA", - "drmR128CleanupCCE", - "drmR128InitCCE", - "drmR128ResetCCE", - "drmR128StartCCE", - "drmR128StopCCE", - "drmR128WaitForIdleCCE", - "drmR128FlushIndirectBuffer", "drmScatterGatherAlloc", "drmScatterGatherFree", "drmUnmap", @@ -3415,6 +3413,15 @@ Bool R128EnterVT(int scrnIndex, int flags) #ifdef XF86DRI if (info->directRenderingEnabled) { + /* This seems to fix that !@#$ irritating switch to VT and back X-freeze + * that has been plaguing some DRI users. It seems that bus mastering + * is turned off on the video card when one switches to a VT and this + * needs to be reactivated when we get back, else things just stop. :) + * Based on Radeon driver fix by Charl P. Botha <http://cpbotha.net/> + * Mike A. Harris <mharris@redhat.com> + */ + xf86EnablePciBusMaster(info->PciInfo, TRUE); + R128CCE_START(pScrn, info); DRIUnlock(pScrn->pScreen); } diff --git a/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_accel.c b/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_accel.c index 78dacb9a8..8d74c85c9 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_accel.c +++ b/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_accel.c @@ -1756,11 +1756,11 @@ drmBufPtr RADEONCPGetBuffer( ScrnInfoPtr pScrn ) while ( 1 ) { do { ret = drmDMA( info->drmFD, &dma ); - if ( ret && ret != -EBUSY ) { + if ( ret && ret != -EAGAIN ) { xf86DrvMsg( pScrn->scrnIndex, X_ERROR, "%s: CP GetBuffer %d\n", __FUNCTION__, ret ); } - } while ( ( ret == -EBUSY ) && ( i++ < RADEON_TIMEOUT ) ); + } while ( ( ret == -EAGAIN ) && ( i++ < RADEON_TIMEOUT ) ); if ( ret == 0 ) { buf = &info->buffers->list[indx]; diff --git a/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c b/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c index 1f3b65eb8..b2f3b813b 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c +++ b/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c @@ -1064,7 +1064,7 @@ Bool RADEONDRIScreenInit(ScreenPtr pScreen) int req_minor, req_patch; if (info->IsR200) { - req_minor = 4; + req_minor = 5; req_patch = 0; } else { @@ -1402,8 +1402,8 @@ RADEONDRIShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf) pbox->y1, pbox->x1 + info->backX, pbox->y1 + info->backY, - pbox->x2 - pbox->x1, - pbox->y2 - pbox->y1); + pbox->x2 - pbox->x1 + 1, + pbox->y2 - pbox->y1 + 1); } } diff --git a/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c b/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c index 63a911921..580eaf0e4 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c +++ b/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c @@ -4454,7 +4454,14 @@ Bool RADEONEnterVT(int scrnIndex, int flags) RADEONEngineRestore(pScrn); #ifdef XF86DRI - if (RADEONPTR(pScrn)->directRenderingEnabled) { + if (info->directRenderingEnabled) { + /* This seems to fix that !@#$ irritating switch to VT and back X-freeze + * that has been plaguing some DRI users. It seems that bus mastering + * is turned off on the video card when one switches to a VT and this + * needs to be reactivated when we get back, else things just stop. :) + * Charl P. Botha <http://cpbotha.net/> */ + xf86EnablePciBusMaster(info->PciInfo, TRUE); + RADEONCP_START(pScrn, info); DRIUnlock(pScrn->pScreen); } diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_drv.h b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_drv.h index 45e145dc1..81ca644a4 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_drv.h +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_drv.h @@ -1221,27 +1221,83 @@ int DRM(unlock)( DRM_IOCTL_ARGS ) } #if DRM_LINUX +#define LINUX_IOCTL_DRM_MIN 0x6400 +#define LINUX_IOCTL_DRM_MAX 0x64ff + static linux_ioctl_function_t DRM( linux_ioctl); static struct linux_ioctl_handler DRM( handler) = {DRM( linux_ioctl), LINUX_IOCTL_DRM_MIN, LINUX_IOCTL_DRM_MAX}; SYSINIT (DRM( register), SI_SUB_KLD, SI_ORDER_MIDDLE, linux_ioctl_register_handler, &DRM( handler)); SYSUNINIT(DRM( unregister), SI_SUB_KLD, SI_ORDER_MIDDLE, linux_ioctl_unregister_handler, &DRM( handler)); +#define LINUX_IOC_VOID IOC_VOID +#define LINUX_IOC_IN IOC_OUT /* Linux has the values the other way around */ +#define LINUX_IOC_OUT IOC_IN + /* * Linux emulation IOCTL */ static int DRM(linux_ioctl)(DRM_STRUCTPROC *p, struct linux_ioctl_args* args) { + u_long cmd = args->cmd; +#define STK_PARAMS 128 + union { + char stkbuf[STK_PARAMS]; + long align; + } ubuf; + caddr_t data=NULL, memp=NULL; + u_int size = IOCPARM_LEN(cmd); + int error; #if (__FreeBSD_version >= 500000) - struct file *fp = p->td_proc->p_fd->fd_ofiles[args->fd]; + struct file *fp; #else - struct file *fp = p->p_fd->fd_ofiles[args->fd]; -#endif - u_long cmd = args->cmd; - caddr_t data = (caddr_t) args->arg; - /* - * Pass the ioctl off to our standard handler. - */ - return(fo_ioctl(fp, cmd, data, p)); + struct file *fp = p->p_fd->fd_ofiles[args->fd]; +#endif + if ( size > STK_PARAMS ) { + if ( size > IOCPARM_MAX ) + return EINVAL; + memp = malloc( (u_long)size, DRM(M_DRM), M_WAITOK ); + data = memp; + } else { + data = ubuf.stkbuf; + } + + if ( cmd & LINUX_IOC_IN ) { + if ( size ) { + error = copyin( (caddr_t)args->arg, data, (u_int)size ); + if (error) { + if ( memp ) + free( data, DRM(M_DRM) ); + return error; + } + } else { + data = (caddr_t)args->arg; + } + } else if ( (cmd & LINUX_IOC_OUT) && size ) { + /* + * Zero the buffer so the user always + * gets back something deterministic. + */ + bzero( data, size ); + } else if ( cmd & LINUX_IOC_VOID ) { + *(caddr_t *)data = (caddr_t)args->arg; + } + +#if (__FreeBSD_version >= 500000) + if ( (error = fget( p, args->fd, &fp )) != 0 ) { + if ( memp ) + free( memp, DRM(M_DRM) ); + return (error); + } + error = fo_ioctl( fp, cmd, data, p->td_ucred, p ); + fdrop( fp, p ); +#else + error = fo_ioctl( fp, cmd, data, p ); +#endif + if ( error == 0 && (cmd & LINUX_IOC_OUT) && size ) + error = copyout( data, (caddr_t)args->arg, (u_int)size ); + if ( memp ) + free( memp, DRM(M_DRM) ); + return error; } #endif /* DRM_LINUX */ diff --git a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_os_freebsd.h b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_os_freebsd.h index 238381394..6f878d4fa 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_os_freebsd.h +++ b/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_os_freebsd.h @@ -65,7 +65,6 @@ #include <sys/proc.h> #include <machine/../linux/linux.h> #include <machine/../linux/linux_proto.h> -#include "drm_linux.h" #endif #define DRM_TIME_SLICE (hz/20) /* Time slice for GLXContexts */ @@ -140,14 +139,18 @@ do { \ } \ } while (0) -#define DRM_COPY_TO_USER_IOCTL(arg1, arg2, arg3) \ - *arg1 = arg2 -#define DRM_COPY_FROM_USER_IOCTL(arg1, arg2, arg3) \ - arg1 = *arg2 -#define DRM_COPY_TO_USER(arg1, arg2, arg3) \ - copyout(arg2, arg1, arg3) -#define DRM_COPY_FROM_USER(arg1, arg2, arg3) \ - copyin(arg2, arg1, arg3) +#define DRM_COPY_TO_USER_IOCTL(user, kern, size) \ + if ( IOCPARM_LEN(cmd) != size) \ + return EINVAL; \ + *user = kern; +#define DRM_COPY_FROM_USER_IOCTL(kern, user, size) \ + if ( IOCPARM_LEN(cmd) != size) \ + return EINVAL; \ + kern = *user; +#define DRM_COPY_TO_USER(user, kern, size) \ + copyout(kern, user, size) +#define DRM_COPY_FROM_USER(kern, user, size) \ + copyin(user, kern, size) /* Macros for userspace access with checking readability once */ /* FIXME: can't find equivalent functionality for nocheck yet. * It's be slower than linux, but should be correct. diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Makefile.linux b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Makefile.linux index 893d49855..a8cd62a75 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Makefile.linux +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Makefile.linux @@ -254,12 +254,12 @@ ChangeLog: $(GAMMAOBJS): $(GAMMAHEADERS) $(TDFXOBJS): $(TDFXHEADERS) +$(R128OBJS): $(R128HEADERS) +$(RADEONOBJS): $(RADEONHEADERS) ifeq ($(AGP),1) $(MGAOBJS): $(MGAHEADERS) $(I810OBJS): $(I810HEADERS) $(I830OBJS): $(I830HEADERS) -$(R128OBJS): $(R128HEADERS) -$(RADEONOBJS): $(RADEONHEADERS) endif clean cleandir:: diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmP.h b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmP.h index c00efb4c5..f31c5c3d9 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmP.h +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmP.h @@ -165,7 +165,7 @@ #define pte_unmap(pte) #endif -#if LINUX_VERSION_CODE < 0x020500 +#if LINUX_VERSION_CODE < 0x020413 /* KERNEL_VERSION(2,4,19) */ static inline struct page * vmalloc_to_page(void * vmalloc_addr) { unsigned long addr = (unsigned long) vmalloc_addr; diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_agpsupport.h b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_agpsupport.h index fc0b29aab..cd46110c4 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_agpsupport.h +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_agpsupport.h @@ -268,11 +268,11 @@ drm_agp_head_t *DRM(agp_init)(void) case INTEL_I810: head->chipset = "Intel i810"; break; case INTEL_I815: head->chipset = "Intel i815"; break; -#if LINUX_VERSION_CODE >= 0x020415 +#if LINUX_VERSION_CODE >= 0x02040f /* KERNEL_VERSION(2,4,15) */ case INTEL_I820: head->chipset = "Intel i820"; break; #endif case INTEL_I840: head->chipset = "Intel i840"; break; -#if LINUX_VERSION_CODE >= 0x020415 +#if LINUX_VERSION_CODE >= 0x02040f /* KERNEL_VERSION(2,4,15) */ case INTEL_I845: head->chipset = "Intel i845"; break; #endif case INTEL_I850: head->chipset = "Intel i850"; break; diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_drv.h b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_drv.h index af6858d7c..81bd78948 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_drv.h +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_drv.h @@ -115,15 +115,15 @@ #ifndef DRIVER_FOPS #define DRIVER_FOPS \ static struct file_operations DRM(fops) = { \ - owner: THIS_MODULE, \ - open: DRM(open), \ - flush: DRM(flush), \ - release: DRM(release), \ - ioctl: DRM(ioctl), \ - mmap: DRM(mmap), \ - read: DRM(read), \ - fasync: DRM(fasync), \ - poll: DRM(poll), \ + .owner = THIS_MODULE, \ + .open = DRM(open), \ + .flush = DRM(flush), \ + .release = DRM(release), \ + .ioctl = DRM(ioctl), \ + .mmap = DRM(mmap), \ + .read = DRM(read), \ + .fasync = DRM(fasync), \ + .poll = DRM(poll), \ } #endif diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_stub.h b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_stub.h index ead5b9595..3c9c69eb5 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_stub.h +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_stub.h @@ -49,7 +49,7 @@ static struct drm_stub_info { static int DRM(stub_open)(struct inode *inode, struct file *filp) { - int minor = MINOR(inode->i_rdev); + int minor = minor(inode->i_rdev); int err = -ENODEV; struct file_operations *old_fops; @@ -66,8 +66,8 @@ static int DRM(stub_open)(struct inode *inode, struct file *filp) } static struct file_operations DRM(stub_fops) = { - owner: THIS_MODULE, - open: DRM(stub_open) + .owner = THIS_MODULE, + .open = DRM(stub_open) }; static int DRM(stub_getminor)(const char *name, struct file_operations *fops, diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_vm.h b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_vm.h index 5fd3571ae..52dfd5944 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_vm.h +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_vm.h @@ -33,27 +33,27 @@ #include "drmP.h" struct vm_operations_struct DRM(vm_ops) = { - nopage: DRM(vm_nopage), - open: DRM(vm_open), - close: DRM(vm_close), + .nopage = DRM(vm_nopage), + .open = DRM(vm_open), + .close = DRM(vm_close), }; struct vm_operations_struct DRM(vm_shm_ops) = { - nopage: DRM(vm_shm_nopage), - open: DRM(vm_open), - close: DRM(vm_shm_close), + .nopage = DRM(vm_shm_nopage), + .open = DRM(vm_open), + .close = DRM(vm_shm_close), }; struct vm_operations_struct DRM(vm_dma_ops) = { - nopage: DRM(vm_dma_nopage), - open: DRM(vm_open), - close: DRM(vm_close), + .nopage = DRM(vm_dma_nopage), + .open = DRM(vm_open), + .close = DRM(vm_close), }; struct vm_operations_struct DRM(vm_sg_ops) = { - nopage: DRM(vm_sg_nopage), - open: DRM(vm_open), - close: DRM(vm_close), + .nopage = DRM(vm_sg_nopage), + .open = DRM(vm_open), + .close = DRM(vm_close), }; struct page *DRM(vm_nopage)(struct vm_area_struct *vma, @@ -130,9 +130,6 @@ struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma, drm_map_t *map = (drm_map_t *)vma->vm_private_data; unsigned long offset; unsigned long i; - pgd_t *pgd; - pmd_t *pmd; - pte_t *pte; struct page *page; if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */ @@ -140,20 +137,12 @@ struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma, offset = address - vma->vm_start; i = (unsigned long)map->handle + offset; - /* We have to walk page tables here because we need large SAREA's, and - * they need to be virtually contiguous in kernel space. - */ - pgd = pgd_offset_k( i ); - if( !pgd_present( *pgd ) ) return NOPAGE_OOM; - pmd = pmd_offset( pgd, i ); - if( !pmd_present( *pmd ) ) return NOPAGE_OOM; - pte = pte_offset( pmd, i ); - if( !pte_present( *pte ) ) return NOPAGE_OOM; - - page = pte_page(*pte); + page = vmalloc_to_page((void *)i); + if (!page) + return NOPAGE_OOM; get_page(page); - DRM_DEBUG("0x%08lx => 0x%08x\n", address, page_to_bus(page)); + DRM_DEBUG("shm_nopage 0x%lx\n", address); return page; } @@ -255,8 +244,7 @@ struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma, get_page(page); - DRM_DEBUG("0x%08lx (page %lu) => 0x%08x\n", address, page_nr, - page_to_bus(page)); + DRM_DEBUG("dma_nopage 0x%lx (page %lu)\n", address, page_nr); return page; } @@ -355,7 +343,7 @@ int DRM(mmap_dma)(struct file *filp, struct vm_area_struct *vma) vma->vm_ops = &DRM(vm_dma_ops); -#if LINUX_VERSION_CODE <= 0x020414 +#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */ vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */ #else vma->vm_flags |= VM_RESERVED; /* Don't swap */ @@ -462,10 +450,17 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma) vma->vm_flags |= VM_IO; /* not in core dump */ } offset = DRIVER_GET_REG_OFS(); - if (remap_page_range(vma->vm_start, +#ifdef __sparc__ + if (io_remap_page_range(DRM_RPR_ARG(vma) vma->vm_start, + VM_OFFSET(vma) + offset, + vma->vm_end - vma->vm_start, + vma->vm_page_prot, 0)) +#else + if (remap_page_range(DRM_RPR_ARG(vma) vma->vm_start, VM_OFFSET(vma) + offset, vma->vm_end - vma->vm_start, vma->vm_page_prot)) +#endif return -EAGAIN; DRM_DEBUG(" Type = %d; start = 0x%lx, end = 0x%lx," " offset = 0x%lx\n", @@ -478,7 +473,7 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma) vma->vm_private_data = (void *)map; /* Don't let this area swap. Change when DRM_KERNEL advisory is supported. */ -#if LINUX_VERSION_CODE <= 0x020414 +#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */ vma->vm_flags |= VM_LOCKED; #else vma->vm_flags |= VM_RESERVED; @@ -487,7 +482,7 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma) case _DRM_SCATTER_GATHER: vma->vm_ops = &DRM(vm_sg_ops); vma->vm_private_data = (void *)map; -#if LINUX_VERSION_CODE <= 0x020414 +#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */ vma->vm_flags |= VM_LOCKED; #else vma->vm_flags |= VM_RESERVED; @@ -496,7 +491,7 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma) default: return -EINVAL; /* This should never happen. */ } -#if LINUX_VERSION_CODE <= 0x020414 +#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */ vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */ #else vma->vm_flags |= VM_RESERVED; /* Don't swap */ diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_dma.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_dma.c index ae0a36169..f4eef3a33 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_dma.c +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i810_dma.c @@ -26,20 +26,18 @@ * * Authors: Rickard E. (Rik) Faith <faith@valinux.com> * Jeff Hartmann <jhartmann@valinux.com> - * Keith Whitwell <keithw@valinux.com> + * Keith Whitwell <keith_whitwell@yahoo.com> * */ #define __NO_VERSION__ #include "i810.h" #include "drmP.h" +#include "drm.h" +#include "i810_drm.h" #include "i810_drv.h" #include <linux/interrupt.h> /* For task queue support */ - -/* in case we don't have a 2.3.99-pre6 kernel or later: */ -#ifndef VM_DONTCOPY -#define VM_DONTCOPY 0 -#endif +#include <linux/delay.h> #define I810_BUF_FREE 2 #define I810_BUF_CLIENT 1 @@ -50,30 +48,28 @@ #define RING_LOCALS unsigned int outring, ringmask; volatile char *virt; -#define BEGIN_LP_RING(n) do { \ - if (I810_VERBOSE) \ - DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n", \ - n, __FUNCTION__); \ - if (dev_priv->ring.space < n*4) \ - i810_wait_ring(dev, n*4); \ - dev_priv->ring.space -= n*4; \ - outring = dev_priv->ring.tail; \ - ringmask = dev_priv->ring.tail_mask; \ - virt = dev_priv->ring.virtual_start; \ +#define BEGIN_LP_RING(n) do { \ + if (0) DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n", n, __FUNCTION__); \ + if (dev_priv->ring.space < n*4) \ + i810_wait_ring(dev, n*4); \ + dev_priv->ring.space -= n*4; \ + outring = dev_priv->ring.tail; \ + ringmask = dev_priv->ring.tail_mask; \ + virt = dev_priv->ring.virtual_start; \ } while (0) -#define ADVANCE_LP_RING() do { \ - if (I810_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING\n"); \ - dev_priv->ring.tail = outring; \ - I810_WRITE(LP_RING + RING_TAIL, outring); \ +#define ADVANCE_LP_RING() do { \ + if (0) DRM_DEBUG("ADVANCE_LP_RING\n"); \ + dev_priv->ring.tail = outring; \ + I810_WRITE(LP_RING + RING_TAIL, outring); \ } while(0) -#define OUT_RING(n) do { \ - if (I810_VERBOSE) DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \ - *(volatile unsigned int *)(virt + outring) = n; \ - outring += 4; \ - outring &= ringmask; \ -} while (0); +#define OUT_RING(n) do { \ + if (0) DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \ + *(volatile unsigned int *)(virt + outring) = n; \ + outring += 4; \ + outring &= ringmask; \ +} while (0) static inline void i810_print_status_page(drm_device_t *dev) { @@ -134,14 +130,14 @@ static int i810_freelist_put(drm_device_t *dev, drm_buf_t *buf) } static struct file_operations i810_buffer_fops = { - open: DRM(open), - flush: DRM(flush), - release: DRM(release), - ioctl: DRM(ioctl), - mmap: i810_mmap_buffers, - read: DRM(read), - fasync: DRM(fasync), - poll: DRM(poll), + .open = DRM(open), + .flush = DRM(flush), + .release = DRM(release), + .ioctl = DRM(ioctl), + .mmap = i810_mmap_buffers, + .read = DRM(read), + .fasync = DRM(fasync), + .poll = DRM(poll), }; int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma) @@ -164,7 +160,7 @@ int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma) buf_priv->currently_mapped = I810_BUF_MAPPED; unlock_kernel(); - if (remap_page_range(vma->vm_start, + if (remap_page_range(DRM_RPR_ARG(vma) vma->vm_start, VM_OFFSET(vma), vma->vm_end - vma->vm_start, vma->vm_page_prot)) return -EAGAIN; @@ -182,36 +178,31 @@ static int i810_map_buffer(drm_buf_t *buf, struct file *filp) if(buf_priv->currently_mapped == I810_BUF_MAPPED) return -EINVAL; - if(VM_DONTCOPY != 0) { #if LINUX_VERSION_CODE <= 0x020402 - down( ¤t->mm->mmap_sem ); + down( ¤t->mm->mmap_sem ); #else - down_write( ¤t->mm->mmap_sem ); + down_write( ¤t->mm->mmap_sem ); #endif - old_fops = filp->f_op; - filp->f_op = &i810_buffer_fops; - dev_priv->mmap_buffer = buf; - buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total, - PROT_READ|PROT_WRITE, - MAP_SHARED, - buf->bus_address); - dev_priv->mmap_buffer = NULL; - filp->f_op = old_fops; - if ((unsigned long)buf_priv->virtual > -1024UL) { - /* Real error */ - DRM_DEBUG("mmap error\n"); - retcode = (signed int)buf_priv->virtual; - buf_priv->virtual = 0; - } + old_fops = filp->f_op; + filp->f_op = &i810_buffer_fops; + dev_priv->mmap_buffer = buf; + buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total, + PROT_READ|PROT_WRITE, + MAP_SHARED, + buf->bus_address); + dev_priv->mmap_buffer = NULL; + filp->f_op = old_fops; + if ((unsigned long)buf_priv->virtual > -1024UL) { + /* Real error */ + DRM_DEBUG("mmap error\n"); + retcode = (signed int)buf_priv->virtual; + buf_priv->virtual = 0; + } #if LINUX_VERSION_CODE <= 0x020402 - up( ¤t->mm->mmap_sem ); + up( ¤t->mm->mmap_sem ); #else - up_write( ¤t->mm->mmap_sem ); + up_write( ¤t->mm->mmap_sem ); #endif - } else { - buf_priv->virtual = buf_priv->kernel_virtual; - buf_priv->currently_mapped = I810_BUF_MAPPED; - } return retcode; } @@ -220,23 +211,21 @@ static int i810_unmap_buffer(drm_buf_t *buf) drm_i810_buf_priv_t *buf_priv = buf->dev_private; int retcode = 0; - if(VM_DONTCOPY != 0) { - if(buf_priv->currently_mapped != I810_BUF_MAPPED) - return -EINVAL; + if(buf_priv->currently_mapped != I810_BUF_MAPPED) + return -EINVAL; #if LINUX_VERSION_CODE <= 0x020402 - down( ¤t->mm->mmap_sem ); + down( ¤t->mm->mmap_sem ); #else - down_write( ¤t->mm->mmap_sem ); + down_write( ¤t->mm->mmap_sem ); #endif - retcode = do_munmap(current->mm, - (unsigned long)buf_priv->virtual, - (size_t) buf->total); + retcode = do_munmap(current->mm, + (unsigned long)buf_priv->virtual, + (size_t) buf->total); #if LINUX_VERSION_CODE <= 0x020402 - up( ¤t->mm->mmap_sem ); + up( ¤t->mm->mmap_sem ); #else - up_write( ¤t->mm->mmap_sem ); + up_write( ¤t->mm->mmap_sem ); #endif - } buf_priv->currently_mapped = I810_BUF_UNMAPPED; buf_priv->virtual = 0; @@ -282,22 +271,34 @@ static unsigned long i810_alloc_page(drm_device_t *dev) if(address == 0UL) return 0; +#if LINUX_VERSION_CODE < 0x020409 atomic_inc(&virt_to_page(address)->count); set_bit(PG_locked, &virt_to_page(address)->flags); - +#else + get_page(virt_to_page(address)); +#if LINUX_VERSION_CODE < 0x020500 + LockPage(virt_to_page(address)); +#else + SetPageLocked(virt_to_page(address)); +#endif +#endif return address; } static void i810_free_page(drm_device_t *dev, unsigned long page) { - if(page == 0UL) - return; - - atomic_dec(&virt_to_page(page)->count); - clear_bit(PG_locked, &virt_to_page(page)->flags); - wake_up(&virt_to_page(page)->wait); - free_page(page); - return; + if (page) { +#if LINUX_VERSION_CODE < 0x020409 + atomic_dec(&virt_to_page(page)->count); + clear_bit(PG_locked, &virt_to_page(page)->flags); + wake_up(&virt_to_page(page)->wait); +#else + struct page *p = virt_to_page(page); + put_page(p); + unlock_page(p); +#endif + free_page(page); + } } static int i810_dma_cleanup(drm_device_t *dev) @@ -341,8 +342,6 @@ static int i810_wait_ring(drm_device_t *dev, int n) end = jiffies + (HZ*3); while (ring->space < n) { - int i; - ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR; ring->space = ring->head - (ring->tail+8); if (ring->space < 0) ring->space += ring->Size; @@ -356,8 +355,7 @@ static int i810_wait_ring(drm_device_t *dev, int n) DRM_ERROR("lockup\n"); goto out_wait_ring; } - - for (i = 0 ; i < 2000 ; i++) ; + udelay(1); } out_wait_ring: @@ -445,9 +443,6 @@ static int i810_dma_initialize(drm_device_t *dev, ((u8 *)dev_priv->sarea_map->handle + init->sarea_priv_offset); - atomic_set(&dev_priv->flush_done, 0); - init_waitqueue_head(&dev_priv->flush_queue); - dev_priv->ring.Start = init->ring_start; dev_priv->ring.End = init->ring_end; dev_priv->ring.Size = init->ring_size; @@ -540,16 +535,12 @@ int i810_dma_init(struct inode *inode, struct file *filp, /* Most efficient way to verify state for the i810 is as it is * emitted. Non-conformant state is silently dropped. - * - * Use 'volatile' & local var tmp to force the emitted values to be - * identical to the verified ones. */ static void i810EmitContextVerified( drm_device_t *dev, - volatile unsigned int *code ) + unsigned int *code ) { drm_i810_private_t *dev_priv = dev->dev_private; int i, j = 0; - unsigned int tmp; RING_LOCALS; BEGIN_LP_RING( I810_CTX_SETUP_SIZE ); @@ -561,14 +552,13 @@ static void i810EmitContextVerified( drm_device_t *dev, OUT_RING( code[I810_CTXREG_ST1] ); for ( i = 4 ; i < I810_CTX_SETUP_SIZE ; i++ ) { - tmp = code[i]; - - if ((tmp & (7<<29)) == (3<<29) && - (tmp & (0x1f<<24)) < (0x1d<<24)) + if ((code[i] & (7<<29)) == (3<<29) && + (code[i] & (0x1f<<24)) < (0x1d<<24)) { - OUT_RING( tmp ); + OUT_RING( code[i] ); j++; } + else printk("constext state dropped!!!\n"); } if (j & 1) @@ -582,7 +572,6 @@ static void i810EmitTexVerified( drm_device_t *dev, { drm_i810_private_t *dev_priv = dev->dev_private; int i, j = 0; - unsigned int tmp; RING_LOCALS; BEGIN_LP_RING( I810_TEX_SETUP_SIZE ); @@ -593,14 +582,14 @@ static void i810EmitTexVerified( drm_device_t *dev, OUT_RING( code[I810_TEXREG_MI3] ); for ( i = 4 ; i < I810_TEX_SETUP_SIZE ; i++ ) { - tmp = code[i]; - if ((tmp & (7<<29)) == (3<<29) && - (tmp & (0x1f<<24)) < (0x1d<<24)) + if ((code[i] & (7<<29)) == (3<<29) && + (code[i] & (0x1f<<24)) < (0x1d<<24)) { - OUT_RING( tmp ); + OUT_RING( code[i] ); j++; } + else printk("texture state dropped!!!\n"); } if (j & 1) @@ -625,9 +614,9 @@ static void i810EmitDestVerified( drm_device_t *dev, if (tmp == dev_priv->front_di1 || tmp == dev_priv->back_di1) { OUT_RING( CMD_OP_DESTBUFFER_INFO ); OUT_RING( tmp ); - } else - DRM_DEBUG("bad di1 %x (allow %x or %x)\n", - tmp, dev_priv->front_di1, dev_priv->back_di1); + } + else + printk("buffer state dropped\n"); /* invarient: */ @@ -712,7 +701,6 @@ static void i810_dma_dispatch_clear( drm_device_t *dev, int flags, continue; if ( flags & I810_FRONT ) { - DRM_DEBUG("clear front\n"); BEGIN_LP_RING( 6 ); OUT_RING( BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3 ); @@ -725,7 +713,6 @@ static void i810_dma_dispatch_clear( drm_device_t *dev, int flags, } if ( flags & I810_BACK ) { - DRM_DEBUG("clear back\n"); BEGIN_LP_RING( 6 ); OUT_RING( BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3 ); @@ -738,7 +725,6 @@ static void i810_dma_dispatch_clear( drm_device_t *dev, int flags, } if ( flags & I810_DEPTH ) { - DRM_DEBUG("clear depth\n"); BEGIN_LP_RING( 6 ); OUT_RING( BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3 ); @@ -764,8 +750,6 @@ static void i810_dma_dispatch_swap( drm_device_t *dev ) int i; RING_LOCALS; - DRM_DEBUG("swapbuffers\n"); - i810_kernel_lost_context(dev); if (nbox > I810_NR_SAREA_CLIPRECTS) @@ -784,10 +768,6 @@ static void i810_dma_dispatch_swap( drm_device_t *dev ) pbox->y2 > dev_priv->h) continue; - DRM_DEBUG("dispatch swap %d,%d-%d,%d!\n", - pbox[i].x1, pbox[i].y1, - pbox[i].x2, pbox[i].y2); - BEGIN_LP_RING( 6 ); OUT_RING( BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4 ); OUT_RING( pitch | (0xCC << 16)); @@ -812,7 +792,7 @@ static void i810_dma_dispatch_vertex(drm_device_t *dev, int nbox = sarea_priv->nbox; unsigned long address = (unsigned long)buf->bus_address; unsigned long start = address - dev->agp->base; - int i = 0, u; + int i = 0; RING_LOCALS; i810_kernel_lost_context(dev); @@ -820,33 +800,16 @@ static void i810_dma_dispatch_vertex(drm_device_t *dev, if (nbox > I810_NR_SAREA_CLIPRECTS) nbox = I810_NR_SAREA_CLIPRECTS; - if (discard) { - u = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, - I810_BUF_HARDWARE); - if(u != I810_BUF_CLIENT) { - DRM_DEBUG("xxxx 2\n"); - } - } - if (used > 4*1024) used = 0; if (sarea_priv->dirty) i810EmitState( dev ); - DRM_DEBUG("dispatch vertex addr 0x%lx, used 0x%x nbox %d\n", - address, used, nbox); - - dev_priv->counter++; - DRM_DEBUG( "dispatch counter : %ld\n", dev_priv->counter); - DRM_DEBUG( "i810_dma_dispatch\n"); - DRM_DEBUG( "start : %lx\n", start); - DRM_DEBUG( "used : %d\n", used); - DRM_DEBUG( "start + used - 4 : %ld\n", start + used - 4); - if (buf_priv->currently_mapped == I810_BUF_MAPPED) { - *(u32 *)buf_priv->virtual = (GFX_OP_PRIMITIVE | - sarea_priv->vertex_prim | + unsigned int prim = (sarea_priv->vertex_prim & PR_MASK); + + *(u32 *)buf_priv->virtual = (GFX_OP_PRIMITIVE | prim | ((used/4)-2)); if (used & 4) { @@ -879,154 +842,62 @@ static void i810_dma_dispatch_vertex(drm_device_t *dev, } while (++i < nbox); } - BEGIN_LP_RING(10); - OUT_RING( CMD_STORE_DWORD_IDX ); - OUT_RING( 20 ); - OUT_RING( dev_priv->counter ); - OUT_RING( 0 ); - if (discard) { + dev_priv->counter++; + + (void) cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, + I810_BUF_HARDWARE); + + BEGIN_LP_RING(8); + OUT_RING( CMD_STORE_DWORD_IDX ); + OUT_RING( 20 ); + OUT_RING( dev_priv->counter ); OUT_RING( CMD_STORE_DWORD_IDX ); OUT_RING( buf_priv->my_use_idx ); OUT_RING( I810_BUF_FREE ); + OUT_RING( CMD_REPORT_HEAD ); OUT_RING( 0 ); + ADVANCE_LP_RING(); } - - OUT_RING( CMD_REPORT_HEAD ); - OUT_RING( 0 ); - ADVANCE_LP_RING(); -} - - -/* Interrupts are only for flushing */ -void i810_dma_service(int irq, void *device, struct pt_regs *regs) -{ - drm_device_t *dev = (drm_device_t *)device; - drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; - u16 temp; - - atomic_inc(&dev->counts[_DRM_STAT_IRQ]); - temp = I810_READ16(I810REG_INT_IDENTITY_R); - temp = temp & ~(0x6000); - if(temp != 0) I810_WRITE16(I810REG_INT_IDENTITY_R, - temp); /* Clear all interrupts */ - else - return; - - queue_task(&dev->tq, &tq_immediate); - mark_bh(IMMEDIATE_BH); } -void i810_dma_immediate_bh(void *device) -{ - drm_device_t *dev = (drm_device_t *) device; - drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; - - atomic_set(&dev_priv->flush_done, 1); - wake_up_interruptible(&dev_priv->flush_queue); -} - -static inline void i810_dma_emit_flush(drm_device_t *dev) -{ - drm_i810_private_t *dev_priv = dev->dev_private; - RING_LOCALS; - - i810_kernel_lost_context(dev); - - BEGIN_LP_RING(2); - OUT_RING( CMD_REPORT_HEAD ); - OUT_RING( GFX_OP_USER_INTERRUPT ); - ADVANCE_LP_RING(); - -/* i810_wait_ring( dev, dev_priv->ring.Size - 8 ); */ -/* atomic_set(&dev_priv->flush_done, 1); */ -/* wake_up_interruptible(&dev_priv->flush_queue); */ -} -static inline void i810_dma_quiescent_emit(drm_device_t *dev) +void i810_dma_quiescent(drm_device_t *dev) { drm_i810_private_t *dev_priv = dev->dev_private; RING_LOCALS; +/* printk("%s\n", __FUNCTION__); */ + i810_kernel_lost_context(dev); BEGIN_LP_RING(4); OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE ); OUT_RING( CMD_REPORT_HEAD ); OUT_RING( 0 ); - OUT_RING( GFX_OP_USER_INTERRUPT ); + OUT_RING( 0 ); ADVANCE_LP_RING(); -/* i810_wait_ring( dev, dev_priv->ring.Size - 8 ); */ -/* atomic_set(&dev_priv->flush_done, 1); */ -/* wake_up_interruptible(&dev_priv->flush_queue); */ -} - -void i810_dma_quiescent(drm_device_t *dev) -{ - DECLARE_WAITQUEUE(entry, current); - drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; - unsigned long end; - - if(dev_priv == NULL) { - return; - } - atomic_set(&dev_priv->flush_done, 0); - add_wait_queue(&dev_priv->flush_queue, &entry); - end = jiffies + (HZ*3); - - for (;;) { - current->state = TASK_INTERRUPTIBLE; - i810_dma_quiescent_emit(dev); - if (atomic_read(&dev_priv->flush_done) == 1) break; - if((signed)(end - jiffies) <= 0) { - DRM_ERROR("lockup\n"); - break; - } - schedule_timeout(HZ*3); - if (signal_pending(current)) { - break; - } - } - - current->state = TASK_RUNNING; - remove_wait_queue(&dev_priv->flush_queue, &entry); - - return; + i810_wait_ring( dev, dev_priv->ring.Size - 8 ); } static int i810_flush_queue(drm_device_t *dev) { - DECLARE_WAITQUEUE(entry, current); - drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; + drm_i810_private_t *dev_priv = dev->dev_private; drm_device_dma_t *dma = dev->dma; - unsigned long end; int i, ret = 0; + RING_LOCALS; + +/* printk("%s\n", __FUNCTION__); */ - if(dev_priv == NULL) { - return 0; - } - atomic_set(&dev_priv->flush_done, 0); - add_wait_queue(&dev_priv->flush_queue, &entry); - end = jiffies + (HZ*3); - for (;;) { - current->state = TASK_INTERRUPTIBLE; - i810_dma_emit_flush(dev); - if (atomic_read(&dev_priv->flush_done) == 1) break; - if((signed)(end - jiffies) <= 0) { - DRM_ERROR("lockup\n"); - break; - } - schedule_timeout(HZ*3); - if (signal_pending(current)) { - ret = -EINTR; /* Can't restart */ - break; - } - } + i810_kernel_lost_context(dev); - current->state = TASK_RUNNING; - remove_wait_queue(&dev_priv->flush_queue, &entry); + BEGIN_LP_RING(2); + OUT_RING( CMD_REPORT_HEAD ); + OUT_RING( 0 ); + ADVANCE_LP_RING(); + i810_wait_ring( dev, dev_priv->ring.Size - 8 ); for (i = 0; i < dma->buf_count; i++) { drm_buf_t *buf = dma->buflist[ i ]; @@ -1038,7 +909,7 @@ static int i810_flush_queue(drm_device_t *dev) if (used == I810_BUF_HARDWARE) DRM_DEBUG("reclaimed from HARDWARE\n"); if (used == I810_BUF_CLIENT) - DRM_DEBUG("still on client HARDWARE\n"); + DRM_DEBUG("still on client\n"); } return ret; @@ -1078,7 +949,6 @@ int i810_flush_ioctl(struct inode *inode, struct file *filp, drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; - DRM_DEBUG("i810_flush_ioctl\n"); if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { DRM_ERROR("i810_flush_ioctl called without lock held\n"); return -EINVAL; @@ -1109,9 +979,6 @@ int i810_dma_vertex(struct inode *inode, struct file *filp, return -EINVAL; } - DRM_DEBUG("i810 dma vertex, idx %d used %d discard %d\n", - vertex.idx, vertex.used, vertex.discard); - if(vertex.idx < 0 || vertex.idx > dma->buf_count) return -EINVAL; i810_dma_dispatch_vertex( dev, @@ -1160,8 +1027,6 @@ int i810_swap_bufs(struct inode *inode, struct file *filp, drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; - DRM_DEBUG("i810_swap_bufs\n"); - if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { DRM_ERROR("i810_swap_buf called without lock held\n"); return -EINVAL; @@ -1197,7 +1062,6 @@ int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd, drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) dev_priv->sarea_priv; - DRM_DEBUG("getbuf\n"); if (copy_from_user(&d, (drm_i810_dma_t *)arg, sizeof(d))) return -EFAULT; @@ -1210,9 +1074,6 @@ int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd, retcode = i810_dma_get_buffer(dev, &d, filp); - DRM_DEBUG("i810_dma: %d returning %d, granted = %d\n", - current->pid, retcode, d.granted); - if (copy_to_user((drm_dma_t *)arg, &d, sizeof(d))) return -EFAULT; sarea_priv->last_dispatch = (int) hw_status[5]; @@ -1220,47 +1081,19 @@ int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd, return retcode; } -int i810_copybuf(struct inode *inode, struct file *filp, unsigned int cmd, - unsigned long arg) +int i810_copybuf(struct inode *inode, + struct file *filp, + unsigned int cmd, + unsigned long arg) { - drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; - drm_i810_copy_t d; - drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private; - u32 *hw_status = (u32 *)dev_priv->hw_status_page; - drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) - dev_priv->sarea_priv; - drm_buf_t *buf; - drm_i810_buf_priv_t *buf_priv; - drm_device_dma_t *dma = dev->dma; - - if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { - DRM_ERROR("i810_dma called without lock held\n"); - return -EINVAL; - } - - if (copy_from_user(&d, (drm_i810_copy_t *)arg, sizeof(d))) - return -EFAULT; - - if(d.idx < 0 || d.idx > dma->buf_count) return -EINVAL; - buf = dma->buflist[ d.idx ]; - buf_priv = buf->dev_private; - if (buf_priv->currently_mapped != I810_BUF_MAPPED) return -EPERM; - - if(d.used < 0 || d.used > buf->total) return -EINVAL; - - if (copy_from_user(buf_priv->virtual, d.address, d.used)) - return -EFAULT; - - sarea_priv->last_dispatch = (int) hw_status[5]; - + /* Never copy - 2.4.x doesn't need it */ return 0; } int i810_docopy(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { - if(VM_DONTCOPY == 0) return 1; + /* Never copy - 2.4.x doesn't need it */ return 0; } diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i830_dma.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i830_dma.c index 661987fb2..643259fc8 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i830_dma.c +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/i830_dma.c @@ -34,8 +34,11 @@ #define __NO_VERSION__ #include "i830.h" #include "drmP.h" +#include "drm.h" +#include "i830_drm.h" #include "i830_drv.h" #include <linux/interrupt.h> /* For task queue support */ +#include <linux/delay.h> /* in case we don't have a 2.3.99-pre6 kernel or later: */ #ifndef VM_DONTCOPY @@ -56,11 +59,10 @@ do { \ int _head; \ int _tail; \ - int _i; \ do { \ _head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR; \ _tail = I830_READ(LP_RING + RING_TAIL) & TAIL_ADDR; \ - for(_i = 0; _i < 65535; _i++); \ + udelay(10); \ } while(_head != _tail); \ } while(0) @@ -91,7 +93,7 @@ do { \ *(volatile unsigned int *)(virt + outring) = n; \ outring += 4; \ outring &= ringmask; \ -} while (0); +} while (0) static inline void i830_print_status_page(drm_device_t *dev) { @@ -151,14 +153,14 @@ static int i830_freelist_put(drm_device_t *dev, drm_buf_t *buf) } static struct file_operations i830_buffer_fops = { - open: DRM(open), - flush: DRM(flush), - release: DRM(release), - ioctl: DRM(ioctl), - mmap: i830_mmap_buffers, - read: DRM(read), - fasync: DRM(fasync), - poll: DRM(poll), + .open = DRM(open), + .flush = DRM(flush), + .release = DRM(release), + .ioctl = DRM(ioctl), + .mmap = i830_mmap_buffers, + .read = DRM(read), + .fasync = DRM(fasync), + .poll = DRM(poll), }; int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma) @@ -181,7 +183,7 @@ int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma) buf_priv->currently_mapped = I830_BUF_MAPPED; unlock_kernel(); - if (remap_page_range(vma->vm_start, + if (remap_page_range(DRM_RPR_ARG(vma) vma->vm_start, VM_OFFSET(vma), vma->vm_end - vma->vm_start, vma->vm_page_prot)) return -EAGAIN; @@ -245,14 +247,11 @@ static int i830_unmap_buffer(drm_buf_t *buf) #else down_write( ¤t->mm->mmap_sem ); #endif -#if LINUX_VERSION_CODE < 0x020399 - retcode = do_munmap((unsigned long)buf_priv->virtual, - (size_t) buf->total); -#else + retcode = do_munmap(current->mm, (unsigned long)buf_priv->virtual, (size_t) buf->total); -#endif + #if LINUX_VERSION_CODE <= 0x020402 up( ¤t->mm->mmap_sem ); #else @@ -304,22 +303,34 @@ static unsigned long i830_alloc_page(drm_device_t *dev) if(address == 0UL) return 0; +#if LINUX_VERSION_CODE < 0x020409 atomic_inc(&virt_to_page(address)->count); set_bit(PG_locked, &virt_to_page(address)->flags); - +#else + get_page(virt_to_page(address)); +#if LINUX_VERSION_CODE < 0x020500 + LockPage(virt_to_page(address)); +#else + SetPageLocked(virt_to_page(address)); +#endif +#endif return address; } static void i830_free_page(drm_device_t *dev, unsigned long page) { - if(page == 0UL) - return; - - atomic_dec(&virt_to_page(page)->count); - clear_bit(PG_locked, &virt_to_page(page)->flags); - wake_up(&virt_to_page(page)->wait); - free_page(page); - return; + if (page) { +#if LINUX_VERSION_CODE < 0x020409 + atomic_dec(&virt_to_page(page)->count); + clear_bit(PG_locked, &virt_to_page(page)->flags); + wake_up(&virt_to_page(page)->wait); +#else + struct page *p = virt_to_page(page); + put_page(p); + unlock_page(p); +#endif + free_page(page); + } } static int i830_dma_cleanup(drm_device_t *dev) @@ -362,9 +373,7 @@ static int i830_wait_ring(drm_device_t *dev, int n) unsigned int last_head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR; end = jiffies + (HZ*3); - while (ring->space < n) { - int i; - + while (ring->space < n) { ring->head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR; ring->space = ring->head - (ring->tail+8); if (ring->space < 0) ring->space += ring->Size; @@ -380,8 +389,7 @@ static int i830_wait_ring(drm_device_t *dev, int n) DRM_ERROR("lockup\n"); goto out_wait_ring; } - - for (i = 0 ; i < 2000 ; i++) ; + udelay(1); } out_wait_ring: diff --git a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mga_drv.h b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mga_drv.h index 51bc706e9..0845009bb 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mga_drv.h +++ b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mga_drv.h @@ -38,7 +38,7 @@ typedef struct drm_mga_primary_buffer { u32 tail; int space; - int wrapped; + volatile long wrapped; volatile u32 *status; diff --git a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mga_state.c b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mga_state.c index adf67de36..734432d59 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mga_state.c +++ b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mga_state.c @@ -37,7 +37,6 @@ #include "drm.h" #include "mga_drm.h" #include "mga_drv.h" -#include "drm.h" /* ================================================================ diff --git a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_cp.c b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_cp.c index d56a90023..01069e498 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_cp.c +++ b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_cp.c @@ -925,6 +925,24 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev, RADEON_WRITE( RADEON_SCRATCH_UMSK, 0x7 ); + /* Writeback doesn't seem to work everywhere, test it first */ + DRM_WRITE32( &dev_priv->scratch[1], 0 ); + RADEON_WRITE( RADEON_SCRATCH_REG1, 0xdeadbeef ); + + for ( tmp = 0 ; tmp < dev_priv->usec_timeout ; tmp++ ) { + if ( DRM_READ32( &dev_priv->scratch[1] ) == 0xdeadbeef ) + break; + DRM_UDELAY( 1 ); + } + + if ( tmp < dev_priv->usec_timeout ) { + dev_priv->writeback_works = 1; + DRM_DEBUG( "writeback test succeeded, tmp=%d\n", tmp ); + } else { + dev_priv->writeback_works = 0; + DRM_DEBUG( "writeback test failed\n" ); + } + dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0; RADEON_WRITE( RADEON_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame ); @@ -1456,8 +1474,8 @@ drm_buf_t *radeon_freelist_get( drm_device_t *dev ) start = dev_priv->last_buf; for ( t = 0 ; t < dev_priv->usec_timeout ; t++ ) { - u32 done_age = DRM_READ32(&dev_priv->scratch[1]); - + u32 done_age = GET_SCRATCH( 1 ); + DRM_DEBUG("done_age = %d\n",done_age); for ( i = start ; i < dma->buf_count ; i++ ) { buf = dma->buflist[i]; buf_priv = buf->dev_private; diff --git a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_drv.h b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_drv.h index 57cd5f4fd..7c341b39e 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_drv.h +++ b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_drv.h @@ -76,6 +76,7 @@ typedef struct drm_radeon_private { drm_radeon_freelist_t *tail; int last_buf; volatile u32 *scratch; + int writeback_works; int usec_timeout; @@ -233,6 +234,10 @@ extern int radeon_cp_flip( DRM_IOCTL_ARGS ); #define RADEON_SCRATCH_UMSK 0x0770 #define RADEON_SCRATCH_ADDR 0x0774 +#define GET_SCRATCH( x ) (dev_priv->writeback_works \ + ? DRM_READ32( &dev_priv->scratch[(x)] ) \ + : RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x) ) ) + #define RADEON_HOST_PATH_CNTL 0x0130 # define RADEON_HDP_SOFT_RESET (1 << 26) # define RADEON_HDP_WC_TIMEOUT_MASK (7 << 28) diff --git a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_state.c b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_state.c index 7b2dbdfbd..7f84e739a 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_state.c +++ b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_state.c @@ -1936,6 +1936,19 @@ static int radeon_emit_packet3_cliprect( drm_device_t *dev, if ( i < cmdbuf->nbox ) { if (DRM_COPY_FROM_USER_UNCHECKED( &box, &boxes[i], sizeof(box) )) return DRM_ERR(EFAULT); + /* FIXME The second and subsequent times round this loop, send a + * WAIT_UNTIL_3D_IDLE before calling emit_clip_rect(). This + * fixes a lockup on fast machines when sending several + * cliprects with a cmdbuf, as when waving a 2D window over + * a 3D window. Something in the commands from user space + * seems to hang the card when they're sent several times + * in a row. That would be the correct place to fix it but + * this works around it until I can figure that out - Tim Smith */ + if ( i ) { + BEGIN_RING( 2 ); + RADEON_WAIT_UNTIL_3D_IDLE(); + ADVANCE_RING(); + } radeon_emit_clip_rect( dev_priv, &box ); } @@ -1944,7 +1957,6 @@ static int radeon_emit_packet3_cliprect( drm_device_t *dev, ADVANCE_RING(); } while ( ++i < cmdbuf->nbox ); - if (cmdbuf->nbox == 1) cmdbuf->nbox = 0; @@ -2107,14 +2119,14 @@ int radeon_cp_getparam( DRM_IOCTL_ARGS ) break; case RADEON_PARAM_LAST_FRAME: dev_priv->stats.last_frame_reads++; - value = DRM_READ32(&dev_priv->scratch[0]); + value = GET_SCRATCH( 0 ); break; case RADEON_PARAM_LAST_DISPATCH: - value = DRM_READ32(&dev_priv->scratch[1]); + value = GET_SCRATCH( 1 ); break; case RADEON_PARAM_LAST_CLEAR: dev_priv->stats.last_clear_reads++; - value = DRM_READ32(&dev_priv->scratch[2]); + value = GET_SCRATCH( 2 ); break; default: return DRM_ERR(EINVAL); diff --git a/xc/programs/Xserver/include/opaque.h b/xc/programs/Xserver/include/opaque.h index 385da7abf..048963991 100644 --- a/xc/programs/Xserver/include/opaque.h +++ b/xc/programs/Xserver/include/opaque.h @@ -75,6 +75,7 @@ extern int limitNoFile; extern Bool permitOldBugs; extern Bool defeatAccessControl; extern char* protNoListen; +extern Bool blackRoot; diff --git a/xc/programs/Xserver/os/utils.c b/xc/programs/Xserver/os/utils.c index 26a9af2a0..14015a91c 100644 --- a/xc/programs/Xserver/os/utils.c +++ b/xc/programs/Xserver/os/utils.c @@ -496,6 +496,7 @@ void UseMsg() ErrorF("-audit int set audit trail level\n"); ErrorF("-auth file select authorization file\n"); ErrorF("bc enable bug compatibility\n"); + ErrorF("-br create root window with black background\n"); ErrorF("+bs enable any backing store support\n"); ErrorF("-bs disable any backing store support\n"); ErrorF("-c turns off key-click\n"); @@ -659,6 +660,8 @@ char *argv[]; } else if ( strcmp( argv[i], "bc") == 0) permitOldBugs = TRUE; + else if ( strcmp( argv[i], "-br") == 0) + blackRoot = TRUE; else if ( strcmp( argv[i], "+bs") == 0) enableBackingStore = TRUE; else if ( strcmp( argv[i], "-bs") == 0) |