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