Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  *
  4.  * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
  5.  * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
  6.  *
  7.  * Permission is hereby granted, free of charge, to any person obtaining a
  8.  * copy of this software and associated documentation files (the "Software"),
  9.  * to deal in the Software without restriction, including without limitation
  10.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11.  * and/or sell copies of the Software, and to permit persons to whom the
  12.  * Software is furnished to do so, subject to the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice shall be included
  15.  * in all copies or substantial portions of the Software.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  18.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  20.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  21.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  22.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  23.  * OTHER DEALINGS IN THE SOFTWARE.
  24.  */
  25.  
  26.  
  27. /**
  28.  * \file matrix.c
  29.  * Matrix operations.
  30.  *
  31.  * \note
  32.  * -# 4x4 transformation matrices are stored in memory in column major order.
  33.  * -# Points/vertices are to be thought of as column vectors.
  34.  * -# Transformation of a point p by a matrix M is: p' = M * p
  35.  */
  36.  
  37.  
  38. #include "glheader.h"
  39. #include "imports.h"
  40. #include "context.h"
  41. #include "enums.h"
  42. #include "macros.h"
  43. #include "matrix.h"
  44. #include "mtypes.h"
  45. #include "math/m_matrix.h"
  46.  
  47.  
  48. /**
  49.  * Apply a perspective projection matrix.
  50.  *
  51.  * \param left left clipping plane coordinate.
  52.  * \param right right clipping plane coordinate.
  53.  * \param bottom bottom clipping plane coordinate.
  54.  * \param top top clipping plane coordinate.
  55.  * \param nearval distance to the near clipping plane.
  56.  * \param farval distance to the far clipping plane.
  57.  *
  58.  * \sa glFrustum().
  59.  *
  60.  * Flushes vertices and validates parameters. Calls _math_matrix_frustum() with
  61.  * the top matrix of the current matrix stack and sets
  62.  * __struct gl_contextRec::NewState.
  63.  */
  64. void GLAPIENTRY
  65. _mesa_Frustum( GLdouble left, GLdouble right,
  66.                GLdouble bottom, GLdouble top,
  67.                GLdouble nearval, GLdouble farval )
  68. {
  69.    GET_CURRENT_CONTEXT(ctx);
  70.  
  71.    FLUSH_VERTICES(ctx, 0);
  72.  
  73.    if (nearval <= 0.0 ||
  74.        farval <= 0.0 ||
  75.        nearval == farval ||
  76.        left == right ||
  77.        top == bottom)
  78.    {
  79.       _mesa_error( ctx,  GL_INVALID_VALUE, "glFrustum" );
  80.       return;
  81.    }
  82.  
  83.    _math_matrix_frustum( ctx->CurrentStack->Top,
  84.                          (GLfloat) left, (GLfloat) right,
  85.                          (GLfloat) bottom, (GLfloat) top,
  86.                          (GLfloat) nearval, (GLfloat) farval );
  87.    ctx->NewState |= ctx->CurrentStack->DirtyFlag;
  88. }
  89.  
  90.  
  91. /**
  92.  * Apply an orthographic projection matrix.
  93.  *
  94.  * \param left left clipping plane coordinate.
  95.  * \param right right clipping plane coordinate.
  96.  * \param bottom bottom clipping plane coordinate.
  97.  * \param top top clipping plane coordinate.
  98.  * \param nearval distance to the near clipping plane.
  99.  * \param farval distance to the far clipping plane.
  100.  *
  101.  * \sa glOrtho().
  102.  *
  103.  * Flushes vertices and validates parameters. Calls _math_matrix_ortho() with
  104.  * the top matrix of the current matrix stack and sets
  105.  * __struct gl_contextRec::NewState.
  106.  */
  107. void GLAPIENTRY
  108. _mesa_Ortho( GLdouble left, GLdouble right,
  109.              GLdouble bottom, GLdouble top,
  110.              GLdouble nearval, GLdouble farval )
  111. {
  112.    GET_CURRENT_CONTEXT(ctx);
  113.  
  114.    FLUSH_VERTICES(ctx, 0);
  115.  
  116.    if (MESA_VERBOSE & VERBOSE_API)
  117.       _mesa_debug(ctx, "glOrtho(%f, %f, %f, %f, %f, %f)\n",
  118.                   left, right, bottom, top, nearval, farval);
  119.  
  120.    if (left == right ||
  121.        bottom == top ||
  122.        nearval == farval)
  123.    {
  124.       _mesa_error( ctx,  GL_INVALID_VALUE, "glOrtho" );
  125.       return;
  126.    }
  127.  
  128.    _math_matrix_ortho( ctx->CurrentStack->Top,
  129.                        (GLfloat) left, (GLfloat) right,
  130.                        (GLfloat) bottom, (GLfloat) top,
  131.                        (GLfloat) nearval, (GLfloat) farval );
  132.    ctx->NewState |= ctx->CurrentStack->DirtyFlag;
  133. }
  134.  
  135.  
  136. /**
  137.  * Set the current matrix stack.
  138.  *
  139.  * \param mode matrix stack.
  140.  *
  141.  * \sa glMatrixMode().
  142.  *
  143.  * Flushes the vertices, validates the parameter and updates
  144.  * __struct gl_contextRec::CurrentStack and gl_transform_attrib::MatrixMode
  145.  * with the specified matrix stack.
  146.  */
  147. void GLAPIENTRY
  148. _mesa_MatrixMode( GLenum mode )
  149. {
  150.    GET_CURRENT_CONTEXT(ctx);
  151.  
  152.    if (ctx->Transform.MatrixMode == mode && mode != GL_TEXTURE)
  153.       return;
  154.    FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
  155.  
  156.    switch (mode) {
  157.    case GL_MODELVIEW:
  158.       ctx->CurrentStack = &ctx->ModelviewMatrixStack;
  159.       break;
  160.    case GL_PROJECTION:
  161.       ctx->CurrentStack = &ctx->ProjectionMatrixStack;
  162.       break;
  163.    case GL_TEXTURE:
  164.       /* This error check is disabled because if we're called from
  165.        * glPopAttrib() when the active texture unit is >= MaxTextureCoordUnits
  166.        * we'll generate an unexpected error.
  167.        * From the GL_ARB_vertex_shader spec it sounds like we should instead
  168.        * do error checking in other places when we actually try to access
  169.        * texture matrices beyond MaxTextureCoordUnits.
  170.        */
  171. #if 0
  172.       if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) {
  173.          _mesa_error(ctx, GL_INVALID_OPERATION,
  174.                      "glMatrixMode(invalid tex unit %d)",
  175.                      ctx->Texture.CurrentUnit);
  176.          return;
  177.       }
  178. #endif
  179.       assert(ctx->Texture.CurrentUnit < ARRAY_SIZE(ctx->TextureMatrixStack));
  180.       ctx->CurrentStack = &ctx->TextureMatrixStack[ctx->Texture.CurrentUnit];
  181.       break;
  182.    case GL_MATRIX0_ARB:
  183.    case GL_MATRIX1_ARB:
  184.    case GL_MATRIX2_ARB:
  185.    case GL_MATRIX3_ARB:
  186.    case GL_MATRIX4_ARB:
  187.    case GL_MATRIX5_ARB:
  188.    case GL_MATRIX6_ARB:
  189.    case GL_MATRIX7_ARB:
  190.       if (ctx->API == API_OPENGL_COMPAT
  191.           && (ctx->Extensions.ARB_vertex_program ||
  192.               ctx->Extensions.ARB_fragment_program)) {
  193.          const GLuint m = mode - GL_MATRIX0_ARB;
  194.          if (m > ctx->Const.MaxProgramMatrices) {
  195.             _mesa_error(ctx, GL_INVALID_ENUM,
  196.                         "glMatrixMode(GL_MATRIX%d_ARB)", m);
  197.             return;
  198.          }
  199.          ctx->CurrentStack = &ctx->ProgramMatrixStack[m];
  200.       }
  201.       else {
  202.          _mesa_error( ctx,  GL_INVALID_ENUM, "glMatrixMode(mode)" );
  203.          return;
  204.       }
  205.       break;
  206.    default:
  207.       _mesa_error( ctx,  GL_INVALID_ENUM, "glMatrixMode(mode)" );
  208.       return;
  209.    }
  210.  
  211.    ctx->Transform.MatrixMode = mode;
  212. }
  213.  
  214.  
  215. /**
  216.  * Push the current matrix stack.
  217.  *
  218.  * \sa glPushMatrix().
  219.  *
  220.  * Verifies the current matrix stack is not full, and duplicates the top-most
  221.  * matrix in the stack.
  222.  * Marks __struct gl_contextRec::NewState with the stack dirty flag.
  223.  */
  224. void GLAPIENTRY
  225. _mesa_PushMatrix( void )
  226. {
  227.    GET_CURRENT_CONTEXT(ctx);
  228.    struct gl_matrix_stack *stack = ctx->CurrentStack;
  229.  
  230.    if (MESA_VERBOSE&VERBOSE_API)
  231.       _mesa_debug(ctx, "glPushMatrix %s\n",
  232.                   _mesa_lookup_enum_by_nr(ctx->Transform.MatrixMode));
  233.  
  234.    if (stack->Depth + 1 >= stack->MaxDepth) {
  235.       if (ctx->Transform.MatrixMode == GL_TEXTURE) {
  236.          _mesa_error(ctx,  GL_STACK_OVERFLOW,
  237.                      "glPushMatrix(mode=GL_TEXTURE, unit=%d)",
  238.                       ctx->Texture.CurrentUnit);
  239.       }
  240.       else {
  241.          _mesa_error(ctx,  GL_STACK_OVERFLOW, "glPushMatrix(mode=%s)",
  242.                      _mesa_lookup_enum_by_nr(ctx->Transform.MatrixMode));
  243.       }
  244.       return;
  245.    }
  246.    _math_matrix_copy( &stack->Stack[stack->Depth + 1],
  247.                       &stack->Stack[stack->Depth] );
  248.    stack->Depth++;
  249.    stack->Top = &(stack->Stack[stack->Depth]);
  250.    ctx->NewState |= stack->DirtyFlag;
  251. }
  252.  
  253.  
  254. /**
  255.  * Pop the current matrix stack.
  256.  *
  257.  * \sa glPopMatrix().
  258.  *
  259.  * Flushes the vertices, verifies the current matrix stack is not empty, and
  260.  * moves the stack head down.
  261.  * Marks __struct gl_contextRec::NewState with the dirty stack flag.
  262.  */
  263. void GLAPIENTRY
  264. _mesa_PopMatrix( void )
  265. {
  266.    GET_CURRENT_CONTEXT(ctx);
  267.    struct gl_matrix_stack *stack = ctx->CurrentStack;
  268.  
  269.    FLUSH_VERTICES(ctx, 0);
  270.  
  271.    if (MESA_VERBOSE&VERBOSE_API)
  272.       _mesa_debug(ctx, "glPopMatrix %s\n",
  273.                   _mesa_lookup_enum_by_nr(ctx->Transform.MatrixMode));
  274.  
  275.    if (stack->Depth == 0) {
  276.       if (ctx->Transform.MatrixMode == GL_TEXTURE) {
  277.          _mesa_error(ctx,  GL_STACK_UNDERFLOW,
  278.                      "glPopMatrix(mode=GL_TEXTURE, unit=%d)",
  279.                       ctx->Texture.CurrentUnit);
  280.       }
  281.       else {
  282.          _mesa_error(ctx,  GL_STACK_UNDERFLOW, "glPopMatrix(mode=%s)",
  283.                      _mesa_lookup_enum_by_nr(ctx->Transform.MatrixMode));
  284.       }
  285.       return;
  286.    }
  287.    stack->Depth--;
  288.    stack->Top = &(stack->Stack[stack->Depth]);
  289.    ctx->NewState |= stack->DirtyFlag;
  290. }
  291.  
  292.  
  293. /**
  294.  * Replace the current matrix with the identity matrix.
  295.  *
  296.  * \sa glLoadIdentity().
  297.  *
  298.  * Flushes the vertices and calls _math_matrix_set_identity() with the
  299.  * top-most matrix in the current stack.
  300.  * Marks __struct gl_contextRec::NewState with the stack dirty flag.
  301.  */
  302. void GLAPIENTRY
  303. _mesa_LoadIdentity( void )
  304. {
  305.    GET_CURRENT_CONTEXT(ctx);
  306.  
  307.    FLUSH_VERTICES(ctx, 0);
  308.  
  309.    if (MESA_VERBOSE & VERBOSE_API)
  310.       _mesa_debug(ctx, "glLoadIdentity()\n");
  311.  
  312.    _math_matrix_set_identity( ctx->CurrentStack->Top );
  313.    ctx->NewState |= ctx->CurrentStack->DirtyFlag;
  314. }
  315.  
  316.  
  317. /**
  318.  * Replace the current matrix with a given matrix.
  319.  *
  320.  * \param m matrix.
  321.  *
  322.  * \sa glLoadMatrixf().
  323.  *
  324.  * Flushes the vertices and calls _math_matrix_loadf() with the top-most
  325.  * matrix in the current stack and the given matrix.
  326.  * Marks __struct gl_contextRec::NewState with the dirty stack flag.
  327.  */
  328. void GLAPIENTRY
  329. _mesa_LoadMatrixf( const GLfloat *m )
  330. {
  331.    GET_CURRENT_CONTEXT(ctx);
  332.    if (!m) return;
  333.    if (MESA_VERBOSE & VERBOSE_API)
  334.       _mesa_debug(ctx,
  335.           "glLoadMatrix(%f %f %f %f, %f %f %f %f, %f %f %f %f, %f %f %f %f\n",
  336.           m[0], m[4], m[8], m[12],
  337.           m[1], m[5], m[9], m[13],
  338.           m[2], m[6], m[10], m[14],
  339.           m[3], m[7], m[11], m[15]);
  340.  
  341.    FLUSH_VERTICES(ctx, 0);
  342.    _math_matrix_loadf( ctx->CurrentStack->Top, m );
  343.    ctx->NewState |= ctx->CurrentStack->DirtyFlag;
  344. }
  345.  
  346.  
  347. /**
  348.  * Multiply the current matrix with a given matrix.
  349.  *
  350.  * \param m matrix.
  351.  *
  352.  * \sa glMultMatrixf().
  353.  *
  354.  * Flushes the vertices and calls _math_matrix_mul_floats() with the top-most
  355.  * matrix in the current stack and the given matrix. Marks
  356.  * __struct gl_contextRec::NewState with the dirty stack flag.
  357.  */
  358. void GLAPIENTRY
  359. _mesa_MultMatrixf( const GLfloat *m )
  360. {
  361.    GET_CURRENT_CONTEXT(ctx);
  362.    if (!m) return;
  363.    if (MESA_VERBOSE & VERBOSE_API)
  364.       _mesa_debug(ctx,
  365.           "glMultMatrix(%f %f %f %f, %f %f %f %f, %f %f %f %f, %f %f %f %f\n",
  366.           m[0], m[4], m[8], m[12],
  367.           m[1], m[5], m[9], m[13],
  368.           m[2], m[6], m[10], m[14],
  369.           m[3], m[7], m[11], m[15]);
  370.  
  371.    FLUSH_VERTICES(ctx, 0);
  372.    _math_matrix_mul_floats( ctx->CurrentStack->Top, m );
  373.    ctx->NewState |= ctx->CurrentStack->DirtyFlag;
  374. }
  375.  
  376.  
  377. /**
  378.  * Multiply the current matrix with a rotation matrix.
  379.  *
  380.  * \param angle angle of rotation, in degrees.
  381.  * \param x rotation vector x coordinate.
  382.  * \param y rotation vector y coordinate.
  383.  * \param z rotation vector z coordinate.
  384.  *
  385.  * \sa glRotatef().
  386.  *
  387.  * Flushes the vertices and calls _math_matrix_rotate() with the top-most
  388.  * matrix in the current stack and the given parameters. Marks
  389.  * __struct gl_contextRec::NewState with the dirty stack flag.
  390.  */
  391. void GLAPIENTRY
  392. _mesa_Rotatef( GLfloat angle, GLfloat x, GLfloat y, GLfloat z )
  393. {
  394.    GET_CURRENT_CONTEXT(ctx);
  395.  
  396.    FLUSH_VERTICES(ctx, 0);
  397.    if (angle != 0.0F) {
  398.       _math_matrix_rotate( ctx->CurrentStack->Top, angle, x, y, z);
  399.       ctx->NewState |= ctx->CurrentStack->DirtyFlag;
  400.    }
  401. }
  402.  
  403.  
  404. /**
  405.  * Multiply the current matrix with a general scaling matrix.
  406.  *
  407.  * \param x x axis scale factor.
  408.  * \param y y axis scale factor.
  409.  * \param z z axis scale factor.
  410.  *
  411.  * \sa glScalef().
  412.  *
  413.  * Flushes the vertices and calls _math_matrix_scale() with the top-most
  414.  * matrix in the current stack and the given parameters. Marks
  415.  * __struct gl_contextRec::NewState with the dirty stack flag.
  416.  */
  417. void GLAPIENTRY
  418. _mesa_Scalef( GLfloat x, GLfloat y, GLfloat z )
  419. {
  420.    GET_CURRENT_CONTEXT(ctx);
  421.  
  422.    FLUSH_VERTICES(ctx, 0);
  423.    _math_matrix_scale( ctx->CurrentStack->Top, x, y, z);
  424.    ctx->NewState |= ctx->CurrentStack->DirtyFlag;
  425. }
  426.  
  427.  
  428. /**
  429.  * Multiply the current matrix with a translation matrix.
  430.  *
  431.  * \param x translation vector x coordinate.
  432.  * \param y translation vector y coordinate.
  433.  * \param z translation vector z coordinate.
  434.  *
  435.  * \sa glTranslatef().
  436.  *
  437.  * Flushes the vertices and calls _math_matrix_translate() with the top-most
  438.  * matrix in the current stack and the given parameters. Marks
  439.  * __struct gl_contextRec::NewState with the dirty stack flag.
  440.  */
  441. void GLAPIENTRY
  442. _mesa_Translatef( GLfloat x, GLfloat y, GLfloat z )
  443. {
  444.    GET_CURRENT_CONTEXT(ctx);
  445.  
  446.    FLUSH_VERTICES(ctx, 0);
  447.    _math_matrix_translate( ctx->CurrentStack->Top, x, y, z);
  448.    ctx->NewState |= ctx->CurrentStack->DirtyFlag;
  449. }
  450.  
  451.  
  452. void GLAPIENTRY
  453. _mesa_LoadMatrixd( const GLdouble *m )
  454. {
  455.    GLint i;
  456.    GLfloat f[16];
  457.    if (!m) return;
  458.    for (i = 0; i < 16; i++)
  459.       f[i] = (GLfloat) m[i];
  460.    _mesa_LoadMatrixf(f);
  461. }
  462.  
  463. void GLAPIENTRY
  464. _mesa_MultMatrixd( const GLdouble *m )
  465. {
  466.    GLint i;
  467.    GLfloat f[16];
  468.    if (!m) return;
  469.    for (i = 0; i < 16; i++)
  470.       f[i] = (GLfloat) m[i];
  471.    _mesa_MultMatrixf( f );
  472. }
  473.  
  474.  
  475. void GLAPIENTRY
  476. _mesa_Rotated( GLdouble angle, GLdouble x, GLdouble y, GLdouble z )
  477. {
  478.    _mesa_Rotatef((GLfloat) angle, (GLfloat) x, (GLfloat) y, (GLfloat) z);
  479. }
  480.  
  481.  
  482. void GLAPIENTRY
  483. _mesa_Scaled( GLdouble x, GLdouble y, GLdouble z )
  484. {
  485.    _mesa_Scalef((GLfloat) x, (GLfloat) y, (GLfloat) z);
  486. }
  487.  
  488.  
  489. void GLAPIENTRY
  490. _mesa_Translated( GLdouble x, GLdouble y, GLdouble z )
  491. {
  492.    _mesa_Translatef((GLfloat) x, (GLfloat) y, (GLfloat) z);
  493. }
  494.  
  495.  
  496. void GLAPIENTRY
  497. _mesa_LoadTransposeMatrixf( const GLfloat *m )
  498. {
  499.    GLfloat tm[16];
  500.    if (!m) return;
  501.    _math_transposef(tm, m);
  502.    _mesa_LoadMatrixf(tm);
  503. }
  504.  
  505.  
  506. void GLAPIENTRY
  507. _mesa_LoadTransposeMatrixd( const GLdouble *m )
  508. {
  509.    GLfloat tm[16];
  510.    if (!m) return;
  511.    _math_transposefd(tm, m);
  512.    _mesa_LoadMatrixf(tm);
  513. }
  514.  
  515.  
  516. void GLAPIENTRY
  517. _mesa_MultTransposeMatrixf( const GLfloat *m )
  518. {
  519.    GLfloat tm[16];
  520.    if (!m) return;
  521.    _math_transposef(tm, m);
  522.    _mesa_MultMatrixf(tm);
  523. }
  524.  
  525.  
  526. void GLAPIENTRY
  527. _mesa_MultTransposeMatrixd( const GLdouble *m )
  528. {
  529.    GLfloat tm[16];
  530.    if (!m) return;
  531.    _math_transposefd(tm, m);
  532.    _mesa_MultMatrixf(tm);
  533. }
  534.  
  535.  
  536.  
  537. /**********************************************************************/
  538. /** \name State management */
  539. /*@{*/
  540.  
  541.  
  542. /**
  543.  * Update the projection matrix stack.
  544.  *
  545.  * \param ctx GL context.
  546.  *
  547.  * Calls _math_matrix_analyse() with the top-matrix of the projection matrix
  548.  * stack, and recomputes user clip positions if necessary.
  549.  *
  550.  * \note This routine references __struct gl_contextRec::Tranform attribute
  551.  * values to compute userclip positions in clip space, but is only called on
  552.  * _NEW_PROJECTION.  The _mesa_ClipPlane() function keeps these values up to
  553.  * date across changes to the __struct gl_contextRec::Transform attributes.
  554.  */
  555. static void
  556. update_projection( struct gl_context *ctx )
  557. {
  558.    _math_matrix_analyse( ctx->ProjectionMatrixStack.Top );
  559.  
  560.    /* Recompute clip plane positions in clipspace.  This is also done
  561.     * in _mesa_ClipPlane().
  562.     */
  563.    if (ctx->Transform.ClipPlanesEnabled) {
  564.       GLuint p;
  565.       for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
  566.          if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
  567.             _mesa_transform_vector( ctx->Transform._ClipUserPlane[p],
  568.                                  ctx->Transform.EyeUserPlane[p],
  569.                                  ctx->ProjectionMatrixStack.Top->inv );
  570.          }
  571.       }
  572.    }
  573. }
  574.  
  575.  
  576. /**
  577.  * Calculate the combined modelview-projection matrix.
  578.  *
  579.  * \param ctx GL context.
  580.  *
  581.  * Multiplies the top matrices of the projection and model view stacks into
  582.  * __struct gl_contextRec::_ModelProjectMatrix via _math_matrix_mul_matrix()
  583.  * and analyzes the resulting matrix via _math_matrix_analyse().
  584.  */
  585. static void
  586. calculate_model_project_matrix( struct gl_context *ctx )
  587. {
  588.    _math_matrix_mul_matrix( &ctx->_ModelProjectMatrix,
  589.                             ctx->ProjectionMatrixStack.Top,
  590.                             ctx->ModelviewMatrixStack.Top );
  591.  
  592.    _math_matrix_analyse( &ctx->_ModelProjectMatrix );
  593. }
  594.  
  595.  
  596. /**
  597.  * Updates the combined modelview-projection matrix.
  598.  *
  599.  * \param ctx GL context.
  600.  * \param new_state new state bit mask.
  601.  *
  602.  * If there is a new model view matrix then analyzes it. If there is a new
  603.  * projection matrix, updates it. Finally calls
  604.  * calculate_model_project_matrix() to recalculate the modelview-projection
  605.  * matrix.
  606.  */
  607. void _mesa_update_modelview_project( struct gl_context *ctx, GLuint new_state )
  608. {
  609.    if (new_state & _NEW_MODELVIEW)
  610.       _math_matrix_analyse( ctx->ModelviewMatrixStack.Top );
  611.  
  612.    if (new_state & _NEW_PROJECTION)
  613.       update_projection( ctx );
  614.  
  615.    /* Keep ModelviewProject up to date always to allow tnl
  616.     * implementations that go model->clip even when eye is required.
  617.     */
  618.    calculate_model_project_matrix(ctx);
  619. }
  620.  
  621. /*@}*/
  622.  
  623.  
  624. /**********************************************************************/
  625. /** Matrix stack initialization */
  626. /*@{*/
  627.  
  628.  
  629. /**
  630.  * Initialize a matrix stack.
  631.  *
  632.  * \param stack matrix stack.
  633.  * \param maxDepth maximum stack depth.
  634.  * \param dirtyFlag dirty flag.
  635.  *
  636.  * Allocates an array of \p maxDepth elements for the matrix stack and calls
  637.  * _math_matrix_ctr() for each element to initialize it.
  638.  */
  639. static void
  640. init_matrix_stack( struct gl_matrix_stack *stack,
  641.                    GLuint maxDepth, GLuint dirtyFlag )
  642. {
  643.    GLuint i;
  644.  
  645.    stack->Depth = 0;
  646.    stack->MaxDepth = maxDepth;
  647.    stack->DirtyFlag = dirtyFlag;
  648.    /* The stack */
  649.    stack->Stack = calloc(maxDepth, sizeof(GLmatrix));
  650.    for (i = 0; i < maxDepth; i++) {
  651.       _math_matrix_ctr(&stack->Stack[i]);
  652.    }
  653.    stack->Top = stack->Stack;
  654. }
  655.  
  656. /**
  657.  * Free matrix stack.
  658.  *
  659.  * \param stack matrix stack.
  660.  *
  661.  * Calls _math_matrix_dtr() for each element of the matrix stack and
  662.  * frees the array.
  663.  */
  664. static void
  665. free_matrix_stack( struct gl_matrix_stack *stack )
  666. {
  667.    GLuint i;
  668.    for (i = 0; i < stack->MaxDepth; i++) {
  669.       _math_matrix_dtr(&stack->Stack[i]);
  670.    }
  671.    free(stack->Stack);
  672.    stack->Stack = stack->Top = NULL;
  673. }
  674.  
  675. /*@}*/
  676.  
  677.  
  678. /**********************************************************************/
  679. /** \name Initialization */
  680. /*@{*/
  681.  
  682.  
  683. /**
  684.  * Initialize the context matrix data.
  685.  *
  686.  * \param ctx GL context.
  687.  *
  688.  * Initializes each of the matrix stacks and the combined modelview-projection
  689.  * matrix.
  690.  */
  691. void _mesa_init_matrix( struct gl_context * ctx )
  692. {
  693.    GLuint i;
  694.  
  695.    /* Initialize matrix stacks */
  696.    init_matrix_stack(&ctx->ModelviewMatrixStack, MAX_MODELVIEW_STACK_DEPTH,
  697.                      _NEW_MODELVIEW);
  698.    init_matrix_stack(&ctx->ProjectionMatrixStack, MAX_PROJECTION_STACK_DEPTH,
  699.                      _NEW_PROJECTION);
  700.    for (i = 0; i < ARRAY_SIZE(ctx->TextureMatrixStack); i++)
  701.       init_matrix_stack(&ctx->TextureMatrixStack[i], MAX_TEXTURE_STACK_DEPTH,
  702.                         _NEW_TEXTURE_MATRIX);
  703.    for (i = 0; i < ARRAY_SIZE(ctx->ProgramMatrixStack); i++)
  704.       init_matrix_stack(&ctx->ProgramMatrixStack[i],
  705.                         MAX_PROGRAM_MATRIX_STACK_DEPTH, _NEW_TRACK_MATRIX);
  706.    ctx->CurrentStack = &ctx->ModelviewMatrixStack;
  707.  
  708.    /* Init combined Modelview*Projection matrix */
  709.    _math_matrix_ctr( &ctx->_ModelProjectMatrix );
  710. }
  711.  
  712.  
  713. /**
  714.  * Free the context matrix data.
  715.  *
  716.  * \param ctx GL context.
  717.  *
  718.  * Frees each of the matrix stacks and the combined modelview-projection
  719.  * matrix.
  720.  */
  721. void _mesa_free_matrix_data( struct gl_context *ctx )
  722. {
  723.    GLuint i;
  724.  
  725.    free_matrix_stack(&ctx->ModelviewMatrixStack);
  726.    free_matrix_stack(&ctx->ProjectionMatrixStack);
  727.    for (i = 0; i < ARRAY_SIZE(ctx->TextureMatrixStack); i++)
  728.       free_matrix_stack(&ctx->TextureMatrixStack[i]);
  729.    for (i = 0; i < ARRAY_SIZE(ctx->ProgramMatrixStack); i++)
  730.       free_matrix_stack(&ctx->ProgramMatrixStack[i]);
  731.    /* combined Modelview*Projection matrix */
  732.    _math_matrix_dtr( &ctx->_ModelProjectMatrix );
  733.  
  734. }
  735.  
  736.  
  737. /**
  738.  * Initialize the context transform attribute group.
  739.  *
  740.  * \param ctx GL context.
  741.  *
  742.  * \todo Move this to a new file with other 'transform' routines.
  743.  */
  744. void _mesa_init_transform( struct gl_context *ctx )
  745. {
  746.    GLuint i;
  747.  
  748.    /* Transformation group */
  749.    ctx->Transform.MatrixMode = GL_MODELVIEW;
  750.    ctx->Transform.Normalize = GL_FALSE;
  751.    ctx->Transform.RescaleNormals = GL_FALSE;
  752.    ctx->Transform.RasterPositionUnclipped = GL_FALSE;
  753.    for (i=0;i<ctx->Const.MaxClipPlanes;i++) {
  754.       ASSIGN_4V( ctx->Transform.EyeUserPlane[i], 0.0, 0.0, 0.0, 0.0 );
  755.    }
  756.    ctx->Transform.ClipPlanesEnabled = 0;
  757. }
  758.  
  759.  
  760. /*@}*/
  761.