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