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