#include "pipe/p_util.h"
#include "nv40_context.h"
-#include "nv40_dma.h"
-static boolean
-nv40_is_format_supported(struct pipe_context *pipe, uint format)
-{
- switch (format) {
- case PIPE_FORMAT_A8R8G8B8_UNORM:
- case PIPE_FORMAT_R5G6B5_UNORM:
- case PIPE_FORMAT_Z24S8_UNORM:
- return TRUE;
- default:
- break;
- };
-
- return FALSE;
-}
+#define NV4X_GRCLASS4097_CHIPSETS 0x00000baf
+#define NV4X_GRCLASS4497_CHIPSETS 0x00005450
+#define NV6X_GRCLASS4497_CHIPSETS 0x00000080
static const char *
nv40_get_name(struct pipe_context *pipe)
{
- struct nv40_context *nv40 = (struct nv40_context *)pipe;
+ struct nv40_context *nv40 = nv40_context(pipe);
static char buffer[128];
snprintf(buffer, sizeof(buffer), "NV%02X", nv40->chipset);
case PIPE_CAP_OCCLUSION_QUERY:
return 1;
case PIPE_CAP_TEXTURE_SHADOW_MAP:
- return 0;
+ return 1;
case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
return 13;
case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
return 16.0;
case PIPE_CAP_MAX_TEXTURE_LOD_BIAS:
return 4.0;
+ case PIPE_CAP_BITMAP_TEXCOORD_BIAS:
+ return 0.0;
default:
NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
return 0.0;
static void
nv40_flush(struct pipe_context *pipe, unsigned flags)
{
- struct nv40_context *nv40 = (struct nv40_context *)pipe;
+ struct nv40_context *nv40 = nv40_context(pipe);
struct nouveau_winsys *nvws = nv40->nvws;
if (flags & PIPE_FLUSH_TEXTURE_CACHE) {
}
if (flags & PIPE_FLUSH_WAIT) {
- nvws->notifier_reset(nv40->sync, 0);
+ nvws->notifier_reset(nv40->hw->sync, 0);
BEGIN_RING(curie, 0x104, 1);
OUT_RING (0);
BEGIN_RING(curie, 0x100, 1);
FIRE_RING();
if (flags & PIPE_FLUSH_WAIT)
- nvws->notifier_wait(nv40->sync, 0, 0, 2000);
+ nvws->notifier_wait(nv40->hw->sync, 0, 0, 2000);
}
static void
-nv40_destroy(struct pipe_context *pipe)
+nv40_channel_takedown(struct nv40_channel_context *cnv40)
{
- struct nv40_context *nv40 = (struct nv40_context *)pipe;
-
- draw_destroy(nv40->draw);
- free(nv40);
+ struct nouveau_winsys *nvws = cnv40->nvws;
+
+ nvws->res_free(&cnv40->vp_exec_heap);
+ nvws->res_free(&cnv40->vp_data_heap);
+ nvws->res_free(&cnv40->query_heap);
+ nvws->notifier_free(&cnv40->query);
+ nvws->notifier_free(&cnv40->sync);
+ nvws->grobj_free(&cnv40->curie);
+ free(cnv40);
}
-static boolean
-nv40_init_hwctx(struct nv40_context *nv40, int curie_class)
+static struct nv40_channel_context *
+nv40_channel_init(struct pipe_winsys *ws, struct nouveau_winsys *nvws,
+ unsigned chipset)
{
- struct nouveau_winsys *nvws = nv40->nvws;
+ struct nv40_channel_context *cnv40 = NULL;
+ struct nouveau_stateobj *so;
+ unsigned curie_class = 0;
int ret;
- if ((ret = nvws->notifier_alloc(nvws, nv40->num_query_objects,
- &nv40->query))) {
- NOUVEAU_ERR("Error creating query notifier objects: %d\n", ret);
- return FALSE;
+ switch (chipset & 0xf0) {
+ case 0x40:
+ if (NV4X_GRCLASS4097_CHIPSETS & (1 << (chipset & 0x0f)))
+ curie_class = NV40TCL;
+ else
+ if (NV4X_GRCLASS4497_CHIPSETS & (1 << (chipset & 0x0f)))
+ curie_class = NV44TCL;
+ break;
+ case 0x60:
+ if (NV6X_GRCLASS4497_CHIPSETS & (1 << (chipset & 0x0f)))
+ curie_class = NV44TCL;
+ break;
+ default:
+ break;
}
- if ((ret = nvws->grobj_alloc(nvws, curie_class,
- &nv40->curie))) {
- NOUVEAU_ERR("Error creating 3D object: %d\n", ret);
- return FALSE;
+ if (!curie_class) {
+ NOUVEAU_ERR("Unknown nv4x chipset: nv%02x\n", chipset);
+ return NULL;
}
- BEGIN_RING(curie, NV40TCL_DMA_NOTIFY, 1);
- OUT_RING (nv40->sync->handle);
- BEGIN_RING(curie, NV40TCL_DMA_TEXTURE0, 2);
- OUT_RING (nvws->channel->vram->handle);
- OUT_RING (nvws->channel->gart->handle);
- BEGIN_RING(curie, NV40TCL_DMA_COLOR1, 1);
- OUT_RING (nvws->channel->vram->handle);
- BEGIN_RING(curie, NV40TCL_DMA_COLOR0, 2);
- OUT_RING (nvws->channel->vram->handle);
- OUT_RING (nvws->channel->vram->handle);
- BEGIN_RING(curie, NV40TCL_DMA_VTXBUF0, 2);
- OUT_RING (nvws->channel->vram->handle);
- OUT_RING (nvws->channel->gart->handle);
- BEGIN_RING(curie, NV40TCL_DMA_FENCE, 2);
- OUT_RING (0);
- OUT_RING (nv40->query->handle);
- BEGIN_RING(curie, NV40TCL_DMA_UNK01AC, 2);
- OUT_RING (nvws->channel->vram->handle);
- OUT_RING (nvws->channel->vram->handle);
- BEGIN_RING(curie, NV40TCL_DMA_COLOR2, 2);
- OUT_RING (nvws->channel->vram->handle);
- OUT_RING (nvws->channel->vram->handle);
-
- BEGIN_RING(curie, 0x1ea4, 3);
- OUT_RING (0x00000010);
- OUT_RING (0x01000100);
- OUT_RING (0xff800006);
-
- /* vtxprog output routing */
- BEGIN_RING(curie, 0x1fc4, 1);
- OUT_RING (0x06144321);
- BEGIN_RING(curie, 0x1fc8, 2);
- OUT_RING (0xedcba987);
- OUT_RING (0x00000021);
- BEGIN_RING(curie, 0x1fd0, 1);
- OUT_RING (0x00171615);
- BEGIN_RING(curie, 0x1fd4, 1);
- OUT_RING (0x001b1a19);
-
- BEGIN_RING(curie, 0x1ef8, 1);
- OUT_RING (0x0020ffff);
- BEGIN_RING(curie, 0x1d64, 1);
- OUT_RING (0x00d30000);
- BEGIN_RING(curie, 0x1e94, 1);
- OUT_RING (0x00000001);
-
- FIRE_RING ();
- return TRUE;
-}
-
-#define GRCLASS4097_CHIPSETS 0x00000baf
-#define GRCLASS4497_CHIPSETS 0x00005450
-struct pipe_context *
-nv40_create(struct pipe_winsys *pipe_winsys, struct nouveau_winsys *nvws,
- unsigned chipset)
-{
- struct nv40_context *nv40;
- int curie_class, ret;
+ cnv40 = calloc(1, sizeof(struct nv40_channel_context));
+ if (!cnv40)
+ return NULL;
+ cnv40->chipset = chipset;
+ cnv40->nvws = nvws;
- if ((chipset & 0xf0) != 0x40) {
- NOUVEAU_ERR("Not a NV4X chipset\n");
+ /* Notifier for sync purposes */
+ ret = nvws->notifier_alloc(nvws, 1, &cnv40->sync);
+ if (ret) {
+ NOUVEAU_ERR("Error creating notifier object: %d\n", ret);
+ nv40_channel_takedown(cnv40);
return NULL;
}
- if (GRCLASS4097_CHIPSETS & (1 << (chipset & 0x0f))) {
- curie_class = 0x4097;
- } else
- if (GRCLASS4497_CHIPSETS & (1 << (chipset & 0x0f))) {
- curie_class = 0x4497;
- } else {
- NOUVEAU_ERR("Unknown NV4X chipset: NV%02x\n", chipset);
+ /* Query objects */
+ ret = nvws->notifier_alloc(nvws, 32, &cnv40->query);
+ if (ret) {
+ NOUVEAU_ERR("Error initialising query objects: %d\n", ret);
+ nv40_channel_takedown(cnv40);
return NULL;
}
- nv40 = CALLOC_STRUCT(nv40_context);
- if (!nv40)
+ ret = nvws->res_init(&cnv40->query_heap, 0, 32);
+ if (ret) {
+ NOUVEAU_ERR("Error initialising query object heap: %d\n", ret);
+ nv40_channel_takedown(cnv40);
return NULL;
- nv40->chipset = chipset;
- nv40->nvws = nvws;
+ }
- if ((ret = nvws->notifier_alloc(nvws, 1, &nv40->sync))) {
- NOUVEAU_ERR("Error creating notifier object: %d\n", ret);
- free(nv40);
+ /* Vtxprog resources */
+ if (nvws->res_init(&cnv40->vp_exec_heap, 0, 512) ||
+ nvws->res_init(&cnv40->vp_data_heap, 0, 256)) {
+ nv40_channel_takedown(cnv40);
return NULL;
}
- nv40->num_query_objects = 32;
- nv40->query_objects = calloc(nv40->num_query_objects,
- sizeof(struct pipe_query_object *));
- if (!nv40->query_objects) {
- free(nv40);
- return NULL;
+ /* 3D object */
+ ret = nvws->grobj_alloc(nvws, curie_class, &cnv40->curie);
+ if (ret) {
+ NOUVEAU_ERR("Error creating 3D object: %d\n", ret);
+ return FALSE;
}
- if (nvws->res_init(&nv40->vertprog.exec_heap, 0, 512) ||
- nvws->res_init(&nv40->vertprog.data_heap, 0, 256)) {
- nvws->res_free(&nv40->vertprog.exec_heap);
- nvws->res_free(&nv40->vertprog.data_heap);
- free(nv40);
- return NULL;
+ /* Static curie initialisation */
+ so = so_new(128, 0);
+ so_method(so, cnv40->curie, NV40TCL_DMA_NOTIFY, 1);
+ so_data (so, cnv40->sync->handle);
+ so_method(so, cnv40->curie, NV40TCL_DMA_TEXTURE0, 2);
+ so_data (so, nvws->channel->vram->handle);
+ so_data (so, nvws->channel->gart->handle);
+ so_method(so, cnv40->curie, NV40TCL_DMA_COLOR1, 1);
+ so_data (so, nvws->channel->vram->handle);
+ so_method(so, cnv40->curie, NV40TCL_DMA_COLOR0, 2);
+ so_data (so, nvws->channel->vram->handle);
+ so_data (so, nvws->channel->vram->handle);
+ so_method(so, cnv40->curie, NV40TCL_DMA_VTXBUF0, 2);
+ so_data (so, nvws->channel->vram->handle);
+ so_data (so, nvws->channel->gart->handle);
+ so_method(so, cnv40->curie, NV40TCL_DMA_FENCE, 2);
+ so_data (so, 0);
+ so_data (so, cnv40->query->handle);
+ so_method(so, cnv40->curie, NV40TCL_DMA_UNK01AC, 2);
+ so_data (so, nvws->channel->vram->handle);
+ so_data (so, nvws->channel->vram->handle);
+ so_method(so, cnv40->curie, NV40TCL_DMA_COLOR2, 2);
+ so_data (so, nvws->channel->vram->handle);
+ so_data (so, nvws->channel->vram->handle);
+
+ so_method(so, cnv40->curie, 0x1ea4, 3);
+ so_data (so, 0x00000010);
+ so_data (so, 0x01000100);
+ so_data (so, 0xff800006);
+
+ /* vtxprog output routing */
+ so_method(so, cnv40->curie, 0x1fc4, 1);
+ so_data (so, 0x06144321);
+ so_method(so, cnv40->curie, 0x1fc8, 2);
+ so_data (so, 0xedcba987);
+ so_data (so, 0x00000021);
+ so_method(so, cnv40->curie, 0x1fd0, 1);
+ so_data (so, 0x00171615);
+ so_method(so, cnv40->curie, 0x1fd4, 1);
+ so_data (so, 0x001b1a19);
+
+ so_method(so, cnv40->curie, 0x1ef8, 1);
+ so_data (so, 0x0020ffff);
+ so_method(so, cnv40->curie, 0x1d64, 1);
+ so_data (so, 0x00d30000);
+ so_method(so, cnv40->curie, 0x1e94, 1);
+ so_data (so, 0x00000001);
+
+ so_emit(nvws, so);
+ so_ref(NULL, &so);
+ nvws->push_flush(nvws->channel, 0);
+
+ return cnv40;
+}
+
+static void
+nv40_destroy(struct pipe_context *pipe)
+{
+ struct nv40_context *nv40 = nv40_context(pipe);
+
+ if (nv40->draw)
+ draw_destroy(nv40->draw);
+
+ if (nv40->hw) {
+ if (--nv40->hw->refcount == 0)
+ nv40_channel_takedown(nv40->hw);
}
- if (!nv40_init_hwctx(nv40, curie_class)) {
- free(nv40);
+ free(nv40);
+}
+
+struct pipe_context *
+nv40_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws,
+ unsigned chipset)
+{
+ struct nv40_context *nv40;
+
+ nv40 = calloc(1, sizeof(struct nv40_context));
+ if (!nv40)
+ return NULL;
+
+ nv40->hw = nv40_channel_init(ws, nvws, chipset);
+ if (!nv40->hw) {
+ nv40_destroy(&nv40->pipe);
return NULL;
}
- nv40->pipe.winsys = pipe_winsys;
+ nv40->chipset = chipset;
+ nv40->nvws = nvws;
+ nv40->pipe.winsys = ws;
nv40->pipe.destroy = nv40_destroy;
- nv40->pipe.is_format_supported = nv40_is_format_supported;
nv40->pipe.get_name = nv40_get_name;
nv40->pipe.get_vendor = nv40_get_vendor;
nv40->pipe.get_param = nv40_get_param;
nv40->pipe.get_paramf = nv40_get_paramf;
-
nv40->pipe.draw_arrays = nv40_draw_arrays;
nv40->pipe.draw_elements = nv40_draw_elements;
nv40->pipe.clear = nv40_clear;
-
nv40->pipe.flush = nv40_flush;
nv40_init_query_functions(nv40);
return &nv40->pipe;
}
-
-
+