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