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
,
130 struct dd_function_table
* functions
,
131 const struct gl_config
* glVisual
,
132 __DRIcontext
* driContextPriv
,
133 void *sharedContextPrivate
)
135 __DRIscreen
*sPriv
= driContextPriv
->driScreenPriv
;
136 radeonScreenPtr screen
= (radeonScreenPtr
) (sPriv
->driverPrivate
);
137 struct gl_context
* ctx
;
138 struct gl_context
* shareCtx
;
141 /* Fill in additional standard functions. */
142 radeonInitDriverFuncs(functions
);
144 radeon
->radeonScreen
= screen
;
145 /* Allocate and initialize the Mesa context */
146 if (sharedContextPrivate
)
147 shareCtx
= &((radeonContextPtr
)sharedContextPrivate
)->glCtx
;
151 if (!_mesa_initialize_context(&radeon
->glCtx
, api
,
156 ctx
= &radeon
->glCtx
;
157 driContextPriv
->driverPrivate
= radeon
;
159 _mesa_meta_init(ctx
);
162 radeon
->dri
.context
= driContextPriv
;
163 radeon
->dri
.screen
= sPriv
;
164 radeon
->dri
.fd
= sPriv
->fd
;
165 radeon
->dri
.drmMinor
= sPriv
->drm_version
.minor
;
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 radeon
->texture_depth
= driQueryOptioni (&radeon
->optionCache
,
184 if (radeon
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_FB
)
185 radeon
->texture_depth
= ( glVisual
->rgbBits
> 16 ) ?
186 DRI_CONF_TEXTURE_DEPTH_32
: DRI_CONF_TEXTURE_DEPTH_16
;
188 radeon
->texture_row_align
= 32;
189 radeon
->texture_rect_row_align
= 64;
190 radeon
->texture_compressed_row_align
= 32;
192 radeon_init_dma(radeon
);
200 * Destroy the command buffer and state atoms.
202 static void radeon_destroy_atom_list(radeonContextPtr radeon
)
204 struct radeon_state_atom
*atom
;
206 foreach(atom
, &radeon
->hw
.atomlist
) {
214 * Cleanup common context fields.
215 * Called by r200DestroyContext
217 void radeonDestroyContext(__DRIcontext
*driContextPriv
)
219 #ifdef RADEON_BO_TRACK
222 GET_CURRENT_CONTEXT(ctx
);
223 radeonContextPtr radeon
= (radeonContextPtr
) driContextPriv
->driverPrivate
;
224 radeonContextPtr current
= ctx
? RADEON_CONTEXT(ctx
) : NULL
;
228 _mesa_meta_free(&radeon
->glCtx
);
230 if (radeon
== current
) {
231 _mesa_make_current(NULL
, NULL
, NULL
);
234 radeon_firevertices(radeon
);
235 if (!is_empty_list(&radeon
->dma
.reserved
)) {
236 rcommonFlushCmdBuf( radeon
, __FUNCTION__
);
239 radeonFreeDmaRegions(radeon
);
240 radeonReleaseArrays(&radeon
->glCtx
, ~0);
241 if (radeon
->vtbl
.free_context
)
242 radeon
->vtbl
.free_context(&radeon
->glCtx
);
243 _swsetup_DestroyContext( &radeon
->glCtx
);
244 _tnl_DestroyContext( &radeon
->glCtx
);
245 _vbo_DestroyContext( &radeon
->glCtx
);
246 _swrast_DestroyContext( &radeon
->glCtx
);
249 /* free the Mesa context data */
250 _mesa_free_context_data(&radeon
->glCtx
);
252 /* free the option cache */
253 driDestroyOptionCache(&radeon
->optionCache
);
255 rcommonDestroyCmdBuf(radeon
);
257 radeon_destroy_atom_list(radeon
);
259 #ifdef RADEON_BO_TRACK
260 track
= fopen("/tmp/tracklog", "w");
262 radeon_tracker_print(&radeon
->radeonScreen
->bom
->tracker
, track
);
269 /* Force the context `c' to be unbound from its buffer.
271 GLboolean
radeonUnbindContext(__DRIcontext
* driContextPriv
)
273 radeonContextPtr radeon
= (radeonContextPtr
) driContextPriv
->driverPrivate
;
275 if (RADEON_DEBUG
& RADEON_DRI
)
276 fprintf(stderr
, "%s ctx %p\n", __FUNCTION__
,
279 /* Unset current context and dispath table */
280 _mesa_make_current(NULL
, NULL
, NULL
);
287 radeon_bits_per_pixel(const struct radeon_renderbuffer
*rb
)
289 return _mesa_get_format_bytes(rb
->base
.Base
.Format
) * 8;
293 * Check if drawable has been invalidated by dri2InvalidateDrawable().
294 * Update renderbuffers if so. This prevents a client from accessing
295 * a backbuffer that has a swap pending but not yet completed.
297 * See intel_prepare_render for equivalent code in intel driver.
300 void radeon_prepare_render(radeonContextPtr radeon
)
302 __DRIcontext
*driContext
= radeon
->dri
.context
;
303 __DRIdrawable
*drawable
;
306 screen
= driContext
->driScreenPriv
;
307 if (!screen
->dri2
.loader
)
310 drawable
= driContext
->driDrawablePriv
;
311 if (drawable
->dri2
.stamp
!= driContext
->dri2
.draw_stamp
) {
312 if (drawable
->lastStamp
!= drawable
->dri2
.stamp
)
313 radeon_update_renderbuffers(driContext
, drawable
, GL_FALSE
);
315 /* Intel driver does the equivalent of this, no clue if it is needed:*/
316 radeon_draw_buffer(&radeon
->glCtx
, radeon
->glCtx
.DrawBuffer
);
318 driContext
->dri2
.draw_stamp
= drawable
->dri2
.stamp
;
321 drawable
= driContext
->driReadablePriv
;
322 if (drawable
->dri2
.stamp
!= driContext
->dri2
.read_stamp
) {
323 if (drawable
->lastStamp
!= drawable
->dri2
.stamp
)
324 radeon_update_renderbuffers(driContext
, drawable
, GL_FALSE
);
325 driContext
->dri2
.read_stamp
= drawable
->dri2
.stamp
;
328 /* If we're currently rendering to the front buffer, the rendering
329 * that will happen next will probably dirty the front buffer. So
330 * mark it as dirty here.
332 if (radeon
->is_front_buffer_rendering
)
333 radeon
->front_buffer_dirty
= GL_TRUE
;
337 radeon_update_renderbuffers(__DRIcontext
*context
, __DRIdrawable
*drawable
,
338 GLboolean front_only
)
340 unsigned int attachments
[10];
341 __DRIbuffer
*buffers
= NULL
;
343 struct radeon_renderbuffer
*rb
;
345 struct radeon_framebuffer
*draw
;
346 radeonContextPtr radeon
;
348 struct radeon_bo
*depth_bo
= NULL
, *bo
;
350 if (RADEON_DEBUG
& RADEON_DRI
)
351 fprintf(stderr
, "enter %s, drawable %p\n", __func__
, drawable
);
353 draw
= drawable
->driverPrivate
;
354 screen
= context
->driScreenPriv
;
355 radeon
= (radeonContextPtr
) context
->driverPrivate
;
357 /* Set this up front, so that in case our buffers get invalidated
358 * while we're getting new buffers, we don't clobber the stamp and
359 * thus ignore the invalidate. */
360 drawable
->lastStamp
= drawable
->dri2
.stamp
;
362 if (screen
->dri2
.loader
363 && (screen
->dri2
.loader
->base
.version
> 2)
364 && (screen
->dri2
.loader
->getBuffersWithFormat
!= NULL
)) {
365 struct radeon_renderbuffer
*depth_rb
;
366 struct radeon_renderbuffer
*stencil_rb
;
369 if ((front_only
|| radeon
->is_front_buffer_rendering
||
370 radeon
->is_front_buffer_reading
||
372 && draw
->color_rb
[0]) {
373 attachments
[i
++] = __DRI_BUFFER_FRONT_LEFT
;
374 attachments
[i
++] = radeon_bits_per_pixel(draw
->color_rb
[0]);
378 if (draw
->color_rb
[1]) {
379 attachments
[i
++] = __DRI_BUFFER_BACK_LEFT
;
380 attachments
[i
++] = radeon_bits_per_pixel(draw
->color_rb
[1]);
383 depth_rb
= radeon_get_renderbuffer(&draw
->base
, BUFFER_DEPTH
);
384 stencil_rb
= radeon_get_renderbuffer(&draw
->base
, BUFFER_STENCIL
);
386 if ((depth_rb
!= NULL
) && (stencil_rb
!= NULL
)) {
387 attachments
[i
++] = __DRI_BUFFER_DEPTH_STENCIL
;
388 attachments
[i
++] = radeon_bits_per_pixel(depth_rb
);
389 } else if (depth_rb
!= NULL
) {
390 attachments
[i
++] = __DRI_BUFFER_DEPTH
;
391 attachments
[i
++] = radeon_bits_per_pixel(depth_rb
);
392 } else if (stencil_rb
!= NULL
) {
393 attachments
[i
++] = __DRI_BUFFER_STENCIL
;
394 attachments
[i
++] = radeon_bits_per_pixel(stencil_rb
);
398 buffers
= (*screen
->dri2
.loader
->getBuffersWithFormat
)(drawable
,
403 drawable
->loaderPrivate
);
404 } else if (screen
->dri2
.loader
) {
406 if (draw
->color_rb
[0])
407 attachments
[i
++] = __DRI_BUFFER_FRONT_LEFT
;
409 if (draw
->color_rb
[1])
410 attachments
[i
++] = __DRI_BUFFER_BACK_LEFT
;
411 if (radeon_get_renderbuffer(&draw
->base
, BUFFER_DEPTH
))
412 attachments
[i
++] = __DRI_BUFFER_DEPTH
;
413 if (radeon_get_renderbuffer(&draw
->base
, BUFFER_STENCIL
))
414 attachments
[i
++] = __DRI_BUFFER_STENCIL
;
417 buffers
= (*screen
->dri2
.loader
->getBuffers
)(drawable
,
422 drawable
->loaderPrivate
);
428 for (i
= 0; i
< count
; i
++) {
429 switch (buffers
[i
].attachment
) {
430 case __DRI_BUFFER_FRONT_LEFT
:
431 rb
= draw
->color_rb
[0];
432 regname
= "dri2 front buffer";
434 case __DRI_BUFFER_FAKE_FRONT_LEFT
:
435 rb
= draw
->color_rb
[0];
436 regname
= "dri2 fake front buffer";
438 case __DRI_BUFFER_BACK_LEFT
:
439 rb
= draw
->color_rb
[1];
440 regname
= "dri2 back buffer";
442 case __DRI_BUFFER_DEPTH
:
443 rb
= radeon_get_renderbuffer(&draw
->base
, BUFFER_DEPTH
);
444 regname
= "dri2 depth buffer";
446 case __DRI_BUFFER_DEPTH_STENCIL
:
447 rb
= radeon_get_renderbuffer(&draw
->base
, BUFFER_DEPTH
);
448 regname
= "dri2 depth / stencil buffer";
450 case __DRI_BUFFER_STENCIL
:
451 rb
= radeon_get_renderbuffer(&draw
->base
, BUFFER_STENCIL
);
452 regname
= "dri2 stencil buffer";
454 case __DRI_BUFFER_ACCUM
:
457 "unhandled buffer attach event, attacment type %d\n",
458 buffers
[i
].attachment
);
466 uint32_t name
= radeon_gem_name_bo(rb
->bo
);
467 if (name
== buffers
[i
].name
)
471 if (RADEON_DEBUG
& RADEON_DRI
)
473 "attaching buffer %s, %d, at %d, cpp %d, pitch %d\n",
474 regname
, buffers
[i
].name
, buffers
[i
].attachment
,
475 buffers
[i
].cpp
, buffers
[i
].pitch
);
477 rb
->cpp
= buffers
[i
].cpp
;
478 rb
->pitch
= buffers
[i
].pitch
;
479 rb
->base
.Base
.Width
= drawable
->w
;
480 rb
->base
.Base
.Height
= drawable
->h
;
483 if (buffers
[i
].attachment
== __DRI_BUFFER_STENCIL
&& depth_bo
) {
484 if (RADEON_DEBUG
& RADEON_DRI
)
485 fprintf(stderr
, "(reusing depth buffer as stencil)\n");
489 uint32_t tiling_flags
= 0, pitch
= 0;
492 bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
496 RADEON_GEM_DOMAIN_VRAM
,
500 fprintf(stderr
, "failed to attach %s %d\n",
501 regname
, buffers
[i
].name
);
505 ret
= radeon_bo_get_tiling(bo
, &tiling_flags
, &pitch
);
508 "failed to get tiling for %s %d\n",
509 regname
, buffers
[i
].name
);
514 if (tiling_flags
& RADEON_TILING_MACRO
)
515 bo
->flags
|= RADEON_BO_FLAGS_MACRO_TILE
;
516 if (tiling_flags
& RADEON_TILING_MICRO
)
517 bo
->flags
|= RADEON_BO_FLAGS_MICRO_TILE
;
521 if (buffers
[i
].attachment
== __DRI_BUFFER_DEPTH
) {
522 if (draw
->base
.Visual
.depthBits
== 16)
527 radeon_renderbuffer_set_bo(rb
, bo
);
530 if (buffers
[i
].attachment
== __DRI_BUFFER_DEPTH_STENCIL
) {
531 rb
= radeon_get_renderbuffer(&draw
->base
, BUFFER_STENCIL
);
533 struct radeon_bo
*stencil_bo
= NULL
;
536 uint32_t name
= radeon_gem_name_bo(rb
->bo
);
537 if (name
== buffers
[i
].name
)
542 radeon_bo_ref(stencil_bo
);
543 radeon_renderbuffer_set_bo(rb
, stencil_bo
);
544 radeon_bo_unref(stencil_bo
);
549 driUpdateFramebufferSize(&radeon
->glCtx
, drawable
);
552 /* Force the context `c' to be the current context and associate with it
555 GLboolean
radeonMakeCurrent(__DRIcontext
* driContextPriv
,
556 __DRIdrawable
* driDrawPriv
,
557 __DRIdrawable
* driReadPriv
)
559 radeonContextPtr radeon
;
560 GET_CURRENT_CONTEXT(curCtx
);
561 struct gl_framebuffer
*drfb
, *readfb
;
564 radeon
= (radeonContextPtr
)driContextPriv
->driverPrivate
;
567 /* According to the glXMakeCurrent() man page: "Pending commands to
568 * the previous context, if any, are flushed before it is released."
569 * But only flush if we're actually changing contexts.
572 if ((radeonContextPtr
)curCtx
&& (radeonContextPtr
)curCtx
!= radeon
) {
576 if (!driContextPriv
) {
577 if (RADEON_DEBUG
& RADEON_DRI
)
578 fprintf(stderr
, "%s ctx is null\n", __FUNCTION__
);
579 _mesa_make_current(NULL
, NULL
, NULL
);
583 if(driDrawPriv
== NULL
&& driReadPriv
== NULL
) {
584 drfb
= _mesa_create_framebuffer(&radeon
->glCtx
.Visual
);
588 drfb
= driDrawPriv
->driverPrivate
;
589 readfb
= driReadPriv
->driverPrivate
;
593 radeon_update_renderbuffers(driContextPriv
, driDrawPriv
, GL_FALSE
);
594 if (driDrawPriv
!= driReadPriv
)
595 radeon_update_renderbuffers(driContextPriv
, driReadPriv
, GL_FALSE
);
596 _mesa_reference_renderbuffer(&radeon
->state
.color
.rb
,
597 &(radeon_get_renderbuffer(drfb
, BUFFER_BACK_LEFT
)->base
.Base
));
598 _mesa_reference_renderbuffer(&radeon
->state
.depth
.rb
,
599 &(radeon_get_renderbuffer(drfb
, BUFFER_DEPTH
)->base
.Base
));
601 if (RADEON_DEBUG
& RADEON_DRI
)
602 fprintf(stderr
, "%s ctx %p dfb %p rfb %p\n", __FUNCTION__
, &radeon
->glCtx
, drfb
, readfb
);
605 driUpdateFramebufferSize(&radeon
->glCtx
, driDrawPriv
);
606 if (driReadPriv
!= driDrawPriv
)
607 driUpdateFramebufferSize(&radeon
->glCtx
, driReadPriv
);
609 _mesa_make_current(&radeon
->glCtx
, drfb
, readfb
);
610 if (driDrawPriv
== NULL
&& driReadPriv
== NULL
)
611 _mesa_reference_framebuffer(&drfb
, NULL
);
613 _mesa_update_state(&radeon
->glCtx
);
615 if (radeon
->glCtx
.DrawBuffer
== drfb
) {
616 if(driDrawPriv
!= NULL
) {
617 radeon_window_moved(radeon
);
620 radeon_draw_buffer(&radeon
->glCtx
, drfb
);
624 if (RADEON_DEBUG
& RADEON_DRI
)
625 fprintf(stderr
, "End %s\n", __FUNCTION__
);