home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 5 / MA_Cover_5.iso / ppc / mesa / src / texobj.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-01-31  |  15.3 KB  |  626 lines

  1. /* $Id: texobj.c,v 1.19 1997/11/07 03:38:07 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  2.5
  6.  * Copyright (C) 1995-1997  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: texobj.c,v $
  26.  * Revision 1.19  1997/11/07 03:38:07  brianp
  27.  * added stdio.h include for SunOS 4.x
  28.  *
  29.  * Revision 1.18  1997/10/13 23:57:59  brianp
  30.  * added target parameter to Driver.BindTexture()
  31.  *
  32.  * Revision 1.17  1997/09/29 23:28:14  brianp
  33.  * updated for new device driver texture functions
  34.  *
  35.  * Revision 1.16  1997/09/27 00:14:39  brianp
  36.  * added GL_EXT_paletted_texture extension
  37.  *
  38.  * Revision 1.15  1997/09/23 00:58:15  brianp
  39.  * now using hash table for texture objects
  40.  *
  41.  * Revision 1.14  1997/08/23 18:41:40  brianp
  42.  * fixed bug in glBindTexture() when binding an incomplete texture image
  43.  *
  44.  * Revision 1.13  1997/08/23 17:14:44  brianp
  45.  * fixed bug:  glBindTexture(target, 0) caused segfault
  46.  *
  47.  * Revision 1.12  1997/07/24 01:25:34  brianp
  48.  * changed precompiled header symbol from PCH to PC_HEADER
  49.  *
  50.  * Revision 1.11  1997/05/28 03:26:49  brianp
  51.  * added precompiled header (PCH) support
  52.  *
  53.  * Revision 1.10  1997/05/17 03:41:49  brianp
  54.  * added code to update ctx->Texture.Current in gl_BindTexture()
  55.  *
  56.  * Revision 1.9  1997/05/03 00:52:52  brianp
  57.  * removed a few unused variables
  58.  *
  59.  * Revision 1.8  1997/05/01 02:08:12  brianp
  60.  * new implementation of gl_BindTexture()
  61.  *
  62.  * Revision 1.7  1997/04/28 23:38:45  brianp
  63.  * added gl_test_texture_object_completeness()
  64.  *
  65.  * Revision 1.6  1997/04/14 02:03:05  brianp
  66.  * added MinMagThresh to texture object
  67.  *
  68.  * Revision 1.5  1997/02/09 18:52:15  brianp
  69.  * added GL_EXT_texture3D support
  70.  *
  71.  * Revision 1.4  1997/01/16 03:35:34  brianp
  72.  * added calls to device driver DeleteTexture() and BindTexture() functions
  73.  *
  74.  * Revision 1.3  1997/01/09 19:49:47  brianp
  75.  * added a check to switch rasterizers if needed in glBindTexture()
  76.  *
  77.  * Revision 1.2  1996/09/27 17:09:42  brianp
  78.  * removed a redundant return statement
  79.  *
  80.  * Revision 1.1  1996/09/13 01:38:16  brianp
  81.  * Initial revision
  82.  *
  83.  */
  84.  
  85.  
  86. #ifdef PC_HEADER
  87. #include "all.h"
  88. #else
  89. #include <assert.h>
  90. #include <stdio.h>
  91. #include <stdlib.h>
  92. #include "context.h"
  93. #include "hash.h"
  94. #include "macros.h"
  95. #include "teximage.h"
  96. #include "texobj.h"
  97. #include "types.h"
  98. #endif
  99.  
  100.  
  101.  
  102. /*
  103.  * Allocate a new texture object and add it to the linked list of texture
  104.  * objects.  If name>0 then also insert the new texture object into the hash
  105.  * table.
  106.  * Input:  shared - the shared GL state structure to contain the texture object
  107.  *         name - integer name for the texture object
  108.  *         dimensions - either 1, 2 or 3
  109.  * Return:  pointer to new texture object
  110.  */
  111. struct gl_texture_object *
  112. gl_alloc_texture_object( struct gl_shared_state *shared, GLuint name,
  113.              GLuint dimensions)
  114. {
  115.    struct gl_texture_object *obj;
  116.  
  117.    assert(dimensions >= 1 && dimensions <= 3);
  118.  
  119.    obj = (struct gl_texture_object *)
  120.              calloc(1,sizeof(struct gl_texture_object));
  121.    if (obj) {
  122.       /* init the non-zero fields */
  123.       obj->Name = name;
  124.       obj->Dimensions = dimensions;
  125.       obj->WrapS = GL_REPEAT;
  126.       obj->WrapT = GL_REPEAT;
  127.       obj->MinFilter = GL_NEAREST_MIPMAP_LINEAR;
  128.       obj->MagFilter = GL_LINEAR;
  129.       obj->MinMagThresh = 0.0F;
  130.       obj->Palette[0] = 255;
  131.       obj->Palette[1] = 255;
  132.       obj->Palette[2] = 255;
  133.       obj->Palette[3] = 255;
  134.       obj->PaletteSize = 1;
  135.       obj->PaletteIntFormat = GL_RGBA;
  136.       obj->PaletteFormat = GL_RGBA;
  137.  
  138.       /* insert into linked list */
  139.       if (shared) {
  140.      obj->Next = shared->TexObjectList;
  141.      shared->TexObjectList = obj;
  142.       }
  143.  
  144.       if (name > 0) {
  145.      /* insert into hash table */
  146.      HashInsert(shared->TexObjects, name, obj);
  147.       }
  148.    }
  149.    return obj;
  150. }
  151.  
  152.  
  153. /*
  154.  * Deallocate a texture object struct and remove it from the given
  155.  * shared GL state.
  156.  * Input:  shared - the shared GL state to which the object belongs
  157.  *         t - the texture object to delete
  158.  */
  159. void gl_free_texture_object( struct gl_shared_state *shared,
  160.                  struct gl_texture_object *t )
  161. {
  162.    struct gl_texture_object *tprev, *tcurr;
  163.  
  164.    assert(t);
  165.  
  166.    /* unlink t from the linked list */
  167.    if (shared) {
  168.       tprev = NULL;
  169.       tcurr = shared->TexObjectList;
  170.       while (tcurr) {
  171.      if (tcurr==t) {
  172.         if (tprev) {
  173.            tprev->Next = t->Next;
  174.         }
  175.         else {
  176.            shared->TexObjectList = t->Next;
  177.         }
  178.         break;
  179.      }
  180.      tprev = tcurr;
  181.      tcurr = tcurr->Next;
  182.       }
  183.    }
  184.  
  185.    if (t->Name) {
  186.       /* remove from hash table */
  187.       HashRemove(shared->TexObjects, t->Name);
  188.    }
  189.  
  190.    /* free texture image */
  191.    {
  192.       GLuint i;
  193.       for (i=0;i<MAX_TEXTURE_LEVELS;i++) {
  194.      if (t->Image[i]) {
  195.         gl_free_texture_image( t->Image[i] );
  196.      }
  197.       }
  198.    }
  199.    /* free this object */
  200.    free( t );
  201. }
  202.  
  203.  
  204.  
  205. /*
  206.  * Examine a texture object to determine if it is complete or not.
  207.  * The t->Complete flag will be set to GL_TRUE or GL_FALSE accordingly.
  208.  */
  209. void gl_test_texture_object_completeness( struct gl_texture_object *t )
  210. {
  211.    t->Complete = GL_TRUE;  /* be optimistic */
  212.  
  213.    /* Always need level zero image */
  214.    if (!t->Image[0] || !t->Image[0]->Data) {
  215.       t->Complete = GL_FALSE;
  216.       return;
  217.    }
  218.  
  219.    if (t->MinFilter!=GL_NEAREST && t->MinFilter!=GL_LINEAR) {
  220.       /*
  221.        * Mipmapping: determine if we have a complete set of mipmaps
  222.        */
  223.       int i;
  224.  
  225.       /* Test dimension-independent attributes */
  226.       for (i=1; i<MAX_TEXTURE_LEVELS; i++) {
  227.      if (t->Image[i]) {
  228.         if (!t->Image[i]->Data) {
  229.            t->Complete = GL_FALSE;
  230.            return;
  231.         }
  232.         if (t->Image[i]->Format != t->Image[0]->Format) {
  233.            t->Complete = GL_FALSE;
  234.            return;
  235.         }
  236.         if (t->Image[i]->Border != t->Image[0]->Border) {
  237.            t->Complete = GL_FALSE;
  238.            return;
  239.         }
  240.      }
  241.       }
  242.  
  243.       /* Test things which depend on number of texture image dimensions */
  244.       if (t->Dimensions==1) {
  245.      /* Test 1-D mipmaps */
  246.      GLuint width = t->Image[0]->Width2;
  247.      for (i=1; i<MAX_TEXTURE_LEVELS; i++) {
  248.         if (width>1) {
  249.            width /= 2;
  250.         }
  251.         if (!t->Image[i]) {
  252.            t->Complete = GL_FALSE;
  253.            return;
  254.         }
  255.         if (!t->Image[i]->Data) {
  256.            t->Complete = GL_FALSE;
  257.            return;
  258.         }
  259.         if (t->Image[i]->Format != t->Image[0]->Format) {
  260.            t->Complete = GL_FALSE;
  261.            return;
  262.         }
  263.         if (t->Image[i]->Border != t->Image[0]->Border) {
  264.            t->Complete = GL_FALSE;
  265.            return;
  266.         }
  267.         if (t->Image[i]->Width2 != width ) {
  268.            t->Complete = GL_FALSE;
  269.            return;
  270.         }
  271.         if (width==1) {
  272.            return;  /* found smallest needed mipmap, all done! */
  273.         }
  274.      }
  275.       }
  276.       else if (t->Dimensions==2) {
  277.      /* Test 2-D mipmaps */
  278.      GLuint width = t->Image[0]->Width2;
  279.      GLuint height = t->Image[0]->Height2;
  280.      for (i=1; i<MAX_TEXTURE_LEVELS; i++) {
  281.         if (width>1) {
  282.            width /= 2;
  283.         }
  284.         if (height>1) {
  285.            height /= 2;
  286.         }
  287.         if (!t->Image[i]) {
  288.            t->Complete = GL_FALSE;
  289.            return;
  290.         }
  291.         if (t->Image[i]->Width2 != width) {
  292.            t->Complete = GL_FALSE;
  293.            return;
  294.         }
  295.         if (t->Image[i]->Height2 != height) {
  296.            t->Complete = GL_FALSE;
  297.            return;
  298.         }
  299.         if (width==1 && height==1) {
  300.            return;  /* found smallest needed mipmap, all done! */
  301.         }
  302.      }
  303.       }
  304.       else if (t->Dimensions==3) {
  305.      /* Test 3-D mipmaps */
  306.      GLuint width = t->Image[0]->Width2;
  307.      GLuint height = t->Image[0]->Height2;
  308.      GLuint depth = t->Image[0]->Depth2;
  309.      for (i=1; i<MAX_TEXTURE_LEVELS; i++) {
  310.         if (width>1) {
  311.            width /= 2;
  312.         }
  313.         if (height>1) {
  314.            height /= 2;
  315.         }
  316.         if (depth>1) {
  317.            depth /= 2;
  318.         }
  319.         if (!t->Image[i]) {
  320.            t->Complete = GL_FALSE;
  321.            return;
  322.         }
  323.         if (t->Image[i]->Width2 != width) {
  324.            t->Complete = GL_FALSE;
  325.            return;
  326.         }
  327.         if (t->Image[i]->Height2 != height) {
  328.            t->Complete = GL_FALSE;
  329.            return;
  330.         }
  331.         if (t->Image[i]->Depth2 != depth) {
  332.            t->Complete = GL_FALSE;
  333.            return;
  334.         }
  335.         if (width==1 && height==1 && depth==1) {
  336.            return;  /* found smallest needed mipmap, all done! */
  337.         }
  338.      }
  339.       }
  340.       else {
  341.      /* Dimensions = ??? */
  342.      gl_problem(NULL, "Bug in gl_test_texture_object_completeness\n");
  343.       }
  344.    }
  345. }
  346.  
  347.  
  348.  
  349. /*
  350.  * Execute glGenTextures
  351.  */
  352. void gl_GenTextures( GLcontext *ctx, GLsizei n, GLuint *texName )
  353. {
  354.    GLuint first, i;
  355.  
  356.    if (INSIDE_BEGIN_END(ctx)) {
  357.       gl_error( ctx, GL_INVALID_OPERATION, "glGenTextures" );
  358.       return;
  359.    }
  360.    if (n<0) {
  361.       gl_error( ctx, GL_INVALID_VALUE, "glGenTextures" );
  362.       return;
  363.    }
  364.  
  365.    first = HashFindFreeKeyBlock(ctx->Shared->TexObjects, n);
  366.    for (i=0;i<n;i++) {
  367.       texName[i] = first + i;
  368.    }
  369. }
  370.  
  371.  
  372.  
  373. /*
  374.  * Execute glDeleteTextures
  375.  */
  376. void gl_DeleteTextures( GLcontext *ctx, GLsizei n, const GLuint *texName)
  377. {
  378.    GLuint i;
  379.  
  380.    if (INSIDE_BEGIN_END(ctx)) {
  381.       gl_error( ctx, GL_INVALID_OPERATION, "glAreTexturesResident" );
  382.       return;
  383.    }
  384.  
  385.    for (i=0;i<n;i++) {
  386.       struct gl_texture_object *t;
  387.       if (texName[i]>0) {
  388.      t = (struct gl_texture_object *)
  389.         HashLookup(ctx->Shared->TexObjects, texName[i]);
  390.      if (t) {
  391.         if (ctx->Texture.Current1D==t) {
  392.            /* revert to default 1-D texture */
  393.            ctx->Texture.Current1D = ctx->Shared->Default1D;
  394.            t->RefCount--;
  395.            assert( t->RefCount >= 0 );
  396.         }
  397.         else if (ctx->Texture.Current2D==t) {
  398.            /* revert to default 2-D texture */
  399.            ctx->Texture.Current2D = ctx->Shared->Default2D;
  400.            t->RefCount--;
  401.            assert( t->RefCount >= 0 );
  402.         }
  403.         else if (ctx->Texture.Current3D==t) {
  404.            /* revert to default 3-D texture */
  405.            ctx->Texture.Current3D = ctx->Shared->Default3D;
  406.            t->RefCount--;
  407.            assert( t->RefCount >= 0 );
  408.         }
  409.  
  410.         /* tell device driver to delete texture */
  411.         if (ctx->Driver.DeleteTexture) {
  412.            (*ctx->Driver.DeleteTexture)( ctx, t );
  413.         }
  414.  
  415.         if (t->RefCount==0) {
  416.            gl_free_texture_object(ctx->Shared, t);
  417.         }
  418.      }
  419.       }
  420.    }
  421. }
  422.  
  423.  
  424.  
  425. /*
  426.  * Execute glBindTexture
  427.  */
  428. void gl_BindTexture( GLcontext *ctx, GLenum target, GLuint texName )
  429. {
  430.    struct gl_texture_object *oldTexObj;
  431.    struct gl_texture_object *newTexObj;
  432.    struct gl_texture_object **targetPointer;
  433.    GLuint targetDimensions;
  434.  
  435.    if (INSIDE_BEGIN_END(ctx)) {
  436.       gl_error( ctx, GL_INVALID_OPERATION, "glAreTexturesResident" );
  437.       return;
  438.    }
  439.    switch (target) {
  440.       case GL_TEXTURE_1D:
  441.      oldTexObj = ctx->Texture.Current1D;
  442.      targetPointer = &ctx->Texture.Current1D;
  443.      targetDimensions = 1;
  444.      break;
  445.       case GL_TEXTURE_2D:
  446.      oldTexObj = ctx->Texture.Current2D;
  447.      targetPointer = &ctx->Texture.Current2D;
  448.      targetDimensions = 2;
  449.      break;
  450.       case GL_TEXTURE_3D_EXT:
  451.      oldTexObj = ctx->Texture.Current3D;
  452.      targetPointer = &ctx->Texture.Current3D;
  453.      targetDimensions = 3;
  454.      break;
  455.       default:
  456.      gl_error( ctx, GL_INVALID_ENUM, "glBindTexture" );
  457.      return;
  458.    }
  459.  
  460.    if (texName==0) {
  461.       /* use default n-D texture */
  462.       switch (target) {
  463.      case GL_TEXTURE_1D:
  464.         newTexObj = ctx->Shared->Default1D;
  465.         break;
  466.      case GL_TEXTURE_2D:
  467.         newTexObj = ctx->Shared->Default2D;
  468.         break;
  469.      case GL_TEXTURE_3D_EXT:
  470.         newTexObj = ctx->Shared->Default3D;
  471.         break;
  472.      default:
  473.         gl_problem(ctx, "Bad target in gl_BindTexture");
  474.         return;
  475.       }
  476.    }
  477.    else {
  478.       newTexObj = (struct gl_texture_object *)
  479.                  HashLookup(ctx->Shared->TexObjects, texName);
  480.       if (newTexObj) {
  481.      if (newTexObj->Dimensions!=targetDimensions) {
  482.         /* wrong dimensionality */
  483.         gl_error( ctx, GL_INVALID_OPERATION, "glBindTextureEXT" );
  484.         return;
  485.      }
  486.       }
  487.       else {
  488.      /* create new texture object */
  489.      newTexObj = gl_alloc_texture_object(ctx->Shared, texName,
  490.                          targetDimensions);
  491.       }
  492.    }
  493.  
  494.    /* Update the Texture.Current[123]D pointer */
  495.    *targetPointer = newTexObj;
  496.  
  497.    /* Tidy up reference counting */
  498.    if (*targetPointer != oldTexObj && oldTexObj->Name>0) {
  499.       /* decrement reference count of the prev texture object */
  500.       oldTexObj->RefCount--;
  501.       assert( oldTexObj->RefCount >= 0 );
  502.    }
  503.  
  504.    if (newTexObj->Name>0) {
  505.       newTexObj->RefCount++;
  506.    }
  507.  
  508.    /* Check if we may have to use a new triangle rasterizer */
  509.    if (   oldTexObj->WrapS != newTexObj->WrapS
  510.        || oldTexObj->WrapT != newTexObj->WrapT
  511.        || oldTexObj->WrapR != newTexObj->WrapR
  512.        || oldTexObj->MinFilter != newTexObj->MinFilter
  513.        || oldTexObj->MagFilter != newTexObj->MagFilter
  514.        || !newTexObj->Complete) {
  515.       ctx->NewState |= NEW_RASTER_OPS;
  516.    }
  517.  
  518.    /* If we've changed the Current[123]D texture object then update the
  519.     * ctx->Texture.Current pointer to point to the new texture object.
  520.     */
  521.    if (oldTexObj==ctx->Texture.Current) {
  522.       ctx->Texture.Current = newTexObj;
  523.    }
  524.  
  525.    /* The current n-D texture object can never be NULL! */
  526.    assert(*targetPointer);
  527.  
  528.    /* Pass BindTexture call to device driver */
  529.    if (ctx->Driver.BindTexture) {
  530.       (*ctx->Driver.BindTexture)( ctx, target, newTexObj );
  531.    }
  532. }
  533.  
  534.  
  535.  
  536. /*
  537.  * Execute glPrioritizeTextures
  538.  */
  539. void gl_PrioritizeTextures( GLcontext *ctx,
  540.                 GLsizei n, const GLuint *texName,
  541.                 const GLclampf *priorities )
  542. {
  543.    GLuint i;
  544.  
  545.    if (INSIDE_BEGIN_END(ctx)) {
  546.       gl_error( ctx, GL_INVALID_OPERATION, "glAreTexturesResident" );
  547.       return;
  548.    }
  549.    if (n<0) {
  550.       gl_error( ctx, GL_INVALID_VALUE, "glAreTexturesResident(n)" );
  551.       return;
  552.    }
  553.  
  554.    for (i=0;i<n;i++) {
  555.       struct gl_texture_object *t;
  556.       if (texName[i]>0) {
  557.      t = (struct gl_texture_object *)
  558.         HashLookup(ctx->Shared->TexObjects, texName[i]);
  559.      if (t) {
  560.         t->Priority = CLAMP( priorities[i], 0.0F, 1.0F );
  561.      }
  562.       }
  563.    }
  564. }
  565.  
  566.  
  567.  
  568. /*
  569.  * Execute glAreTexturesResident
  570.  */
  571. GLboolean gl_AreTexturesResident( GLcontext *ctx, GLsizei n,
  572.                   const GLuint *texName,
  573.                   GLboolean *residences )
  574. {
  575.    GLboolean resident = GL_TRUE;
  576.    GLuint i;
  577.  
  578.    if (INSIDE_BEGIN_END(ctx)) {
  579.       gl_error( ctx, GL_INVALID_OPERATION, "glAreTexturesResident" );
  580.       return GL_FALSE;
  581.    }
  582.    if (n<0) {
  583.       gl_error( ctx, GL_INVALID_VALUE, "glAreTexturesResident(n)" );
  584.       return GL_FALSE;
  585.    }
  586.  
  587.    for (i=0;i<n;i++) {
  588.       struct gl_texture_object *t;
  589.       if (texName[i]==0) {
  590.      gl_error( ctx, GL_INVALID_VALUE, "glAreTexturesResident(textures)" );
  591.      return GL_FALSE;
  592.       }
  593.       t = (struct gl_texture_object *)
  594.      HashLookup(ctx->Shared->TexObjects, texName[i]);
  595.       if (t) {
  596.      /* we consider all valid texture objects to be resident */
  597.      residences[i] = GL_TRUE;
  598.       }
  599.       else {
  600.      gl_error( ctx, GL_INVALID_VALUE, "glAreTexturesResident(textures)" );
  601.      return GL_FALSE;
  602.       }
  603.    }
  604.    return resident;
  605. }
  606.  
  607.  
  608.  
  609. /*
  610.  * Execute glIsTexture
  611.  */
  612. GLboolean gl_IsTexture( GLcontext *ctx, GLuint texture )
  613. {
  614.    if (INSIDE_BEGIN_END(ctx)) {
  615.       gl_error( ctx, GL_INVALID_OPERATION, "glIsTextures" );
  616.       return GL_FALSE;
  617.    }
  618.    if (texture>0 && HashLookup(ctx->Shared->TexObjects, texture)) {
  619.       return GL_TRUE;
  620.    }
  621.    else {
  622.       return GL_FALSE;
  623.    }
  624. }
  625.  
  626.