fixups for interface changes (mostly state trackers)
[mesa.git] / src / gallium / drivers / trace / tr_rbug.c
1 /**************************************************************************
2 *
3 * Copyright 2009 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28
29 #include "util/u_string.h"
30 #include "util/u_memory.h"
31 #include "util/u_simple_list.h"
32 #include "util/u_network.h"
33
34 #include "tgsi/tgsi_parse.h"
35
36 #include "tr_dump.h"
37 #include "tr_state.h"
38 #include "tr_buffer.h"
39 #include "tr_texture.h"
40
41 #include "rbug/rbug.h"
42
43 #include <errno.h>
44
45 #if defined(PIPE_SUBSYSTEM_WINDOWS_USER)
46 # define sleep Sleep
47 #elif defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD)
48 void usleep(int);
49 # define sleep usleep
50 #else
51 # warning "No socket implementation"
52 #endif
53
54 #define U642VOID(x) ((void *)(unsigned long)(x))
55 #define VOID2U64(x) ((uint64_t)(unsigned long)(x))
56
57 struct trace_rbug
58 {
59 struct trace_screen *tr_scr;
60 struct rbug_connection *con;
61 pipe_thread thread;
62 boolean running;
63 };
64
65 PIPE_THREAD_ROUTINE(trace_rbug_thread, void_tr_rbug);
66
67
68 /**********************************************************
69 * Helper functions
70 */
71
72
73 static struct trace_context *
74 trace_rbug_get_context_locked(struct trace_screen *tr_scr, rbug_context_t ctx)
75 {
76 struct trace_context *tr_ctx = NULL;
77 struct tr_list *ptr;
78
79 foreach(ptr, &tr_scr->contexts) {
80 tr_ctx = (struct trace_context *)((char*)ptr - offsetof(struct trace_context, list));
81 if (ctx == VOID2U64(tr_ctx))
82 break;
83 tr_ctx = NULL;
84 }
85
86 return tr_ctx;
87 }
88
89 static struct trace_shader *
90 trace_rbug_get_shader_locked(struct trace_context *tr_ctx, rbug_shader_t shdr)
91 {
92 struct trace_shader *tr_shdr = NULL;
93 struct tr_list *ptr;
94
95 foreach(ptr, &tr_ctx->shaders) {
96 tr_shdr = (struct trace_shader *)((char*)ptr - offsetof(struct trace_shader, list));
97 if (shdr == VOID2U64(tr_shdr))
98 break;
99 tr_shdr = NULL;
100 }
101
102 return tr_shdr;
103 }
104
105 static void *
106 trace_shader_create_locked(struct pipe_context *pipe,
107 struct trace_shader *tr_shdr,
108 struct tgsi_token *tokens)
109 {
110 void *state = NULL;
111 struct pipe_shader_state pss = { 0 };
112 pss.tokens = tokens;
113
114 if (tr_shdr->type == TRACE_SHADER_FRAGMENT) {
115 state = pipe->create_fs_state(pipe, &pss);
116 } else if (tr_shdr->type == TRACE_SHADER_VERTEX) {
117 state = pipe->create_vs_state(pipe, &pss);
118 } else
119 assert(0);
120
121 return state;
122 }
123
124 static void
125 trace_shader_bind_locked(struct pipe_context *pipe,
126 struct trace_shader *tr_shdr,
127 void *state)
128 {
129 if (tr_shdr->type == TRACE_SHADER_FRAGMENT) {
130 pipe->bind_fs_state(pipe, state);
131 } else if (tr_shdr->type == TRACE_SHADER_VERTEX) {
132 pipe->bind_vs_state(pipe, state);
133 } else
134 assert(0);
135 }
136
137 static void
138 trace_shader_delete_locked(struct pipe_context *pipe,
139 struct trace_shader *tr_shdr,
140 void *state)
141 {
142 if (tr_shdr->type == TRACE_SHADER_FRAGMENT) {
143 pipe->delete_fs_state(pipe, state);
144 } else if (tr_shdr->type == TRACE_SHADER_VERTEX) {
145 pipe->delete_vs_state(pipe, state);
146 } else
147 assert(0);
148 }
149
150 /************************************************
151 * Request handler functions
152 */
153
154
155 static int
156 trace_rbug_texture_list(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
157 {
158 struct trace_screen *tr_scr = tr_rbug->tr_scr;
159 struct trace_texture *tr_tex = NULL;
160 struct tr_list *ptr;
161 rbug_texture_t *texs;
162 int i = 0;
163
164 pipe_mutex_lock(tr_scr->list_mutex);
165 texs = MALLOC(tr_scr->num_textures * sizeof(rbug_texture_t));
166 foreach(ptr, &tr_scr->textures) {
167 tr_tex = (struct trace_texture *)((char*)ptr - offsetof(struct trace_texture, list));
168 texs[i++] = VOID2U64(tr_tex);
169 }
170 pipe_mutex_unlock(tr_scr->list_mutex);
171
172 rbug_send_texture_list_reply(tr_rbug->con, serial, texs, i, NULL);
173 FREE(texs);
174
175 return 0;
176 }
177
178 static int
179 trace_rbug_texture_info(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
180 {
181 struct trace_screen *tr_scr = tr_rbug->tr_scr;
182 struct trace_texture *tr_tex;
183 struct rbug_proto_texture_info *gpti = (struct rbug_proto_texture_info *)header;
184 struct tr_list *ptr;
185 struct pipe_texture *t;
186
187 pipe_mutex_lock(tr_scr->list_mutex);
188 foreach(ptr, &tr_scr->textures) {
189 tr_tex = (struct trace_texture *)((char*)ptr - offsetof(struct trace_texture, list));
190 if (gpti->texture == VOID2U64(tr_tex))
191 break;
192 tr_tex = NULL;
193 }
194
195 if (!tr_tex) {
196 pipe_mutex_unlock(tr_scr->list_mutex);
197 return -ESRCH;
198 }
199
200 t = tr_tex->texture;
201 rbug_send_texture_info_reply(tr_rbug->con, serial,
202 t->target, t->format,
203 &t->width0, 1,
204 &t->height0, 1,
205 &t->depth0, 1,
206 pf_get_blockwidth(t->format),
207 pf_get_blockheight(t->format),
208 pf_get_blocksize(t->format),
209 t->last_level,
210 t->nr_samples,
211 t->tex_usage,
212 NULL);
213
214 pipe_mutex_unlock(tr_scr->list_mutex);
215
216 return 0;
217 }
218
219 static int
220 trace_rbug_texture_read(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
221 {
222 struct rbug_proto_texture_read *gptr = (struct rbug_proto_texture_read *)header;
223
224 struct trace_screen *tr_scr = tr_rbug->tr_scr;
225 struct trace_texture *tr_tex;
226 struct tr_list *ptr;
227
228 struct pipe_screen *screen = tr_scr->screen;
229 struct pipe_texture *tex;
230 struct pipe_transfer *t;
231
232 void *map;
233
234 pipe_mutex_lock(tr_scr->list_mutex);
235 foreach(ptr, &tr_scr->textures) {
236 tr_tex = (struct trace_texture *)((char*)ptr - offsetof(struct trace_texture, list));
237 if (gptr->texture == VOID2U64(tr_tex))
238 break;
239 tr_tex = NULL;
240 }
241
242 if (!tr_tex) {
243 pipe_mutex_unlock(tr_scr->list_mutex);
244 return -ESRCH;
245 }
246
247 tex = tr_tex->texture;
248 t = screen->get_tex_transfer(tr_scr->screen, tex,
249 gptr->face, gptr->level, gptr->zslice,
250 PIPE_TRANSFER_READ,
251 gptr->x, gptr->y, gptr->w, gptr->h);
252
253 map = screen->transfer_map(screen, t);
254
255 rbug_send_texture_read_reply(tr_rbug->con, serial,
256 t->texture->format,
257 pf_get_blockwidth(t->texture->format),
258 pf_get_blockheight(t->texture->format),
259 pf_get_blocksize(t->texture->format),
260 (uint8_t*)map,
261 t->stride * pf_get_nblocksy(t->texture->format, t->height),
262 t->stride,
263 NULL);
264
265 screen->transfer_unmap(screen, t);
266 screen->tex_transfer_destroy(t);
267
268 pipe_mutex_unlock(tr_scr->list_mutex);
269
270 return 0;
271 }
272
273 static int
274 trace_rbug_context_list(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
275 {
276 struct trace_screen *tr_scr = tr_rbug->tr_scr;
277 struct tr_list *ptr;
278 struct trace_context *tr_ctx = NULL;
279 rbug_context_t *ctxs;
280 int i = 0;
281
282 pipe_mutex_lock(tr_scr->list_mutex);
283 ctxs = MALLOC(tr_scr->num_contexts * sizeof(rbug_context_t));
284 foreach(ptr, &tr_scr->contexts) {
285 tr_ctx = (struct trace_context *)((char*)ptr - offsetof(struct trace_context, list));
286 ctxs[i++] = VOID2U64(tr_ctx);
287 }
288 pipe_mutex_unlock(tr_scr->list_mutex);
289
290 rbug_send_context_list_reply(tr_rbug->con, serial, ctxs, i, NULL);
291 FREE(ctxs);
292
293 return 0;
294 }
295
296 static int
297 trace_rbug_context_info(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
298 {
299 struct rbug_proto_context_info *info = (struct rbug_proto_context_info *)header;
300
301 struct trace_screen *tr_scr = tr_rbug->tr_scr;
302 struct trace_context *tr_ctx = NULL;
303 rbug_texture_t cbufs[PIPE_MAX_COLOR_BUFS];
304 rbug_texture_t texs[PIPE_MAX_SAMPLERS];
305 int i;
306
307 pipe_mutex_lock(tr_scr->list_mutex);
308 tr_ctx = trace_rbug_get_context_locked(tr_scr, info->context);
309
310 if (!tr_ctx) {
311 pipe_mutex_unlock(tr_scr->list_mutex);
312 return -ESRCH;
313 }
314
315 /* protect the pipe context */
316 pipe_mutex_lock(tr_ctx->draw_mutex);
317 trace_dump_call_lock();
318
319 for (i = 0; i < tr_ctx->curr.nr_cbufs; i++)
320 cbufs[i] = VOID2U64(tr_ctx->curr.cbufs[i]);
321
322 for (i = 0; i < tr_ctx->curr.num_texs; i++)
323 texs[i] = VOID2U64(tr_ctx->curr.tex[i]);
324
325 rbug_send_context_info_reply(tr_rbug->con, serial,
326 VOID2U64(tr_ctx->curr.vs), VOID2U64(tr_ctx->curr.fs),
327 texs, tr_ctx->curr.num_texs,
328 cbufs, tr_ctx->curr.nr_cbufs,
329 VOID2U64(tr_ctx->curr.zsbuf),
330 tr_ctx->draw_blocker, tr_ctx->draw_blocked, NULL);
331
332 trace_dump_call_unlock();
333 pipe_mutex_unlock(tr_ctx->draw_mutex);
334
335 pipe_mutex_unlock(tr_scr->list_mutex);
336
337 return 0;
338 }
339
340 static int
341 trace_rbug_context_draw_block(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
342 {
343 struct rbug_proto_context_draw_block *block = (struct rbug_proto_context_draw_block *)header;
344
345 struct trace_screen *tr_scr = tr_rbug->tr_scr;
346 struct trace_context *tr_ctx = NULL;
347
348 pipe_mutex_lock(tr_scr->list_mutex);
349 tr_ctx = trace_rbug_get_context_locked(tr_scr, block->context);
350
351 if (!tr_ctx) {
352 pipe_mutex_unlock(tr_scr->list_mutex);
353 return -ESRCH;
354 }
355
356 pipe_mutex_lock(tr_ctx->draw_mutex);
357 tr_ctx->draw_blocker |= block->block;
358 pipe_mutex_unlock(tr_ctx->draw_mutex);
359
360 pipe_mutex_unlock(tr_scr->list_mutex);
361
362 return 0;
363 }
364
365 static int
366 trace_rbug_context_draw_step(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
367 {
368 struct rbug_proto_context_draw_step *step = (struct rbug_proto_context_draw_step *)header;
369
370 struct trace_screen *tr_scr = tr_rbug->tr_scr;
371 struct trace_context *tr_ctx = NULL;
372
373 pipe_mutex_lock(tr_scr->list_mutex);
374 tr_ctx = trace_rbug_get_context_locked(tr_scr, step->context);
375
376 if (!tr_ctx) {
377 pipe_mutex_unlock(tr_scr->list_mutex);
378 return -ESRCH;
379 }
380
381 pipe_mutex_lock(tr_ctx->draw_mutex);
382 if (tr_ctx->draw_blocked & RBUG_BLOCK_RULE) {
383 if (step->step & RBUG_BLOCK_RULE)
384 tr_ctx->draw_blocked &= ~RBUG_BLOCK_MASK;
385 } else {
386 tr_ctx->draw_blocked &= ~step->step;
387 }
388 pipe_mutex_unlock(tr_ctx->draw_mutex);
389
390 #ifdef PIPE_THREAD_HAVE_CONDVAR
391 pipe_condvar_broadcast(tr_ctx->draw_cond);
392 #endif
393
394 pipe_mutex_unlock(tr_scr->list_mutex);
395
396 return 0;
397 }
398
399 static int
400 trace_rbug_context_draw_unblock(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
401 {
402 struct rbug_proto_context_draw_unblock *unblock = (struct rbug_proto_context_draw_unblock *)header;
403
404 struct trace_screen *tr_scr = tr_rbug->tr_scr;
405 struct trace_context *tr_ctx = NULL;
406
407 pipe_mutex_lock(tr_scr->list_mutex);
408 tr_ctx = trace_rbug_get_context_locked(tr_scr, unblock->context);
409
410 if (!tr_ctx) {
411 pipe_mutex_unlock(tr_scr->list_mutex);
412 return -ESRCH;
413 }
414
415 pipe_mutex_lock(tr_ctx->draw_mutex);
416 if (tr_ctx->draw_blocked & RBUG_BLOCK_RULE) {
417 if (unblock->unblock & RBUG_BLOCK_RULE)
418 tr_ctx->draw_blocked &= ~RBUG_BLOCK_MASK;
419 } else {
420 tr_ctx->draw_blocked &= ~unblock->unblock;
421 }
422 tr_ctx->draw_blocker &= ~unblock->unblock;
423 pipe_mutex_unlock(tr_ctx->draw_mutex);
424
425 #ifdef PIPE_THREAD_HAVE_CONDVAR
426 pipe_condvar_broadcast(tr_ctx->draw_cond);
427 #endif
428
429 pipe_mutex_unlock(tr_scr->list_mutex);
430
431 return 0;
432 }
433
434 static int
435 trace_rbug_context_draw_rule(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
436 {
437 struct rbug_proto_context_draw_rule *rule = (struct rbug_proto_context_draw_rule *)header;
438
439 struct trace_screen *tr_scr = tr_rbug->tr_scr;
440 struct trace_context *tr_ctx = NULL;
441
442 pipe_mutex_lock(tr_scr->list_mutex);
443 tr_ctx = trace_rbug_get_context_locked(tr_scr, rule->context);
444
445 if (!tr_ctx) {
446 pipe_mutex_unlock(tr_scr->list_mutex);
447 return -ESRCH;
448 }
449
450 pipe_mutex_lock(tr_ctx->draw_mutex);
451 tr_ctx->draw_rule.vs = U642VOID(rule->vertex);
452 tr_ctx->draw_rule.fs = U642VOID(rule->fragment);
453 tr_ctx->draw_rule.tex = U642VOID(rule->texture);
454 tr_ctx->draw_rule.surf = U642VOID(rule->surface);
455 tr_ctx->draw_rule.blocker = rule->block;
456 tr_ctx->draw_blocker |= RBUG_BLOCK_RULE;
457 pipe_mutex_unlock(tr_ctx->draw_mutex);
458
459 #ifdef PIPE_THREAD_HAVE_CONDVAR
460 pipe_condvar_broadcast(tr_ctx->draw_cond);
461 #endif
462
463 pipe_mutex_unlock(tr_scr->list_mutex);
464
465 return 0;
466 }
467
468 static int
469 trace_rbug_context_flush(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
470 {
471 struct rbug_proto_context_flush *flush = (struct rbug_proto_context_flush *)header;
472
473 struct trace_screen *tr_scr = tr_rbug->tr_scr;
474 struct trace_context *tr_ctx = NULL;
475
476 pipe_mutex_lock(tr_scr->list_mutex);
477 tr_ctx = trace_rbug_get_context_locked(tr_scr, flush->context);
478
479 if (!tr_ctx) {
480 pipe_mutex_unlock(tr_scr->list_mutex);
481 return -ESRCH;
482 }
483
484 /* protect the pipe context */
485 trace_dump_call_lock();
486
487 tr_ctx->pipe->flush(tr_ctx->pipe, flush->flags, NULL);
488
489 trace_dump_call_unlock();
490 pipe_mutex_unlock(tr_scr->list_mutex);
491
492 return 0;
493 }
494
495 static int
496 trace_rbug_shader_list(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
497 {
498 struct rbug_proto_shader_list *list = (struct rbug_proto_shader_list *)header;
499
500 struct trace_screen *tr_scr = tr_rbug->tr_scr;
501 struct trace_context *tr_ctx = NULL;
502 struct trace_shader *tr_shdr = NULL;
503 struct tr_list *ptr;
504 rbug_shader_t *shdrs;
505 int i = 0;
506
507 pipe_mutex_lock(tr_scr->list_mutex);
508 tr_ctx = trace_rbug_get_context_locked(tr_scr, list->context);
509
510 if (!tr_ctx) {
511 pipe_mutex_unlock(tr_scr->list_mutex);
512 return -ESRCH;
513 }
514
515 pipe_mutex_lock(tr_ctx->list_mutex);
516 shdrs = MALLOC(tr_ctx->num_shaders * sizeof(rbug_shader_t));
517 foreach(ptr, &tr_ctx->shaders) {
518 tr_shdr = (struct trace_shader *)((char*)ptr - offsetof(struct trace_shader, list));
519 shdrs[i++] = VOID2U64(tr_shdr);
520 }
521
522 pipe_mutex_unlock(tr_ctx->list_mutex);
523 pipe_mutex_unlock(tr_scr->list_mutex);
524
525 rbug_send_shader_list_reply(tr_rbug->con, serial, shdrs, i, NULL);
526 FREE(shdrs);
527
528 return 0;
529 }
530
531 static int
532 trace_rbug_shader_info(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
533 {
534 struct rbug_proto_shader_info *info = (struct rbug_proto_shader_info *)header;
535
536 struct trace_screen *tr_scr = tr_rbug->tr_scr;
537 struct trace_context *tr_ctx = NULL;
538 struct trace_shader *tr_shdr = NULL;
539 unsigned original_len;
540 unsigned replaced_len;
541
542 pipe_mutex_lock(tr_scr->list_mutex);
543 tr_ctx = trace_rbug_get_context_locked(tr_scr, info->context);
544
545 if (!tr_ctx) {
546 pipe_mutex_unlock(tr_scr->list_mutex);
547 return -ESRCH;
548 }
549
550 pipe_mutex_lock(tr_ctx->list_mutex);
551
552 tr_shdr = trace_rbug_get_shader_locked(tr_ctx, info->shader);
553
554 if (!tr_shdr) {
555 pipe_mutex_unlock(tr_ctx->list_mutex);
556 pipe_mutex_unlock(tr_scr->list_mutex);
557 return -ESRCH;
558 }
559
560 /* just in case */
561 assert(sizeof(struct tgsi_token) == 4);
562
563 original_len = tgsi_num_tokens(tr_shdr->tokens);
564 if (tr_shdr->replaced_tokens)
565 replaced_len = tgsi_num_tokens(tr_shdr->replaced_tokens);
566 else
567 replaced_len = 0;
568
569 rbug_send_shader_info_reply(tr_rbug->con, serial,
570 (uint32_t*)tr_shdr->tokens, original_len,
571 (uint32_t*)tr_shdr->replaced_tokens, replaced_len,
572 tr_shdr->disabled,
573 NULL);
574
575 pipe_mutex_unlock(tr_ctx->list_mutex);
576 pipe_mutex_unlock(tr_scr->list_mutex);
577
578 return 0;
579 }
580
581 static int
582 trace_rbug_shader_disable(struct trace_rbug *tr_rbug, struct rbug_header *header)
583 {
584 struct rbug_proto_shader_disable *dis = (struct rbug_proto_shader_disable *)header;
585
586 struct trace_screen *tr_scr = tr_rbug->tr_scr;
587 struct trace_context *tr_ctx = NULL;
588 struct trace_shader *tr_shdr = NULL;
589
590 pipe_mutex_lock(tr_scr->list_mutex);
591 tr_ctx = trace_rbug_get_context_locked(tr_scr, dis->context);
592
593 if (!tr_ctx) {
594 pipe_mutex_unlock(tr_scr->list_mutex);
595 return -ESRCH;
596 }
597
598 pipe_mutex_lock(tr_ctx->list_mutex);
599
600 tr_shdr = trace_rbug_get_shader_locked(tr_ctx, dis->shader);
601
602 if (!tr_shdr) {
603 pipe_mutex_unlock(tr_ctx->list_mutex);
604 pipe_mutex_unlock(tr_scr->list_mutex);
605 return -ESRCH;
606 }
607
608 tr_shdr->disabled = dis->disable;
609
610 pipe_mutex_unlock(tr_ctx->list_mutex);
611 pipe_mutex_unlock(tr_scr->list_mutex);
612
613 return 0;
614 }
615
616 static int
617 trace_rbug_shader_replace(struct trace_rbug *tr_rbug, struct rbug_header *header)
618 {
619 struct rbug_proto_shader_replace *rep = (struct rbug_proto_shader_replace *)header;
620
621 struct trace_screen *tr_scr = tr_rbug->tr_scr;
622 struct trace_context *tr_ctx = NULL;
623 struct trace_shader *tr_shdr = NULL;
624 struct pipe_context *pipe = NULL;
625 void *state;
626
627 pipe_mutex_lock(tr_scr->list_mutex);
628 tr_ctx = trace_rbug_get_context_locked(tr_scr, rep->context);
629
630 if (!tr_ctx) {
631 pipe_mutex_unlock(tr_scr->list_mutex);
632 return -ESRCH;
633 }
634
635 pipe_mutex_lock(tr_ctx->list_mutex);
636
637 tr_shdr = trace_rbug_get_shader_locked(tr_ctx, rep->shader);
638
639 if (!tr_shdr) {
640 pipe_mutex_unlock(tr_ctx->list_mutex);
641 pipe_mutex_unlock(tr_scr->list_mutex);
642 return -ESRCH;
643 }
644
645 /* protect the pipe context */
646 trace_dump_call_lock();
647
648 pipe = tr_ctx->pipe;
649
650 /* remove old replaced shader */
651 if (tr_shdr->replaced) {
652 if (tr_ctx->curr.fs == tr_shdr || tr_ctx->curr.vs == tr_shdr)
653 trace_shader_bind_locked(pipe, tr_shdr, tr_shdr->state);
654
655 FREE(tr_shdr->replaced_tokens);
656 trace_shader_delete_locked(pipe, tr_shdr, tr_shdr->replaced);
657 tr_shdr->replaced = NULL;
658 tr_shdr->replaced_tokens = NULL;
659 }
660
661 /* empty inputs means restore old which we did above */
662 if (rep->tokens_len == 0)
663 goto out;
664
665 tr_shdr->replaced_tokens = tgsi_dup_tokens((struct tgsi_token *)rep->tokens);
666 if (!tr_shdr->replaced_tokens)
667 goto err;
668
669 state = trace_shader_create_locked(pipe, tr_shdr, tr_shdr->replaced_tokens);
670 if (!state)
671 goto err;
672
673 /* bind new shader if the shader is currently a bound */
674 if (tr_ctx->curr.fs == tr_shdr || tr_ctx->curr.vs == tr_shdr)
675 trace_shader_bind_locked(pipe, tr_shdr, state);
676
677 /* save state */
678 tr_shdr->replaced = state;
679
680 out:
681 trace_dump_call_unlock();
682 pipe_mutex_unlock(tr_ctx->list_mutex);
683 pipe_mutex_unlock(tr_scr->list_mutex);
684
685 return 0;
686
687 err:
688 FREE(tr_shdr->replaced_tokens);
689 tr_shdr->replaced = NULL;
690 tr_shdr->replaced_tokens = NULL;
691
692 trace_dump_call_unlock();
693 pipe_mutex_unlock(tr_ctx->list_mutex);
694 pipe_mutex_unlock(tr_scr->list_mutex);
695 return -EINVAL;
696 }
697
698 static boolean
699 trace_rbug_header(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
700 {
701 int ret = 0;
702
703 switch(header->opcode) {
704 case RBUG_OP_PING:
705 rbug_send_ping_reply(tr_rbug->con, serial, NULL);
706 break;
707 case RBUG_OP_TEXTURE_LIST:
708 ret = trace_rbug_texture_list(tr_rbug, header, serial);
709 break;
710 case RBUG_OP_TEXTURE_INFO:
711 ret = trace_rbug_texture_info(tr_rbug, header, serial);
712 break;
713 case RBUG_OP_TEXTURE_READ:
714 ret = trace_rbug_texture_read(tr_rbug, header, serial);
715 break;
716 case RBUG_OP_CONTEXT_LIST:
717 ret = trace_rbug_context_list(tr_rbug, header, serial);
718 break;
719 case RBUG_OP_CONTEXT_INFO:
720 ret = trace_rbug_context_info(tr_rbug, header, serial);
721 break;
722 case RBUG_OP_CONTEXT_DRAW_BLOCK:
723 ret = trace_rbug_context_draw_block(tr_rbug, header, serial);
724 break;
725 case RBUG_OP_CONTEXT_DRAW_STEP:
726 ret = trace_rbug_context_draw_step(tr_rbug, header, serial);
727 break;
728 case RBUG_OP_CONTEXT_DRAW_UNBLOCK:
729 ret = trace_rbug_context_draw_unblock(tr_rbug, header, serial);
730 break;
731 case RBUG_OP_CONTEXT_DRAW_RULE:
732 ret = trace_rbug_context_draw_rule(tr_rbug, header, serial);
733 break;
734 case RBUG_OP_CONTEXT_FLUSH:
735 ret = trace_rbug_context_flush(tr_rbug, header, serial);
736 break;
737 case RBUG_OP_SHADER_LIST:
738 ret = trace_rbug_shader_list(tr_rbug, header, serial);
739 break;
740 case RBUG_OP_SHADER_INFO:
741 ret = trace_rbug_shader_info(tr_rbug, header, serial);
742 break;
743 case RBUG_OP_SHADER_DISABLE:
744 ret = trace_rbug_shader_disable(tr_rbug, header);
745 break;
746 case RBUG_OP_SHADER_REPLACE:
747 ret = trace_rbug_shader_replace(tr_rbug, header);
748 break;
749 default:
750 debug_printf("%s - unsupported opcode %u\n", __FUNCTION__, header->opcode);
751 ret = -ENOSYS;
752 break;
753 }
754 rbug_free_header(header);
755
756 if (ret)
757 rbug_send_error_reply(tr_rbug->con, serial, ret, NULL);
758
759 return TRUE;
760 }
761
762 static void
763 trace_rbug_con(struct trace_rbug *tr_rbug)
764 {
765 struct rbug_header *header;
766 uint32_t serial;
767
768 debug_printf("%s - connection received\n", __FUNCTION__);
769
770 while(tr_rbug->running) {
771 header = rbug_get_message(tr_rbug->con, &serial);
772 if (!header)
773 break;
774
775 if (!trace_rbug_header(tr_rbug, header, serial))
776 break;
777 }
778
779 debug_printf("%s - connection closed\n", __FUNCTION__);
780
781 rbug_disconnect(tr_rbug->con);
782 tr_rbug->con = NULL;
783 }
784
785 PIPE_THREAD_ROUTINE(trace_rbug_thread, void_tr_rbug)
786 {
787 struct trace_rbug *tr_rbug = void_tr_rbug;
788 uint16_t port = 13370;
789 int s = -1;
790 int c;
791
792 u_socket_init();
793
794 for (;port <= 13379 && s < 0; port++)
795 s = u_socket_listen_on_port(port);
796
797 if (s < 0) {
798 debug_printf("trace_rbug - failed to listen\n");
799 return NULL;
800 }
801
802 u_socket_block(s, false);
803
804 debug_printf("trace_rbug - remote debugging listening on port %u\n", --port);
805
806 while(tr_rbug->running) {
807 sleep(1);
808
809 c = u_socket_accept(s);
810 if (c < 0)
811 continue;
812
813 u_socket_block(c, true);
814 tr_rbug->con = rbug_from_socket(c);
815
816 trace_rbug_con(tr_rbug);
817
818 u_socket_close(c);
819 }
820
821 u_socket_close(s);
822
823 u_socket_stop();
824
825 return NULL;
826 }
827
828 /**********************************************************
829 *
830 */
831
832 struct trace_rbug *
833 trace_rbug_start(struct trace_screen *tr_scr)
834 {
835 struct trace_rbug *tr_rbug = CALLOC_STRUCT(trace_rbug);
836 if (!tr_rbug)
837 return NULL;
838
839 tr_rbug->tr_scr = tr_scr;
840 tr_rbug->running = TRUE;
841 tr_rbug->thread = pipe_thread_create(trace_rbug_thread, tr_rbug);
842
843 return tr_rbug;
844 }
845
846 void
847 trace_rbug_stop(struct trace_rbug *tr_rbug)
848 {
849 if (!tr_rbug)
850 return;
851
852 tr_rbug->running = false;
853 pipe_thread_wait(tr_rbug->thread);
854
855 FREE(tr_rbug);
856
857 return;
858 }
859
860 void
861 trace_rbug_notify_draw_blocked(struct trace_context *tr_ctx)
862 {
863 struct trace_screen *tr_scr = trace_screen(tr_ctx->base.screen);
864 struct trace_rbug *tr_rbug = tr_scr->rbug;
865
866 if (tr_rbug && tr_rbug->con)
867 rbug_send_context_draw_blocked(tr_rbug->con,
868 VOID2U64(tr_ctx), tr_ctx->draw_blocked, NULL);
869 }