radeon/r200/r300: consolidate swap buffers
[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 static void
252 radeon_make_kernel_renderbuffer_current(radeonContextPtr radeon,
253 GLframebuffer *draw)
254 {
255 /* if radeon->fake */
256 struct radeon_renderbuffer *rb;
257
258 if ((rb = (void *)draw->Attachment[BUFFER_FRONT_LEFT].Renderbuffer)) {
259
260 if (!rb->bo) {
261 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
262 radeon->radeonScreen->frontOffset,
263 0,
264 0,
265 RADEON_GEM_DOMAIN_VRAM,
266 0);
267 }
268 rb->cpp = radeon->radeonScreen->cpp;
269 rb->pitch = radeon->radeonScreen->frontPitch * rb->cpp;
270 }
271 if ((rb = (void *)draw->Attachment[BUFFER_BACK_LEFT].Renderbuffer)) {
272 if (!rb->bo) {
273 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
274 radeon->radeonScreen->backOffset,
275 0,
276 0,
277 RADEON_GEM_DOMAIN_VRAM,
278 0);
279 }
280 rb->cpp = radeon->radeonScreen->cpp;
281 rb->pitch = radeon->radeonScreen->backPitch * rb->cpp;
282 }
283 if ((rb = (void *)draw->Attachment[BUFFER_DEPTH].Renderbuffer)) {
284 if (!rb->bo) {
285 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
286 radeon->radeonScreen->depthOffset,
287 0,
288 0,
289 RADEON_GEM_DOMAIN_VRAM,
290 0);
291 }
292 rb->cpp = radeon->radeonScreen->cpp;
293 rb->pitch = radeon->radeonScreen->depthPitch * rb->cpp;
294 }
295 }
296
297 static void
298 radeon_make_renderbuffer_current(radeonContextPtr radeon,
299 GLframebuffer *draw)
300 {
301 int size = 4096*4096*4;
302 /* if radeon->fake */
303 struct radeon_renderbuffer *rb;
304
305 if (radeon->radeonScreen->kernel_mm) {
306 radeon_make_kernel_renderbuffer_current(radeon, draw);
307 return;
308 }
309
310
311 if ((rb = (void *)draw->Attachment[BUFFER_FRONT_LEFT].Renderbuffer)) {
312 if (!rb->bo) {
313 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
314 radeon->radeonScreen->frontOffset +
315 radeon->radeonScreen->fbLocation,
316 size,
317 4096,
318 RADEON_GEM_DOMAIN_VRAM,
319 0);
320 }
321 rb->cpp = radeon->radeonScreen->cpp;
322 rb->pitch = radeon->radeonScreen->frontPitch * rb->cpp;
323 }
324 if ((rb = (void *)draw->Attachment[BUFFER_BACK_LEFT].Renderbuffer)) {
325 if (!rb->bo) {
326 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
327 radeon->radeonScreen->backOffset +
328 radeon->radeonScreen->fbLocation,
329 size,
330 4096,
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 radeon->radeonScreen->fbLocation,
342 size,
343 4096,
344 RADEON_GEM_DOMAIN_VRAM,
345 0);
346 }
347 rb->cpp = radeon->radeonScreen->cpp;
348 rb->pitch = radeon->radeonScreen->depthPitch * rb->cpp;
349 }
350 }
351
352
353 void
354 radeon_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
355 {
356 unsigned int attachments[10];
357 __DRIbuffer *buffers;
358 __DRIscreen *screen;
359 struct radeon_renderbuffer *rb;
360 int i, count;
361 GLframebuffer *draw;
362 radeonContextPtr radeon;
363
364 draw = drawable->driverPrivate;
365 screen = context->driScreenPriv;
366 radeon = (radeonContextPtr) context->driverPrivate;
367 i = 0;
368 if ((rb = (void *)draw->Attachment[BUFFER_FRONT_LEFT].Renderbuffer)) {
369 attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
370 }
371 if ((rb = (void *)draw->Attachment[BUFFER_BACK_LEFT].Renderbuffer)) {
372 attachments[i++] = __DRI_BUFFER_BACK_LEFT;
373 }
374 if ((rb = (void *)draw->Attachment[BUFFER_DEPTH].Renderbuffer)) {
375 attachments[i++] = __DRI_BUFFER_DEPTH;
376 }
377
378 buffers = (*screen->dri2.loader->getBuffers)(drawable,
379 &drawable->w,
380 &drawable->h,
381 attachments, i,
382 &count,
383 drawable->loaderPrivate);
384 if (buffers == NULL)
385 return;
386
387 /* set one cliprect to cover the whole drawable */
388 drawable->x = 0;
389 drawable->y = 0;
390 drawable->backX = 0;
391 drawable->backY = 0;
392 drawable->numClipRects = 1;
393 drawable->pClipRects[0].x1 = 0;
394 drawable->pClipRects[0].y1 = 0;
395 drawable->pClipRects[0].x2 = drawable->w;
396 drawable->pClipRects[0].y2 = drawable->h;
397 drawable->numBackClipRects = 1;
398 drawable->pBackClipRects[0].x1 = 0;
399 drawable->pBackClipRects[0].y1 = 0;
400 drawable->pBackClipRects[0].x2 = drawable->w;
401 drawable->pBackClipRects[0].y2 = drawable->h;
402 for (i = 0; i < count; i++) {
403 switch (buffers[i].attachment) {
404 case __DRI_BUFFER_FRONT_LEFT:
405 rb = (void *)draw->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
406 if (rb->bo) {
407 radeon_bo_unref(rb->bo);
408 rb->bo = NULL;
409 }
410 rb->cpp = buffers[i].cpp;
411 rb->pitch = buffers[i].pitch;
412 rb->width = drawable->w;
413 rb->height = drawable->h;
414 rb->has_surface = 0;
415 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
416 buffers[i].name,
417 0,
418 0,
419 RADEON_GEM_DOMAIN_VRAM,
420 buffers[i].flags);
421 if (rb->bo == NULL) {
422 fprintf(stderr, "failled to attach front %d\n",
423 buffers[i].name);
424 }
425 break;
426 case __DRI_BUFFER_BACK_LEFT:
427 rb = (void *)draw->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
428 if (rb->bo) {
429 radeon_bo_unref(rb->bo);
430 rb->bo = NULL;
431 }
432 rb->cpp = buffers[i].cpp;
433 rb->pitch = buffers[i].pitch;
434 rb->width = drawable->w;
435 rb->height = drawable->h;
436 rb->has_surface = 0;
437 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
438 buffers[i].name,
439 0,
440 0,
441 RADEON_GEM_DOMAIN_VRAM,
442 buffers[i].flags);
443 break;
444 case __DRI_BUFFER_DEPTH:
445 rb = (void *)draw->Attachment[BUFFER_DEPTH].Renderbuffer;
446 if (rb->bo) {
447 radeon_bo_unref(rb->bo);
448 rb->bo = NULL;
449 }
450 rb->cpp = buffers[i].cpp;
451 rb->pitch = buffers[i].pitch;
452 rb->width = drawable->w;
453 rb->height = drawable->h;
454 rb->has_surface = 0;
455 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
456 buffers[i].name,
457 0,
458 0,
459 RADEON_GEM_DOMAIN_VRAM,
460 buffers[i].flags);
461 break;
462 case __DRI_BUFFER_STENCIL:
463 break;
464 case __DRI_BUFFER_ACCUM:
465 default:
466 fprintf(stderr,
467 "unhandled buffer attach event, attacment type %d\n",
468 buffers[i].attachment);
469 return;
470 }
471 }
472 radeon = (radeonContextPtr) context->driverPrivate;
473 driUpdateFramebufferSize(radeon->glCtx, drawable);
474 }
475
476
477 /* Force the context `c' to be the current context and associate with it
478 * buffer `b'.
479 */
480 GLboolean radeonMakeCurrent(__DRIcontextPrivate * driContextPriv,
481 __DRIdrawablePrivate * driDrawPriv,
482 __DRIdrawablePrivate * driReadPriv)
483 {
484 radeonContextPtr radeon;
485 GLframebuffer *dfb, *rfb;
486
487 if (!driContextPriv) {
488 if (RADEON_DEBUG & DEBUG_DRI)
489 fprintf(stderr, "%s ctx is null\n", __FUNCTION__);
490 _mesa_make_current(NULL, NULL, NULL);
491 return GL_TRUE;
492 }
493 radeon = (radeonContextPtr) driContextPriv->driverPrivate;
494 dfb = driDrawPriv->driverPrivate;
495 rfb = driReadPriv->driverPrivate;
496
497 if (driContextPriv->driScreenPriv->dri2.enabled) {
498 radeon_update_renderbuffers(driContextPriv, driDrawPriv);
499 if (driDrawPriv != driReadPriv)
500 radeon_update_renderbuffers(driContextPriv, driReadPriv);
501 radeon->state.color.rrb =
502 (void *)dfb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
503 radeon->state.depth.rrb =
504 (void *)dfb->Attachment[BUFFER_DEPTH].Renderbuffer;
505 }
506
507
508 if (RADEON_DEBUG & DEBUG_DRI)
509 fprintf(stderr, "%s ctx %p\n", __FUNCTION__, radeon->glCtx);
510
511 driUpdateFramebufferSize(radeon->glCtx, driDrawPriv);
512 if (driReadPriv != driDrawPriv)
513 driUpdateFramebufferSize(radeon->glCtx, driReadPriv);
514
515 if (!driContextPriv->driScreenPriv->dri2.enabled) {
516 radeon_make_renderbuffer_current(radeon, dfb);
517 }
518
519 _mesa_make_current(radeon->glCtx, dfb, rfb);
520
521 if (radeon->dri.drawable != driDrawPriv) {
522 if (driDrawPriv->swap_interval == (unsigned)-1) {
523 driDrawPriv->vblFlags =
524 (radeon->radeonScreen->irq != 0)
525 ? driGetDefaultVBlankFlags(&radeon->
526 optionCache)
527 : VBLANK_FLAG_NO_IRQ;
528
529 driDrawableInitVBlank(driDrawPriv);
530 }
531 }
532
533 radeon->dri.readable = driReadPriv;
534
535 if (radeon->dri.drawable != driDrawPriv ||
536 radeon->lastStamp != driDrawPriv->lastStamp) {
537 radeon->dri.drawable = driDrawPriv;
538
539 radeonSetCliprects(radeon);
540 r300UpdateViewportOffset(radeon->glCtx);
541 }
542
543 _mesa_update_state(radeon->glCtx);
544
545 if (!driContextPriv->driScreenPriv->dri2.enabled) {
546 radeonUpdatePageFlipping(radeon);
547 }
548
549 if (RADEON_DEBUG & DEBUG_DRI)
550 fprintf(stderr, "End %s\n", __FUNCTION__);
551 return GL_TRUE;
552 }
553
554 /* Force the context `c' to be unbound from its buffer.
555 */
556 GLboolean radeonUnbindContext(__DRIcontextPrivate * driContextPriv)
557 {
558 radeonContextPtr radeon = (radeonContextPtr) driContextPriv->driverPrivate;
559
560 if (RADEON_DEBUG & DEBUG_DRI)
561 fprintf(stderr, "%s ctx %p\n", __FUNCTION__,
562 radeon->glCtx);
563
564 return GL_TRUE;
565 }
566