diff options
author | Jerome Glisse <jglisse@redhat.com> | 2010-02-16 22:49:46 +0100 |
---|---|---|
committer | Jerome Glisse <jglisse@redhat.com> | 2010-02-16 22:49:46 +0100 |
commit | 84d9dae08b7b2b70ae71d469248c2da5769b26e1 (patch) | |
tree | e204a28a6106564fed75f186766ce7a76391b75b | |
parent | f2891214515d6f5e2f46d31402c7d21ee13467a7 (diff) |
split code that is kernel/userspace agnostic
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | r600_atom.c | 471 | ||||
-rw-r--r-- | r600_atom_api.h | 20 | ||||
-rw-r--r-- | r600_batch.c | 521 |
4 files changed, 536 insertions, 478 deletions
@@ -1,5 +1,5 @@ OBJECTS = radeon.o mode.o test.o r700_atom.o radeon_device.o radeon_atom.o\ - r600_atom.o r600_shader.o + r600_atom.o r600_shader.o r600_batch.o CFLAGS = -g3 -O0 -std=gnu99 -I/usr/include/drm LDFLAGS = -ldrm -ldrm_radeon DEPS = radeon.h diff --git a/r600_atom.c b/r600_atom.c index daf5db7..7685810 100644 --- a/r600_atom.c +++ b/r600_atom.c @@ -19,55 +19,9 @@ #include "r600d.h" /* - * helpers functions - */ -static void r600_emit_flush(struct radeon_device *rdev, - struct radeon_ib *ib, - struct radeon_bo *bo, - u32 flags) -{ - ib->ptr[ib->cpkts++] = PKT3(PKT3_SURFACE_SYNC, 3); - ib->ptr[ib->cpkts++] = flags; - ib->ptr[ib->cpkts++] = radeon_bo_size(bo) >> 8; - ib->ptr[ib->cpkts++] = 0x00000000; - ib->ptr[ib->cpkts++] = 0x0000000A; - ib->ptr[ib->cpkts++] = PKT3(PKT3_NOP, 0); - ib->ptr[ib->cpkts++] = radeon_ib_reloc(ib, bo, RADEON_GEM_DOMAIN_VRAM | - RADEON_GEM_DOMAIN_GTT); -} - -static void r600_emit_resources(struct radeon_device *rdev, - struct radeon_ib *ib, - struct radeon_bo *bo, - u32 dw0, u32 dw1, u32 dw2, u32 dw3, - u32 dw4, u32 dw5, u32 dw6, u32 dw7) -{ - ib->ptr[ib->cpkts++] = PKT3(PKT3_SURFACE_SYNC, 3); - ib->ptr[ib->cpkts++] = 0x01000000; - ib->ptr[ib->cpkts++] = radeon_bo_size(bo) >> 8; - ib->ptr[ib->cpkts++] = 0x00000000; - ib->ptr[ib->cpkts++] = 0x0000000A; - ib->ptr[ib->cpkts++] = PKT3(PKT3_NOP, 0); - ib->ptr[ib->cpkts++] = radeon_ib_reloc(ib, bo, RADEON_GEM_DOMAIN_VRAM | - RADEON_GEM_DOMAIN_GTT); - ib->ptr[ib->cpkts++] = PKT3(PKT3_SET_RESOURCE, 7); - ib->ptr[ib->cpkts++] = dw0; - ib->ptr[ib->cpkts++] = dw1; - ib->ptr[ib->cpkts++] = dw2; - ib->ptr[ib->cpkts++] = dw3; - ib->ptr[ib->cpkts++] = dw4; - ib->ptr[ib->cpkts++] = dw5; - ib->ptr[ib->cpkts++] = dw6; - ib->ptr[ib->cpkts++] = dw7; - ib->ptr[ib->cpkts++] = PKT3(PKT3_NOP, 0); - ib->ptr[ib->cpkts++] = radeon_ib_reloc(ib, bo, RADEON_GEM_DOMAIN_VRAM | - RADEON_GEM_DOMAIN_GTT); -} - -/* * r600_cb */ -static int r600_cb_emit(struct radeon_device *rdev, +int r600_cb_emit(struct radeon_device *rdev, struct radeon_atom *atom, void *data, struct radeon_ib *ib) @@ -84,7 +38,7 @@ static int r600_cb_emit(struct radeon_device *rdev, /* FIXME delete */ void r600_tflat(struct radeon_atom *atom); -static int r600_cb_create(struct radeon_device *rdev, +int r600_cb_create(struct radeon_device *rdev, struct r600_atoms *atoms, struct radeon_atom *atom, void *data) @@ -269,7 +223,7 @@ fprintf(stderr, "%s %d pkts\n", __func__, atom->npkts); /* * r600_cb_cntl */ -static int r600_cb_cntl_create(struct radeon_device *rdev, +int r600_cb_cntl_create(struct radeon_device *rdev, struct r600_atoms *atoms, struct radeon_atom *atom, void *data) @@ -328,7 +282,7 @@ fprintf(stderr, "%s %d pkts\n", __func__, atom->npkts); /* * r600_pa */ -static int r600_pa_create(struct radeon_device *rdev, +int r600_pa_create(struct radeon_device *rdev, struct r600_atoms *atoms, struct radeon_atom *atom, void *data) @@ -421,7 +375,7 @@ fprintf(stderr, "%s %d pkts\n", __func__, atom->npkts); /* * r600_vport */ -static int r600_vport_create(struct radeon_device *rdev, +int r600_vport_create(struct radeon_device *rdev, struct r600_atoms *atoms, struct radeon_atom *atom, void *data) @@ -483,7 +437,7 @@ fprintf(stderr, "%s %d pkts\n", __func__, atom->npkts); /* * r600_blend */ -static int r600_blend_create(struct radeon_device *rdev, +int r600_blend_create(struct radeon_device *rdev, struct r600_atoms *atoms, struct radeon_atom *atom, void *data) @@ -521,7 +475,7 @@ fprintf(stderr, "%s %d pkts\n", __func__, atom->npkts); /* * r600_constant */ -static int r600_constants_create(struct radeon_device *rdev, +int r600_constants_create(struct radeon_device *rdev, struct r600_atoms *atoms, struct radeon_atom *atom, void *data) @@ -555,7 +509,7 @@ static int r600_constants_create(struct radeon_device *rdev, /* * r600_db */ -static int r600_db_emit(struct radeon_device *rdev, +int r600_db_emit(struct radeon_device *rdev, struct radeon_atom *atom, void *data, struct radeon_ib *ib) @@ -570,7 +524,7 @@ static int r600_db_emit(struct radeon_device *rdev, return r; } -static int r600_db_create(struct radeon_device *rdev, +int r600_db_create(struct radeon_device *rdev, struct r600_atoms *atoms, struct radeon_atom *atom, void *data) @@ -683,7 +637,7 @@ fprintf(stderr, "%s %d pkts\n", __func__, atom->npkts); /* * r600_db_cntl */ -static int r600_db_cntl_create(struct radeon_device *rdev, +int r600_db_cntl_create(struct radeon_device *rdev, struct r600_atoms *atoms, struct radeon_atom *atom, void *data) @@ -738,7 +692,7 @@ fprintf(stderr, "%s %d pkts\n", __func__, atom->npkts); /* * r600_vs_shader */ -static int r600_vs_shader_emit(struct radeon_device *rdev, +int r600_vs_shader_emit(struct radeon_device *rdev, struct radeon_atom *atom, void *data, struct radeon_ib *ib) @@ -763,7 +717,7 @@ static int r600_vs_shader_emit(struct radeon_device *rdev, return r; } -static int r600_vs_shader_create(struct radeon_device *rdev, +int r600_vs_shader_create(struct radeon_device *rdev, struct r600_atoms *atoms, struct radeon_atom *atom, void *data) @@ -841,7 +795,7 @@ fprintf(stderr, "%s %d pkts\n", __func__, atom->npkts); /* * r600_ps_shader */ -static int r600_ps_shader_emit(struct radeon_device *rdev, +int r600_ps_shader_emit(struct radeon_device *rdev, struct radeon_atom *atom, void *data, struct radeon_ib *ib) @@ -859,7 +813,7 @@ static int r600_ps_shader_emit(struct radeon_device *rdev, return r; } -static int r600_ps_shader_create(struct radeon_device *rdev, +int r600_ps_shader_create(struct radeon_device *rdev, struct r600_atoms *atoms, struct radeon_atom *atom, void *data) @@ -906,403 +860,6 @@ fprintf(stderr, "%s %d pkts\n", __func__, atom->npkts); return 0; } -/* - * r600 atom core functions - */ -int r600_atom_create(struct radeon_device *rdev, - struct r600_atoms *atoms, - struct drm_radeon_atom *patom, - struct radeon_atom **atomptr) -{ - struct radeon_atom *atom; - struct r600_state_container *cont; - int r; - - *atomptr = NULL; - atom = malloc(sizeof(struct radeon_atom)); - if (atom == NULL) - return -ENOMEM; - memset(atom, 0, sizeof(struct radeon_atom)); - cont = patom->data; - patom->id = 0; - radeon_device_set_bo_list(rdev, cont->nbo, cont->bo); - atom->type = patom->type; - mutex_lock(&atoms->mutex); - switch (patom->type) { - case R600_ATOM_CB: - r = r600_cb_create(rdev, atoms, atom, cont->data); - if (r) - return r; - break; - case R600_ATOM_CB_CNTL: - r = r600_cb_cntl_create(rdev, atoms, atom, cont->data); - if (r) - return r; - break; - case R600_ATOM_PA: - r = r600_pa_create(rdev, atoms, atom, cont->data); - if (r) - return r; - break; - case R600_ATOM_VPORT: - r = r600_vport_create(rdev, atoms, atom, cont->data); - if (r) - return r; - break; - case R600_ATOM_BLEND: - r = r600_blend_create(rdev, atoms, atom, cont->data); - if (r) - return r; - break; - case R600_ATOM_CONSTANTS: - r = r600_constants_create(rdev, atoms, atom, cont->data); - if (r) - return r; - break; - case R600_ATOM_DB: - r = r600_db_create(rdev, atoms, atom, cont->data); - if (r) - return r; - break; - case R600_ATOM_DB_CNTL: - r = r600_db_cntl_create(rdev, atoms, atom, cont->data); - if (r) - return r; - break; - case R600_ATOM_VS_SHADER: - r = r600_vs_shader_create(rdev, atoms, atom, cont->data); - if (r) - return r; - break; - case R600_ATOM_PS_SHADER: - r = r600_ps_shader_create(rdev, atoms, atom, cont->data); - if (r) - return r; - break; - default: - dev_err(rdev->dev, "unknown R600 atom type 0x%08X\n", patom->type); - return -EINVAL; - } - patom->id = atom->id; - *atomptr = atom; - mutex_unlock(&atoms->mutex); - return 0; -} - -/* - * r600_batch - */ -static int r600_batch_alloc(struct r600_batch **batch) -{ - struct r600_batch *rbatch; - - *batch = NULL; - rbatch = malloc(sizeof(*rbatch)); - if (rbatch == NULL) - return -ENOMEM; - INIT_LIST_HEAD(&rbatch->list); - INIT_LIST_HEAD(&rbatch->pre_flushes); - INIT_LIST_HEAD(&rbatch->post_flushes); - rbatch->nemit_atoms = 0; - rbatch->shaders_idx = 0; - rbatch->nfs_resources = 0; - *batch = rbatch; - return 0; -} - -/* - * r600_batches - */ -static int r600_batches_fs_resource_is_present(struct radeon_device *rdev, - struct r600_batches *batches, - struct drm_r600_vs_buffer *buffer) -{ - int i; - - for (i = 0; i < batches->nfs_resources; i++) { - if (!memcmp(&batches->fs_resource[i], buffer, sizeof(struct drm_r600_vs_buffer))) { - buffer->resource_id = i; - return 1; - } - } - return 0; -} - -static int r600_batches_fs_resource_add(struct radeon_device *rdev, - struct r600_batches *batches, - struct drm_r600_vs_buffer *buffer) -{ - int i = batches->nfs_resources++; - - buffer->resource_id = i; - memcpy(&batches->fs_resource[i].drm, buffer, sizeof(struct drm_r600_vs_buffer)); - batches->fs_resource[i].bo = radeon_bo_lookup(rdev, buffer->handle); - if (batches->fs_resource[i].bo == NULL) - return -EINVAL; - return 0; -} - -static void r600_batches_clear_locked(struct radeon_device *rdev, struct r600_batches *batches) -{ - struct r600_batch *batch, *n; - int i; - - list_for_each_entry_safe(batch, n, &batches->batches, list) { - for (i = 0; i < R600_BATCH_NATOMS; i++) { - if (batch->atoms[i]) - radeon_atom_put(batch->atoms[i]); - } - radeon_atom_flush_cleanup(&batch->pre_flushes); - radeon_atom_flush_cleanup(&batch->post_flushes); - list_del(&batch->list); - radeon_bo_unmap(batch->shaders); - radeon_bo_unref(batch->shaders); - kfree(batch); - } - INIT_LIST_HEAD(&batches->batches); - for (i = 0; i < batches->nfs_resources; i++) { - radeon_bo_unref(batches->fs_resource[i].bo); - } - batches->nfs_resources = 0; - r700_batches_states_default(rdev, batches); - batches->npkts = batches->ib->cpkts; -} - -static int r600_batches_flush_locked(struct radeon_device *rdev, struct r600_batches *batches) -{ - struct r600_batch *batch; - struct radeon_atom_flush *flush; - int r, i; - - for (i = 0; i < batches->nfs_resources; i++) { - r600_emit_resources(rdev, batches->ib, batches->fs_resource[i].bo, - (batches->fs_resource[i].drm.resource_id + 160) * 7, - batches->fs_resource[i].drm.sq_vtx_constant_word0, - radeon_bo_size(batches->fs_resource[i].bo) - - batches->fs_resource[i].drm.sq_vtx_constant_word0, - batches->fs_resource[i].drm.sq_vtx_constant_word2, - batches->fs_resource[i].drm.sq_vtx_constant_word3, - 0, 0, 0xC0000000); - } - list_for_each_entry(batch, &batches->batches, list) { - list_for_each_entry(flush, &batch->pre_flushes, list) { - r600_emit_flush(rdev, batches->ib, flush->bo, flush->flags); - } - /* FIXME shader flush should be conditional */ - r600_emit_flush(rdev, batches->ib, batch->shaders, 0x08000000); - for (i = 0; i < batch->nemit_atoms; i++) { - r = batch->emit_atoms[i]->emit(rdev, batch->emit_atoms[i], batch, batches->ib); - if (r) - goto out_err; - } - /* flush + wait until */ - batches->ib->ptr[batches->ib->cpkts++] = PKT3(PKT3_EVENT_WRITE, 0); - batches->ib->ptr[batches->ib->cpkts++] = 0x00000016; - batches->ib->ptr[batches->ib->cpkts++] = PKT3(PKT3_SET_CONFIG_REG, 1); - batches->ib->ptr[batches->ib->cpkts++] = 0x00000010; - batches->ib->ptr[batches->ib->cpkts++] = 0x00028000; - list_for_each_entry(flush, &batch->post_flushes, list) { - r600_emit_flush(rdev, batches->ib, flush->bo, flush->flags); - } - } - r = radeon_ib_schedule(rdev, batches->ib); -out_err: - /* FIXME helper function */ - batches->ib->cpkts = 0; - batches->ib->nrelocs = 0; - r600_batches_clear_locked(rdev, batches); - return r; -} - -int r600_batches_queue(struct radeon_device *rdev, - struct r600_atoms *atoms, - struct drm_r600_batch *batch) -{ - struct r600_batch *rbatch; - struct r600_batches *batches = &atoms->batches; - int r, i, j; - - r = r600_batch_alloc(&rbatch); - if (r) - return r; - memcpy(&rbatch->inputs, &batch->inputs, sizeof(struct r600_vs_input)); - mutex_lock(&atoms->mutex); - i = 0; - if (batch->blend == NULL || batch->cb_cntl == NULL || - batch->pa == NULL || batch->vport == NULL || - batch->cb == NULL || batch->db_cntl == NULL || - batch->vs_shader == NULL || batch->ps_shader == NULL) { - mutex_unlock(&atoms->mutex); - free(rbatch); - dev_err(rdev->dev, "invalid batch\n"); - return -EINVAL; - } - rbatch->shaders = radeon_bo_open(rdev->radeon->bom, 0, R600_SHADER_SIZE, 0, RADEON_GEM_DOMAIN_GTT, 0); - if (rbatch->shaders == NULL) { - mutex_unlock(&atoms->mutex); - kfree(rbatch); - dev_err(rdev->dev, "can't create buffer for shaders\n"); - return -ENOMEM; - } - r = radeon_bo_map(rbatch->shaders, 1); - if (r) { - mutex_unlock(&atoms->mutex); - kfree(rbatch); - dev_err(rdev->dev, "can't map buffer for shaders\n"); - return r; - } - rbatch->atoms[i++] = batch->blend; kref_get(&batch->blend->kref); - rbatch->atoms[i++] = batch->cb_cntl; kref_get(&batch->cb_cntl->kref); - rbatch->atoms[i++] = batch->pa; kref_get(&batch->pa->kref); - rbatch->atoms[i++] = batch->vport; kref_get(&batch->vport->kref); - rbatch->atoms[i++] = batch->vs_shader; kref_get(&batch->vs_shader->kref); - rbatch->atoms[i++] = batch->ps_shader; kref_get(&batch->ps_shader->kref); - rbatch->atoms[i++] = batch->db_cntl; kref_get(&batch->db_cntl->kref); - rbatch->atoms[i++] = batch->vs_constants; - if (batch->vs_constants) - kref_get(&batch->vs_constants->kref); - rbatch->atoms[i++] = batch->ps_constants; - if (batch->ps_constants) - kref_get(&batch->ps_constants->kref); - rbatch->atoms[i++] = batch->db; - if (batch->db) - kref_get(&batch->db->kref); - rbatch->atoms[i++] = batch->cb; kref_get(&batch->cb->kref); -reprocess: - radeon_atom_flush_cleanup(&rbatch->pre_flushes); - radeon_atom_flush_cleanup(&rbatch->post_flushes); - rbatch->nflushes = 0; - rbatch->npkts = 0; - /* flush + wait until = 5dw */ - rbatch->npkts += 5; - for (i = 0; i < rbatch->inputs.drm.nbuffers; i++) { - if (!r600_batches_fs_resource_is_present(rdev, batches, &rbatch->inputs.drm.buffers[i])) { - rbatch->nfs_resources += 1; - rbatch->inputs.drm.buffers[i].resource_id = -1; - } - } - rbatch->npkts += rbatch->nfs_resources * 18; - for (i = 0; i < R600_BATCH_NATOMS; i++) { - if (rbatch->atoms[i]) { - for (j = 0; j < rbatch->atoms[i]->nbo; j++) { - r = radeon_atom_flush_add(&rbatch->pre_flushes, rbatch->atoms[i]->bo[j], rbatch->atoms[i]->flags[j]); - if (r < 0) - goto out_err; - } - rbatch->nflushes += rbatch->atoms[i]->nbo; - if (batches->last_id[i] != rbatch->atoms[i]->id) - rbatch->emit_atoms[rbatch->nemit_atoms++] = rbatch->atoms[i]; - } - } - /* add flush */ - rbatch->npkts += rbatch->nflushes * 7; - /* FIXME shader flush should be conditional only if we change shaders */ - rbatch->npkts += 7; - /* if batch is bigger than ib size it's an invalid one, this should - * not happen - */ - if (rbatch->npkts > batches->ib->length_dw) { - dev_err(rdev->dev, "single batch to big (%d) to fit into ib (%d)\n", - rbatch->npkts, batches->ib->length_dw); - goto out_err; - } - /* flush or not ? */ - if (batches->npkts + rbatch->npkts > batches->ib->length_dw) { - r = r600_batches_flush_locked(rdev, batches); - if (r) - goto out_err; - goto reprocess; - } - /* batch is queued */ - for (i = 0; i < R600_BATCH_NATOMS; i++) { - if (rbatch->atoms[i]) { - batches->last_id[i] = rbatch->atoms[i]->id; - } - } - radeon_device_set_bo_list(rdev, rbatch->inputs.nbo, rbatch->inputs.bo); - for (i = 0; i < rbatch->inputs.drm.nbuffers; i++) { - if (rbatch->inputs.drm.buffers[i].resource_id == -1) { - r = r600_batches_fs_resource_add(rdev, batches, &rbatch->inputs.drm.buffers[i]); - if (r) - goto out_err; - } - } - batches->npkts += rbatch->npkts; - list_add_tail(&rbatch->list, &batches->batches); - mutex_unlock(&atoms->mutex); - return 0; -out_err: - for (i = 0; i < R600_BATCH_NATOMS; i++) { - if (rbatch->atoms[i]) - radeon_atom_put(rbatch->atoms[i]); - } - mutex_unlock(&rdev->asic.r700.atom.mutex); - radeon_bo_unmap(rbatch->shaders); - radeon_bo_unref(rbatch->shaders); - free(rbatch); - return r; -} - -static int r600_batches_init(struct radeon_device *rdev, struct r600_batches *batches) -{ - int r; - - memset(batches, 0 , sizeof(struct r600_batches)); - INIT_LIST_HEAD(&batches->batches); - r = radeon_ib_get(rdev, &batches->ib); - if (r) - return r; - r700_batches_states_default(rdev, batches); - batches->npkts = batches->ib->cpkts; - return 0; -} - -static void r600_batches_cleanup_locked(struct radeon_device *rdev, struct r600_batches *batches) -{ - r600_batches_clear_locked(rdev, batches); - radeon_ib_free(batches->ib); - batches->ib = NULL; -} - -int r600_batches_flush(struct radeon_device *rdev, struct r600_atoms *atoms) -{ - int r; - - mutex_lock(&atoms->mutex); - r = r600_batches_flush_locked(rdev, &atoms->batches); - mutex_unlock(&atoms->mutex); - return r; -} - -int r600_atoms_init(struct radeon_device *rdev, struct r600_atoms *atoms) -{ - memset(atoms, 0, sizeof(*atoms)); - mutex_init(&atoms->mutex); - INIT_LIST_HEAD(&atoms->blend_atoms); - INIT_LIST_HEAD(&atoms->cb_atoms); - INIT_LIST_HEAD(&atoms->cb_cntl_atoms); - INIT_LIST_HEAD(&atoms->constants_atoms); - INIT_LIST_HEAD(&atoms->db_atoms); - INIT_LIST_HEAD(&atoms->db_cntl_atoms); - INIT_LIST_HEAD(&atoms->pa_atoms); - INIT_LIST_HEAD(&atoms->sq_atoms); - INIT_LIST_HEAD(&atoms->vport_atoms); - INIT_LIST_HEAD(&atoms->vs_shader_atoms); - INIT_LIST_HEAD(&atoms->ps_shader_atoms); - idr_init(&atoms->idr); - atoms->npipes = 2; - atoms->nbanks = 4; - atoms->group_bytes = 256; - return r600_batches_init(rdev, &atoms->batches); -} - -void r600_atoms_release(struct radeon_device *rdev, struct r600_atoms *atoms) -{ - mutex_lock(&atoms->mutex); - r600_batches_cleanup_locked(rdev, &atoms->batches); - idr_destroy(&atoms->idr); - mutex_unlock(&atoms->mutex); -} diff --git a/r600_atom_api.h b/r600_atom_api.h deleted file mode 100644 index 0ee7208..0000000 --- a/r600_atom_api.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright © 2010 Jerome Glisse <glisse@freedesktop.org> - * - * This file is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#ifndef R600_ATOM_API_H -#define R600_ATOM_API_H - -#endif diff --git a/r600_batch.c b/r600_batch.c new file mode 100644 index 0000000..db44a0b --- /dev/null +++ b/r600_batch.c @@ -0,0 +1,521 @@ +/* + * Copyright © 2010 Jerome Glisse <glisse@freedesktop.org> + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "radeon.h" +#include "radeon_device.h" +#include "r600d.h" + +/* state creation functions prototype */ +int r600_cb_emit(struct radeon_device *rdev, + struct radeon_atom *atom, + void *data, + struct radeon_ib *ib); +int r600_cb_create(struct radeon_device *rdev, + struct r600_atoms *atoms, + struct radeon_atom *atom, + void *data); +int r600_cb_cntl_create(struct radeon_device *rdev, + struct r600_atoms *atoms, + struct radeon_atom *atom, + void *data); +int r600_pa_create(struct radeon_device *rdev, + struct r600_atoms *atoms, + struct radeon_atom *atom, + void *data); +int r600_vport_create(struct radeon_device *rdev, + struct r600_atoms *atoms, + struct radeon_atom *atom, + void *data); +int r600_blend_create(struct radeon_device *rdev, + struct r600_atoms *atoms, + struct radeon_atom *atom, + void *data); +int r600_constants_create(struct radeon_device *rdev, + struct r600_atoms *atoms, + struct radeon_atom *atom, + void *data); +int r600_db_emit(struct radeon_device *rdev, + struct radeon_atom *atom, + void *data, + struct radeon_ib *ib); +int r600_db_create(struct radeon_device *rdev, + struct r600_atoms *atoms, + struct radeon_atom *atom, + void *data); +int r600_db_cntl_create(struct radeon_device *rdev, + struct r600_atoms *atoms, + struct radeon_atom *atom, + void *data); +int r600_vs_shader_emit(struct radeon_device *rdev, + struct radeon_atom *atom, + void *data, + struct radeon_ib *ib); +int r600_vs_shader_create(struct radeon_device *rdev, + struct r600_atoms *atoms, + struct radeon_atom *atom, + void *data); +int r600_ps_shader_emit(struct radeon_device *rdev, + struct radeon_atom *atom, + void *data, + struct radeon_ib *ib); +int r600_ps_shader_create(struct radeon_device *rdev, + struct r600_atoms *atoms, + struct radeon_atom *atom, + void *data); + +/* + * helpers functions + */ +static void r600_emit_flush(struct radeon_device *rdev, + struct radeon_ib *ib, + struct radeon_bo *bo, + u32 flags) +{ + ib->ptr[ib->cpkts++] = PKT3(PKT3_SURFACE_SYNC, 3); + ib->ptr[ib->cpkts++] = flags; + ib->ptr[ib->cpkts++] = radeon_bo_size(bo) >> 8; + ib->ptr[ib->cpkts++] = 0x00000000; + ib->ptr[ib->cpkts++] = 0x0000000A; + ib->ptr[ib->cpkts++] = PKT3(PKT3_NOP, 0); + ib->ptr[ib->cpkts++] = radeon_ib_reloc(ib, bo, RADEON_GEM_DOMAIN_VRAM | + RADEON_GEM_DOMAIN_GTT); +} + +static void r600_emit_resources(struct radeon_device *rdev, + struct radeon_ib *ib, + struct radeon_bo *bo, + u32 dw0, u32 dw1, u32 dw2, u32 dw3, + u32 dw4, u32 dw5, u32 dw6, u32 dw7) +{ + ib->ptr[ib->cpkts++] = PKT3(PKT3_SURFACE_SYNC, 3); + ib->ptr[ib->cpkts++] = 0x01000000; + ib->ptr[ib->cpkts++] = radeon_bo_size(bo) >> 8; + ib->ptr[ib->cpkts++] = 0x00000000; + ib->ptr[ib->cpkts++] = 0x0000000A; + ib->ptr[ib->cpkts++] = PKT3(PKT3_NOP, 0); + ib->ptr[ib->cpkts++] = radeon_ib_reloc(ib, bo, RADEON_GEM_DOMAIN_VRAM | + RADEON_GEM_DOMAIN_GTT); + ib->ptr[ib->cpkts++] = PKT3(PKT3_SET_RESOURCE, 7); + ib->ptr[ib->cpkts++] = dw0; + ib->ptr[ib->cpkts++] = dw1; + ib->ptr[ib->cpkts++] = dw2; + ib->ptr[ib->cpkts++] = dw3; + ib->ptr[ib->cpkts++] = dw4; + ib->ptr[ib->cpkts++] = dw5; + ib->ptr[ib->cpkts++] = dw6; + ib->ptr[ib->cpkts++] = dw7; + ib->ptr[ib->cpkts++] = PKT3(PKT3_NOP, 0); + ib->ptr[ib->cpkts++] = radeon_ib_reloc(ib, bo, RADEON_GEM_DOMAIN_VRAM | + RADEON_GEM_DOMAIN_GTT); +} + +/* + * r600_batch + */ +static int r600_batch_alloc(struct r600_batch **batch) +{ + struct r600_batch *rbatch; + + *batch = NULL; + rbatch = malloc(sizeof(*rbatch)); + if (rbatch == NULL) + return -ENOMEM; + INIT_LIST_HEAD(&rbatch->list); + INIT_LIST_HEAD(&rbatch->pre_flushes); + INIT_LIST_HEAD(&rbatch->post_flushes); + rbatch->nemit_atoms = 0; + rbatch->shaders_idx = 0; + rbatch->nfs_resources = 0; + *batch = rbatch; + return 0; +} + +/* + * r600_batches + */ +static int r600_batches_fs_resource_is_present(struct radeon_device *rdev, + struct r600_batches *batches, + struct drm_r600_vs_buffer *buffer) +{ + int i; + + for (i = 0; i < batches->nfs_resources; i++) { + if (!memcmp(&batches->fs_resource[i], buffer, sizeof(struct drm_r600_vs_buffer))) { + buffer->resource_id = i; + return 1; + } + } + return 0; +} + +static int r600_batches_fs_resource_add(struct radeon_device *rdev, + struct r600_batches *batches, + struct drm_r600_vs_buffer *buffer) +{ + int i = batches->nfs_resources++; + + buffer->resource_id = i; + memcpy(&batches->fs_resource[i].drm, buffer, sizeof(struct drm_r600_vs_buffer)); + batches->fs_resource[i].bo = radeon_bo_lookup(rdev, buffer->handle); + if (batches->fs_resource[i].bo == NULL) + return -EINVAL; + return 0; +} + +static void r600_batches_clear_locked(struct radeon_device *rdev, struct r600_batches *batches) +{ + struct r600_batch *batch, *n; + int i; + + list_for_each_entry_safe(batch, n, &batches->batches, list) { + for (i = 0; i < R600_BATCH_NATOMS; i++) { + if (batch->atoms[i]) + radeon_atom_put(batch->atoms[i]); + } + radeon_atom_flush_cleanup(&batch->pre_flushes); + radeon_atom_flush_cleanup(&batch->post_flushes); + list_del(&batch->list); + radeon_bo_unmap(batch->shaders); + radeon_bo_unref(batch->shaders); + kfree(batch); + } + INIT_LIST_HEAD(&batches->batches); + for (i = 0; i < batches->nfs_resources; i++) { + radeon_bo_unref(batches->fs_resource[i].bo); + } + batches->nfs_resources = 0; + r700_batches_states_default(rdev, batches); + batches->npkts = batches->ib->cpkts; +} + +static int r600_batches_flush_locked(struct radeon_device *rdev, struct r600_batches *batches) +{ + struct r600_batch *batch; + struct radeon_atom_flush *flush; + int r, i; + + for (i = 0; i < batches->nfs_resources; i++) { + r600_emit_resources(rdev, batches->ib, batches->fs_resource[i].bo, + (batches->fs_resource[i].drm.resource_id + 160) * 7, + batches->fs_resource[i].drm.sq_vtx_constant_word0, + radeon_bo_size(batches->fs_resource[i].bo) - + batches->fs_resource[i].drm.sq_vtx_constant_word0, + batches->fs_resource[i].drm.sq_vtx_constant_word2, + batches->fs_resource[i].drm.sq_vtx_constant_word3, + 0, 0, 0xC0000000); + } + list_for_each_entry(batch, &batches->batches, list) { + list_for_each_entry(flush, &batch->pre_flushes, list) { + r600_emit_flush(rdev, batches->ib, flush->bo, flush->flags); + } + /* FIXME shader flush should be conditional */ + r600_emit_flush(rdev, batches->ib, batch->shaders, 0x08000000); + for (i = 0; i < batch->nemit_atoms; i++) { + r = batch->emit_atoms[i]->emit(rdev, batch->emit_atoms[i], batch, batches->ib); + if (r) + goto out_err; + } + /* flush + wait until */ + batches->ib->ptr[batches->ib->cpkts++] = PKT3(PKT3_EVENT_WRITE, 0); + batches->ib->ptr[batches->ib->cpkts++] = 0x00000016; + batches->ib->ptr[batches->ib->cpkts++] = PKT3(PKT3_SET_CONFIG_REG, 1); + batches->ib->ptr[batches->ib->cpkts++] = 0x00000010; + batches->ib->ptr[batches->ib->cpkts++] = 0x00028000; + list_for_each_entry(flush, &batch->post_flushes, list) { + r600_emit_flush(rdev, batches->ib, flush->bo, flush->flags); + } + } + r = radeon_ib_schedule(rdev, batches->ib); +out_err: + /* FIXME helper function */ + batches->ib->cpkts = 0; + batches->ib->nrelocs = 0; + r600_batches_clear_locked(rdev, batches); + return r; +} + +int r600_batches_queue(struct radeon_device *rdev, + struct r600_atoms *atoms, + struct drm_r600_batch *batch) +{ + struct r600_batch *rbatch; + struct r600_batches *batches = &atoms->batches; + int r, i, j; + + r = r600_batch_alloc(&rbatch); + if (r) + return r; + memcpy(&rbatch->inputs, &batch->inputs, sizeof(struct r600_vs_input)); + mutex_lock(&atoms->mutex); + i = 0; + if (batch->blend == NULL || batch->cb_cntl == NULL || + batch->pa == NULL || batch->vport == NULL || + batch->cb == NULL || batch->db_cntl == NULL || + batch->vs_shader == NULL || batch->ps_shader == NULL) { + mutex_unlock(&atoms->mutex); + free(rbatch); + dev_err(rdev->dev, "invalid batch\n"); + return -EINVAL; + } + rbatch->shaders = radeon_bo_open(rdev->radeon->bom, 0, R600_SHADER_SIZE, 0, RADEON_GEM_DOMAIN_GTT, 0); + if (rbatch->shaders == NULL) { + mutex_unlock(&atoms->mutex); + kfree(rbatch); + dev_err(rdev->dev, "can't create buffer for shaders\n"); + return -ENOMEM; + } + r = radeon_bo_map(rbatch->shaders, 1); + if (r) { + mutex_unlock(&atoms->mutex); + kfree(rbatch); + dev_err(rdev->dev, "can't map buffer for shaders\n"); + return r; + } + rbatch->atoms[i++] = batch->blend; kref_get(&batch->blend->kref); + rbatch->atoms[i++] = batch->cb_cntl; kref_get(&batch->cb_cntl->kref); + rbatch->atoms[i++] = batch->pa; kref_get(&batch->pa->kref); + rbatch->atoms[i++] = batch->vport; kref_get(&batch->vport->kref); + rbatch->atoms[i++] = batch->vs_shader; kref_get(&batch->vs_shader->kref); + rbatch->atoms[i++] = batch->ps_shader; kref_get(&batch->ps_shader->kref); + rbatch->atoms[i++] = batch->db_cntl; kref_get(&batch->db_cntl->kref); + rbatch->atoms[i++] = batch->vs_constants; + if (batch->vs_constants) + kref_get(&batch->vs_constants->kref); + rbatch->atoms[i++] = batch->ps_constants; + if (batch->ps_constants) + kref_get(&batch->ps_constants->kref); + rbatch->atoms[i++] = batch->db; + if (batch->db) + kref_get(&batch->db->kref); + rbatch->atoms[i++] = batch->cb; kref_get(&batch->cb->kref); +reprocess: + radeon_atom_flush_cleanup(&rbatch->pre_flushes); + radeon_atom_flush_cleanup(&rbatch->post_flushes); + rbatch->nflushes = 0; + rbatch->npkts = 0; + /* flush + wait until = 5dw */ + rbatch->npkts += 5; + for (i = 0; i < rbatch->inputs.drm.nbuffers; i++) { + if (!r600_batches_fs_resource_is_present(rdev, batches, &rbatch->inputs.drm.buffers[i])) { + rbatch->nfs_resources += 1; + rbatch->inputs.drm.buffers[i].resource_id = -1; + } + } + rbatch->npkts += rbatch->nfs_resources * 18; + for (i = 0; i < R600_BATCH_NATOMS; i++) { + if (rbatch->atoms[i]) { + for (j = 0; j < rbatch->atoms[i]->nbo; j++) { + r = radeon_atom_flush_add(&rbatch->pre_flushes, rbatch->atoms[i]->bo[j], rbatch->atoms[i]->flags[j]); + if (r < 0) + goto out_err; + } + rbatch->nflushes += rbatch->atoms[i]->nbo; + if (batches->last_id[i] != rbatch->atoms[i]->id) + rbatch->emit_atoms[rbatch->nemit_atoms++] = rbatch->atoms[i]; + } + } + /* add flush */ + rbatch->npkts += rbatch->nflushes * 7; + /* FIXME shader flush should be conditional only if we change shaders */ + rbatch->npkts += 7; + /* if batch is bigger than ib size it's an invalid one, this should + * not happen + */ + if (rbatch->npkts > batches->ib->length_dw) { + dev_err(rdev->dev, "single batch to big (%d) to fit into ib (%d)\n", + rbatch->npkts, batches->ib->length_dw); + goto out_err; + } + /* flush or not ? */ + if (batches->npkts + rbatch->npkts > batches->ib->length_dw) { + r = r600_batches_flush_locked(rdev, batches); + if (r) + goto out_err; + goto reprocess; + } + /* batch is queued */ + for (i = 0; i < R600_BATCH_NATOMS; i++) { + if (rbatch->atoms[i]) { + batches->last_id[i] = rbatch->atoms[i]->id; + } + } + radeon_device_set_bo_list(rdev, rbatch->inputs.nbo, rbatch->inputs.bo); + for (i = 0; i < rbatch->inputs.drm.nbuffers; i++) { + if (rbatch->inputs.drm.buffers[i].resource_id == -1) { + r = r600_batches_fs_resource_add(rdev, batches, &rbatch->inputs.drm.buffers[i]); + if (r) + goto out_err; + } + } + batches->npkts += rbatch->npkts; + list_add_tail(&rbatch->list, &batches->batches); + mutex_unlock(&atoms->mutex); + return 0; +out_err: + for (i = 0; i < R600_BATCH_NATOMS; i++) { + if (rbatch->atoms[i]) + radeon_atom_put(rbatch->atoms[i]); + } + mutex_unlock(&rdev->asic.r700.atom.mutex); + radeon_bo_unmap(rbatch->shaders); + radeon_bo_unref(rbatch->shaders); + free(rbatch); + return r; +} + +static int r600_batches_init(struct radeon_device *rdev, struct r600_batches *batches) +{ + int r; + + memset(batches, 0 , sizeof(struct r600_batches)); + INIT_LIST_HEAD(&batches->batches); + r = radeon_ib_get(rdev, &batches->ib); + if (r) + return r; + r700_batches_states_default(rdev, batches); + batches->npkts = batches->ib->cpkts; + return 0; +} + +static void r600_batches_cleanup_locked(struct radeon_device *rdev, struct r600_batches *batches) +{ + r600_batches_clear_locked(rdev, batches); + radeon_ib_free(batches->ib); + batches->ib = NULL; +} + +int r600_batches_flush(struct radeon_device *rdev, struct r600_atoms *atoms) +{ + int r; + + mutex_lock(&atoms->mutex); + r = r600_batches_flush_locked(rdev, &atoms->batches); + mutex_unlock(&atoms->mutex); + return r; +} + +int r600_atoms_init(struct radeon_device *rdev, struct r600_atoms *atoms) +{ + memset(atoms, 0, sizeof(*atoms)); + mutex_init(&atoms->mutex); + INIT_LIST_HEAD(&atoms->blend_atoms); + INIT_LIST_HEAD(&atoms->cb_atoms); + INIT_LIST_HEAD(&atoms->cb_cntl_atoms); + INIT_LIST_HEAD(&atoms->constants_atoms); + INIT_LIST_HEAD(&atoms->db_atoms); + INIT_LIST_HEAD(&atoms->db_cntl_atoms); + INIT_LIST_HEAD(&atoms->pa_atoms); + INIT_LIST_HEAD(&atoms->sq_atoms); + INIT_LIST_HEAD(&atoms->vport_atoms); + INIT_LIST_HEAD(&atoms->vs_shader_atoms); + INIT_LIST_HEAD(&atoms->ps_shader_atoms); + idr_init(&atoms->idr); + atoms->npipes = 2; + atoms->nbanks = 4; + atoms->group_bytes = 256; + return r600_batches_init(rdev, &atoms->batches); +} + +void r600_atoms_release(struct radeon_device *rdev, struct r600_atoms *atoms) +{ + mutex_lock(&atoms->mutex); + r600_batches_cleanup_locked(rdev, &atoms->batches); + idr_destroy(&atoms->idr); + mutex_unlock(&atoms->mutex); +} + +/* + * r600 atom core functions + */ +int r600_atom_create(struct radeon_device *rdev, + struct r600_atoms *atoms, + struct drm_radeon_atom *patom, + struct radeon_atom **atomptr) +{ + struct radeon_atom *atom; + struct r600_state_container *cont; + int r; + + *atomptr = NULL; + atom = malloc(sizeof(struct radeon_atom)); + if (atom == NULL) + return -ENOMEM; + memset(atom, 0, sizeof(struct radeon_atom)); + cont = patom->data; + patom->id = 0; + radeon_device_set_bo_list(rdev, cont->nbo, cont->bo); + atom->type = patom->type; + mutex_lock(&atoms->mutex); + switch (patom->type) { + case R600_ATOM_CB: + r = r600_cb_create(rdev, atoms, atom, cont->data); + if (r) + return r; + break; + case R600_ATOM_CB_CNTL: + r = r600_cb_cntl_create(rdev, atoms, atom, cont->data); + if (r) + return r; + break; + case R600_ATOM_PA: + r = r600_pa_create(rdev, atoms, atom, cont->data); + if (r) + return r; + break; + case R600_ATOM_VPORT: + r = r600_vport_create(rdev, atoms, atom, cont->data); + if (r) + return r; + break; + case R600_ATOM_BLEND: + r = r600_blend_create(rdev, atoms, atom, cont->data); + if (r) + return r; + break; + case R600_ATOM_CONSTANTS: + r = r600_constants_create(rdev, atoms, atom, cont->data); + if (r) + return r; + break; + case R600_ATOM_DB: + r = r600_db_create(rdev, atoms, atom, cont->data); + if (r) + return r; + break; + case R600_ATOM_DB_CNTL: + r = r600_db_cntl_create(rdev, atoms, atom, cont->data); + if (r) + return r; + break; + case R600_ATOM_VS_SHADER: + r = r600_vs_shader_create(rdev, atoms, atom, cont->data); + if (r) + return r; + break; + case R600_ATOM_PS_SHADER: + r = r600_ps_shader_create(rdev, atoms, atom, cont->data); + if (r) + return r; + break; + default: + dev_err(rdev->dev, "unknown R600 atom type 0x%08X\n", patom->type); + return -EINVAL; + } + patom->id = atom->id; + *atomptr = atom; + mutex_unlock(&atoms->mutex); + return 0; +} |