Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygent_dd_dmatmp.h
Go to the documentation of this file.
00001 /* 00002 * Mesa 3-D graphics library 00003 * Version: 6.5.1 00004 * 00005 * Copyright (C) 1999-2006 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 00042 #if !defined(HAVE_TRIANGLES) 00043 #error "must have at least triangles to use render template" 00044 #endif 00045 00046 #if !HAVE_ELTS 00047 #define ELTS_VARS(buf) 00048 #define ALLOC_ELTS(nr) 0 00049 #define EMIT_ELT( offset, elt ) 00050 #define EMIT_TWO_ELTS( offset, elt0, elt1 ) 00051 #define INCR_ELTS( nr ) 00052 #define ELT_INIT(prim) 00053 #define GET_CURRENT_VB_MAX_ELTS() 0 00054 #define GET_SUBSEQUENT_VB_MAX_ELTS() 0 00055 #define RELEASE_ELT_VERTS() 00056 #define EMIT_INDEXED_VERTS( ctx, start, count ) 00057 #endif 00058 00059 #ifndef EMIT_TWO_ELTS 00060 #define EMIT_TWO_ELTS( offset, elt0, elt1 ) \ 00061 do { \ 00062 EMIT_ELT( offset, elt0 ); \ 00063 EMIT_ELT( offset+1, elt1 ); \ 00064 } while (0) 00065 #endif 00066 00067 00068 /**********************************************************************/ 00069 /* Render whole begin/end objects */ 00070 /**********************************************************************/ 00071 00072 00073 00074 00075 #if (HAVE_ELTS) 00076 static void *TAG(emit_elts)( GLcontext *ctx, GLuint *elts, GLuint nr, 00077 void *buf) 00078 { 00079 GLint i; 00080 LOCAL_VARS; 00081 ELTS_VARS(buf); 00082 00083 for ( i = 0 ; i+1 < nr ; i+=2, elts += 2 ) { 00084 EMIT_TWO_ELTS( 0, elts[0], elts[1] ); 00085 INCR_ELTS( 2 ); 00086 } 00087 00088 if (i < nr) { 00089 EMIT_ELT( 0, elts[0] ); 00090 INCR_ELTS( 1 ); 00091 } 00092 00093 return (void *)ELTPTR; 00094 } 00095 #endif 00096 00097 static __inline void *TAG(emit_verts)( GLcontext *ctx, GLuint start, 00098 GLuint count, void *buf ) 00099 { 00100 return EMIT_VERTS(ctx, start, count, buf); 00101 } 00102 00103 /*********************************************************************** 00104 * Render non-indexed primitives. 00105 ***********************************************************************/ 00106 00107 static void TAG(render_points_verts)( GLcontext *ctx, 00108 GLuint start, 00109 GLuint count, 00110 GLuint flags ) 00111 { 00112 if (HAVE_POINTS) { 00113 LOCAL_VARS; 00114 int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS(); 00115 int currentsz; 00116 GLuint j, nr; 00117 00118 INIT( GL_POINTS ); 00119 00120 currentsz = GET_CURRENT_VB_MAX_VERTS(); 00121 if (currentsz < 8) 00122 currentsz = dmasz; 00123 00124 for (j = start; j < count; j += nr ) { 00125 nr = MIN2( currentsz, count - j ); 00126 TAG(emit_verts)( ctx, j, nr, ALLOC_VERTS(nr) ); 00127 currentsz = dmasz; 00128 } 00129 00130 } else { 00131 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__); 00132 return; 00133 } 00134 } 00135 00136 static void TAG(render_lines_verts)( GLcontext *ctx, 00137 GLuint start, 00138 GLuint count, 00139 GLuint flags ) 00140 { 00141 if (HAVE_LINES) { 00142 LOCAL_VARS; 00143 int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS(); 00144 int currentsz; 00145 GLuint j, nr; 00146 00147 INIT( GL_LINES ); 00148 00149 /* Emit whole number of lines in total and in each buffer: 00150 */ 00151 count -= (count-start) & 1; 00152 currentsz = GET_CURRENT_VB_MAX_VERTS(); 00153 currentsz -= currentsz & 1; 00154 dmasz -= dmasz & 1; 00155 00156 if (currentsz < 8) 00157 currentsz = dmasz; 00158 00159 for (j = start; j < count; j += nr ) { 00160 nr = MIN2( currentsz, count - j ); 00161 TAG(emit_verts)( ctx, j, nr, ALLOC_VERTS(nr) ); 00162 currentsz = dmasz; 00163 } 00164 00165 } else { 00166 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__); 00167 return; 00168 } 00169 } 00170 00171 00172 static void TAG(render_line_strip_verts)( GLcontext *ctx, 00173 GLuint start, 00174 GLuint count, 00175 GLuint flags ) 00176 { 00177 if (HAVE_LINE_STRIPS) { 00178 LOCAL_VARS; 00179 int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS(); 00180 int currentsz; 00181 GLuint j, nr; 00182 00183 INIT( GL_LINE_STRIP ); 00184 00185 currentsz = GET_CURRENT_VB_MAX_VERTS(); 00186 if (currentsz < 8) 00187 currentsz = dmasz; 00188 00189 for (j = start; j + 1 < count; j += nr - 1 ) { 00190 nr = MIN2( currentsz, count - j ); 00191 TAG(emit_verts)( ctx, j, nr, ALLOC_VERTS(nr) ); 00192 currentsz = dmasz; 00193 } 00194 00195 FLUSH(); 00196 00197 } else { 00198 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__); 00199 return; 00200 } 00201 } 00202 00203 00204 static void TAG(render_line_loop_verts)( GLcontext *ctx, 00205 GLuint start, 00206 GLuint count, 00207 GLuint flags ) 00208 { 00209 if (HAVE_LINE_STRIPS) { 00210 LOCAL_VARS; 00211 int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS(); 00212 int currentsz; 00213 GLuint j, nr; 00214 00215 INIT( GL_LINE_STRIP ); 00216 00217 if (flags & PRIM_BEGIN) 00218 j = start; 00219 else 00220 j = start + 1; 00221 00222 /* Ensure last vertex won't wrap buffers: 00223 */ 00224 currentsz = GET_CURRENT_VB_MAX_VERTS(); 00225 currentsz--; 00226 dmasz--; 00227 00228 if (currentsz < 8) { 00229 currentsz = dmasz; 00230 } 00231 00232 if (j + 1 < count) { 00233 for ( ; j + 1 < count; j += nr - 1 ) { 00234 nr = MIN2( currentsz, count - j ); 00235 00236 if (j + nr >= count && 00237 start < count - 1 && 00238 (flags & PRIM_END)) 00239 { 00240 void *tmp; 00241 tmp = ALLOC_VERTS(nr+1); 00242 tmp = TAG(emit_verts)( ctx, j, nr, tmp ); 00243 tmp = TAG(emit_verts)( ctx, start, 1, tmp ); 00244 } 00245 else { 00246 TAG(emit_verts)( ctx, j, nr, ALLOC_VERTS(nr) ); 00247 currentsz = dmasz; 00248 } 00249 } 00250 00251 } 00252 else if (start + 1 < count && (flags & PRIM_END)) { 00253 void *tmp; 00254 tmp = ALLOC_VERTS(2); 00255 tmp = TAG(emit_verts)( ctx, start+1, 1, tmp ); 00256 tmp = TAG(emit_verts)( ctx, start, 1, tmp ); 00257 } 00258 00259 FLUSH(); 00260 00261 } else { 00262 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__); 00263 return; 00264 } 00265 } 00266 00267 00268 static void TAG(render_triangles_verts)( GLcontext *ctx, 00269 GLuint start, 00270 GLuint count, 00271 GLuint flags ) 00272 { 00273 LOCAL_VARS; 00274 int dmasz = (GET_SUBSEQUENT_VB_MAX_VERTS()/3) * 3; 00275 int currentsz; 00276 GLuint j, nr; 00277 00278 INIT(GL_TRIANGLES); 00279 00280 currentsz = (GET_CURRENT_VB_MAX_VERTS()/3) * 3; 00281 00282 /* Emit whole number of tris in total. dmasz is already a multiple 00283 * of 3. 00284 */ 00285 count -= (count-start)%3; 00286 00287 if (currentsz < 8) 00288 currentsz = dmasz; 00289 00290 for (j = start; j < count; j += nr) { 00291 nr = MIN2( currentsz, count - j ); 00292 TAG(emit_verts)( ctx, j, nr, ALLOC_VERTS(nr) ); 00293 currentsz = dmasz; 00294 } 00295 } 00296 00297 00298 00299 static void TAG(render_tri_strip_verts)( GLcontext *ctx, 00300 GLuint start, 00301 GLuint count, 00302 GLuint flags ) 00303 { 00304 if (HAVE_TRI_STRIPS) { 00305 LOCAL_VARS; 00306 GLuint j, nr; 00307 int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS(); 00308 int currentsz; 00309 00310 INIT(GL_TRIANGLE_STRIP); 00311 00312 currentsz = GET_CURRENT_VB_MAX_VERTS(); 00313 00314 if (currentsz < 8) { 00315 currentsz = dmasz; 00316 } 00317 00318 /* From here on emit even numbers of tris when wrapping over buffers: 00319 */ 00320 dmasz -= (dmasz & 1); 00321 currentsz -= (currentsz & 1); 00322 00323 for (j = start ; j + 2 < count; j += nr - 2 ) { 00324 nr = MIN2( currentsz, count - j ); 00325 TAG(emit_verts)( ctx, j, nr, ALLOC_VERTS(nr) ); 00326 currentsz = dmasz; 00327 } 00328 00329 FLUSH(); 00330 00331 } else { 00332 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__); 00333 return; 00334 } 00335 } 00336 00337 static void TAG(render_tri_fan_verts)( GLcontext *ctx, 00338 GLuint start, 00339 GLuint count, 00340 GLuint flags ) 00341 { 00342 if (HAVE_TRI_FANS) { 00343 LOCAL_VARS; 00344 GLuint j, nr; 00345 int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS(); 00346 int currentsz; 00347 00348 INIT(GL_TRIANGLE_FAN); 00349 00350 currentsz = GET_CURRENT_VB_MAX_VERTS(); 00351 if (currentsz < 8) { 00352 currentsz = dmasz; 00353 } 00354 00355 for (j = start + 1 ; j + 1 < count; j += nr - 2 ) { 00356 void *tmp; 00357 nr = MIN2( currentsz, count - j + 1 ); 00358 tmp = ALLOC_VERTS( nr ); 00359 tmp = TAG(emit_verts)( ctx, start, 1, tmp ); 00360 tmp = TAG(emit_verts)( ctx, j, nr - 1, tmp ); 00361 currentsz = dmasz; 00362 } 00363 00364 FLUSH(); 00365 } 00366 else { 00367 /* Could write code to emit these as indexed vertices (for the 00368 * g400, for instance). 00369 */ 00370 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__); 00371 return; 00372 } 00373 } 00374 00375 00376 static void TAG(render_poly_verts)( GLcontext *ctx, 00377 GLuint start, 00378 GLuint count, 00379 GLuint flags ) 00380 { 00381 if (HAVE_POLYGONS) { 00382 LOCAL_VARS; 00383 GLuint j, nr; 00384 int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS(); 00385 int currentsz; 00386 00387 INIT(GL_POLYGON); 00388 00389 currentsz = GET_CURRENT_VB_MAX_VERTS(); 00390 if (currentsz < 8) { 00391 currentsz = dmasz; 00392 } 00393 00394 for (j = start + 1 ; j + 1 < count ; j += nr - 2 ) { 00395 void *tmp; 00396 nr = MIN2( currentsz, count - j + 1 ); 00397 tmp = ALLOC_VERTS( nr ); 00398 tmp = TAG(emit_verts)( ctx, start, 1, tmp ); 00399 tmp = TAG(emit_verts)( ctx, j, nr - 1, tmp ); 00400 currentsz = dmasz; 00401 } 00402 00403 FLUSH(); 00404 } 00405 else if (HAVE_TRI_FANS && ctx->Light.ShadeModel == GL_SMOOTH) { 00406 TAG(render_tri_fan_verts)( ctx, start, count, flags ); 00407 } else { 00408 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__); 00409 return; 00410 } 00411 } 00412 00413 static void TAG(render_quad_strip_verts)( GLcontext *ctx, 00414 GLuint start, 00415 GLuint count, 00416 GLuint flags ) 00417 { 00418 GLuint j, nr; 00419 00420 if (HAVE_QUAD_STRIPS) { 00421 LOCAL_VARS; 00422 GLuint j, nr; 00423 int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS(); 00424 int currentsz; 00425 00426 INIT(GL_QUAD_STRIP); 00427 00428 currentsz = GET_CURRENT_VB_MAX_VERTS(); 00429 if (currentsz < 8) { 00430 currentsz = dmasz; 00431 } 00432 00433 dmasz -= (dmasz & 2); 00434 currentsz -= (currentsz & 2); 00435 00436 for (j = start ; j + 3 < count; j += nr - 2 ) { 00437 nr = MIN2( currentsz, count - j ); 00438 TAG(emit_verts)( ctx, j, nr, ALLOC_VERTS(nr) ); 00439 currentsz = dmasz; 00440 } 00441 00442 FLUSH(); 00443 00444 } else if (HAVE_TRI_STRIPS && 00445 ctx->Light.ShadeModel == GL_FLAT && 00446 TNL_CONTEXT(ctx)->vb.ColorPtr[0]->stride) { 00447 if (HAVE_ELTS) { 00448 LOCAL_VARS; 00449 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS(); 00450 int currentsz; 00451 GLuint j, nr; 00452 00453 EMIT_INDEXED_VERTS( ctx, start, count ); 00454 00455 /* Simulate flat-shaded quadstrips using indexed vertices: 00456 */ 00457 ELT_INIT( GL_TRIANGLES ); 00458 00459 currentsz = GET_CURRENT_VB_MAX_ELTS(); 00460 00461 /* Emit whole number of quads in total, and in each buffer. 00462 */ 00463 dmasz -= dmasz & 1; 00464 count -= (count-start) & 1; 00465 currentsz -= currentsz & 1; 00466 00467 if (currentsz < 12) 00468 currentsz = dmasz; 00469 00470 currentsz = currentsz/6*2; 00471 dmasz = dmasz/6*2; 00472 00473 for (j = start; j + 3 < count; j += nr - 2 ) { 00474 nr = MIN2( currentsz, count - j ); 00475 if (nr >= 4) { 00476 GLint quads = (nr/2)-1; 00477 GLint i; 00478 ELTS_VARS( ALLOC_ELTS( quads*6 ) ); 00479 00480 for ( i = j-start ; i < j-start+quads*2 ; i+=2 ) { 00481 EMIT_TWO_ELTS( 0, (i+0), (i+1) ); 00482 EMIT_TWO_ELTS( 2, (i+2), (i+1) ); 00483 EMIT_TWO_ELTS( 4, (i+3), (i+2) ); 00484 INCR_ELTS( 6 ); 00485 } 00486 00487 FLUSH(); 00488 } 00489 currentsz = dmasz; 00490 } 00491 00492 RELEASE_ELT_VERTS(); 00493 FLUSH(); 00494 } 00495 else { 00496 /* Vertices won't fit in a single buffer or elts not 00497 * available - should never happen. 00498 */ 00499 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__); 00500 return; 00501 } 00502 } 00503 else if (HAVE_TRI_STRIPS) { 00504 LOCAL_VARS; 00505 int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS(); 00506 int currentsz; 00507 00508 /* Emit smooth-shaded quadstrips as tristrips: 00509 */ 00510 FLUSH(); 00511 INIT( GL_TRIANGLE_STRIP ); 00512 00513 /* Emit whole number of quads in total, and in each buffer. 00514 */ 00515 dmasz -= dmasz & 1; 00516 currentsz = GET_CURRENT_VB_MAX_VERTS(); 00517 currentsz -= currentsz & 1; 00518 count -= (count-start) & 1; 00519 00520 if (currentsz < 8) { 00521 currentsz = dmasz; 00522 } 00523 00524 for (j = start; j + 3 < count; j += nr - 2 ) { 00525 nr = MIN2( currentsz, count - j ); 00526 TAG(emit_verts)( ctx, j, nr, ALLOC_VERTS(nr) ); 00527 currentsz = dmasz; 00528 } 00529 00530 FLUSH(); 00531 00532 } else { 00533 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__); 00534 return; 00535 } 00536 } 00537 00538 00539 static void TAG(render_quads_verts)( GLcontext *ctx, 00540 GLuint start, 00541 GLuint count, 00542 GLuint flags ) 00543 { 00544 if (HAVE_QUADS) { 00545 LOCAL_VARS; 00546 int dmasz = (GET_SUBSEQUENT_VB_MAX_VERTS()/4) * 4; 00547 int currentsz; 00548 GLuint j, nr; 00549 00550 INIT(GL_QUADS); 00551 00552 /* Emit whole number of quads in total. dmasz is already a multiple 00553 * of 4. 00554 */ 00555 count -= (count-start)%4; 00556 00557 currentsz = (GET_CURRENT_VB_MAX_VERTS()/4) * 4; 00558 if (currentsz < 8) 00559 currentsz = dmasz; 00560 00561 for (j = start; j < count; j += nr) { 00562 nr = MIN2( currentsz, count - j ); 00563 TAG(emit_verts)( ctx, j, nr, ALLOC_VERTS(nr) ); 00564 currentsz = dmasz; 00565 } 00566 } 00567 else if (HAVE_ELTS) { 00568 /* Hardware doesn't have a quad primitive type -- try to 00569 * simulate it using indexed vertices and the triangle 00570 * primitive: 00571 */ 00572 LOCAL_VARS; 00573 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS(); 00574 int currentsz; 00575 GLuint j, nr; 00576 00577 EMIT_INDEXED_VERTS( ctx, start, count ); 00578 00579 FLUSH(); 00580 ELT_INIT( GL_TRIANGLES ); 00581 currentsz = GET_CURRENT_VB_MAX_ELTS(); 00582 00583 /* Emit whole number of quads in total, and in each buffer. 00584 */ 00585 dmasz -= dmasz & 3; 00586 count -= (count-start) & 3; 00587 currentsz -= currentsz & 3; 00588 00589 /* Adjust for rendering as triangles: 00590 */ 00591 currentsz = currentsz/6*4; 00592 dmasz = dmasz/6*4; 00593 00594 if (currentsz < 8) 00595 currentsz = dmasz; 00596 00597 for (j = start; j < count; j += nr ) { 00598 nr = MIN2( currentsz, count - j ); 00599 if (nr >= 4) { 00600 GLint quads = nr/4; 00601 GLint i; 00602 ELTS_VARS( ALLOC_ELTS( quads*6 ) ); 00603 00604 for ( i = j-start ; i < j-start+quads*4 ; i+=4 ) { 00605 EMIT_TWO_ELTS( 0, (i+0), (i+1) ); 00606 EMIT_TWO_ELTS( 2, (i+3), (i+1) ); 00607 EMIT_TWO_ELTS( 4, (i+2), (i+3) ); 00608 INCR_ELTS( 6 ); 00609 } 00610 00611 FLUSH(); 00612 } 00613 currentsz = dmasz; 00614 } 00615 00616 RELEASE_ELT_VERTS(); 00617 } 00618 else if (HAVE_TRIANGLES) { 00619 /* Hardware doesn't have a quad primitive type -- try to 00620 * simulate it using triangle primitive. This is a win for 00621 * gears, but is it useful in the broader world? 00622 */ 00623 LOCAL_VARS; 00624 GLuint j; 00625 00626 INIT(GL_TRIANGLES); 00627 00628 for (j = start; j < count-3; j += 4) { 00629 void *tmp = ALLOC_VERTS( 6 ); 00630 /* Send v0, v1, v3 00631 */ 00632 tmp = EMIT_VERTS(ctx, j, 2, tmp); 00633 tmp = EMIT_VERTS(ctx, j + 3, 1, tmp); 00634 /* Send v1, v2, v3 00635 */ 00636 tmp = EMIT_VERTS(ctx, j + 1, 3, tmp); 00637 } 00638 } 00639 else { 00640 /* Vertices won't fit in a single buffer, should never happen. 00641 */ 00642 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__); 00643 return; 00644 } 00645 } 00646 00647 static void TAG(render_noop)( GLcontext *ctx, 00648 GLuint start, 00649 GLuint count, 00650 GLuint flags ) 00651 { 00652 } 00653 00654 00655 00656 00657 static tnl_render_func TAG(render_tab_verts)[GL_POLYGON+2] = 00658 { 00659 TAG(render_points_verts), 00660 TAG(render_lines_verts), 00661 TAG(render_line_loop_verts), 00662 TAG(render_line_strip_verts), 00663 TAG(render_triangles_verts), 00664 TAG(render_tri_strip_verts), 00665 TAG(render_tri_fan_verts), 00666 TAG(render_quads_verts), 00667 TAG(render_quad_strip_verts), 00668 TAG(render_poly_verts), 00669 TAG(render_noop), 00670 }; 00671 00672 00673 /**************************************************************************** 00674 * Render elts using hardware indexed verts * 00675 ****************************************************************************/ 00676 00677 #if (HAVE_ELTS) 00678 static void TAG(render_points_elts)( GLcontext *ctx, 00679 GLuint start, 00680 GLuint count, 00681 GLuint flags ) 00682 { 00683 if (HAVE_POINTS) { 00684 LOCAL_VARS; 00685 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS(); 00686 int currentsz; 00687 GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts; 00688 GLuint j, nr; 00689 00690 ELT_INIT( GL_POINTS ); 00691 00692 currentsz = GET_CURRENT_VB_MAX_ELTS(); 00693 if (currentsz < 8) 00694 currentsz = dmasz; 00695 00696 for (j = start; j < count; j += nr ) { 00697 nr = MIN2( currentsz, count - j ); 00698 TAG(emit_elts)( ctx, elts+j, nr, ALLOC_ELTS(nr) ); 00699 FLUSH(); 00700 currentsz = dmasz; 00701 } 00702 } else { 00703 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__); 00704 return; 00705 } 00706 } 00707 00708 00709 00710 static void TAG(render_lines_elts)( GLcontext *ctx, 00711 GLuint start, 00712 GLuint count, 00713 GLuint flags ) 00714 { 00715 if (HAVE_LINES) { 00716 LOCAL_VARS; 00717 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS(); 00718 int currentsz; 00719 GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts; 00720 GLuint j, nr; 00721 00722 ELT_INIT( GL_LINES ); 00723 00724 /* Emit whole number of lines in total and in each buffer: 00725 */ 00726 count -= (count-start) & 1; 00727 currentsz -= currentsz & 1; 00728 dmasz -= dmasz & 1; 00729 00730 currentsz = GET_CURRENT_VB_MAX_ELTS(); 00731 if (currentsz < 8) 00732 currentsz = dmasz; 00733 00734 for (j = start; j < count; j += nr ) { 00735 nr = MIN2( currentsz, count - j ); 00736 TAG(emit_elts)( ctx, elts+j, nr, ALLOC_ELTS(nr) ); 00737 FLUSH(); 00738 currentsz = dmasz; 00739 } 00740 } else { 00741 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__); 00742 return; 00743 } 00744 } 00745 00746 00747 static void TAG(render_line_strip_elts)( GLcontext *ctx, 00748 GLuint start, 00749 GLuint count, 00750 GLuint flags ) 00751 { 00752 if (HAVE_LINE_STRIPS) { 00753 LOCAL_VARS; 00754 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS(); 00755 int currentsz; 00756 GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts; 00757 GLuint j, nr; 00758 00759 FLUSH(); /* always a new primitive */ 00760 ELT_INIT( GL_LINE_STRIP ); 00761 00762 currentsz = GET_CURRENT_VB_MAX_ELTS(); 00763 if (currentsz < 8) 00764 currentsz = dmasz; 00765 00766 for (j = start; j + 1 < count; j += nr - 1 ) { 00767 nr = MIN2( currentsz, count - j ); 00768 TAG(emit_elts)( ctx, elts+j, nr, ALLOC_ELTS(nr) ); 00769 FLUSH(); 00770 currentsz = dmasz; 00771 } 00772 } else { 00773 /* TODO: Try to emit as indexed lines. 00774 */ 00775 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__); 00776 return; 00777 } 00778 } 00779 00780 00781 static void TAG(render_line_loop_elts)( GLcontext *ctx, 00782 GLuint start, 00783 GLuint count, 00784 GLuint flags ) 00785 { 00786 if (HAVE_LINE_STRIPS) { 00787 LOCAL_VARS; 00788 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS(); 00789 int currentsz; 00790 GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts; 00791 GLuint j, nr; 00792 00793 FLUSH(); 00794 ELT_INIT( GL_LINE_STRIP ); 00795 00796 if (flags & PRIM_BEGIN) 00797 j = start; 00798 else 00799 j = start + 1; 00800 00801 currentsz = GET_CURRENT_VB_MAX_ELTS(); 00802 if (currentsz < 8) { 00803 currentsz = dmasz; 00804 } 00805 00806 /* Ensure last vertex doesn't wrap: 00807 */ 00808 currentsz--; 00809 dmasz--; 00810 00811 if (j + 1 < count) { 00812 for ( ; j + 1 < count; j += nr - 1 ) { 00813 nr = MIN2( currentsz, count - j ); 00814 00815 if (j + nr >= count && 00816 start < count - 1 && 00817 (flags & PRIM_END)) 00818 { 00819 void *tmp; 00820 tmp = ALLOC_ELTS(nr+1); 00821 tmp = TAG(emit_elts)( ctx, elts+j, nr, tmp ); 00822 tmp = TAG(emit_elts)( ctx, elts+start, 1, tmp ); 00823 } 00824 else { 00825 TAG(emit_elts)( ctx, elts+j, nr, ALLOC_ELTS(nr) ); 00826 currentsz = dmasz; 00827 } 00828 } 00829 00830 } 00831 else if (start + 1 < count && (flags & PRIM_END)) { 00832 void *tmp; 00833 tmp = ALLOC_ELTS(2); 00834 tmp = TAG(emit_elts)( ctx, elts+start+1, 1, tmp ); 00835 tmp = TAG(emit_elts)( ctx, elts+start, 1, tmp ); 00836 } 00837 00838 FLUSH(); 00839 } else { 00840 /* TODO: Try to emit as indexed lines */ 00841 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__); 00842 return; 00843 } 00844 } 00845 00846 00847 /* For verts, we still eliminate the copy from main memory to dma 00848 * buffers. For elts, this is probably no better (worse?) than the 00849 * standard path. 00850 */ 00851 static void TAG(render_triangles_elts)( GLcontext *ctx, 00852 GLuint start, 00853 GLuint count, 00854 GLuint flags ) 00855 { 00856 LOCAL_VARS; 00857 GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts; 00858 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS()/3*3; 00859 int currentsz; 00860 GLuint j, nr; 00861 00862 FLUSH(); 00863 ELT_INIT( GL_TRIANGLES ); 00864 00865 currentsz = GET_CURRENT_VB_MAX_ELTS(); 00866 00867 /* Emit whole number of tris in total. dmasz is already a multiple 00868 * of 3. 00869 */ 00870 count -= (count-start)%3; 00871 currentsz -= currentsz%3; 00872 if (currentsz < 8) 00873 currentsz = dmasz; 00874 00875 for (j = start; j < count; j += nr) { 00876 nr = MIN2( currentsz, count - j ); 00877 TAG(emit_elts)( ctx, elts+j, nr, ALLOC_ELTS(nr) ); 00878 FLUSH(); 00879 currentsz = dmasz; 00880 } 00881 } 00882 00883 00884 00885 static void TAG(render_tri_strip_elts)( GLcontext *ctx, 00886 GLuint start, 00887 GLuint count, 00888 GLuint flags ) 00889 { 00890 if (HAVE_TRI_STRIPS) { 00891 LOCAL_VARS; 00892 GLuint j, nr; 00893 GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts; 00894 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS(); 00895 int currentsz; 00896 00897 FLUSH(); 00898 ELT_INIT( GL_TRIANGLE_STRIP ); 00899 00900 currentsz = GET_CURRENT_VB_MAX_ELTS(); 00901 if (currentsz < 8) { 00902 currentsz = dmasz; 00903 } 00904 00905 /* Keep the same winding over multiple buffers: 00906 */ 00907 dmasz -= (dmasz & 1); 00908 currentsz -= (currentsz & 1); 00909 00910 for (j = start ; j + 2 < count; j += nr - 2 ) { 00911 nr = MIN2( currentsz, count - j ); 00912 TAG(emit_elts)( ctx, elts+j, nr, ALLOC_ELTS(nr) ); 00913 FLUSH(); 00914 currentsz = dmasz; 00915 } 00916 } else { 00917 /* TODO: try to emit as indexed triangles */ 00918 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__); 00919 return; 00920 } 00921 } 00922 00923 static void TAG(render_tri_fan_elts)( GLcontext *ctx, 00924 GLuint start, 00925 GLuint count, 00926 GLuint flags ) 00927 { 00928 if (HAVE_TRI_FANS) { 00929 LOCAL_VARS; 00930 GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts; 00931 GLuint j, nr; 00932 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS(); 00933 int currentsz; 00934 00935 FLUSH(); 00936 ELT_INIT( GL_TRIANGLE_FAN ); 00937 00938 currentsz = GET_CURRENT_VB_MAX_ELTS(); 00939 if (currentsz < 8) { 00940 currentsz = dmasz; 00941 } 00942 00943 for (j = start + 1 ; j + 1 < count; j += nr - 2 ) { 00944 void *tmp; 00945 nr = MIN2( currentsz, count - j + 1 ); 00946 tmp = ALLOC_ELTS( nr ); 00947 tmp = TAG(emit_elts)( ctx, elts+start, 1, tmp ); 00948 tmp = TAG(emit_elts)( ctx, elts+j, nr - 1, tmp ); 00949 FLUSH(); 00950 currentsz = dmasz; 00951 } 00952 } else { 00953 /* TODO: try to emit as indexed triangles */ 00954 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__); 00955 return; 00956 } 00957 } 00958 00959 00960 static void TAG(render_poly_elts)( GLcontext *ctx, 00961 GLuint start, 00962 GLuint count, 00963 GLuint flags ) 00964 { 00965 if (HAVE_POLYGONS) { 00966 LOCAL_VARS; 00967 GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts; 00968 GLuint j, nr; 00969 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS(); 00970 int currentsz; 00971 00972 FLUSH(); 00973 ELT_INIT( GL_POLYGON ); 00974 00975 currentsz = GET_CURRENT_VB_MAX_ELTS(); 00976 if (currentsz < 8) { 00977 currentsz = dmasz; 00978 } 00979 00980 for (j = start + 1 ; j + 1 < count; j += nr - 2 ) { 00981 void *tmp; 00982 nr = MIN2( currentsz, count - j + 1 ); 00983 tmp = ALLOC_ELTS( nr ); 00984 tmp = TAG(emit_elts)( ctx, elts+start, 1, tmp ); 00985 tmp = TAG(emit_elts)( ctx, elts+j, nr - 1, tmp ); 00986 FLUSH(); 00987 currentsz = dmasz; 00988 } 00989 } else if (HAVE_TRI_FANS && ctx->Light.ShadeModel == GL_SMOOTH) { 00990 TAG(render_tri_fan_verts)( ctx, start, count, flags ); 00991 } else { 00992 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__); 00993 return; 00994 } 00995 } 00996 00997 static void TAG(render_quad_strip_elts)( GLcontext *ctx, 00998 GLuint start, 00999 GLuint count, 01000 GLuint flags ) 01001 { 01002 if (HAVE_QUAD_STRIPS && 0) { 01003 } 01004 else if (HAVE_TRI_STRIPS) { 01005 LOCAL_VARS; 01006 GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts; 01007 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS(); 01008 int currentsz; 01009 GLuint j, nr; 01010 01011 FLUSH(); 01012 currentsz = GET_CURRENT_VB_MAX_ELTS(); 01013 01014 /* Emit whole number of quads in total, and in each buffer. 01015 */ 01016 dmasz -= dmasz & 1; 01017 count -= (count-start) & 1; 01018 currentsz -= currentsz & 1; 01019 01020 if (currentsz < 12) 01021 currentsz = dmasz; 01022 01023 if (ctx->Light.ShadeModel == GL_FLAT) { 01024 ELT_INIT( GL_TRIANGLES ); 01025 01026 currentsz = currentsz/6*2; 01027 dmasz = dmasz/6*2; 01028 01029 for (j = start; j + 3 < count; j += nr - 2 ) { 01030 nr = MIN2( currentsz, count - j ); 01031 01032 if (nr >= 4) 01033 { 01034 GLint i; 01035 GLint quads = (nr/2)-1; 01036 ELTS_VARS( ALLOC_ELTS( quads*6 ) ); 01037 01038 for ( i = j-start ; i < j-start+quads ; i++, elts += 2 ) { 01039 EMIT_TWO_ELTS( 0, elts[0], elts[1] ); 01040 EMIT_TWO_ELTS( 2, elts[2], elts[1] ); 01041 EMIT_TWO_ELTS( 4, elts[3], elts[2] ); 01042 INCR_ELTS( 6 ); 01043 } 01044 01045 FLUSH(); 01046 } 01047 01048 currentsz = dmasz; 01049 } 01050 } 01051 else { 01052 ELT_INIT( GL_TRIANGLE_STRIP ); 01053 01054 for (j = start; j + 3 < count; j += nr - 2 ) { 01055 nr = MIN2( currentsz, count - j ); 01056 TAG(emit_elts)( ctx, elts+j, nr, ALLOC_ELTS(nr) ); 01057 FLUSH(); 01058 currentsz = dmasz; 01059 } 01060 } 01061 } 01062 } 01063 01064 01065 static void TAG(render_quads_elts)( GLcontext *ctx, 01066 GLuint start, 01067 GLuint count, 01068 GLuint flags ) 01069 { 01070 if (HAVE_QUADS) { 01071 LOCAL_VARS; 01072 GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts; 01073 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS()/4*4; 01074 int currentsz; 01075 GLuint j, nr; 01076 01077 FLUSH(); 01078 ELT_INIT( GL_TRIANGLES ); 01079 01080 currentsz = GET_CURRENT_VB_MAX_ELTS()/4*4; 01081 01082 count -= (count-start)%4; 01083 01084 if (currentsz < 8) 01085 currentsz = dmasz; 01086 01087 for (j = start; j < count; j += nr) { 01088 nr = MIN2( currentsz, count - j ); 01089 TAG(emit_elts)( ctx, elts+j, nr, ALLOC_ELTS(nr) ); 01090 FLUSH(); 01091 currentsz = dmasz; 01092 } 01093 } else { 01094 LOCAL_VARS; 01095 GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts; 01096 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS(); 01097 int currentsz; 01098 GLuint j, nr; 01099 01100 ELT_INIT( GL_TRIANGLES ); 01101 currentsz = GET_CURRENT_VB_MAX_ELTS(); 01102 01103 /* Emit whole number of quads in total, and in each buffer. 01104 */ 01105 dmasz -= dmasz & 3; 01106 count -= (count-start) & 3; 01107 currentsz -= currentsz & 3; 01108 01109 /* Adjust for rendering as triangles: 01110 */ 01111 currentsz = currentsz/6*4; 01112 dmasz = dmasz/6*4; 01113 01114 if (currentsz < 8) 01115 currentsz = dmasz; 01116 01117 for (j = start; j + 3 < count; j += nr - 2 ) { 01118 nr = MIN2( currentsz, count - j ); 01119 01120 if (nr >= 4) 01121 { 01122 GLint quads = nr/4; 01123 GLint i; 01124 ELTS_VARS( ALLOC_ELTS( quads * 6 ) ); 01125 01126 for ( i = j-start ; i < j-start+quads ; i++, elts += 4 ) { 01127 EMIT_TWO_ELTS( 0, elts[0], elts[1] ); 01128 EMIT_TWO_ELTS( 2, elts[3], elts[1] ); 01129 EMIT_TWO_ELTS( 4, elts[2], elts[3] ); 01130 INCR_ELTS( 6 ); 01131 } 01132 01133 FLUSH(); 01134 } 01135 01136 currentsz = dmasz; 01137 } 01138 } 01139 } 01140 01141 01142 01143 static tnl_render_func TAG(render_tab_elts)[GL_POLYGON+2] = 01144 { 01145 TAG(render_points_elts), 01146 TAG(render_lines_elts), 01147 TAG(render_line_loop_elts), 01148 TAG(render_line_strip_elts), 01149 TAG(render_triangles_elts), 01150 TAG(render_tri_strip_elts), 01151 TAG(render_tri_fan_elts), 01152 TAG(render_quads_elts), 01153 TAG(render_quad_strip_elts), 01154 TAG(render_poly_elts), 01155 TAG(render_noop), 01156 }; 01157 01158 01159 01160 #endif 01161 01162 01163 01164 /* Pre-check the primitives in the VB to prevent the need for 01165 * fallbacks later on. 01166 */ 01167 static GLboolean TAG(validate_render)( GLcontext *ctx, 01168 struct vertex_buffer *VB ) 01169 { 01170 GLint i; 01171 01172 if (VB->ClipOrMask & ~CLIP_CULL_BIT) 01173 return GL_FALSE; 01174 01175 if (VB->Elts && !HAVE_ELTS) 01176 return GL_FALSE; 01177 01178 for (i = 0 ; i < VB->PrimitiveCount ; i++) { 01179 GLuint prim = VB->Primitive[i].mode; 01180 GLuint count = VB->Primitive[i].count; 01181 GLboolean ok = GL_FALSE; 01182 01183 if (!count) 01184 continue; 01185 01186 switch (prim & PRIM_MODE_MASK) { 01187 case GL_POINTS: 01188 ok = HAVE_POINTS; 01189 break; 01190 case GL_LINES: 01191 ok = HAVE_LINES && !ctx->Line.StippleFlag; 01192 break; 01193 case GL_LINE_STRIP: 01194 ok = HAVE_LINE_STRIPS && !ctx->Line.StippleFlag; 01195 break; 01196 case GL_LINE_LOOP: 01197 ok = HAVE_LINE_STRIPS && !ctx->Line.StippleFlag; 01198 break; 01199 case GL_TRIANGLES: 01200 ok = HAVE_TRIANGLES; 01201 break; 01202 case GL_TRIANGLE_STRIP: 01203 ok = HAVE_TRI_STRIPS; 01204 break; 01205 case GL_TRIANGLE_FAN: 01206 ok = HAVE_TRI_FANS; 01207 break; 01208 case GL_POLYGON: 01209 if (HAVE_POLYGONS) { 01210 ok = GL_TRUE; 01211 } 01212 else { 01213 ok = (HAVE_TRI_FANS && ctx->Light.ShadeModel == GL_SMOOTH); 01214 } 01215 break; 01216 case GL_QUAD_STRIP: 01217 if (VB->Elts) { 01218 ok = HAVE_TRI_STRIPS; 01219 } 01220 else if (HAVE_QUAD_STRIPS) { 01221 ok = GL_TRUE; 01222 } else if (HAVE_TRI_STRIPS && 01223 ctx->Light.ShadeModel == GL_FLAT && 01224 VB->ColorPtr[0]->stride != 0) { 01225 if (HAVE_ELTS) { 01226 ok = (GLint) count < GET_SUBSEQUENT_VB_MAX_ELTS(); 01227 } 01228 else { 01229 ok = GL_FALSE; 01230 } 01231 } 01232 else 01233 ok = HAVE_TRI_STRIPS; 01234 break; 01235 case GL_QUADS: 01236 if (HAVE_QUADS) { 01237 ok = GL_TRUE; 01238 } else if (HAVE_ELTS) { 01239 ok = (GLint) count < GET_SUBSEQUENT_VB_MAX_ELTS(); 01240 } 01241 else { 01242 ok = HAVE_TRIANGLES; /* flatshading is ok. */ 01243 } 01244 break; 01245 default: 01246 break; 01247 } 01248 01249 if (!ok) { 01250 /* fprintf(stderr, "not ok %s\n", _mesa_lookup_enum_by_nr(prim & PRIM_MODE_MASK)); */ 01251 return GL_FALSE; 01252 } 01253 } 01254 01255 return GL_TRUE; 01256 } 01257 Generated on Sun May 27 2012 04:20:47 for ReactOS by
1.7.6.1
|