add gamma driver - no kernel driver yet
[mesa.git] / src / mesa / drivers / dri / gamma / gamma_render.c
1 /*
2 * Copyright 2001 by Alan Hourihane.
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Alan Hourihane not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. Alan Hourihane makes no representations
11 * about the suitability of this software for any purpose. It is provided
12 * "as is" without express or implied warranty.
13 *
14 * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 *
22 * Authors: Alan Hourihane, <alanh@tungstengraphics.com>
23 *
24 * 3DLabs Gamma driver.
25 *
26 */
27
28 #include "glheader.h"
29 #include "context.h"
30 #include "macros.h"
31 #include "imports.h"
32 #include "mtypes.h"
33
34 #include "tnl/t_context.h"
35
36 #include "gamma_context.h"
37 #include "gamma_tris.h"
38 #include "gamma_vb.h"
39
40
41 /* !! Should template this eventually !! */
42
43 static void gamma_emit( GLcontext *ctx, GLuint start, GLuint end)
44 {
45 gammaContextPtr gmesa = GAMMA_CONTEXT(ctx);
46 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
47 GLfloat (*coord)[4];
48 GLuint coord_stride;
49 GLubyte (*col)[4];
50 GLuint col_stride;
51 int i;
52 GLuint tc0_stride = 0;
53 GLfloat (*tc0)[4] = 0;
54 GLuint tc0_size = 0;
55
56 if (VB->ColorPtr[0]->Type != GL_UNSIGNED_BYTE)
57 gamma_import_float_colors( ctx );
58
59 col = VB->ColorPtr[0]->Ptr;
60 col_stride = VB->ColorPtr[0]->StrideB;
61
62 if (ctx->Texture.Unit[0]._ReallyEnabled) {
63 tc0_stride = VB->TexCoordPtr[0]->stride;
64 tc0 = VB->TexCoordPtr[0]->data;
65 tc0_size = VB->TexCoordPtr[0]->size;
66 coord = VB->ClipPtr->data;
67 coord_stride = VB->ClipPtr->stride;
68 } else {
69 coord = VB->NdcPtr->data;
70 coord_stride = VB->NdcPtr->stride;
71 }
72
73 if (VB->importable_data) {
74 if (start) {
75 coord = (GLfloat (*)[4])((GLubyte *)coord + start * coord_stride);
76 STRIDE_4UB(col, start * col_stride);
77 if (ctx->Texture.Unit[0]._ReallyEnabled)
78 tc0 = (GLfloat (*)[4])((GLubyte *)tc0 + start * tc0_stride);
79 }
80
81 if (ctx->Texture.Unit[0]._ReallyEnabled && tc0_size == 4) {
82 for (i=start; i < end; i++) {
83 CHECK_DMA_BUFFER(gmesa, 9);
84 WRITEF(gmesa->buf, Tq4, tc0[0][3]);
85 WRITEF(gmesa->buf, Tr4, tc0[0][2]);
86 WRITEF(gmesa->buf, Tt4, tc0[0][0]);
87 WRITEF(gmesa->buf, Ts4, tc0[0][1]);
88 WRITE(gmesa->buf, PackedColor4, *(CARD32*)col[0]);
89 WRITEF(gmesa->buf, Vw, coord[0][3]);
90 WRITEF(gmesa->buf, Vz, coord[0][2]);
91 WRITEF(gmesa->buf, Vy, coord[0][1]);
92 WRITEF(gmesa->buf, Vx4, coord[0][0]);
93 STRIDE_4UB(col, col_stride);
94 tc0 = (GLfloat (*)[4])((GLubyte *)tc0 + tc0_stride);
95 coord = (GLfloat (*)[4])((GLubyte *)coord + coord_stride);
96 }
97 } else if (ctx->Texture.Unit[0]._ReallyEnabled && tc0_size == 2) {
98 for (i=start; i < end; i++) {
99 CHECK_DMA_BUFFER(gmesa, 7);
100 WRITEF(gmesa->buf, Tt2, tc0[0][0]);
101 WRITEF(gmesa->buf, Ts2, tc0[0][1]);
102 WRITE(gmesa->buf, PackedColor4, *(CARD32*)col[0]);
103 WRITEF(gmesa->buf, Vw, coord[0][3]);
104 WRITEF(gmesa->buf, Vz, coord[0][2]);
105 WRITEF(gmesa->buf, Vy, coord[0][1]);
106 WRITEF(gmesa->buf, Vx4, coord[0][0]);
107 STRIDE_4UB(col, col_stride);
108 tc0 = (GLfloat (*)[4])((GLubyte *)tc0 + tc0_stride);
109 coord = (GLfloat (*)[4])((GLubyte *)coord + coord_stride);
110 }
111 } else {
112 for (i=start; i < end; i++) {
113 CHECK_DMA_BUFFER(gmesa, 4);
114 WRITE(gmesa->buf, PackedColor4, *(CARD32*)col[0]);
115 WRITEF(gmesa->buf, Vz, coord[0][2]);
116 WRITEF(gmesa->buf, Vy, coord[0][1]);
117 WRITEF(gmesa->buf, Vx3, coord[0][0]);
118 STRIDE_4UB(col, col_stride);
119 coord = (GLfloat (*)[4])((GLubyte *)coord + coord_stride);
120 }
121 }
122 } else {
123 if (ctx->Texture.Unit[0]._ReallyEnabled && tc0_size == 4) {
124 for (i=start; i < end; i++) {
125 CHECK_DMA_BUFFER(gmesa, 9);
126 WRITEF(gmesa->buf, Tq4, tc0[i][3]);
127 WRITEF(gmesa->buf, Tr4, tc0[i][2]);
128 WRITEF(gmesa->buf, Tt4, tc0[i][0]);
129 WRITEF(gmesa->buf, Ts4, tc0[i][1]);
130 WRITE(gmesa->buf, PackedColor4, *(CARD32*)col[i]);
131 WRITEF(gmesa->buf, Vw, coord[i][3]);
132 WRITEF(gmesa->buf, Vz, coord[i][2]);
133 WRITEF(gmesa->buf, Vy, coord[i][1]);
134 WRITEF(gmesa->buf, Vx4, coord[i][0]);
135 }
136 } else if (ctx->Texture.Unit[0]._ReallyEnabled && tc0_size == 2) {
137 for (i=start; i < end; i++) {
138 CHECK_DMA_BUFFER(gmesa, 7);
139 WRITEF(gmesa->buf, Tt2, tc0[i][0]);
140 WRITEF(gmesa->buf, Ts2, tc0[i][1]);
141 WRITE(gmesa->buf, PackedColor4, *(CARD32*)col[i]);
142 WRITEF(gmesa->buf, Vw, coord[i][3]);
143 WRITEF(gmesa->buf, Vz, coord[i][2]);
144 WRITEF(gmesa->buf, Vy, coord[i][1]);
145 WRITEF(gmesa->buf, Vx4, coord[i][0]);
146 }
147 } else {
148 for (i=start; i < end; i++) {
149 CHECK_DMA_BUFFER(gmesa, 4);
150 WRITE(gmesa->buf, PackedColor4, *(CARD32*)col[i]);
151 WRITEF(gmesa->buf, Vz, coord[i][2]);
152 WRITEF(gmesa->buf, Vy, coord[i][1]);
153 WRITEF(gmesa->buf, Vx3, coord[i][0]);
154 }
155 }
156 }
157 }
158
159 #define HAVE_POINTS 1
160 #define HAVE_LINES 1
161 #define HAVE_LINE_STRIPS 1
162 #define HAVE_TRIANGLES 1
163 #define HAVE_TRI_STRIPS 1
164 #define HAVE_TRI_STRIP_1 0
165 #define HAVE_TRI_FANS 1
166 #define HAVE_QUADS 1
167 #define HAVE_QUAD_STRIPS 1
168 #define HAVE_POLYGONS 1
169
170 #define HAVE_ELTS 0
171
172 static void VERT_FALLBACK( GLcontext *ctx,
173 GLuint start,
174 GLuint count,
175 GLuint flags )
176 {
177 TNLcontext *tnl = TNL_CONTEXT(ctx);
178 tnl->Driver.Render.PrimitiveNotify( ctx, flags & PRIM_MODE_MASK );
179 tnl->Driver.Render.BuildVertices( ctx, start, count, ~0 );
180 tnl->Driver.Render.PrimTabVerts[flags&PRIM_MODE_MASK]( ctx, start, count, flags );
181 GAMMA_CONTEXT(ctx)->SetupNewInputs = VERT_BIT_CLIP;
182 }
183
184 static const GLuint hw_prim[GL_POLYGON+1] = {
185 B_PrimType_Points,
186 B_PrimType_Lines,
187 B_PrimType_LineLoop,
188 B_PrimType_LineStrip,
189 B_PrimType_Triangles,
190 B_PrimType_TriangleStrip,
191 B_PrimType_TriangleFan,
192 B_PrimType_Quads,
193 B_PrimType_QuadStrip,
194 B_PrimType_Polygon
195 };
196
197 static __inline void gammaStartPrimitive( gammaContextPtr gmesa, GLenum prim )
198 {
199 CHECK_DMA_BUFFER(gmesa, 1);
200 WRITE(gmesa->buf, Begin, gmesa->Begin | hw_prim[prim]);
201 }
202
203 static __inline void gammaEndPrimitive( gammaContextPtr gmesa )
204 {
205 GLcontext *ctx = gmesa->glCtx;
206
207 if ( ctx->Line.SmoothFlag ||
208 ctx->Polygon.SmoothFlag ||
209 ctx->Point.SmoothFlag ) {
210 CHECK_DMA_BUFFER(gmesa, 1);
211 WRITE(gmesa->buf, FlushSpan, 0);
212 }
213
214 CHECK_DMA_BUFFER(gmesa, 1);
215 WRITE(gmesa->buf, End, 0);
216 }
217
218 #define LOCAL_VARS gammaContextPtr gmesa = GAMMA_CONTEXT(ctx)
219 #define INIT( prim ) gammaStartPrimitive( gmesa, prim )
220 #define FINISH gammaEndPrimitive( gmesa )
221 #define NEW_PRIMITIVE() /* GAMMA_STATECHANGE( gmesa, 0 ) */
222 #define NEW_BUFFER() /* GAMMA_FIREVERTICES( gmesa ) */
223 #define GET_CURRENT_VB_MAX_VERTS() \
224 (gmesa->bufSize - gmesa->bufCount) / 2
225 #define GET_SUBSEQUENT_VB_MAX_VERTS() \
226 GAMMA_DMA_BUFFER_SIZE / 2
227 #define EMIT_VERTS( ctx, j, nr ) gamma_emit(ctx, j, (j)+(nr))
228
229 #define TAG(x) gamma_##x
230 #include "tnl_dd/t_dd_dmatmp.h"
231
232
233 /**********************************************************************/
234 /* Render pipeline stage */
235 /**********************************************************************/
236
237
238 static GLboolean gamma_run_render( GLcontext *ctx,
239 struct gl_pipeline_stage *stage )
240 {
241 gammaContextPtr gmesa = GAMMA_CONTEXT(ctx);
242 TNLcontext *tnl = TNL_CONTEXT(ctx);
243 struct vertex_buffer *VB = &tnl->vb;
244 GLuint i, length, flags = 0;
245 render_func *tab;
246
247 /* GH: THIS IS A HACK!!! */
248 if (VB->ClipOrMask || gmesa->RenderIndex != 0)
249 return GL_TRUE; /* don't handle clipping here */
250
251 /* We don't do elts */
252 if (VB->Elts)
253 return GL_TRUE;
254
255 tab = TAG(render_tab_verts);
256
257 tnl->Driver.Render.Start( ctx );
258
259 for (i = VB->FirstPrimitive ; !(flags & PRIM_LAST) ; i += length)
260 {
261 flags = VB->Primitive[i];
262 length = VB->PrimitiveLength[i];
263 if (length)
264 tab[flags & PRIM_MODE_MASK]( ctx, i, i + length, flags );
265 }
266
267 tnl->Driver.Render.Finish( ctx );
268
269 return GL_FALSE; /* finished the pipe */
270 }
271
272
273 static void gamma_check_render( GLcontext *ctx,
274 struct gl_pipeline_stage *stage )
275 {
276 GLuint inputs = VERT_BIT_CLIP | VERT_BIT_COLOR0;
277
278 if (ctx->RenderMode == GL_RENDER) {
279 if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)
280 inputs |= VERT_BIT_COLOR1;
281
282 if (ctx->Texture.Unit[0]._ReallyEnabled)
283 inputs |= VERT_BIT_TEX0;
284
285 if (ctx->Texture.Unit[1]._ReallyEnabled)
286 inputs |= VERT_BIT_TEX1;
287
288 if (ctx->Fog.Enabled)
289 inputs |= VERT_BIT_FOG;
290 }
291
292 stage->inputs = inputs;
293 }
294
295
296 static void dtr( struct gl_pipeline_stage *stage )
297 {
298 (void)stage;
299 }
300
301
302 const struct gl_pipeline_stage _gamma_render_stage =
303 {
304 "gamma render",
305 (_DD_NEW_SEPARATE_SPECULAR |
306 _NEW_TEXTURE|
307 _NEW_FOG|
308 _NEW_RENDERMODE), /* re-check (new inputs) */
309 0, /* re-run (always runs) */
310 GL_TRUE, /* active */
311 0, 0, /* inputs (set in check_render), outputs */
312 0, 0, /* changed_inputs, private */
313 dtr, /* destructor */
314 gamma_check_render, /* check - initially set to alloc data */
315 gamma_run_render /* run */
316 };