ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

t_draw.c
Go to the documentation of this file.
00001 /*
00002  * Mesa 3-D graphics library
00003  * Version:  7.1
00004  *
00005  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
00006  *
00007  * Permission is hereby granted, free of charge, to any person obtaining a
00008  * copy of this software and associated documentation files (the "Software"),
00009  * to deal in the Software without restriction, including without limitation
00010  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00011  * and/or sell copies of the Software, and to permit persons to whom the
00012  * Software is furnished to do so, subject to the following conditions:
00013  *
00014  * The above copyright notice and this permission notice shall be included
00015  * in all copies or substantial portions of the Software.
00016  *
00017  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00018  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00019  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00020  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00021  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00022  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00023  *
00024  * Authors:
00025  *    Keith Whitwell <keith@tungstengraphics.com>
00026  */
00027 
00028 #include "main/glheader.h"
00029 #include "main/context.h"
00030 #include "main/imports.h"
00031 #include "main/state.h"
00032 #include "main/mtypes.h"
00033 #include "main/macros.h"
00034 #include "main/enums.h"
00035 
00036 #include "t_context.h"
00037 #include "t_pipeline.h"
00038 #include "t_vp_build.h"
00039 #include "t_vertex.h"
00040 #include "tnl.h"
00041 
00042 
00043 
00044 static GLubyte *get_space(GLcontext *ctx, GLuint bytes)
00045 {
00046    TNLcontext *tnl = TNL_CONTEXT(ctx);
00047    GLubyte *space = _mesa_malloc(bytes);
00048    
00049    tnl->block[tnl->nr_blocks++] = space;
00050    return space;
00051 }
00052 
00053 
00054 static void free_space(GLcontext *ctx)
00055 {
00056    TNLcontext *tnl = TNL_CONTEXT(ctx);
00057    GLuint i;
00058    for (i = 0; i < tnl->nr_blocks; i++)
00059       _mesa_free(tnl->block[i]);
00060    tnl->nr_blocks = 0;
00061 }
00062 
00063 
00064 /* Convert the incoming array to GLfloats.  Understands the
00065  * array->Normalized flag and selects the correct conversion method.
00066  */
00067 #define CONVERT( TYPE, MACRO ) do {     \
00068    GLuint i, j;                 \
00069    if (input->Normalized) {         \
00070       for (i = 0; i < count; i++) {     \
00071      const TYPE *in = (TYPE *)ptr;      \
00072      for (j = 0; j < sz; j++) {     \
00073         *fptr++ = MACRO(*in);       \
00074         in++;               \
00075      }                  \
00076      ptr += input->StrideB;         \
00077       }                     \
00078    } else {                 \
00079       for (i = 0; i < count; i++) {     \
00080      const TYPE *in = (TYPE *)ptr;      \
00081      for (j = 0; j < sz; j++) {     \
00082         *fptr++ = (GLfloat)(*in);       \
00083         in++;               \
00084      }                  \
00085      ptr += input->StrideB;         \
00086       }                     \
00087    }                        \
00088 } while (0)
00089 
00090 
00091 
00092 /* Adjust pointer to point at first requested element, convert to
00093  * floating point, populate VB->AttribPtr[].
00094  */
00095 static void _tnl_import_array( GLcontext *ctx,
00096                    GLuint attrib,
00097                    GLuint count,
00098                    const struct gl_client_array *input,
00099                    const GLubyte *ptr )
00100 {
00101    TNLcontext *tnl = TNL_CONTEXT(ctx);
00102    struct vertex_buffer *VB = &tnl->vb;
00103    GLuint stride = input->StrideB;
00104 
00105    if (input->Type != GL_FLOAT) {
00106       const GLuint sz = input->Size;
00107       GLubyte *buf = get_space(ctx, count * sz * sizeof(GLfloat));
00108       GLfloat *fptr = (GLfloat *)buf;
00109 
00110       switch (input->Type) {
00111       case GL_BYTE: 
00112      CONVERT(GLbyte, BYTE_TO_FLOAT); 
00113      break;
00114       case GL_UNSIGNED_BYTE: 
00115      CONVERT(GLubyte, UBYTE_TO_FLOAT); 
00116      break;
00117       case GL_SHORT: 
00118      CONVERT(GLshort, SHORT_TO_FLOAT); 
00119      break;
00120       case GL_UNSIGNED_SHORT: 
00121      CONVERT(GLushort, USHORT_TO_FLOAT); 
00122      break;
00123       case GL_INT: 
00124      CONVERT(GLint, INT_TO_FLOAT); 
00125      break;
00126       case GL_UNSIGNED_INT: 
00127      CONVERT(GLuint, UINT_TO_FLOAT); 
00128      break;
00129       case GL_DOUBLE: 
00130      CONVERT(GLdouble, (GLfloat)); 
00131      break;
00132       default:
00133      assert(0);
00134      break;
00135       }
00136 
00137       ptr = buf;
00138       stride = sz * sizeof(GLfloat);
00139    }
00140 
00141    VB->AttribPtr[attrib] = &tnl->tmp_inputs[attrib];
00142    VB->AttribPtr[attrib]->data = (GLfloat (*)[4])ptr;
00143    VB->AttribPtr[attrib]->start = (GLfloat *)ptr;
00144    VB->AttribPtr[attrib]->count = count;
00145    VB->AttribPtr[attrib]->stride = stride;
00146    VB->AttribPtr[attrib]->size = input->Size;
00147 
00148    /* This should die, but so should the whole GLvector4f concept: 
00149     */
00150    VB->AttribPtr[attrib]->flags = (((1<<input->Size)-1) | 
00151                    VEC_NOT_WRITEABLE |
00152                    (stride == 4*sizeof(GLfloat) ? 0 : VEC_BAD_STRIDE));
00153    
00154    VB->AttribPtr[attrib]->storage = NULL;
00155 }
00156 
00157 #define CLIPVERTS  ((6 + MAX_CLIP_PLANES) * 2)
00158 
00159 
00160 static GLboolean *_tnl_import_edgeflag( GLcontext *ctx,
00161                     const GLvector4f *input,
00162                     GLuint count)
00163 {
00164    const GLubyte *ptr = (const GLubyte *)input->data;
00165    const GLuint stride = input->stride;
00166    GLboolean *space = (GLboolean *)get_space(ctx, count + CLIPVERTS);
00167    GLboolean *bptr = space;
00168    GLuint i;
00169 
00170    for (i = 0; i < count; i++) {
00171       *bptr++ = ((GLfloat *)ptr)[0] == 1.0;
00172       ptr += stride;
00173    }
00174 
00175    return space;
00176 }
00177 
00178 
00179 static void bind_inputs( GLcontext *ctx, 
00180              const struct gl_client_array *inputs[],
00181              GLint count,
00182              struct gl_buffer_object **bo,
00183              GLuint *nr_bo )
00184 {
00185    TNLcontext *tnl = TNL_CONTEXT(ctx);
00186    struct vertex_buffer *VB = &tnl->vb;
00187    GLuint i;
00188 
00189    /* Map all the VBOs
00190     */
00191    for (i = 0; i < VERT_ATTRIB_MAX; i++) {
00192       const void *ptr;
00193 
00194       if (inputs[i]->BufferObj->Name) { 
00195      if (!inputs[i]->BufferObj->Pointer) {
00196         bo[*nr_bo] = inputs[i]->BufferObj;
00197         (*nr_bo)++;
00198         ctx->Driver.MapBuffer(ctx, 
00199                   GL_ARRAY_BUFFER,
00200                   GL_READ_ONLY_ARB,
00201                   inputs[i]->BufferObj);
00202         
00203         assert(inputs[i]->BufferObj->Pointer);
00204      }
00205      
00206      ptr = ADD_POINTERS(inputs[i]->BufferObj->Pointer,
00207                 inputs[i]->Ptr);
00208       }
00209       else
00210      ptr = inputs[i]->Ptr;
00211 
00212       /* Just make sure the array is floating point, otherwise convert to
00213        * temporary storage.  
00214        *
00215        * XXX: remove the GLvector4f type at some stage and just use
00216        * client arrays.
00217        */
00218       _tnl_import_array(ctx, i, count, inputs[i], ptr);
00219    }
00220 
00221    /* We process only the vertices between min & max index:
00222     */
00223    VB->Count = count;
00224 
00225 
00226    /* Legacy pointers -- remove one day.
00227     */
00228    VB->ObjPtr = VB->AttribPtr[_TNL_ATTRIB_POS];
00229    VB->NormalPtr = VB->AttribPtr[_TNL_ATTRIB_NORMAL];
00230    VB->ColorPtr[0] = VB->AttribPtr[_TNL_ATTRIB_COLOR0];
00231    VB->ColorPtr[1] = NULL;
00232    VB->IndexPtr[0] = VB->AttribPtr[_TNL_ATTRIB_COLOR_INDEX];
00233    VB->IndexPtr[1] = NULL;
00234    VB->SecondaryColorPtr[0] = VB->AttribPtr[_TNL_ATTRIB_COLOR1];
00235    VB->SecondaryColorPtr[1] = NULL;
00236    VB->FogCoordPtr = VB->AttribPtr[_TNL_ATTRIB_FOG];
00237 
00238    for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
00239       VB->TexCoordPtr[i] = VB->AttribPtr[_TNL_ATTRIB_TEX0 + i];
00240    }
00241 
00242    /* Clipping and drawing code still requires this to be a packed
00243     * array of ubytes which can be written into.  TODO: Fix and
00244     * remove.
00245     */
00246    if (ctx->Polygon.FrontMode != GL_FILL ||
00247        ctx->Polygon.BackMode != GL_FILL)
00248    {
00249       VB->EdgeFlag = _tnl_import_edgeflag( ctx, 
00250                        VB->AttribPtr[_TNL_ATTRIB_EDGEFLAG],
00251                        VB->Count );
00252    }
00253    else {
00254       /* the data previously pointed to by EdgeFlag may have been freed */
00255       VB->EdgeFlag = NULL;
00256    }
00257 }
00258 
00259 
00260 /* Translate indices to GLuints and store in VB->Elts.
00261  */
00262 static void bind_indices( GLcontext *ctx,
00263               const struct _mesa_index_buffer *ib,
00264               struct gl_buffer_object **bo,
00265               GLuint *nr_bo)
00266 {
00267    TNLcontext *tnl = TNL_CONTEXT(ctx);
00268    struct vertex_buffer *VB = &tnl->vb;
00269    GLuint i;
00270    void *ptr;
00271 
00272    if (!ib) {
00273       VB->Elts = NULL;
00274       return;
00275    }
00276 
00277    if (ib->obj->Name && !ib->obj->Pointer) {
00278       bo[*nr_bo] = ib->obj;
00279       (*nr_bo)++;
00280       ctx->Driver.MapBuffer(ctx, 
00281                 GL_ELEMENT_ARRAY_BUFFER,
00282                 GL_READ_ONLY_ARB,
00283                 ib->obj);
00284 
00285       assert(ib->obj->Pointer);
00286    }
00287 
00288    ptr = ADD_POINTERS(ib->obj->Pointer, ib->ptr);
00289 
00290    if (ib->type == GL_UNSIGNED_INT) {
00291       VB->Elts = (GLuint *) ptr;
00292    }
00293    else {
00294       GLuint *elts = (GLuint *)get_space(ctx, ib->count * sizeof(GLuint));
00295       VB->Elts = elts;
00296 
00297       if (ib->type == GL_UNSIGNED_SHORT) {
00298      const GLushort *in = (GLushort *)ptr;
00299      for (i = 0; i < ib->count; i++) 
00300         *elts++ = (GLuint)(*in++);
00301       }
00302       else {
00303      const GLubyte *in = (GLubyte *)ptr;
00304      for (i = 0; i < ib->count; i++) 
00305         *elts++ = (GLuint)(*in++);
00306       }
00307    }
00308 }
00309 
00310 static void bind_prims( GLcontext *ctx,
00311             const struct _mesa_prim *prim,
00312             GLuint nr_prims )
00313 {
00314    TNLcontext *tnl = TNL_CONTEXT(ctx);
00315    struct vertex_buffer *VB = &tnl->vb;
00316 
00317    VB->Primitive = prim;
00318    VB->PrimitiveCount = nr_prims;
00319 }
00320 
00321 static void unmap_vbos( GLcontext *ctx,
00322             struct gl_buffer_object **bo,
00323             GLuint nr_bo )
00324 {
00325    GLuint i;
00326    for (i = 0; i < nr_bo; i++) { 
00327       ctx->Driver.UnmapBuffer(ctx, 
00328                   0, /* target -- I don't see why this would be needed */
00329                   bo[i]);
00330    }
00331 }
00332 
00333 
00334 
00335 /* This is the main entrypoint into the slimmed-down software tnl
00336  * module.  In a regular swtnl driver, this can be plugged straight
00337  * into the vbo->Driver.DrawPrims() callback.
00338  */
00339 void _tnl_draw_prims( GLcontext *ctx,
00340               const struct gl_client_array *arrays[],
00341               const struct _mesa_prim *prim,
00342               GLuint nr_prims,
00343               const struct _mesa_index_buffer *ib,
00344               GLuint min_index,
00345               GLuint max_index)
00346 {
00347    TNLcontext *tnl = TNL_CONTEXT(ctx);
00348    const GLuint TEST_SPLIT = 0;
00349    const GLint max = TEST_SPLIT ? 8 : tnl->vb.Size - MAX_CLIPPED_VERTICES;
00350 
00351    if (0)
00352    {
00353       GLuint i;
00354       _mesa_printf("%s %d..%d\n", __FUNCTION__, min_index, max_index);
00355       for (i = 0; i < nr_prims; i++)
00356      _mesa_printf("prim %d: %s start %d count %d\n", i, 
00357               _mesa_lookup_enum_by_nr(prim[i].mode),
00358               prim[i].start,
00359               prim[i].count);
00360    }
00361 
00362    if (min_index) {
00363       /* We always translate away calls with min_index != 0. 
00364        */
00365       vbo_rebase_prims( ctx, arrays, prim, nr_prims, ib, 
00366             min_index, max_index,
00367             _tnl_draw_prims );
00368       return;
00369    }
00370    else if (max_index > max) {
00371       /* The software TNL pipeline has a fixed amount of storage for
00372        * vertices and it is necessary to split incoming drawing commands
00373        * if they exceed that limit.
00374        */
00375       struct split_limits limits;
00376       limits.max_verts = max;
00377       limits.max_vb_size = ~0;
00378       limits.max_indices = ~0;
00379 
00380       /* This will split the buffers one way or another and
00381        * recursively call back into this function.
00382        */
00383       vbo_split_prims( ctx, arrays, prim, nr_prims, ib, 
00384                0, max_index,
00385                _tnl_draw_prims,
00386                &limits );
00387    }
00388    else {
00389       /* May need to map a vertex buffer object for every attribute plus
00390        * one for the index buffer.
00391        */
00392       struct gl_buffer_object *bo[VERT_ATTRIB_MAX + 1];
00393       GLuint nr_bo = 0;
00394 
00395       /* Binding inputs may imply mapping some vertex buffer objects.
00396        * They will need to be unmapped below.
00397        */
00398       bind_inputs(ctx, arrays, max_index+1, bo, &nr_bo);
00399       bind_indices(ctx, ib, bo, &nr_bo);
00400       bind_prims(ctx, prim, nr_prims );
00401 
00402       TNL_CONTEXT(ctx)->Driver.RunPipeline(ctx);
00403 
00404       unmap_vbos(ctx, bo, nr_bo);
00405       free_space(ctx);
00406    }
00407 }
00408 

Generated on Sat May 26 2012 04:19:35 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.