Rev 4358 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4358 | Serge | 1 | /* |
2 | * Copyright 2010 Christoph Bumiller |
||
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 OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR |
||
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
||
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
||
20 | * OTHER DEALINGS IN THE SOFTWARE. |
||
21 | */ |
||
22 | |||
23 | #include "util/u_format.h" |
||
24 | #include "util/u_format_s3tc.h" |
||
25 | #include "pipe/p_screen.h" |
||
26 | |||
27 | #include "nv50_context.h" |
||
28 | #include "nv50_screen.h" |
||
29 | |||
30 | #include "nouveau/nv_object.xml.h" |
||
31 | #include |
||
32 | |||
33 | #ifndef NOUVEAU_GETPARAM_GRAPH_UNITS |
||
34 | # define NOUVEAU_GETPARAM_GRAPH_UNITS 13 |
||
35 | #endif |
||
36 | |||
37 | /* affected by LOCAL_WARPS_LOG_ALLOC / LOCAL_WARPS_NO_CLAMP */ |
||
38 | #define LOCAL_WARPS_ALLOC 32 |
||
39 | /* affected by STACK_WARPS_LOG_ALLOC / STACK_WARPS_NO_CLAMP */ |
||
40 | #define STACK_WARPS_ALLOC 32 |
||
41 | |||
42 | #define THREADS_IN_WARP 32 |
||
43 | |||
44 | #define ONE_TEMP_SIZE (4/*vector*/ * sizeof(float)) |
||
45 | |||
46 | static boolean |
||
47 | nv50_screen_is_format_supported(struct pipe_screen *pscreen, |
||
48 | enum pipe_format format, |
||
49 | enum pipe_texture_target target, |
||
50 | unsigned sample_count, |
||
51 | unsigned bindings) |
||
52 | { |
||
53 | if (sample_count > 8) |
||
54 | return FALSE; |
||
55 | if (!(0x117 & (1 << sample_count))) /* 0, 1, 2, 4 or 8 */ |
||
56 | return FALSE; |
||
57 | if (sample_count == 8 && util_format_get_blocksizebits(format) >= 128) |
||
58 | return FALSE; |
||
59 | |||
60 | if (!util_format_is_supported(format, bindings)) |
||
61 | return FALSE; |
||
62 | |||
63 | switch (format) { |
||
64 | case PIPE_FORMAT_Z16_UNORM: |
||
65 | if (nv50_screen(pscreen)->tesla->oclass < NVA0_3D_CLASS) |
||
66 | return FALSE; |
||
67 | break; |
||
68 | default: |
||
69 | break; |
||
70 | } |
||
71 | |||
72 | /* transfers & shared are always supported */ |
||
73 | bindings &= ~(PIPE_BIND_TRANSFER_READ | |
||
74 | PIPE_BIND_TRANSFER_WRITE | |
||
75 | PIPE_BIND_SHARED); |
||
76 | |||
77 | return (nv50_format_table[format].usage & bindings) == bindings; |
||
78 | } |
||
79 | |||
80 | static int |
||
81 | nv50_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) |
||
82 | { |
||
83 | const uint16_t class_3d = nouveau_screen(pscreen)->class_3d; |
||
84 | |||
85 | switch (param) { |
||
86 | case PIPE_CAP_MAX_COMBINED_SAMPLERS: |
||
87 | return 64; |
||
88 | case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: |
||
89 | return 14; |
||
90 | case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: |
||
91 | return 12; |
||
92 | case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: |
||
93 | return 14; |
||
94 | case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS: |
||
95 | return 512; |
||
96 | case PIPE_CAP_MIN_TEXEL_OFFSET: |
||
97 | return -8; |
||
98 | case PIPE_CAP_MAX_TEXEL_OFFSET: |
||
99 | return 7; |
||
100 | case PIPE_CAP_TEXTURE_MIRROR_CLAMP: |
||
101 | case PIPE_CAP_TEXTURE_SWIZZLE: |
||
102 | case PIPE_CAP_TEXTURE_SHADOW_MAP: |
||
103 | case PIPE_CAP_NPOT_TEXTURES: |
||
104 | case PIPE_CAP_ANISOTROPIC_FILTER: |
||
105 | case PIPE_CAP_SCALED_RESOLVE: |
||
106 | case PIPE_CAP_TEXTURE_BUFFER_OBJECTS: |
||
107 | return 1; |
||
108 | case PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE: |
||
109 | return 65536; |
||
110 | case PIPE_CAP_SEAMLESS_CUBE_MAP: |
||
111 | return nv50_screen(pscreen)->tesla->oclass >= NVA0_3D_CLASS; |
||
112 | case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE: |
||
113 | return 0; |
||
114 | case PIPE_CAP_CUBE_MAP_ARRAY: |
||
115 | return 0; |
||
116 | /* |
||
117 | return nv50_screen(pscreen)->tesla->oclass >= NVA3_3D_CLASS; |
||
118 | */ |
||
119 | case PIPE_CAP_TWO_SIDED_STENCIL: |
||
120 | case PIPE_CAP_DEPTH_CLIP_DISABLE: |
||
121 | case PIPE_CAP_POINT_SPRITE: |
||
122 | return 1; |
||
123 | case PIPE_CAP_SM3: |
||
124 | return 1; |
||
125 | case PIPE_CAP_GLSL_FEATURE_LEVEL: |
||
126 | return 140; |
||
127 | case PIPE_CAP_MAX_RENDER_TARGETS: |
||
128 | return 8; |
||
129 | case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS: |
||
130 | return 1; |
||
131 | case PIPE_CAP_FRAGMENT_COLOR_CLAMPED: |
||
132 | case PIPE_CAP_VERTEX_COLOR_UNCLAMPED: |
||
133 | case PIPE_CAP_VERTEX_COLOR_CLAMPED: |
||
134 | return 1; |
||
135 | case PIPE_CAP_QUERY_TIMESTAMP: |
||
136 | case PIPE_CAP_QUERY_TIME_ELAPSED: |
||
137 | case PIPE_CAP_OCCLUSION_QUERY: |
||
138 | return 1; |
||
139 | case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS: |
||
140 | return 4; |
||
141 | case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS: |
||
142 | case PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS: |
||
143 | return 64; |
||
144 | case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME: |
||
145 | return (class_3d >= NVA0_3D_CLASS) ? 1 : 0; |
||
146 | case PIPE_CAP_BLEND_EQUATION_SEPARATE: |
||
147 | case PIPE_CAP_INDEP_BLEND_ENABLE: |
||
148 | return 1; |
||
149 | case PIPE_CAP_INDEP_BLEND_FUNC: |
||
150 | return nv50_screen(pscreen)->tesla->oclass >= NVA3_3D_CLASS; |
||
151 | case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: |
||
152 | case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: |
||
153 | return 1; |
||
154 | case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: |
||
155 | case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: |
||
156 | return 0; |
||
157 | case PIPE_CAP_SHADER_STENCIL_EXPORT: |
||
158 | return 0; |
||
159 | case PIPE_CAP_PRIMITIVE_RESTART: |
||
160 | case PIPE_CAP_TGSI_INSTANCEID: |
||
161 | case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR: |
||
162 | case PIPE_CAP_MIXED_COLORBUFFER_FORMATS: |
||
163 | case PIPE_CAP_CONDITIONAL_RENDER: |
||
164 | case PIPE_CAP_TEXTURE_BARRIER: |
||
165 | case PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION: |
||
166 | case PIPE_CAP_START_INSTANCE: |
||
167 | return 1; |
||
168 | case PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS: |
||
169 | return 0; /* state trackers will know better */ |
||
170 | case PIPE_CAP_USER_CONSTANT_BUFFERS: |
||
171 | case PIPE_CAP_USER_INDEX_BUFFERS: |
||
172 | case PIPE_CAP_USER_VERTEX_BUFFERS: |
||
173 | return 1; |
||
174 | case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT: |
||
175 | return 256; |
||
176 | case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT: |
||
177 | return 1; /* 256 for binding as RT, but that's not possible in GL */ |
||
178 | case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT: |
||
179 | return NOUVEAU_MIN_BUFFER_MAP_ALIGN; |
||
180 | case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY: |
||
181 | case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY: |
||
182 | case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY: |
||
183 | case PIPE_CAP_TGSI_TEXCOORD: |
||
184 | case PIPE_CAP_TEXTURE_MULTISAMPLE: |
||
185 | return 0; |
||
186 | case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER: |
||
187 | return 1; |
||
188 | case PIPE_CAP_QUERY_PIPELINE_STATISTICS: |
||
189 | return 0; |
||
190 | case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK: |
||
191 | return PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_NV50; |
||
192 | case PIPE_CAP_ENDIANNESS: |
||
193 | return PIPE_ENDIAN_LITTLE; |
||
194 | default: |
||
195 | NOUVEAU_ERR("unknown PIPE_CAP %d\n", param); |
||
196 | return 0; |
||
197 | } |
||
198 | } |
||
199 | |||
200 | static int |
||
201 | nv50_screen_get_shader_param(struct pipe_screen *pscreen, unsigned shader, |
||
202 | enum pipe_shader_cap param) |
||
203 | { |
||
204 | switch (shader) { |
||
205 | case PIPE_SHADER_VERTEX: |
||
206 | case PIPE_SHADER_GEOMETRY: |
||
207 | case PIPE_SHADER_FRAGMENT: |
||
208 | break; |
||
209 | default: |
||
210 | return 0; |
||
211 | } |
||
212 | |||
213 | switch (param) { |
||
214 | case PIPE_SHADER_CAP_MAX_INSTRUCTIONS: |
||
215 | case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS: |
||
216 | case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS: |
||
217 | case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS: |
||
218 | return 16384; |
||
219 | case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH: |
||
220 | return 4; |
||
221 | case PIPE_SHADER_CAP_MAX_INPUTS: |
||
222 | if (shader == PIPE_SHADER_VERTEX) |
||
223 | return 32; |
||
4401 | Serge | 224 | return 15; |
4358 | Serge | 225 | case PIPE_SHADER_CAP_MAX_CONSTS: |
226 | return 65536 / 16; |
||
227 | case PIPE_SHADER_CAP_MAX_CONST_BUFFERS: |
||
228 | return NV50_MAX_PIPE_CONSTBUFS; |
||
229 | case PIPE_SHADER_CAP_MAX_ADDRS: |
||
230 | return 1; |
||
231 | case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR: |
||
232 | case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR: |
||
233 | return shader != PIPE_SHADER_FRAGMENT; |
||
234 | case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR: |
||
235 | case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR: |
||
236 | return 1; |
||
237 | case PIPE_SHADER_CAP_MAX_PREDS: |
||
238 | return 0; |
||
239 | case PIPE_SHADER_CAP_MAX_TEMPS: |
||
240 | return nv50_screen(pscreen)->max_tls_space / ONE_TEMP_SIZE; |
||
241 | case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED: |
||
242 | return 1; |
||
243 | case PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED: |
||
244 | return 0; |
||
245 | case PIPE_SHADER_CAP_SUBROUTINES: |
||
246 | return 0; /* please inline, or provide function declarations */ |
||
247 | case PIPE_SHADER_CAP_INTEGERS: |
||
248 | return 1; |
||
249 | case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS: |
||
250 | return 32; |
||
251 | default: |
||
252 | NOUVEAU_ERR("unknown PIPE_SHADER_CAP %d\n", param); |
||
253 | return 0; |
||
254 | } |
||
255 | } |
||
256 | |||
257 | static float |
||
258 | nv50_screen_get_paramf(struct pipe_screen *pscreen, enum pipe_capf param) |
||
259 | { |
||
260 | switch (param) { |
||
261 | case PIPE_CAPF_MAX_LINE_WIDTH: |
||
262 | case PIPE_CAPF_MAX_LINE_WIDTH_AA: |
||
263 | return 10.0f; |
||
264 | case PIPE_CAPF_MAX_POINT_WIDTH: |
||
265 | case PIPE_CAPF_MAX_POINT_WIDTH_AA: |
||
266 | return 64.0f; |
||
267 | case PIPE_CAPF_MAX_TEXTURE_ANISOTROPY: |
||
268 | return 16.0f; |
||
269 | case PIPE_CAPF_MAX_TEXTURE_LOD_BIAS: |
||
270 | return 4.0f; |
||
271 | default: |
||
272 | NOUVEAU_ERR("unknown PIPE_CAP %d\n", param); |
||
273 | return 0.0f; |
||
274 | } |
||
275 | } |
||
276 | |||
277 | static void |
||
278 | nv50_screen_destroy(struct pipe_screen *pscreen) |
||
279 | { |
||
280 | struct nv50_screen *screen = nv50_screen(pscreen); |
||
281 | |||
282 | if (screen->base.fence.current) { |
||
283 | nouveau_fence_wait(screen->base.fence.current); |
||
284 | nouveau_fence_ref (NULL, &screen->base.fence.current); |
||
285 | } |
||
286 | if (screen->base.pushbuf) |
||
287 | screen->base.pushbuf->user_priv = NULL; |
||
288 | |||
289 | if (screen->blitter) |
||
290 | nv50_blitter_destroy(screen); |
||
291 | |||
292 | nouveau_bo_ref(NULL, &screen->code); |
||
293 | nouveau_bo_ref(NULL, &screen->tls_bo); |
||
294 | nouveau_bo_ref(NULL, &screen->stack_bo); |
||
295 | nouveau_bo_ref(NULL, &screen->txc); |
||
296 | nouveau_bo_ref(NULL, &screen->uniforms); |
||
297 | nouveau_bo_ref(NULL, &screen->fence.bo); |
||
298 | |||
299 | nouveau_heap_destroy(&screen->vp_code_heap); |
||
300 | nouveau_heap_destroy(&screen->gp_code_heap); |
||
301 | nouveau_heap_destroy(&screen->fp_code_heap); |
||
302 | |||
303 | FREE(screen->tic.entries); |
||
304 | |||
305 | nouveau_object_del(&screen->tesla); |
||
306 | nouveau_object_del(&screen->eng2d); |
||
307 | nouveau_object_del(&screen->m2mf); |
||
308 | nouveau_object_del(&screen->sync); |
||
309 | |||
310 | nouveau_screen_fini(&screen->base); |
||
311 | |||
312 | FREE(screen); |
||
313 | } |
||
314 | |||
315 | static void |
||
316 | nv50_screen_fence_emit(struct pipe_screen *pscreen, u32 *sequence) |
||
317 | { |
||
318 | struct nv50_screen *screen = nv50_screen(pscreen); |
||
319 | struct nouveau_pushbuf *push = screen->base.pushbuf; |
||
320 | |||
321 | /* we need to do it after possible flush in MARK_RING */ |
||
322 | *sequence = ++screen->base.fence.sequence; |
||
323 | |||
324 | PUSH_DATA (push, NV50_FIFO_PKHDR(NV50_3D(QUERY_ADDRESS_HIGH), 4)); |
||
325 | PUSH_DATAh(push, screen->fence.bo->offset); |
||
326 | PUSH_DATA (push, screen->fence.bo->offset); |
||
327 | PUSH_DATA (push, *sequence); |
||
328 | PUSH_DATA (push, NV50_3D_QUERY_GET_MODE_WRITE_UNK0 | |
||
329 | NV50_3D_QUERY_GET_UNK4 | |
||
330 | NV50_3D_QUERY_GET_UNIT_CROP | |
||
331 | NV50_3D_QUERY_GET_TYPE_QUERY | |
||
332 | NV50_3D_QUERY_GET_QUERY_SELECT_ZERO | |
||
333 | NV50_3D_QUERY_GET_SHORT); |
||
334 | } |
||
335 | |||
336 | static u32 |
||
337 | nv50_screen_fence_update(struct pipe_screen *pscreen) |
||
338 | { |
||
339 | return nv50_screen(pscreen)->fence.map[0]; |
||
340 | } |
||
341 | |||
342 | static void |
||
343 | nv50_screen_init_hwctx(struct nv50_screen *screen) |
||
344 | { |
||
345 | struct nouveau_pushbuf *push = screen->base.pushbuf; |
||
346 | struct nv04_fifo *fifo; |
||
347 | unsigned i; |
||
348 | |||
349 | fifo = (struct nv04_fifo *)screen->base.channel->data; |
||
350 | |||
351 | BEGIN_NV04(push, SUBC_M2MF(NV01_SUBCHAN_OBJECT), 1); |
||
352 | PUSH_DATA (push, screen->m2mf->handle); |
||
353 | BEGIN_NV04(push, SUBC_M2MF(NV03_M2MF_DMA_NOTIFY), 3); |
||
354 | PUSH_DATA (push, screen->sync->handle); |
||
355 | PUSH_DATA (push, fifo->vram); |
||
356 | PUSH_DATA (push, fifo->vram); |
||
357 | |||
358 | BEGIN_NV04(push, SUBC_2D(NV01_SUBCHAN_OBJECT), 1); |
||
359 | PUSH_DATA (push, screen->eng2d->handle); |
||
360 | BEGIN_NV04(push, NV50_2D(DMA_NOTIFY), 4); |
||
361 | PUSH_DATA (push, screen->sync->handle); |
||
362 | PUSH_DATA (push, fifo->vram); |
||
363 | PUSH_DATA (push, fifo->vram); |
||
364 | PUSH_DATA (push, fifo->vram); |
||
365 | BEGIN_NV04(push, NV50_2D(OPERATION), 1); |
||
366 | PUSH_DATA (push, NV50_2D_OPERATION_SRCCOPY); |
||
367 | BEGIN_NV04(push, NV50_2D(CLIP_ENABLE), 1); |
||
368 | PUSH_DATA (push, 0); |
||
369 | BEGIN_NV04(push, NV50_2D(COLOR_KEY_ENABLE), 1); |
||
370 | PUSH_DATA (push, 0); |
||
371 | BEGIN_NV04(push, SUBC_2D(0x0888), 1); |
||
372 | PUSH_DATA (push, 1); |
||
373 | |||
374 | BEGIN_NV04(push, SUBC_3D(NV01_SUBCHAN_OBJECT), 1); |
||
375 | PUSH_DATA (push, screen->tesla->handle); |
||
376 | |||
377 | BEGIN_NV04(push, NV50_3D(COND_MODE), 1); |
||
378 | PUSH_DATA (push, NV50_3D_COND_MODE_ALWAYS); |
||
379 | |||
380 | BEGIN_NV04(push, NV50_3D(DMA_NOTIFY), 1); |
||
381 | PUSH_DATA (push, screen->sync->handle); |
||
382 | BEGIN_NV04(push, NV50_3D(DMA_ZETA), 11); |
||
383 | for (i = 0; i < 11; ++i) |
||
384 | PUSH_DATA(push, fifo->vram); |
||
385 | BEGIN_NV04(push, NV50_3D(DMA_COLOR(0)), NV50_3D_DMA_COLOR__LEN); |
||
386 | for (i = 0; i < NV50_3D_DMA_COLOR__LEN; ++i) |
||
387 | PUSH_DATA(push, fifo->vram); |
||
388 | |||
389 | BEGIN_NV04(push, NV50_3D(REG_MODE), 1); |
||
390 | PUSH_DATA (push, NV50_3D_REG_MODE_STRIPED); |
||
391 | BEGIN_NV04(push, NV50_3D(UNK1400_LANES), 1); |
||
392 | PUSH_DATA (push, 0xf); |
||
393 | |||
394 | if (debug_get_bool_option("NOUVEAU_SHADER_WATCHDOG", TRUE)) { |
||
395 | BEGIN_NV04(push, NV50_3D(WATCHDOG_TIMER), 1); |
||
396 | PUSH_DATA (push, 0x18); |
||
397 | } |
||
398 | |||
399 | BEGIN_NV04(push, NV50_3D(RT_CONTROL), 1); |
||
400 | PUSH_DATA (push, 1); |
||
401 | |||
402 | BEGIN_NV04(push, NV50_3D(CSAA_ENABLE), 1); |
||
403 | PUSH_DATA (push, 0); |
||
404 | BEGIN_NV04(push, NV50_3D(MULTISAMPLE_ENABLE), 1); |
||
405 | PUSH_DATA (push, 0); |
||
406 | BEGIN_NV04(push, NV50_3D(MULTISAMPLE_MODE), 1); |
||
407 | PUSH_DATA (push, NV50_3D_MULTISAMPLE_MODE_MS1); |
||
408 | BEGIN_NV04(push, NV50_3D(MULTISAMPLE_CTRL), 1); |
||
409 | PUSH_DATA (push, 0); |
||
410 | BEGIN_NV04(push, NV50_3D(LINE_LAST_PIXEL), 1); |
||
411 | PUSH_DATA (push, 0); |
||
412 | BEGIN_NV04(push, NV50_3D(BLEND_SEPARATE_ALPHA), 1); |
||
413 | PUSH_DATA (push, 1); |
||
414 | |||
415 | if (screen->tesla->oclass >= NVA0_3D_CLASS) { |
||
416 | BEGIN_NV04(push, SUBC_3D(NVA0_3D_TEX_MISC), 1); |
||
417 | PUSH_DATA (push, NVA0_3D_TEX_MISC_SEAMLESS_CUBE_MAP); |
||
418 | } |
||
419 | |||
420 | BEGIN_NV04(push, NV50_3D(SCREEN_Y_CONTROL), 1); |
||
421 | PUSH_DATA (push, 0); |
||
422 | BEGIN_NV04(push, NV50_3D(WINDOW_OFFSET_X), 2); |
||
423 | PUSH_DATA (push, 0); |
||
424 | PUSH_DATA (push, 0); |
||
425 | BEGIN_NV04(push, NV50_3D(ZCULL_REGION), 1); |
||
426 | PUSH_DATA (push, 0x3f); |
||
427 | |||
428 | BEGIN_NV04(push, NV50_3D(VP_ADDRESS_HIGH), 2); |
||
429 | PUSH_DATAh(push, screen->code->offset + (0 << NV50_CODE_BO_SIZE_LOG2)); |
||
430 | PUSH_DATA (push, screen->code->offset + (0 << NV50_CODE_BO_SIZE_LOG2)); |
||
431 | |||
432 | BEGIN_NV04(push, NV50_3D(FP_ADDRESS_HIGH), 2); |
||
433 | PUSH_DATAh(push, screen->code->offset + (1 << NV50_CODE_BO_SIZE_LOG2)); |
||
434 | PUSH_DATA (push, screen->code->offset + (1 << NV50_CODE_BO_SIZE_LOG2)); |
||
435 | |||
436 | BEGIN_NV04(push, NV50_3D(GP_ADDRESS_HIGH), 2); |
||
437 | PUSH_DATAh(push, screen->code->offset + (2 << NV50_CODE_BO_SIZE_LOG2)); |
||
438 | PUSH_DATA (push, screen->code->offset + (2 << NV50_CODE_BO_SIZE_LOG2)); |
||
439 | |||
440 | BEGIN_NV04(push, NV50_3D(LOCAL_ADDRESS_HIGH), 3); |
||
441 | PUSH_DATAh(push, screen->tls_bo->offset); |
||
442 | PUSH_DATA (push, screen->tls_bo->offset); |
||
443 | PUSH_DATA (push, util_logbase2(screen->cur_tls_space / 8)); |
||
444 | |||
445 | BEGIN_NV04(push, NV50_3D(STACK_ADDRESS_HIGH), 3); |
||
446 | PUSH_DATAh(push, screen->stack_bo->offset); |
||
447 | PUSH_DATA (push, screen->stack_bo->offset); |
||
448 | PUSH_DATA (push, 4); |
||
449 | |||
450 | BEGIN_NV04(push, NV50_3D(CB_DEF_ADDRESS_HIGH), 3); |
||
451 | PUSH_DATAh(push, screen->uniforms->offset + (0 << 16)); |
||
452 | PUSH_DATA (push, screen->uniforms->offset + (0 << 16)); |
||
453 | PUSH_DATA (push, (NV50_CB_PVP << 16) | 0x0000); |
||
454 | |||
455 | BEGIN_NV04(push, NV50_3D(CB_DEF_ADDRESS_HIGH), 3); |
||
456 | PUSH_DATAh(push, screen->uniforms->offset + (1 << 16)); |
||
457 | PUSH_DATA (push, screen->uniforms->offset + (1 << 16)); |
||
458 | PUSH_DATA (push, (NV50_CB_PGP << 16) | 0x0000); |
||
459 | |||
460 | BEGIN_NV04(push, NV50_3D(CB_DEF_ADDRESS_HIGH), 3); |
||
461 | PUSH_DATAh(push, screen->uniforms->offset + (2 << 16)); |
||
462 | PUSH_DATA (push, screen->uniforms->offset + (2 << 16)); |
||
463 | PUSH_DATA (push, (NV50_CB_PFP << 16) | 0x0000); |
||
464 | |||
465 | BEGIN_NV04(push, NV50_3D(CB_DEF_ADDRESS_HIGH), 3); |
||
466 | PUSH_DATAh(push, screen->uniforms->offset + (3 << 16)); |
||
467 | PUSH_DATA (push, screen->uniforms->offset + (3 << 16)); |
||
468 | PUSH_DATA (push, (NV50_CB_AUX << 16) | 0x0200); |
||
469 | |||
470 | BEGIN_NI04(push, NV50_3D(SET_PROGRAM_CB), 3); |
||
471 | PUSH_DATA (push, (NV50_CB_AUX << 12) | 0xf01); |
||
472 | PUSH_DATA (push, (NV50_CB_AUX << 12) | 0xf21); |
||
473 | PUSH_DATA (push, (NV50_CB_AUX << 12) | 0xf31); |
||
474 | |||
475 | /* return { 0.0, 0.0, 0.0, 0.0 } on out-of-bounds vtxbuf access */ |
||
476 | BEGIN_NV04(push, NV50_3D(CB_ADDR), 1); |
||
477 | PUSH_DATA (push, ((1 << 9) << 6) | NV50_CB_AUX); |
||
478 | BEGIN_NI04(push, NV50_3D(CB_DATA(0)), 4); |
||
479 | PUSH_DATAf(push, 0.0f); |
||
480 | PUSH_DATAf(push, 0.0f); |
||
481 | PUSH_DATAf(push, 0.0f); |
||
482 | PUSH_DATAf(push, 0.0f); |
||
483 | BEGIN_NV04(push, NV50_3D(VERTEX_RUNOUT_ADDRESS_HIGH), 2); |
||
484 | PUSH_DATAh(push, screen->uniforms->offset + (3 << 16) + (1 << 9)); |
||
485 | PUSH_DATA (push, screen->uniforms->offset + (3 << 16) + (1 << 9)); |
||
486 | |||
487 | /* max TIC (bits 4:8) & TSC bindings, per program type */ |
||
488 | for (i = 0; i < 3; ++i) { |
||
489 | BEGIN_NV04(push, NV50_3D(TEX_LIMITS(i)), 1); |
||
490 | PUSH_DATA (push, 0x54); |
||
491 | } |
||
492 | |||
493 | BEGIN_NV04(push, NV50_3D(TIC_ADDRESS_HIGH), 3); |
||
494 | PUSH_DATAh(push, screen->txc->offset); |
||
495 | PUSH_DATA (push, screen->txc->offset); |
||
496 | PUSH_DATA (push, NV50_TIC_MAX_ENTRIES - 1); |
||
497 | |||
498 | BEGIN_NV04(push, NV50_3D(TSC_ADDRESS_HIGH), 3); |
||
499 | PUSH_DATAh(push, screen->txc->offset + 65536); |
||
500 | PUSH_DATA (push, screen->txc->offset + 65536); |
||
501 | PUSH_DATA (push, NV50_TSC_MAX_ENTRIES - 1); |
||
502 | |||
503 | BEGIN_NV04(push, NV50_3D(LINKED_TSC), 1); |
||
504 | PUSH_DATA (push, 0); |
||
505 | |||
506 | BEGIN_NV04(push, NV50_3D(CLIP_RECTS_EN), 1); |
||
507 | PUSH_DATA (push, 0); |
||
508 | BEGIN_NV04(push, NV50_3D(CLIP_RECTS_MODE), 1); |
||
509 | PUSH_DATA (push, NV50_3D_CLIP_RECTS_MODE_INSIDE_ANY); |
||
510 | BEGIN_NV04(push, NV50_3D(CLIP_RECT_HORIZ(0)), 8 * 2); |
||
511 | for (i = 0; i < 8 * 2; ++i) |
||
512 | PUSH_DATA(push, 0); |
||
513 | BEGIN_NV04(push, NV50_3D(CLIPID_ENABLE), 1); |
||
514 | PUSH_DATA (push, 0); |
||
515 | |||
516 | BEGIN_NV04(push, NV50_3D(VIEWPORT_TRANSFORM_EN), 1); |
||
517 | PUSH_DATA (push, 1); |
||
518 | BEGIN_NV04(push, NV50_3D(DEPTH_RANGE_NEAR(0)), 2); |
||
519 | PUSH_DATAf(push, 0.0f); |
||
520 | PUSH_DATAf(push, 1.0f); |
||
521 | |||
522 | BEGIN_NV04(push, NV50_3D(VIEW_VOLUME_CLIP_CTRL), 1); |
||
523 | #ifdef NV50_SCISSORS_CLIPPING |
||
524 | PUSH_DATA (push, 0x0000); |
||
525 | #else |
||
526 | PUSH_DATA (push, 0x1080); |
||
527 | #endif |
||
528 | |||
529 | BEGIN_NV04(push, NV50_3D(CLEAR_FLAGS), 1); |
||
530 | PUSH_DATA (push, NV50_3D_CLEAR_FLAGS_CLEAR_RECT_VIEWPORT); |
||
531 | |||
532 | /* We use scissors instead of exact view volume clipping, |
||
533 | * so they're always enabled. |
||
534 | */ |
||
535 | BEGIN_NV04(push, NV50_3D(SCISSOR_ENABLE(0)), 3); |
||
536 | PUSH_DATA (push, 1); |
||
537 | PUSH_DATA (push, 8192 << 16); |
||
538 | PUSH_DATA (push, 8192 << 16); |
||
539 | |||
540 | BEGIN_NV04(push, NV50_3D(RASTERIZE_ENABLE), 1); |
||
541 | PUSH_DATA (push, 1); |
||
542 | BEGIN_NV04(push, NV50_3D(POINT_RASTER_RULES), 1); |
||
543 | PUSH_DATA (push, NV50_3D_POINT_RASTER_RULES_OGL); |
||
544 | BEGIN_NV04(push, NV50_3D(FRAG_COLOR_CLAMP_EN), 1); |
||
545 | PUSH_DATA (push, 0x11111111); |
||
546 | BEGIN_NV04(push, NV50_3D(EDGEFLAG), 1); |
||
547 | PUSH_DATA (push, 1); |
||
548 | |||
549 | PUSH_KICK (push); |
||
550 | } |
||
551 | |||
552 | static int nv50_tls_alloc(struct nv50_screen *screen, unsigned tls_space, |
||
553 | uint64_t *tls_size) |
||
554 | { |
||
555 | struct nouveau_device *dev = screen->base.device; |
||
556 | int ret; |
||
557 | |||
558 | screen->cur_tls_space = util_next_power_of_two(tls_space / ONE_TEMP_SIZE) * |
||
559 | ONE_TEMP_SIZE; |
||
560 | if (nouveau_mesa_debug) |
||
561 | debug_printf("allocating space for %u temps\n", |
||
562 | util_next_power_of_two(tls_space / ONE_TEMP_SIZE)); |
||
563 | *tls_size = screen->cur_tls_space * util_next_power_of_two(screen->TPs) * |
||
564 | screen->MPsInTP * LOCAL_WARPS_ALLOC * THREADS_IN_WARP; |
||
565 | |||
566 | ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 1 << 16, |
||
567 | *tls_size, NULL, &screen->tls_bo); |
||
568 | if (ret) { |
||
569 | NOUVEAU_ERR("Failed to allocate local bo: %d\n", ret); |
||
570 | return ret; |
||
571 | } |
||
572 | |||
573 | return 0; |
||
574 | } |
||
575 | |||
576 | int nv50_tls_realloc(struct nv50_screen *screen, unsigned tls_space) |
||
577 | { |
||
578 | struct nouveau_pushbuf *push = screen->base.pushbuf; |
||
579 | int ret; |
||
580 | uint64_t tls_size; |
||
581 | |||
582 | if (tls_space < screen->cur_tls_space) |
||
583 | return 0; |
||
584 | if (tls_space > screen->max_tls_space) { |
||
585 | /* fixable by limiting number of warps (LOCAL_WARPS_LOG_ALLOC / |
||
586 | * LOCAL_WARPS_NO_CLAMP) */ |
||
587 | NOUVEAU_ERR("Unsupported number of temporaries (%u > %u). Fixable if someone cares.\n", |
||
588 | (unsigned)(tls_space / ONE_TEMP_SIZE), |
||
589 | (unsigned)(screen->max_tls_space / ONE_TEMP_SIZE)); |
||
590 | return -ENOMEM; |
||
591 | } |
||
592 | |||
593 | nouveau_bo_ref(NULL, &screen->tls_bo); |
||
594 | ret = nv50_tls_alloc(screen, tls_space, &tls_size); |
||
595 | if (ret) |
||
596 | return ret; |
||
597 | |||
598 | BEGIN_NV04(push, NV50_3D(LOCAL_ADDRESS_HIGH), 3); |
||
599 | PUSH_DATAh(push, screen->tls_bo->offset); |
||
600 | PUSH_DATA (push, screen->tls_bo->offset); |
||
601 | PUSH_DATA (push, util_logbase2(screen->cur_tls_space / 8)); |
||
602 | |||
603 | return 1; |
||
604 | } |
||
605 | |||
606 | struct pipe_screen * |
||
607 | nv50_screen_create(struct nouveau_device *dev) |
||
608 | { |
||
609 | struct nv50_screen *screen; |
||
610 | struct pipe_screen *pscreen; |
||
611 | struct nouveau_object *chan; |
||
612 | uint64_t value; |
||
613 | uint32_t tesla_class; |
||
614 | unsigned stack_size; |
||
615 | int ret; |
||
616 | |||
617 | screen = CALLOC_STRUCT(nv50_screen); |
||
618 | if (!screen) |
||
619 | return NULL; |
||
620 | pscreen = &screen->base.base; |
||
621 | |||
622 | ret = nouveau_screen_init(&screen->base, dev); |
||
623 | if (ret) { |
||
624 | NOUVEAU_ERR("nouveau_screen_init failed: %d\n", ret); |
||
625 | goto fail; |
||
626 | } |
||
627 | |||
628 | /* TODO: Prevent FIFO prefetch before transfer of index buffers and |
||
629 | * admit them to VRAM. |
||
630 | */ |
||
631 | screen->base.vidmem_bindings |= PIPE_BIND_CONSTANT_BUFFER | |
||
632 | PIPE_BIND_VERTEX_BUFFER; |
||
633 | screen->base.sysmem_bindings |= |
||
634 | PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER; |
||
635 | |||
636 | screen->base.pushbuf->user_priv = screen; |
||
637 | screen->base.pushbuf->rsvd_kick = 5; |
||
638 | |||
639 | chan = screen->base.channel; |
||
640 | |||
641 | pscreen->destroy = nv50_screen_destroy; |
||
642 | pscreen->context_create = nv50_create; |
||
643 | pscreen->is_format_supported = nv50_screen_is_format_supported; |
||
644 | pscreen->get_param = nv50_screen_get_param; |
||
645 | pscreen->get_shader_param = nv50_screen_get_shader_param; |
||
646 | pscreen->get_paramf = nv50_screen_get_paramf; |
||
647 | |||
648 | nv50_screen_init_resource_functions(pscreen); |
||
649 | |||
650 | if (screen->base.device->chipset < 0x84) { |
||
651 | /* PMPEG */ |
||
652 | nouveau_screen_init_vdec(&screen->base); |
||
653 | } else if (screen->base.device->chipset < 0x98 || |
||
654 | screen->base.device->chipset == 0xa0) { |
||
655 | /* VP2 */ |
||
656 | screen->base.base.get_video_param = nv84_screen_get_video_param; |
||
657 | screen->base.base.is_video_format_supported = nv84_screen_video_supported; |
||
658 | } else { |
||
659 | /* Unsupported, but need to init pointers. */ |
||
660 | nouveau_screen_init_vdec(&screen->base); |
||
661 | } |
||
662 | |||
663 | ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0, 4096, |
||
664 | NULL, &screen->fence.bo); |
||
665 | if (ret) { |
||
666 | NOUVEAU_ERR("Failed to allocate fence bo: %d\n", ret); |
||
667 | goto fail; |
||
668 | } |
||
669 | |||
670 | nouveau_bo_map(screen->fence.bo, 0, NULL); |
||
671 | screen->fence.map = screen->fence.bo->map; |
||
672 | screen->base.fence.emit = nv50_screen_fence_emit; |
||
673 | screen->base.fence.update = nv50_screen_fence_update; |
||
674 | |||
675 | ret = nouveau_object_new(chan, 0xbeef0301, NOUVEAU_NOTIFIER_CLASS, |
||
676 | &(struct nv04_notify){ .length = 32 }, |
||
677 | sizeof(struct nv04_notify), &screen->sync); |
||
678 | if (ret) { |
||
679 | NOUVEAU_ERR("Failed to allocate notifier: %d\n", ret); |
||
680 | goto fail; |
||
681 | } |
||
682 | |||
683 | ret = nouveau_object_new(chan, 0xbeef5039, NV50_M2MF_CLASS, |
||
684 | NULL, 0, &screen->m2mf); |
||
685 | if (ret) { |
||
686 | NOUVEAU_ERR("Failed to allocate PGRAPH context for M2MF: %d\n", ret); |
||
687 | goto fail; |
||
688 | } |
||
689 | |||
690 | ret = nouveau_object_new(chan, 0xbeef502d, NV50_2D_CLASS, |
||
691 | NULL, 0, &screen->eng2d); |
||
692 | if (ret) { |
||
693 | NOUVEAU_ERR("Failed to allocate PGRAPH context for 2D: %d\n", ret); |
||
694 | goto fail; |
||
695 | } |
||
696 | |||
697 | switch (dev->chipset & 0xf0) { |
||
698 | case 0x50: |
||
699 | tesla_class = NV50_3D_CLASS; |
||
700 | break; |
||
701 | case 0x80: |
||
702 | case 0x90: |
||
703 | tesla_class = NV84_3D_CLASS; |
||
704 | break; |
||
705 | case 0xa0: |
||
706 | switch (dev->chipset) { |
||
707 | case 0xa0: |
||
708 | case 0xaa: |
||
709 | case 0xac: |
||
710 | tesla_class = NVA0_3D_CLASS; |
||
711 | break; |
||
712 | case 0xaf: |
||
713 | tesla_class = NVAF_3D_CLASS; |
||
714 | break; |
||
715 | default: |
||
716 | tesla_class = NVA3_3D_CLASS; |
||
717 | break; |
||
718 | } |
||
719 | break; |
||
720 | default: |
||
721 | NOUVEAU_ERR("Not a known NV50 chipset: NV%02x\n", dev->chipset); |
||
722 | goto fail; |
||
723 | } |
||
724 | screen->base.class_3d = tesla_class; |
||
725 | |||
726 | ret = nouveau_object_new(chan, 0xbeef5097, tesla_class, |
||
727 | NULL, 0, &screen->tesla); |
||
728 | if (ret) { |
||
729 | NOUVEAU_ERR("Failed to allocate PGRAPH context for 3D: %d\n", ret); |
||
730 | goto fail; |
||
731 | } |
||
732 | |||
733 | ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 1 << 16, |
||
734 | 3 << NV50_CODE_BO_SIZE_LOG2, NULL, &screen->code); |
||
735 | if (ret) { |
||
736 | NOUVEAU_ERR("Failed to allocate code bo: %d\n", ret); |
||
737 | goto fail; |
||
738 | } |
||
739 | |||
740 | nouveau_heap_init(&screen->vp_code_heap, 0, 1 << NV50_CODE_BO_SIZE_LOG2); |
||
741 | nouveau_heap_init(&screen->gp_code_heap, 0, 1 << NV50_CODE_BO_SIZE_LOG2); |
||
742 | nouveau_heap_init(&screen->fp_code_heap, 0, 1 << NV50_CODE_BO_SIZE_LOG2); |
||
743 | |||
744 | nouveau_getparam(dev, NOUVEAU_GETPARAM_GRAPH_UNITS, &value); |
||
745 | |||
746 | screen->TPs = util_bitcount(value & 0xffff); |
||
747 | screen->MPsInTP = util_bitcount((value >> 24) & 0xf); |
||
748 | |||
749 | stack_size = util_next_power_of_two(screen->TPs) * screen->MPsInTP * |
||
750 | STACK_WARPS_ALLOC * 64 * 8; |
||
751 | |||
752 | ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 1 << 16, stack_size, NULL, |
||
753 | &screen->stack_bo); |
||
754 | if (ret) { |
||
755 | NOUVEAU_ERR("Failed to allocate stack bo: %d\n", ret); |
||
756 | goto fail; |
||
757 | } |
||
758 | |||
759 | uint64_t size_of_one_temp = util_next_power_of_two(screen->TPs) * |
||
760 | screen->MPsInTP * LOCAL_WARPS_ALLOC * THREADS_IN_WARP * |
||
761 | ONE_TEMP_SIZE; |
||
762 | screen->max_tls_space = dev->vram_size / size_of_one_temp * ONE_TEMP_SIZE; |
||
763 | screen->max_tls_space /= 2; /* half of vram */ |
||
764 | |||
765 | /* hw can address max 64 KiB */ |
||
766 | screen->max_tls_space = MIN2(screen->max_tls_space, 64 << 10); |
||
767 | |||
768 | uint64_t tls_size; |
||
769 | unsigned tls_space = 4/*temps*/ * ONE_TEMP_SIZE; |
||
770 | ret = nv50_tls_alloc(screen, tls_space, &tls_size); |
||
771 | if (ret) |
||
772 | goto fail; |
||
773 | |||
774 | if (nouveau_mesa_debug) |
||
775 | debug_printf("TPs = %u, MPsInTP = %u, VRAM = %"PRIu64" MiB, tls_size = %"PRIu64" KiB\n", |
||
776 | screen->TPs, screen->MPsInTP, dev->vram_size >> 20, tls_size >> 10); |
||
777 | |||
778 | ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 1 << 16, 4 << 16, NULL, |
||
779 | &screen->uniforms); |
||
780 | if (ret) { |
||
781 | NOUVEAU_ERR("Failed to allocate uniforms bo: %d\n", ret); |
||
782 | goto fail; |
||
783 | } |
||
784 | |||
785 | ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 1 << 16, 3 << 16, NULL, |
||
786 | &screen->txc); |
||
787 | if (ret) { |
||
788 | NOUVEAU_ERR("Failed to allocate TIC/TSC bo: %d\n", ret); |
||
789 | goto fail; |
||
790 | } |
||
791 | |||
792 | screen->tic.entries = CALLOC(4096, sizeof(void *)); |
||
793 | screen->tsc.entries = screen->tic.entries + 2048; |
||
794 | |||
795 | if (!nv50_blitter_create(screen)) |
||
796 | goto fail; |
||
797 | |||
798 | nv50_screen_init_hwctx(screen); |
||
799 | |||
800 | nouveau_fence_new(&screen->base, &screen->base.fence.current, FALSE); |
||
801 | |||
802 | return pscreen; |
||
803 | |||
804 | fail: |
||
805 | nv50_screen_destroy(pscreen); |
||
806 | return NULL; |
||
807 | } |
||
808 | |||
809 | int |
||
810 | nv50_screen_tic_alloc(struct nv50_screen *screen, void *entry) |
||
811 | { |
||
812 | int i = screen->tic.next; |
||
813 | |||
814 | while (screen->tic.lock[i / 32] & (1 << (i % 32))) |
||
815 | i = (i + 1) & (NV50_TIC_MAX_ENTRIES - 1); |
||
816 | |||
817 | screen->tic.next = (i + 1) & (NV50_TIC_MAX_ENTRIES - 1); |
||
818 | |||
819 | if (screen->tic.entries[i]) |
||
820 | nv50_tic_entry(screen->tic.entries[i])->id = -1; |
||
821 | |||
822 | screen->tic.entries[i] = entry; |
||
823 | return i; |
||
824 | } |
||
825 | |||
826 | int |
||
827 | nv50_screen_tsc_alloc(struct nv50_screen *screen, void *entry) |
||
828 | { |
||
829 | int i = screen->tsc.next; |
||
830 | |||
831 | while (screen->tsc.lock[i / 32] & (1 << (i % 32))) |
||
832 | i = (i + 1) & (NV50_TSC_MAX_ENTRIES - 1); |
||
833 | |||
834 | screen->tsc.next = (i + 1) & (NV50_TSC_MAX_ENTRIES - 1); |
||
835 | |||
836 | if (screen->tsc.entries[i]) |
||
837 | nv50_tsc_entry(screen->tsc.entries[i])->id = -1; |
||
838 | |||
839 | screen->tsc.entries[i] = entry; |
||
840 | return i; |
||
841 | }><>><>><>><>><>><>><>><>><>><>><>><>><>>>>><>><>><>>>><>><>><>><>><>><>><>><>><>><>><>><>><>><>><>><>><>><>><>><>><>><>><>><>><>><>><>>>>><> |