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 "drivers/common/meta.h"
39 #include "main/context.h"
40 #include "main/framebuffer.h"
41 #include "main/renderbuffer.h"
42 #include "main/state.h"
43 #include "main/simple_list.h"
44 #include "swrast/swrast.h"
45 #include "swrast_setup/swrast_setup.h"
49 int RADEON_DEBUG
= (0);
53 static const char* get_chip_family_name(int chip_family
)
56 case CHIP_FAMILY_R100
: return "R100";
57 case CHIP_FAMILY_RV100
: return "RV100";
58 case CHIP_FAMILY_RS100
: return "RS100";
59 case CHIP_FAMILY_RV200
: return "RV200";
60 case CHIP_FAMILY_RS200
: return "RS200";
61 case CHIP_FAMILY_R200
: return "R200";
62 case CHIP_FAMILY_RV250
: return "RV250";
63 case CHIP_FAMILY_RS300
: return "RS300";
64 case CHIP_FAMILY_RV280
: return "RV280";
65 case CHIP_FAMILY_R300
: return "R300";
66 case CHIP_FAMILY_R350
: return "R350";
67 case CHIP_FAMILY_RV350
: return "RV350";
68 case CHIP_FAMILY_RV380
: return "RV380";
69 case CHIP_FAMILY_R420
: return "R420";
70 case CHIP_FAMILY_RV410
: return "RV410";
71 case CHIP_FAMILY_RS400
: return "RS400";
72 case CHIP_FAMILY_RS600
: return "RS600";
73 case CHIP_FAMILY_RS690
: return "RS690";
74 case CHIP_FAMILY_RS740
: return "RS740";
75 case CHIP_FAMILY_RV515
: return "RV515";
76 case CHIP_FAMILY_R520
: return "R520";
77 case CHIP_FAMILY_RV530
: return "RV530";
78 case CHIP_FAMILY_R580
: return "R580";
79 case CHIP_FAMILY_RV560
: return "RV560";
80 case CHIP_FAMILY_RV570
: return "RV570";
81 case CHIP_FAMILY_R600
: return "R600";
82 case CHIP_FAMILY_RV610
: return "RV610";
83 case CHIP_FAMILY_RV630
: return "RV630";
84 case CHIP_FAMILY_RV670
: return "RV670";
85 case CHIP_FAMILY_RV620
: return "RV620";
86 case CHIP_FAMILY_RV635
: return "RV635";
87 case CHIP_FAMILY_RS780
: return "RS780";
88 case CHIP_FAMILY_RS880
: return "RS880";
89 case CHIP_FAMILY_RV770
: return "RV770";
90 case CHIP_FAMILY_RV730
: return "RV730";
91 case CHIP_FAMILY_RV710
: return "RV710";
92 case CHIP_FAMILY_RV740
: return "RV740";
93 case CHIP_FAMILY_CEDAR
: return "CEDAR";
94 case CHIP_FAMILY_REDWOOD
: return "REDWOOD";
95 case CHIP_FAMILY_JUNIPER
: return "JUNIPER";
96 case CHIP_FAMILY_CYPRESS
: return "CYPRESS";
97 case CHIP_FAMILY_HEMLOCK
: return "HEMLOCK";
98 case CHIP_FAMILY_PALM
: return "PALM";
99 case CHIP_FAMILY_SUMO
: return "SUMO";
100 case CHIP_FAMILY_SUMO2
: return "SUMO2";
101 case CHIP_FAMILY_BARTS
: return "BARTS";
102 case CHIP_FAMILY_TURKS
: return "TURKS";
103 case CHIP_FAMILY_CAICOS
: return "CAICOS";
104 default: return "unknown";
109 /* Return various strings for glGetString().
111 static const GLubyte
*radeonGetString(struct gl_context
* ctx
, GLenum name
)
113 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
114 static char buffer
[128];
118 return (GLubyte
*) "Tungsten Graphics, Inc.";
123 GLuint agp_mode
= (radeon
->radeonScreen
->card_type
==RADEON_CARD_PCI
) ? 0 :
124 radeon
->radeonScreen
->AGPMode
;
125 const char* chipclass
;
126 char hardwarename
[32];
128 if (IS_R200_CLASS(radeon
->radeonScreen
))
133 sprintf(hardwarename
, "%s (%s %04X)",
135 get_chip_family_name(radeon
->radeonScreen
->chip_family
),
136 radeon
->radeonScreen
->device_id
);
138 offset
= driGetRendererString(buffer
, hardwarename
, agp_mode
);
140 sprintf(&buffer
[offset
], " %sTCL",
141 !(radeon
->TclFallback
& RADEON_TCL_FALLBACK_TCL_DISABLE
)
144 strcat(buffer
, " DRI2");
146 return (GLubyte
*) buffer
;
154 /* Initialize the driver's misc functions.
156 static void radeonInitDriverFuncs(struct dd_function_table
*functions
)
158 functions
->GetString
= radeonGetString
;
162 * Create and initialize all common fields of the context,
163 * including the Mesa context itself.
165 GLboolean
radeonInitContext(radeonContextPtr radeon
,
166 struct dd_function_table
* functions
,
167 const struct gl_config
* glVisual
,
168 __DRIcontext
* driContextPriv
,
169 void *sharedContextPrivate
)
171 __DRIscreen
*sPriv
= driContextPriv
->driScreenPriv
;
172 radeonScreenPtr screen
= (radeonScreenPtr
) (sPriv
->driverPrivate
);
173 struct gl_context
* ctx
;
174 struct gl_context
* shareCtx
;
177 /* Fill in additional standard functions. */
178 radeonInitDriverFuncs(functions
);
180 radeon
->radeonScreen
= screen
;
181 /* Allocate and initialize the Mesa context */
182 if (sharedContextPrivate
)
183 shareCtx
= ((radeonContextPtr
)sharedContextPrivate
)->glCtx
;
186 radeon
->glCtx
= _mesa_create_context(API_OPENGL
, glVisual
, shareCtx
,
187 functions
, (void *)radeon
);
192 driContextPriv
->driverPrivate
= radeon
;
194 _mesa_meta_init(ctx
);
197 radeon
->dri
.context
= driContextPriv
;
198 radeon
->dri
.screen
= sPriv
;
199 radeon
->dri
.fd
= sPriv
->fd
;
200 radeon
->dri
.drmMinor
= sPriv
->drm_version
.minor
;
203 fthrottle_mode
= driQueryOptioni(&radeon
->optionCache
, "fthrottle_mode");
204 radeon
->iw
.irq_seq
= -1;
205 radeon
->irqsEmitted
= 0;
206 radeon
->do_irqs
= (fthrottle_mode
== DRI_CONF_FTHROTTLE_IRQS
&&
207 radeon
->radeonScreen
->irq
);
209 radeon
->do_usleeps
= (fthrottle_mode
== DRI_CONF_FTHROTTLE_USLEEPS
);
211 if (!radeon
->do_irqs
)
213 "IRQ's not enabled, falling back to %s: %d %d\n",
214 radeon
->do_usleeps
? "usleeps" : "busy waits",
215 fthrottle_mode
, radeon
->radeonScreen
->irq
);
217 radeon
->texture_depth
= driQueryOptioni (&radeon
->optionCache
,
219 if (radeon
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_FB
)
220 radeon
->texture_depth
= ( glVisual
->rgbBits
> 16 ) ?
221 DRI_CONF_TEXTURE_DEPTH_32
: DRI_CONF_TEXTURE_DEPTH_16
;
223 if (IS_R200_CLASS(radeon
->radeonScreen
) ||
224 IS_R100_CLASS(radeon
->radeonScreen
)) {
225 radeon
->texture_row_align
= 32;
226 radeon
->texture_rect_row_align
= 64;
227 radeon
->texture_compressed_row_align
= 32;
230 radeon_init_dma(radeon
);
238 * Destroy the command buffer and state atoms.
240 static void radeon_destroy_atom_list(radeonContextPtr radeon
)
242 struct radeon_state_atom
*atom
;
244 foreach(atom
, &radeon
->hw
.atomlist
) {
253 * Cleanup common context fields.
254 * Called by r200DestroyContext/r300DestroyContext
256 void radeonDestroyContext(__DRIcontext
*driContextPriv
)
258 #ifdef RADEON_BO_TRACK
261 GET_CURRENT_CONTEXT(ctx
);
262 radeonContextPtr radeon
= (radeonContextPtr
) driContextPriv
->driverPrivate
;
263 radeonContextPtr current
= ctx
? RADEON_CONTEXT(ctx
) : NULL
;
267 _mesa_meta_free(radeon
->glCtx
);
269 if (radeon
== current
) {
270 _mesa_make_current(NULL
, NULL
, NULL
);
273 radeon_firevertices(radeon
);
274 if (!is_empty_list(&radeon
->dma
.reserved
)) {
275 rcommonFlushCmdBuf( radeon
, __FUNCTION__
);
278 radeonFreeDmaRegions(radeon
);
279 radeonReleaseArrays(radeon
->glCtx
, ~0);
280 if (radeon
->vtbl
.free_context
)
281 radeon
->vtbl
.free_context(radeon
->glCtx
);
282 _swsetup_DestroyContext( radeon
->glCtx
);
283 _tnl_DestroyContext( radeon
->glCtx
);
284 _vbo_DestroyContext( radeon
->glCtx
);
285 _swrast_DestroyContext( radeon
->glCtx
);
288 /* free the Mesa context */
289 _mesa_destroy_context(radeon
->glCtx
);
291 /* _mesa_destroy_context() might result in calls to functions that
292 * depend on the DriverCtx, so don't set it to NULL before.
294 * radeon->glCtx->DriverCtx = NULL;
296 /* free the option cache */
297 driDestroyOptionCache(&radeon
->optionCache
);
299 rcommonDestroyCmdBuf(radeon
);
301 radeon_destroy_atom_list(radeon
);
303 if (radeon
->state
.scissor
.pClipRects
) {
304 FREE(radeon
->state
.scissor
.pClipRects
);
305 radeon
->state
.scissor
.pClipRects
= 0;
307 #ifdef RADEON_BO_TRACK
308 track
= fopen("/tmp/tracklog", "w");
310 radeon_tracker_print(&radeon
->radeonScreen
->bom
->tracker
, track
);
317 /* Force the context `c' to be unbound from its buffer.
319 GLboolean
radeonUnbindContext(__DRIcontext
* driContextPriv
)
321 radeonContextPtr radeon
= (radeonContextPtr
) driContextPriv
->driverPrivate
;
323 if (RADEON_DEBUG
& RADEON_DRI
)
324 fprintf(stderr
, "%s ctx %p\n", __FUNCTION__
,
327 /* Unset current context and dispath table */
328 _mesa_make_current(NULL
, NULL
, NULL
);
335 radeon_bits_per_pixel(const struct radeon_renderbuffer
*rb
)
337 return _mesa_get_format_bytes(rb
->base
.Format
) * 8;
341 * Check if drawable has been invalidated by dri2InvalidateDrawable().
342 * Update renderbuffers if so. This prevents a client from accessing
343 * a backbuffer that has a swap pending but not yet completed.
345 * See intel_prepare_render for equivalent code in intel driver.
348 void radeon_prepare_render(radeonContextPtr radeon
)
350 __DRIcontext
*driContext
= radeon
->dri
.context
;
351 __DRIdrawable
*drawable
;
354 screen
= driContext
->driScreenPriv
;
355 if (!screen
->dri2
.loader
)
358 drawable
= driContext
->driDrawablePriv
;
359 if (drawable
->dri2
.stamp
!= driContext
->dri2
.draw_stamp
) {
360 if (drawable
->lastStamp
!= drawable
->dri2
.stamp
)
361 radeon_update_renderbuffers(driContext
, drawable
, GL_FALSE
);
363 /* Intel driver does the equivalent of this, no clue if it is needed:*/
364 radeon_draw_buffer(radeon
->glCtx
, radeon
->glCtx
->DrawBuffer
);
366 driContext
->dri2
.draw_stamp
= drawable
->dri2
.stamp
;
369 drawable
= driContext
->driReadablePriv
;
370 if (drawable
->dri2
.stamp
!= driContext
->dri2
.read_stamp
) {
371 if (drawable
->lastStamp
!= drawable
->dri2
.stamp
)
372 radeon_update_renderbuffers(driContext
, drawable
, GL_FALSE
);
373 driContext
->dri2
.read_stamp
= drawable
->dri2
.stamp
;
376 /* If we're currently rendering to the front buffer, the rendering
377 * that will happen next will probably dirty the front buffer. So
378 * mark it as dirty here.
380 if (radeon
->is_front_buffer_rendering
)
381 radeon
->front_buffer_dirty
= GL_TRUE
;
385 radeon_update_renderbuffers(__DRIcontext
*context
, __DRIdrawable
*drawable
,
386 GLboolean front_only
)
388 unsigned int attachments
[10];
389 __DRIbuffer
*buffers
= NULL
;
391 struct radeon_renderbuffer
*rb
;
393 struct radeon_framebuffer
*draw
;
394 radeonContextPtr radeon
;
396 struct radeon_bo
*depth_bo
= NULL
, *bo
;
398 if (RADEON_DEBUG
& RADEON_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 /* Set this up front, so that in case our buffers get invalidated
406 * while we're getting new buffers, we don't clobber the stamp and
407 * thus ignore the invalidate. */
408 drawable
->lastStamp
= drawable
->dri2
.stamp
;
410 if (screen
->dri2
.loader
411 && (screen
->dri2
.loader
->base
.version
> 2)
412 && (screen
->dri2
.loader
->getBuffersWithFormat
!= NULL
)) {
413 struct radeon_renderbuffer
*depth_rb
;
414 struct radeon_renderbuffer
*stencil_rb
;
417 if ((front_only
|| radeon
->is_front_buffer_rendering
||
418 radeon
->is_front_buffer_reading
||
420 && draw
->color_rb
[0]) {
421 attachments
[i
++] = __DRI_BUFFER_FRONT_LEFT
;
422 attachments
[i
++] = radeon_bits_per_pixel(draw
->color_rb
[0]);
426 if (draw
->color_rb
[1]) {
427 attachments
[i
++] = __DRI_BUFFER_BACK_LEFT
;
428 attachments
[i
++] = radeon_bits_per_pixel(draw
->color_rb
[1]);
431 depth_rb
= radeon_get_renderbuffer(&draw
->base
, BUFFER_DEPTH
);
432 stencil_rb
= radeon_get_renderbuffer(&draw
->base
, BUFFER_STENCIL
);
434 if ((depth_rb
!= NULL
) && (stencil_rb
!= NULL
)) {
435 attachments
[i
++] = __DRI_BUFFER_DEPTH_STENCIL
;
436 attachments
[i
++] = radeon_bits_per_pixel(depth_rb
);
437 } else if (depth_rb
!= NULL
) {
438 attachments
[i
++] = __DRI_BUFFER_DEPTH
;
439 attachments
[i
++] = radeon_bits_per_pixel(depth_rb
);
440 } else if (stencil_rb
!= NULL
) {
441 attachments
[i
++] = __DRI_BUFFER_STENCIL
;
442 attachments
[i
++] = radeon_bits_per_pixel(stencil_rb
);
446 buffers
= (*screen
->dri2
.loader
->getBuffersWithFormat
)(drawable
,
451 drawable
->loaderPrivate
);
452 } else if (screen
->dri2
.loader
) {
454 if (draw
->color_rb
[0])
455 attachments
[i
++] = __DRI_BUFFER_FRONT_LEFT
;
457 if (draw
->color_rb
[1])
458 attachments
[i
++] = __DRI_BUFFER_BACK_LEFT
;
459 if (radeon_get_renderbuffer(&draw
->base
, BUFFER_DEPTH
))
460 attachments
[i
++] = __DRI_BUFFER_DEPTH
;
461 if (radeon_get_renderbuffer(&draw
->base
, BUFFER_STENCIL
))
462 attachments
[i
++] = __DRI_BUFFER_STENCIL
;
465 buffers
= (*screen
->dri2
.loader
->getBuffers
)(drawable
,
470 drawable
->loaderPrivate
);
476 for (i
= 0; i
< count
; i
++) {
477 switch (buffers
[i
].attachment
) {
478 case __DRI_BUFFER_FRONT_LEFT
:
479 rb
= draw
->color_rb
[0];
480 regname
= "dri2 front buffer";
482 case __DRI_BUFFER_FAKE_FRONT_LEFT
:
483 rb
= draw
->color_rb
[0];
484 regname
= "dri2 fake front buffer";
486 case __DRI_BUFFER_BACK_LEFT
:
487 rb
= draw
->color_rb
[1];
488 regname
= "dri2 back buffer";
490 case __DRI_BUFFER_DEPTH
:
491 rb
= radeon_get_renderbuffer(&draw
->base
, BUFFER_DEPTH
);
492 regname
= "dri2 depth buffer";
494 case __DRI_BUFFER_DEPTH_STENCIL
:
495 rb
= radeon_get_renderbuffer(&draw
->base
, BUFFER_DEPTH
);
496 regname
= "dri2 depth / stencil buffer";
498 case __DRI_BUFFER_STENCIL
:
499 rb
= radeon_get_renderbuffer(&draw
->base
, BUFFER_STENCIL
);
500 regname
= "dri2 stencil buffer";
502 case __DRI_BUFFER_ACCUM
:
505 "unhandled buffer attach event, attacment type %d\n",
506 buffers
[i
].attachment
);
514 uint32_t name
= radeon_gem_name_bo(rb
->bo
);
515 if (name
== buffers
[i
].name
)
519 if (RADEON_DEBUG
& RADEON_DRI
)
521 "attaching buffer %s, %d, at %d, cpp %d, pitch %d\n",
522 regname
, buffers
[i
].name
, buffers
[i
].attachment
,
523 buffers
[i
].cpp
, buffers
[i
].pitch
);
525 rb
->cpp
= buffers
[i
].cpp
;
526 rb
->pitch
= buffers
[i
].pitch
;
527 rb
->base
.Width
= drawable
->w
;
528 rb
->base
.Height
= drawable
->h
;
531 if (buffers
[i
].attachment
== __DRI_BUFFER_STENCIL
&& depth_bo
) {
532 if (RADEON_DEBUG
& RADEON_DRI
)
533 fprintf(stderr
, "(reusing depth buffer as stencil)\n");
537 uint32_t tiling_flags
= 0, pitch
= 0;
540 bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
544 RADEON_GEM_DOMAIN_VRAM
,
548 fprintf(stderr
, "failed to attach %s %d\n",
549 regname
, buffers
[i
].name
);
553 ret
= radeon_bo_get_tiling(bo
, &tiling_flags
, &pitch
);
556 "failed to get tiling for %s %d\n",
557 regname
, buffers
[i
].name
);
562 if (tiling_flags
& RADEON_TILING_MACRO
)
563 bo
->flags
|= RADEON_BO_FLAGS_MACRO_TILE
;
564 if (tiling_flags
& RADEON_TILING_MICRO
)
565 bo
->flags
|= RADEON_BO_FLAGS_MICRO_TILE
;
569 if (buffers
[i
].attachment
== __DRI_BUFFER_DEPTH
) {
570 if (draw
->base
.Visual
.depthBits
== 16)
575 radeon_renderbuffer_set_bo(rb
, bo
);
578 if (buffers
[i
].attachment
== __DRI_BUFFER_DEPTH_STENCIL
) {
579 rb
= radeon_get_renderbuffer(&draw
->base
, BUFFER_STENCIL
);
581 struct radeon_bo
*stencil_bo
= NULL
;
584 uint32_t name
= radeon_gem_name_bo(rb
->bo
);
585 if (name
== buffers
[i
].name
)
590 radeon_bo_ref(stencil_bo
);
591 radeon_renderbuffer_set_bo(rb
, stencil_bo
);
592 radeon_bo_unref(stencil_bo
);
597 driUpdateFramebufferSize(radeon
->glCtx
, drawable
);
600 /* Force the context `c' to be the current context and associate with it
603 GLboolean
radeonMakeCurrent(__DRIcontext
* driContextPriv
,
604 __DRIdrawable
* driDrawPriv
,
605 __DRIdrawable
* driReadPriv
)
607 radeonContextPtr radeon
;
608 struct gl_framebuffer
*drfb
, *readfb
;
610 if (!driContextPriv
) {
611 if (RADEON_DEBUG
& RADEON_DRI
)
612 fprintf(stderr
, "%s ctx is null\n", __FUNCTION__
);
613 _mesa_make_current(NULL
, NULL
, NULL
);
617 radeon
= (radeonContextPtr
) driContextPriv
->driverPrivate
;
619 if(driDrawPriv
== NULL
&& driReadPriv
== NULL
) {
620 drfb
= _mesa_create_framebuffer(&radeon
->glCtx
->Visual
);
624 drfb
= driDrawPriv
->driverPrivate
;
625 readfb
= driReadPriv
->driverPrivate
;
629 radeon_update_renderbuffers(driContextPriv
, driDrawPriv
, GL_FALSE
);
630 if (driDrawPriv
!= driReadPriv
)
631 radeon_update_renderbuffers(driContextPriv
, driReadPriv
, GL_FALSE
);
632 _mesa_reference_renderbuffer(&radeon
->state
.color
.rb
,
633 &(radeon_get_renderbuffer(drfb
, BUFFER_BACK_LEFT
)->base
));
634 _mesa_reference_renderbuffer(&radeon
->state
.depth
.rb
,
635 &(radeon_get_renderbuffer(drfb
, BUFFER_DEPTH
)->base
));
637 if (RADEON_DEBUG
& RADEON_DRI
)
638 fprintf(stderr
, "%s ctx %p dfb %p rfb %p\n", __FUNCTION__
, radeon
->glCtx
, drfb
, readfb
);
641 driUpdateFramebufferSize(radeon
->glCtx
, driDrawPriv
);
642 if (driReadPriv
!= driDrawPriv
)
643 driUpdateFramebufferSize(radeon
->glCtx
, driReadPriv
);
645 _mesa_make_current(radeon
->glCtx
, drfb
, readfb
);
646 if (driDrawPriv
== NULL
&& driReadPriv
== NULL
)
647 _mesa_reference_framebuffer(&drfb
, NULL
);
649 _mesa_update_state(radeon
->glCtx
);
651 if (radeon
->glCtx
->DrawBuffer
== drfb
) {
652 if(driDrawPriv
!= NULL
) {
653 radeon_window_moved(radeon
);
656 radeon_draw_buffer(radeon
->glCtx
, drfb
);
660 if (RADEON_DEBUG
& RADEON_DRI
)
661 fprintf(stderr
, "End %s\n", __FUNCTION__
);