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