#include #include "xf86drm.h" #include "radeon_drm.h" #include #include #include #include #include #include "radeondemo.h" #include "radeon.h" #include "radeon_bo_gem.h" #include "radeon_cs_gem.h" struct radeon _radeon_ctx; struct radeon *radeon = &_radeon_ctx; bool is_accel_working(struct radeon *radeon) { struct drm_radeon_info ginfo; int r,tmp; memset(&ginfo, 0, sizeof(ginfo)); ginfo.request = RADEON_INFO_ACCEL_WORKING2; r = drmCommandWriteRead(radeon->fd, DRM_RADEON_INFO, &ginfo, sizeof(ginfo)); if (r) { /* If kernel is too old before 2.6.32 than assume accel is working */ if (r == -EINVAL) { ErrorF("Kernel too old missing accel " "information, assuming accel is working\n"); return true; } return false; } if (tmp) return true; return false; } int radeon_init(struct radeon *radeon, int fd) { radeon->fd = fd; is_accel_working(radeon); { struct drm_radeon_gem_info mminfo; if (!drmCommandWriteRead(fd, DRM_RADEON_GEM_INFO, &mminfo, sizeof(mminfo))) { radeon->vram_size = mminfo.vram_visible; radeon->gart_size = mminfo.gart_size; printf( "mem size init: gart size :%llx vram size: s:%llx visible:%llx\n", (unsigned long long)mminfo.gart_size, (unsigned long long)mminfo.vram_size, (unsigned long long)mminfo.vram_visible); } } radeon->bufmgr = radeon_bo_manager_gem_ctor(fd); if (!radeon->bufmgr) return -1; radeon->csm = radeon_cs_manager_gem_ctor(fd); if (!radeon->csm) return -1; radeon->cs = radeon_cs_create(radeon->csm, 16384); if (!radeon->cs) return -1; radeon_cs_set_limit(radeon->cs, RADEON_GEM_DOMAIN_VRAM, radeon->vram_size); radeon_cs_set_limit(radeon->cs, RADEON_GEM_DOMAIN_GTT, radeon->gart_size); radeon_cs_space_set_flush(radeon->cs, (void(*)(void *))radeon_cs_flush_indirect, radeon); radeon_vbo_init_lists(radeon); if (radeon->cardinfo->chip_family >= CHIP_FAMILY_CEDAR) { EVERGREENAllocShaders(radeon); if (radeon->cardinfo->chip_family >= CHIP_FAMILY_CAYMAN) { CAYMANLoadShaders(radeon); } else EVERGREENLoadShaders(radeon); } radeon->accel_state.XInited3D = false; radeon->accel_state.src_obj[0].bo = NULL; radeon->accel_state.src_obj[1].bo = NULL; radeon->accel_state.dst_obj.bo = NULL; radeon->accel_state.vbo.vb_start_op = -1; radeon->accel_state.cbuf.vb_start_op = -1; radeon->accel_state.finish_op = evergreen_finish_op; radeon->accel_state.vbo.verts_per_op = 3; radeon->accel_state.cbuf.verts_per_op = 1; return 0; } void radeon_fini(struct radeon *radeon) { radeon_cs_destroy(radeon->cs); radeon_bo_manager_gem_dtor(radeon->bufmgr); radeon_cs_manager_gem_dtor(radeon->csm); } int main(int argc, char **argv) { int drmFD; int ret; char pciid[20]; drmSetVersion sv; ret = radeon_detect(radeon); if (ret < 0) exit(-1); snprintf(pciid, 20, "pci:%04d:%02d:%02d.%01d", radeon->pci_device->domain, radeon->pci_device->bus, radeon->pci_device->dev, radeon->pci_device->func); drmFD = drmOpen(NULL, pciid); if (drmFD < 0) { drmError(drmFD, __func__); fprintf(stderr, "Check that BusId is correct. You can find the correct BusId in /var/log/Xorg.0.log\n"); fprintf(stderr, "You can also try setting the environment variable LIBGL_DEBUG to \"verbose\" to see what libdrm is trying to do.\n"); exit(-1); } sv.drm_di_major = 1; sv.drm_di_minor = 1; sv.drm_dd_major = -1; sv.drm_dd_minor = -1; ret = drmSetInterfaceVersion(drmFD, &sv); if (ret != 0){ drmClose(drmFD); return -1; } ret = radeon_init(radeon, drmFD); if (ret < 0) { fprintf(stderr,"uanbel to init radeon\n"); exit(-1); } if (radeon->cardinfo->chip_family >= CHIP_FAMILY_CEDAR) { eg_run_test1(radeon); eg_run_test2(radeon); } radeon_fini(radeon); drmClose(drmFD); } void ErrorF(const char *f, ...) { va_list args; va_start(args, f); vfprintf(stderr, f, args); va_end(args); } void radeon_cs_flush_indirect(struct radeon *radeon) { struct radeon_accel_state *accel_state = &radeon->accel_state; int ret; int i; if (!radeon->cs->cdw) return; /* release the current VBO so we don't block on mapping it later */ if (accel_state->vbo.vb_offset && accel_state->vbo.vb_bo) { radeon_vbo_put(radeon, &accel_state->vbo); accel_state->vbo.vb_start_op = -1; } /* release the current VBO so we don't block on mapping it later */ if (accel_state->cbuf.vb_bo) { radeon_vbo_put(radeon, &accel_state->cbuf); accel_state->cbuf.vb_start_op = -1; } for (i = 0; i < radeon->cs->cdw; i++) fprintf(stderr,"%d: %08x\n", i, radeon->cs->packets[i]); radeon_cs_emit(radeon->cs); radeon_cs_erase(radeon->cs); radeon_vbo_flush_bos(radeon); ret = radeon_cs_space_check_with_bo(radeon->cs, accel_state->vbo.vb_bo, RADEON_GEM_DOMAIN_GTT, 0); if (ret) ErrorF("space check failed in flush\n"); accel_state->XInited3D = false; } void radeon_ddx_cs_start(struct radeon *radeon, int n, const char *file, const char *func, int line) { if (radeon->cs->cdw + n > radeon->cs->ndw) { radeon_cs_flush_indirect(radeon); } radeon_cs_begin(radeon->cs, n, file, func, line); } void radeon_vb_no_space(struct radeon *radeon, struct radeon_vbo_object *vbo, int vert_size) { struct radeon_accel_state *accel_state = &radeon->accel_state; if (vbo->vb_bo) { if (vbo->vb_start_op != vbo->vb_offset) { accel_state->finish_op(radeon, vert_size); accel_state->ib_reset_op = radeon->cs->cdw; } /* release the current VBO */ radeon_vbo_put(radeon, vbo); } /* get a new one */ radeon_vbo_get(radeon, vbo); return; } void radeon_ib_discard(struct radeon *radeon) { struct radeon_accel_state *accel_state = &radeon->accel_state; int ret; if (accel_state->ib_reset_op) { /* if we have data just reset the CS and ignore the operation */ radeon->cs->cdw = accel_state->ib_reset_op; accel_state->ib_reset_op = 0; goto out; } accel_state->vbo.vb_offset = 0; accel_state->vbo.vb_start_op = -1; accel_state->cbuf.vb_offset = 0; accel_state->cbuf.vb_start_op = -1; if (CS_FULL(radeon->cs)) { radeon_cs_flush_indirect(radeon); return; } radeon_cs_erase(radeon->cs); ret = radeon_cs_space_check_with_bo(radeon->cs, accel_state->vbo.vb_bo, RADEON_GEM_DOMAIN_GTT, 0); if (ret) ErrorF("space check failed in flush\n"); if (accel_state->cbuf.vb_bo) { ret = radeon_cs_space_check_with_bo(radeon->cs, accel_state->cbuf.vb_bo, RADEON_GEM_DOMAIN_GTT, 0); if (ret) ErrorF("space check failed in flush\n"); } out: accel_state->XInited3D = false; } int radeon_cp_start(struct radeon *radeon) { struct radeon_accel_state *accel_state = &radeon->accel_state; if (CS_FULL(radeon->cs)) { radeon_cs_flush_indirect(radeon); } accel_state->ib_reset_op = radeon->cs->cdw; accel_state->vbo.vb_start_op = accel_state->vbo.vb_offset; accel_state->cbuf.vb_start_op = accel_state->cbuf.vb_offset; return 0; }