nv50_query.c revision 6b3ca672eb85d30d6c28e91000e2cc2231a41bef
1/* 2 * Copyright 2008 Ben Skeggs 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 * SOFTWARE. 21 */ 22 23#include "pipe/p_context.h" 24#include "pipe/p_inlines.h" 25 26#include "nv50_context.h" 27 28struct nv50_query { 29 struct pipe_buffer *buffer; 30 unsigned type; 31 boolean ready; 32 uint64_t result; 33}; 34 35static INLINE struct nv50_query * 36nv50_query(struct pipe_query *pipe) 37{ 38 return (struct nv50_query *)pipe; 39} 40 41static struct pipe_query * 42nv50_query_create(struct pipe_context *pipe, unsigned type) 43{ 44 struct pipe_screen *screen = pipe->screen; 45 struct nv50_query *q = CALLOC_STRUCT(nv50_query); 46 47 assert (q->type == PIPE_QUERY_OCCLUSION_COUNTER); 48 q->type = type; 49 50 q->buffer = screen->buffer_create(screen, 256, 0, 16); 51 if (!q->buffer) { 52 FREE(q); 53 return NULL; 54 } 55 56 return (struct pipe_query *)q; 57} 58 59static void 60nv50_query_destroy(struct pipe_context *pipe, struct pipe_query *pq) 61{ 62 struct nv50_query *q = nv50_query(pq); 63 64 if (q) { 65 pipe_buffer_reference(&q->buffer, NULL); 66 FREE(q); 67 } 68} 69 70static void 71nv50_query_begin(struct pipe_context *pipe, struct pipe_query *pq) 72{ 73 struct nv50_context *nv50 = nv50_context(pipe); 74 struct nouveau_channel *chan = nv50->screen->base.channel; 75 struct nouveau_grobj *tesla = nv50->screen->tesla; 76 struct nv50_query *q = nv50_query(pq); 77 78 BEGIN_RING(chan, tesla, 0x1530, 1); 79 OUT_RING (chan, 1); 80 BEGIN_RING(chan, tesla, 0x1514, 1); 81 OUT_RING (chan, 1); 82 83 q->ready = FALSE; 84} 85 86static void 87nv50_query_end(struct pipe_context *pipe, struct pipe_query *pq) 88{ 89 struct nv50_context *nv50 = nv50_context(pipe); 90 struct nouveau_channel *chan = nv50->screen->base.channel; 91 struct nouveau_grobj *tesla = nv50->screen->tesla; 92 struct nv50_query *q = nv50_query(pq); 93 struct nouveau_bo *bo = nouveau_bo(q->buffer); 94 95 WAIT_RING (chan, 5); 96 BEGIN_RING(chan, tesla, 0x1b00, 4); 97 OUT_RELOCh(chan, bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); 98 OUT_RELOCl(chan, bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); 99 OUT_RING (chan, 0x00000000); 100 OUT_RING (chan, 0x0100f002); 101 FIRE_RING (chan); 102} 103 104static boolean 105nv50_query_result(struct pipe_context *pipe, struct pipe_query *pq, 106 boolean wait, uint64_t *result) 107{ 108 struct pipe_screen *pscreen = pipe->screen; 109 struct nv50_query *q = nv50_query(pq); 110 111 /*XXX: Want to be able to return FALSE here instead of blocking 112 * until the result is available.. 113 */ 114 115 if (!q->ready) { 116 uint32_t *map = pipe_buffer_map(pscreen, q->buffer, 117 PIPE_BUFFER_USAGE_CPU_READ); 118 q->result = map[1]; 119 q->ready = TRUE; 120 pipe_buffer_unmap(pscreen, q->buffer); 121 } 122 123 *result = q->result; 124 return q->ready; 125} 126 127void 128nv50_init_query_functions(struct nv50_context *nv50) 129{ 130 nv50->pipe.create_query = nv50_query_create; 131 nv50->pipe.destroy_query = nv50_query_destroy; 132 nv50->pipe.begin_query = nv50_query_begin; 133 nv50->pipe.end_query = nv50_query_end; 134 nv50->pipe.get_query_result = nv50_query_result; 135} 136