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