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/format/u_format.h"
31 #include "util/u_string.h"
32 #include "util/u_inlines.h"
33 #include "util/u_memory.h"
34 #include "util/simple_list.h"
35 #include "util/u_network.h"
36 #include "util/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 *)(uintptr_t)(x))
48 #define VOID2U64(x) ((uint64_t)(uintptr_t)(x))
49 
50 struct rbug_rbug
51 {
52    struct rbug_screen *rb_screen;
53    struct rbug_connection *con;
54    thrd_t thread;
55    bool running;
56 };
57 
58 int
59 rbug_thread(void *void_rbug);
60 
61 
62 /**********************************************************
63  * Helper functions
64  */
65 
66 
67 static struct rbug_context *
rbug_get_context_locked(struct rbug_screen * rb_screen,rbug_context_t ctx)68 rbug_get_context_locked(struct rbug_screen *rb_screen, rbug_context_t ctx)
69 {
70    struct rbug_context *rb_context = NULL;
71    struct rbug_list *ptr;
72 
73    foreach(ptr, &rb_screen->contexts) {
74       rb_context = container_of(ptr, struct rbug_context, list);
75       if (ctx == VOID2U64(rb_context))
76          break;
77       rb_context = NULL;
78    }
79 
80    return rb_context;
81 }
82 
83 static struct rbug_shader *
rbug_get_shader_locked(struct rbug_context * rb_context,rbug_shader_t shdr)84 rbug_get_shader_locked(struct rbug_context *rb_context, rbug_shader_t shdr)
85 {
86    struct rbug_shader *tr_shdr = NULL;
87    struct rbug_list *ptr;
88 
89    foreach(ptr, &rb_context->shaders) {
90       tr_shdr = container_of(ptr, struct rbug_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 *
rbug_shader_create_locked(struct pipe_context * pipe,struct rbug_shader * rb_shader,struct tgsi_token * tokens)100 rbug_shader_create_locked(struct pipe_context *pipe,
101                           struct rbug_shader *rb_shader,
102                           struct tgsi_token *tokens)
103 {
104    void *state = NULL;
105    struct pipe_shader_state pss;
106    memset(&pss, 0, sizeof(pss));
107    pss.tokens = tokens;
108 
109    switch(rb_shader->type) {
110    case RBUG_SHADER_FRAGMENT:
111       state = pipe->create_fs_state(pipe, &pss);
112       break;
113    case RBUG_SHADER_VERTEX:
114       state = pipe->create_vs_state(pipe, &pss);
115       break;
116    case RBUG_SHADER_GEOM:
117       state = pipe->create_gs_state(pipe, &pss);
118       break;
119    default:
120       assert(0);
121       break;
122    }
123 
124    return state;
125 }
126 
127 static void
rbug_shader_bind_locked(struct pipe_context * pipe,struct rbug_shader * rb_shader,void * state)128 rbug_shader_bind_locked(struct pipe_context *pipe,
129                         struct rbug_shader *rb_shader,
130                         void *state)
131 {
132    switch(rb_shader->type) {
133    case RBUG_SHADER_FRAGMENT:
134       pipe->bind_fs_state(pipe, state);
135       break;
136    case RBUG_SHADER_VERTEX:
137       pipe->bind_vs_state(pipe, state);
138       break;
139    case RBUG_SHADER_GEOM:
140       pipe->bind_gs_state(pipe, state);
141       break;
142    default:
143       assert(0);
144       break;
145    }
146 }
147 
148 static void
rbug_shader_delete_locked(struct pipe_context * pipe,struct rbug_shader * rb_shader,void * state)149 rbug_shader_delete_locked(struct pipe_context *pipe,
150                           struct rbug_shader *rb_shader,
151                           void *state)
152 {
153    switch(rb_shader->type) {
154    case RBUG_SHADER_FRAGMENT:
155       pipe->delete_fs_state(pipe, state);
156       break;
157    case RBUG_SHADER_VERTEX:
158       pipe->delete_vs_state(pipe, state);
159       break;
160    case RBUG_SHADER_GEOM:
161       pipe->delete_gs_state(pipe, state);
162       break;
163    default:
164       assert(0);
165       break;
166    }
167 }
168 
169 /************************************************
170  * Request handler functions
171  */
172 
173 
174 static int
rbug_texture_list(struct rbug_rbug * tr_rbug,struct rbug_header * header,uint32_t serial)175 rbug_texture_list(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
176 {
177    struct rbug_screen *rb_screen = tr_rbug->rb_screen;
178    struct rbug_resource *tr_tex = NULL;
179    struct rbug_list *ptr;
180    rbug_texture_t *texs;
181    int i = 0;
182 
183    mtx_lock(&rb_screen->list_mutex);
184    texs = MALLOC(rb_screen->num_resources * sizeof(rbug_texture_t));
185    foreach(ptr, &rb_screen->resources) {
186       tr_tex = container_of(ptr, struct rbug_resource, list);
187       texs[i++] = VOID2U64(tr_tex);
188    }
189    mtx_unlock(&rb_screen->list_mutex);
190 
191    rbug_send_texture_list_reply(tr_rbug->con, serial, texs, i, NULL);
192    FREE(texs);
193 
194    return 0;
195 }
196 
197 static int
rbug_texture_info(struct rbug_rbug * tr_rbug,struct rbug_header * header,uint32_t serial)198 rbug_texture_info(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
199 {
200    struct rbug_screen *rb_screen = tr_rbug->rb_screen;
201    struct rbug_resource *tr_tex = NULL;
202    struct rbug_proto_texture_info *gpti = (struct rbug_proto_texture_info *)header;
203    struct rbug_list *ptr;
204    struct pipe_resource *t;
205    uint16_t num_layers;
206 
207    mtx_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       mtx_unlock(&rb_screen->list_mutex);
217       return -ESRCH;
218    }
219 
220    t = tr_tex->resource;
221    num_layers = util_num_layers(t, 0);
222 
223    rbug_send_texture_info_reply(tr_rbug->con, serial,
224                                t->target, t->format,
225                                &t->width0, 1,
226                                &t->height0, 1,
227                                &num_layers, 1,
228                                util_format_get_blockwidth(t->format),
229                                util_format_get_blockheight(t->format),
230                                util_format_get_blocksize(t->format),
231                                t->last_level,
232                                t->nr_samples,
233                                t->bind,
234                                NULL);
235 
236    mtx_unlock(&rb_screen->list_mutex);
237 
238    return 0;
239 }
240 
241 static int
rbug_texture_read(struct rbug_rbug * tr_rbug,struct rbug_header * header,uint32_t serial)242 rbug_texture_read(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
243 {
244    struct rbug_proto_texture_read *gptr = (struct rbug_proto_texture_read *)header;
245 
246    struct rbug_screen *rb_screen = tr_rbug->rb_screen;
247    struct rbug_resource *tr_tex = NULL;
248    struct rbug_list *ptr;
249 
250    struct pipe_context *context = rb_screen->private_context;
251    struct pipe_resource *tex;
252    struct pipe_transfer *t;
253 
254    void *map;
255 
256    mtx_lock(&rb_screen->list_mutex);
257    foreach(ptr, &rb_screen->resources) {
258       tr_tex = container_of(ptr, struct rbug_resource, list);
259       if (gptr->texture == VOID2U64(tr_tex))
260          break;
261       tr_tex = NULL;
262    }
263 
264    if (!tr_tex) {
265       mtx_unlock(&rb_screen->list_mutex);
266       return -ESRCH;
267    }
268 
269    tex = tr_tex->resource;
270    map = pipe_texture_map(context, tex,
271                            gptr->level, gptr->face + gptr->zslice,
272                            PIPE_MAP_READ,
273                            gptr->x, gptr->y, gptr->w, gptr->h, &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->texture_unmap(context, t);
287 
288    mtx_unlock(&rb_screen->list_mutex);
289 
290    return 0;
291 }
292 
293 static int
rbug_context_list(struct rbug_rbug * tr_rbug,struct rbug_header * header,uint32_t serial)294 rbug_context_list(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
295 {
296    struct rbug_screen *rb_screen = tr_rbug->rb_screen;
297    struct rbug_list *ptr;
298    struct rbug_context *rb_context = NULL;
299    rbug_context_t *ctxs;
300    int i = 0;
301 
302    mtx_lock(&rb_screen->list_mutex);
303    ctxs = MALLOC(rb_screen->num_contexts * sizeof(rbug_context_t));
304    foreach(ptr, &rb_screen->contexts) {
305       rb_context = container_of(ptr, struct rbug_context, list);
306       ctxs[i++] = VOID2U64(rb_context);
307    }
308    mtx_unlock(&rb_screen->list_mutex);
309 
310    rbug_send_context_list_reply(tr_rbug->con, serial, ctxs, i, NULL);
311    FREE(ctxs);
312 
313    return 0;
314 }
315 
316 static int
rbug_context_info(struct rbug_rbug * tr_rbug,struct rbug_header * header,uint32_t serial)317 rbug_context_info(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
318 {
319    struct rbug_proto_context_info *info = (struct rbug_proto_context_info *)header;
320 
321    struct rbug_screen *rb_screen = tr_rbug->rb_screen;
322    struct rbug_context *rb_context = NULL;
323    rbug_texture_t cbufs[PIPE_MAX_COLOR_BUFS];
324    rbug_texture_t texs[PIPE_MAX_SHADER_SAMPLER_VIEWS];
325    unsigned i;
326 
327    mtx_lock(&rb_screen->list_mutex);
328    rb_context = rbug_get_context_locked(rb_screen, info->context);
329 
330    if (!rb_context) {
331       mtx_unlock(&rb_screen->list_mutex);
332       return -ESRCH;
333    }
334 
335    /* protect the pipe context */
336    mtx_lock(&rb_context->draw_mutex);
337    mtx_lock(&rb_context->call_mutex);
338 
339    for (i = 0; i < rb_context->curr.nr_cbufs; i++)
340       cbufs[i] = VOID2U64(rb_context->curr.cbufs[i]);
341 
342    /* XXX what about vertex/geometry shader texture views? */
343    for (i = 0; i < rb_context->curr.num_views[PIPE_SHADER_FRAGMENT]; i++)
344       texs[i] = VOID2U64(rb_context->curr.texs[PIPE_SHADER_FRAGMENT][i]);
345 
346    rbug_send_context_info_reply(tr_rbug->con, serial,
347                                 VOID2U64(rb_context->curr.shader[PIPE_SHADER_VERTEX]), VOID2U64(rb_context->curr.shader[PIPE_SHADER_FRAGMENT]),
348                                 texs, rb_context->curr.num_views[PIPE_SHADER_FRAGMENT],
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    mtx_unlock(&rb_context->call_mutex);
354    mtx_unlock(&rb_context->draw_mutex);
355    mtx_unlock(&rb_screen->list_mutex);
356 
357    return 0;
358 }
359 
360 static int
rbug_context_draw_block(struct rbug_rbug * tr_rbug,struct rbug_header * header,uint32_t serial)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    mtx_lock(&rb_screen->list_mutex);
369    rb_context = rbug_get_context_locked(rb_screen, block->context);
370 
371    if (!rb_context) {
372       mtx_unlock(&rb_screen->list_mutex);
373       return -ESRCH;
374    }
375 
376    mtx_lock(&rb_context->draw_mutex);
377    rb_context->draw_blocker |= block->block;
378    mtx_unlock(&rb_context->draw_mutex);
379 
380    mtx_unlock(&rb_screen->list_mutex);
381 
382    return 0;
383 }
384 
385 static int
rbug_context_draw_step(struct rbug_rbug * tr_rbug,struct rbug_header * header,uint32_t serial)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    mtx_lock(&rb_screen->list_mutex);
394    rb_context = rbug_get_context_locked(rb_screen, step->context);
395 
396    if (!rb_context) {
397       mtx_unlock(&rb_screen->list_mutex);
398       return -ESRCH;
399    }
400 
401    mtx_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    mtx_unlock(&rb_context->draw_mutex);
409 
410    cnd_broadcast(&rb_context->draw_cond);
411 
412    mtx_unlock(&rb_screen->list_mutex);
413 
414    return 0;
415 }
416 
417 static int
rbug_context_draw_unblock(struct rbug_rbug * tr_rbug,struct rbug_header * header,uint32_t serial)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    mtx_lock(&rb_screen->list_mutex);
426    rb_context = rbug_get_context_locked(rb_screen, unblock->context);
427 
428    if (!rb_context) {
429       mtx_unlock(&rb_screen->list_mutex);
430       return -ESRCH;
431    }
432 
433    mtx_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    mtx_unlock(&rb_context->draw_mutex);
442 
443    cnd_broadcast(&rb_context->draw_cond);
444 
445    mtx_unlock(&rb_screen->list_mutex);
446 
447    return 0;
448 }
449 
450 static int
rbug_context_draw_rule(struct rbug_rbug * tr_rbug,struct rbug_header * header,uint32_t serial)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    mtx_lock(&rb_screen->list_mutex);
459    rb_context = rbug_get_context_locked(rb_screen, rule->context);
460 
461    if (!rb_context) {
462       mtx_unlock(&rb_screen->list_mutex);
463       return -ESRCH;
464    }
465 
466    mtx_lock(&rb_context->draw_mutex);
467    rb_context->draw_rule.shader[PIPE_SHADER_VERTEX] = U642VOID(rule->vertex);
468    rb_context->draw_rule.shader[PIPE_SHADER_FRAGMENT] = 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    mtx_unlock(&rb_context->draw_mutex);
474 
475    cnd_broadcast(&rb_context->draw_cond);
476 
477    mtx_unlock(&rb_screen->list_mutex);
478 
479    return 0;
480 }
481 
482 static int
rbug_context_flush(struct rbug_rbug * tr_rbug,struct rbug_header * header,uint32_t serial)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    mtx_lock(&rb_screen->list_mutex);
491    rb_context = rbug_get_context_locked(rb_screen, flush->context);
492 
493    if (!rb_context) {
494       mtx_unlock(&rb_screen->list_mutex);
495       return -ESRCH;
496    }
497 
498    /* protect the pipe context */
499    mtx_lock(&rb_context->call_mutex);
500 
501    rb_context->pipe->flush(rb_context->pipe, NULL, 0);
502 
503    mtx_unlock(&rb_context->call_mutex);
504    mtx_unlock(&rb_screen->list_mutex);
505 
506    return 0;
507 }
508 
509 static int
rbug_shader_list(struct rbug_rbug * tr_rbug,struct rbug_header * header,uint32_t serial)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    mtx_lock(&rb_screen->list_mutex);
522    rb_context = rbug_get_context_locked(rb_screen, list->context);
523 
524    if (!rb_context) {
525       mtx_unlock(&rb_screen->list_mutex);
526       return -ESRCH;
527    }
528 
529    mtx_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    mtx_unlock(&rb_context->list_mutex);
537    mtx_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
rbug_shader_info(struct rbug_rbug * tr_rbug,struct rbug_header * header,uint32_t serial)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    mtx_lock(&rb_screen->list_mutex);
557    rb_context = rbug_get_context_locked(rb_screen, info->context);
558 
559    if (!rb_context) {
560       mtx_unlock(&rb_screen->list_mutex);
561       return -ESRCH;
562    }
563 
564    mtx_lock(&rb_context->list_mutex);
565 
566    tr_shdr = rbug_get_shader_locked(rb_context, info->shader);
567 
568    if (!tr_shdr) {
569       mtx_unlock(&rb_context->list_mutex);
570       mtx_unlock(&rb_screen->list_mutex);
571       return -ESRCH;
572    }
573 
574    /* just in case */
575    assert(sizeof(struct tgsi_token) == 4);
576 
577    if (tr_shdr->tokens) {
578            original_len = tgsi_num_tokens(tr_shdr->tokens);
579            if (tr_shdr->replaced_tokens)
580                    replaced_len = tgsi_num_tokens(tr_shdr->replaced_tokens);
581            else
582                    replaced_len = 0;
583 
584            rbug_send_shader_info_reply(tr_rbug->con, serial,
585                                        (uint32_t*)tr_shdr->tokens, original_len,
586                                        (uint32_t*)tr_shdr->replaced_tokens, replaced_len,
587                                        tr_shdr->disabled,
588                                        NULL);
589    }
590 
591    mtx_unlock(&rb_context->list_mutex);
592    mtx_unlock(&rb_screen->list_mutex);
593 
594    return 0;
595 }
596 
597 static int
rbug_shader_disable(struct rbug_rbug * tr_rbug,struct rbug_header * header)598 rbug_shader_disable(struct rbug_rbug *tr_rbug, struct rbug_header *header)
599 {
600    struct rbug_proto_shader_disable *dis = (struct rbug_proto_shader_disable *)header;
601 
602    struct rbug_screen *rb_screen = tr_rbug->rb_screen;
603    struct rbug_context *rb_context = NULL;
604    struct rbug_shader *tr_shdr = NULL;
605 
606    mtx_lock(&rb_screen->list_mutex);
607    rb_context = rbug_get_context_locked(rb_screen, dis->context);
608 
609    if (!rb_context) {
610       mtx_unlock(&rb_screen->list_mutex);
611       return -ESRCH;
612    }
613 
614    mtx_lock(&rb_context->list_mutex);
615 
616    tr_shdr = rbug_get_shader_locked(rb_context, dis->shader);
617 
618    if (!tr_shdr) {
619       mtx_unlock(&rb_context->list_mutex);
620       mtx_unlock(&rb_screen->list_mutex);
621       return -ESRCH;
622    }
623 
624    tr_shdr->disabled = dis->disable;
625 
626    mtx_unlock(&rb_context->list_mutex);
627    mtx_unlock(&rb_screen->list_mutex);
628 
629    return 0;
630 }
631 
632 static int
rbug_shader_replace(struct rbug_rbug * tr_rbug,struct rbug_header * header)633 rbug_shader_replace(struct rbug_rbug *tr_rbug, struct rbug_header *header)
634 {
635    struct rbug_proto_shader_replace *rep = (struct rbug_proto_shader_replace *)header;
636 
637    struct rbug_screen *rb_screen = tr_rbug->rb_screen;
638    struct rbug_context *rb_context = NULL;
639    struct rbug_shader *tr_shdr = NULL;
640    struct pipe_context *pipe = NULL;
641    void *state;
642 
643    mtx_lock(&rb_screen->list_mutex);
644    rb_context = rbug_get_context_locked(rb_screen, rep->context);
645 
646    if (!rb_context) {
647       mtx_unlock(&rb_screen->list_mutex);
648       return -ESRCH;
649    }
650 
651    mtx_lock(&rb_context->list_mutex);
652 
653    tr_shdr = rbug_get_shader_locked(rb_context, rep->shader);
654 
655    if (!tr_shdr) {
656       mtx_unlock(&rb_context->list_mutex);
657       mtx_unlock(&rb_screen->list_mutex);
658       return -ESRCH;
659    }
660 
661    /* protect the pipe context */
662    mtx_lock(&rb_context->call_mutex);
663 
664    pipe = rb_context->pipe;
665 
666    /* remove old replaced shader */
667    if (tr_shdr->replaced_shader) {
668       /* if this shader is bound rebind the original shader */
669       if (rb_context->curr.shader[PIPE_SHADER_FRAGMENT] == tr_shdr || rb_context->curr.shader[PIPE_SHADER_VERTEX] == tr_shdr)
670          rbug_shader_bind_locked(pipe, tr_shdr, tr_shdr->shader);
671 
672       FREE(tr_shdr->replaced_tokens);
673       rbug_shader_delete_locked(pipe, tr_shdr, tr_shdr->replaced_shader);
674       tr_shdr->replaced_shader = NULL;
675       tr_shdr->replaced_tokens = NULL;
676    }
677 
678    /* empty inputs means restore old which we did above */
679    if (rep->tokens_len == 0)
680       goto out;
681 
682    tr_shdr->replaced_tokens = tgsi_dup_tokens((struct tgsi_token *)rep->tokens);
683    if (!tr_shdr->replaced_tokens)
684       goto err;
685 
686    state = rbug_shader_create_locked(pipe, tr_shdr, tr_shdr->replaced_tokens);
687    if (!state)
688       goto err;
689 
690    /* bind new shader if the shader is currently a bound */
691    if (rb_context->curr.shader[PIPE_SHADER_FRAGMENT] == tr_shdr || rb_context->curr.shader[PIPE_SHADER_VERTEX] == tr_shdr)
692       rbug_shader_bind_locked(pipe, tr_shdr, state);
693 
694    /* save state */
695    tr_shdr->replaced_shader = state;
696 
697 out:
698    mtx_unlock(&rb_context->call_mutex);
699    mtx_unlock(&rb_context->list_mutex);
700    mtx_unlock(&rb_screen->list_mutex);
701 
702    return 0;
703 
704 err:
705    FREE(tr_shdr->replaced_tokens);
706    tr_shdr->replaced_shader = NULL;
707    tr_shdr->replaced_tokens = NULL;
708 
709    mtx_unlock(&rb_context->call_mutex);
710    mtx_unlock(&rb_context->list_mutex);
711    mtx_unlock(&rb_screen->list_mutex);
712    return -EINVAL;
713 }
714 
715 static bool
rbug_header(struct rbug_rbug * tr_rbug,struct rbug_header * header,uint32_t serial)716 rbug_header(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
717 {
718    int ret = 0;
719 
720    switch(header->opcode) {
721       case RBUG_OP_PING:
722          rbug_send_ping_reply(tr_rbug->con, serial, NULL);
723          break;
724       case RBUG_OP_TEXTURE_LIST:
725          ret = rbug_texture_list(tr_rbug, header, serial);
726          break;
727       case RBUG_OP_TEXTURE_INFO:
728          ret = rbug_texture_info(tr_rbug, header, serial);
729          break;
730       case RBUG_OP_TEXTURE_READ:
731          ret = rbug_texture_read(tr_rbug, header, serial);
732          break;
733       case RBUG_OP_CONTEXT_LIST:
734          ret = rbug_context_list(tr_rbug, header, serial);
735          break;
736       case RBUG_OP_CONTEXT_INFO:
737          ret = rbug_context_info(tr_rbug, header, serial);
738          break;
739       case RBUG_OP_CONTEXT_DRAW_BLOCK:
740          ret = rbug_context_draw_block(tr_rbug, header, serial);
741          break;
742       case RBUG_OP_CONTEXT_DRAW_STEP:
743          ret = rbug_context_draw_step(tr_rbug, header, serial);
744          break;
745       case RBUG_OP_CONTEXT_DRAW_UNBLOCK:
746          ret = rbug_context_draw_unblock(tr_rbug, header, serial);
747          break;
748       case RBUG_OP_CONTEXT_DRAW_RULE:
749          ret = rbug_context_draw_rule(tr_rbug, header, serial);
750          break;
751       case RBUG_OP_CONTEXT_FLUSH:
752          ret = rbug_context_flush(tr_rbug, header, serial);
753          break;
754       case RBUG_OP_SHADER_LIST:
755          ret = rbug_shader_list(tr_rbug, header, serial);
756          break;
757       case RBUG_OP_SHADER_INFO:
758          ret = rbug_shader_info(tr_rbug, header, serial);
759          break;
760       case RBUG_OP_SHADER_DISABLE:
761          ret = rbug_shader_disable(tr_rbug, header);
762          break;
763       case RBUG_OP_SHADER_REPLACE:
764          ret = rbug_shader_replace(tr_rbug, header);
765          break;
766       default:
767          debug_printf("%s - unsupported opcode %u\n", __FUNCTION__, header->opcode);
768          ret = -ENOSYS;
769          break;
770    }
771    rbug_free_header(header);
772 
773    if (ret)
774       rbug_send_error_reply(tr_rbug->con, serial, ret, NULL);
775 
776    return true;
777 }
778 
779 static void
rbug_con(struct rbug_rbug * tr_rbug)780 rbug_con(struct rbug_rbug *tr_rbug)
781 {
782    struct rbug_header *header;
783    uint32_t serial;
784 
785    debug_printf("%s - connection received\n", __FUNCTION__);
786 
787    while(tr_rbug->running) {
788       header = rbug_get_message(tr_rbug->con, &serial);
789       if (!header)
790          break;
791 
792       if (!rbug_header(tr_rbug, header, serial))
793          break;
794    }
795 
796    debug_printf("%s - connection closed\n", __FUNCTION__);
797 
798    rbug_disconnect(tr_rbug->con);
799    tr_rbug->con = NULL;
800 }
801 
802 int
rbug_thread(void * void_tr_rbug)803 rbug_thread(void *void_tr_rbug)
804 {
805    struct rbug_rbug *tr_rbug = void_tr_rbug;
806    uint16_t port = 13370;
807    int s = -1;
808    int c;
809 
810    u_socket_init();
811 
812    for (;port <= 13379 && s < 0; port++)
813       s = u_socket_listen_on_port(port);
814 
815    if (s < 0) {
816       debug_printf("rbug_rbug - failed to listen\n");
817       return 0;
818    }
819 
820    u_socket_block(s, false);
821 
822    debug_printf("rbug_rbug - remote debugging listening on port %u\n", --port);
823 
824    while(tr_rbug->running) {
825       os_time_sleep(1);
826 
827       c = u_socket_accept(s);
828       if (c < 0)
829          continue;
830 
831       u_socket_block(c, true);
832       tr_rbug->con = rbug_from_socket(c);
833 
834       rbug_con(tr_rbug);
835 
836       u_socket_close(c);
837    }
838 
839    u_socket_close(s);
840 
841    u_socket_stop();
842 
843    return 0;
844 }
845 
846 /**********************************************************
847  *
848  */
849 
850 struct rbug_rbug *
rbug_start(struct rbug_screen * rb_screen)851 rbug_start(struct rbug_screen *rb_screen)
852 {
853    struct rbug_rbug *tr_rbug = CALLOC_STRUCT(rbug_rbug);
854    if (!tr_rbug)
855       return NULL;
856 
857    tr_rbug->rb_screen = rb_screen;
858    tr_rbug->running = true;
859    tr_rbug->thread = u_thread_create(rbug_thread, tr_rbug);
860 
861    return tr_rbug;
862 }
863 
864 void
rbug_stop(struct rbug_rbug * tr_rbug)865 rbug_stop(struct rbug_rbug *tr_rbug)
866 {
867    if (!tr_rbug)
868       return;
869 
870    tr_rbug->running = false;
871    thrd_join(tr_rbug->thread, NULL);
872 
873    FREE(tr_rbug);
874 
875    return;
876 }
877 
878 void
rbug_notify_draw_blocked(struct rbug_context * rb_context)879 rbug_notify_draw_blocked(struct rbug_context *rb_context)
880 {
881    struct rbug_screen *rb_screen = rbug_screen(rb_context->base.screen);
882    struct rbug_rbug *tr_rbug = rb_screen->rbug;
883 
884    if (tr_rbug && tr_rbug->con)
885       rbug_send_context_draw_blocked(tr_rbug->con,
886                                      VOID2U64(rb_context), rb_context->draw_blocked, NULL);
887 }
888