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