2 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
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.
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:
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.
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.
28 **************************************************************************/
31 * \file radeon_context.c
32 * Common context initialization.
34 * \author Keith Whitwell <keith@tungstengraphics.com>
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"
46 #include "drivers/common/driverfuncs.h"
47 #include "swrast/swrast.h"
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"
55 #include "radeon_state.h"
56 #include "r300_state.h"
60 #include "xmlpool.h" /* for symbolic values of enum-type options */
61 #include "drirenderbuffer.h"
63 #define DRIVER_DATE "20060815"
66 /* Return various strings for glGetString().
68 static const GLubyte
*radeonGetString(GLcontext
* ctx
, GLenum name
)
70 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
71 static char buffer
[128];
75 if (IS_R300_CLASS(radeon
->radeonScreen
))
76 return (GLubyte
*) "DRI R300 Project";
78 return (GLubyte
*) "Tungsten Graphics, Inc.";
83 GLuint agp_mode
= (radeon
->radeonScreen
->card_type
==RADEON_CARD_PCI
) ? 0 :
84 radeon
->radeonScreen
->AGPMode
;
87 if (IS_R300_CLASS(radeon
->radeonScreen
))
92 offset
= driGetRendererString(buffer
, chipname
, DRIVER_DATE
,
95 if (IS_R300_CLASS(radeon
->radeonScreen
)) {
96 sprintf(&buffer
[offset
], " %sTCL",
97 (radeon
->radeonScreen
->chip_flags
& RADEON_CHIPSET_TCL
)
100 sprintf(&buffer
[offset
], " %sTCL",
101 !(radeon
->TclFallback
& RADEON_TCL_FALLBACK_TCL_DISABLE
)
105 return (GLubyte
*) buffer
;
113 /* Initialize the driver's misc functions.
115 static void radeonInitDriverFuncs(struct dd_function_table
*functions
)
117 functions
->GetString
= radeonGetString
;
122 * Create and initialize all common fields of the context,
123 * including the Mesa context itself.
125 GLboolean
radeonInitContext(radeonContextPtr radeon
,
126 struct dd_function_table
* functions
,
127 const __GLcontextModes
* glVisual
,
128 __DRIcontextPrivate
* driContextPriv
,
129 void *sharedContextPrivate
)
131 __DRIscreenPrivate
*sPriv
= driContextPriv
->driScreenPriv
;
132 radeonScreenPtr screen
= (radeonScreenPtr
) (sPriv
->private);
137 /* Fill in additional standard functions. */
138 radeonInitDriverFuncs(functions
);
140 radeon
->radeonScreen
= screen
;
141 /* Allocate and initialize the Mesa context */
142 if (sharedContextPrivate
)
143 shareCtx
= ((radeonContextPtr
)sharedContextPrivate
)->glCtx
;
146 radeon
->glCtx
= _mesa_create_context(glVisual
, shareCtx
,
147 functions
, (void *)radeon
);
152 driContextPriv
->driverPrivate
= radeon
;
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
;
164 radeon
->sarea
= (drm_radeon_sarea_t
*) ((GLubyte
*) sPriv
->pSAREA
+
165 screen
->sarea_priv_offset
);
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
);
174 radeon
->do_usleeps
= (fthrottle_mode
== DRI_CONF_FTHROTTLE_USLEEPS
);
176 if (!radeon
->do_irqs
)
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
);
182 (*sPriv
->systemTime
->getUST
) (&radeon
->swap_ust
);
189 * Cleanup common context fields.
190 * Called by r200DestroyContext/r300DestroyContext
192 void radeonCleanupContext(radeonContextPtr radeon
)
195 struct radeon_renderbuffer
*rb
;
198 fb
= (void*)radeon
->dri
.drawable
->driverPrivate
;
199 rb
= (void *)fb
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
;
201 radeon_bo_unref(rb
->bo
);
204 rb
= (void *)fb
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
;
206 radeon_bo_unref(rb
->bo
);
209 rb
= (void *)fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
211 radeon_bo_unref(rb
->bo
);
214 fb
= (void*)radeon
->dri
.readable
->driverPrivate
;
215 rb
= (void *)fb
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
;
217 radeon_bo_unref(rb
->bo
);
220 rb
= (void *)fb
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
;
222 radeon_bo_unref(rb
->bo
);
225 rb
= (void *)fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
227 radeon_bo_unref(rb
->bo
);
231 /* _mesa_destroy_context() might result in calls to functions that
232 * depend on the DriverCtx, so don't set it to NULL before.
234 * radeon->glCtx->DriverCtx = NULL;
237 /* free the Mesa context */
238 _mesa_destroy_context(radeon
->glCtx
);
240 if (radeon
->state
.scissor
.pClipRects
) {
241 FREE(radeon
->state
.scissor
.pClipRects
);
242 radeon
->state
.scissor
.pClipRects
= 0;
244 track
= fopen("/tmp/tracklog", "w");
246 radeon_tracker_print(&radeon
->radeonScreen
->bom
->tracker
, track
);
253 * Swap front and back buffer.
255 void radeonSwapBuffers(__DRIdrawablePrivate
* dPriv
)
257 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
258 radeonContextPtr radeon
;
261 radeon
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
264 if (ctx
->Visual
.doubleBufferMode
) {
265 _mesa_notifySwapBuffers(ctx
);/* flush pending rendering comands */
266 if (radeon
->doPageFlip
) {
267 radeonPageFlip(dPriv
);
269 radeonCopyBuffer(dPriv
, NULL
);
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!",
279 void radeonCopySubBuffer(__DRIdrawablePrivate
* dPriv
,
280 int x
, int y
, int w
, int h
)
282 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
283 radeonContextPtr radeon
;
286 radeon
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
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
);
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!",
306 radeon_make_kernel_renderbuffer_current(radeonContextPtr radeon
,
309 /* if radeon->fake */
310 struct radeon_renderbuffer
*rb
;
312 if ((rb
= (void *)draw
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
)) {
315 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
316 radeon
->radeonScreen
->frontOffset
,
319 RADEON_GEM_DOMAIN_VRAM
,
322 rb
->cpp
= radeon
->radeonScreen
->cpp
;
323 rb
->pitch
= radeon
->radeonScreen
->frontPitch
* rb
->cpp
;
325 if ((rb
= (void *)draw
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
)) {
327 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
328 radeon
->radeonScreen
->backOffset
,
331 RADEON_GEM_DOMAIN_VRAM
,
334 rb
->cpp
= radeon
->radeonScreen
->cpp
;
335 rb
->pitch
= radeon
->radeonScreen
->backPitch
* rb
->cpp
;
337 if ((rb
= (void *)draw
->Attachment
[BUFFER_DEPTH
].Renderbuffer
)) {
339 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
340 radeon
->radeonScreen
->depthOffset
,
343 RADEON_GEM_DOMAIN_VRAM
,
346 rb
->cpp
= radeon
->radeonScreen
->cpp
;
347 rb
->pitch
= radeon
->radeonScreen
->depthPitch
* rb
->cpp
;
352 radeon_make_renderbuffer_current(radeonContextPtr radeon
,
355 int size
= 4096*4096*4;
356 /* if radeon->fake */
357 struct radeon_renderbuffer
*rb
;
359 if (radeon
->radeonScreen
->kernel_mm
) {
360 radeon_make_kernel_renderbuffer_current(radeon
, draw
);
365 if ((rb
= (void *)draw
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
)) {
367 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
368 radeon
->radeonScreen
->frontOffset
+
369 radeon
->radeonScreen
->fbLocation
,
372 RADEON_GEM_DOMAIN_VRAM
,
375 rb
->cpp
= radeon
->radeonScreen
->cpp
;
376 rb
->pitch
= radeon
->radeonScreen
->frontPitch
* rb
->cpp
;
378 if ((rb
= (void *)draw
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
)) {
380 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
381 radeon
->radeonScreen
->backOffset
+
382 radeon
->radeonScreen
->fbLocation
,
385 RADEON_GEM_DOMAIN_VRAM
,
388 rb
->cpp
= radeon
->radeonScreen
->cpp
;
389 rb
->pitch
= radeon
->radeonScreen
->backPitch
* rb
->cpp
;
391 if ((rb
= (void *)draw
->Attachment
[BUFFER_DEPTH
].Renderbuffer
)) {
393 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
394 radeon
->radeonScreen
->depthOffset
+
395 radeon
->radeonScreen
->fbLocation
,
398 RADEON_GEM_DOMAIN_VRAM
,
401 rb
->cpp
= radeon
->radeonScreen
->cpp
;
402 rb
->pitch
= radeon
->radeonScreen
->depthPitch
* rb
->cpp
;
408 radeon_update_renderbuffers(__DRIcontext
*context
, __DRIdrawable
*drawable
)
410 unsigned int attachments
[10];
411 __DRIbuffer
*buffers
;
413 struct radeon_renderbuffer
*rb
;
416 radeonContextPtr radeon
;
418 draw
= drawable
->driverPrivate
;
419 screen
= context
->driScreenPriv
;
420 radeon
= (radeonContextPtr
) context
->driverPrivate
;
422 if ((rb
= (void *)draw
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
)) {
423 attachments
[i
++] = __DRI_BUFFER_FRONT_LEFT
;
425 if ((rb
= (void *)draw
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
)) {
426 attachments
[i
++] = __DRI_BUFFER_BACK_LEFT
;
428 if ((rb
= (void *)draw
->Attachment
[BUFFER_DEPTH
].Renderbuffer
)) {
429 attachments
[i
++] = __DRI_BUFFER_DEPTH
;
432 buffers
= (*screen
->dri2
.loader
->getBuffers
)(drawable
,
437 drawable
->loaderPrivate
);
441 /* set one cliprect to cover the whole drawable */
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
;
461 radeon_bo_unref(rb
->bo
);
464 rb
->cpp
= buffers
[i
].cpp
;
465 rb
->pitch
= buffers
[i
].pitch
;
466 rb
->width
= drawable
->w
;
467 rb
->height
= drawable
->h
;
469 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
473 RADEON_GEM_DOMAIN_VRAM
,
475 if (rb
->bo
== NULL
) {
476 fprintf(stderr
, "failled to attach front %d\n",
480 case __DRI_BUFFER_BACK_LEFT
:
481 rb
= (void *)draw
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
;
483 radeon_bo_unref(rb
->bo
);
486 rb
->cpp
= buffers
[i
].cpp
;
487 rb
->pitch
= buffers
[i
].pitch
;
488 rb
->width
= drawable
->w
;
489 rb
->height
= drawable
->h
;
491 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
495 RADEON_GEM_DOMAIN_VRAM
,
498 case __DRI_BUFFER_DEPTH
:
499 rb
= (void *)draw
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
501 radeon_bo_unref(rb
->bo
);
504 rb
->cpp
= buffers
[i
].cpp
;
505 rb
->pitch
= buffers
[i
].pitch
;
506 rb
->width
= drawable
->w
;
507 rb
->height
= drawable
->h
;
509 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
513 RADEON_GEM_DOMAIN_VRAM
,
516 case __DRI_BUFFER_STENCIL
:
518 case __DRI_BUFFER_ACCUM
:
521 "unhandled buffer attach event, attacment type %d\n",
522 buffers
[i
].attachment
);
526 radeon
= (radeonContextPtr
) context
->driverPrivate
;
527 driUpdateFramebufferSize(radeon
->glCtx
, drawable
);
531 /* Force the context `c' to be the current context and associate with it
534 GLboolean
radeonMakeCurrent(__DRIcontextPrivate
* driContextPriv
,
535 __DRIdrawablePrivate
* driDrawPriv
,
536 __DRIdrawablePrivate
* driReadPriv
)
538 radeonContextPtr radeon
;
539 GLframebuffer
*dfb
, *rfb
;
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
);
547 radeon
= (radeonContextPtr
) driContextPriv
->driverPrivate
;
548 dfb
= driDrawPriv
->driverPrivate
;
549 rfb
= driReadPriv
->driverPrivate
;
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
;
562 if (RADEON_DEBUG
& DEBUG_DRI
)
563 fprintf(stderr
, "%s ctx %p\n", __FUNCTION__
, radeon
->glCtx
);
565 driUpdateFramebufferSize(radeon
->glCtx
, driDrawPriv
);
566 if (driReadPriv
!= driDrawPriv
)
567 driUpdateFramebufferSize(radeon
->glCtx
, driReadPriv
);
569 if (!driContextPriv
->driScreenPriv
->dri2
.enabled
) {
570 radeon_make_renderbuffer_current(radeon
, dfb
);
573 _mesa_make_current(radeon
->glCtx
, dfb
, rfb
);
575 if (radeon
->dri
.drawable
!= driDrawPriv
) {
576 if (driDrawPriv
->swap_interval
== (unsigned)-1) {
577 driDrawPriv
->vblFlags
=
578 (radeon
->radeonScreen
->irq
!= 0)
579 ? driGetDefaultVBlankFlags(&radeon
->
581 : VBLANK_FLAG_NO_IRQ
;
583 driDrawableInitVBlank(driDrawPriv
);
587 radeon
->dri
.readable
= driReadPriv
;
589 if (radeon
->dri
.drawable
!= driDrawPriv
||
590 radeon
->lastStamp
!= driDrawPriv
->lastStamp
) {
591 radeon
->dri
.drawable
= driDrawPriv
;
593 radeonSetCliprects(radeon
);
594 r300UpdateViewportOffset(radeon
->glCtx
);
597 _mesa_update_state(radeon
->glCtx
);
599 if (!driContextPriv
->driScreenPriv
->dri2
.enabled
) {
600 radeonUpdatePageFlipping(radeon
);
603 if (RADEON_DEBUG
& DEBUG_DRI
)
604 fprintf(stderr
, "End %s\n", __FUNCTION__
);
608 /* Force the context `c' to be unbound from its buffer.
610 GLboolean
radeonUnbindContext(__DRIcontextPrivate
* driContextPriv
)
612 radeonContextPtr radeon
= (radeonContextPtr
) driContextPriv
->driverPrivate
;
614 if (RADEON_DEBUG
& DEBUG_DRI
)
615 fprintf(stderr
, "%s ctx %p\n", __FUNCTION__
,