static boolean nvc0_query_allocate(struct nvc0_context *nvc0, struct nvc0_query *q, int size) { struct nvc0_screen *screen = nvc0->screen; int ret; if (q->bo) { nouveau_bo_ref(NULL, &q->bo); if (q->u.mm) { if (q->state == NVC0_QUERY_STATE_READY) nouveau_mm_free(q->u.mm); else nouveau_fence_work(screen->base.fence.current, nouveau_mm_free_work, q->u.mm); } } if (size) { q->u.mm = nouveau_mm_allocate(screen->base.mm_GART, size, &q->bo, &q->base); if (!q->bo) return FALSE; q->offset = q->base; ret = nouveau_bo_map(q->bo, 0, screen->base.client); if (ret) { nvc0_query_allocate(nvc0, q, 0); return FALSE; } q->data = (uint32_t *)((uint8_t *)q->bo->map + q->base); } return TRUE; }
static void nvc0_query_destroy(struct pipe_context *pipe, struct pipe_query *pq) { nvc0_query_allocate(nvc0_context(pipe), nvc0_query(pq), 0); nouveau_fence_ref(NULL, &nvc0_query(pq)->fence); FREE(nvc0_query(pq)); }
static void nvc0_query_rotate(struct nvc0_context *nvc0, struct nvc0_query *q) { q->offset += q->rotate; q->data += q->rotate / sizeof(*q->data); if (q->offset - q->base == NVC0_QUERY_ALLOC_SPACE) nvc0_query_allocate(nvc0, q, NVC0_QUERY_ALLOC_SPACE); }
static struct pipe_query * nvc0_query_create(struct pipe_context *pipe, unsigned type) { struct nvc0_context *nvc0 = nvc0_context(pipe); struct nvc0_query *q; unsigned space = NVC0_QUERY_ALLOC_SPACE; q = CALLOC_STRUCT(nvc0_query); if (!q) return NULL; switch (type) { case PIPE_QUERY_OCCLUSION_COUNTER: case PIPE_QUERY_OCCLUSION_PREDICATE: q->rotate = 32; space = NVC0_QUERY_ALLOC_SPACE; break; case PIPE_QUERY_PIPELINE_STATISTICS: q->is64bit = TRUE; space = 512; break; case PIPE_QUERY_SO_STATISTICS: case PIPE_QUERY_SO_OVERFLOW_PREDICATE: q->is64bit = TRUE; space = 64; break; case PIPE_QUERY_TIME_ELAPSED: case PIPE_QUERY_TIMESTAMP: case PIPE_QUERY_TIMESTAMP_DISJOINT: case PIPE_QUERY_GPU_FINISHED: case PIPE_QUERY_PRIMITIVES_GENERATED: case PIPE_QUERY_PRIMITIVES_EMITTED: space = 32; break; case NVC0_QUERY_TFB_BUFFER_OFFSET: space = 16; break; default: FREE(q); return NULL; } if (!nvc0_query_allocate(nvc0, q, space)) { FREE(q); return NULL; } q->type = type; if (q->rotate) { /* we advance before query_begin ! */ q->offset -= q->rotate; q->data -= q->rotate / sizeof(*q->data); } else if (!q->is64bit) q->data[0] = 0; /* initialize sequence */ return (struct pipe_query *)q; }
static struct pipe_query * nvc0_query_create(struct pipe_context *pipe, unsigned type) { struct nvc0_context *nvc0 = nvc0_context(pipe); struct nvc0_query *q; unsigned space = NVC0_QUERY_ALLOC_SPACE; q = CALLOC_STRUCT(nvc0_query); if (!q) return NULL; switch (type) { case PIPE_QUERY_OCCLUSION_COUNTER: case PIPE_QUERY_OCCLUSION_PREDICATE: q->rotate = 32; space = NVC0_QUERY_ALLOC_SPACE; break; case PIPE_QUERY_PIPELINE_STATISTICS: q->is64bit = TRUE; space = 512; break; case PIPE_QUERY_SO_STATISTICS: case PIPE_QUERY_SO_OVERFLOW_PREDICATE: q->is64bit = TRUE; space = 64; break; case PIPE_QUERY_PRIMITIVES_GENERATED: case PIPE_QUERY_PRIMITIVES_EMITTED: q->is64bit = TRUE; space = 32; break; case PIPE_QUERY_TIME_ELAPSED: case PIPE_QUERY_TIMESTAMP: case PIPE_QUERY_TIMESTAMP_DISJOINT: case PIPE_QUERY_GPU_FINISHED: space = 32; break; case NVC0_QUERY_TFB_BUFFER_OFFSET: space = 16; break; default: #ifdef NOUVEAU_ENABLE_DRIVER_STATISTICS if (type >= NVC0_QUERY_DRV_STAT(0) && type <= NVC0_QUERY_DRV_STAT_LAST) { space = 0; q->is64bit = true; q->index = type - NVC0_QUERY_DRV_STAT(0); break; } else #endif if (nvc0->screen->base.class_3d >= NVE4_3D_CLASS && nvc0->screen->base.device->drm_version >= 0x01000101) { if (type >= NVE4_PM_QUERY(0) && type <= NVE4_PM_QUERY_LAST) { /* for each MP: * [00] = WS0.C0 * [04] = WS0.C1 * [08] = WS0.C2 * [0c] = WS0.C3 * [10] = WS0.C0 * [14] = WS1.C1 * [18] = WS1.C2 * [1c] = WS1.C3 * [20] = WS1.C0 * [24] = WS2.C1 * [28] = WS2.C2 * [2c] = WS2.C3 * [30] = WS3.C0 * [34] = WS3.C1 * [38] = WS3.C2 * [3c] = WS3.C3 * [40] = MP.C4 * [44] = MP.C5 * [48] = MP.C6 * [4c] = MP.C7 * [50] = WS0.sequence * [54] = WS1.sequence * [58] = WS2.sequence * [5c] = WS3.sequence */ space = (4 * 4 + 4 + 4) * nvc0->screen->mp_count * sizeof(uint32_t); break; } } debug_printf("invalid query type: %u\n", type); FREE(q); return NULL; } if (!nvc0_query_allocate(nvc0, q, space)) { FREE(q); return NULL; } q->type = type; if (q->rotate) { /* we advance before query_begin ! */ q->offset -= q->rotate; q->data -= q->rotate / sizeof(*q->data); } else if (!q->is64bit) q->data[0] = 0; /* initialize sequence */ return (struct pipe_query *)q; }
static void nvc0_query_destroy(struct pipe_context *pipe, struct pipe_query *pq) { nvc0_query_allocate(nvc0_context(pipe), nvc0_query(pq), 0); FREE(nvc0_query(pq)); }