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 */
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"
48 #define DRIVER_DATE "20090101"
51 int RADEON_DEBUG
= (0);
54 /* Return various strings for glGetString().
56 static const GLubyte
*radeonGetString(GLcontext
* ctx
, GLenum name
)
58 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
59 static char buffer
[128];
63 if (IS_R300_CLASS(radeon
->radeonScreen
))
64 return (GLubyte
*) "DRI R300 Project";
66 return (GLubyte
*) "Tungsten Graphics, Inc.";
71 GLuint agp_mode
= (radeon
->radeonScreen
->card_type
==RADEON_CARD_PCI
) ? 0 :
72 radeon
->radeonScreen
->AGPMode
;
75 if (IS_R300_CLASS(radeon
->radeonScreen
))
77 else if (IS_R200_CLASS(radeon
->radeonScreen
))
82 offset
= driGetRendererString(buffer
, chipname
, DRIVER_DATE
,
85 if (IS_R300_CLASS(radeon
->radeonScreen
)) {
86 sprintf(&buffer
[offset
], " %sTCL",
87 (radeon
->radeonScreen
->chip_flags
& RADEON_CHIPSET_TCL
)
90 sprintf(&buffer
[offset
], " %sTCL",
91 !(radeon
->TclFallback
& RADEON_TCL_FALLBACK_TCL_DISABLE
)
95 if (radeon
->radeonScreen
->driScreen
->dri2
.enabled
)
96 strcat(buffer
, " DRI2");
98 return (GLubyte
*) buffer
;
106 /* Initialize the driver's misc functions.
108 static void radeonInitDriverFuncs(struct dd_function_table
*functions
)
110 functions
->GetString
= radeonGetString
;
114 * Create and initialize all common fields of the context,
115 * including the Mesa context itself.
117 GLboolean
radeonInitContext(radeonContextPtr radeon
,
118 struct dd_function_table
* functions
,
119 const __GLcontextModes
* glVisual
,
120 __DRIcontextPrivate
* driContextPriv
,
121 void *sharedContextPrivate
)
123 __DRIscreenPrivate
*sPriv
= driContextPriv
->driScreenPriv
;
124 radeonScreenPtr screen
= (radeonScreenPtr
) (sPriv
->private);
129 /* Fill in additional standard functions. */
130 radeonInitDriverFuncs(functions
);
132 radeon
->radeonScreen
= screen
;
133 /* Allocate and initialize the Mesa context */
134 if (sharedContextPrivate
)
135 shareCtx
= ((radeonContextPtr
)sharedContextPrivate
)->glCtx
;
138 radeon
->glCtx
= _mesa_create_context(glVisual
, shareCtx
,
139 functions
, (void *)radeon
);
144 driContextPriv
->driverPrivate
= radeon
;
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
;
156 radeon
->sarea
= (drm_radeon_sarea_t
*) ((GLubyte
*) sPriv
->pSAREA
+
157 screen
->sarea_priv_offset
);
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
);
166 radeon
->do_usleeps
= (fthrottle_mode
== DRI_CONF_FTHROTTLE_USLEEPS
);
168 if (!radeon
->do_irqs
)
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
);
174 radeon
->texture_depth
= driQueryOptioni (&radeon
->optionCache
,
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
;
186 * Destroy the command buffer and state atoms.
188 static void radeon_destroy_atom_list(radeonContextPtr radeon
)
190 struct radeon_state_atom
*atom
;
192 foreach(atom
, &radeon
->hw
.atomlist
) {
201 * Cleanup common context fields.
202 * Called by r200DestroyContext/r300DestroyContext
204 void radeonDestroyContext(__DRIcontextPrivate
*driContextPriv
)
206 #ifdef RADEON_BO_TRACK
209 GET_CURRENT_CONTEXT(ctx
);
210 radeonContextPtr radeon
= (radeonContextPtr
) driContextPriv
->driverPrivate
;
211 radeonContextPtr current
= ctx
? RADEON_CONTEXT(ctx
) : NULL
;
213 if (radeon
== current
) {
214 radeon_firevertices(radeon
);
215 _mesa_make_current(NULL
, NULL
, NULL
);
221 if (radeon
->dma
.current
) {
222 rcommonFlushCmdBuf( radeon
, __FUNCTION__
);
225 radeonReleaseArrays(radeon
->glCtx
, ~0);
227 if (radeon
->vtbl
.free_context
)
228 radeon
->vtbl
.free_context(radeon
->glCtx
);
229 _swsetup_DestroyContext( radeon
->glCtx
);
230 _tnl_DestroyContext( radeon
->glCtx
);
231 _vbo_DestroyContext( radeon
->glCtx
);
232 _swrast_DestroyContext( radeon
->glCtx
);
234 radeonDestroyBuffer(radeon
->dri
.drawable
);
235 radeonDestroyBuffer(radeon
->dri
.readable
);
238 /* free the Mesa context */
239 _mesa_destroy_context(radeon
->glCtx
);
241 /* _mesa_destroy_context() might result in calls to functions that
242 * depend on the DriverCtx, so don't set it to NULL before.
244 * radeon->glCtx->DriverCtx = NULL;
246 /* free the option cache */
247 driDestroyOptionCache(&radeon
->optionCache
);
249 rcommonDestroyCmdBuf(radeon
);
251 radeon_destroy_atom_list(radeon
);
253 if (radeon
->state
.scissor
.pClipRects
) {
254 FREE(radeon
->state
.scissor
.pClipRects
);
255 radeon
->state
.scissor
.pClipRects
= 0;
258 #ifdef RADEON_BO_TRACK
259 track
= fopen("/tmp/tracklog", "w");
261 radeon_tracker_print(&radeon
->radeonScreen
->bom
->tracker
, track
);
268 /* Force the context `c' to be unbound from its buffer.
270 GLboolean
radeonUnbindContext(__DRIcontextPrivate
* driContextPriv
)
272 radeonContextPtr radeon
= (radeonContextPtr
) driContextPriv
->driverPrivate
;
274 if (RADEON_DEBUG
& DEBUG_DRI
)
275 fprintf(stderr
, "%s ctx %p\n", __FUNCTION__
,
283 radeon_make_kernel_renderbuffer_current(radeonContextPtr radeon
,
284 struct radeon_framebuffer
*draw
)
286 /* if radeon->fake */
287 struct radeon_renderbuffer
*rb
;
289 if ((rb
= (void *)draw
->base
.Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
)) {
291 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
292 radeon
->radeonScreen
->frontOffset
,
295 RADEON_GEM_DOMAIN_VRAM
,
298 rb
->cpp
= radeon
->radeonScreen
->cpp
;
299 rb
->pitch
= radeon
->radeonScreen
->frontPitch
* rb
->cpp
;
301 if ((rb
= (void *)draw
->base
.Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
)) {
303 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
304 radeon
->radeonScreen
->backOffset
,
307 RADEON_GEM_DOMAIN_VRAM
,
310 rb
->cpp
= radeon
->radeonScreen
->cpp
;
311 rb
->pitch
= radeon
->radeonScreen
->backPitch
* rb
->cpp
;
313 if ((rb
= (void *)draw
->base
.Attachment
[BUFFER_DEPTH
].Renderbuffer
)) {
315 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
316 radeon
->radeonScreen
->depthOffset
,
319 RADEON_GEM_DOMAIN_VRAM
,
322 rb
->cpp
= radeon
->radeonScreen
->cpp
;
323 rb
->pitch
= radeon
->radeonScreen
->depthPitch
* rb
->cpp
;
325 if ((rb
= (void *)draw
->base
.Attachment
[BUFFER_STENCIL
].Renderbuffer
)) {
327 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
328 radeon
->radeonScreen
->depthOffset
,
331 RADEON_GEM_DOMAIN_VRAM
,
334 rb
->cpp
= radeon
->radeonScreen
->cpp
;
335 rb
->pitch
= radeon
->radeonScreen
->depthPitch
* rb
->cpp
;
340 radeon_make_renderbuffer_current(radeonContextPtr radeon
,
341 struct radeon_framebuffer
*draw
)
343 int size
= 4096*4096*4;
344 /* if radeon->fake */
345 struct radeon_renderbuffer
*rb
;
347 if (radeon
->radeonScreen
->kernel_mm
) {
348 radeon_make_kernel_renderbuffer_current(radeon
, draw
);
353 if ((rb
= (void *)draw
->base
.Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
)) {
355 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
356 radeon
->radeonScreen
->frontOffset
+
357 radeon
->radeonScreen
->fbLocation
,
360 RADEON_GEM_DOMAIN_VRAM
,
363 rb
->cpp
= radeon
->radeonScreen
->cpp
;
364 rb
->pitch
= radeon
->radeonScreen
->frontPitch
* rb
->cpp
;
366 if ((rb
= (void *)draw
->base
.Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
)) {
368 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
369 radeon
->radeonScreen
->backOffset
+
370 radeon
->radeonScreen
->fbLocation
,
373 RADEON_GEM_DOMAIN_VRAM
,
376 rb
->cpp
= radeon
->radeonScreen
->cpp
;
377 rb
->pitch
= radeon
->radeonScreen
->backPitch
* rb
->cpp
;
379 if ((rb
= (void *)draw
->base
.Attachment
[BUFFER_DEPTH
].Renderbuffer
)) {
381 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
382 radeon
->radeonScreen
->depthOffset
+
383 radeon
->radeonScreen
->fbLocation
,
386 RADEON_GEM_DOMAIN_VRAM
,
389 rb
->cpp
= radeon
->radeonScreen
->cpp
;
390 rb
->pitch
= radeon
->radeonScreen
->depthPitch
* rb
->cpp
;
392 if ((rb
= (void *)draw
->base
.Attachment
[BUFFER_STENCIL
].Renderbuffer
)) {
394 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
395 radeon
->radeonScreen
->depthOffset
+
396 radeon
->radeonScreen
->fbLocation
,
399 RADEON_GEM_DOMAIN_VRAM
,
402 rb
->cpp
= radeon
->radeonScreen
->cpp
;
403 rb
->pitch
= radeon
->radeonScreen
->depthPitch
* rb
->cpp
;
409 radeon_update_renderbuffers(__DRIcontext
*context
, __DRIdrawable
*drawable
)
411 unsigned int attachments
[10];
412 __DRIbuffer
*buffers
;
414 struct radeon_renderbuffer
*rb
;
416 struct radeon_framebuffer
*draw
;
417 radeonContextPtr radeon
;
419 struct radeon_bo
*depth_bo
= NULL
, *bo
;
421 if (RADEON_DEBUG
& DEBUG_DRI
)
422 fprintf(stderr
, "enter %s, drawable %p\n", __func__
, drawable
);
424 draw
= drawable
->driverPrivate
;
425 screen
= context
->driScreenPriv
;
426 radeon
= (radeonContextPtr
) context
->driverPrivate
;
428 if (draw
->color_rb
[0])
429 attachments
[i
++] = __DRI_BUFFER_FRONT_LEFT
;
430 if (draw
->color_rb
[1])
431 attachments
[i
++] = __DRI_BUFFER_BACK_LEFT
;
432 if (radeon_get_renderbuffer(&draw
->base
, BUFFER_DEPTH
))
433 attachments
[i
++] = __DRI_BUFFER_DEPTH
;
434 if (radeon_get_renderbuffer(&draw
->base
, BUFFER_STENCIL
))
435 attachments
[i
++] = __DRI_BUFFER_STENCIL
;
437 buffers
= (*screen
->dri2
.loader
->getBuffers
)(drawable
,
442 drawable
->loaderPrivate
);
446 /* set one cliprect to cover the whole drawable */
451 drawable
->numClipRects
= 1;
452 drawable
->pClipRects
[0].x1
= 0;
453 drawable
->pClipRects
[0].y1
= 0;
454 drawable
->pClipRects
[0].x2
= drawable
->w
;
455 drawable
->pClipRects
[0].y2
= drawable
->h
;
456 drawable
->numBackClipRects
= 1;
457 drawable
->pBackClipRects
[0].x1
= 0;
458 drawable
->pBackClipRects
[0].y1
= 0;
459 drawable
->pBackClipRects
[0].x2
= drawable
->w
;
460 drawable
->pBackClipRects
[0].y2
= drawable
->h
;
461 for (i
= 0; i
< count
; i
++) {
462 switch (buffers
[i
].attachment
) {
463 case __DRI_BUFFER_FRONT_LEFT
:
464 rb
= draw
->color_rb
[0];
465 regname
= "dri2 front buffer";
467 case __DRI_BUFFER_BACK_LEFT
:
468 rb
= draw
->color_rb
[1];
469 regname
= "dri2 back buffer";
471 case __DRI_BUFFER_DEPTH
:
472 rb
= radeon_get_renderbuffer(&draw
->base
, BUFFER_DEPTH
);
473 regname
= "dri2 depth buffer";
475 case __DRI_BUFFER_STENCIL
:
476 rb
= radeon_get_renderbuffer(&draw
->base
, BUFFER_STENCIL
);
477 regname
= "dri2 stencil buffer";
479 case __DRI_BUFFER_ACCUM
:
482 "unhandled buffer attach event, attacment type %d\n",
483 buffers
[i
].attachment
);
491 uint32_t name
= radeon_gem_name_bo(rb
->bo
);
492 if (name
== buffers
[i
].name
)
496 if (RADEON_DEBUG
& DEBUG_DRI
)
498 "attaching buffer %s, %d, at %d, cpp %d, pitch %d\n",
499 regname
, buffers
[i
].name
, buffers
[i
].attachment
,
500 buffers
[i
].cpp
, buffers
[i
].pitch
);
502 rb
->cpp
= buffers
[i
].cpp
;
503 rb
->pitch
= buffers
[i
].pitch
;
504 rb
->width
= drawable
->w
;
505 rb
->height
= drawable
->h
;
508 if (buffers
[i
].attachment
== __DRI_BUFFER_STENCIL
&& depth_bo
) {
509 if (RADEON_DEBUG
& DEBUG_DRI
)
510 fprintf(stderr
, "(reusing depth buffer as stencil)\n");
514 bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
518 RADEON_GEM_DOMAIN_VRAM
,
522 fprintf(stderr
, "failed to attach %s %d\n",
523 regname
, buffers
[i
].name
);
528 if (buffers
[i
].attachment
== __DRI_BUFFER_DEPTH
) {
529 if (draw
->base
.Visual
.depthBits
== 16)
534 radeon_renderbuffer_set_bo(rb
, bo
);
539 driUpdateFramebufferSize(radeon
->glCtx
, drawable
);
542 /* Force the context `c' to be the current context and associate with it
545 GLboolean
radeonMakeCurrent(__DRIcontextPrivate
* driContextPriv
,
546 __DRIdrawablePrivate
* driDrawPriv
,
547 __DRIdrawablePrivate
* driReadPriv
)
549 radeonContextPtr radeon
;
550 struct radeon_framebuffer
*drfb
;
551 struct gl_framebuffer
*readfb
;
553 if (!driContextPriv
) {
554 if (RADEON_DEBUG
& DEBUG_DRI
)
555 fprintf(stderr
, "%s ctx is null\n", __FUNCTION__
);
556 _mesa_make_current(NULL
, NULL
, NULL
);
560 radeon
= (radeonContextPtr
) driContextPriv
->driverPrivate
;
561 drfb
= driDrawPriv
->driverPrivate
;
562 readfb
= driReadPriv
->driverPrivate
;
564 if (driContextPriv
->driScreenPriv
->dri2
.enabled
) {
565 radeon_update_renderbuffers(driContextPriv
, driDrawPriv
);
566 if (driDrawPriv
!= driReadPriv
)
567 radeon_update_renderbuffers(driContextPriv
, driReadPriv
);
568 radeon
->state
.color
.rrb
=
569 radeon_get_renderbuffer(&drfb
->base
, BUFFER_BACK_LEFT
);
570 radeon
->state
.depth
.rrb
=
571 radeon_get_renderbuffer(&drfb
->base
, BUFFER_DEPTH
);
573 radeon_make_renderbuffer_current(radeon
, drfb
);
577 if (RADEON_DEBUG
& DEBUG_DRI
)
578 fprintf(stderr
, "%s ctx %p dfb %p rfb %p\n", __FUNCTION__
, radeon
->glCtx
, drfb
, readfb
);
580 if (radeon
->dri
.readable
!= driReadPriv
)
581 radeon
->dri
.readable
= driReadPriv
;
583 driUpdateFramebufferSize(radeon
->glCtx
, driDrawPriv
);
584 if (driReadPriv
!= driDrawPriv
)
585 driUpdateFramebufferSize(radeon
->glCtx
, driReadPriv
);
587 _mesa_make_current(radeon
->glCtx
, &drfb
->base
, readfb
);
589 _mesa_update_state(radeon
->glCtx
);
591 if (radeon
->glCtx
->DrawBuffer
== &drfb
->base
) {
593 if (radeon
->dri
.drawable
!= driDrawPriv
) {
594 if (driDrawPriv
->swap_interval
== (unsigned)-1) {
596 driDrawPriv
->vblFlags
=
597 (radeon
->radeonScreen
->irq
!= 0)
598 ? driGetDefaultVBlankFlags(&radeon
->
600 : VBLANK_FLAG_NO_IRQ
;
602 driDrawableInitVBlank(driDrawPriv
);
603 drfb
->vbl_waited
= driDrawPriv
->vblSeq
;
605 for (i
= 0; i
< 2; i
++) {
606 if (drfb
->color_rb
[i
])
607 drfb
->color_rb
[i
]->vbl_pending
= driDrawPriv
->vblSeq
;
611 radeon
->dri
.drawable
= driDrawPriv
;
613 radeon_window_moved(radeon
);
615 radeon_draw_buffer(radeon
->glCtx
, &drfb
->base
);
619 if (RADEON_DEBUG
& DEBUG_DRI
)
620 fprintf(stderr
, "End %s\n", __FUNCTION__
);