• 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/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 *
rbug_get_context_locked(struct rbug_screen * rb_screen,rbug_context_t ctx)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 *
rbug_get_shader_locked(struct rbug_context * rb_context,rbug_shader_t shdr)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 *
rbug_shader_create_locked(struct pipe_context * pipe,struct rbug_shader * rb_shader,struct tgsi_token * tokens)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;
108    memset(&pss, 0, sizeof(pss));
109    pss.tokens = tokens;
110 
111    switch(rb_shader->type) {
112    case RBUG_SHADER_FRAGMENT:
113       state = pipe->create_fs_state(pipe, &pss);
114       break;
115    case RBUG_SHADER_VERTEX:
116       state = pipe->create_vs_state(pipe, &pss);
117       break;
118    case RBUG_SHADER_GEOM:
119       state = pipe->create_gs_state(pipe, &pss);
120       break;
121    default:
122       assert(0);
123       break;
124    }
125 
126    return state;
127 }
128 
129 static void
rbug_shader_bind_locked(struct pipe_context * pipe,struct rbug_shader * rb_shader,void * state)130 rbug_shader_bind_locked(struct pipe_context *pipe,
131                         struct rbug_shader *rb_shader,
132                         void *state)
133 {
134    switch(rb_shader->type) {
135    case RBUG_SHADER_FRAGMENT:
136       pipe->bind_fs_state(pipe, state);
137       break;
138    case RBUG_SHADER_VERTEX:
139       pipe->bind_vs_state(pipe, state);
140       break;
141    case RBUG_SHADER_GEOM:
142       pipe->bind_gs_state(pipe, state);
143       break;
144    default:
145       assert(0);
146       break;
147    }
148 }
149 
150 static void
rbug_shader_delete_locked(struct pipe_context * pipe,struct rbug_shader * rb_shader,void * state)151 rbug_shader_delete_locked(struct pipe_context *pipe,
152                           struct rbug_shader *rb_shader,
153                           void *state)
154 {
155    switch(rb_shader->type) {
156    case RBUG_SHADER_FRAGMENT:
157       pipe->delete_fs_state(pipe, state);
158       break;
159    case RBUG_SHADER_VERTEX:
160       pipe->delete_vs_state(pipe, state);
161       break;
162    case RBUG_SHADER_GEOM:
163       pipe->delete_gs_state(pipe, state);
164       break;
165    default:
166       assert(0);
167       break;
168    }
169 }
170 
171 /************************************************
172  * Request handler functions
173  */
174 
175 
176 static int
rbug_texture_list(struct rbug_rbug * tr_rbug,struct rbug_header * header,uint32_t serial)177 rbug_texture_list(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
178 {
179    struct rbug_screen *rb_screen = tr_rbug->rb_screen;
180    struct rbug_resource *tr_tex = NULL;
181    struct rbug_list *ptr;
182    rbug_texture_t *texs;
183    int i = 0;
184 
185    pipe_mutex_lock(rb_screen->list_mutex);
186    texs = MALLOC(rb_screen->num_resources * sizeof(rbug_texture_t));
187    foreach(ptr, &rb_screen->resources) {
188       tr_tex = container_of(ptr, struct rbug_resource, list);
189       texs[i++] = VOID2U64(tr_tex);
190    }
191    pipe_mutex_unlock(rb_screen->list_mutex);
192 
193    rbug_send_texture_list_reply(tr_rbug->con, serial, texs, i, NULL);
194    FREE(texs);
195 
196    return 0;
197 }
198 
199 static int
rbug_texture_info(struct rbug_rbug * tr_rbug,struct rbug_header * header,uint32_t serial)200 rbug_texture_info(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
201 {
202    struct rbug_screen *rb_screen = tr_rbug->rb_screen;
203    struct rbug_resource *tr_tex = NULL;
204    struct rbug_proto_texture_info *gpti = (struct rbug_proto_texture_info *)header;
205    struct rbug_list *ptr;
206    struct pipe_resource *t;
207 
208    pipe_mutex_lock(rb_screen->list_mutex);
209    foreach(ptr, &rb_screen->resources) {
210       tr_tex = container_of(ptr, struct rbug_resource, list);
211       if (gpti->texture == VOID2U64(tr_tex))
212          break;
213       tr_tex = NULL;
214    }
215 
216    if (!tr_tex) {
217       pipe_mutex_unlock(rb_screen->list_mutex);
218       return -ESRCH;
219    }
220 
221    t = tr_tex->resource;
222    rbug_send_texture_info_reply(tr_rbug->con, serial,
223                                t->target, t->format,
224                                &t->width0, 1,
225                                &t->height0, 1,
226                                &t->depth0, 1,
227                                util_format_get_blockwidth(t->format),
228                                util_format_get_blockheight(t->format),
229                                util_format_get_blocksize(t->format),
230                                t->last_level,
231                                t->nr_samples,
232                                t->bind,
233                                NULL);
234 
235    pipe_mutex_unlock(rb_screen->list_mutex);
236 
237    return 0;
238 }
239 
240 static int
rbug_texture_read(struct rbug_rbug * tr_rbug,struct rbug_header * header,uint32_t serial)241 rbug_texture_read(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
242 {
243    struct rbug_proto_texture_read *gptr = (struct rbug_proto_texture_read *)header;
244 
245    struct rbug_screen *rb_screen = tr_rbug->rb_screen;
246    struct rbug_resource *tr_tex = NULL;
247    struct rbug_list *ptr;
248 
249    struct pipe_context *context = rb_screen->private_context;
250    struct pipe_resource *tex;
251    struct pipe_transfer *t;
252 
253    void *map;
254 
255    pipe_mutex_lock(rb_screen->list_mutex);
256    foreach(ptr, &rb_screen->resources) {
257       tr_tex = container_of(ptr, struct rbug_resource, list);
258       if (gptr->texture == VOID2U64(tr_tex))
259          break;
260       tr_tex = NULL;
261    }
262 
263    if (!tr_tex) {
264       pipe_mutex_unlock(rb_screen->list_mutex);
265       return -ESRCH;
266    }
267 
268    tex = tr_tex->resource;
269    t = pipe_get_transfer(context, tex,
270                          gptr->level, gptr->face + gptr->zslice,
271                          PIPE_TRANSFER_READ,
272                          gptr->x, gptr->y, gptr->w, gptr->h);
273 
274    map = context->transfer_map(context, t);
275 
276    rbug_send_texture_read_reply(tr_rbug->con, serial,
277                                 t->resource->format,
278                                 util_format_get_blockwidth(t->resource->format),
279                                 util_format_get_blockheight(t->resource->format),
280                                 util_format_get_blocksize(t->resource->format),
281                                 (uint8_t*)map,
282                                 t->stride * util_format_get_nblocksy(t->resource->format,
283                                                                      t->box.height),
284                                 t->stride,
285                                 NULL);
286 
287    context->transfer_unmap(context, t);
288    context->transfer_destroy(context, t);
289 
290    pipe_mutex_unlock(rb_screen->list_mutex);
291 
292    return 0;
293 }
294 
295 static int
rbug_context_list(struct rbug_rbug * tr_rbug,struct rbug_header * header,uint32_t serial)296 rbug_context_list(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
297 {
298    struct rbug_screen *rb_screen = tr_rbug->rb_screen;
299    struct rbug_list *ptr;
300    struct rbug_context *rb_context = NULL;
301    rbug_context_t *ctxs;
302    int i = 0;
303 
304    pipe_mutex_lock(rb_screen->list_mutex);
305    ctxs = MALLOC(rb_screen->num_contexts * sizeof(rbug_context_t));
306    foreach(ptr, &rb_screen->contexts) {
307       rb_context = container_of(ptr, struct rbug_context, list);
308       ctxs[i++] = VOID2U64(rb_context);
309    }
310    pipe_mutex_unlock(rb_screen->list_mutex);
311 
312    rbug_send_context_list_reply(tr_rbug->con, serial, ctxs, i, NULL);
313    FREE(ctxs);
314 
315    return 0;
316 }
317 
318 static int
rbug_context_info(struct rbug_rbug * tr_rbug,struct rbug_header * header,uint32_t serial)319 rbug_context_info(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
320 {
321    struct rbug_proto_context_info *info = (struct rbug_proto_context_info *)header;
322 
323    struct rbug_screen *rb_screen = tr_rbug->rb_screen;
324    struct rbug_context *rb_context = NULL;
325    rbug_texture_t cbufs[PIPE_MAX_COLOR_BUFS];
326    rbug_texture_t texs[PIPE_MAX_SAMPLERS];
327    int i;
328 
329    pipe_mutex_lock(rb_screen->list_mutex);
330    rb_context = rbug_get_context_locked(rb_screen, info->context);
331 
332    if (!rb_context) {
333       pipe_mutex_unlock(rb_screen->list_mutex);
334       return -ESRCH;
335    }
336 
337    /* protect the pipe context */
338    pipe_mutex_lock(rb_context->draw_mutex);
339    pipe_mutex_lock(rb_context->call_mutex);
340 
341    for (i = 0; i < rb_context->curr.nr_cbufs; i++)
342       cbufs[i] = VOID2U64(rb_context->curr.cbufs[i]);
343 
344    /* XXX what about vertex/geometry shader texture views? */
345    for (i = 0; i < rb_context->curr.num_views[PIPE_SHADER_FRAGMENT]; i++)
346       texs[i] = VOID2U64(rb_context->curr.texs[PIPE_SHADER_FRAGMENT][i]);
347 
348    rbug_send_context_info_reply(tr_rbug->con, serial,
349                                 VOID2U64(rb_context->curr.shader[PIPE_SHADER_VERTEX]), VOID2U64(rb_context->curr.shader[PIPE_SHADER_FRAGMENT]),
350                                 texs, rb_context->curr.num_views[PIPE_SHADER_FRAGMENT],
351                                 cbufs, rb_context->curr.nr_cbufs,
352                                 VOID2U64(rb_context->curr.zsbuf),
353                                 rb_context->draw_blocker, rb_context->draw_blocked, NULL);
354 
355    pipe_mutex_unlock(rb_context->call_mutex);
356    pipe_mutex_unlock(rb_context->draw_mutex);
357    pipe_mutex_unlock(rb_screen->list_mutex);
358 
359    return 0;
360 }
361 
362 static int
rbug_context_draw_block(struct rbug_rbug * tr_rbug,struct rbug_header * header,uint32_t serial)363 rbug_context_draw_block(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
364 {
365    struct rbug_proto_context_draw_block *block = (struct rbug_proto_context_draw_block *)header;
366 
367    struct rbug_screen *rb_screen = tr_rbug->rb_screen;
368    struct rbug_context *rb_context = NULL;
369 
370    pipe_mutex_lock(rb_screen->list_mutex);
371    rb_context = rbug_get_context_locked(rb_screen, block->context);
372 
373    if (!rb_context) {
374       pipe_mutex_unlock(rb_screen->list_mutex);
375       return -ESRCH;
376    }
377 
378    pipe_mutex_lock(rb_context->draw_mutex);
379    rb_context->draw_blocker |= block->block;
380    pipe_mutex_unlock(rb_context->draw_mutex);
381 
382    pipe_mutex_unlock(rb_screen->list_mutex);
383 
384    return 0;
385 }
386 
387 static int
rbug_context_draw_step(struct rbug_rbug * tr_rbug,struct rbug_header * header,uint32_t serial)388 rbug_context_draw_step(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
389 {
390    struct rbug_proto_context_draw_step *step = (struct rbug_proto_context_draw_step *)header;
391 
392    struct rbug_screen *rb_screen = tr_rbug->rb_screen;
393    struct rbug_context *rb_context = NULL;
394 
395    pipe_mutex_lock(rb_screen->list_mutex);
396    rb_context = rbug_get_context_locked(rb_screen, step->context);
397 
398    if (!rb_context) {
399       pipe_mutex_unlock(rb_screen->list_mutex);
400       return -ESRCH;
401    }
402 
403    pipe_mutex_lock(rb_context->draw_mutex);
404    if (rb_context->draw_blocked & RBUG_BLOCK_RULE) {
405       if (step->step & RBUG_BLOCK_RULE)
406          rb_context->draw_blocked &= ~RBUG_BLOCK_MASK;
407    } else {
408       rb_context->draw_blocked &= ~step->step;
409    }
410    pipe_mutex_unlock(rb_context->draw_mutex);
411 
412    pipe_condvar_broadcast(rb_context->draw_cond);
413 
414    pipe_mutex_unlock(rb_screen->list_mutex);
415 
416    return 0;
417 }
418 
419 static int
rbug_context_draw_unblock(struct rbug_rbug * tr_rbug,struct rbug_header * header,uint32_t serial)420 rbug_context_draw_unblock(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
421 {
422    struct rbug_proto_context_draw_unblock *unblock = (struct rbug_proto_context_draw_unblock *)header;
423 
424    struct rbug_screen *rb_screen = tr_rbug->rb_screen;
425    struct rbug_context *rb_context = NULL;
426 
427    pipe_mutex_lock(rb_screen->list_mutex);
428    rb_context = rbug_get_context_locked(rb_screen, unblock->context);
429 
430    if (!rb_context) {
431       pipe_mutex_unlock(rb_screen->list_mutex);
432       return -ESRCH;
433    }
434 
435    pipe_mutex_lock(rb_context->draw_mutex);
436    if (rb_context->draw_blocked & RBUG_BLOCK_RULE) {
437       if (unblock->unblock & RBUG_BLOCK_RULE)
438          rb_context->draw_blocked &= ~RBUG_BLOCK_MASK;
439    } else {
440       rb_context->draw_blocked &= ~unblock->unblock;
441    }
442    rb_context->draw_blocker &= ~unblock->unblock;
443    pipe_mutex_unlock(rb_context->draw_mutex);
444 
445    pipe_condvar_broadcast(rb_context->draw_cond);
446 
447    pipe_mutex_unlock(rb_screen->list_mutex);
448 
449    return 0;
450 }
451 
452 static int
rbug_context_draw_rule(struct rbug_rbug * tr_rbug,struct rbug_header * header,uint32_t serial)453 rbug_context_draw_rule(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
454 {
455    struct rbug_proto_context_draw_rule *rule = (struct rbug_proto_context_draw_rule *)header;
456 
457    struct rbug_screen *rb_screen = tr_rbug->rb_screen;
458    struct rbug_context *rb_context = NULL;
459 
460    pipe_mutex_lock(rb_screen->list_mutex);
461    rb_context = rbug_get_context_locked(rb_screen, rule->context);
462 
463    if (!rb_context) {
464       pipe_mutex_unlock(rb_screen->list_mutex);
465       return -ESRCH;
466    }
467 
468    pipe_mutex_lock(rb_context->draw_mutex);
469    rb_context->draw_rule.shader[PIPE_SHADER_VERTEX] = U642VOID(rule->vertex);
470    rb_context->draw_rule.shader[PIPE_SHADER_FRAGMENT] = U642VOID(rule->fragment);
471    rb_context->draw_rule.texture = U642VOID(rule->texture);
472    rb_context->draw_rule.surf = U642VOID(rule->surface);
473    rb_context->draw_rule.blocker = rule->block;
474    rb_context->draw_blocker |= RBUG_BLOCK_RULE;
475    pipe_mutex_unlock(rb_context->draw_mutex);
476 
477    pipe_condvar_broadcast(rb_context->draw_cond);
478 
479    pipe_mutex_unlock(rb_screen->list_mutex);
480 
481    return 0;
482 }
483 
484 static int
rbug_context_flush(struct rbug_rbug * tr_rbug,struct rbug_header * header,uint32_t serial)485 rbug_context_flush(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
486 {
487    struct rbug_proto_context_flush *flush = (struct rbug_proto_context_flush *)header;
488 
489    struct rbug_screen *rb_screen = tr_rbug->rb_screen;
490    struct rbug_context *rb_context = NULL;
491 
492    pipe_mutex_lock(rb_screen->list_mutex);
493    rb_context = rbug_get_context_locked(rb_screen, flush->context);
494 
495    if (!rb_context) {
496       pipe_mutex_unlock(rb_screen->list_mutex);
497       return -ESRCH;
498    }
499 
500    /* protect the pipe context */
501    pipe_mutex_lock(rb_context->call_mutex);
502 
503    rb_context->pipe->flush(rb_context->pipe, NULL);
504 
505    pipe_mutex_unlock(rb_context->call_mutex);
506    pipe_mutex_unlock(rb_screen->list_mutex);
507 
508    return 0;
509 }
510 
511 static int
rbug_shader_list(struct rbug_rbug * tr_rbug,struct rbug_header * header,uint32_t serial)512 rbug_shader_list(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
513 {
514    struct rbug_proto_shader_list *list = (struct rbug_proto_shader_list *)header;
515 
516    struct rbug_screen *rb_screen = tr_rbug->rb_screen;
517    struct rbug_context *rb_context = NULL;
518    struct rbug_shader *tr_shdr = NULL;
519    struct rbug_list *ptr;
520    rbug_shader_t *shdrs;
521    int i = 0;
522 
523    pipe_mutex_lock(rb_screen->list_mutex);
524    rb_context = rbug_get_context_locked(rb_screen, list->context);
525 
526    if (!rb_context) {
527       pipe_mutex_unlock(rb_screen->list_mutex);
528       return -ESRCH;
529    }
530 
531    pipe_mutex_lock(rb_context->list_mutex);
532    shdrs = MALLOC(rb_context->num_shaders * sizeof(rbug_shader_t));
533    foreach(ptr, &rb_context->shaders) {
534       tr_shdr = container_of(ptr, struct rbug_shader, list);
535       shdrs[i++] = VOID2U64(tr_shdr);
536    }
537 
538    pipe_mutex_unlock(rb_context->list_mutex);
539    pipe_mutex_unlock(rb_screen->list_mutex);
540 
541    rbug_send_shader_list_reply(tr_rbug->con, serial, shdrs, i, NULL);
542    FREE(shdrs);
543 
544    return 0;
545 }
546 
547 static int
rbug_shader_info(struct rbug_rbug * tr_rbug,struct rbug_header * header,uint32_t serial)548 rbug_shader_info(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
549 {
550    struct rbug_proto_shader_info *info = (struct rbug_proto_shader_info *)header;
551 
552    struct rbug_screen *rb_screen = tr_rbug->rb_screen;
553    struct rbug_context *rb_context = NULL;
554    struct rbug_shader *tr_shdr = NULL;
555    unsigned original_len;
556    unsigned replaced_len;
557 
558    pipe_mutex_lock(rb_screen->list_mutex);
559    rb_context = rbug_get_context_locked(rb_screen, info->context);
560 
561    if (!rb_context) {
562       pipe_mutex_unlock(rb_screen->list_mutex);
563       return -ESRCH;
564    }
565 
566    pipe_mutex_lock(rb_context->list_mutex);
567 
568    tr_shdr = rbug_get_shader_locked(rb_context, info->shader);
569 
570    if (!tr_shdr) {
571       pipe_mutex_unlock(rb_context->list_mutex);
572       pipe_mutex_unlock(rb_screen->list_mutex);
573       return -ESRCH;
574    }
575 
576    /* just in case */
577    assert(sizeof(struct tgsi_token) == 4);
578 
579    original_len = tgsi_num_tokens(tr_shdr->tokens);
580    if (tr_shdr->replaced_tokens)
581       replaced_len = tgsi_num_tokens(tr_shdr->replaced_tokens);
582    else
583       replaced_len = 0;
584 
585    rbug_send_shader_info_reply(tr_rbug->con, serial,
586                                (uint32_t*)tr_shdr->tokens, original_len,
587                                (uint32_t*)tr_shdr->replaced_tokens, replaced_len,
588                                tr_shdr->disabled,
589                                NULL);
590 
591    pipe_mutex_unlock(rb_context->list_mutex);
592    pipe_mutex_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    pipe_mutex_lock(rb_screen->list_mutex);
607    rb_context = rbug_get_context_locked(rb_screen, dis->context);
608 
609    if (!rb_context) {
610       pipe_mutex_unlock(rb_screen->list_mutex);
611       return -ESRCH;
612    }
613 
614    pipe_mutex_lock(rb_context->list_mutex);
615 
616    tr_shdr = rbug_get_shader_locked(rb_context, dis->shader);
617 
618    if (!tr_shdr) {
619       pipe_mutex_unlock(rb_context->list_mutex);
620       pipe_mutex_unlock(rb_screen->list_mutex);
621       return -ESRCH;
622    }
623 
624    tr_shdr->disabled = dis->disable;
625 
626    pipe_mutex_unlock(rb_context->list_mutex);
627    pipe_mutex_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    pipe_mutex_lock(rb_screen->list_mutex);
644    rb_context = rbug_get_context_locked(rb_screen, rep->context);
645 
646    if (!rb_context) {
647       pipe_mutex_unlock(rb_screen->list_mutex);
648       return -ESRCH;
649    }
650 
651    pipe_mutex_lock(rb_context->list_mutex);
652 
653    tr_shdr = rbug_get_shader_locked(rb_context, rep->shader);
654 
655    if (!tr_shdr) {
656       pipe_mutex_unlock(rb_context->list_mutex);
657       pipe_mutex_unlock(rb_screen->list_mutex);
658       return -ESRCH;
659    }
660 
661    /* protect the pipe context */
662    pipe_mutex_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    pipe_mutex_unlock(rb_context->call_mutex);
699    pipe_mutex_unlock(rb_context->list_mutex);
700    pipe_mutex_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    pipe_mutex_unlock(rb_context->call_mutex);
710    pipe_mutex_unlock(rb_context->list_mutex);
711    pipe_mutex_unlock(rb_screen->list_mutex);
712    return -EINVAL;
713 }
714 
715 static boolean
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 
PIPE_THREAD_ROUTINE(rbug_thread,void_tr_rbug)802 PIPE_THREAD_ROUTINE(rbug_thread, void_tr_rbug)
803 {
804    struct rbug_rbug *tr_rbug = void_tr_rbug;
805    uint16_t port = 13370;
806    int s = -1;
807    int c;
808 
809    u_socket_init();
810 
811    for (;port <= 13379 && s < 0; port++)
812       s = u_socket_listen_on_port(port);
813 
814    if (s < 0) {
815       debug_printf("rbug_rbug - failed to listen\n");
816       return NULL;
817    }
818 
819    u_socket_block(s, false);
820 
821    debug_printf("rbug_rbug - remote debugging listening on port %u\n", --port);
822 
823    while(tr_rbug->running) {
824       os_time_sleep(1);
825 
826       c = u_socket_accept(s);
827       if (c < 0)
828          continue;
829 
830       u_socket_block(c, true);
831       tr_rbug->con = rbug_from_socket(c);
832 
833       rbug_con(tr_rbug);
834 
835       u_socket_close(c);
836    }
837 
838    u_socket_close(s);
839 
840    u_socket_stop();
841 
842    return NULL;
843 }
844 
845 /**********************************************************
846  *
847  */
848 
849 struct rbug_rbug *
rbug_start(struct rbug_screen * rb_screen)850 rbug_start(struct rbug_screen *rb_screen)
851 {
852    struct rbug_rbug *tr_rbug = CALLOC_STRUCT(rbug_rbug);
853    if (!tr_rbug)
854       return NULL;
855 
856    tr_rbug->rb_screen = rb_screen;
857    tr_rbug->running = TRUE;
858    tr_rbug->thread = pipe_thread_create(rbug_thread, tr_rbug);
859 
860    return tr_rbug;
861 }
862 
863 void
rbug_stop(struct rbug_rbug * tr_rbug)864 rbug_stop(struct rbug_rbug *tr_rbug)
865 {
866    if (!tr_rbug)
867       return;
868 
869    tr_rbug->running = false;
870    pipe_thread_wait(tr_rbug->thread);
871 
872    FREE(tr_rbug);
873 
874    return;
875 }
876 
877 void
rbug_notify_draw_blocked(struct rbug_context * rb_context)878 rbug_notify_draw_blocked(struct rbug_context *rb_context)
879 {
880    struct rbug_screen *rb_screen = rbug_screen(rb_context->base.screen);
881    struct rbug_rbug *tr_rbug = rb_screen->rbug;
882 
883    if (tr_rbug && tr_rbug->con)
884       rbug_send_context_draw_blocked(tr_rbug->con,
885                                      VOID2U64(rb_context), rb_context->draw_blocked, NULL);
886 }
887