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/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 radeon
->texture_depth
= driQueryOptioni (&radeon
->optionCache
,
170 if (radeon
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_FB
)
171 radeon
->texture_depth
= ( glVisual
->rgbBits
> 16 ) ?
172 DRI_CONF_TEXTURE_DEPTH_32
: DRI_CONF_TEXTURE_DEPTH_16
;
178 * Cleanup common context fields.
179 * Called by r200DestroyContext/r300DestroyContext
181 void radeonCleanupContext(radeonContextPtr radeon
)
183 #ifdef RADEON_BO_TRACK
186 struct radeon_renderbuffer
*rb
;
187 struct radeon_framebuffer
*rfb
;
189 /* free the Mesa context */
190 _mesa_destroy_context(radeon
->glCtx
);
192 rfb
= (void*)radeon
->dri
.drawable
->driverPrivate
;
193 rb
= rfb
->color_rb
[0];
195 radeon_bo_unref(rb
->bo
);
198 rb
= rfb
->color_rb
[1];
200 radeon_bo_unref(rb
->bo
);
203 rb
= radeon_get_renderbuffer(&rfb
->base
, BUFFER_DEPTH
);
205 radeon_bo_unref(rb
->bo
);
208 rfb
= (void*)radeon
->dri
.readable
->driverPrivate
;
209 rb
= rfb
->color_rb
[0];
211 radeon_bo_unref(rb
->bo
);
214 rb
= rfb
->color_rb
[1];
216 radeon_bo_unref(rb
->bo
);
219 rb
= radeon_get_renderbuffer(&rfb
->base
, BUFFER_DEPTH
);
221 radeon_bo_unref(rb
->bo
);
225 /* _mesa_destroy_context() might result in calls to functions that
226 * depend on the DriverCtx, so don't set it to NULL before.
228 * radeon->glCtx->DriverCtx = NULL;
233 /* free the option cache */
234 driDestroyOptionCache(&radeon
->optionCache
);
236 rcommonDestroyCmdBuf(radeon
);
238 if (radeon
->state
.scissor
.pClipRects
) {
239 FREE(radeon
->state
.scissor
.pClipRects
);
240 radeon
->state
.scissor
.pClipRects
= 0;
242 #ifdef RADEON_BO_TRACK
243 track
= fopen("/tmp/tracklog", "w");
245 radeon_tracker_print(&radeon
->radeonScreen
->bom
->tracker
, track
);
251 /* Force the context `c' to be unbound from its buffer.
253 GLboolean
radeonUnbindContext(__DRIcontextPrivate
* driContextPriv
)
255 radeonContextPtr radeon
= (radeonContextPtr
) driContextPriv
->driverPrivate
;
257 if (RADEON_DEBUG
& DEBUG_DRI
)
258 fprintf(stderr
, "%s ctx %p\n", __FUNCTION__
,
266 radeon_make_kernel_renderbuffer_current(radeonContextPtr radeon
,
267 struct radeon_framebuffer
*draw
)
269 /* if radeon->fake */
270 struct radeon_renderbuffer
*rb
;
272 if ((rb
= (void *)draw
->base
.Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
)) {
274 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
275 radeon
->radeonScreen
->frontOffset
,
278 RADEON_GEM_DOMAIN_VRAM
,
281 rb
->cpp
= radeon
->radeonScreen
->cpp
;
282 rb
->pitch
= radeon
->radeonScreen
->frontPitch
* rb
->cpp
;
284 if ((rb
= (void *)draw
->base
.Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
)) {
286 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
287 radeon
->radeonScreen
->backOffset
,
290 RADEON_GEM_DOMAIN_VRAM
,
293 rb
->cpp
= radeon
->radeonScreen
->cpp
;
294 rb
->pitch
= radeon
->radeonScreen
->backPitch
* rb
->cpp
;
296 if ((rb
= (void *)draw
->base
.Attachment
[BUFFER_DEPTH
].Renderbuffer
)) {
298 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
299 radeon
->radeonScreen
->depthOffset
,
302 RADEON_GEM_DOMAIN_VRAM
,
305 rb
->cpp
= radeon
->radeonScreen
->cpp
;
306 rb
->pitch
= radeon
->radeonScreen
->depthPitch
* rb
->cpp
;
308 if ((rb
= (void *)draw
->base
.Attachment
[BUFFER_STENCIL
].Renderbuffer
)) {
310 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
311 radeon
->radeonScreen
->depthOffset
,
314 RADEON_GEM_DOMAIN_VRAM
,
317 rb
->cpp
= radeon
->radeonScreen
->cpp
;
318 rb
->pitch
= radeon
->radeonScreen
->depthPitch
* rb
->cpp
;
323 radeon_make_renderbuffer_current(radeonContextPtr radeon
,
324 struct radeon_framebuffer
*draw
)
326 int size
= 4096*4096*4;
327 /* if radeon->fake */
328 struct radeon_renderbuffer
*rb
;
330 if (radeon
->radeonScreen
->kernel_mm
) {
331 radeon_make_kernel_renderbuffer_current(radeon
, draw
);
336 if ((rb
= (void *)draw
->base
.Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
)) {
338 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
339 radeon
->radeonScreen
->frontOffset
+
340 radeon
->radeonScreen
->fbLocation
,
343 RADEON_GEM_DOMAIN_VRAM
,
346 rb
->cpp
= radeon
->radeonScreen
->cpp
;
347 rb
->pitch
= radeon
->radeonScreen
->frontPitch
* rb
->cpp
;
349 if ((rb
= (void *)draw
->base
.Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
)) {
351 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
352 radeon
->radeonScreen
->backOffset
+
353 radeon
->radeonScreen
->fbLocation
,
356 RADEON_GEM_DOMAIN_VRAM
,
359 rb
->cpp
= radeon
->radeonScreen
->cpp
;
360 rb
->pitch
= radeon
->radeonScreen
->backPitch
* rb
->cpp
;
362 if ((rb
= (void *)draw
->base
.Attachment
[BUFFER_DEPTH
].Renderbuffer
)) {
364 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
365 radeon
->radeonScreen
->depthOffset
+
366 radeon
->radeonScreen
->fbLocation
,
369 RADEON_GEM_DOMAIN_VRAM
,
372 rb
->cpp
= radeon
->radeonScreen
->cpp
;
373 rb
->pitch
= radeon
->radeonScreen
->depthPitch
* rb
->cpp
;
375 if ((rb
= (void *)draw
->base
.Attachment
[BUFFER_STENCIL
].Renderbuffer
)) {
377 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
378 radeon
->radeonScreen
->depthOffset
+
379 radeon
->radeonScreen
->fbLocation
,
382 RADEON_GEM_DOMAIN_VRAM
,
385 rb
->cpp
= radeon
->radeonScreen
->cpp
;
386 rb
->pitch
= radeon
->radeonScreen
->depthPitch
* rb
->cpp
;
392 radeon_update_renderbuffers(__DRIcontext
*context
, __DRIdrawable
*drawable
)
394 unsigned int attachments
[10];
395 __DRIbuffer
*buffers
;
397 struct radeon_renderbuffer
*rb
;
399 struct radeon_framebuffer
*draw
;
400 radeonContextPtr radeon
;
402 struct radeon_bo
*depth_bo
= NULL
, *bo
;
404 if (RADEON_DEBUG
& DEBUG_DRI
)
405 fprintf(stderr
, "enter %s, drawable %p\n", __func__
, drawable
);
407 draw
= drawable
->driverPrivate
;
408 screen
= context
->driScreenPriv
;
409 radeon
= (radeonContextPtr
) context
->driverPrivate
;
411 if (draw
->color_rb
[0])
412 attachments
[i
++] = __DRI_BUFFER_FRONT_LEFT
;
413 if (draw
->color_rb
[1])
414 attachments
[i
++] = __DRI_BUFFER_BACK_LEFT
;
415 if (radeon_get_renderbuffer(&draw
->base
, BUFFER_DEPTH
))
416 attachments
[i
++] = __DRI_BUFFER_DEPTH
;
417 if (radeon_get_renderbuffer(&draw
->base
, BUFFER_STENCIL
))
418 attachments
[i
++] = __DRI_BUFFER_STENCIL
;
420 buffers
= (*screen
->dri2
.loader
->getBuffers
)(drawable
,
425 drawable
->loaderPrivate
);
429 /* set one cliprect to cover the whole drawable */
434 drawable
->numClipRects
= 1;
435 drawable
->pClipRects
[0].x1
= 0;
436 drawable
->pClipRects
[0].y1
= 0;
437 drawable
->pClipRects
[0].x2
= drawable
->w
;
438 drawable
->pClipRects
[0].y2
= drawable
->h
;
439 drawable
->numBackClipRects
= 1;
440 drawable
->pBackClipRects
[0].x1
= 0;
441 drawable
->pBackClipRects
[0].y1
= 0;
442 drawable
->pBackClipRects
[0].x2
= drawable
->w
;
443 drawable
->pBackClipRects
[0].y2
= drawable
->h
;
444 for (i
= 0; i
< count
; i
++) {
445 switch (buffers
[i
].attachment
) {
446 case __DRI_BUFFER_FRONT_LEFT
:
447 rb
= draw
->color_rb
[0];
448 regname
= "dri2 front buffer";
450 case __DRI_BUFFER_BACK_LEFT
:
451 rb
= draw
->color_rb
[1];
452 regname
= "dri2 back buffer";
454 case __DRI_BUFFER_DEPTH
:
455 rb
= radeon_get_renderbuffer(&draw
->base
, BUFFER_DEPTH
);
456 regname
= "dri2 depth buffer";
458 case __DRI_BUFFER_STENCIL
:
459 rb
= radeon_get_renderbuffer(&draw
->base
, BUFFER_STENCIL
);
460 regname
= "dri2 stencil buffer";
462 case __DRI_BUFFER_ACCUM
:
465 "unhandled buffer attach event, attacment type %d\n",
466 buffers
[i
].attachment
);
474 uint32_t name
= radeon_gem_name_bo(rb
->bo
);
475 if (name
== buffers
[i
].name
)
479 if (RADEON_DEBUG
& DEBUG_DRI
)
481 "attaching buffer %s, %d, at %d, cpp %d, pitch %d\n",
482 regname
, buffers
[i
].name
, buffers
[i
].attachment
,
483 buffers
[i
].cpp
, buffers
[i
].pitch
);
485 rb
->cpp
= buffers
[i
].cpp
;
486 rb
->pitch
= buffers
[i
].pitch
;
487 rb
->width
= drawable
->w
;
488 rb
->height
= drawable
->h
;
491 if (buffers
[i
].attachment
== __DRI_BUFFER_STENCIL
&& depth_bo
) {
492 if (RADEON_DEBUG
& DEBUG_DRI
)
493 fprintf(stderr
, "(reusing depth buffer as stencil)\n");
497 bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
501 RADEON_GEM_DOMAIN_VRAM
,
505 fprintf(stderr
, "failed to attach %s %d\n",
506 regname
, buffers
[i
].name
);
511 if (buffers
[i
].attachment
== __DRI_BUFFER_DEPTH
)
514 radeon_renderbuffer_set_bo(rb
, bo
);
519 driUpdateFramebufferSize(radeon
->glCtx
, drawable
);
522 /* Force the context `c' to be the current context and associate with it
525 GLboolean
radeonMakeCurrent(__DRIcontextPrivate
* driContextPriv
,
526 __DRIdrawablePrivate
* driDrawPriv
,
527 __DRIdrawablePrivate
* driReadPriv
)
529 radeonContextPtr radeon
;
530 struct radeon_framebuffer
*drfb
;
531 struct gl_framebuffer
*readfb
;
533 if (!driContextPriv
) {
534 if (RADEON_DEBUG
& DEBUG_DRI
)
535 fprintf(stderr
, "%s ctx is null\n", __FUNCTION__
);
536 _mesa_make_current(NULL
, NULL
, NULL
);
540 radeon
= (radeonContextPtr
) driContextPriv
->driverPrivate
;
541 drfb
= driDrawPriv
->driverPrivate
;
542 readfb
= driReadPriv
->driverPrivate
;
544 if (driContextPriv
->driScreenPriv
->dri2
.enabled
) {
545 radeon_update_renderbuffers(driContextPriv
, driDrawPriv
);
546 if (driDrawPriv
!= driReadPriv
)
547 radeon_update_renderbuffers(driContextPriv
, driReadPriv
);
548 radeon
->state
.color
.rrb
=
549 radeon_get_renderbuffer(&drfb
->base
, BUFFER_BACK_LEFT
);
550 radeon
->state
.depth
.rrb
=
551 radeon_get_renderbuffer(&drfb
->base
, BUFFER_DEPTH
);
553 radeon_make_renderbuffer_current(radeon
, drfb
);
557 if (RADEON_DEBUG
& DEBUG_DRI
)
558 fprintf(stderr
, "%s ctx %p dfb %p rfb %p\n", __FUNCTION__
, radeon
->glCtx
, drfb
, readfb
);
560 if (radeon
->dri
.readable
!= driReadPriv
)
561 radeon
->dri
.readable
= driReadPriv
;
563 driUpdateFramebufferSize(radeon
->glCtx
, driDrawPriv
);
564 if (driReadPriv
!= driDrawPriv
)
565 driUpdateFramebufferSize(radeon
->glCtx
, driReadPriv
);
567 _mesa_make_current(radeon
->glCtx
, &drfb
->base
, readfb
);
569 _mesa_update_state(radeon
->glCtx
);
571 if (radeon
->glCtx
->DrawBuffer
== &drfb
->base
) {
573 if (radeon
->dri
.drawable
!= driDrawPriv
) {
574 if (driDrawPriv
->swap_interval
== (unsigned)-1) {
576 driDrawPriv
->vblFlags
=
577 (radeon
->radeonScreen
->irq
!= 0)
578 ? driGetDefaultVBlankFlags(&radeon
->
580 : VBLANK_FLAG_NO_IRQ
;
582 driDrawableInitVBlank(driDrawPriv
);
583 drfb
->vbl_waited
= driDrawPriv
->vblSeq
;
585 for (i
= 0; i
< 2; i
++) {
586 if (drfb
->color_rb
[i
])
587 drfb
->color_rb
[i
]->vbl_pending
= driDrawPriv
->vblSeq
;
591 radeon
->dri
.drawable
= driDrawPriv
;
593 radeon_window_moved(radeon
);
595 radeon_draw_buffer(radeon
->glCtx
, &drfb
->base
);
599 if (RADEON_DEBUG
& DEBUG_DRI
)
600 fprintf(stderr
, "End %s\n", __FUNCTION__
);