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/fbobject.h"
42 #include "main/renderbuffer.h"
43 #include "main/state.h"
44 #include "main/simple_list.h"
45 #include "swrast/swrast.h"
46 #include "swrast_setup/swrast_setup.h"
50 int RADEON_DEBUG
= (0);
54 static const char* get_chip_family_name(int chip_family
)
57 #if defined(RADEON_R100)
58 case CHIP_FAMILY_R100
: return "R100";
59 case CHIP_FAMILY_RV100
: return "RV100";
60 case CHIP_FAMILY_RS100
: return "RS100";
61 case CHIP_FAMILY_RV200
: return "RV200";
62 case CHIP_FAMILY_RS200
: return "RS200";
63 #elif defined(RADEON_R200)
64 case CHIP_FAMILY_R200
: return "R200";
65 case CHIP_FAMILY_RV250
: return "RV250";
66 case CHIP_FAMILY_RS300
: return "RS300";
67 case CHIP_FAMILY_RV280
: return "RV280";
69 default: return "unknown";
74 /* Return various strings for glGetString().
76 static const GLubyte
*radeonGetString(struct gl_context
* ctx
, GLenum name
)
78 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
79 static char buffer
[128];
83 return (GLubyte
*) "Mesa Project";
88 GLuint agp_mode
= (radeon
->radeonScreen
->card_type
==RADEON_CARD_PCI
) ? 0 :
89 radeon
->radeonScreen
->AGPMode
;
90 char hardwarename
[32];
92 sprintf(hardwarename
, "%s (%s %04X)",
93 #if defined(RADEON_R100)
95 #elif defined(RADEON_R200)
98 get_chip_family_name(radeon
->radeonScreen
->chip_family
),
99 radeon
->radeonScreen
->device_id
);
101 offset
= driGetRendererString(buffer
, hardwarename
, agp_mode
);
103 sprintf(&buffer
[offset
], " %sTCL",
104 !(radeon
->TclFallback
& RADEON_TCL_FALLBACK_TCL_DISABLE
)
107 strcat(buffer
, " DRI2");
109 return (GLubyte
*) buffer
;
117 /* Initialize the driver's misc functions.
119 static void radeonInitDriverFuncs(struct dd_function_table
*functions
)
121 functions
->GetString
= radeonGetString
;
125 * Create and initialize all common fields of the context,
126 * including the Mesa context itself.
128 GLboolean
radeonInitContext(radeonContextPtr radeon
,
129 struct dd_function_table
* functions
,
130 const struct gl_config
* glVisual
,
131 __DRIcontext
* driContextPriv
,
132 void *sharedContextPrivate
)
134 __DRIscreen
*sPriv
= driContextPriv
->driScreenPriv
;
135 radeonScreenPtr screen
= (radeonScreenPtr
) (sPriv
->driverPrivate
);
136 struct gl_context
* ctx
;
137 struct gl_context
* shareCtx
;
140 /* Fill in additional standard functions. */
141 radeonInitDriverFuncs(functions
);
143 radeon
->radeonScreen
= screen
;
144 /* Allocate and initialize the Mesa context */
145 if (sharedContextPrivate
)
146 shareCtx
= &((radeonContextPtr
)sharedContextPrivate
)->glCtx
;
150 if (!_mesa_initialize_context(&radeon
->glCtx
, API_OPENGL_COMPAT
,
155 ctx
= &radeon
->glCtx
;
156 driContextPriv
->driverPrivate
= radeon
;
158 _mesa_meta_init(ctx
);
161 radeon
->dri
.context
= driContextPriv
;
162 radeon
->dri
.screen
= sPriv
;
163 radeon
->dri
.fd
= sPriv
->fd
;
164 radeon
->dri
.drmMinor
= sPriv
->drm_version
.minor
;
167 fthrottle_mode
= driQueryOptioni(&radeon
->optionCache
, "fthrottle_mode");
168 radeon
->iw
.irq_seq
= -1;
169 radeon
->irqsEmitted
= 0;
170 radeon
->do_irqs
= (fthrottle_mode
== DRI_CONF_FTHROTTLE_IRQS
&&
171 radeon
->radeonScreen
->irq
);
173 radeon
->do_usleeps
= (fthrottle_mode
== DRI_CONF_FTHROTTLE_USLEEPS
);
175 if (!radeon
->do_irqs
)
177 "IRQ's not enabled, falling back to %s: %d %d\n",
178 radeon
->do_usleeps
? "usleeps" : "busy waits",
179 fthrottle_mode
, radeon
->radeonScreen
->irq
);
181 radeon
->texture_depth
= driQueryOptioni (&radeon
->optionCache
,
183 if (radeon
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_FB
)
184 radeon
->texture_depth
= ( glVisual
->rgbBits
> 16 ) ?
185 DRI_CONF_TEXTURE_DEPTH_32
: DRI_CONF_TEXTURE_DEPTH_16
;
187 radeon
->texture_row_align
= 32;
188 radeon
->texture_rect_row_align
= 64;
189 radeon
->texture_compressed_row_align
= 32;
191 radeon_init_dma(radeon
);
199 * Destroy the command buffer and state atoms.
201 static void radeon_destroy_atom_list(radeonContextPtr radeon
)
203 struct radeon_state_atom
*atom
;
205 foreach(atom
, &radeon
->hw
.atomlist
) {
213 * Cleanup common context fields.
214 * Called by r200DestroyContext
216 void radeonDestroyContext(__DRIcontext
*driContextPriv
)
218 #ifdef RADEON_BO_TRACK
221 GET_CURRENT_CONTEXT(ctx
);
222 radeonContextPtr radeon
= (radeonContextPtr
) driContextPriv
->driverPrivate
;
223 radeonContextPtr current
= ctx
? RADEON_CONTEXT(ctx
) : NULL
;
227 _mesa_meta_free(&radeon
->glCtx
);
229 if (radeon
== current
) {
230 _mesa_make_current(NULL
, NULL
, NULL
);
233 radeon_firevertices(radeon
);
234 if (!is_empty_list(&radeon
->dma
.reserved
)) {
235 rcommonFlushCmdBuf( radeon
, __FUNCTION__
);
238 radeonFreeDmaRegions(radeon
);
239 radeonReleaseArrays(&radeon
->glCtx
, ~0);
240 if (radeon
->vtbl
.free_context
)
241 radeon
->vtbl
.free_context(&radeon
->glCtx
);
242 _swsetup_DestroyContext( &radeon
->glCtx
);
243 _tnl_DestroyContext( &radeon
->glCtx
);
244 _vbo_DestroyContext( &radeon
->glCtx
);
245 _swrast_DestroyContext( &radeon
->glCtx
);
248 /* free the Mesa context data */
249 _mesa_free_context_data(&radeon
->glCtx
);
251 /* free the option cache */
252 driDestroyOptionCache(&radeon
->optionCache
);
254 rcommonDestroyCmdBuf(radeon
);
256 radeon_destroy_atom_list(radeon
);
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(__DRIcontext
* driContextPriv
)
272 radeonContextPtr radeon
= (radeonContextPtr
) driContextPriv
->driverPrivate
;
274 if (RADEON_DEBUG
& RADEON_DRI
)
275 fprintf(stderr
, "%s ctx %p\n", __FUNCTION__
,
278 /* Unset current context and dispath table */
279 _mesa_make_current(NULL
, NULL
, NULL
);
286 radeon_bits_per_pixel(const struct radeon_renderbuffer
*rb
)
288 return _mesa_get_format_bytes(rb
->base
.Base
.Format
) * 8;
292 * Check if drawable has been invalidated by dri2InvalidateDrawable().
293 * Update renderbuffers if so. This prevents a client from accessing
294 * a backbuffer that has a swap pending but not yet completed.
296 * See intel_prepare_render for equivalent code in intel driver.
299 void radeon_prepare_render(radeonContextPtr radeon
)
301 __DRIcontext
*driContext
= radeon
->dri
.context
;
302 __DRIdrawable
*drawable
;
305 screen
= driContext
->driScreenPriv
;
306 if (!screen
->dri2
.loader
)
309 drawable
= driContext
->driDrawablePriv
;
310 if (drawable
->dri2
.stamp
!= driContext
->dri2
.draw_stamp
) {
311 if (drawable
->lastStamp
!= drawable
->dri2
.stamp
)
312 radeon_update_renderbuffers(driContext
, drawable
, GL_FALSE
);
314 /* Intel driver does the equivalent of this, no clue if it is needed:*/
315 radeon_draw_buffer(&radeon
->glCtx
, radeon
->glCtx
.DrawBuffer
);
317 driContext
->dri2
.draw_stamp
= drawable
->dri2
.stamp
;
320 drawable
= driContext
->driReadablePriv
;
321 if (drawable
->dri2
.stamp
!= driContext
->dri2
.read_stamp
) {
322 if (drawable
->lastStamp
!= drawable
->dri2
.stamp
)
323 radeon_update_renderbuffers(driContext
, drawable
, GL_FALSE
);
324 driContext
->dri2
.read_stamp
= drawable
->dri2
.stamp
;
327 /* If we're currently rendering to the front buffer, the rendering
328 * that will happen next will probably dirty the front buffer. So
329 * mark it as dirty here.
331 if (radeon
->is_front_buffer_rendering
)
332 radeon
->front_buffer_dirty
= GL_TRUE
;
336 radeon_update_renderbuffers(__DRIcontext
*context
, __DRIdrawable
*drawable
,
337 GLboolean front_only
)
339 unsigned int attachments
[10];
340 __DRIbuffer
*buffers
= NULL
;
342 struct radeon_renderbuffer
*rb
;
344 struct radeon_framebuffer
*draw
;
345 radeonContextPtr radeon
;
347 struct radeon_bo
*depth_bo
= NULL
, *bo
;
349 if (RADEON_DEBUG
& RADEON_DRI
)
350 fprintf(stderr
, "enter %s, drawable %p\n", __func__
, drawable
);
352 draw
= drawable
->driverPrivate
;
353 screen
= context
->driScreenPriv
;
354 radeon
= (radeonContextPtr
) context
->driverPrivate
;
356 /* Set this up front, so that in case our buffers get invalidated
357 * while we're getting new buffers, we don't clobber the stamp and
358 * thus ignore the invalidate. */
359 drawable
->lastStamp
= drawable
->dri2
.stamp
;
361 if (screen
->dri2
.loader
362 && (screen
->dri2
.loader
->base
.version
> 2)
363 && (screen
->dri2
.loader
->getBuffersWithFormat
!= NULL
)) {
364 struct radeon_renderbuffer
*depth_rb
;
365 struct radeon_renderbuffer
*stencil_rb
;
368 if ((front_only
|| radeon
->is_front_buffer_rendering
||
369 radeon
->is_front_buffer_reading
||
371 && draw
->color_rb
[0]) {
372 attachments
[i
++] = __DRI_BUFFER_FRONT_LEFT
;
373 attachments
[i
++] = radeon_bits_per_pixel(draw
->color_rb
[0]);
377 if (draw
->color_rb
[1]) {
378 attachments
[i
++] = __DRI_BUFFER_BACK_LEFT
;
379 attachments
[i
++] = radeon_bits_per_pixel(draw
->color_rb
[1]);
382 depth_rb
= radeon_get_renderbuffer(&draw
->base
, BUFFER_DEPTH
);
383 stencil_rb
= radeon_get_renderbuffer(&draw
->base
, BUFFER_STENCIL
);
385 if ((depth_rb
!= NULL
) && (stencil_rb
!= NULL
)) {
386 attachments
[i
++] = __DRI_BUFFER_DEPTH_STENCIL
;
387 attachments
[i
++] = radeon_bits_per_pixel(depth_rb
);
388 } else if (depth_rb
!= NULL
) {
389 attachments
[i
++] = __DRI_BUFFER_DEPTH
;
390 attachments
[i
++] = radeon_bits_per_pixel(depth_rb
);
391 } else if (stencil_rb
!= NULL
) {
392 attachments
[i
++] = __DRI_BUFFER_STENCIL
;
393 attachments
[i
++] = radeon_bits_per_pixel(stencil_rb
);
397 buffers
= (*screen
->dri2
.loader
->getBuffersWithFormat
)(drawable
,
402 drawable
->loaderPrivate
);
403 } else if (screen
->dri2
.loader
) {
405 if (draw
->color_rb
[0])
406 attachments
[i
++] = __DRI_BUFFER_FRONT_LEFT
;
408 if (draw
->color_rb
[1])
409 attachments
[i
++] = __DRI_BUFFER_BACK_LEFT
;
410 if (radeon_get_renderbuffer(&draw
->base
, BUFFER_DEPTH
))
411 attachments
[i
++] = __DRI_BUFFER_DEPTH
;
412 if (radeon_get_renderbuffer(&draw
->base
, BUFFER_STENCIL
))
413 attachments
[i
++] = __DRI_BUFFER_STENCIL
;
416 buffers
= (*screen
->dri2
.loader
->getBuffers
)(drawable
,
421 drawable
->loaderPrivate
);
427 for (i
= 0; i
< count
; i
++) {
428 switch (buffers
[i
].attachment
) {
429 case __DRI_BUFFER_FRONT_LEFT
:
430 rb
= draw
->color_rb
[0];
431 regname
= "dri2 front buffer";
433 case __DRI_BUFFER_FAKE_FRONT_LEFT
:
434 rb
= draw
->color_rb
[0];
435 regname
= "dri2 fake front buffer";
437 case __DRI_BUFFER_BACK_LEFT
:
438 rb
= draw
->color_rb
[1];
439 regname
= "dri2 back buffer";
441 case __DRI_BUFFER_DEPTH
:
442 rb
= radeon_get_renderbuffer(&draw
->base
, BUFFER_DEPTH
);
443 regname
= "dri2 depth buffer";
445 case __DRI_BUFFER_DEPTH_STENCIL
:
446 rb
= radeon_get_renderbuffer(&draw
->base
, BUFFER_DEPTH
);
447 regname
= "dri2 depth / stencil buffer";
449 case __DRI_BUFFER_STENCIL
:
450 rb
= radeon_get_renderbuffer(&draw
->base
, BUFFER_STENCIL
);
451 regname
= "dri2 stencil buffer";
453 case __DRI_BUFFER_ACCUM
:
456 "unhandled buffer attach event, attacment type %d\n",
457 buffers
[i
].attachment
);
465 uint32_t name
= radeon_gem_name_bo(rb
->bo
);
466 if (name
== buffers
[i
].name
)
470 if (RADEON_DEBUG
& RADEON_DRI
)
472 "attaching buffer %s, %d, at %d, cpp %d, pitch %d\n",
473 regname
, buffers
[i
].name
, buffers
[i
].attachment
,
474 buffers
[i
].cpp
, buffers
[i
].pitch
);
476 rb
->cpp
= buffers
[i
].cpp
;
477 rb
->pitch
= buffers
[i
].pitch
;
478 rb
->base
.Base
.Width
= drawable
->w
;
479 rb
->base
.Base
.Height
= drawable
->h
;
482 if (buffers
[i
].attachment
== __DRI_BUFFER_STENCIL
&& depth_bo
) {
483 if (RADEON_DEBUG
& RADEON_DRI
)
484 fprintf(stderr
, "(reusing depth buffer as stencil)\n");
488 uint32_t tiling_flags
= 0, pitch
= 0;
491 bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
495 RADEON_GEM_DOMAIN_VRAM
,
499 fprintf(stderr
, "failed to attach %s %d\n",
500 regname
, buffers
[i
].name
);
504 ret
= radeon_bo_get_tiling(bo
, &tiling_flags
, &pitch
);
507 "failed to get tiling for %s %d\n",
508 regname
, buffers
[i
].name
);
513 if (tiling_flags
& RADEON_TILING_MACRO
)
514 bo
->flags
|= RADEON_BO_FLAGS_MACRO_TILE
;
515 if (tiling_flags
& RADEON_TILING_MICRO
)
516 bo
->flags
|= RADEON_BO_FLAGS_MICRO_TILE
;
520 if (buffers
[i
].attachment
== __DRI_BUFFER_DEPTH
) {
521 if (draw
->base
.Visual
.depthBits
== 16)
526 radeon_renderbuffer_set_bo(rb
, bo
);
529 if (buffers
[i
].attachment
== __DRI_BUFFER_DEPTH_STENCIL
) {
530 rb
= radeon_get_renderbuffer(&draw
->base
, BUFFER_STENCIL
);
532 struct radeon_bo
*stencil_bo
= NULL
;
535 uint32_t name
= radeon_gem_name_bo(rb
->bo
);
536 if (name
== buffers
[i
].name
)
541 radeon_bo_ref(stencil_bo
);
542 radeon_renderbuffer_set_bo(rb
, stencil_bo
);
543 radeon_bo_unref(stencil_bo
);
548 driUpdateFramebufferSize(&radeon
->glCtx
, drawable
);
551 /* Force the context `c' to be the current context and associate with it
554 GLboolean
radeonMakeCurrent(__DRIcontext
* driContextPriv
,
555 __DRIdrawable
* driDrawPriv
,
556 __DRIdrawable
* driReadPriv
)
558 radeonContextPtr radeon
;
559 GET_CURRENT_CONTEXT(curCtx
);
560 struct gl_framebuffer
*drfb
, *readfb
;
563 radeon
= (radeonContextPtr
)driContextPriv
->driverPrivate
;
566 /* According to the glXMakeCurrent() man page: "Pending commands to
567 * the previous context, if any, are flushed before it is released."
568 * But only flush if we're actually changing contexts.
571 if ((radeonContextPtr
)curCtx
&& (radeonContextPtr
)curCtx
!= radeon
) {
575 if (!driContextPriv
) {
576 if (RADEON_DEBUG
& RADEON_DRI
)
577 fprintf(stderr
, "%s ctx is null\n", __FUNCTION__
);
578 _mesa_make_current(NULL
, NULL
, NULL
);
582 if(driDrawPriv
== NULL
&& driReadPriv
== NULL
) {
583 drfb
= _mesa_create_framebuffer(&radeon
->glCtx
.Visual
);
587 drfb
= driDrawPriv
->driverPrivate
;
588 readfb
= driReadPriv
->driverPrivate
;
592 radeon_update_renderbuffers(driContextPriv
, driDrawPriv
, GL_FALSE
);
593 if (driDrawPriv
!= driReadPriv
)
594 radeon_update_renderbuffers(driContextPriv
, driReadPriv
, GL_FALSE
);
595 _mesa_reference_renderbuffer(&radeon
->state
.color
.rb
,
596 &(radeon_get_renderbuffer(drfb
, BUFFER_BACK_LEFT
)->base
.Base
));
597 _mesa_reference_renderbuffer(&radeon
->state
.depth
.rb
,
598 &(radeon_get_renderbuffer(drfb
, BUFFER_DEPTH
)->base
.Base
));
600 if (RADEON_DEBUG
& RADEON_DRI
)
601 fprintf(stderr
, "%s ctx %p dfb %p rfb %p\n", __FUNCTION__
, &radeon
->glCtx
, drfb
, readfb
);
604 driUpdateFramebufferSize(&radeon
->glCtx
, driDrawPriv
);
605 if (driReadPriv
!= driDrawPriv
)
606 driUpdateFramebufferSize(&radeon
->glCtx
, driReadPriv
);
608 _mesa_make_current(&radeon
->glCtx
, drfb
, readfb
);
609 if (driDrawPriv
== NULL
&& driReadPriv
== NULL
)
610 _mesa_reference_framebuffer(&drfb
, NULL
);
612 _mesa_update_state(&radeon
->glCtx
);
614 if (radeon
->glCtx
.DrawBuffer
== drfb
) {
615 if(driDrawPriv
!= NULL
) {
616 radeon_window_moved(radeon
);
619 radeon_draw_buffer(&radeon
->glCtx
, drfb
);
623 if (RADEON_DEBUG
& RADEON_DRI
)
624 fprintf(stderr
, "End %s\n", __FUNCTION__
);