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 "main/state.h"
41 #define DRIVER_DATE "20090101"
44 int RADEON_DEBUG
= (0);
47 /* Return various strings for glGetString().
49 static const GLubyte
*radeonGetString(GLcontext
* ctx
, GLenum name
)
51 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
52 static char buffer
[128];
56 if (IS_R300_CLASS(radeon
->radeonScreen
))
57 return (GLubyte
*) "DRI R300 Project";
59 return (GLubyte
*) "Tungsten Graphics, Inc.";
64 GLuint agp_mode
= (radeon
->radeonScreen
->card_type
==RADEON_CARD_PCI
) ? 0 :
65 radeon
->radeonScreen
->AGPMode
;
68 if (IS_R300_CLASS(radeon
->radeonScreen
))
70 else if (IS_R200_CLASS(radeon
->radeonScreen
))
75 offset
= driGetRendererString(buffer
, chipname
, DRIVER_DATE
,
78 if (IS_R300_CLASS(radeon
->radeonScreen
)) {
79 sprintf(&buffer
[offset
], " %sTCL",
80 (radeon
->radeonScreen
->chip_flags
& RADEON_CHIPSET_TCL
)
83 sprintf(&buffer
[offset
], " %sTCL",
84 !(radeon
->TclFallback
& RADEON_TCL_FALLBACK_TCL_DISABLE
)
88 if (radeon
->radeonScreen
->driScreen
->dri2
.enabled
)
89 strcat(buffer
, " DRI2");
91 return (GLubyte
*) buffer
;
99 /* Initialize the driver's misc functions.
101 static void radeonInitDriverFuncs(struct dd_function_table
*functions
)
103 functions
->GetString
= radeonGetString
;
107 * Create and initialize all common fields of the context,
108 * including the Mesa context itself.
110 GLboolean
radeonInitContext(radeonContextPtr radeon
,
111 struct dd_function_table
* functions
,
112 const __GLcontextModes
* glVisual
,
113 __DRIcontextPrivate
* driContextPriv
,
114 void *sharedContextPrivate
)
116 __DRIscreenPrivate
*sPriv
= driContextPriv
->driScreenPriv
;
117 radeonScreenPtr screen
= (radeonScreenPtr
) (sPriv
->private);
122 /* Fill in additional standard functions. */
123 radeonInitDriverFuncs(functions
);
125 radeon
->radeonScreen
= screen
;
126 /* Allocate and initialize the Mesa context */
127 if (sharedContextPrivate
)
128 shareCtx
= ((radeonContextPtr
)sharedContextPrivate
)->glCtx
;
131 radeon
->glCtx
= _mesa_create_context(glVisual
, shareCtx
,
132 functions
, (void *)radeon
);
137 driContextPriv
->driverPrivate
= radeon
;
140 radeon
->dri
.context
= driContextPriv
;
141 radeon
->dri
.screen
= sPriv
;
142 radeon
->dri
.drawable
= NULL
;
143 radeon
->dri
.readable
= NULL
;
144 radeon
->dri
.hwContext
= driContextPriv
->hHWContext
;
145 radeon
->dri
.hwLock
= &sPriv
->pSAREA
->lock
;
146 radeon
->dri
.fd
= sPriv
->fd
;
147 radeon
->dri
.drmMinor
= sPriv
->drm_version
.minor
;
149 radeon
->sarea
= (drm_radeon_sarea_t
*) ((GLubyte
*) sPriv
->pSAREA
+
150 screen
->sarea_priv_offset
);
153 fthrottle_mode
= driQueryOptioni(&radeon
->optionCache
, "fthrottle_mode");
154 radeon
->iw
.irq_seq
= -1;
155 radeon
->irqsEmitted
= 0;
156 radeon
->do_irqs
= (fthrottle_mode
== DRI_CONF_FTHROTTLE_IRQS
&&
157 radeon
->radeonScreen
->irq
);
159 radeon
->do_usleeps
= (fthrottle_mode
== DRI_CONF_FTHROTTLE_USLEEPS
);
161 if (!radeon
->do_irqs
)
163 "IRQ's not enabled, falling back to %s: %d %d\n",
164 radeon
->do_usleeps
? "usleeps" : "busy waits",
165 fthrottle_mode
, radeon
->radeonScreen
->irq
);
171 * Cleanup common context fields.
172 * Called by r200DestroyContext/r300DestroyContext
174 void radeonCleanupContext(radeonContextPtr radeon
)
176 #ifdef RADEON_BO_TRACK
179 struct radeon_renderbuffer
*rb
;
180 struct radeon_framebuffer
*rfb
;
182 /* free the Mesa context */
183 _mesa_destroy_context(radeon
->glCtx
);
185 rfb
= (void*)radeon
->dri
.drawable
->driverPrivate
;
186 rb
= rfb
->color_rb
[0];
188 radeon_bo_unref(rb
->bo
);
191 rb
= rfb
->color_rb
[1];
193 radeon_bo_unref(rb
->bo
);
196 rb
= radeon_get_renderbuffer(&rfb
->base
, BUFFER_DEPTH
);
198 radeon_bo_unref(rb
->bo
);
201 rfb
= (void*)radeon
->dri
.readable
->driverPrivate
;
202 rb
= rfb
->color_rb
[0];
204 radeon_bo_unref(rb
->bo
);
207 rb
= rfb
->color_rb
[1];
209 radeon_bo_unref(rb
->bo
);
212 rb
= radeon_get_renderbuffer(&rfb
->base
, BUFFER_DEPTH
);
214 radeon_bo_unref(rb
->bo
);
218 /* _mesa_destroy_context() might result in calls to functions that
219 * depend on the DriverCtx, so don't set it to NULL before.
221 * radeon->glCtx->DriverCtx = NULL;
226 /* free the option cache */
227 driDestroyOptionCache(&radeon
->optionCache
);
229 rcommonDestroyCmdBuf(radeon
);
231 if (radeon
->state
.scissor
.pClipRects
) {
232 FREE(radeon
->state
.scissor
.pClipRects
);
233 radeon
->state
.scissor
.pClipRects
= 0;
235 #ifdef RADEON_BO_TRACK
236 track
= fopen("/tmp/tracklog", "w");
238 radeon_tracker_print(&radeon
->radeonScreen
->bom
->tracker
, track
);
244 /* Force the context `c' to be unbound from its buffer.
246 GLboolean
radeonUnbindContext(__DRIcontextPrivate
* driContextPriv
)
248 radeonContextPtr radeon
= (radeonContextPtr
) driContextPriv
->driverPrivate
;
250 if (RADEON_DEBUG
& DEBUG_DRI
)
251 fprintf(stderr
, "%s ctx %p\n", __FUNCTION__
,
259 radeon_make_kernel_renderbuffer_current(radeonContextPtr radeon
,
260 struct radeon_framebuffer
*draw
)
262 /* if radeon->fake */
263 struct radeon_renderbuffer
*rb
;
265 if ((rb
= (void *)draw
->base
.Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
)) {
267 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
268 radeon
->radeonScreen
->frontOffset
,
271 RADEON_GEM_DOMAIN_VRAM
,
274 rb
->cpp
= radeon
->radeonScreen
->cpp
;
275 rb
->pitch
= radeon
->radeonScreen
->frontPitch
* rb
->cpp
;
277 if ((rb
= (void *)draw
->base
.Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
)) {
279 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
280 radeon
->radeonScreen
->backOffset
,
283 RADEON_GEM_DOMAIN_VRAM
,
286 rb
->cpp
= radeon
->radeonScreen
->cpp
;
287 rb
->pitch
= radeon
->radeonScreen
->backPitch
* rb
->cpp
;
289 if ((rb
= (void *)draw
->base
.Attachment
[BUFFER_DEPTH
].Renderbuffer
)) {
291 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
292 radeon
->radeonScreen
->depthOffset
,
295 RADEON_GEM_DOMAIN_VRAM
,
298 rb
->cpp
= radeon
->radeonScreen
->cpp
;
299 rb
->pitch
= radeon
->radeonScreen
->depthPitch
* rb
->cpp
;
301 if ((rb
= (void *)draw
->base
.Attachment
[BUFFER_STENCIL
].Renderbuffer
)) {
303 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
304 radeon
->radeonScreen
->depthOffset
,
307 RADEON_GEM_DOMAIN_VRAM
,
310 rb
->cpp
= radeon
->radeonScreen
->cpp
;
311 rb
->pitch
= radeon
->radeonScreen
->depthPitch
* rb
->cpp
;
316 radeon_make_renderbuffer_current(radeonContextPtr radeon
,
317 struct radeon_framebuffer
*draw
)
319 int size
= 4096*4096*4;
320 /* if radeon->fake */
321 struct radeon_renderbuffer
*rb
;
323 if (radeon
->radeonScreen
->kernel_mm
) {
324 radeon_make_kernel_renderbuffer_current(radeon
, draw
);
329 if ((rb
= (void *)draw
->base
.Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
)) {
331 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
332 radeon
->radeonScreen
->frontOffset
+
333 radeon
->radeonScreen
->fbLocation
,
336 RADEON_GEM_DOMAIN_VRAM
,
339 rb
->cpp
= radeon
->radeonScreen
->cpp
;
340 rb
->pitch
= radeon
->radeonScreen
->frontPitch
* rb
->cpp
;
342 if ((rb
= (void *)draw
->base
.Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
)) {
344 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
345 radeon
->radeonScreen
->backOffset
+
346 radeon
->radeonScreen
->fbLocation
,
349 RADEON_GEM_DOMAIN_VRAM
,
352 rb
->cpp
= radeon
->radeonScreen
->cpp
;
353 rb
->pitch
= radeon
->radeonScreen
->backPitch
* rb
->cpp
;
355 if ((rb
= (void *)draw
->base
.Attachment
[BUFFER_DEPTH
].Renderbuffer
)) {
357 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
358 radeon
->radeonScreen
->depthOffset
+
359 radeon
->radeonScreen
->fbLocation
,
362 RADEON_GEM_DOMAIN_VRAM
,
365 rb
->cpp
= radeon
->radeonScreen
->cpp
;
366 rb
->pitch
= radeon
->radeonScreen
->depthPitch
* rb
->cpp
;
368 if ((rb
= (void *)draw
->base
.Attachment
[BUFFER_STENCIL
].Renderbuffer
)) {
370 rb
->bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
371 radeon
->radeonScreen
->depthOffset
+
372 radeon
->radeonScreen
->fbLocation
,
375 RADEON_GEM_DOMAIN_VRAM
,
378 rb
->cpp
= radeon
->radeonScreen
->cpp
;
379 rb
->pitch
= radeon
->radeonScreen
->depthPitch
* rb
->cpp
;
385 radeon_update_renderbuffers(__DRIcontext
*context
, __DRIdrawable
*drawable
)
387 unsigned int attachments
[10];
388 __DRIbuffer
*buffers
;
390 struct radeon_renderbuffer
*rb
;
392 struct radeon_framebuffer
*draw
;
393 radeonContextPtr radeon
;
395 struct radeon_bo
*depth_bo
, *bo
;
397 if (RADEON_DEBUG
& DEBUG_DRI
)
398 fprintf(stderr
, "enter %s, drawable %p\n", __func__
, drawable
);
400 draw
= drawable
->driverPrivate
;
401 screen
= context
->driScreenPriv
;
402 radeon
= (radeonContextPtr
) context
->driverPrivate
;
404 if (draw
->color_rb
[0])
405 attachments
[i
++] = __DRI_BUFFER_FRONT_LEFT
;
406 if (draw
->color_rb
[1])
407 attachments
[i
++] = __DRI_BUFFER_BACK_LEFT
;
408 if (radeon_get_renderbuffer(&draw
->base
, BUFFER_DEPTH
))
409 attachments
[i
++] = __DRI_BUFFER_DEPTH
;
410 if (radeon_get_renderbuffer(&draw
->base
, BUFFER_STENCIL
))
411 attachments
[i
++] = __DRI_BUFFER_STENCIL
;
413 buffers
= (*screen
->dri2
.loader
->getBuffers
)(drawable
,
418 drawable
->loaderPrivate
);
422 /* set one cliprect to cover the whole drawable */
427 drawable
->numClipRects
= 1;
428 drawable
->pClipRects
[0].x1
= 0;
429 drawable
->pClipRects
[0].y1
= 0;
430 drawable
->pClipRects
[0].x2
= drawable
->w
;
431 drawable
->pClipRects
[0].y2
= drawable
->h
;
432 drawable
->numBackClipRects
= 1;
433 drawable
->pBackClipRects
[0].x1
= 0;
434 drawable
->pBackClipRects
[0].y1
= 0;
435 drawable
->pBackClipRects
[0].x2
= drawable
->w
;
436 drawable
->pBackClipRects
[0].y2
= drawable
->h
;
437 for (i
= 0; i
< count
; i
++) {
438 switch (buffers
[i
].attachment
) {
439 case __DRI_BUFFER_FRONT_LEFT
:
440 rb
= draw
->color_rb
[0];
441 regname
= "dri2 front buffer";
443 case __DRI_BUFFER_BACK_LEFT
:
444 rb
= draw
->color_rb
[1];
445 regname
= "dri2 back buffer";
447 case __DRI_BUFFER_DEPTH
:
448 rb
= radeon_get_renderbuffer(&draw
->base
, BUFFER_DEPTH
);
449 regname
= "dri2 depth buffer";
451 case __DRI_BUFFER_STENCIL
:
452 rb
= radeon_get_renderbuffer(&draw
->base
, BUFFER_STENCIL
);
453 regname
= "dri2 stencil buffer";
455 case __DRI_BUFFER_ACCUM
:
458 "unhandled buffer attach event, attacment type %d\n",
459 buffers
[i
].attachment
);
467 uint32_t name
= radeon_gem_name_bo(rb
->bo
);
468 if (name
== buffers
[i
].name
)
472 if (RADEON_DEBUG
& DEBUG_DRI
)
474 "attaching buffer %s, %d, at %d, cpp %d, pitch %d\n",
475 regname
, buffers
[i
].name
, buffers
[i
].attachment
,
476 buffers
[i
].cpp
, buffers
[i
].pitch
);
478 rb
->cpp
= buffers
[i
].cpp
;
479 rb
->pitch
= buffers
[i
].pitch
;
480 rb
->width
= drawable
->w
;
481 rb
->height
= drawable
->h
;
484 if (buffers
[i
].attachment
== __DRI_BUFFER_STENCIL
&& depth_bo
) {
485 if (RADEON_DEBUG
& DEBUG_DRI
)
486 fprintf(stderr
, "(reusing depth buffer as stencil)\n");
490 bo
= radeon_bo_open(radeon
->radeonScreen
->bom
,
494 RADEON_GEM_DOMAIN_VRAM
,
498 fprintf(stderr
, "failed to attach %s %d\n",
499 regname
, buffers
[i
].name
);
504 if (buffers
[i
].attachment
== __DRI_BUFFER_DEPTH
)
507 radeon_renderbuffer_set_bo(rb
, bo
);
512 driUpdateFramebufferSize(radeon
->glCtx
, drawable
);
515 /* Force the context `c' to be the current context and associate with it
518 GLboolean
radeonMakeCurrent(__DRIcontextPrivate
* driContextPriv
,
519 __DRIdrawablePrivate
* driDrawPriv
,
520 __DRIdrawablePrivate
* driReadPriv
)
522 radeonContextPtr radeon
;
523 struct radeon_framebuffer
*drfb
;
524 struct gl_framebuffer
*readfb
;
526 if (!driContextPriv
) {
527 if (RADEON_DEBUG
& DEBUG_DRI
)
528 fprintf(stderr
, "%s ctx is null\n", __FUNCTION__
);
529 _mesa_make_current(NULL
, NULL
, NULL
);
533 radeon
= (radeonContextPtr
) driContextPriv
->driverPrivate
;
534 drfb
= driDrawPriv
->driverPrivate
;
535 readfb
= driReadPriv
->driverPrivate
;
537 if (driContextPriv
->driScreenPriv
->dri2
.enabled
) {
538 radeon_update_renderbuffers(driContextPriv
, driDrawPriv
);
539 if (driDrawPriv
!= driReadPriv
)
540 radeon_update_renderbuffers(driContextPriv
, driReadPriv
);
541 radeon
->state
.color
.rrb
=
542 radeon_get_renderbuffer(&drfb
->base
, BUFFER_BACK_LEFT
);
543 radeon
->state
.depth
.rrb
=
544 radeon_get_renderbuffer(&drfb
->base
, BUFFER_DEPTH
);
546 radeon_make_renderbuffer_current(radeon
, drfb
);
550 if (RADEON_DEBUG
& DEBUG_DRI
)
551 fprintf(stderr
, "%s ctx %p dfb %p rfb %p\n", __FUNCTION__
, radeon
->glCtx
, drfb
, readfb
);
553 if (radeon
->dri
.readable
!= driReadPriv
)
554 radeon
->dri
.readable
= driReadPriv
;
556 driUpdateFramebufferSize(radeon
->glCtx
, driDrawPriv
);
557 if (driReadPriv
!= driDrawPriv
)
558 driUpdateFramebufferSize(radeon
->glCtx
, driReadPriv
);
560 _mesa_make_current(radeon
->glCtx
, &drfb
->base
, readfb
);
562 _mesa_update_state(radeon
->glCtx
);
564 if (radeon
->glCtx
->DrawBuffer
== &drfb
->base
) {
566 if (radeon
->dri
.drawable
!= driDrawPriv
) {
567 if (driDrawPriv
->swap_interval
== (unsigned)-1) {
569 driDrawPriv
->vblFlags
=
570 (radeon
->radeonScreen
->irq
!= 0)
571 ? driGetDefaultVBlankFlags(&radeon
->
573 : VBLANK_FLAG_NO_IRQ
;
575 driDrawableInitVBlank(driDrawPriv
);
576 drfb
->vbl_waited
= driDrawPriv
->vblSeq
;
578 for (i
= 0; i
< 2; i
++) {
579 if (drfb
->color_rb
[i
])
580 drfb
->color_rb
[i
]->vbl_pending
= driDrawPriv
->vblSeq
;
584 radeon
->dri
.drawable
= driDrawPriv
;
586 radeon_window_moved(radeon
);
588 radeon_draw_buffer(radeon
->glCtx
, &drfb
->base
);
592 if (RADEON_DEBUG
& DEBUG_DRI
)
593 fprintf(stderr
, "End %s\n", __FUNCTION__
);