2 * \file radeon_subset_vtx.c
3 * \brief Vertex buffering.
5 * \author Keith Whitwell <keith@tungstengraphics.com>
9 * Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
10 * Tungsten Graphics Inc., Cedar Park, Texas.
12 * All Rights Reserved.
14 * Permission is hereby granted, free of charge, to any person obtaining a
15 * copy of this software and associated documentation files (the "Software"),
16 * to deal in the Software without restriction, including without limitation
17 * on the rights to use, copy, modify, merge, publish, distribute, sub
18 * license, and/or sell copies of the Software, and to permit persons to whom
19 * the Software is furnished to do so, subject to the following conditions:
21 * The above copyright notice and this permission notice (including the next
22 * paragraph) shall be included in all copies or substantial portions of the
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
28 * ATI, TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
29 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
30 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
31 * USE OR OTHER DEALINGS IN THE SOFTWARE.
41 /*#include "mmath.h" */
48 #include "radeon_context.h"
49 #include "radeon_state.h"
50 #include "radeon_ioctl.h"
51 #include "radeon_subset.h"
54 * \brief Union for vertex data.
57 float f
; /**< \brief floating point value */
58 int i
; /**< \brief integer point value */
63 * \brief Maximum number of dwords per vertex.
65 * Defined as 10 to hold: \code xyzw rgba st \endcode
67 #define MAX_VERTEX_DWORDS 10
71 * \brief Global vertex buffer data.
75 * \brief Notification mechanism.
77 * These are treated as a stack to allow us to do things like build quads in
78 * temporary storage and then emit them as triangles.
81 GLint vertspace
; /**< \brief free vertices count */
82 GLint initial_vertspace
; /**< \brief total vertices count */
83 GLint
*dmaptr
; /**< \brief */
84 void (*notify
)( void ); /**< \brief notification callback */
88 * \brief Storage for current vertex.
90 union vertex_dword vertex
[MAX_VERTEX_DWORDS
];
93 * \brief Temporary storage for quads, etc.
95 union vertex_dword vertex_store
[MAX_VERTEX_DWORDS
* 4];
100 * Pointers to either vertex or ctx->Current.Attrib, depending on whether
101 * color/texture participates in the current vertex.
104 GLfloat
*floatcolorptr
; /**< \brief color */
105 GLfloat
*texcoordptr
; /**< \brief texture */
109 * \brief Pointer to the GL context.
114 * \brief Active primitive.
116 * \note May differ from ctx->Driver.CurrentExecPrimitive.
119 GLenum prim
; /**< \brief primitive */
120 GLuint vertex_format
; /**< \brief vertex format */
121 GLint vertex_size
; /**< \brief vertex size */
122 GLboolean recheck
; /**< \brief set if it's needed to validate this information */
127 static void radeonFlushVertices( GLcontext
*, GLuint
);
131 * \brief Primitive information table.
133 static struct prims_t
{
134 int start
, /**< \brief vertex count for the starting primitive */
135 incr
, /**< \brief vertex increment for a further primitive */
136 hwprim
; /**< \brief hardware primitive */
138 { 1, 1, RADEON_CP_VC_CNTL_PRIM_TYPE_POINT
},
139 { 2, 2, RADEON_CP_VC_CNTL_PRIM_TYPE_LINE
},
140 { 2, 1, RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP
},
141 { 2, 1, RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP
},
142 { 3, 3, RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST
},
143 { 3, 1, RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP
},
144 { 3, 1, RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN
},
145 { 4, 4, RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST
},
146 { 4, 2, RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP
},
147 { 3, 1, RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN
},
152 * \brief Finish the primitive in the vertex buffer.
154 * \param rmesa Radeon context.
156 * Truncates any redundant vertices off the end of the buffer, emit the
157 * remaining vertices and advances the current DMA region.
159 static void finish_prim( radeonContextPtr rmesa
)
161 GLuint prim_end
= vb
.stack
[0].initial_vertspace
- vb
.stack
[0].vertspace
;
163 /* Too few vertices? (eg: 2 vertices for a triangles prim?)
165 if (prim_end
< prims
[vb
.prim
].start
)
168 /* Drop redundant vertices off end of primitive. (eg: 5 vertices
169 * for triangles prim?)
171 prim_end
-= (prim_end
- prims
[vb
.prim
].start
) % prims
[vb
.prim
].incr
;
173 radeonEmitVertexAOS( rmesa
, vb
.vertex_size
, GET_START(&rmesa
->dma
.current
) );
175 radeonEmitVbufPrim( rmesa
, vb
.vertex_format
,
176 prims
[vb
.prim
].hwprim
| rmesa
->tcl
.tcl_flag
,
179 rmesa
->dma
.current
.ptr
=
180 rmesa
->dma
.current
.start
+= prim_end
* vb
.vertex_size
* 4;
185 * \brief Copy a vertex from the current DMA region
187 * \param rmesa Radeon context.
188 * \param n vertex index relative to the current DMA region.
189 * \param dst destination pointer.
191 * Used internally by copy_dma_verts().
193 static void copy_vertex( radeonContextPtr rmesa
, GLuint n
, GLfloat
*dst
)
196 GLfloat
*src
= (GLfloat
*)(rmesa
->dma
.current
.address
+
197 rmesa
->dma
.current
.ptr
+
198 n
* vb
.vertex_size
* 4);
200 for (i
= 0 ; i
< vb
.vertex_size
; i
++)
206 * \brief Copy last vertices from the current DMA buffer to resume in a new buffer.
208 * \param rmesa Radeon context.
209 * \param tmp destination buffer.
211 * Takes from the current DMA buffer the last vertices necessary to resume in a
212 * new buffer, according to the current primitive. Uses internally
213 * copy_vertex() for the vertex copying.
216 static GLuint
copy_dma_verts( radeonContextPtr rmesa
,
217 GLfloat (*tmp
)[MAX_VERTEX_DWORDS
] )
220 GLuint nr
= vb
.stack
[0].initial_vertspace
- vb
.stack
[0].vertspace
;
228 for (i
= 0 ; i
< ovf
; i
++)
229 copy_vertex( rmesa
, nr
-ovf
+i
, tmp
[i
] );
234 copy_vertex( rmesa
, nr
-1, tmp
[0] );
237 case GL_TRIANGLE_FAN
:
242 copy_vertex( rmesa
, 0, tmp
[0] );
245 copy_vertex( rmesa
, 0, tmp
[0] );
246 copy_vertex( rmesa
, nr
-1, tmp
[1] );
251 for (i
= 0 ; i
< ovf
; i
++)
252 copy_vertex( rmesa
, nr
-ovf
+i
, tmp
[i
] );
256 for (i
= 0 ; i
< ovf
; i
++)
257 copy_vertex( rmesa
, nr
-ovf
+i
, tmp
[i
] );
259 case GL_TRIANGLE_STRIP
:
262 for (i
= 0 ; i
< ovf
; i
++)
263 copy_vertex( rmesa
, nr
-ovf
+i
, tmp
[i
] );
270 static void notify_wrap_buffer( void );
273 * \brief Resets the vertex buffer notification mechanism.
275 * Fills in vb_t::stack with the values from the current DMA region in
276 * radeon_dma::current and sets the notification callback to
277 * notify_wrap_buffer().
279 static void reset_notify( void )
281 radeonContextPtr rmesa
= RADEON_CONTEXT( vb
.context
);
283 vb
.stack
[0].dmaptr
= (int *)(rmesa
->dma
.current
.address
+
284 rmesa
->dma
.current
.ptr
);
285 vb
.stack
[0].vertspace
= ((rmesa
->dma
.current
.end
- rmesa
->dma
.current
.ptr
) /
286 (vb
.vertex_size
* 4));
287 vb
.stack
[0].vertspace
&= ~1; /* even numbers only -- avoid tristrip parity */
288 vb
.stack
[0].initial_vertspace
= vb
.stack
[0].vertspace
;
289 vb
.stack
[0].notify
= notify_wrap_buffer
;
293 * \brief Full buffer notification callback.
295 * Makes a copy of the necessary vertices of the current buffer via
296 * copy_dma_verts(), gets and resets new buffer via radeon and re-emits the
299 static void notify_wrap_buffer( void )
301 GLcontext
*ctx
= vb
.context
;
302 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
303 GLfloat tmp
[3][MAX_VERTEX_DWORDS
];
304 GLuint i
, nrverts
= 0;
306 /* Copy vertices out of dma:
308 nrverts
= copy_dma_verts( rmesa
, tmp
);
309 finish_prim( rmesa
);
313 radeonRefillCurrentDmaRegion( rmesa
);
315 /* Reset vertspace[0], dmaptr
319 /* Reemit saved vertices
321 for (i
= 0 ; i
< nrverts
; i
++) {
322 memcpy( vb
.stack
[0].dmaptr
, tmp
[i
], vb
.vertex_size
* 4 );
323 vb
.stack
[0].dmaptr
+= vb
.vertex_size
;
324 vb
.stack
[0].vertspace
--;
329 static void notify_noop( void )
331 vb
.stack
[0].dmaptr
= (int *)vb
.vertex
;
332 vb
.stack
[0].notify
= notify_noop
;
333 vb
.stack
[0].vertspace
= 1;
337 * \brief Pop the notification mechanism stack.
339 * Simply copy the second stack array element into the first.
341 * \sa vb_t::stack and push_notify().
343 static void pop_notify( void )
345 vb
.stack
[0] = vb
.stack
[1];
349 * \brief Push the notification mechanism stack.
351 * \param notify new notify callback for the stack head.
352 * \param space space available for vertices in \p store.
353 * \param store buffer where to store the vertices.
355 * Copy the second stack array element into the first and makes the stack head
356 * use the given resources.
358 * \sa vb_t::stack and pop_notify().
360 static void push_notify( void (*notify
)( void ), int space
,
361 union vertex_dword
*store
)
363 vb
.stack
[1] = vb
.stack
[0];
364 vb
.stack
[0].notify
= notify
;
365 vb
.stack
[0].initial_vertspace
= space
;
366 vb
.stack
[0].vertspace
= space
;
367 vb
.stack
[0].dmaptr
= (int *)store
;
372 * \brief Emit a stored vertex (in vb_t::vertex_store) to DMA.
374 * \param v vertex index.
376 * Adds the vertex into the current vertex buffer and calls the notification
377 * callback vb_t::notify().
379 static void emit_vertex( int v
)
381 int i
, *tmp
= (int *)vb
.vertex_store
+ v
* vb
.vertex_size
;
383 for (i
= 0 ; i
< vb
.vertex_size
; i
++)
384 *vb
.stack
[0].dmaptr
++ = *tmp
++;
386 if (--vb
.stack
[0].vertspace
== 0)
387 vb
.stack
[0].notify();
392 * \brief Emit a quad (in vb_t::vertex_store) to DMA as two triangles.
394 * \param v0 first vertex index.
395 * \param v1 second vertex index.
396 * \param v2 third vertex index.
397 * \param v3 fourth vertex index.
399 * Calls emit_vertex() to emit the triangles' vertices.
401 static void emit_quad( int v0
, int v1
, int v2
, int v3
)
403 emit_vertex( v0
); emit_vertex( v1
); emit_vertex( v3
);
404 emit_vertex( v1
); emit_vertex( v2
); emit_vertex( v3
);
408 * \brief Every fourth vertex in a quad primitive, this is called to emit it.
410 * Pops the notification stack, calls emit_quad() and pushes the notification
411 * stack again, with itself and the vb_t::vertex_store to process another four
414 static void notify_quad( void )
417 emit_quad( 0, 1, 2, 3 );
418 push_notify( notify_quad
, 4, vb
.vertex_store
);
421 static void notify_qstrip1( void );
424 * \brief After the 4th vertex, emit either a quad or a flipped quad each two
427 * Pops the notification stack, calls emit_quad() with the flipped vertices and
428 * pushes the notification stack again, with notify_qstrip1() and the
429 * vb_t::vertex_store to process another two vertices.
431 * \sa notify_qstrip1().
433 static void notify_qstrip0( void )
436 emit_quad( 0, 1, 3, 2 );
437 push_notify( notify_qstrip1
, 2, vb
.vertex_store
);
441 * \brief After the 4th vertex, emit either a quad or a flipped quad each two
444 * Pops the notification stack, calls emit_quad() with the straight vertices
445 * and pushes the notification stack again, with notify_qstrip0() and the
446 * vb_t::vertex_store to process another two vertices.
448 * \sa notify_qstrip0().
450 static void notify_qstrip1( void )
453 emit_quad( 2, 3, 1, 0 );
454 push_notify( notify_qstrip0
, 2, vb
.vertex_store
+ 2*vb
.vertex_size
);
458 * \brief Emit the saved vertex (but hang on to it for later).
460 * Continue processing this primitive as a linestrip.
462 * Pops the notification stack and calls emit_quad with the first vertex.
464 static void notify_lineloop0( void )
471 * \brief Invalidate the current vertex format.
473 * \param ctx GL context.
475 * Sets the vb_t::recheck flag.
477 void radeonVtxfmtInvalidate( GLcontext
*ctx
)
479 vb
.recheck
= GL_TRUE
;
484 * \brief Validate the vertex format from the context.
486 * \param ctx GL context.
488 * Signals a new primitive and determines the appropriate vertex format and
489 * size. Points vb_t::floatcolorptr and vb_t::texcoordptr to the current vertex
490 * and sets them to the current color and texture attributes.
492 * Clears the vb_t::recheck flag on exit.
494 static void radeonVtxfmtValidate( GLcontext
*ctx
)
496 radeonContextPtr rmesa
= RADEON_CONTEXT( ctx
);
497 GLuint ind
= (RADEON_CP_VC_FRMT_Z
|
498 RADEON_CP_VC_FRMT_FPCOLOR
|
499 RADEON_CP_VC_FRMT_FPALPHA
);
501 if (ctx
->Driver
.NeedFlush
)
502 ctx
->Driver
.FlushVertices( ctx
, ctx
->Driver
.NeedFlush
);
504 if (ctx
->Texture
.Unit
[0]._ReallyEnabled
)
505 ind
|= RADEON_CP_VC_FRMT_ST0
;
507 RADEON_NEWPRIM(rmesa
);
508 vb
.vertex_format
= ind
;
511 /* Would prefer to use ubyte floats in the vertex:
513 vb
.floatcolorptr
= &vb
.vertex
[vb
.vertex_size
].f
;
515 vb
.floatcolorptr
[0] = ctx
->Current
.Attrib
[VERT_ATTRIB_COLOR0
][0];
516 vb
.floatcolorptr
[1] = ctx
->Current
.Attrib
[VERT_ATTRIB_COLOR0
][1];
517 vb
.floatcolorptr
[2] = ctx
->Current
.Attrib
[VERT_ATTRIB_COLOR0
][2];
518 vb
.floatcolorptr
[3] = ctx
->Current
.Attrib
[VERT_ATTRIB_COLOR0
][3];
520 if (ind
& RADEON_CP_VC_FRMT_ST0
) {
521 vb
.texcoordptr
= &vb
.vertex
[vb
.vertex_size
].f
;
523 vb
.texcoordptr
[0] = ctx
->Current
.Attrib
[VERT_ATTRIB_TEX0
][0];
524 vb
.texcoordptr
[1] = ctx
->Current
.Attrib
[VERT_ATTRIB_TEX0
][1];
527 vb
.texcoordptr
= ctx
->Current
.Attrib
[VERT_ATTRIB_TEX0
];
529 vb
.recheck
= GL_FALSE
;
530 ctx
->Driver
.NeedFlush
= FLUSH_UPDATE_CURRENT
;
534 #define RESET_STIPPLE() do { \
535 RADEON_STATECHANGE( rmesa, lin ); \
536 radeonEmitState( rmesa ); \
539 #define AUTO_STIPPLE( mode ) do { \
540 RADEON_STATECHANGE( rmesa, lin ); \
542 rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] |= \
543 RADEON_LINE_PATTERN_AUTO_RESET; \
545 rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] &= \
546 ~RADEON_LINE_PATTERN_AUTO_RESET; \
547 radeonEmitState( rmesa ); \
552 * \brief Process glBegin().
554 * \param mode primitive.
556 static void radeon_Begin( GLenum mode
)
558 GLcontext
*ctx
= vb
.context
;
559 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
562 if (mode
> GL_POLYGON
) {
563 _mesa_error( ctx
, GL_INVALID_ENUM
, "glBegin" );
567 if (ctx
->Driver
.CurrentExecPrimitive
!= GL_POLYGON
+1) {
568 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glBegin" );
573 _mesa_update_state( ctx
);
575 if (rmesa
->NewGLState
)
576 radeonValidateState( ctx
);
579 radeonVtxfmtValidate( ctx
);
581 /* Do we need to grab a new DMA region for the vertices?
583 if (rmesa
->dma
.current
.ptr
+ 12*vb
.vertex_size
*4 > rmesa
->dma
.current
.end
) {
584 RADEON_NEWPRIM( rmesa
);
585 radeonRefillCurrentDmaRegion( rmesa
);
589 vb
.prim
= ctx
->Driver
.CurrentExecPrimitive
= mode
;
590 se_cntl
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] | RADEON_FLAT_SHADE_VTX_LAST
;
592 if (ctx
->Line
.StippleFlag
&&
594 mode
== GL_LINE_LOOP
||
595 mode
== GL_LINE_STRIP
))
600 if (ctx
->Line
.StippleFlag
)
601 AUTO_STIPPLE( GL_TRUE
);
604 vb
.prim
= GL_LINE_STRIP
;
605 push_notify( notify_lineloop0
, 1, vb
.vertex_store
);
608 vb
.prim
= GL_TRIANGLES
;
609 push_notify( notify_quad
, 4, vb
.vertex_store
);
612 if (ctx
->_TriangleCaps
& DD_FLATSHADE
) {
613 vb
.prim
= GL_TRIANGLES
;
614 push_notify( notify_qstrip0
, 4, vb
.vertex_store
);
618 if (ctx
->_TriangleCaps
& DD_FLATSHADE
)
619 se_cntl
&= ~RADEON_FLAT_SHADE_VTX_LAST
;
625 if (se_cntl
!= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
]) {
626 RADEON_STATECHANGE( rmesa
, set
);
627 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = se_cntl
;
633 * \brief Process glEnd().
636 static void radeon_End( void )
638 GLcontext
*ctx
= vb
.context
;
639 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
641 if (ctx
->Driver
.CurrentExecPrimitive
== GL_POLYGON
+1) {
642 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glEnd" );
646 /* Need to finish a line loop?
648 if (ctx
->Driver
.CurrentExecPrimitive
== GL_LINE_LOOP
)
651 /* Need to pop off quads/quadstrip/etc notification?
653 if (vb
.stack
[0].notify
!= notify_wrap_buffer
)
656 finish_prim( rmesa
);
658 if (ctx
->Driver
.CurrentExecPrimitive
== GL_LINES
&& ctx
->Line
.StippleFlag
)
659 AUTO_STIPPLE( GL_FALSE
);
661 ctx
->Driver
.CurrentExecPrimitive
= GL_POLYGON
+1;
668 * \brief Flush vertices.
670 * \param ctx GL context.
671 * \param flags flags.
673 * If FLUSH_UPDATE_CURRENT is et in \p flags then the current vertex attributes
674 * in the GL context is updated from vb_t::floatcolorptr and vb_t::texcoordptr.
676 static void radeonFlushVertices( GLcontext
*ctx
, GLuint flags
)
678 if (flags
& FLUSH_UPDATE_CURRENT
) {
679 ctx
->Current
.Attrib
[VERT_ATTRIB_COLOR0
][0] = vb
.floatcolorptr
[0];
680 ctx
->Current
.Attrib
[VERT_ATTRIB_COLOR0
][1] = vb
.floatcolorptr
[1];
681 ctx
->Current
.Attrib
[VERT_ATTRIB_COLOR0
][2] = vb
.floatcolorptr
[2];
682 ctx
->Current
.Attrib
[VERT_ATTRIB_COLOR0
][3] = vb
.floatcolorptr
[3];
684 if (vb
.vertex_format
& RADEON_CP_VC_FRMT_ST0
) {
685 ctx
->Current
.Attrib
[VERT_ATTRIB_TEX0
][0] = vb
.texcoordptr
[0];
686 ctx
->Current
.Attrib
[VERT_ATTRIB_TEX0
][1] = vb
.texcoordptr
[1];
687 ctx
->Current
.Attrib
[VERT_ATTRIB_TEX0
][2] = 0.0F
;
688 ctx
->Current
.Attrib
[VERT_ATTRIB_TEX0
][3] = 1.0F
;
692 ctx
->Driver
.NeedFlush
&= ~FLUSH_STORED_VERTICES
;
697 * \brief Set current vertex coordinates.
699 * \param x x vertex coordinate.
700 * \param y y vertex coordinate.
701 * \param z z vertex coordinate.
703 * Set the current vertex coordinates. If run out of space in this buffer call
704 * the notification callback.
706 static __inline__
void radeon_Vertex3f( GLfloat x
, GLfloat y
, GLfloat z
)
710 *vb
.stack
[0].dmaptr
++ = *(int *)&x
;
711 *vb
.stack
[0].dmaptr
++ = *(int *)&y
;
712 *vb
.stack
[0].dmaptr
++ = *(int *)&z
;
714 for (i
= 3; i
< vb
.vertex_size
; i
++)
715 *vb
.stack
[0].dmaptr
++ = vb
.vertex
[i
].i
;
717 if (--vb
.stack
[0].vertspace
== 0)
718 vb
.stack
[0].notify();
722 * \brief Set current vertex color.
724 * \param r red color component.
725 * \param g gree color component.
726 * \param b blue color component.
727 * \param a alpha color component.
729 * Sets the current vertex color via vb_t::floatcolorptr.
731 static __inline__
void radeon_Color4f( GLfloat r
, GLfloat g
,
732 GLfloat b
, GLfloat a
)
734 GLfloat
*dest
= vb
.floatcolorptr
;
742 * \brief Set current vertex texture coordinates.
744 * \param s texture coordinate.
745 * \param t texture coordinate.
747 * Sets the current vertex color via vb_t::texcoordptr.
749 static __inline__
void radeon_TexCoord2f( GLfloat s
, GLfloat t
)
751 GLfloat
*dest
= vb
.texcoordptr
;
757 * Calls radeon_Vertex3f(), which is expanded inline by the compiler to be
760 static void radeon_Vertex3fv( const GLfloat
*v
)
762 radeon_Vertex3f( v
[0], v
[1], v
[2] );
766 * Calls radeon_Vertex3f(), which is expanded inline by the compiler to be
769 static void radeon_Vertex2f( GLfloat x
, GLfloat y
)
771 radeon_Vertex3f( x
, y
, 0 );
775 * Calls radeon_Vertex3f(), which is expanded inline by the compiler to be
778 static void radeon_Vertex2fv( const GLfloat
*v
)
780 radeon_Vertex3f( v
[0], v
[1], 0 );
784 * Calls radeon_Vertex3f(), which is expanded inline by the compiler to be
787 static void radeon_Color4fv( const GLfloat
*v
)
789 radeon_Color4f( v
[0], v
[1], v
[2], v
[3] );
793 * Calls radeon_Color4f(), which is expanded inline by the compiler to be
796 static void radeon_Color3f( GLfloat r
, GLfloat g
, GLfloat b
)
798 radeon_Color4f( r
, g
, b
, 1.0 );
802 * Calls radeon_Color4f(), which is expanded inline by the compiler to be
805 static void radeon_Color3fv( const GLfloat
*v
)
807 radeon_Color4f( v
[0], v
[1], v
[2], 1.0 );
811 * Calls radeon_TexCoord2f(), which is expanded inline by the compiler to be
814 static void radeon_TexCoord2fv( const GLfloat
*v
)
816 radeon_TexCoord2f( v
[0], v
[1] );
823 void radeonVtxfmtUnbindContext( GLcontext
*ctx
)
830 void radeonVtxfmtMakeCurrent( GLcontext
*ctx
)
837 void radeonVtxfmtDestroy( GLcontext
*ctx
)
842 * \brief Software rendering fallback.
844 * \param ctx GL context.
845 * \param bit fallback bitmask.
846 * \param mode enable or disable.
848 * Does nothing except display a warning message if \p mode is set.
850 void radeonFallback( GLcontext
*ctx
, GLuint bit
, GLboolean mode
)
853 fprintf(stderr
, "Warning: hit nonexistant fallback path!\n");
857 * \brief Software TCL fallback.
859 * \param ctx GL context.
860 * \param bit fallback bitmask.
861 * \param mode enable or disable.
863 * Does nothing except display a warning message if \p mode is set.
865 void radeonTclFallback( GLcontext
*ctx
, GLuint bit
, GLboolean mode
)
868 fprintf(stderr
, "Warning: hit nonexistant fallback path!\n");
872 * \brief Called by radeonPointsBitmap() to disable TCL.
874 * \param rmesa Radeon context.
875 * \param flag whether to enable or disable TCL.
877 * Updates radeon_tcl_info::tcl_flag.
879 void radeonSubsetVtxEnableTCL( radeonContextPtr rmesa
, GLboolean flag
)
881 rmesa
->tcl
.tcl_flag
= flag
? RADEON_CP_VC_CNTL_TCL_ENABLE
: 0;
886 /**********************************************************************/
887 /** \name Noop mode for operation without focus */
888 /**********************************************************************/
893 * \brief Process glBegin().
895 * \param mode primitive.
897 static void radeon_noop_Begin(GLenum mode
)
899 GET_CURRENT_CONTEXT(ctx
);
901 if (mode
> GL_POLYGON
) {
902 _mesa_error( ctx
, GL_INVALID_ENUM
, "glBegin" );
906 if (ctx
->Driver
.CurrentExecPrimitive
!= GL_POLYGON
+1) {
907 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glBegin" );
911 ctx
->Driver
.CurrentExecPrimitive
= mode
;
915 * \brief Process glEnd().
917 static void radeon_noop_End(void)
919 GET_CURRENT_CONTEXT(ctx
);
920 ctx
->Driver
.CurrentExecPrimitive
= GL_POLYGON
+1;
925 * \brief Install the noop callbacks.
927 * \param ctx GL context.
929 * Installs the noop callbacks into the glapi table. These functions
930 * will not attempt to emit any DMA vertices, but will keep internal
931 * GL state updated. Borrows heavily from the select code.
933 static void radeon_noop_Install( GLcontext
*ctx
)
935 ctx
->Exec
->Begin
= radeon_noop_Begin
;
936 ctx
->Exec
->End
= radeon_noop_End
;
938 vb
.texcoordptr
= ctx
->Current
.Attrib
[VERT_ATTRIB_TEX0
];
939 vb
.floatcolorptr
= ctx
->Current
.Attrib
[VERT_ATTRIB_COLOR0
];
946 * \brief Setup the GL context callbacks.
948 * \param ctx GL context.
950 * Setups the GL context callbacks and links _glapi_table entries related to
951 * the glBegin()/glEnd() pairs to the functions in this module.
953 * Called by radeonCreateContext() and radeonRenderMode().
955 void radeonVtxfmtInit( GLcontext
*ctx
)
957 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
958 struct _glapi_table
*exec
= ctx
->Exec
;
960 exec
->Color3f
= radeon_Color3f
;
961 exec
->Color3fv
= radeon_Color3fv
;
962 exec
->Color4f
= radeon_Color4f
;
963 exec
->Color4fv
= radeon_Color4fv
;
964 exec
->TexCoord2f
= radeon_TexCoord2f
;
965 exec
->TexCoord2fv
= radeon_TexCoord2fv
;
966 exec
->Vertex2f
= radeon_Vertex2f
;
967 exec
->Vertex2fv
= radeon_Vertex2fv
;
968 exec
->Vertex3f
= radeon_Vertex3f
;
969 exec
->Vertex3fv
= radeon_Vertex3fv
;
970 exec
->Begin
= radeon_Begin
;
971 exec
->End
= radeon_End
;
975 ctx
->Driver
.FlushVertices
= radeonFlushVertices
;
976 ctx
->Driver
.CurrentExecPrimitive
= GL_POLYGON
+1;
978 if (rmesa
->radeonScreen
->buffers
) {
979 radeonVtxfmtValidate( ctx
);
983 radeon_noop_Install( ctx
);