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