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