959e168767a69c3fe1656a60e308e3aeaff3f477
[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 *rb_shader,
101 struct tgsi_token *tokens)
102 {
103 void *state = NULL;
104 struct pipe_shader_state pss = { 0 };
105 pss.tokens = tokens;
106
107 switch(rb_shader->type) {
108 case RBUG_SHADER_FRAGMENT:
109 state = pipe->create_fs_state(pipe, &pss);
110 break;
111 case RBUG_SHADER_VERTEX:
112 state = pipe->create_vs_state(pipe, &pss);
113 break;
114 case RBUG_SHADER_GEOM:
115 state = pipe->create_gs_state(pipe, &pss);
116 break;
117 default:
118 assert(0);
119 break;
120 }
121
122 return state;
123 }
124
125 static void
126 rbug_shader_bind_locked(struct pipe_context *pipe,
127 struct rbug_shader *rb_shader,
128 void *state)
129 {
130 switch(rb_shader->type) {
131 case RBUG_SHADER_FRAGMENT:
132 pipe->bind_fs_state(pipe, state);
133 break;
134 case RBUG_SHADER_VERTEX:
135 pipe->bind_vs_state(pipe, state);
136 break;
137 case RBUG_SHADER_GEOM:
138 pipe->bind_gs_state(pipe, state);
139 break;
140 default:
141 assert(0);
142 break;
143 }
144 }
145
146 static void
147 rbug_shader_delete_locked(struct pipe_context *pipe,
148 struct rbug_shader *rb_shader,
149 void *state)
150 {
151 switch(rb_shader->type) {
152 case RBUG_SHADER_FRAGMENT:
153 pipe->delete_fs_state(pipe, state);
154 break;
155 case RBUG_SHADER_VERTEX:
156 pipe->delete_vs_state(pipe, state);
157 break;
158 case RBUG_SHADER_GEOM:
159 pipe->delete_gs_state(pipe, state);
160 break;
161 default:
162 assert(0);
163 break;
164 }
165 }
166
167 /************************************************
168 * Request handler functions
169 */
170
171
172 static int
173 rbug_texture_list(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
174 {
175 struct rbug_screen *rb_screen = tr_rbug->rb_screen;
176 struct rbug_resource *tr_tex = NULL;
177 struct rbug_list *ptr;
178 rbug_texture_t *texs;
179 int i = 0;
180
181 pipe_mutex_lock(rb_screen->list_mutex);
182 texs = MALLOC(rb_screen->num_resources * sizeof(rbug_texture_t));
183 foreach(ptr, &rb_screen->resources) {
184 tr_tex = (struct rbug_resource *)((char*)ptr - offsetof(struct rbug_resource, list));
185 texs[i++] = VOID2U64(tr_tex);
186 }
187 pipe_mutex_unlock(rb_screen->list_mutex);
188
189 rbug_send_texture_list_reply(tr_rbug->con, serial, texs, i, NULL);
190 FREE(texs);
191
192 return 0;
193 }
194
195 static int
196 rbug_texture_info(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
197 {
198 struct rbug_screen *rb_screen = tr_rbug->rb_screen;
199 struct rbug_resource *tr_tex = NULL;
200 struct rbug_proto_texture_info *gpti = (struct rbug_proto_texture_info *)header;
201 struct rbug_list *ptr;
202 struct pipe_resource *t;
203
204 pipe_mutex_lock(rb_screen->list_mutex);
205 foreach(ptr, &rb_screen->resources) {
206 tr_tex = (struct rbug_resource *)((char*)ptr - offsetof(struct rbug_resource, list));
207 if (gpti->texture == VOID2U64(tr_tex))
208 break;
209 tr_tex = NULL;
210 }
211
212 if (!tr_tex) {
213 pipe_mutex_unlock(rb_screen->list_mutex);
214 return -ESRCH;
215 }
216
217 t = tr_tex->resource;
218 rbug_send_texture_info_reply(tr_rbug->con, serial,
219 t->target, t->format,
220 &t->width0, 1,
221 &t->height0, 1,
222 &t->depth0, 1,
223 util_format_get_blockwidth(t->format),
224 util_format_get_blockheight(t->format),
225 util_format_get_blocksize(t->format),
226 t->last_level,
227 t->nr_samples,
228 t->bind,
229 NULL);
230
231 pipe_mutex_unlock(rb_screen->list_mutex);
232
233 return 0;
234 }
235
236 static int
237 rbug_texture_read(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
238 {
239 struct rbug_proto_texture_read *gptr = (struct rbug_proto_texture_read *)header;
240
241 struct rbug_screen *rb_screen = tr_rbug->rb_screen;
242 struct rbug_resource *tr_tex = NULL;
243 struct rbug_list *ptr;
244
245 struct pipe_context *context = rb_screen->private_context;
246 struct pipe_resource *tex;
247 struct pipe_transfer *t;
248
249 void *map;
250
251 pipe_mutex_lock(rb_screen->list_mutex);
252 foreach(ptr, &rb_screen->resources) {
253 tr_tex = (struct rbug_resource *)((char*)ptr - offsetof(struct rbug_resource, list));
254 if (gptr->texture == VOID2U64(tr_tex))
255 break;
256 tr_tex = NULL;
257 }
258
259 if (!tr_tex) {
260 pipe_mutex_unlock(rb_screen->list_mutex);
261 return -ESRCH;
262 }
263
264 tex = tr_tex->resource;
265 t = pipe_get_transfer(context, tex,
266 gptr->face, gptr->level, gptr->zslice,
267 PIPE_TRANSFER_READ,
268 gptr->x, gptr->y, gptr->w, gptr->h);
269
270 map = context->transfer_map(context, t);
271
272 rbug_send_texture_read_reply(tr_rbug->con, serial,
273 t->resource->format,
274 util_format_get_blockwidth(t->resource->format),
275 util_format_get_blockheight(t->resource->format),
276 util_format_get_blocksize(t->resource->format),
277 (uint8_t*)map,
278 t->stride * util_format_get_nblocksy(t->resource->format,
279 t->box.height),
280 t->stride,
281 NULL);
282
283 context->transfer_unmap(context, t);
284 context->transfer_destroy(context, t);
285
286 pipe_mutex_unlock(rb_screen->list_mutex);
287
288 return 0;
289 }
290
291 static int
292 rbug_context_list(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
293 {
294 struct rbug_screen *rb_screen = tr_rbug->rb_screen;
295 struct rbug_list *ptr;
296 struct rbug_context *rb_context = NULL;
297 rbug_context_t *ctxs;
298 int i = 0;
299
300 pipe_mutex_lock(rb_screen->list_mutex);
301 ctxs = MALLOC(rb_screen->num_contexts * sizeof(rbug_context_t));
302 foreach(ptr, &rb_screen->contexts) {
303 rb_context = (struct rbug_context *)((char*)ptr - offsetof(struct rbug_context, list));
304 ctxs[i++] = VOID2U64(rb_context);
305 }
306 pipe_mutex_unlock(rb_screen->list_mutex);
307
308 rbug_send_context_list_reply(tr_rbug->con, serial, ctxs, i, NULL);
309 FREE(ctxs);
310
311 return 0;
312 }
313
314 static int
315 rbug_context_info(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
316 {
317 struct rbug_proto_context_info *info = (struct rbug_proto_context_info *)header;
318
319 struct rbug_screen *rb_screen = tr_rbug->rb_screen;
320 struct rbug_context *rb_context = NULL;
321 rbug_texture_t cbufs[PIPE_MAX_COLOR_BUFS];
322 rbug_texture_t texs[PIPE_MAX_SAMPLERS];
323 int i;
324
325 pipe_mutex_lock(rb_screen->list_mutex);
326 rb_context = rbug_get_context_locked(rb_screen, info->context);
327
328 if (!rb_context) {
329 pipe_mutex_unlock(rb_screen->list_mutex);
330 return -ESRCH;
331 }
332
333 /* protect the pipe context */
334 pipe_mutex_lock(rb_context->draw_mutex);
335 pipe_mutex_lock(rb_context->call_mutex);
336
337 for (i = 0; i < rb_context->curr.nr_cbufs; i++)
338 cbufs[i] = VOID2U64(rb_context->curr.cbufs[i]);
339
340 for (i = 0; i < rb_context->curr.num_fs_views; i++)
341 texs[i] = VOID2U64(rb_context->curr.fs_texs[i]);
342
343 rbug_send_context_info_reply(tr_rbug->con, serial,
344 VOID2U64(rb_context->curr.vs), VOID2U64(rb_context->curr.fs),
345 texs, rb_context->curr.num_fs_views,
346 cbufs, rb_context->curr.nr_cbufs,
347 VOID2U64(rb_context->curr.zsbuf),
348 rb_context->draw_blocker, rb_context->draw_blocked, NULL);
349
350 pipe_mutex_unlock(rb_context->call_mutex);
351 pipe_mutex_unlock(rb_context->draw_mutex);
352 pipe_mutex_unlock(rb_screen->list_mutex);
353
354 return 0;
355 }
356
357 static int
358 rbug_context_draw_block(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
359 {
360 struct rbug_proto_context_draw_block *block = (struct rbug_proto_context_draw_block *)header;
361
362 struct rbug_screen *rb_screen = tr_rbug->rb_screen;
363 struct rbug_context *rb_context = NULL;
364
365 pipe_mutex_lock(rb_screen->list_mutex);
366 rb_context = rbug_get_context_locked(rb_screen, block->context);
367
368 if (!rb_context) {
369 pipe_mutex_unlock(rb_screen->list_mutex);
370 return -ESRCH;
371 }
372
373 pipe_mutex_lock(rb_context->draw_mutex);
374 rb_context->draw_blocker |= block->block;
375 pipe_mutex_unlock(rb_context->draw_mutex);
376
377 pipe_mutex_unlock(rb_screen->list_mutex);
378
379 return 0;
380 }
381
382 static int
383 rbug_context_draw_step(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
384 {
385 struct rbug_proto_context_draw_step *step = (struct rbug_proto_context_draw_step *)header;
386
387 struct rbug_screen *rb_screen = tr_rbug->rb_screen;
388 struct rbug_context *rb_context = NULL;
389
390 pipe_mutex_lock(rb_screen->list_mutex);
391 rb_context = rbug_get_context_locked(rb_screen, step->context);
392
393 if (!rb_context) {
394 pipe_mutex_unlock(rb_screen->list_mutex);
395 return -ESRCH;
396 }
397
398 pipe_mutex_lock(rb_context->draw_mutex);
399 if (rb_context->draw_blocked & RBUG_BLOCK_RULE) {
400 if (step->step & RBUG_BLOCK_RULE)
401 rb_context->draw_blocked &= ~RBUG_BLOCK_MASK;
402 } else {
403 rb_context->draw_blocked &= ~step->step;
404 }
405 pipe_mutex_unlock(rb_context->draw_mutex);
406
407 #ifdef PIPE_THREAD_HAVE_CONDVAR
408 pipe_condvar_broadcast(rb_context->draw_cond);
409 #endif
410
411 pipe_mutex_unlock(rb_screen->list_mutex);
412
413 return 0;
414 }
415
416 static int
417 rbug_context_draw_unblock(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
418 {
419 struct rbug_proto_context_draw_unblock *unblock = (struct rbug_proto_context_draw_unblock *)header;
420
421 struct rbug_screen *rb_screen = tr_rbug->rb_screen;
422 struct rbug_context *rb_context = NULL;
423
424 pipe_mutex_lock(rb_screen->list_mutex);
425 rb_context = rbug_get_context_locked(rb_screen, unblock->context);
426
427 if (!rb_context) {
428 pipe_mutex_unlock(rb_screen->list_mutex);
429 return -ESRCH;
430 }
431
432 pipe_mutex_lock(rb_context->draw_mutex);
433 if (rb_context->draw_blocked & RBUG_BLOCK_RULE) {
434 if (unblock->unblock & RBUG_BLOCK_RULE)
435 rb_context->draw_blocked &= ~RBUG_BLOCK_MASK;
436 } else {
437 rb_context->draw_blocked &= ~unblock->unblock;
438 }
439 rb_context->draw_blocker &= ~unblock->unblock;
440 pipe_mutex_unlock(rb_context->draw_mutex);
441
442 #ifdef PIPE_THREAD_HAVE_CONDVAR
443 pipe_condvar_broadcast(rb_context->draw_cond);
444 #endif
445
446 pipe_mutex_unlock(rb_screen->list_mutex);
447
448 return 0;
449 }
450
451 static int
452 rbug_context_draw_rule(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
453 {
454 struct rbug_proto_context_draw_rule *rule = (struct rbug_proto_context_draw_rule *)header;
455
456 struct rbug_screen *rb_screen = tr_rbug->rb_screen;
457 struct rbug_context *rb_context = NULL;
458
459 pipe_mutex_lock(rb_screen->list_mutex);
460 rb_context = rbug_get_context_locked(rb_screen, rule->context);
461
462 if (!rb_context) {
463 pipe_mutex_unlock(rb_screen->list_mutex);
464 return -ESRCH;
465 }
466
467 pipe_mutex_lock(rb_context->draw_mutex);
468 rb_context->draw_rule.vs = U642VOID(rule->vertex);
469 rb_context->draw_rule.fs = U642VOID(rule->fragment);
470 rb_context->draw_rule.texture = U642VOID(rule->texture);
471 rb_context->draw_rule.surf = U642VOID(rule->surface);
472 rb_context->draw_rule.blocker = rule->block;
473 rb_context->draw_blocker |= RBUG_BLOCK_RULE;
474 pipe_mutex_unlock(rb_context->draw_mutex);
475
476 #ifdef PIPE_THREAD_HAVE_CONDVAR
477 pipe_condvar_broadcast(rb_context->draw_cond);
478 #endif
479
480 pipe_mutex_unlock(rb_screen->list_mutex);
481
482 return 0;
483 }
484
485 static int
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 pipe_mutex_lock(rb_screen->list_mutex);
494 rb_context = rbug_get_context_locked(rb_screen, flush->context);
495
496 if (!rb_context) {
497 pipe_mutex_unlock(rb_screen->list_mutex);
498 return -ESRCH;
499 }
500
501 /* protect the pipe context */
502 pipe_mutex_lock(rb_context->call_mutex);
503
504 rb_context->pipe->flush(rb_context->pipe, flush->flags, NULL);
505
506 pipe_mutex_unlock(rb_context->call_mutex);
507 pipe_mutex_unlock(rb_screen->list_mutex);
508
509 return 0;
510 }
511
512 static int
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 pipe_mutex_lock(rb_screen->list_mutex);
525 rb_context = rbug_get_context_locked(rb_screen, list->context);
526
527 if (!rb_context) {
528 pipe_mutex_unlock(rb_screen->list_mutex);
529 return -ESRCH;
530 }
531
532 pipe_mutex_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 = (struct rbug_shader *)((char*)ptr - offsetof(struct rbug_shader, list));
536 shdrs[i++] = VOID2U64(tr_shdr);
537 }
538
539 pipe_mutex_unlock(rb_context->list_mutex);
540 pipe_mutex_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
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 pipe_mutex_lock(rb_screen->list_mutex);
560 rb_context = rbug_get_context_locked(rb_screen, info->context);
561
562 if (!rb_context) {
563 pipe_mutex_unlock(rb_screen->list_mutex);
564 return -ESRCH;
565 }
566
567 pipe_mutex_lock(rb_context->list_mutex);
568
569 tr_shdr = rbug_get_shader_locked(rb_context, info->shader);
570
571 if (!tr_shdr) {
572 pipe_mutex_unlock(rb_context->list_mutex);
573 pipe_mutex_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 pipe_mutex_unlock(rb_context->list_mutex);
593 pipe_mutex_unlock(rb_screen->list_mutex);
594
595 return 0;
596 }
597
598 static int
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 pipe_mutex_lock(rb_screen->list_mutex);
608 rb_context = rbug_get_context_locked(rb_screen, dis->context);
609
610 if (!rb_context) {
611 pipe_mutex_unlock(rb_screen->list_mutex);
612 return -ESRCH;
613 }
614
615 pipe_mutex_lock(rb_context->list_mutex);
616
617 tr_shdr = rbug_get_shader_locked(rb_context, dis->shader);
618
619 if (!tr_shdr) {
620 pipe_mutex_unlock(rb_context->list_mutex);
621 pipe_mutex_unlock(rb_screen->list_mutex);
622 return -ESRCH;
623 }
624
625 tr_shdr->disabled = dis->disable;
626
627 pipe_mutex_unlock(rb_context->list_mutex);
628 pipe_mutex_unlock(rb_screen->list_mutex);
629
630 return 0;
631 }
632
633 static int
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 pipe_mutex_lock(rb_screen->list_mutex);
645 rb_context = rbug_get_context_locked(rb_screen, rep->context);
646
647 if (!rb_context) {
648 pipe_mutex_unlock(rb_screen->list_mutex);
649 return -ESRCH;
650 }
651
652 pipe_mutex_lock(rb_context->list_mutex);
653
654 tr_shdr = rbug_get_shader_locked(rb_context, rep->shader);
655
656 if (!tr_shdr) {
657 pipe_mutex_unlock(rb_context->list_mutex);
658 pipe_mutex_unlock(rb_screen->list_mutex);
659 return -ESRCH;
660 }
661
662 /* protect the pipe context */
663 pipe_mutex_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.fs == tr_shdr || rb_context->curr.vs == 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.fs == tr_shdr || rb_context->curr.vs == 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 pipe_mutex_unlock(rb_context->call_mutex);
700 pipe_mutex_unlock(rb_context->list_mutex);
701 pipe_mutex_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 pipe_mutex_unlock(rb_context->call_mutex);
711 pipe_mutex_unlock(rb_context->list_mutex);
712 pipe_mutex_unlock(rb_screen->list_mutex);
713 return -EINVAL;
714 }
715
716 static boolean
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
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 PIPE_THREAD_ROUTINE(rbug_thread, 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 NULL;
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 NULL;
844 }
845
846 /**********************************************************
847 *
848 */
849
850 struct rbug_rbug *
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 = pipe_thread_create(rbug_thread, tr_rbug);
860
861 return tr_rbug;
862 }
863
864 void
865 rbug_stop(struct rbug_rbug *tr_rbug)
866 {
867 if (!tr_rbug)
868 return;
869
870 tr_rbug->running = false;
871 pipe_thread_wait(tr_rbug->thread);
872
873 FREE(tr_rbug);
874
875 return;
876 }
877
878 void
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 }