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
);
252 radeon_make_kernel_renderbuffer_current(radeonContextPtr radeon
,
255 /* if radeon->fake */
256 struct radeon_renderbuffer
*rb
;
258 if ((rb
= (void *)draw
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
)) {
261 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
262 radeon
->radeonScreen
->frontOffset
,
265 RADEON_GEM_DOMAIN_VRAM
,
268 rb
->cpp
= radeon
->radeonScreen
->cpp
;
269 rb
->pitch
= radeon
->radeonScreen
->frontPitch
* rb
->cpp
;
271 if ((rb
= (void *)draw
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
)) {
273 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
274 radeon
->radeonScreen
->backOffset
,
277 RADEON_GEM_DOMAIN_VRAM
,
280 rb
->cpp
= radeon
->radeonScreen
->cpp
;
281 rb
->pitch
= radeon
->radeonScreen
->backPitch
* rb
->cpp
;
283 if ((rb
= (void *)draw
->Attachment
[BUFFER_DEPTH
].Renderbuffer
)) {
285 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
286 radeon
->radeonScreen
->depthOffset
,
289 RADEON_GEM_DOMAIN_VRAM
,
292 rb
->cpp
= radeon
->radeonScreen
->cpp
;
293 rb
->pitch
= radeon
->radeonScreen
->depthPitch
* rb
->cpp
;
298 radeon_make_renderbuffer_current(radeonContextPtr radeon
,
301 int size
= 4096*4096*4;
302 /* if radeon->fake */
303 struct radeon_renderbuffer
*rb
;
305 if (radeon
->radeonScreen
->kernel_mm
) {
306 radeon_make_kernel_renderbuffer_current(radeon
, draw
);
311 if ((rb
= (void *)draw
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
)) {
313 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
314 radeon
->radeonScreen
->frontOffset
+
315 radeon
->radeonScreen
->fbLocation
,
318 RADEON_GEM_DOMAIN_VRAM
,
321 rb
->cpp
= radeon
->radeonScreen
->cpp
;
322 rb
->pitch
= radeon
->radeonScreen
->frontPitch
* rb
->cpp
;
324 if ((rb
= (void *)draw
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
)) {
326 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
327 radeon
->radeonScreen
->backOffset
+
328 radeon
->radeonScreen
->fbLocation
,
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
+
341 radeon
->radeonScreen
->fbLocation
,
344 RADEON_GEM_DOMAIN_VRAM
,
347 rb
->cpp
= radeon
->radeonScreen
->cpp
;
348 rb
->pitch
= radeon
->radeonScreen
->depthPitch
* rb
->cpp
;
354 radeon_update_renderbuffers(__DRIcontext
*context
, __DRIdrawable
*drawable
)
356 unsigned int attachments
[10];
357 __DRIbuffer
*buffers
;
359 struct radeon_renderbuffer
*rb
;
362 radeonContextPtr radeon
;
364 draw
= drawable
->driverPrivate
;
365 screen
= context
->driScreenPriv
;
366 radeon
= (radeonContextPtr
) context
->driverPrivate
;
368 if ((rb
= (void *)draw
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
)) {
369 attachments
[i
++] = __DRI_BUFFER_FRONT_LEFT
;
371 if ((rb
= (void *)draw
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
)) {
372 attachments
[i
++] = __DRI_BUFFER_BACK_LEFT
;
374 if ((rb
= (void *)draw
->Attachment
[BUFFER_DEPTH
].Renderbuffer
)) {
375 attachments
[i
++] = __DRI_BUFFER_DEPTH
;
378 buffers
= (*screen
->dri2
.loader
->getBuffers
)(drawable
,
383 drawable
->loaderPrivate
);
387 /* set one cliprect to cover the whole drawable */
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
;
407 radeon_bo_unref(rb
->bo
);
410 rb
->cpp
= buffers
[i
].cpp
;
411 rb
->pitch
= buffers
[i
].pitch
;
412 rb
->width
= drawable
->w
;
413 rb
->height
= drawable
->h
;
415 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
419 RADEON_GEM_DOMAIN_VRAM
,
421 if (rb
->bo
== NULL
) {
422 fprintf(stderr
, "failled to attach front %d\n",
426 case __DRI_BUFFER_BACK_LEFT
:
427 rb
= (void *)draw
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
;
429 radeon_bo_unref(rb
->bo
);
432 rb
->cpp
= buffers
[i
].cpp
;
433 rb
->pitch
= buffers
[i
].pitch
;
434 rb
->width
= drawable
->w
;
435 rb
->height
= drawable
->h
;
437 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
441 RADEON_GEM_DOMAIN_VRAM
,
444 case __DRI_BUFFER_DEPTH
:
445 rb
= (void *)draw
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
447 radeon_bo_unref(rb
->bo
);
450 rb
->cpp
= buffers
[i
].cpp
;
451 rb
->pitch
= buffers
[i
].pitch
;
452 rb
->width
= drawable
->w
;
453 rb
->height
= drawable
->h
;
455 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
459 RADEON_GEM_DOMAIN_VRAM
,
462 case __DRI_BUFFER_STENCIL
:
464 case __DRI_BUFFER_ACCUM
:
467 "unhandled buffer attach event, attacment type %d\n",
468 buffers
[i
].attachment
);
472 radeon
= (radeonContextPtr
) context
->driverPrivate
;
473 driUpdateFramebufferSize(radeon
->glCtx
, drawable
);
477 /* Force the context `c' to be the current context and associate with it
480 GLboolean
radeonMakeCurrent(__DRIcontextPrivate
* driContextPriv
,
481 __DRIdrawablePrivate
* driDrawPriv
,
482 __DRIdrawablePrivate
* driReadPriv
)
484 radeonContextPtr radeon
;
485 GLframebuffer
*dfb
, *rfb
;
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
);
493 radeon
= (radeonContextPtr
) driContextPriv
->driverPrivate
;
494 dfb
= driDrawPriv
->driverPrivate
;
495 rfb
= driReadPriv
->driverPrivate
;
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
;
508 if (RADEON_DEBUG
& DEBUG_DRI
)
509 fprintf(stderr
, "%s ctx %p\n", __FUNCTION__
, radeon
->glCtx
);
511 driUpdateFramebufferSize(radeon
->glCtx
, driDrawPriv
);
512 if (driReadPriv
!= driDrawPriv
)
513 driUpdateFramebufferSize(radeon
->glCtx
, driReadPriv
);
515 if (!driContextPriv
->driScreenPriv
->dri2
.enabled
) {
516 radeon_make_renderbuffer_current(radeon
, dfb
);
519 _mesa_make_current(radeon
->glCtx
, dfb
, rfb
);
521 if (radeon
->dri
.drawable
!= driDrawPriv
) {
522 if (driDrawPriv
->swap_interval
== (unsigned)-1) {
523 driDrawPriv
->vblFlags
=
524 (radeon
->radeonScreen
->irq
!= 0)
525 ? driGetDefaultVBlankFlags(&radeon
->
527 : VBLANK_FLAG_NO_IRQ
;
529 driDrawableInitVBlank(driDrawPriv
);
533 radeon
->dri
.readable
= driReadPriv
;
535 if (radeon
->dri
.drawable
!= driDrawPriv
||
536 radeon
->lastStamp
!= driDrawPriv
->lastStamp
) {
537 radeon
->dri
.drawable
= driDrawPriv
;
539 radeonSetCliprects(radeon
);
540 r300UpdateViewportOffset(radeon
->glCtx
);
543 _mesa_update_state(radeon
->glCtx
);
545 if (!driContextPriv
->driScreenPriv
->dri2
.enabled
) {
546 radeonUpdatePageFlipping(radeon
);
549 if (RADEON_DEBUG
& DEBUG_DRI
)
550 fprintf(stderr
, "End %s\n", __FUNCTION__
);
554 /* Force the context `c' to be unbound from its buffer.
556 GLboolean
radeonUnbindContext(__DRIcontextPrivate
* driContextPriv
)
558 radeonContextPtr radeon
= (radeonContextPtr
) driContextPriv
->driverPrivate
;
560 if (RADEON_DEBUG
& DEBUG_DRI
)
561 fprintf(stderr
, "%s ctx %p\n", __FUNCTION__
,