Merge branch 'master' of git+ssh://keithw@git.freedesktop.org/git/mesa/mesa into...
[mesa.git] / src / mesa / drivers / dri / r300 / radeon_context.c
1 /*
2 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
3
4 The Weather Channel (TM) funded Tungsten Graphics to develop the
5 initial release of the Radeon 8500 driver under the XFree86 license.
6 This notice must be preserved.
7
8 Permission is hereby granted, free of charge, to any person obtaining
9 a copy of this software and associated documentation files (the
10 "Software"), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sublicense, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
15
16 The above copyright notice and this permission notice (including the
17 next paragraph) shall be included in all copies or substantial
18 portions of the Software.
19
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
24 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
28 **************************************************************************/
29
30 /**
31 * \file radeon_context.c
32 * Common context initialization.
33 *
34 * \author Keith Whitwell <keith@tungstengraphics.com>
35 */
36
37 #include <dlfcn.h>
38
39 #include "glheader.h"
40 #include "imports.h"
41 #include "context.h"
42 #include "state.h"
43 #include "matrix.h"
44 #include "framebuffer.h"
45
46 #include "drivers/common/driverfuncs.h"
47 #include "swrast/swrast.h"
48
49 #include "radeon_screen.h"
50 #include "radeon_ioctl.h"
51 #include "radeon_macros.h"
52 #include "radeon_reg.h"
53
54 #include "r300_state.h"
55
56 #include "utils.h"
57 #include "vblank.h"
58 #include "xmlpool.h" /* for symbolic values of enum-type options */
59
60 #define DRIVER_DATE "20060815"
61
62
63 /* Return various strings for glGetString().
64 */
65 static const GLubyte *radeonGetString(GLcontext * ctx, GLenum name)
66 {
67 radeonContextPtr radeon = RADEON_CONTEXT(ctx);
68 static char buffer[128];
69
70 switch (name) {
71 case GL_VENDOR:
72 return (GLubyte *) "Tungsten Graphics, Inc.";
73
74 case GL_RENDERER:
75 {
76 unsigned offset;
77 GLuint agp_mode = (radeon->radeonScreen->card_type==RADEON_CARD_PCI) ? 0 :
78 radeon->radeonScreen->AGPMode;
79 const char* chipname;
80
81 if (IS_R300_CLASS(radeon->radeonScreen))
82 chipname = "R300";
83 else
84 chipname = "R200";
85
86 offset = driGetRendererString(buffer, chipname, DRIVER_DATE,
87 agp_mode);
88
89 sprintf(&buffer[offset], " %sTCL",
90 !(radeon->TclFallback & RADEON_TCL_FALLBACK_TCL_DISABLE)
91 ? "" : "NO-");
92
93 return (GLubyte *) buffer;
94 }
95
96 default:
97 return NULL;
98 }
99 }
100
101 /* Initialize the driver's misc functions.
102 */
103 static void radeonInitDriverFuncs(struct dd_function_table *functions)
104 {
105 functions->GetString = radeonGetString;
106 }
107
108
109 /**
110 * Create and initialize all common fields of the context,
111 * including the Mesa context itself.
112 */
113 GLboolean radeonInitContext(radeonContextPtr radeon,
114 struct dd_function_table* functions,
115 const __GLcontextModes * glVisual,
116 __DRIcontextPrivate * driContextPriv,
117 void *sharedContextPrivate)
118 {
119 __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
120 radeonScreenPtr screen = (radeonScreenPtr) (sPriv->private);
121 GLcontext* ctx;
122 GLcontext* shareCtx;
123 int fthrottle_mode;
124
125 /* Fill in additional standard functions. */
126 radeonInitDriverFuncs(functions);
127
128 /* Allocate and initialize the Mesa context */
129 if (sharedContextPrivate)
130 shareCtx = ((radeonContextPtr)sharedContextPrivate)->glCtx;
131 else
132 shareCtx = NULL;
133 radeon->glCtx = _mesa_create_context(glVisual, shareCtx,
134 functions, (void *)radeon);
135 if (!radeon->glCtx)
136 return GL_FALSE;
137
138 ctx = radeon->glCtx;
139 driContextPriv->driverPrivate = radeon;
140
141 /* DRI fields */
142 radeon->dri.context = driContextPriv;
143 radeon->dri.screen = sPriv;
144 radeon->dri.drawable = NULL;
145 radeon->dri.readable = NULL;
146 radeon->dri.hwContext = driContextPriv->hHWContext;
147 radeon->dri.hwLock = &sPriv->pSAREA->lock;
148 radeon->dri.fd = sPriv->fd;
149 radeon->dri.drmMinor = sPriv->drmMinor;
150
151 radeon->radeonScreen = screen;
152 radeon->sarea = (drm_radeon_sarea_t *) ((GLubyte *) sPriv->pSAREA +
153 screen->sarea_priv_offset);
154
155 /* Setup IRQs */
156 fthrottle_mode = driQueryOptioni(&radeon->optionCache, "fthrottle_mode");
157 radeon->iw.irq_seq = -1;
158 radeon->irqsEmitted = 0;
159 radeon->do_irqs = (fthrottle_mode == DRI_CONF_FTHROTTLE_IRQS &&
160 radeon->radeonScreen->irq);
161
162 radeon->do_usleeps = (fthrottle_mode == DRI_CONF_FTHROTTLE_USLEEPS);
163
164 if (!radeon->do_irqs)
165 fprintf(stderr,
166 "IRQ's not enabled, falling back to %s: %d %d\n",
167 radeon->do_usleeps ? "usleeps" : "busy waits",
168 fthrottle_mode, radeon->radeonScreen->irq);
169
170 radeon->vblank_flags = (radeon->radeonScreen->irq != 0)
171 ? driGetDefaultVBlankFlags(&radeon->optionCache) : VBLANK_FLAG_NO_IRQ;
172
173 (*dri_interface->getUST) (&radeon->swap_ust);
174
175 return GL_TRUE;
176 }
177
178
179 /**
180 * Cleanup common context fields.
181 * Called by r200DestroyContext/r300DestroyContext
182 */
183 void radeonCleanupContext(radeonContextPtr radeon)
184 {
185 /* _mesa_destroy_context() might result in calls to functions that
186 * depend on the DriverCtx, so don't set it to NULL before.
187 *
188 * radeon->glCtx->DriverCtx = NULL;
189 */
190
191 /* free the Mesa context */
192 _mesa_destroy_context(radeon->glCtx);
193
194 if (radeon->state.scissor.pClipRects) {
195 FREE(radeon->state.scissor.pClipRects);
196 radeon->state.scissor.pClipRects = 0;
197 }
198 }
199
200
201 /**
202 * Swap front and back buffer.
203 */
204 void radeonSwapBuffers(__DRIdrawablePrivate * dPriv)
205 {
206 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
207 radeonContextPtr radeon;
208 GLcontext *ctx;
209
210 radeon = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
211 ctx = radeon->glCtx;
212
213 if (ctx->Visual.doubleBufferMode) {
214 _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */
215 if (radeon->doPageFlip) {
216 radeonPageFlip(dPriv);
217 } else {
218 radeonCopyBuffer(dPriv, NULL);
219 }
220 }
221 } else {
222 /* XXX this shouldn't be an error but we can't handle it for now */
223 _mesa_problem(NULL, "%s: drawable has no context!",
224 __FUNCTION__);
225 }
226 }
227
228 void radeonCopySubBuffer(__DRIdrawablePrivate * dPriv,
229 int x, int y, int w, int h )
230 {
231 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
232 radeonContextPtr radeon;
233 GLcontext *ctx;
234
235 radeon = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
236 ctx = radeon->glCtx;
237
238 if (ctx->Visual.doubleBufferMode) {
239 drm_clip_rect_t rect;
240 rect.x1 = x + dPriv->x;
241 rect.y1 = (dPriv->h - y - h) + dPriv->y;
242 rect.x2 = rect.x1 + w;
243 rect.y2 = rect.y1 + h;
244 _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */
245 radeonCopyBuffer(dPriv, &rect);
246 }
247 } else {
248 /* XXX this shouldn't be an error but we can't handle it for now */
249 _mesa_problem(NULL, "%s: drawable has no context!",
250 __FUNCTION__);
251 }
252 }
253
254 /* Force the context `c' to be the current context and associate with it
255 * buffer `b'.
256 */
257 GLboolean radeonMakeCurrent(__DRIcontextPrivate * driContextPriv,
258 __DRIdrawablePrivate * driDrawPriv,
259 __DRIdrawablePrivate * driReadPriv)
260 {
261 if (driContextPriv) {
262 radeonContextPtr radeon =
263 (radeonContextPtr) driContextPriv->driverPrivate;
264
265 if (RADEON_DEBUG & DEBUG_DRI)
266 fprintf(stderr, "%s ctx %p\n", __FUNCTION__,
267 radeon->glCtx);
268
269 if (radeon->dri.drawable != driDrawPriv) {
270 driDrawableInitVBlank(driDrawPriv,
271 radeon->vblank_flags,
272 &radeon->vbl_seq);
273 }
274
275 if (radeon->dri.drawable != driDrawPriv ||
276 radeon->dri.readable != driReadPriv) {
277 radeon->dri.drawable = driDrawPriv;
278 radeon->dri.readable = driReadPriv;
279
280 r300UpdateWindow(radeon->glCtx);
281 r300UpdateViewportOffset(radeon->glCtx);
282 }
283
284 _mesa_make_current(radeon->glCtx,
285 (GLframebuffer *) driDrawPriv->
286 driverPrivate,
287 (GLframebuffer *) driReadPriv->
288 driverPrivate);
289
290 if (!radeon->glCtx->Viewport.Width) {
291 _mesa_set_viewport(radeon->glCtx, 0, 0,
292 driDrawPriv->w, driDrawPriv->h);
293 }
294
295 _mesa_update_state(radeon->glCtx);
296 } else {
297 if (RADEON_DEBUG & DEBUG_DRI)
298 fprintf(stderr, "%s ctx is null\n", __FUNCTION__);
299 _mesa_make_current(0, 0, 0);
300 }
301
302 if (RADEON_DEBUG & DEBUG_DRI)
303 fprintf(stderr, "End %s\n", __FUNCTION__);
304 return GL_TRUE;
305 }
306
307 /* Force the context `c' to be unbound from its buffer.
308 */
309 GLboolean radeonUnbindContext(__DRIcontextPrivate * driContextPriv)
310 {
311 radeonContextPtr radeon = (radeonContextPtr) driContextPriv->driverPrivate;
312
313 if (RADEON_DEBUG & DEBUG_DRI)
314 fprintf(stderr, "%s ctx %p\n", __FUNCTION__,
315 radeon->glCtx);
316
317 return GL_TRUE;
318 }
319