1 /**************************************************************************
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.
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.
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:
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.
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.
33 **************************************************************************/
35 #include "radeon_common.h"
36 #include "xmlpool.h" /* for symbolic values of enum-type options */
38 #include "drirenderbuffer.h"
40 #include "main/state.h"
42 #define DRIVER_DATE "20090101"
45 int RADEON_DEBUG
= (0);
48 /* Return various strings for glGetString().
50 static const GLubyte
*radeonGetString(GLcontext
* ctx
, GLenum name
)
52 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
53 static char buffer
[128];
57 if (IS_R300_CLASS(radeon
->radeonScreen
))
58 return (GLubyte
*) "DRI R300 Project";
60 return (GLubyte
*) "Tungsten Graphics, Inc.";
65 GLuint agp_mode
= (radeon
->radeonScreen
->card_type
==RADEON_CARD_PCI
) ? 0 :
66 radeon
->radeonScreen
->AGPMode
;
69 if (IS_R300_CLASS(radeon
->radeonScreen
))
71 else if (IS_R200_CLASS(radeon
->radeonScreen
))
76 offset
= driGetRendererString(buffer
, chipname
, DRIVER_DATE
,
79 if (IS_R300_CLASS(radeon
->radeonScreen
)) {
80 sprintf(&buffer
[offset
], " %sTCL",
81 (radeon
->radeonScreen
->chip_flags
& RADEON_CHIPSET_TCL
)
84 sprintf(&buffer
[offset
], " %sTCL",
85 !(radeon
->TclFallback
& RADEON_TCL_FALLBACK_TCL_DISABLE
)
89 if (radeon
->radeonScreen
->driScreen
->dri2
.enabled
)
90 strcat(buffer
, " DRI2");
92 return (GLubyte
*) buffer
;
100 /* Initialize the driver's misc functions.
102 static void radeonInitDriverFuncs(struct dd_function_table
*functions
)
104 functions
->GetString
= radeonGetString
;
108 * Create and initialize all common fields of the context,
109 * including the Mesa context itself.
111 GLboolean
radeonInitContext(radeonContextPtr radeon
,
112 struct dd_function_table
* functions
,
113 const __GLcontextModes
* glVisual
,
114 __DRIcontextPrivate
* driContextPriv
,
115 void *sharedContextPrivate
)
117 __DRIscreenPrivate
*sPriv
= driContextPriv
->driScreenPriv
;
118 radeonScreenPtr screen
= (radeonScreenPtr
) (sPriv
->private);
123 /* Fill in additional standard functions. */
124 radeonInitDriverFuncs(functions
);
126 radeon
->radeonScreen
= screen
;
127 /* Allocate and initialize the Mesa context */
128 if (sharedContextPrivate
)
129 shareCtx
= ((radeonContextPtr
)sharedContextPrivate
)->glCtx
;
132 radeon
->glCtx
= _mesa_create_context(glVisual
, shareCtx
,
133 functions
, (void *)radeon
);
138 driContextPriv
->driverPrivate
= radeon
;
141 radeon
->dri
.context
= driContextPriv
;
142 radeon
->dri
.screen
= sPriv
;
143 radeon
->dri
.drawable
= NULL
;
144 radeon
->dri
.readable
= NULL
;
145 radeon
->dri
.hwContext
= driContextPriv
->hHWContext
;
146 radeon
->dri
.hwLock
= &sPriv
->pSAREA
->lock
;
147 radeon
->dri
.fd
= sPriv
->fd
;
148 radeon
->dri
.drmMinor
= sPriv
->drm_version
.minor
;
150 radeon
->sarea
= (drm_radeon_sarea_t
*) ((GLubyte
*) sPriv
->pSAREA
+
151 screen
->sarea_priv_offset
);
154 fthrottle_mode
= driQueryOptioni(&radeon
->optionCache
, "fthrottle_mode");
155 radeon
->iw
.irq_seq
= -1;
156 radeon
->irqsEmitted
= 0;
157 radeon
->do_irqs
= (fthrottle_mode
== DRI_CONF_FTHROTTLE_IRQS
&&
158 radeon
->radeonScreen
->irq
);
160 radeon
->do_usleeps
= (fthrottle_mode
== DRI_CONF_FTHROTTLE_USLEEPS
);
162 if (!radeon
->do_irqs
)
164 "IRQ's not enabled, falling back to %s: %d %d\n",
165 radeon
->do_usleeps
? "usleeps" : "busy waits",
166 fthrottle_mode
, radeon
->radeonScreen
->irq
);
168 (*sPriv
->systemTime
->getUST
) (&radeon
->swap_ust
);
174 * Cleanup common context fields.
175 * Called by r200DestroyContext/r300DestroyContext
177 void radeonCleanupContext(radeonContextPtr radeon
)
179 #ifdef RADEON_BO_TRACK
182 struct radeon_renderbuffer
*rb
;
185 /* free the Mesa context */
186 _mesa_destroy_context(radeon
->glCtx
);
188 fb
= (void*)radeon
->dri
.drawable
->driverPrivate
;
189 rb
= (void *)fb
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
;
191 radeon_bo_unref(rb
->bo
);
194 rb
= (void *)fb
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
;
196 radeon_bo_unref(rb
->bo
);
199 rb
= (void *)fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
201 radeon_bo_unref(rb
->bo
);
204 fb
= (void*)radeon
->dri
.readable
->driverPrivate
;
205 rb
= (void *)fb
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
;
207 radeon_bo_unref(rb
->bo
);
210 rb
= (void *)fb
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
;
212 radeon_bo_unref(rb
->bo
);
215 rb
= (void *)fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
217 radeon_bo_unref(rb
->bo
);
221 /* _mesa_destroy_context() might result in calls to functions that
222 * depend on the DriverCtx, so don't set it to NULL before.
224 * radeon->glCtx->DriverCtx = NULL;
229 /* free the option cache */
230 driDestroyOptionCache(&radeon
->optionCache
);
232 rcommonDestroyCmdBuf(radeon
);
234 if (radeon
->state
.scissor
.pClipRects
) {
235 FREE(radeon
->state
.scissor
.pClipRects
);
236 radeon
->state
.scissor
.pClipRects
= 0;
238 #ifdef RADEON_BO_TRACK
239 track
= fopen("/tmp/tracklog", "w");
241 radeon_tracker_print(&radeon
->radeonScreen
->bom
->tracker
, track
);
247 /* Force the context `c' to be unbound from its buffer.
249 GLboolean
radeonUnbindContext(__DRIcontextPrivate
* driContextPriv
)
251 radeonContextPtr radeon
= (radeonContextPtr
) driContextPriv
->driverPrivate
;
253 if (RADEON_DEBUG
& DEBUG_DRI
)
254 fprintf(stderr
, "%s ctx %p\n", __FUNCTION__
,
262 radeon_make_kernel_renderbuffer_current(radeonContextPtr radeon
,
265 /* if radeon->fake */
266 struct radeon_renderbuffer
*rb
;
268 if ((rb
= (void *)draw
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
)) {
270 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
271 radeon
->radeonScreen
->frontOffset
,
274 RADEON_GEM_DOMAIN_VRAM
,
277 rb
->cpp
= radeon
->radeonScreen
->cpp
;
278 rb
->pitch
= radeon
->radeonScreen
->frontPitch
* rb
->cpp
;
280 if ((rb
= (void *)draw
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
)) {
282 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
283 radeon
->radeonScreen
->backOffset
,
286 RADEON_GEM_DOMAIN_VRAM
,
289 rb
->cpp
= radeon
->radeonScreen
->cpp
;
290 rb
->pitch
= radeon
->radeonScreen
->backPitch
* rb
->cpp
;
292 if ((rb
= (void *)draw
->Attachment
[BUFFER_DEPTH
].Renderbuffer
)) {
294 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
295 radeon
->radeonScreen
->depthOffset
,
298 RADEON_GEM_DOMAIN_VRAM
,
301 rb
->cpp
= radeon
->radeonScreen
->cpp
;
302 rb
->pitch
= radeon
->radeonScreen
->depthPitch
* rb
->cpp
;
304 if ((rb
= (void *)draw
->Attachment
[BUFFER_STENCIL
].Renderbuffer
)) {
306 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
307 radeon
->radeonScreen
->depthOffset
,
310 RADEON_GEM_DOMAIN_VRAM
,
313 rb
->cpp
= radeon
->radeonScreen
->cpp
;
314 rb
->pitch
= radeon
->radeonScreen
->depthPitch
* rb
->cpp
;
319 radeon_make_renderbuffer_current(radeonContextPtr radeon
,
322 int size
= 4096*4096*4;
323 /* if radeon->fake */
324 struct radeon_renderbuffer
*rb
;
326 if (radeon
->radeonScreen
->kernel_mm
) {
327 radeon_make_kernel_renderbuffer_current(radeon
, draw
);
332 if ((rb
= (void *)draw
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
)) {
334 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
335 radeon
->radeonScreen
->frontOffset
+
336 radeon
->radeonScreen
->fbLocation
,
339 RADEON_GEM_DOMAIN_VRAM
,
342 rb
->cpp
= radeon
->radeonScreen
->cpp
;
343 rb
->pitch
= radeon
->radeonScreen
->frontPitch
* rb
->cpp
;
345 if ((rb
= (void *)draw
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
)) {
347 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
348 radeon
->radeonScreen
->backOffset
+
349 radeon
->radeonScreen
->fbLocation
,
352 RADEON_GEM_DOMAIN_VRAM
,
355 rb
->cpp
= radeon
->radeonScreen
->cpp
;
356 rb
->pitch
= radeon
->radeonScreen
->backPitch
* rb
->cpp
;
358 if ((rb
= (void *)draw
->Attachment
[BUFFER_DEPTH
].Renderbuffer
)) {
360 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
361 radeon
->radeonScreen
->depthOffset
+
362 radeon
->radeonScreen
->fbLocation
,
365 RADEON_GEM_DOMAIN_VRAM
,
368 rb
->cpp
= radeon
->radeonScreen
->cpp
;
369 rb
->pitch
= radeon
->radeonScreen
->depthPitch
* rb
->cpp
;
371 if ((rb
= (void *)draw
->Attachment
[BUFFER_STENCIL
].Renderbuffer
)) {
373 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
374 radeon
->radeonScreen
->depthOffset
+
375 radeon
->radeonScreen
->fbLocation
,
378 RADEON_GEM_DOMAIN_VRAM
,
381 rb
->cpp
= radeon
->radeonScreen
->cpp
;
382 rb
->pitch
= radeon
->radeonScreen
->depthPitch
* rb
->cpp
;
388 radeon_update_renderbuffers(__DRIcontext
*context
, __DRIdrawable
*drawable
)
390 unsigned int attachments
[10];
391 __DRIbuffer
*buffers
;
393 struct radeon_renderbuffer
*rb
;
396 radeonContextPtr radeon
;
398 if (RADEON_DEBUG
& DEBUG_DRI
)
399 fprintf(stderr
, "enter %s, drawable %p\n", __func__
, drawable
);
401 draw
= drawable
->driverPrivate
;
402 screen
= context
->driScreenPriv
;
403 radeon
= (radeonContextPtr
) context
->driverPrivate
;
405 if ((rb
= (void *)draw
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
)) {
406 attachments
[i
++] = __DRI_BUFFER_FRONT_LEFT
;
408 if ((rb
= (void *)draw
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
)) {
409 attachments
[i
++] = __DRI_BUFFER_BACK_LEFT
;
411 if ((rb
= (void *)draw
->Attachment
[BUFFER_DEPTH
].Renderbuffer
)) {
412 attachments
[i
++] = __DRI_BUFFER_DEPTH
;
415 buffers
= (*screen
->dri2
.loader
->getBuffers
)(drawable
,
420 drawable
->loaderPrivate
);
424 /* set one cliprect to cover the whole drawable */
429 drawable
->numClipRects
= 1;
430 drawable
->pClipRects
[0].x1
= 0;
431 drawable
->pClipRects
[0].y1
= 0;
432 drawable
->pClipRects
[0].x2
= drawable
->w
;
433 drawable
->pClipRects
[0].y2
= drawable
->h
;
434 drawable
->numBackClipRects
= 1;
435 drawable
->pBackClipRects
[0].x1
= 0;
436 drawable
->pBackClipRects
[0].y1
= 0;
437 drawable
->pBackClipRects
[0].x2
= drawable
->w
;
438 drawable
->pBackClipRects
[0].y2
= drawable
->h
;
439 for (i
= 0; i
< count
; i
++) {
440 switch (buffers
[i
].attachment
) {
441 case __DRI_BUFFER_FRONT_LEFT
:
442 rb
= (void *)draw
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
;
444 radeon_bo_unref(rb
->bo
);
447 rb
->cpp
= buffers
[i
].cpp
;
448 rb
->pitch
= buffers
[i
].pitch
;
449 rb
->width
= drawable
->w
;
450 rb
->height
= drawable
->h
;
452 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
456 RADEON_GEM_DOMAIN_VRAM
,
458 if (rb
->bo
== NULL
) {
459 fprintf(stderr
, "failled to attach front %d\n",
463 case __DRI_BUFFER_BACK_LEFT
:
464 rb
= (void *)draw
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
;
466 radeon_bo_unref(rb
->bo
);
469 rb
->cpp
= buffers
[i
].cpp
;
470 rb
->pitch
= buffers
[i
].pitch
;
471 rb
->width
= drawable
->w
;
472 rb
->height
= drawable
->h
;
474 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
478 RADEON_GEM_DOMAIN_VRAM
,
481 case __DRI_BUFFER_DEPTH
:
482 rb
= (void *)draw
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
484 radeon_bo_unref(rb
->bo
);
487 rb
->cpp
= buffers
[i
].cpp
;
488 rb
->pitch
= buffers
[i
].pitch
;
489 rb
->width
= drawable
->w
;
490 rb
->height
= drawable
->h
;
492 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
496 RADEON_GEM_DOMAIN_VRAM
,
499 case __DRI_BUFFER_STENCIL
:
501 case __DRI_BUFFER_ACCUM
:
504 "unhandled buffer attach event, attacment type %d\n",
505 buffers
[i
].attachment
);
509 radeon
= (radeonContextPtr
) context
->driverPrivate
;
510 driUpdateFramebufferSize(radeon
->glCtx
, drawable
);
513 /* Force the context `c' to be the current context and associate with it
516 GLboolean
radeonMakeCurrent(__DRIcontextPrivate
* driContextPriv
,
517 __DRIdrawablePrivate
* driDrawPriv
,
518 __DRIdrawablePrivate
* driReadPriv
)
520 radeonContextPtr radeon
;
521 GLframebuffer
*dfb
, *rfb
;
523 if (!driContextPriv
) {
524 if (RADEON_DEBUG
& DEBUG_DRI
)
525 fprintf(stderr
, "%s ctx is null\n", __FUNCTION__
);
526 _mesa_make_current(NULL
, NULL
, NULL
);
529 radeon
= (radeonContextPtr
) driContextPriv
->driverPrivate
;
530 dfb
= driDrawPriv
->driverPrivate
;
531 rfb
= driReadPriv
->driverPrivate
;
533 if (driContextPriv
->driScreenPriv
->dri2
.enabled
) {
534 radeon_update_renderbuffers(driContextPriv
, driDrawPriv
);
535 if (driDrawPriv
!= driReadPriv
)
536 radeon_update_renderbuffers(driContextPriv
, driReadPriv
);
537 radeon
->state
.color
.rrb
=
538 (void *)dfb
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
;
539 radeon
->state
.depth
.rrb
=
540 (void *)dfb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
542 radeon_make_renderbuffer_current(radeon
, dfb
);
546 if (RADEON_DEBUG
& DEBUG_DRI
)
547 fprintf(stderr
, "%s ctx %p dfb %p rfb %p\n", __FUNCTION__
, radeon
->glCtx
, dfb
, rfb
);
549 driUpdateFramebufferSize(radeon
->glCtx
, driDrawPriv
);
550 if (driReadPriv
!= driDrawPriv
)
551 driUpdateFramebufferSize(radeon
->glCtx
, driReadPriv
);
555 _mesa_make_current(radeon
->glCtx
, dfb
, rfb
);
557 if (radeon
->dri
.drawable
!= driDrawPriv
) {
558 if (driDrawPriv
->swap_interval
== (unsigned)-1) {
559 driDrawPriv
->vblFlags
=
560 (radeon
->radeonScreen
->irq
!= 0)
561 ? driGetDefaultVBlankFlags(&radeon
->
563 : VBLANK_FLAG_NO_IRQ
;
565 driDrawableInitVBlank(driDrawPriv
);
569 radeon
->dri
.readable
= driReadPriv
;
571 if (radeon
->dri
.drawable
!= driDrawPriv
||
572 radeon
->lastStamp
!= driDrawPriv
->lastStamp
) {
573 radeon
->dri
.drawable
= driDrawPriv
;
575 radeonSetCliprects(radeon
);
576 radeon
->vtbl
.update_viewport_offset(radeon
->glCtx
);
579 _mesa_update_state(radeon
->glCtx
);
581 if (!driContextPriv
->driScreenPriv
->dri2
.enabled
) {
582 radeonUpdatePageFlipping(radeon
);
585 if (RADEON_DEBUG
& DEBUG_DRI
)
586 fprintf(stderr
, "End %s\n", __FUNCTION__
);