Merge branch '7.8'
[mesa.git] / src / mesa / drivers / dri / mach64 / mach64_context.c
1 /* -*- mode: c; c-basic-offset: 3 -*- */
2 /*
3 * Copyright 2000 Gareth Hughes
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * GARETH HUGHES BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /*
26 * Authors:
27 * Gareth Hughes <gareth@valinux.com>
28 * Leif Delgass <ldelgass@retinalburn.net>
29 * Jos�Fonseca <j_r_fonseca@yahoo.co.uk>
30 */
31
32 #include "main/glheader.h"
33 #include "main/context.h"
34 #include "main/extensions.h"
35 #include "main/simple_list.h"
36 #include "main/imports.h"
37
38 #include "swrast/swrast.h"
39 #include "swrast_setup/swrast_setup.h"
40 #include "vbo/vbo.h"
41
42 #include "tnl/tnl.h"
43 #include "tnl/t_pipeline.h"
44
45 #include "drivers/common/driverfuncs.h"
46
47 #include "mach64_context.h"
48 #include "mach64_ioctl.h"
49 #include "mach64_dd.h"
50 #include "mach64_span.h"
51 #include "mach64_state.h"
52 #include "mach64_tex.h"
53 #include "mach64_tris.h"
54 #include "mach64_vb.h"
55
56 #include "utils.h"
57 #include "vblank.h"
58
59 #ifndef MACH64_DEBUG
60 int MACH64_DEBUG = (0);
61 #endif
62
63 static const struct dri_debug_control debug_control[] =
64 {
65 { "sync", DEBUG_ALWAYS_SYNC },
66 { "api", DEBUG_VERBOSE_API },
67 { "msg", DEBUG_VERBOSE_MSG },
68 { "lru", DEBUG_VERBOSE_LRU },
69 { "dri", DEBUG_VERBOSE_DRI },
70 { "ioctl", DEBUG_VERBOSE_IOCTL },
71 { "prims", DEBUG_VERBOSE_PRIMS },
72 { "count", DEBUG_VERBOSE_COUNT },
73 { "nowait", DEBUG_NOWAIT },
74 { "fall", DEBUG_VERBOSE_FALLBACK },
75 { NULL, 0 }
76 };
77
78 static const struct dri_extension card_extensions[] =
79 {
80 { "GL_ARB_multitexture", NULL },
81 { "GL_EXT_texture_edge_clamp", NULL },
82 { "GL_MESA_ycbcr_texture", NULL },
83 { "GL_SGIS_generate_mipmap", NULL },
84 { NULL, NULL }
85 };
86
87
88 /* Create the device specific context.
89 */
90 GLboolean mach64CreateContext( const __GLcontextModes *glVisual,
91 __DRIcontext *driContextPriv,
92 void *sharedContextPrivate )
93 {
94 GLcontext *ctx, *shareCtx;
95 __DRIscreen *driScreen = driContextPriv->driScreenPriv;
96 struct dd_function_table functions;
97 mach64ContextPtr mmesa;
98 mach64ScreenPtr mach64Screen;
99 int i, heap;
100 GLuint *c_textureSwapsPtr = NULL;
101
102 #if DO_DEBUG
103 MACH64_DEBUG = driParseDebugString(getenv("MACH64_DEBUG"), debug_control);
104 #endif
105
106 /* Allocate the mach64 context */
107 mmesa = (mach64ContextPtr) CALLOC( sizeof(*mmesa) );
108 if ( !mmesa )
109 return GL_FALSE;
110
111 /* Init default driver functions then plug in our Mach64-specific functions
112 * (the texture functions are especially important)
113 */
114 _mesa_init_driver_functions( &functions );
115 mach64InitDriverFuncs( &functions );
116 mach64InitIoctlFuncs( &functions );
117 mach64InitTextureFuncs( &functions );
118
119 /* Allocate the Mesa context */
120 if (sharedContextPrivate)
121 shareCtx = ((mach64ContextPtr) sharedContextPrivate)->glCtx;
122 else
123 shareCtx = NULL;
124 mmesa->glCtx = _mesa_create_context(glVisual, shareCtx,
125 &functions, (void *)mmesa);
126 if (!mmesa->glCtx) {
127 FREE(mmesa);
128 return GL_FALSE;
129 }
130 driContextPriv->driverPrivate = mmesa;
131 ctx = mmesa->glCtx;
132
133 mmesa->driContext = driContextPriv;
134 mmesa->driScreen = driScreen;
135 mmesa->driDrawable = NULL;
136 mmesa->hHWContext = driContextPriv->hHWContext;
137 mmesa->driHwLock = &driScreen->pSAREA->lock;
138 mmesa->driFd = driScreen->fd;
139
140 mach64Screen = mmesa->mach64Screen = (mach64ScreenPtr)driScreen->private;
141
142 /* Parse configuration files */
143 driParseConfigFiles (&mmesa->optionCache, &mach64Screen->optionCache,
144 mach64Screen->driScreen->myNum, "mach64");
145
146 mmesa->sarea = (drm_mach64_sarea_t *)((char *)driScreen->pSAREA +
147 sizeof(drm_sarea_t));
148
149 mmesa->CurrentTexObj[0] = NULL;
150 mmesa->CurrentTexObj[1] = NULL;
151
152 (void) memset( mmesa->texture_heaps, 0, sizeof( mmesa->texture_heaps ) );
153 make_empty_list( &mmesa->swapped );
154
155 mmesa->firstTexHeap = mach64Screen->firstTexHeap;
156 mmesa->lastTexHeap = mach64Screen->firstTexHeap + mach64Screen->numTexHeaps;
157
158 for ( i = mmesa->firstTexHeap ; i < mmesa->lastTexHeap ; i++ ) {
159 mmesa->texture_heaps[i] = driCreateTextureHeap( i, mmesa,
160 mach64Screen->texSize[i],
161 6, /* align to 64-byte boundary, use 12 for page-size boundary */
162 MACH64_NR_TEX_REGIONS,
163 (drmTextureRegionPtr)mmesa->sarea->tex_list[i],
164 &mmesa->sarea->tex_age[i],
165 &mmesa->swapped,
166 sizeof( mach64TexObj ),
167 (destroy_texture_object_t *) mach64DestroyTexObj );
168
169 #if ENABLE_PERF_BOXES
170 c_textureSwapsPtr = & mmesa->c_textureSwaps;
171 #endif
172 driSetTextureSwapCounterLocation( mmesa->texture_heaps[i],
173 c_textureSwapsPtr );
174 }
175
176 mmesa->RenderIndex = -1; /* Impossible value */
177 mmesa->vert_buf = NULL;
178 mmesa->num_verts = 0;
179 mmesa->new_state = MACH64_NEW_ALL;
180 mmesa->dirty = MACH64_UPLOAD_ALL;
181
182 /* Set the maximum texture size small enough that we can
183 * guarentee that both texture units can bind a maximal texture
184 * and have them both in memory (on-card or AGP) at once.
185 * Test for 2 textures * bytes/texel * size * size. There's no
186 * need to account for mipmaps since we only upload one level.
187 */
188
189 ctx->Const.MaxTextureUnits = 2;
190 ctx->Const.MaxTextureImageUnits = 2;
191 ctx->Const.MaxTextureCoordUnits = 2;
192 ctx->Const.MaxDrawBuffers = 1;
193
194 heap = mach64Screen->IsPCI ? MACH64_CARD_HEAP : MACH64_AGP_HEAP;
195
196 driCalculateMaxTextureLevels( & mmesa->texture_heaps[heap],
197 1,
198 & ctx->Const,
199 mach64Screen->cpp,
200 10, /* max 2D texture size is 1024x1024 */
201 0, /* 3D textures unsupported. */
202 0, /* cube textures unsupported. */
203 0, /* texture rectangles unsupported. */
204 1, /* mipmapping unsupported. */
205 GL_TRUE, /* need to have both textures in
206 either local or AGP memory */
207 0 );
208
209 #if ENABLE_PERF_BOXES
210 mmesa->boxes = ( getenv( "LIBGL_PERFORMANCE_BOXES" ) != NULL );
211 #endif
212
213 /* Allocate the vertex buffer
214 */
215 mmesa->vert_buf = _mesa_align_malloc(MACH64_BUFFER_SIZE, 32);
216 if ( !mmesa->vert_buf )
217 return GL_FALSE;
218 mmesa->vert_used = 0;
219 mmesa->vert_total = MACH64_BUFFER_SIZE;
220
221 /* Initialize the software rasterizer and helper modules.
222 */
223 _swrast_CreateContext( ctx );
224 _vbo_CreateContext( ctx );
225 _tnl_CreateContext( ctx );
226 _swsetup_CreateContext( ctx );
227
228 /* Install the customized pipeline:
229 */
230 /* _tnl_destroy_pipeline( ctx ); */
231 /* _tnl_install_pipeline( ctx, mach64_pipeline ); */
232
233 /* Configure swrast and T&L to match hardware characteristics:
234 */
235 _swrast_allow_pixel_fog( ctx, GL_FALSE );
236 _swrast_allow_vertex_fog( ctx, GL_TRUE );
237 _tnl_allow_pixel_fog( ctx, GL_FALSE );
238 _tnl_allow_vertex_fog( ctx, GL_TRUE );
239
240 driInitExtensions( ctx, card_extensions, GL_TRUE );
241
242 mach64InitVB( ctx );
243 mach64InitTriFuncs( ctx );
244 mach64DDInitStateFuncs( ctx );
245 mach64DDInitSpanFuncs( ctx );
246 mach64DDInitState( mmesa );
247
248 mmesa->do_irqs = (mmesa->mach64Screen->irq && !getenv("MACH64_NO_IRQS"));
249
250 driContextPriv->driverPrivate = (void *)mmesa;
251
252 if (driQueryOptionb(&mmesa->optionCache, "no_rast")) {
253 fprintf(stderr, "disabling 3D acceleration\n");
254 FALLBACK(mmesa, MACH64_FALLBACK_DISABLE, 1);
255 }
256
257 return GL_TRUE;
258 }
259
260 /* Destroy the device specific context.
261 */
262 void mach64DestroyContext( __DRIcontext *driContextPriv )
263 {
264 mach64ContextPtr mmesa = (mach64ContextPtr) driContextPriv->driverPrivate;
265
266 assert(mmesa); /* should never be null */
267 if ( mmesa ) {
268 GLboolean release_texture_heaps;
269
270 release_texture_heaps = (mmesa->glCtx->Shared->RefCount == 1);
271
272 _swsetup_DestroyContext( mmesa->glCtx );
273 _tnl_DestroyContext( mmesa->glCtx );
274 _vbo_DestroyContext( mmesa->glCtx );
275 _swrast_DestroyContext( mmesa->glCtx );
276
277 if (release_texture_heaps) {
278 /* This share group is about to go away, free our private
279 * texture object data.
280 */
281 int i;
282
283 for ( i = mmesa->firstTexHeap ; i < mmesa->lastTexHeap ; i++ ) {
284 driDestroyTextureHeap( mmesa->texture_heaps[i] );
285 mmesa->texture_heaps[i] = NULL;
286 }
287
288 assert( is_empty_list( & mmesa->swapped ) );
289 }
290
291 mach64FreeVB( mmesa->glCtx );
292
293 /* Free the vertex buffer */
294 if ( mmesa->vert_buf )
295 _mesa_align_free( mmesa->vert_buf );
296
297 /* free the Mesa context */
298 mmesa->glCtx->DriverCtx = NULL;
299 _mesa_destroy_context(mmesa->glCtx);
300
301 FREE( mmesa );
302 }
303 }
304
305 /* Force the context `c' to be the current context and associate with it
306 * buffer `b'.
307 */
308 GLboolean
309 mach64MakeCurrent( __DRIcontext *driContextPriv,
310 __DRIdrawable *driDrawPriv,
311 __DRIdrawable *driReadPriv )
312 {
313 if ( driContextPriv ) {
314 GET_CURRENT_CONTEXT(ctx);
315 mach64ContextPtr oldMach64Ctx = ctx ? MACH64_CONTEXT(ctx) : NULL;
316 mach64ContextPtr newMach64Ctx = (mach64ContextPtr) driContextPriv->driverPrivate;
317
318 if ( newMach64Ctx != oldMach64Ctx ) {
319 newMach64Ctx->new_state |= MACH64_NEW_CONTEXT;
320 newMach64Ctx->dirty = MACH64_UPLOAD_ALL;
321 }
322
323
324 if ( newMach64Ctx->driDrawable != driDrawPriv ) {
325 if (driDrawPriv->swap_interval == (unsigned)-1) {
326 driDrawPriv->vblFlags = (newMach64Ctx->do_irqs)
327 ? driGetDefaultVBlankFlags(&newMach64Ctx->optionCache)
328 : VBLANK_FLAG_NO_IRQ;
329
330 driDrawableInitVBlank( driDrawPriv );
331 }
332
333 newMach64Ctx->driDrawable = driDrawPriv;
334 mach64CalcViewport( newMach64Ctx->glCtx );
335 }
336
337 _mesa_make_current( newMach64Ctx->glCtx,
338 (GLframebuffer *) driDrawPriv->driverPrivate,
339 (GLframebuffer *) driReadPriv->driverPrivate );
340
341
342 newMach64Ctx->new_state |= MACH64_NEW_CLIP;
343 } else {
344 _mesa_make_current( NULL, NULL, NULL );
345 }
346
347 return GL_TRUE;
348 }
349
350
351 /* Force the context `c' to be unbound from its buffer.
352 */
353 GLboolean
354 mach64UnbindContext( __DRIcontext *driContextPriv )
355 {
356 return GL_TRUE;
357 }