radeon/r200/r300: attempt to move lock to common code
[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 "main/glheader.h"
40 #include "main/imports.h"
41 #include "main/context.h"
42 #include "main/state.h"
43 #include "main/matrix.h"
44 #include "main/framebuffer.h"
45
46 #include "drivers/common/driverfuncs.h"
47 #include "swrast/swrast.h"
48
49 #include "radeon_buffer.h"
50 #include "radeon_screen.h"
51 #include "radeon_ioctl.h"
52 #include "radeon_macros.h"
53 #include "radeon_reg.h"
54
55 #include "radeon_state.h"
56 #include "r300_state.h"
57
58 #include "utils.h"
59 #include "vblank.h"
60 #include "xmlpool.h" /* for symbolic values of enum-type options */
61 #include "drirenderbuffer.h"
62
63 #define DRIVER_DATE "20060815"
64
65
66 /* Return various strings for glGetString().
67 */
68 static const GLubyte *radeonGetString(GLcontext * ctx, GLenum name)
69 {
70 radeonContextPtr radeon = RADEON_CONTEXT(ctx);
71 static char buffer[128];
72
73 switch (name) {
74 case GL_VENDOR:
75 if (IS_R300_CLASS(radeon->radeonScreen))
76 return (GLubyte *) "DRI R300 Project";
77 else
78 return (GLubyte *) "Tungsten Graphics, Inc.";
79
80 case GL_RENDERER:
81 {
82 unsigned offset;
83 GLuint agp_mode = (radeon->radeonScreen->card_type==RADEON_CARD_PCI) ? 0 :
84 radeon->radeonScreen->AGPMode;
85 const char* chipname;
86
87 if (IS_R300_CLASS(radeon->radeonScreen))
88 chipname = "R300";
89 else
90 chipname = "R200";
91
92 offset = driGetRendererString(buffer, chipname, DRIVER_DATE,
93 agp_mode);
94
95 if (IS_R300_CLASS(radeon->radeonScreen)) {
96 sprintf(&buffer[offset], " %sTCL",
97 (radeon->radeonScreen->chip_flags & RADEON_CHIPSET_TCL)
98 ? "" : "NO-");
99 } else {
100 sprintf(&buffer[offset], " %sTCL",
101 !(radeon->TclFallback & RADEON_TCL_FALLBACK_TCL_DISABLE)
102 ? "" : "NO-");
103 }
104
105 return (GLubyte *) buffer;
106 }
107
108 default:
109 return NULL;
110 }
111 }
112
113 /* Initialize the driver's misc functions.
114 */
115 static void radeonInitDriverFuncs(struct dd_function_table *functions)
116 {
117 functions->GetString = radeonGetString;
118 }
119
120
121 /**
122 * Create and initialize all common fields of the context,
123 * including the Mesa context itself.
124 */
125 GLboolean radeonInitContext(radeonContextPtr radeon,
126 struct dd_function_table* functions,
127 const __GLcontextModes * glVisual,
128 __DRIcontextPrivate * driContextPriv,
129 void *sharedContextPrivate)
130 {
131 __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
132 radeonScreenPtr screen = (radeonScreenPtr) (sPriv->private);
133 GLcontext* ctx;
134 GLcontext* shareCtx;
135 int fthrottle_mode;
136
137 /* Fill in additional standard functions. */
138 radeonInitDriverFuncs(functions);
139
140 radeon->radeonScreen = screen;
141 /* Allocate and initialize the Mesa context */
142 if (sharedContextPrivate)
143 shareCtx = ((radeonContextPtr)sharedContextPrivate)->glCtx;
144 else
145 shareCtx = NULL;
146 radeon->glCtx = _mesa_create_context(glVisual, shareCtx,
147 functions, (void *)radeon);
148 if (!radeon->glCtx)
149 return GL_FALSE;
150
151 ctx = radeon->glCtx;
152 driContextPriv->driverPrivate = radeon;
153
154 /* DRI fields */
155 radeon->dri.context = driContextPriv;
156 radeon->dri.screen = sPriv;
157 radeon->dri.drawable = NULL;
158 radeon->dri.readable = NULL;
159 radeon->dri.hwContext = driContextPriv->hHWContext;
160 radeon->dri.hwLock = &sPriv->pSAREA->lock;
161 radeon->dri.fd = sPriv->fd;
162 radeon->dri.drmMinor = sPriv->drm_version.minor;
163
164 radeon->sarea = (drm_radeon_sarea_t *) ((GLubyte *) sPriv->pSAREA +
165 screen->sarea_priv_offset);
166
167 /* Setup IRQs */
168 fthrottle_mode = driQueryOptioni(&radeon->optionCache, "fthrottle_mode");
169 radeon->iw.irq_seq = -1;
170 radeon->irqsEmitted = 0;
171 radeon->do_irqs = (fthrottle_mode == DRI_CONF_FTHROTTLE_IRQS &&
172 radeon->radeonScreen->irq);
173
174 radeon->do_usleeps = (fthrottle_mode == DRI_CONF_FTHROTTLE_USLEEPS);
175
176 if (!radeon->do_irqs)
177 fprintf(stderr,
178 "IRQ's not enabled, falling back to %s: %d %d\n",
179 radeon->do_usleeps ? "usleeps" : "busy waits",
180 fthrottle_mode, radeon->radeonScreen->irq);
181
182 (*sPriv->systemTime->getUST) (&radeon->swap_ust);
183
184 return GL_TRUE;
185 }
186
187
188 /**
189 * Cleanup common context fields.
190 * Called by r200DestroyContext/r300DestroyContext
191 */
192 void radeonCleanupContext(radeonContextPtr radeon)
193 {
194 FILE *track;
195 struct radeon_renderbuffer *rb;
196 GLframebuffer *fb;
197
198 fb = (void*)radeon->dri.drawable->driverPrivate;
199 rb = (void *)fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
200 if (rb && rb->bo) {
201 radeon_bo_unref(rb->bo);
202 rb->bo = NULL;
203 }
204 rb = (void *)fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
205 if (rb && rb->bo) {
206 radeon_bo_unref(rb->bo);
207 rb->bo = NULL;
208 }
209 rb = (void *)fb->Attachment[BUFFER_DEPTH].Renderbuffer;
210 if (rb && rb->bo) {
211 radeon_bo_unref(rb->bo);
212 rb->bo = NULL;
213 }
214 fb = (void*)radeon->dri.readable->driverPrivate;
215 rb = (void *)fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
216 if (rb && rb->bo) {
217 radeon_bo_unref(rb->bo);
218 rb->bo = NULL;
219 }
220 rb = (void *)fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
221 if (rb && rb->bo) {
222 radeon_bo_unref(rb->bo);
223 rb->bo = NULL;
224 }
225 rb = (void *)fb->Attachment[BUFFER_DEPTH].Renderbuffer;
226 if (rb && rb->bo) {
227 radeon_bo_unref(rb->bo);
228 rb->bo = NULL;
229 }
230
231 /* _mesa_destroy_context() might result in calls to functions that
232 * depend on the DriverCtx, so don't set it to NULL before.
233 *
234 * radeon->glCtx->DriverCtx = NULL;
235 */
236
237 /* free the Mesa context */
238 _mesa_destroy_context(radeon->glCtx);
239
240 if (radeon->state.scissor.pClipRects) {
241 FREE(radeon->state.scissor.pClipRects);
242 radeon->state.scissor.pClipRects = 0;
243 }
244 track = fopen("/tmp/tracklog", "w");
245 if (track) {
246 radeon_tracker_print(&radeon->radeonScreen->bom->tracker, track);
247 fclose(track);
248 }
249 }
250
251
252 /**
253 * Swap front and back buffer.
254 */
255 void radeonSwapBuffers(__DRIdrawablePrivate * dPriv)
256 {
257 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
258 radeonContextPtr radeon;
259 GLcontext *ctx;
260
261 radeon = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
262 ctx = radeon->glCtx;
263
264 if (ctx->Visual.doubleBufferMode) {
265 _mesa_notifySwapBuffers(ctx);/* flush pending rendering comands */
266 if (radeon->doPageFlip) {
267 radeonPageFlip(dPriv);
268 } else {
269 radeonCopyBuffer(dPriv, NULL);
270 }
271 }
272 } else {
273 /* XXX this shouldn't be an error but we can't handle it for now */
274 _mesa_problem(NULL, "%s: drawable has no context!",
275 __FUNCTION__);
276 }
277 }
278
279 void radeonCopySubBuffer(__DRIdrawablePrivate * dPriv,
280 int x, int y, int w, int h )
281 {
282 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
283 radeonContextPtr radeon;
284 GLcontext *ctx;
285
286 radeon = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
287 ctx = radeon->glCtx;
288
289 if (ctx->Visual.doubleBufferMode) {
290 drm_clip_rect_t rect;
291 rect.x1 = x + dPriv->x;
292 rect.y1 = (dPriv->h - y - h) + dPriv->y;
293 rect.x2 = rect.x1 + w;
294 rect.y2 = rect.y1 + h;
295 _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */
296 radeonCopyBuffer(dPriv, &rect);
297 }
298 } else {
299 /* XXX this shouldn't be an error but we can't handle it for now */
300 _mesa_problem(NULL, "%s: drawable has no context!",
301 __FUNCTION__);
302 }
303 }
304
305 static void
306 radeon_make_kernel_renderbuffer_current(radeonContextPtr radeon,
307 GLframebuffer *draw)
308 {
309 /* if radeon->fake */
310 struct radeon_renderbuffer *rb;
311
312 if ((rb = (void *)draw->Attachment[BUFFER_FRONT_LEFT].Renderbuffer)) {
313
314 if (!rb->bo) {
315 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
316 radeon->radeonScreen->frontOffset,
317 0,
318 0,
319 RADEON_GEM_DOMAIN_VRAM,
320 0);
321 }
322 rb->cpp = radeon->radeonScreen->cpp;
323 rb->pitch = radeon->radeonScreen->frontPitch * rb->cpp;
324 }
325 if ((rb = (void *)draw->Attachment[BUFFER_BACK_LEFT].Renderbuffer)) {
326 if (!rb->bo) {
327 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
328 radeon->radeonScreen->backOffset,
329 0,
330 0,
331 RADEON_GEM_DOMAIN_VRAM,
332 0);
333 }
334 rb->cpp = radeon->radeonScreen->cpp;
335 rb->pitch = radeon->radeonScreen->backPitch * rb->cpp;
336 }
337 if ((rb = (void *)draw->Attachment[BUFFER_DEPTH].Renderbuffer)) {
338 if (!rb->bo) {
339 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
340 radeon->radeonScreen->depthOffset,
341 0,
342 0,
343 RADEON_GEM_DOMAIN_VRAM,
344 0);
345 }
346 rb->cpp = radeon->radeonScreen->cpp;
347 rb->pitch = radeon->radeonScreen->depthPitch * rb->cpp;
348 }
349 }
350
351 static void
352 radeon_make_renderbuffer_current(radeonContextPtr radeon,
353 GLframebuffer *draw)
354 {
355 int size = 4096*4096*4;
356 /* if radeon->fake */
357 struct radeon_renderbuffer *rb;
358
359 if (radeon->radeonScreen->kernel_mm) {
360 radeon_make_kernel_renderbuffer_current(radeon, draw);
361 return;
362 }
363
364
365 if ((rb = (void *)draw->Attachment[BUFFER_FRONT_LEFT].Renderbuffer)) {
366 if (!rb->bo) {
367 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
368 radeon->radeonScreen->frontOffset +
369 radeon->radeonScreen->fbLocation,
370 size,
371 4096,
372 RADEON_GEM_DOMAIN_VRAM,
373 0);
374 }
375 rb->cpp = radeon->radeonScreen->cpp;
376 rb->pitch = radeon->radeonScreen->frontPitch * rb->cpp;
377 }
378 if ((rb = (void *)draw->Attachment[BUFFER_BACK_LEFT].Renderbuffer)) {
379 if (!rb->bo) {
380 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
381 radeon->radeonScreen->backOffset +
382 radeon->radeonScreen->fbLocation,
383 size,
384 4096,
385 RADEON_GEM_DOMAIN_VRAM,
386 0);
387 }
388 rb->cpp = radeon->radeonScreen->cpp;
389 rb->pitch = radeon->radeonScreen->backPitch * rb->cpp;
390 }
391 if ((rb = (void *)draw->Attachment[BUFFER_DEPTH].Renderbuffer)) {
392 if (!rb->bo) {
393 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
394 radeon->radeonScreen->depthOffset +
395 radeon->radeonScreen->fbLocation,
396 size,
397 4096,
398 RADEON_GEM_DOMAIN_VRAM,
399 0);
400 }
401 rb->cpp = radeon->radeonScreen->cpp;
402 rb->pitch = radeon->radeonScreen->depthPitch * rb->cpp;
403 }
404 }
405
406
407 void
408 radeon_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
409 {
410 unsigned int attachments[10];
411 __DRIbuffer *buffers;
412 __DRIscreen *screen;
413 struct radeon_renderbuffer *rb;
414 int i, count;
415 GLframebuffer *draw;
416 radeonContextPtr radeon;
417
418 draw = drawable->driverPrivate;
419 screen = context->driScreenPriv;
420 radeon = (radeonContextPtr) context->driverPrivate;
421 i = 0;
422 if ((rb = (void *)draw->Attachment[BUFFER_FRONT_LEFT].Renderbuffer)) {
423 attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
424 }
425 if ((rb = (void *)draw->Attachment[BUFFER_BACK_LEFT].Renderbuffer)) {
426 attachments[i++] = __DRI_BUFFER_BACK_LEFT;
427 }
428 if ((rb = (void *)draw->Attachment[BUFFER_DEPTH].Renderbuffer)) {
429 attachments[i++] = __DRI_BUFFER_DEPTH;
430 }
431
432 buffers = (*screen->dri2.loader->getBuffers)(drawable,
433 &drawable->w,
434 &drawable->h,
435 attachments, i,
436 &count,
437 drawable->loaderPrivate);
438 if (buffers == NULL)
439 return;
440
441 /* set one cliprect to cover the whole drawable */
442 drawable->x = 0;
443 drawable->y = 0;
444 drawable->backX = 0;
445 drawable->backY = 0;
446 drawable->numClipRects = 1;
447 drawable->pClipRects[0].x1 = 0;
448 drawable->pClipRects[0].y1 = 0;
449 drawable->pClipRects[0].x2 = drawable->w;
450 drawable->pClipRects[0].y2 = drawable->h;
451 drawable->numBackClipRects = 1;
452 drawable->pBackClipRects[0].x1 = 0;
453 drawable->pBackClipRects[0].y1 = 0;
454 drawable->pBackClipRects[0].x2 = drawable->w;
455 drawable->pBackClipRects[0].y2 = drawable->h;
456 for (i = 0; i < count; i++) {
457 switch (buffers[i].attachment) {
458 case __DRI_BUFFER_FRONT_LEFT:
459 rb = (void *)draw->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
460 if (rb->bo) {
461 radeon_bo_unref(rb->bo);
462 rb->bo = NULL;
463 }
464 rb->cpp = buffers[i].cpp;
465 rb->pitch = buffers[i].pitch;
466 rb->width = drawable->w;
467 rb->height = drawable->h;
468 rb->has_surface = 0;
469 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
470 buffers[i].name,
471 0,
472 0,
473 RADEON_GEM_DOMAIN_VRAM,
474 buffers[i].flags);
475 if (rb->bo == NULL) {
476 fprintf(stderr, "failled to attach front %d\n",
477 buffers[i].name);
478 }
479 break;
480 case __DRI_BUFFER_BACK_LEFT:
481 rb = (void *)draw->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
482 if (rb->bo) {
483 radeon_bo_unref(rb->bo);
484 rb->bo = NULL;
485 }
486 rb->cpp = buffers[i].cpp;
487 rb->pitch = buffers[i].pitch;
488 rb->width = drawable->w;
489 rb->height = drawable->h;
490 rb->has_surface = 0;
491 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
492 buffers[i].name,
493 0,
494 0,
495 RADEON_GEM_DOMAIN_VRAM,
496 buffers[i].flags);
497 break;
498 case __DRI_BUFFER_DEPTH:
499 rb = (void *)draw->Attachment[BUFFER_DEPTH].Renderbuffer;
500 if (rb->bo) {
501 radeon_bo_unref(rb->bo);
502 rb->bo = NULL;
503 }
504 rb->cpp = buffers[i].cpp;
505 rb->pitch = buffers[i].pitch;
506 rb->width = drawable->w;
507 rb->height = drawable->h;
508 rb->has_surface = 0;
509 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
510 buffers[i].name,
511 0,
512 0,
513 RADEON_GEM_DOMAIN_VRAM,
514 buffers[i].flags);
515 break;
516 case __DRI_BUFFER_STENCIL:
517 break;
518 case __DRI_BUFFER_ACCUM:
519 default:
520 fprintf(stderr,
521 "unhandled buffer attach event, attacment type %d\n",
522 buffers[i].attachment);
523 return;
524 }
525 }
526 radeon = (radeonContextPtr) context->driverPrivate;
527 driUpdateFramebufferSize(radeon->glCtx, drawable);
528 }
529
530
531 /* Force the context `c' to be the current context and associate with it
532 * buffer `b'.
533 */
534 GLboolean radeonMakeCurrent(__DRIcontextPrivate * driContextPriv,
535 __DRIdrawablePrivate * driDrawPriv,
536 __DRIdrawablePrivate * driReadPriv)
537 {
538 radeonContextPtr radeon;
539 GLframebuffer *dfb, *rfb;
540
541 if (!driContextPriv) {
542 if (RADEON_DEBUG & DEBUG_DRI)
543 fprintf(stderr, "%s ctx is null\n", __FUNCTION__);
544 _mesa_make_current(NULL, NULL, NULL);
545 return GL_TRUE;
546 }
547 radeon = (radeonContextPtr) driContextPriv->driverPrivate;
548 dfb = driDrawPriv->driverPrivate;
549 rfb = driReadPriv->driverPrivate;
550
551 if (driContextPriv->driScreenPriv->dri2.enabled) {
552 radeon_update_renderbuffers(driContextPriv, driDrawPriv);
553 if (driDrawPriv != driReadPriv)
554 radeon_update_renderbuffers(driContextPriv, driReadPriv);
555 radeon->state.color.rrb =
556 (void *)dfb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
557 radeon->state.depth.rrb =
558 (void *)dfb->Attachment[BUFFER_DEPTH].Renderbuffer;
559 }
560
561
562 if (RADEON_DEBUG & DEBUG_DRI)
563 fprintf(stderr, "%s ctx %p\n", __FUNCTION__, radeon->glCtx);
564
565 driUpdateFramebufferSize(radeon->glCtx, driDrawPriv);
566 if (driReadPriv != driDrawPriv)
567 driUpdateFramebufferSize(radeon->glCtx, driReadPriv);
568
569 if (!driContextPriv->driScreenPriv->dri2.enabled) {
570 radeon_make_renderbuffer_current(radeon, dfb);
571 }
572
573 _mesa_make_current(radeon->glCtx, dfb, rfb);
574
575 if (radeon->dri.drawable != driDrawPriv) {
576 if (driDrawPriv->swap_interval == (unsigned)-1) {
577 driDrawPriv->vblFlags =
578 (radeon->radeonScreen->irq != 0)
579 ? driGetDefaultVBlankFlags(&radeon->
580 optionCache)
581 : VBLANK_FLAG_NO_IRQ;
582
583 driDrawableInitVBlank(driDrawPriv);
584 }
585 }
586
587 radeon->dri.readable = driReadPriv;
588
589 if (radeon->dri.drawable != driDrawPriv ||
590 radeon->lastStamp != driDrawPriv->lastStamp) {
591 radeon->dri.drawable = driDrawPriv;
592
593 radeonSetCliprects(radeon);
594 r300UpdateViewportOffset(radeon->glCtx);
595 }
596
597 _mesa_update_state(radeon->glCtx);
598
599 if (!driContextPriv->driScreenPriv->dri2.enabled) {
600 radeonUpdatePageFlipping(radeon);
601 }
602
603 if (RADEON_DEBUG & DEBUG_DRI)
604 fprintf(stderr, "End %s\n", __FUNCTION__);
605 return GL_TRUE;
606 }
607
608 /* Force the context `c' to be unbound from its buffer.
609 */
610 GLboolean radeonUnbindContext(__DRIcontextPrivate * driContextPriv)
611 {
612 radeonContextPtr radeon = (radeonContextPtr) driContextPriv->driverPrivate;
613
614 if (RADEON_DEBUG & DEBUG_DRI)
615 fprintf(stderr, "%s ctx %p\n", __FUNCTION__,
616 radeon->glCtx);
617
618 return GL_TRUE;
619 }
620