2 * EGL driver for radeon_dri.so
12 #include <sys/ioctl.h>
15 #include "eglconfig.h"
16 #include "eglcontext.h"
17 #include "egldisplay.h"
18 #include "egldriver.h"
19 #include "eglglobals.h"
22 #include "eglscreen.h"
23 #include "eglsurface.h"
29 #include "drm_sarea.h"
30 #include "radeon_drm.h"
31 #include "radeon_dri.h"
34 static size_t radeon_drm_page_size
;
37 * radeon driver-specific driver class derived from _EGLDriver
39 typedef struct radeon_driver
41 _EGLDriver Base
; /* base class/object */
46 RADEONSetParam(driDisplay
*disp
, int param
, int value
)
48 drm_radeon_setparam_t sp
;
51 memset(&sp
, 0, sizeof(sp
));
55 if ((ret
=drmCommandWrite(disp
->drmFD
, DRM_RADEON_SETPARAM
, &sp
, sizeof(sp
)))) {
56 fprintf(stderr
,"Set param failed\n", ret
);
64 RADEONCheckDRMVersion(driDisplay
*disp
, RADEONInfoPtr info
)
66 drmVersionPtr version
;
68 version
= drmGetVersion(disp
->drmFD
);
70 int req_minor
, req_patch
;
72 /* Need 1.21.x for card type detection getparam
77 if (version
->version_major
!= 1 ||
78 version
->version_minor
< req_minor
||
79 (version
->version_minor
== req_minor
&&
80 version
->version_patchlevel
< req_patch
)) {
81 /* Incompatible drm version */
83 "[dri] RADEONDRIScreenInit failed because of a version "
85 "[dri] radeon.o kernel module version is %d.%d.%d "
86 "but version 1.%d.%d or newer is needed.\n"
87 "[dri] Disabling DRI.\n",
88 version
->version_major
,
89 version
->version_minor
,
90 version
->version_patchlevel
,
93 drmFreeVersion(version
);
97 info
->drmMinor
= version
->version_minor
;
98 drmFreeVersion(version
);
106 * \brief Compute base 2 logarithm.
110 * \return base 2 logarithm of \p val.
112 static int RADEONMinBits(int val
)
117 for (bits
= 0; val
; val
>>= 1, ++bits
);
122 /* Initialize the PCI GART state. Request memory for use in PCI space,
123 * and initialize the Radeon registers to point to that memory.
125 static int RADEONDRIPciInit(driDisplay
*disp
, RADEONInfoPtr info
)
128 int flags
= DRM_READ_ONLY
| DRM_LOCKED
| DRM_KERNEL
;
131 ret
= drmScatterGatherAlloc(disp
->drmFD
, info
->gartSize
*1024*1024,
132 &info
->gartMemHandle
);
134 fprintf(stderr
, "[pci] Out of memory (%d)\n", ret
);
138 "[pci] %d kB allocated with handle 0x%04lx\n",
139 info
->gartSize
*1024, (long) info
->gartMemHandle
);
141 info
->gartOffset
= 0;
143 /* Initialize the CP ring buffer data */
144 info
->ringStart
= info
->gartOffset
;
145 info
->ringMapSize
= info
->ringSize
*1024*1024 + radeon_drm_page_size
;
147 info
->ringReadOffset
= info
->ringStart
+ info
->ringMapSize
;
148 info
->ringReadMapSize
= radeon_drm_page_size
;
150 /* Reserve space for vertex/indirect buffers */
151 info
->bufStart
= info
->ringReadOffset
+ info
->ringReadMapSize
;
152 info
->bufMapSize
= info
->bufSize
*1024*1024;
154 /* Reserve the rest for AGP textures */
155 info
->gartTexStart
= info
->bufStart
+ info
->bufMapSize
;
156 s
= (info
->gartSize
*1024*1024 - info
->gartTexStart
);
157 l
= RADEONMinBits((s
-1) / RADEON_NR_TEX_REGIONS
);
158 if (l
< RADEON_LOG_TEX_GRANULARITY
) l
= RADEON_LOG_TEX_GRANULARITY
;
159 info
->gartTexMapSize
= (s
>> l
) << l
;
160 info
->log2GARTTexGran
= l
;
162 if (drmAddMap(disp
->drmFD
, info
->ringStart
, info
->ringMapSize
,
163 DRM_SCATTER_GATHER
, flags
, &info
->ringHandle
) < 0) {
165 "[pci] Could not add ring mapping\n");
169 "[pci] ring handle = 0x%08lx\n", info
->ringHandle
);
171 if (drmAddMap(disp
->drmFD
, info
->ringReadOffset
, info
->ringReadMapSize
,
172 DRM_SCATTER_GATHER
, flags
, &info
->ringReadPtrHandle
) < 0) {
174 "[pci] Could not add ring read ptr mapping\n");
178 "[pci] ring read ptr handle = 0x%08lx\n",
179 info
->ringReadPtrHandle
);
181 if (drmAddMap(disp
->drmFD
, info
->bufStart
, info
->bufMapSize
,
182 DRM_SCATTER_GATHER
, 0, &info
->bufHandle
) < 0) {
184 "[pci] Could not add vertex/indirect buffers mapping\n");
188 "[pci] vertex/indirect buffers handle = 0x%08lx\n",
191 if (drmAddMap(disp
->drmFD
, info
->gartTexStart
, info
->gartTexMapSize
,
192 DRM_SCATTER_GATHER
, 0, &info
->gartTexHandle
) < 0) {
194 "[pci] Could not add GART texture map mapping\n");
198 "[pci] GART texture map handle = 0x%08lx\n",
199 info
->gartTexHandle
);
206 * \brief Initialize the AGP state
208 * \param ctx display handle.
209 * \param info driver private data.
211 * \return one on success, or zero on failure.
213 * Acquires and enables the AGP device. Reserves memory in the AGP space for
214 * the ring buffer, vertex buffers and textures. Initialize the Radeon
215 * registers to point to that memory and add client mappings.
217 static int RADEONDRIAgpInit( driDisplay
*disp
, RADEONInfoPtr info
)
223 if (drmAgpAcquire(disp
->drmFD
) < 0) {
224 fprintf(stderr
, "[gart] AGP not available\n");
228 mode
= drmAgpGetMode(disp
->drmFD
); /* Default mode */
229 /* Disable fast write entirely - too many lockups.
231 mode
&= ~RADEON_AGP_MODE_MASK
;
233 case 4: mode
|= RADEON_AGP_4X_MODE
;
234 case 2: mode
|= RADEON_AGP_2X_MODE
;
235 case 1: default: mode
|= RADEON_AGP_1X_MODE
;
238 if (drmAgpEnable(disp
->drmFD
, mode
) < 0) {
239 fprintf(stderr
, "[gart] AGP not enabled\n");
240 drmAgpRelease(disp
->drmFD
);
245 /* Workaround for some hardware bugs */
246 if (info
->ChipFamily
< CHIP_FAMILY_R200
)
247 OUTREG(RADEON_AGP_CNTL
, INREG(RADEON_AGP_CNTL
) | 0x000e0000);
249 info
->gartOffset
= 0;
251 if ((ret
= drmAgpAlloc(disp
->drmFD
, info
->gartSize
*1024*1024, 0, NULL
,
252 &info
->gartMemHandle
)) < 0) {
253 fprintf(stderr
, "[gart] Out of memory (%d)\n", ret
);
254 drmAgpRelease(disp
->drmFD
);
258 "[gart] %d kB allocated with handle 0x%08x\n",
259 info
->gartSize
*1024, (unsigned)info
->gartMemHandle
);
261 if (drmAgpBind(disp
->drmFD
,
262 info
->gartMemHandle
, info
->gartOffset
) < 0) {
263 fprintf(stderr
, "[gart] Could not bind\n");
264 drmAgpFree(disp
->drmFD
, info
->gartMemHandle
);
265 drmAgpRelease(disp
->drmFD
);
269 /* Initialize the CP ring buffer data */
270 info
->ringStart
= info
->gartOffset
;
271 info
->ringMapSize
= info
->ringSize
*1024*1024 + radeon_drm_page_size
;
273 info
->ringReadOffset
= info
->ringStart
+ info
->ringMapSize
;
274 info
->ringReadMapSize
= radeon_drm_page_size
;
276 /* Reserve space for vertex/indirect buffers */
277 info
->bufStart
= info
->ringReadOffset
+ info
->ringReadMapSize
;
278 info
->bufMapSize
= info
->bufSize
*1024*1024;
280 /* Reserve the rest for AGP textures */
281 info
->gartTexStart
= info
->bufStart
+ info
->bufMapSize
;
282 s
= (info
->gartSize
*1024*1024 - info
->gartTexStart
);
283 l
= RADEONMinBits((s
-1) / RADEON_NR_TEX_REGIONS
);
284 if (l
< RADEON_LOG_TEX_GRANULARITY
) l
= RADEON_LOG_TEX_GRANULARITY
;
285 info
->gartTexMapSize
= (s
>> l
) << l
;
286 info
->log2GARTTexGran
= l
;
288 if (drmAddMap(disp
->drmFD
, info
->ringStart
, info
->ringMapSize
,
289 DRM_AGP
, DRM_READ_ONLY
, &info
->ringHandle
) < 0) {
290 fprintf(stderr
, "[gart] Could not add ring mapping\n");
293 fprintf(stderr
, "[gart] ring handle = 0x%08lx\n", info
->ringHandle
);
296 if (drmAddMap(disp
->drmFD
, info
->ringReadOffset
, info
->ringReadMapSize
,
297 DRM_AGP
, DRM_READ_ONLY
, &info
->ringReadPtrHandle
) < 0) {
299 "[gart] Could not add ring read ptr mapping\n");
304 "[gart] ring read ptr handle = 0x%08lx\n",
305 info
->ringReadPtrHandle
);
307 if (drmAddMap(disp
->drmFD
, info
->bufStart
, info
->bufMapSize
,
308 DRM_AGP
, 0, &info
->bufHandle
) < 0) {
310 "[gart] Could not add vertex/indirect buffers mapping\n");
314 "[gart] vertex/indirect buffers handle = 0x%08lx\n",
317 if (drmAddMap(disp
->drmFD
, info
->gartTexStart
, info
->gartTexMapSize
,
318 DRM_AGP
, 0, &info
->gartTexHandle
) < 0) {
320 "[gart] Could not add AGP texture map mapping\n");
324 "[gart] AGP texture map handle = 0x%08lx\n",
325 info
->gartTexHandle
);
332 * Initialize all the memory-related fields of the RADEONInfo object.
333 * This includes the various 'offset' and 'size' fields.
336 RADEONMemoryInit(driDisplay
*disp
, RADEONInfoPtr info
)
338 int width_bytes
= disp
->virtualWidth
* disp
->cpp
;
340 int bufferSize
= ((disp
->virtualHeight
* width_bytes
341 + RADEON_BUFFER_ALIGN
)
342 & ~RADEON_BUFFER_ALIGN
);
343 int depthSize
= ((((disp
->virtualHeight
+15) & ~15) * width_bytes
344 + RADEON_BUFFER_ALIGN
)
345 & ~RADEON_BUFFER_ALIGN
);
347 int pcie_gart_table_size
= 0;
349 info
->frontOffset
= 0;
350 info
->frontPitch
= disp
->virtualWidth
;
352 if (disp
->card_type
==RADEON_CARD_PCIE
)
353 pcie_gart_table_size
= RADEON_PCIGART_TABLE_SIZE
;
355 /* Front, back and depth buffers - everything else texture??
357 info
->textureSize
= disp
->fbSize
- pcie_gart_table_size
- 2 * bufferSize
- depthSize
;
359 if (info
->textureSize
< 0)
362 l
= RADEONMinBits((info
->textureSize
-1) / RADEON_NR_TEX_REGIONS
);
363 if (l
< RADEON_LOG_TEX_GRANULARITY
) l
= RADEON_LOG_TEX_GRANULARITY
;
365 /* Round the texture size up to the nearest whole number of
366 * texture regions. Again, be greedy about this, don't
369 info
->log2TexGran
= l
;
370 info
->textureSize
= (info
->textureSize
>> l
) << l
;
372 /* Set a minimum usable local texture heap size. This will fit
373 * two 256x256x32bpp textures.
375 if (info
->textureSize
< 512 * 1024) {
376 info
->textureOffset
= 0;
377 info
->textureSize
= 0;
380 /* Reserve space for textures */
381 info
->textureOffset
= ((disp
->fbSize
- pcie_gart_table_size
- info
->textureSize
+
382 RADEON_BUFFER_ALIGN
) &
383 ~RADEON_BUFFER_ALIGN
);
385 /* Reserve space for the shared depth
388 info
->depthOffset
= ((info
->textureOffset
- depthSize
+
389 RADEON_BUFFER_ALIGN
) &
390 ~RADEON_BUFFER_ALIGN
);
391 info
->depthPitch
= disp
->virtualWidth
;
393 info
->backOffset
= ((info
->depthOffset
- bufferSize
+
394 RADEON_BUFFER_ALIGN
) &
395 ~RADEON_BUFFER_ALIGN
);
396 info
->backPitch
= disp
->virtualWidth
;
398 if (pcie_gart_table_size
)
399 info
->pcieGartTableOffset
= disp
->fbSize
- pcie_gart_table_size
;
402 "Will use back buffer at offset 0x%x, pitch %d\n",
403 info
->backOffset
, info
->backPitch
);
405 "Will use depth buffer at offset 0x%x, pitch %d\n",
406 info
->depthOffset
, info
->depthPitch
);
408 "Will use %d kb for textures at offset 0x%x\n",
409 info
->textureSize
/1024, info
->textureOffset
);
410 if (pcie_gart_table_size
)
413 "Will use %d kb for PCIE GART Table at offset 0x%x\n",
414 pcie_gart_table_size
/1024, info
->pcieGartTableOffset
);
417 /* XXX I don't think these are needed. */
419 info
->frontPitchOffset
= (((info
->frontPitch
* cpp
/ 64) << 22) |
420 (info
->frontOffset
>> 10));
422 info
->backPitchOffset
= (((info
->backPitch
* cpp
/ 64) << 22) |
423 (info
->backOffset
>> 10));
425 info
->depthPitchOffset
= (((info
->depthPitch
* cpp
/ 64) << 22) |
426 (info
->depthOffset
>> 10));
429 if (pcie_gart_table_size
)
430 RADEONSetParam(disp
, RADEON_SETPARAM_PCIGART_LOCATION
, info
->pcieGartTableOffset
);
437 * \brief Initialize the kernel data structures and enable the CP engine.
439 * \param ctx display handle.
440 * \param info driver private data.
442 * \return non-zero on success, or zero on failure.
444 * This function is a wrapper around the DRM_RADEON_CP_INIT command, passing
445 * all the parameters in a drm_radeon_init_t structure.
447 static int RADEONDRIKernelInit( driDisplay
*disp
,
450 int cpp
= disp
->bpp
/ 8;
451 drm_radeon_init_t drmInfo
;
454 memset(&drmInfo
, 0, sizeof(drmInfo
));
456 if ( (info
->ChipFamily
>= CHIP_FAMILY_R300
) )
457 drmInfo
.func
= RADEON_INIT_R300_CP
;
458 else if ( (info
->ChipFamily
== CHIP_FAMILY_R200
) ||
459 (info
->ChipFamily
== CHIP_FAMILY_RV250
) ||
460 (info
->ChipFamily
== CHIP_FAMILY_M9
) ||
461 (info
->ChipFamily
== CHIP_FAMILY_RV280
) )
462 drmInfo
.func
= RADEON_INIT_R200_CP
;
464 drmInfo
.func
= RADEON_INIT_CP
;
466 /* This is the struct passed to the kernel module for its initialization */
468 * The front/back/depth_offset/pitch fields may change depending upon
469 * which drawing surface we're using!!! They can't be set just once
470 * during initialization.
471 * Looks like we'll need a new ioctl to update these fields for drawing
472 * to other surfaces...
474 drmInfo
.sarea_priv_offset
= sizeof(drm_sarea_t
);
475 drmInfo
.cp_mode
= RADEON_DEFAULT_CP_BM_MODE
;
476 drmInfo
.gart_size
= info
->gartSize
*1024*1024;
477 drmInfo
.ring_size
= info
->ringSize
*1024*1024;
478 drmInfo
.usec_timeout
= 1000;
479 drmInfo
.fb_bpp
= disp
->bpp
;
480 drmInfo
.depth_bpp
= disp
->bpp
;
481 drmInfo
.front_offset
= info
->frontOffset
;
482 drmInfo
.front_pitch
= info
->frontPitch
* cpp
;
483 drmInfo
.back_offset
= info
->backOffset
;
484 drmInfo
.back_pitch
= info
->backPitch
* cpp
;
485 drmInfo
.depth_offset
= info
->depthOffset
;
486 drmInfo
.depth_pitch
= info
->depthPitch
* cpp
;
487 drmInfo
.ring_offset
= info
->ringHandle
;
488 drmInfo
.ring_rptr_offset
= info
->ringReadPtrHandle
;
489 drmInfo
.buffers_offset
= info
->bufHandle
;
490 drmInfo
.gart_textures_offset
= info
->gartTexHandle
;
492 ret
= drmCommandWrite(disp
->drmFD
, DRM_RADEON_CP_INIT
, &drmInfo
,
493 sizeof(drm_radeon_init_t
));
500 * \brief Add a map for the vertex buffers that will be accessed by any
503 * \param ctx display handle.
504 * \param info driver private data.
506 * \return one on success, or zero on failure.
508 * Calls drmAddBufs() with the previously allocated vertex buffers.
510 static int RADEONDRIBufInit( driDisplay
*disp
, RADEONInfoPtr info
)
512 /* Initialize vertex buffers */
513 info
->bufNumBufs
= drmAddBufs(disp
->drmFD
,
514 info
->bufMapSize
/ RADEON_BUFFER_SIZE
,
516 (disp
->card_type
!=RADEON_CARD_AGP
) ? DRM_SG_BUFFER
: DRM_AGP_BUFFER
,
519 if (info
->bufNumBufs
<= 0) {
521 "[drm] Could not create vertex/indirect buffers list\n");
525 "[drm] Added %d %d byte vertex/indirect buffers\n",
526 info
->bufNumBufs
, RADEON_BUFFER_SIZE
);
533 * \brief Install an IRQ handler.
535 * \param disp display handle.
536 * \param info driver private data.
538 * Attempts to install an IRQ handler via drmCtlInstHandler(), falling back to
539 * IRQ-free operation on failure.
541 static void RADEONDRIIrqInit(driDisplay
*disp
, RADEONInfoPtr info
)
543 if ((drmCtlInstHandler(disp
->drmFD
, 0)) != 0)
544 fprintf(stderr
, "[drm] failure adding irq handler, "
545 "there is a device already using that irq\n"
546 "[drm] falling back to irq-free operation\n");
551 * \brief Initialize the AGP heap.
553 * \param disp display handle.
554 * \param info driver private data.
556 * This function is a wrapper around the DRM_RADEON_INIT_HEAP command, passing
557 * all the parameters in a drm_radeon_mem_init_heap structure.
559 static void RADEONDRIAgpHeapInit(driDisplay
*disp
,
562 drm_radeon_mem_init_heap_t drmHeap
;
564 /* Start up the simple memory manager for gart space */
565 drmHeap
.region
= RADEON_MEM_REGION_GART
;
567 drmHeap
.size
= info
->gartTexMapSize
;
569 if (drmCommandWrite(disp
->drmFD
, DRM_RADEON_INIT_HEAP
,
570 &drmHeap
, sizeof(drmHeap
))) {
572 "[drm] Failed to initialized gart heap manager\n");
575 "[drm] Initialized kernel gart heap manager, %d\n",
576 info
->gartTexMapSize
);
580 static int RADEONGetCardType(driDisplay
*disp
, RADEONInfoPtr info
)
582 drm_radeon_getparam_t gp
;
585 gp
.param
= RADEON_PARAM_CARD_TYPE
;
586 gp
.value
= &disp
->card_type
;
588 ret
=drmCommandWriteRead(disp
->drmFD
, DRM_RADEON_GETPARAM
, &gp
, sizeof(gp
));
590 fprintf(stderr
, "drm_radeon_getparam_t (RADEON_PARAM_CARD_TYPE) : %d\n", ret
);
594 return disp
->card_type
;
598 * Called at the start of each server generation.
600 * \param disp display handle.
601 * \param info driver private data.
603 * \return non-zero on success, or zero on failure.
605 * Performs static frame buffer allocation. Opens the DRM device and add maps
606 * to the SAREA, framebuffer and MMIO regions. Fills in \p info with more
607 * information. Creates a \e server context to grab the lock for the
608 * initialization ioctls and calls the other initilization functions in this
609 * file. Starts the CP engine via the DRM_RADEON_CP_START command.
611 * Setups a RADEONDRIRec structure to be passed to radeon_dri.so for its
615 RADEONScreenInit( driDisplay
*disp
, RADEONInfoPtr info
,
616 RADEONDRIPtr pRADEONDRI
)
620 /* XXX this probably isn't needed here */
622 int width_bytes
= (disp
->virtualWidth
* disp
->cpp
);
623 int maxy
= disp
->fbSize
/ width_bytes
;
625 if (maxy
<= disp
->virtualHeight
* 3) {
626 _eglLog(_EGL_WARNING
,
627 "Static buffer allocation failed -- "
628 "need at least %d kB video memory (have %d kB)\n",
629 (disp
->virtualWidth
* disp
->virtualHeight
*
630 disp
->cpp
* 3 + 1023) / 1024,
631 disp
->fbSize
/ 1024);
636 /* Memory manager setup */
637 if (!RADEONMemoryInit(disp
, info
)) {
641 /* Create a 'server' context so we can grab the lock for
642 * initialization ioctls.
644 if ((err
= drmCreateContext(disp
->drmFD
, &disp
->serverContext
)) != 0) {
645 _eglLog(_EGL_WARNING
, "%s: drmCreateContext failed %d\n",
650 DRM_LOCK(disp
->drmFD
, disp
->pSAREA
, disp
->serverContext
, 0);
652 /* Initialize the kernel data structures */
653 if (!RADEONDRIKernelInit(disp
, info
)) {
654 _eglLog(_EGL_WARNING
, "RADEONDRIKernelInit failed\n");
655 DRM_UNLOCK(disp
->drmFD
, disp
->pSAREA
, disp
->serverContext
);
659 /* Initialize the vertex buffers list */
660 if (!RADEONDRIBufInit(disp
, info
)) {
661 fprintf(stderr
, "RADEONDRIBufInit failed\n");
662 DRM_UNLOCK(disp
->drmFD
, disp
->pSAREA
, disp
->serverContext
);
667 RADEONDRIIrqInit(disp
, info
);
669 /* Initialize kernel gart memory manager */
670 RADEONDRIAgpHeapInit(disp
, info
);
672 /* Initialize the SAREA private data structure */
674 drm_radeon_sarea_t
*pSAREAPriv
;
675 pSAREAPriv
= (drm_radeon_sarea_t
*)(((char*)disp
->pSAREA
) +
676 sizeof(drm_sarea_t
));
677 memset(pSAREAPriv
, 0, sizeof(*pSAREAPriv
));
678 pSAREAPriv
->pfState
= info
->page_flip_enable
;
681 for ( i
= 0;; i
++ ) {
684 drm_handle_t handle
, offset
;
688 if ( ( rc
= drmGetMap( disp
->drmFD
, i
, &offset
, &size
, &type
, &flags
, &handle
, &mtrr
) ) != 0 )
690 if ( type
== DRM_REGISTERS
) {
691 pRADEONDRI
->registerHandle
= offset
;
692 pRADEONDRI
->registerSize
= size
;
696 /* Quick hack to clear the front & back buffers. Could also use
697 * the clear ioctl to do this, but would need to setup hw state
700 drimemsetio((char *)disp
->pFB
+ info
->frontOffset
,
702 info
->frontPitch
* disp
->cpp
* disp
->virtualHeight
);
704 drimemsetio((char *)disp
->pFB
+ info
->backOffset
,
706 info
->backPitch
* disp
->cpp
* disp
->virtualHeight
);
709 /* This is the struct passed to radeon_dri.so for its initialization */
710 pRADEONDRI
->deviceID
= info
->Chipset
;
711 pRADEONDRI
->width
= disp
->virtualWidth
;
712 pRADEONDRI
->height
= disp
->virtualHeight
;
713 pRADEONDRI
->depth
= disp
->bpp
; /* XXX: depth */
714 pRADEONDRI
->bpp
= disp
->bpp
;
715 pRADEONDRI
->IsPCI
= (disp
->card_type
!= RADEON_CARD_AGP
);;
716 pRADEONDRI
->frontOffset
= info
->frontOffset
;
717 pRADEONDRI
->frontPitch
= info
->frontPitch
;
718 pRADEONDRI
->backOffset
= info
->backOffset
;
719 pRADEONDRI
->backPitch
= info
->backPitch
;
720 pRADEONDRI
->depthOffset
= info
->depthOffset
;
721 pRADEONDRI
->depthPitch
= info
->depthPitch
;
722 pRADEONDRI
->textureOffset
= info
->textureOffset
;
723 pRADEONDRI
->textureSize
= info
->textureSize
;
724 pRADEONDRI
->log2TexGran
= info
->log2TexGran
;
725 pRADEONDRI
->statusHandle
= info
->ringReadPtrHandle
;
726 pRADEONDRI
->statusSize
= info
->ringReadMapSize
;
727 pRADEONDRI
->gartTexHandle
= info
->gartTexHandle
;
728 pRADEONDRI
->gartTexMapSize
= info
->gartTexMapSize
;
729 pRADEONDRI
->log2GARTTexGran
= info
->log2GARTTexGran
;
730 pRADEONDRI
->gartTexOffset
= info
->gartTexStart
;
731 pRADEONDRI
->sarea_priv_offset
= sizeof(drm_sarea_t
);
733 /* Don't release the lock now - let the VT switch handler do it. */
740 * \brief Get Radeon chip family from chipset number.
742 * \param info driver private data.
744 * \return non-zero on success, or zero on failure.
746 * Called by radeonInitFBDev() to set RADEONInfoRec::ChipFamily
747 * according to the value of RADEONInfoRec::Chipset. Fails if the
748 * chipset is unrecognized or not appropriate for this driver (i.e., not
749 * an r100 style radeon)
751 static int get_chipfamily_from_chipset( RADEONInfoPtr info
)
753 switch (info
->Chipset
) {
754 case PCI_CHIP_RADEON_LY
:
755 case PCI_CHIP_RADEON_LZ
:
756 info
->ChipFamily
= CHIP_FAMILY_M6
;
759 case PCI_CHIP_RADEON_QY
:
760 case PCI_CHIP_RADEON_QZ
:
761 info
->ChipFamily
= CHIP_FAMILY_VE
;
764 case PCI_CHIP_R200_QL
:
765 case PCI_CHIP_R200_QN
:
766 case PCI_CHIP_R200_QO
:
767 case PCI_CHIP_R200_Ql
:
768 case PCI_CHIP_R200_BB
:
769 info
->ChipFamily
= CHIP_FAMILY_R200
;
772 case PCI_CHIP_RV200_QW
: /* RV200 desktop */
773 case PCI_CHIP_RV200_QX
:
774 info
->ChipFamily
= CHIP_FAMILY_RV200
;
777 case PCI_CHIP_RADEON_LW
:
778 case PCI_CHIP_RADEON_LX
:
779 info
->ChipFamily
= CHIP_FAMILY_M7
;
782 case PCI_CHIP_RV250_Id
:
783 case PCI_CHIP_RV250_Ie
:
784 case PCI_CHIP_RV250_If
:
785 case PCI_CHIP_RV250_Ig
:
786 info
->ChipFamily
= CHIP_FAMILY_RV250
;
789 case PCI_CHIP_RV250_Ld
:
790 case PCI_CHIP_RV250_Le
:
791 case PCI_CHIP_RV250_Lf
:
792 case PCI_CHIP_RV250_Lg
:
793 info
->ChipFamily
= CHIP_FAMILY_M9
;
796 case PCI_CHIP_RV280_Y_
:
797 case PCI_CHIP_RV280_Ya
:
798 case PCI_CHIP_RV280_Yb
:
799 case PCI_CHIP_RV280_Yc
:
800 info
->ChipFamily
= CHIP_FAMILY_RV280
;
803 case PCI_CHIP_R300_ND
:
804 case PCI_CHIP_R300_NE
:
805 case PCI_CHIP_R300_NF
:
806 case PCI_CHIP_R300_NG
:
807 info
->ChipFamily
= CHIP_FAMILY_R300
;
810 case PCI_CHIP_RV370_5460
:
811 info
->ChipFamily
= CHIP_FAMILY_RV380
;
815 /* Original Radeon/7200 */
816 info
->ChipFamily
= CHIP_FAMILY_RADEON
;
824 * \brief Initialize the framebuffer device mode
826 * \param disp display handle.
828 * \return one on success, or zero on failure.
830 * Fills in \p info with some default values and some information from \p disp
831 * and then calls RADEONScreenInit() for the screen initialization.
833 * Before exiting clears the framebuffer memory accessing it directly.
835 static int radeonInitFBDev( driDisplay
*disp
, RADEONDRIPtr pRADEONDRI
)
838 RADEONInfoPtr info
= calloc(1, sizeof(*info
));
840 disp
->driverPrivate
= (void *)info
;
842 info
->gartFastWrite
= RADEON_DEFAULT_AGP_FAST_WRITE
;
843 info
->gartSize
= RADEON_DEFAULT_AGP_SIZE
;
844 info
->gartTexSize
= RADEON_DEFAULT_AGP_TEX_SIZE
;
845 info
->bufSize
= RADEON_DEFAULT_BUFFER_SIZE
;
846 info
->ringSize
= RADEON_DEFAULT_RING_SIZE
;
847 info
->page_flip_enable
= RADEON_DEFAULT_PAGE_FLIP
;
850 "Using %d MB AGP aperture\n", info
->gartSize
);
852 "Using %d MB for the ring buffer\n", info
->ringSize
);
854 "Using %d MB for vertex/indirect buffers\n", info
->bufSize
);
856 "Using %d MB for AGP textures\n", info
->gartTexSize
);
858 "page flipping %sabled\n", info
->page_flip_enable
?"en":"dis");
860 info
->Chipset
= disp
->chipset
;
862 if (!get_chipfamily_from_chipset( info
)) {
863 fprintf(stderr
, "Unknown or non-radeon chipset -- cannot continue\n");
864 fprintf(stderr
, "==> Verify PCI BusID is correct in miniglx.conf\n");
868 if (info
->ChipFamily
>= CHIP_FAMILY_R300
) {
870 "Direct rendering not yet supported on "
871 "Radeon 9700 and newer cards\n");
877 /* don't seem to need this here */
878 info
->frontPitch
= disp
->virtualWidth
;
881 /* Check the radeon DRM version */
882 if (!RADEONCheckDRMVersion(disp
, info
)) {
886 if (RADEONGetCardType(disp
, info
)<0)
889 if (disp
->card_type
!=RADEON_CARD_AGP
) {
891 if (!RADEONDRIPciInit(disp
, info
))
896 if (!RADEONDRIAgpInit(disp
, info
))
900 if (!RADEONScreenInit( disp
, info
, pRADEONDRI
))
903 /* Initialize and start the CP if required */
904 if ((err
= drmCommandNone(disp
->drmFD
, DRM_RADEON_CP_START
)) != 0) {
905 fprintf(stderr
, "%s: CP start %d\n", __FUNCTION__
, err
);
914 * Create list of all supported surface configs, attach list to the display.
917 radeonFillInConfigs(_EGLDisplay
*disp
, unsigned pixel_bits
,
919 unsigned stencil_bits
, GLboolean have_back_buffer
)
923 unsigned int i
, num_configs
;
924 unsigned int depth_buffer_factor
;
925 unsigned int back_buffer_factor
;
929 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
930 * enough to add support. Basically, if a context is created with an
931 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
932 * will never be used.
934 static const GLenum back_buffer_modes
[] = {
935 GLX_NONE
, GLX_SWAP_UNDEFINED_OML
/*, GLX_SWAP_COPY_OML */
938 uint8_t depth_bits_array
[2];
939 uint8_t stencil_bits_array
[2];
941 depth_bits_array
[0] = depth_bits
;
942 depth_bits_array
[1] = depth_bits
;
944 /* Just like with the accumulation buffer, always provide some modes
945 * with a stencil buffer. It will be a sw fallback, but some apps won't
948 stencil_bits_array
[0] = 0;
949 stencil_bits_array
[1] = (stencil_bits
== 0) ? 8 : stencil_bits
;
951 depth_buffer_factor
= ((depth_bits
!= 0) || (stencil_bits
!= 0)) ? 2 : 1;
952 back_buffer_factor
= (have_back_buffer
) ? 2 : 1;
954 num_configs
= depth_buffer_factor
* back_buffer_factor
* 2;
956 if (pixel_bits
== 16) {
958 fb_type
= GL_UNSIGNED_SHORT_5_6_5
;
961 fb_type
= GL_UNSIGNED_INT_8_8_8_8_REV
;
964 configs
= calloc(sizeof(*configs
), num_configs
);
966 if (!_eglFillInConfigs(c
, fb_format
, fb_type
,
967 depth_bits_array
, stencil_bits_array
,
969 back_buffer_modes
, back_buffer_factor
,
971 fprintf(stderr
, "[%s:%u] Error creating FBConfig!\n",
976 /* Mark the visual as slow if there are "fake" stencil bits.
978 for (i
= 0, c
= configs
; i
< num_configs
; i
++, c
++) {
979 int stencil
= GET_CONFIG_ATTRIB(c
, EGL_STENCIL_SIZE
);
980 if ((stencil
!= 0) && (stencil
!= stencil_bits
)) {
981 SET_CONFIG_ATTRIB(c
, EGL_CONFIG_CAVEAT
, EGL_SLOW_CONFIG
);
985 for (i
= 0, c
= configs
; i
< num_configs
; i
++, c
++)
986 _eglAddConfig(disp
, c
);
995 * Show the given surface on the named screen.
996 * If surface is EGL_NO_SURFACE, disable the screen's output.
999 radeonShowScreenSurfaceMESA(_EGLDriver
*drv
, EGLDisplay dpy
, EGLScreenMESA screen
,
1000 EGLSurface surface
, EGLModeMESA m
)
1002 EGLBoolean b
= _eglDRIShowScreenSurfaceMESA(drv
, dpy
, screen
, surface
, m
);
1008 * Called via eglInitialize() by user.
1011 radeonInitialize(_EGLDriver
*drv
, EGLDisplay dpy
, EGLint
*major
, EGLint
*minor
)
1013 __DRIframebuffer framebuffer
;
1014 driDisplay
*display
;
1017 radeon_drm_page_size
= getpagesize();
1019 if (!_eglDRIInitialize(drv
, dpy
, major
, minor
))
1022 display
= Lookup_driDisplay(dpy
);
1024 framebuffer
.dev_priv_size
= sizeof(RADEONDRIRec
);
1025 framebuffer
.dev_priv
= malloc(sizeof(RADEONDRIRec
));
1027 /* XXX we shouldn't hard-code values here! */
1028 /* we won't know the screen surface size until the user calls
1029 * eglCreateScreenSurfaceMESA().
1032 display
->virtualWidth
= 1024;
1033 display
->virtualHeight
= 768;
1035 display
->virtualWidth
= 1280;
1036 display
->virtualHeight
= 1024;
1041 if (!_eglDRIGetDisplayInfo(display
))
1044 framebuffer
.base
= display
->pFB
;
1045 framebuffer
.width
= display
->virtualWidth
;
1046 framebuffer
.height
= display
->virtualHeight
;
1047 framebuffer
.stride
= display
->virtualWidth
;
1048 framebuffer
.size
= display
->fbSize
;
1049 radeonInitFBDev( display
, framebuffer
.dev_priv
);
1051 if (!_eglDRICreateDisplay(display
, &framebuffer
))
1054 if (!_eglDRICreateScreens(display
))
1057 /* create a variety of both 32 and 16-bit configurations */
1058 radeonFillInConfigs(&display
->Base
, 32, 24, 8, GL_TRUE
);
1059 radeonFillInConfigs(&display
->Base
, 16, 16, 0, GL_TRUE
);
1061 drv
->Initialized
= EGL_TRUE
;
1067 * The bootstrap function. Return a new radeonDriver object and
1068 * plug in API functions.
1071 _eglMain(_EGLDisplay
*dpy
)
1073 radeonDriver
*radeon
;
1075 radeon
= (radeonDriver
*) calloc(1, sizeof(*radeon
));
1080 /* First fill in the dispatch table with defaults */
1081 _eglDRIInitDriverFallbacks(&radeon
->Base
);
1083 /* then plug in our radeon-specific functions */
1084 radeon
->Base
.API
.Initialize
= radeonInitialize
;
1085 radeon
->Base
.API
.ShowScreenSurfaceMESA
= radeonShowScreenSurfaceMESA
;
1087 return &radeon
->Base
;