Merge commit 'origin/master' into radeon-rewrite
[mesa.git] / src / mesa / drivers / dri / radeon / radeon_common_context.c
1 /**************************************************************************
2
3 Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
4 VA Linux Systems Inc., Fremont, California.
5 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
6
7 The Weather Channel (TM) funded Tungsten Graphics to develop the
8 initial release of the Radeon 8500 driver under the XFree86 license.
9 This notice must be preserved.
10
11 All Rights Reserved.
12
13 Permission is hereby granted, free of charge, to any person obtaining
14 a copy of this software and associated documentation files (the
15 "Software"), to deal in the Software without restriction, including
16 without limitation the rights to use, copy, modify, merge, publish,
17 distribute, sublicense, and/or sell copies of the Software, and to
18 permit persons to whom the Software is furnished to do so, subject to
19 the following conditions:
20
21 The above copyright notice and this permission notice (including the
22 next paragraph) shall be included in all copies or substantial
23 portions of the Software.
24
25 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
28 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
29 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32
33 **************************************************************************/
34
35 #include "radeon_common.h"
36 #include "xmlpool.h" /* for symbolic values of enum-type options */
37 #include "utils.h"
38 #include "vblank.h"
39 #include "drirenderbuffer.h"
40 #include "main/context.h"
41 #include "main/framebuffer.h"
42 #include "main/state.h"
43 #include "main/simple_list.h"
44 #include "swrast/swrast.h"
45 #include "swrast_setup/swrast_setup.h"
46 #include "tnl/tnl.h"
47
48 #define DRIVER_DATE "20090101"
49
50 #ifndef RADEON_DEBUG
51 int RADEON_DEBUG = (0);
52 #endif
53
54 /* Return various strings for glGetString().
55 */
56 static const GLubyte *radeonGetString(GLcontext * ctx, GLenum name)
57 {
58 radeonContextPtr radeon = RADEON_CONTEXT(ctx);
59 static char buffer[128];
60
61 switch (name) {
62 case GL_VENDOR:
63 if (IS_R300_CLASS(radeon->radeonScreen))
64 return (GLubyte *) "DRI R300 Project";
65 else
66 return (GLubyte *) "Tungsten Graphics, Inc.";
67
68 case GL_RENDERER:
69 {
70 unsigned offset;
71 GLuint agp_mode = (radeon->radeonScreen->card_type==RADEON_CARD_PCI) ? 0 :
72 radeon->radeonScreen->AGPMode;
73 const char* chipname;
74
75 if (IS_R300_CLASS(radeon->radeonScreen))
76 chipname = "R300";
77 else if (IS_R200_CLASS(radeon->radeonScreen))
78 chipname = "R200";
79 else
80 chipname = "R100";
81
82 offset = driGetRendererString(buffer, chipname, DRIVER_DATE,
83 agp_mode);
84
85 if (IS_R300_CLASS(radeon->radeonScreen)) {
86 sprintf(&buffer[offset], " %sTCL",
87 (radeon->radeonScreen->chip_flags & RADEON_CHIPSET_TCL)
88 ? "" : "NO-");
89 } else {
90 sprintf(&buffer[offset], " %sTCL",
91 !(radeon->TclFallback & RADEON_TCL_FALLBACK_TCL_DISABLE)
92 ? "" : "NO-");
93 }
94
95 if (radeon->radeonScreen->driScreen->dri2.enabled)
96 strcat(buffer, " DRI2");
97
98 return (GLubyte *) buffer;
99 }
100
101 default:
102 return NULL;
103 }
104 }
105
106 /* Initialize the driver's misc functions.
107 */
108 static void radeonInitDriverFuncs(struct dd_function_table *functions)
109 {
110 functions->GetString = radeonGetString;
111 }
112
113 /**
114 * Create and initialize all common fields of the context,
115 * including the Mesa context itself.
116 */
117 GLboolean radeonInitContext(radeonContextPtr radeon,
118 struct dd_function_table* functions,
119 const __GLcontextModes * glVisual,
120 __DRIcontextPrivate * driContextPriv,
121 void *sharedContextPrivate)
122 {
123 __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
124 radeonScreenPtr screen = (radeonScreenPtr) (sPriv->private);
125 GLcontext* ctx;
126 GLcontext* shareCtx;
127 int fthrottle_mode;
128
129 /* Fill in additional standard functions. */
130 radeonInitDriverFuncs(functions);
131
132 radeon->radeonScreen = screen;
133 /* Allocate and initialize the Mesa context */
134 if (sharedContextPrivate)
135 shareCtx = ((radeonContextPtr)sharedContextPrivate)->glCtx;
136 else
137 shareCtx = NULL;
138 radeon->glCtx = _mesa_create_context(glVisual, shareCtx,
139 functions, (void *)radeon);
140 if (!radeon->glCtx)
141 return GL_FALSE;
142
143 ctx = radeon->glCtx;
144 driContextPriv->driverPrivate = radeon;
145
146 /* DRI fields */
147 radeon->dri.context = driContextPriv;
148 radeon->dri.screen = sPriv;
149 radeon->dri.drawable = NULL;
150 radeon->dri.readable = NULL;
151 radeon->dri.hwContext = driContextPriv->hHWContext;
152 radeon->dri.hwLock = &sPriv->pSAREA->lock;
153 radeon->dri.fd = sPriv->fd;
154 radeon->dri.drmMinor = sPriv->drm_version.minor;
155
156 radeon->sarea = (drm_radeon_sarea_t *) ((GLubyte *) sPriv->pSAREA +
157 screen->sarea_priv_offset);
158
159 /* Setup IRQs */
160 fthrottle_mode = driQueryOptioni(&radeon->optionCache, "fthrottle_mode");
161 radeon->iw.irq_seq = -1;
162 radeon->irqsEmitted = 0;
163 radeon->do_irqs = (fthrottle_mode == DRI_CONF_FTHROTTLE_IRQS &&
164 radeon->radeonScreen->irq);
165
166 radeon->do_usleeps = (fthrottle_mode == DRI_CONF_FTHROTTLE_USLEEPS);
167
168 if (!radeon->do_irqs)
169 fprintf(stderr,
170 "IRQ's not enabled, falling back to %s: %d %d\n",
171 radeon->do_usleeps ? "usleeps" : "busy waits",
172 fthrottle_mode, radeon->radeonScreen->irq);
173
174 radeon->texture_depth = driQueryOptioni (&radeon->optionCache,
175 "texture_depth");
176 if (radeon->texture_depth == DRI_CONF_TEXTURE_DEPTH_FB)
177 radeon->texture_depth = ( glVisual->rgbBits > 16 ) ?
178 DRI_CONF_TEXTURE_DEPTH_32 : DRI_CONF_TEXTURE_DEPTH_16;
179
180 radeon->texture_row_align = 32;
181
182 return GL_TRUE;
183 }
184
185
186
187 /**
188 * Destroy the command buffer and state atoms.
189 */
190 static void radeon_destroy_atom_list(radeonContextPtr radeon)
191 {
192 struct radeon_state_atom *atom;
193
194 foreach(atom, &radeon->hw.atomlist) {
195 FREE(atom->cmd);
196 if (atom->lastcmd)
197 FREE(atom->lastcmd);
198 }
199
200 }
201
202 /**
203 * Cleanup common context fields.
204 * Called by r200DestroyContext/r300DestroyContext
205 */
206 void radeonDestroyContext(__DRIcontextPrivate *driContextPriv )
207 {
208 #ifdef RADEON_BO_TRACK
209 FILE *track;
210 #endif
211 GET_CURRENT_CONTEXT(ctx);
212 radeonContextPtr radeon = (radeonContextPtr) driContextPriv->driverPrivate;
213 radeonContextPtr current = ctx ? RADEON_CONTEXT(ctx) : NULL;
214
215 if (radeon == current) {
216 radeon_firevertices(radeon);
217 _mesa_make_current(NULL, NULL, NULL);
218 }
219
220 assert(radeon);
221 if (radeon) {
222
223 if (radeon->dma.current) {
224 rcommonFlushCmdBuf( radeon, __FUNCTION__ );
225 }
226
227 radeonReleaseArrays(radeon->glCtx, ~0);
228
229 if (radeon->vtbl.free_context)
230 radeon->vtbl.free_context(radeon->glCtx);
231 _swsetup_DestroyContext( radeon->glCtx );
232 _tnl_DestroyContext( radeon->glCtx );
233 _vbo_DestroyContext( radeon->glCtx );
234 _swrast_DestroyContext( radeon->glCtx );
235
236 radeonDestroyBuffer(radeon->dri.drawable);
237 radeonDestroyBuffer(radeon->dri.readable);
238
239 /* free atom list */
240 /* free the Mesa context */
241 _mesa_destroy_context(radeon->glCtx);
242
243 /* _mesa_destroy_context() might result in calls to functions that
244 * depend on the DriverCtx, so don't set it to NULL before.
245 *
246 * radeon->glCtx->DriverCtx = NULL;
247 */
248 /* free the option cache */
249 driDestroyOptionCache(&radeon->optionCache);
250
251 rcommonDestroyCmdBuf(radeon);
252
253 radeon_destroy_atom_list(radeon);
254
255 if (radeon->state.scissor.pClipRects) {
256 FREE(radeon->state.scissor.pClipRects);
257 radeon->state.scissor.pClipRects = 0;
258 }
259 }
260 #ifdef RADEON_BO_TRACK
261 track = fopen("/tmp/tracklog", "w");
262 if (track) {
263 radeon_tracker_print(&radeon->radeonScreen->bom->tracker, track);
264 fclose(track);
265 }
266 #endif
267 FREE(radeon);
268 }
269
270 /* Force the context `c' to be unbound from its buffer.
271 */
272 GLboolean radeonUnbindContext(__DRIcontextPrivate * driContextPriv)
273 {
274 radeonContextPtr radeon = (radeonContextPtr) driContextPriv->driverPrivate;
275
276 if (RADEON_DEBUG & DEBUG_DRI)
277 fprintf(stderr, "%s ctx %p\n", __FUNCTION__,
278 radeon->glCtx);
279
280 return GL_TRUE;
281 }
282
283
284 static void
285 radeon_make_kernel_renderbuffer_current(radeonContextPtr radeon,
286 struct radeon_framebuffer *draw)
287 {
288 /* if radeon->fake */
289 struct radeon_renderbuffer *rb;
290
291 if ((rb = (void *)draw->base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer)) {
292 if (!rb->bo) {
293 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
294 radeon->radeonScreen->frontOffset,
295 0,
296 0,
297 RADEON_GEM_DOMAIN_VRAM,
298 0);
299 }
300 rb->cpp = radeon->radeonScreen->cpp;
301 rb->pitch = radeon->radeonScreen->frontPitch * rb->cpp;
302 }
303 if ((rb = (void *)draw->base.Attachment[BUFFER_BACK_LEFT].Renderbuffer)) {
304 if (!rb->bo) {
305 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
306 radeon->radeonScreen->backOffset,
307 0,
308 0,
309 RADEON_GEM_DOMAIN_VRAM,
310 0);
311 }
312 rb->cpp = radeon->radeonScreen->cpp;
313 rb->pitch = radeon->radeonScreen->backPitch * rb->cpp;
314 }
315 if ((rb = (void *)draw->base.Attachment[BUFFER_DEPTH].Renderbuffer)) {
316 if (!rb->bo) {
317 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
318 radeon->radeonScreen->depthOffset,
319 0,
320 0,
321 RADEON_GEM_DOMAIN_VRAM,
322 0);
323 }
324 rb->cpp = radeon->radeonScreen->cpp;
325 rb->pitch = radeon->radeonScreen->depthPitch * rb->cpp;
326 }
327 if ((rb = (void *)draw->base.Attachment[BUFFER_STENCIL].Renderbuffer)) {
328 if (!rb->bo) {
329 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
330 radeon->radeonScreen->depthOffset,
331 0,
332 0,
333 RADEON_GEM_DOMAIN_VRAM,
334 0);
335 }
336 rb->cpp = radeon->radeonScreen->cpp;
337 rb->pitch = radeon->radeonScreen->depthPitch * rb->cpp;
338 }
339 }
340
341 static void
342 radeon_make_renderbuffer_current(radeonContextPtr radeon,
343 struct radeon_framebuffer *draw)
344 {
345 int size = 4096*4096*4;
346 /* if radeon->fake */
347 struct radeon_renderbuffer *rb;
348
349 if (radeon->radeonScreen->kernel_mm) {
350 radeon_make_kernel_renderbuffer_current(radeon, draw);
351 return;
352 }
353
354
355 if ((rb = (void *)draw->base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer)) {
356 if (!rb->bo) {
357 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
358 radeon->radeonScreen->frontOffset +
359 radeon->radeonScreen->fbLocation,
360 size,
361 4096,
362 RADEON_GEM_DOMAIN_VRAM,
363 0);
364 }
365 rb->cpp = radeon->radeonScreen->cpp;
366 rb->pitch = radeon->radeonScreen->frontPitch * rb->cpp;
367 }
368 if ((rb = (void *)draw->base.Attachment[BUFFER_BACK_LEFT].Renderbuffer)) {
369 if (!rb->bo) {
370 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
371 radeon->radeonScreen->backOffset +
372 radeon->radeonScreen->fbLocation,
373 size,
374 4096,
375 RADEON_GEM_DOMAIN_VRAM,
376 0);
377 }
378 rb->cpp = radeon->radeonScreen->cpp;
379 rb->pitch = radeon->radeonScreen->backPitch * rb->cpp;
380 }
381 if ((rb = (void *)draw->base.Attachment[BUFFER_DEPTH].Renderbuffer)) {
382 if (!rb->bo) {
383 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
384 radeon->radeonScreen->depthOffset +
385 radeon->radeonScreen->fbLocation,
386 size,
387 4096,
388 RADEON_GEM_DOMAIN_VRAM,
389 0);
390 }
391 rb->cpp = radeon->radeonScreen->cpp;
392 rb->pitch = radeon->radeonScreen->depthPitch * rb->cpp;
393 }
394 if ((rb = (void *)draw->base.Attachment[BUFFER_STENCIL].Renderbuffer)) {
395 if (!rb->bo) {
396 rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
397 radeon->radeonScreen->depthOffset +
398 radeon->radeonScreen->fbLocation,
399 size,
400 4096,
401 RADEON_GEM_DOMAIN_VRAM,
402 0);
403 }
404 rb->cpp = radeon->radeonScreen->cpp;
405 rb->pitch = radeon->radeonScreen->depthPitch * rb->cpp;
406 }
407 }
408
409
410 void
411 radeon_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
412 {
413 unsigned int attachments[10];
414 __DRIbuffer *buffers;
415 __DRIscreen *screen;
416 struct radeon_renderbuffer *rb;
417 int i, count;
418 struct radeon_framebuffer *draw;
419 radeonContextPtr radeon;
420 char *regname;
421 struct radeon_bo *depth_bo = NULL, *bo;
422
423 if (RADEON_DEBUG & DEBUG_DRI)
424 fprintf(stderr, "enter %s, drawable %p\n", __func__, drawable);
425
426 draw = drawable->driverPrivate;
427 screen = context->driScreenPriv;
428 radeon = (radeonContextPtr) context->driverPrivate;
429 i = 0;
430 if (draw->color_rb[0])
431 attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
432 if (draw->color_rb[1])
433 attachments[i++] = __DRI_BUFFER_BACK_LEFT;
434 if (radeon_get_renderbuffer(&draw->base, BUFFER_DEPTH))
435 attachments[i++] = __DRI_BUFFER_DEPTH;
436 if (radeon_get_renderbuffer(&draw->base, BUFFER_STENCIL))
437 attachments[i++] = __DRI_BUFFER_STENCIL;
438
439 buffers = (*screen->dri2.loader->getBuffers)(drawable,
440 &drawable->w,
441 &drawable->h,
442 attachments, i,
443 &count,
444 drawable->loaderPrivate);
445 if (buffers == NULL)
446 return;
447
448 /* set one cliprect to cover the whole drawable */
449 drawable->x = 0;
450 drawable->y = 0;
451 drawable->backX = 0;
452 drawable->backY = 0;
453 drawable->numClipRects = 1;
454 drawable->pClipRects[0].x1 = 0;
455 drawable->pClipRects[0].y1 = 0;
456 drawable->pClipRects[0].x2 = drawable->w;
457 drawable->pClipRects[0].y2 = drawable->h;
458 drawable->numBackClipRects = 1;
459 drawable->pBackClipRects[0].x1 = 0;
460 drawable->pBackClipRects[0].y1 = 0;
461 drawable->pBackClipRects[0].x2 = drawable->w;
462 drawable->pBackClipRects[0].y2 = drawable->h;
463 for (i = 0; i < count; i++) {
464 switch (buffers[i].attachment) {
465 case __DRI_BUFFER_FRONT_LEFT:
466 rb = draw->color_rb[0];
467 regname = "dri2 front buffer";
468 break;
469 case __DRI_BUFFER_BACK_LEFT:
470 rb = draw->color_rb[1];
471 regname = "dri2 back buffer";
472 break;
473 case __DRI_BUFFER_DEPTH:
474 rb = radeon_get_renderbuffer(&draw->base, BUFFER_DEPTH);
475 regname = "dri2 depth buffer";
476 break;
477 case __DRI_BUFFER_STENCIL:
478 rb = radeon_get_renderbuffer(&draw->base, BUFFER_STENCIL);
479 regname = "dri2 stencil buffer";
480 break;
481 case __DRI_BUFFER_ACCUM:
482 default:
483 fprintf(stderr,
484 "unhandled buffer attach event, attacment type %d\n",
485 buffers[i].attachment);
486 return;
487 }
488
489 if (rb == NULL)
490 continue;
491
492 if (rb->bo) {
493 uint32_t name = radeon_gem_name_bo(rb->bo);
494 if (name == buffers[i].name)
495 continue;
496 }
497
498 if (RADEON_DEBUG & DEBUG_DRI)
499 fprintf(stderr,
500 "attaching buffer %s, %d, at %d, cpp %d, pitch %d\n",
501 regname, buffers[i].name, buffers[i].attachment,
502 buffers[i].cpp, buffers[i].pitch);
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
510 if (buffers[i].attachment == __DRI_BUFFER_STENCIL && depth_bo) {
511 if (RADEON_DEBUG & DEBUG_DRI)
512 fprintf(stderr, "(reusing depth buffer as stencil)\n");
513 bo = depth_bo;
514 radeon_bo_ref(bo);
515 } else {
516 bo = radeon_bo_open(radeon->radeonScreen->bom,
517 buffers[i].name,
518 0,
519 0,
520 RADEON_GEM_DOMAIN_VRAM,
521 buffers[i].flags);
522 if (bo == NULL) {
523
524 fprintf(stderr, "failed to attach %s %d\n",
525 regname, buffers[i].name);
526
527 }
528 }
529
530 if (buffers[i].attachment == __DRI_BUFFER_DEPTH) {
531 if (draw->base.Visual.depthBits == 16)
532 rb->cpp = 2;
533 depth_bo = bo;
534 }
535
536 radeon_renderbuffer_set_bo(rb, bo);
537 radeon_bo_unref(bo);
538
539 }
540
541 driUpdateFramebufferSize(radeon->glCtx, drawable);
542 }
543
544 /* Force the context `c' to be the current context and associate with it
545 * buffer `b'.
546 */
547 GLboolean radeonMakeCurrent(__DRIcontextPrivate * driContextPriv,
548 __DRIdrawablePrivate * driDrawPriv,
549 __DRIdrawablePrivate * driReadPriv)
550 {
551 radeonContextPtr radeon;
552 struct radeon_framebuffer *drfb;
553 struct gl_framebuffer *readfb;
554
555 if (!driContextPriv) {
556 if (RADEON_DEBUG & DEBUG_DRI)
557 fprintf(stderr, "%s ctx is null\n", __FUNCTION__);
558 _mesa_make_current(NULL, NULL, NULL);
559 return GL_TRUE;
560 }
561
562 radeon = (radeonContextPtr) driContextPriv->driverPrivate;
563 drfb = driDrawPriv->driverPrivate;
564 readfb = driReadPriv->driverPrivate;
565
566 if (driContextPriv->driScreenPriv->dri2.enabled) {
567 radeon_update_renderbuffers(driContextPriv, driDrawPriv);
568 if (driDrawPriv != driReadPriv)
569 radeon_update_renderbuffers(driContextPriv, driReadPriv);
570 radeon->state.color.rrb =
571 radeon_get_renderbuffer(&drfb->base, BUFFER_BACK_LEFT);
572 radeon->state.depth.rrb =
573 radeon_get_renderbuffer(&drfb->base, BUFFER_DEPTH);
574 } else {
575 radeon_make_renderbuffer_current(radeon, drfb);
576 }
577
578
579 if (RADEON_DEBUG & DEBUG_DRI)
580 fprintf(stderr, "%s ctx %p dfb %p rfb %p\n", __FUNCTION__, radeon->glCtx, drfb, readfb);
581
582 if (radeon->dri.readable != driReadPriv)
583 radeon->dri.readable = driReadPriv;
584
585 driUpdateFramebufferSize(radeon->glCtx, driDrawPriv);
586 if (driReadPriv != driDrawPriv)
587 driUpdateFramebufferSize(radeon->glCtx, driReadPriv);
588
589 _mesa_make_current(radeon->glCtx, &drfb->base, readfb);
590
591 _mesa_update_state(radeon->glCtx);
592
593 if (radeon->glCtx->DrawBuffer == &drfb->base) {
594
595 if (radeon->dri.drawable != driDrawPriv) {
596 if (driDrawPriv->swap_interval == (unsigned)-1) {
597 int i;
598 driDrawPriv->vblFlags =
599 (radeon->radeonScreen->irq != 0)
600 ? driGetDefaultVBlankFlags(&radeon->
601 optionCache)
602 : VBLANK_FLAG_NO_IRQ;
603
604 driDrawableInitVBlank(driDrawPriv);
605 drfb->vbl_waited = driDrawPriv->vblSeq;
606
607 for (i = 0; i < 2; i++) {
608 if (drfb->color_rb[i])
609 drfb->color_rb[i]->vbl_pending = driDrawPriv->vblSeq;
610 }
611
612 }
613 radeon->dri.drawable = driDrawPriv;
614
615 radeon_window_moved(radeon);
616 }
617 radeon_draw_buffer(radeon->glCtx, &drfb->base);
618 }
619
620
621 if (RADEON_DEBUG & DEBUG_DRI)
622 fprintf(stderr, "End %s\n", __FUNCTION__);
623 return GL_TRUE;
624 }
625