mesa: Don't bind DRAW/READ_FRAMEBUFFER separately without FBO blit support
[mesa.git] / src / mesa / drivers / dri / radeon / server / radeon_egl.c
1 /*
2 * EGL driver for radeon_dri.so
3 */
4 #include <assert.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <dirent.h>
9 #include <errno.h>
10 #include <fcntl.h>
11 #include <unistd.h>
12 #include <sys/ioctl.h>
13 #include <sys/mman.h>
14
15 #include "eglconfig.h"
16 #include "eglcontext.h"
17 #include "egldisplay.h"
18 #include "egldriver.h"
19 #include "eglglobals.h"
20 #include "egllog.h"
21 #include "eglmode.h"
22 #include "eglscreen.h"
23 #include "eglsurface.h"
24 #include "egldri.h"
25
26 #include "mtypes.h"
27 #include "memops.h"
28 #include "drm.h"
29 #include "drm_sarea.h"
30 #include "radeon_drm.h"
31 #include "radeon_dri.h"
32 #include "radeon.h"
33
34 static size_t radeon_drm_page_size;
35
36 /**
37 * radeon driver-specific driver class derived from _EGLDriver
38 */
39 typedef struct radeon_driver
40 {
41 _EGLDriver Base; /* base class/object */
42 GLuint radeonStuff;
43 } radeonDriver;
44
45 static int
46 RADEONSetParam(driDisplay *disp, int param, int value)
47 {
48 drm_radeon_setparam_t sp;
49 int ret;
50
51 memset(&sp, 0, sizeof(sp));
52 sp.param = param;
53 sp.value = value;
54
55 if ((ret=drmCommandWrite(disp->drmFD, DRM_RADEON_SETPARAM, &sp, sizeof(sp)))) {
56 fprintf(stderr,"Set param failed\n", ret);
57 return -1;
58 }
59
60 return 0;
61 }
62
63 static int
64 RADEONCheckDRMVersion(driDisplay *disp, RADEONInfoPtr info)
65 {
66 drmVersionPtr version;
67
68 version = drmGetVersion(disp->drmFD);
69 if (version) {
70 int req_minor, req_patch;
71
72 /* Need 1.21.x for card type detection getparam
73 */
74 req_minor = 21;
75 req_patch = 0;
76
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 */
82 fprintf(stderr,
83 "[dri] RADEONDRIScreenInit failed because of a version "
84 "mismatch.\n"
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,
91 req_minor,
92 req_patch);
93 drmFreeVersion(version);
94 return 0;
95 }
96
97 info->drmMinor = version->version_minor;
98 drmFreeVersion(version);
99 }
100
101 return 1;
102 }
103
104
105 /**
106 * \brief Compute base 2 logarithm.
107 *
108 * \param val value.
109 *
110 * \return base 2 logarithm of \p val.
111 */
112 static int RADEONMinBits(int val)
113 {
114 int bits;
115
116 if (!val) return 1;
117 for (bits = 0; val; val >>= 1, ++bits);
118 return bits;
119 }
120
121
122 /* Initialize the PCI GART state. Request memory for use in PCI space,
123 * and initialize the Radeon registers to point to that memory.
124 */
125 static int RADEONDRIPciInit(driDisplay *disp, RADEONInfoPtr info)
126 {
127 int ret;
128 int flags = DRM_READ_ONLY | DRM_LOCKED | DRM_KERNEL;
129 int s, l;
130
131 ret = drmScatterGatherAlloc(disp->drmFD, info->gartSize*1024*1024,
132 &info->gartMemHandle);
133 if (ret < 0) {
134 fprintf(stderr, "[pci] Out of memory (%d)\n", ret);
135 return 0;
136 }
137 fprintf(stderr,
138 "[pci] %d kB allocated with handle 0x%04lx\n",
139 info->gartSize*1024, (long) info->gartMemHandle);
140
141 info->gartOffset = 0;
142
143 /* Initialize the CP ring buffer data */
144 info->ringStart = info->gartOffset;
145 info->ringMapSize = info->ringSize*1024*1024 + radeon_drm_page_size;
146
147 info->ringReadOffset = info->ringStart + info->ringMapSize;
148 info->ringReadMapSize = radeon_drm_page_size;
149
150 /* Reserve space for vertex/indirect buffers */
151 info->bufStart = info->ringReadOffset + info->ringReadMapSize;
152 info->bufMapSize = info->bufSize*1024*1024;
153
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;
161
162 if (drmAddMap(disp->drmFD, info->ringStart, info->ringMapSize,
163 DRM_SCATTER_GATHER, flags, &info->ringHandle) < 0) {
164 fprintf(stderr,
165 "[pci] Could not add ring mapping\n");
166 return 0;
167 }
168 fprintf(stderr,
169 "[pci] ring handle = 0x%08lx\n", info->ringHandle);
170
171 if (drmAddMap(disp->drmFD, info->ringReadOffset, info->ringReadMapSize,
172 DRM_SCATTER_GATHER, flags, &info->ringReadPtrHandle) < 0) {
173 fprintf(stderr,
174 "[pci] Could not add ring read ptr mapping\n");
175 return 0;
176 }
177 fprintf(stderr,
178 "[pci] ring read ptr handle = 0x%08lx\n",
179 info->ringReadPtrHandle);
180
181 if (drmAddMap(disp->drmFD, info->bufStart, info->bufMapSize,
182 DRM_SCATTER_GATHER, 0, &info->bufHandle) < 0) {
183 fprintf(stderr,
184 "[pci] Could not add vertex/indirect buffers mapping\n");
185 return 0;
186 }
187 fprintf(stderr,
188 "[pci] vertex/indirect buffers handle = 0x%08lx\n",
189 info->bufHandle);
190
191 if (drmAddMap(disp->drmFD, info->gartTexStart, info->gartTexMapSize,
192 DRM_SCATTER_GATHER, 0, &info->gartTexHandle) < 0) {
193 fprintf(stderr,
194 "[pci] Could not add GART texture map mapping\n");
195 return 0;
196 }
197 fprintf(stderr,
198 "[pci] GART texture map handle = 0x%08lx\n",
199 info->gartTexHandle);
200
201 return 1;
202 }
203
204
205 /**
206 * \brief Initialize the AGP state
207 *
208 * \param ctx display handle.
209 * \param info driver private data.
210 *
211 * \return one on success, or zero on failure.
212 *
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.
216 */
217 static int RADEONDRIAgpInit( driDisplay *disp, RADEONInfoPtr info)
218 {
219 int mode, ret;
220 int s, l;
221 int agpmode = 1;
222
223 if (drmAgpAcquire(disp->drmFD) < 0) {
224 fprintf(stderr, "[gart] AGP not available\n");
225 return 0;
226 }
227
228 mode = drmAgpGetMode(disp->drmFD); /* Default mode */
229 /* Disable fast write entirely - too many lockups.
230 */
231 mode &= ~RADEON_AGP_MODE_MASK;
232 switch (agpmode) {
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;
236 }
237
238 if (drmAgpEnable(disp->drmFD, mode) < 0) {
239 fprintf(stderr, "[gart] AGP not enabled\n");
240 drmAgpRelease(disp->drmFD);
241 return 0;
242 }
243
244 #if 0
245 /* Workaround for some hardware bugs */
246 if (info->ChipFamily < CHIP_FAMILY_R200)
247 OUTREG(RADEON_AGP_CNTL, INREG(RADEON_AGP_CNTL) | 0x000e0000);
248 #endif
249 info->gartOffset = 0;
250
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);
255 return 0;
256 }
257 fprintf(stderr,
258 "[gart] %d kB allocated with handle 0x%08x\n",
259 info->gartSize*1024, (unsigned)info->gartMemHandle);
260
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);
266 return 0;
267 }
268
269 /* Initialize the CP ring buffer data */
270 info->ringStart = info->gartOffset;
271 info->ringMapSize = info->ringSize*1024*1024 + radeon_drm_page_size;
272
273 info->ringReadOffset = info->ringStart + info->ringMapSize;
274 info->ringReadMapSize = radeon_drm_page_size;
275
276 /* Reserve space for vertex/indirect buffers */
277 info->bufStart = info->ringReadOffset + info->ringReadMapSize;
278 info->bufMapSize = info->bufSize*1024*1024;
279
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;
287
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");
291 return 0;
292 }
293 fprintf(stderr, "[gart] ring handle = 0x%08lx\n", info->ringHandle);
294
295
296 if (drmAddMap(disp->drmFD, info->ringReadOffset, info->ringReadMapSize,
297 DRM_AGP, DRM_READ_ONLY, &info->ringReadPtrHandle) < 0) {
298 fprintf(stderr,
299 "[gart] Could not add ring read ptr mapping\n");
300 return 0;
301 }
302
303 fprintf(stderr,
304 "[gart] ring read ptr handle = 0x%08lx\n",
305 info->ringReadPtrHandle);
306
307 if (drmAddMap(disp->drmFD, info->bufStart, info->bufMapSize,
308 DRM_AGP, 0, &info->bufHandle) < 0) {
309 fprintf(stderr,
310 "[gart] Could not add vertex/indirect buffers mapping\n");
311 return 0;
312 }
313 fprintf(stderr,
314 "[gart] vertex/indirect buffers handle = 0x%08lx\n",
315 info->bufHandle);
316
317 if (drmAddMap(disp->drmFD, info->gartTexStart, info->gartTexMapSize,
318 DRM_AGP, 0, &info->gartTexHandle) < 0) {
319 fprintf(stderr,
320 "[gart] Could not add AGP texture map mapping\n");
321 return 0;
322 }
323 fprintf(stderr,
324 "[gart] AGP texture map handle = 0x%08lx\n",
325 info->gartTexHandle);
326
327 return 1;
328 }
329
330
331 /**
332 * Initialize all the memory-related fields of the RADEONInfo object.
333 * This includes the various 'offset' and 'size' fields.
334 */
335 static int
336 RADEONMemoryInit(driDisplay *disp, RADEONInfoPtr info)
337 {
338 int width_bytes = disp->virtualWidth * disp->cpp;
339 int cpp = 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);
346 int l;
347 int pcie_gart_table_size = 0;
348
349 info->frontOffset = 0;
350 info->frontPitch = disp->virtualWidth;
351
352 if (disp->card_type==RADEON_CARD_PCIE)
353 pcie_gart_table_size = RADEON_PCIGART_TABLE_SIZE;
354
355 /* Front, back and depth buffers - everything else texture??
356 */
357 info->textureSize = disp->fbSize - pcie_gart_table_size - 2 * bufferSize - depthSize;
358
359 if (info->textureSize < 0)
360 return 0;
361
362 l = RADEONMinBits((info->textureSize-1) / RADEON_NR_TEX_REGIONS);
363 if (l < RADEON_LOG_TEX_GRANULARITY) l = RADEON_LOG_TEX_GRANULARITY;
364
365 /* Round the texture size up to the nearest whole number of
366 * texture regions. Again, be greedy about this, don't
367 * round down.
368 */
369 info->log2TexGran = l;
370 info->textureSize = (info->textureSize >> l) << l;
371
372 /* Set a minimum usable local texture heap size. This will fit
373 * two 256x256x32bpp textures.
374 */
375 if (info->textureSize < 512 * 1024) {
376 info->textureOffset = 0;
377 info->textureSize = 0;
378 }
379
380 /* Reserve space for textures */
381 info->textureOffset = ((disp->fbSize - pcie_gart_table_size - info->textureSize +
382 RADEON_BUFFER_ALIGN) &
383 ~RADEON_BUFFER_ALIGN);
384
385 /* Reserve space for the shared depth
386 * buffer.
387 */
388 info->depthOffset = ((info->textureOffset - depthSize +
389 RADEON_BUFFER_ALIGN) &
390 ~RADEON_BUFFER_ALIGN);
391 info->depthPitch = disp->virtualWidth;
392
393 info->backOffset = ((info->depthOffset - bufferSize +
394 RADEON_BUFFER_ALIGN) &
395 ~RADEON_BUFFER_ALIGN);
396 info->backPitch = disp->virtualWidth;
397
398 if (pcie_gart_table_size)
399 info->pcieGartTableOffset = disp->fbSize - pcie_gart_table_size;
400
401 fprintf(stderr,
402 "Will use back buffer at offset 0x%x, pitch %d\n",
403 info->backOffset, info->backPitch);
404 fprintf(stderr,
405 "Will use depth buffer at offset 0x%x, pitch %d\n",
406 info->depthOffset, info->depthPitch);
407 fprintf(stderr,
408 "Will use %d kb for textures at offset 0x%x\n",
409 info->textureSize/1024, info->textureOffset);
410 if (pcie_gart_table_size)
411 {
412 fprintf(stderr,
413 "Will use %d kb for PCIE GART Table at offset 0x%x\n",
414 pcie_gart_table_size/1024, info->pcieGartTableOffset);
415 }
416
417 /* XXX I don't think these are needed. */
418 #if 0
419 info->frontPitchOffset = (((info->frontPitch * cpp / 64) << 22) |
420 (info->frontOffset >> 10));
421
422 info->backPitchOffset = (((info->backPitch * cpp / 64) << 22) |
423 (info->backOffset >> 10));
424
425 info->depthPitchOffset = (((info->depthPitch * cpp / 64) << 22) |
426 (info->depthOffset >> 10));
427 #endif
428
429 if (pcie_gart_table_size)
430 RADEONSetParam(disp, RADEON_SETPARAM_PCIGART_LOCATION, info->pcieGartTableOffset);
431
432 return 1;
433 }
434
435
436 /**
437 * \brief Initialize the kernel data structures and enable the CP engine.
438 *
439 * \param ctx display handle.
440 * \param info driver private data.
441 *
442 * \return non-zero on success, or zero on failure.
443 *
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.
446 */
447 static int RADEONDRIKernelInit( driDisplay *disp,
448 RADEONInfoPtr info)
449 {
450 int cpp = disp->bpp / 8;
451 drm_radeon_init_t drmInfo;
452 int ret;
453
454 memset(&drmInfo, 0, sizeof(drmInfo));
455
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;
463 else
464 drmInfo.func = RADEON_INIT_CP;
465
466 /* This is the struct passed to the kernel module for its initialization */
467 /* XXX problem here:
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...
473 */
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;
491
492 ret = drmCommandWrite(disp->drmFD, DRM_RADEON_CP_INIT, &drmInfo,
493 sizeof(drm_radeon_init_t));
494
495 return ret >= 0;
496 }
497
498
499 /**
500 * \brief Add a map for the vertex buffers that will be accessed by any
501 * DRI-based clients.
502 *
503 * \param ctx display handle.
504 * \param info driver private data.
505 *
506 * \return one on success, or zero on failure.
507 *
508 * Calls drmAddBufs() with the previously allocated vertex buffers.
509 */
510 static int RADEONDRIBufInit( driDisplay *disp, RADEONInfoPtr info )
511 {
512 /* Initialize vertex buffers */
513 info->bufNumBufs = drmAddBufs(disp->drmFD,
514 info->bufMapSize / RADEON_BUFFER_SIZE,
515 RADEON_BUFFER_SIZE,
516 (disp->card_type!=RADEON_CARD_AGP) ? DRM_SG_BUFFER : DRM_AGP_BUFFER,
517 info->bufStart);
518
519 if (info->bufNumBufs <= 0) {
520 fprintf(stderr,
521 "[drm] Could not create vertex/indirect buffers list\n");
522 return 0;
523 }
524 fprintf(stderr,
525 "[drm] Added %d %d byte vertex/indirect buffers\n",
526 info->bufNumBufs, RADEON_BUFFER_SIZE);
527
528 return 1;
529 }
530
531
532 /**
533 * \brief Install an IRQ handler.
534 *
535 * \param disp display handle.
536 * \param info driver private data.
537 *
538 * Attempts to install an IRQ handler via drmCtlInstHandler(), falling back to
539 * IRQ-free operation on failure.
540 */
541 static void RADEONDRIIrqInit(driDisplay *disp, RADEONInfoPtr info)
542 {
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");
547 }
548
549
550 /**
551 * \brief Initialize the AGP heap.
552 *
553 * \param disp display handle.
554 * \param info driver private data.
555 *
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.
558 */
559 static void RADEONDRIAgpHeapInit(driDisplay *disp,
560 RADEONInfoPtr info)
561 {
562 drm_radeon_mem_init_heap_t drmHeap;
563
564 /* Start up the simple memory manager for gart space */
565 drmHeap.region = RADEON_MEM_REGION_GART;
566 drmHeap.start = 0;
567 drmHeap.size = info->gartTexMapSize;
568
569 if (drmCommandWrite(disp->drmFD, DRM_RADEON_INIT_HEAP,
570 &drmHeap, sizeof(drmHeap))) {
571 fprintf(stderr,
572 "[drm] Failed to initialized gart heap manager\n");
573 } else {
574 fprintf(stderr,
575 "[drm] Initialized kernel gart heap manager, %d\n",
576 info->gartTexMapSize);
577 }
578 }
579
580 static int RADEONGetCardType(driDisplay *disp, RADEONInfoPtr info)
581 {
582 drm_radeon_getparam_t gp;
583 int ret;
584
585 gp.param = RADEON_PARAM_CARD_TYPE;
586 gp.value = &disp->card_type;
587
588 ret=drmCommandWriteRead(disp->drmFD, DRM_RADEON_GETPARAM, &gp, sizeof(gp));
589 if (ret) {
590 fprintf(stderr, "drm_radeon_getparam_t (RADEON_PARAM_CARD_TYPE) : %d\n", ret);
591 return -1;
592 }
593
594 return disp->card_type;
595 }
596
597 /**
598 * Called at the start of each server generation.
599 *
600 * \param disp display handle.
601 * \param info driver private data.
602 *
603 * \return non-zero on success, or zero on failure.
604 *
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.
610 *
611 * Setups a RADEONDRIRec structure to be passed to radeon_dri.so for its
612 * initialization.
613 */
614 static int
615 RADEONScreenInit( driDisplay *disp, RADEONInfoPtr info,
616 RADEONDRIPtr pRADEONDRI)
617 {
618 int i, err;
619
620 /* XXX this probably isn't needed here */
621 {
622 int width_bytes = (disp->virtualWidth * disp->cpp);
623 int maxy = disp->fbSize / width_bytes;
624
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);
632 return 0;
633 }
634 }
635
636 /* Memory manager setup */
637 if (!RADEONMemoryInit(disp, info)) {
638 return 0;
639 }
640
641 /* Create a 'server' context so we can grab the lock for
642 * initialization ioctls.
643 */
644 if ((err = drmCreateContext(disp->drmFD, &disp->serverContext)) != 0) {
645 _eglLog(_EGL_WARNING, "%s: drmCreateContext failed %d\n",
646 __FUNCTION__, err);
647 return 0;
648 }
649
650 DRM_LOCK(disp->drmFD, disp->pSAREA, disp->serverContext, 0);
651
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);
656 return 0;
657 }
658
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);
663 return 0;
664 }
665
666 /* Initialize IRQ */
667 RADEONDRIIrqInit(disp, info);
668
669 /* Initialize kernel gart memory manager */
670 RADEONDRIAgpHeapInit(disp, info);
671
672 /* Initialize the SAREA private data structure */
673 {
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;
679 }
680
681 for ( i = 0;; i++ ) {
682 drmMapType type;
683 drmMapFlags flags;
684 drm_handle_t handle, offset;
685 drmSize size;
686 int rc, mtrr;
687
688 if ( ( rc = drmGetMap( disp->drmFD, i, &offset, &size, &type, &flags, &handle, &mtrr ) ) != 0 )
689 break;
690 if ( type == DRM_REGISTERS ) {
691 pRADEONDRI->registerHandle = offset;
692 pRADEONDRI->registerSize = size;
693 break;
694 }
695 }
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
698 * first.
699 */
700 drimemsetio((char *)disp->pFB + info->frontOffset,
701 0xEE,
702 info->frontPitch * disp->cpp * disp->virtualHeight );
703
704 drimemsetio((char *)disp->pFB + info->backOffset,
705 0x30,
706 info->backPitch * disp->cpp * disp->virtualHeight );
707
708
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);
732
733 /* Don't release the lock now - let the VT switch handler do it. */
734
735 return 1;
736 }
737
738
739 /**
740 * \brief Get Radeon chip family from chipset number.
741 *
742 * \param info driver private data.
743 *
744 * \return non-zero on success, or zero on failure.
745 *
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)
750 */
751 static int get_chipfamily_from_chipset( RADEONInfoPtr info )
752 {
753 switch (info->Chipset) {
754 case PCI_CHIP_RADEON_LY:
755 case PCI_CHIP_RADEON_LZ:
756 info->ChipFamily = CHIP_FAMILY_M6;
757 break;
758
759 case PCI_CHIP_RADEON_QY:
760 case PCI_CHIP_RADEON_QZ:
761 info->ChipFamily = CHIP_FAMILY_VE;
762 break;
763
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;
770 break;
771
772 case PCI_CHIP_RV200_QW: /* RV200 desktop */
773 case PCI_CHIP_RV200_QX:
774 info->ChipFamily = CHIP_FAMILY_RV200;
775 break;
776
777 case PCI_CHIP_RADEON_LW:
778 case PCI_CHIP_RADEON_LX:
779 info->ChipFamily = CHIP_FAMILY_M7;
780 break;
781
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;
787 break;
788
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;
794 break;
795
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;
801 break;
802
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;
808 break;
809
810 case PCI_CHIP_RV370_5460:
811 info->ChipFamily = CHIP_FAMILY_RV380;
812 break;
813
814 default:
815 /* Original Radeon/7200 */
816 info->ChipFamily = CHIP_FAMILY_RADEON;
817 }
818
819 return 1;
820 }
821
822
823 /**
824 * \brief Initialize the framebuffer device mode
825 *
826 * \param disp display handle.
827 *
828 * \return one on success, or zero on failure.
829 *
830 * Fills in \p info with some default values and some information from \p disp
831 * and then calls RADEONScreenInit() for the screen initialization.
832 *
833 * Before exiting clears the framebuffer memory accessing it directly.
834 */
835 static int radeonInitFBDev( driDisplay *disp, RADEONDRIPtr pRADEONDRI )
836 {
837 int err;
838 RADEONInfoPtr info = calloc(1, sizeof(*info));
839
840 disp->driverPrivate = (void *)info;
841
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;
848
849 fprintf(stderr,
850 "Using %d MB AGP aperture\n", info->gartSize);
851 fprintf(stderr,
852 "Using %d MB for the ring buffer\n", info->ringSize);
853 fprintf(stderr,
854 "Using %d MB for vertex/indirect buffers\n", info->bufSize);
855 fprintf(stderr,
856 "Using %d MB for AGP textures\n", info->gartTexSize);
857 fprintf(stderr,
858 "page flipping %sabled\n", info->page_flip_enable?"en":"dis");
859
860 info->Chipset = disp->chipset;
861
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");
865 return 0;
866 }
867 #if 0
868 if (info->ChipFamily >= CHIP_FAMILY_R300) {
869 fprintf(stderr,
870 "Direct rendering not yet supported on "
871 "Radeon 9700 and newer cards\n");
872 return 0;
873 }
874 #endif
875
876 #if 00
877 /* don't seem to need this here */
878 info->frontPitch = disp->virtualWidth;
879 #endif
880
881 /* Check the radeon DRM version */
882 if (!RADEONCheckDRMVersion(disp, info)) {
883 return 0;
884 }
885
886 if (RADEONGetCardType(disp, info)<0)
887 return 0;
888
889 if (disp->card_type!=RADEON_CARD_AGP) {
890 /* Initialize PCI */
891 if (!RADEONDRIPciInit(disp, info))
892 return 0;
893 }
894 else {
895 /* Initialize AGP */
896 if (!RADEONDRIAgpInit(disp, info))
897 return 0;
898 }
899
900 if (!RADEONScreenInit( disp, info, pRADEONDRI))
901 return 0;
902
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);
906 return 0;
907 }
908
909 return 1;
910 }
911
912
913 /**
914 * Create list of all supported surface configs, attach list to the display.
915 */
916 static EGLBoolean
917 radeonFillInConfigs(_EGLDisplay *disp, unsigned pixel_bits,
918 unsigned depth_bits,
919 unsigned stencil_bits, GLboolean have_back_buffer)
920 {
921 _EGLConfig *configs;
922 _EGLConfig *c;
923 unsigned int i, num_configs;
924 unsigned int depth_buffer_factor;
925 unsigned int back_buffer_factor;
926 GLenum fb_format;
927 GLenum fb_type;
928
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.
933 */
934 static const GLenum back_buffer_modes[] = {
935 GLX_NONE, GLX_SWAP_UNDEFINED_OML /*, GLX_SWAP_COPY_OML */
936 };
937
938 uint8_t depth_bits_array[2];
939 uint8_t stencil_bits_array[2];
940
941 depth_bits_array[0] = depth_bits;
942 depth_bits_array[1] = depth_bits;
943
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
946 * care about that.
947 */
948 stencil_bits_array[0] = 0;
949 stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
950
951 depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 2 : 1;
952 back_buffer_factor = (have_back_buffer) ? 2 : 1;
953
954 num_configs = depth_buffer_factor * back_buffer_factor * 2;
955
956 if (pixel_bits == 16) {
957 fb_format = GL_RGB;
958 fb_type = GL_UNSIGNED_SHORT_5_6_5;
959 } else {
960 fb_format = GL_RGBA;
961 fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
962 }
963
964 configs = calloc(sizeof(*configs), num_configs);
965 c = configs;
966 if (!_eglFillInConfigs(c, fb_format, fb_type,
967 depth_bits_array, stencil_bits_array,
968 depth_buffer_factor,
969 back_buffer_modes, back_buffer_factor,
970 GLX_TRUE_COLOR)) {
971 fprintf(stderr, "[%s:%u] Error creating FBConfig!\n",
972 __func__, __LINE__);
973 return EGL_FALSE;
974 }
975
976 /* Mark the visual as slow if there are "fake" stencil bits.
977 */
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);
982 }
983 }
984
985 for (i = 0, c = configs; i < num_configs; i++, c++)
986 _eglAddConfig(disp, c);
987
988 free(configs);
989
990 return EGL_TRUE;
991 }
992
993
994 /**
995 * Show the given surface on the named screen.
996 * If surface is EGL_NO_SURFACE, disable the screen's output.
997 */
998 static EGLBoolean
999 radeonShowScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen,
1000 EGLSurface surface, EGLModeMESA m)
1001 {
1002 EGLBoolean b = _eglDRIShowScreenSurfaceMESA(drv, dpy, screen, surface, m);
1003 return b;
1004 }
1005
1006
1007 /**
1008 * Called via eglInitialize() by user.
1009 */
1010 static EGLBoolean
1011 radeonInitialize(_EGLDriver *drv, EGLDisplay dpy, EGLint *major, EGLint *minor)
1012 {
1013 __DRIframebuffer framebuffer;
1014 driDisplay *display;
1015
1016 /* one-time init */
1017 radeon_drm_page_size = getpagesize();
1018
1019 if (!_eglDRIInitialize(drv, dpy, major, minor))
1020 return EGL_FALSE;
1021
1022 display = Lookup_driDisplay(dpy);
1023
1024 framebuffer.dev_priv_size = sizeof(RADEONDRIRec);
1025 framebuffer.dev_priv = malloc(sizeof(RADEONDRIRec));
1026
1027 /* XXX we shouldn't hard-code values here! */
1028 /* we won't know the screen surface size until the user calls
1029 * eglCreateScreenSurfaceMESA().
1030 */
1031 #if 0
1032 display->virtualWidth = 1024;
1033 display->virtualHeight = 768;
1034 #else
1035 display->virtualWidth = 1280;
1036 display->virtualHeight = 1024;
1037 #endif
1038 display->bpp = 32;
1039 display->cpp = 4;
1040
1041 if (!_eglDRIGetDisplayInfo(display))
1042 return EGL_FALSE;
1043
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 );
1050
1051 if (!_eglDRICreateDisplay(display, &framebuffer))
1052 return EGL_FALSE;
1053
1054 if (!_eglDRICreateScreens(display))
1055 return EGL_FALSE;
1056
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);
1060
1061 drv->Initialized = EGL_TRUE;
1062 return EGL_TRUE;
1063 }
1064
1065
1066 /**
1067 * The bootstrap function. Return a new radeonDriver object and
1068 * plug in API functions.
1069 */
1070 _EGLDriver *
1071 _eglMain(_EGLDisplay *dpy)
1072 {
1073 radeonDriver *radeon;
1074
1075 radeon = (radeonDriver *) calloc(1, sizeof(*radeon));
1076 if (!radeon) {
1077 return NULL;
1078 }
1079
1080 /* First fill in the dispatch table with defaults */
1081 _eglDRIInitDriverFallbacks(&radeon->Base);
1082
1083 /* then plug in our radeon-specific functions */
1084 radeon->Base.API.Initialize = radeonInitialize;
1085 radeon->Base.API.ShowScreenSurfaceMESA = radeonShowScreenSurfaceMESA;
1086
1087 return &radeon->Base;
1088 }