Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  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.  
  53. struct rbug_rbug
  54. {
  55.    struct rbug_screen *rb_screen;
  56.    struct rbug_connection *con;
  57.    pipe_thread thread;
  58.    boolean running;
  59. };
  60.  
  61. PIPE_THREAD_ROUTINE(rbug_thread, void_rbug);
  62.  
  63.  
  64. /**********************************************************
  65.  * Helper functions
  66.  */
  67.  
  68.  
  69. static struct rbug_context *
  70. rbug_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.  
  85. static struct rbug_shader *
  86. rbug_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.  
  101. static void *
  102. rbug_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.  
  129. static void
  130. rbug_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.  
  150. static void
  151. rbug_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.  
  176. static int
  177. rbug_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.  
  199. static int
  200. rbug_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.  
  240. static int
  241. rbug_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.    map = pipe_transfer_map(context, tex,
  270.                            gptr->level, gptr->face + gptr->zslice,
  271.                            PIPE_TRANSFER_READ,
  272.                            gptr->x, gptr->y, gptr->w, gptr->h, &t);
  273.  
  274.    rbug_send_texture_read_reply(tr_rbug->con, serial,
  275.                                 t->resource->format,
  276.                                 util_format_get_blockwidth(t->resource->format),
  277.                                 util_format_get_blockheight(t->resource->format),
  278.                                 util_format_get_blocksize(t->resource->format),
  279.                                 (uint8_t*)map,
  280.                                 t->stride * util_format_get_nblocksy(t->resource->format,
  281.                                                                      t->box.height),
  282.                                 t->stride,
  283.                                 NULL);
  284.  
  285.    context->transfer_unmap(context, t);
  286.  
  287.    pipe_mutex_unlock(rb_screen->list_mutex);
  288.  
  289.    return 0;
  290. }
  291.  
  292. static int
  293. rbug_context_list(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
  294. {
  295.    struct rbug_screen *rb_screen = tr_rbug->rb_screen;
  296.    struct rbug_list *ptr;
  297.    struct rbug_context *rb_context = NULL;
  298.    rbug_context_t *ctxs;
  299.    int i = 0;
  300.  
  301.    pipe_mutex_lock(rb_screen->list_mutex);
  302.    ctxs = MALLOC(rb_screen->num_contexts * sizeof(rbug_context_t));
  303.    foreach(ptr, &rb_screen->contexts) {
  304.       rb_context = container_of(ptr, struct rbug_context, list);
  305.       ctxs[i++] = VOID2U64(rb_context);
  306.    }
  307.    pipe_mutex_unlock(rb_screen->list_mutex);
  308.  
  309.    rbug_send_context_list_reply(tr_rbug->con, serial, ctxs, i, NULL);
  310.    FREE(ctxs);
  311.  
  312.    return 0;
  313. }
  314.  
  315. static int
  316. rbug_context_info(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
  317. {
  318.    struct rbug_proto_context_info *info = (struct rbug_proto_context_info *)header;
  319.  
  320.    struct rbug_screen *rb_screen = tr_rbug->rb_screen;
  321.    struct rbug_context *rb_context = NULL;
  322.    rbug_texture_t cbufs[PIPE_MAX_COLOR_BUFS];
  323.    rbug_texture_t texs[PIPE_MAX_SAMPLERS];
  324.    unsigned i;
  325.  
  326.    pipe_mutex_lock(rb_screen->list_mutex);
  327.    rb_context = rbug_get_context_locked(rb_screen, info->context);
  328.  
  329.    if (!rb_context) {
  330.       pipe_mutex_unlock(rb_screen->list_mutex);
  331.       return -ESRCH;
  332.    }
  333.  
  334.    /* protect the pipe context */
  335.    pipe_mutex_lock(rb_context->draw_mutex);
  336.    pipe_mutex_lock(rb_context->call_mutex);
  337.  
  338.    for (i = 0; i < rb_context->curr.nr_cbufs; i++)
  339.       cbufs[i] = VOID2U64(rb_context->curr.cbufs[i]);
  340.  
  341.    /* XXX what about vertex/geometry shader texture views? */
  342.    for (i = 0; i < rb_context->curr.num_views[PIPE_SHADER_FRAGMENT]; i++)
  343.       texs[i] = VOID2U64(rb_context->curr.texs[PIPE_SHADER_FRAGMENT][i]);
  344.  
  345.    rbug_send_context_info_reply(tr_rbug->con, serial,
  346.                                 VOID2U64(rb_context->curr.shader[PIPE_SHADER_VERTEX]), VOID2U64(rb_context->curr.shader[PIPE_SHADER_FRAGMENT]),
  347.                                 texs, rb_context->curr.num_views[PIPE_SHADER_FRAGMENT],
  348.                                 cbufs, rb_context->curr.nr_cbufs,
  349.                                 VOID2U64(rb_context->curr.zsbuf),
  350.                                 rb_context->draw_blocker, rb_context->draw_blocked, NULL);
  351.  
  352.    pipe_mutex_unlock(rb_context->call_mutex);
  353.    pipe_mutex_unlock(rb_context->draw_mutex);
  354.    pipe_mutex_unlock(rb_screen->list_mutex);
  355.  
  356.    return 0;
  357. }
  358.  
  359. static int
  360. rbug_context_draw_block(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
  361. {
  362.    struct rbug_proto_context_draw_block *block = (struct rbug_proto_context_draw_block *)header;
  363.  
  364.    struct rbug_screen *rb_screen = tr_rbug->rb_screen;
  365.    struct rbug_context *rb_context = NULL;
  366.  
  367.    pipe_mutex_lock(rb_screen->list_mutex);
  368.    rb_context = rbug_get_context_locked(rb_screen, block->context);
  369.  
  370.    if (!rb_context) {
  371.       pipe_mutex_unlock(rb_screen->list_mutex);
  372.       return -ESRCH;
  373.    }
  374.  
  375.    pipe_mutex_lock(rb_context->draw_mutex);
  376.    rb_context->draw_blocker |= block->block;
  377.    pipe_mutex_unlock(rb_context->draw_mutex);
  378.  
  379.    pipe_mutex_unlock(rb_screen->list_mutex);
  380.  
  381.    return 0;
  382. }
  383.  
  384. static int
  385. rbug_context_draw_step(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
  386. {
  387.    struct rbug_proto_context_draw_step *step = (struct rbug_proto_context_draw_step *)header;
  388.  
  389.    struct rbug_screen *rb_screen = tr_rbug->rb_screen;
  390.    struct rbug_context *rb_context = NULL;
  391.  
  392.    pipe_mutex_lock(rb_screen->list_mutex);
  393.    rb_context = rbug_get_context_locked(rb_screen, step->context);
  394.  
  395.    if (!rb_context) {
  396.       pipe_mutex_unlock(rb_screen->list_mutex);
  397.       return -ESRCH;
  398.    }
  399.  
  400.    pipe_mutex_lock(rb_context->draw_mutex);
  401.    if (rb_context->draw_blocked & RBUG_BLOCK_RULE) {
  402.       if (step->step & RBUG_BLOCK_RULE)
  403.          rb_context->draw_blocked &= ~RBUG_BLOCK_MASK;
  404.    } else {
  405.       rb_context->draw_blocked &= ~step->step;
  406.    }
  407.    pipe_mutex_unlock(rb_context->draw_mutex);
  408.  
  409.    pipe_condvar_broadcast(rb_context->draw_cond);
  410.  
  411.    pipe_mutex_unlock(rb_screen->list_mutex);
  412.  
  413.    return 0;
  414. }
  415.  
  416. static int
  417. rbug_context_draw_unblock(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
  418. {
  419.    struct rbug_proto_context_draw_unblock *unblock = (struct rbug_proto_context_draw_unblock *)header;
  420.  
  421.    struct rbug_screen *rb_screen = tr_rbug->rb_screen;
  422.    struct rbug_context *rb_context = NULL;
  423.  
  424.    pipe_mutex_lock(rb_screen->list_mutex);
  425.    rb_context = rbug_get_context_locked(rb_screen, unblock->context);
  426.  
  427.    if (!rb_context) {
  428.       pipe_mutex_unlock(rb_screen->list_mutex);
  429.       return -ESRCH;
  430.    }
  431.  
  432.    pipe_mutex_lock(rb_context->draw_mutex);
  433.    if (rb_context->draw_blocked & RBUG_BLOCK_RULE) {
  434.       if (unblock->unblock & RBUG_BLOCK_RULE)
  435.          rb_context->draw_blocked &= ~RBUG_BLOCK_MASK;
  436.    } else {
  437.       rb_context->draw_blocked &= ~unblock->unblock;
  438.    }
  439.    rb_context->draw_blocker &= ~unblock->unblock;
  440.    pipe_mutex_unlock(rb_context->draw_mutex);
  441.  
  442.    pipe_condvar_broadcast(rb_context->draw_cond);
  443.  
  444.    pipe_mutex_unlock(rb_screen->list_mutex);
  445.  
  446.    return 0;
  447. }
  448.  
  449. static int
  450. rbug_context_draw_rule(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
  451. {
  452.    struct rbug_proto_context_draw_rule *rule = (struct rbug_proto_context_draw_rule *)header;
  453.  
  454.    struct rbug_screen *rb_screen = tr_rbug->rb_screen;
  455.    struct rbug_context *rb_context = NULL;
  456.  
  457.    pipe_mutex_lock(rb_screen->list_mutex);
  458.    rb_context = rbug_get_context_locked(rb_screen, rule->context);
  459.  
  460.    if (!rb_context) {
  461.       pipe_mutex_unlock(rb_screen->list_mutex);
  462.       return -ESRCH;
  463.    }
  464.  
  465.    pipe_mutex_lock(rb_context->draw_mutex);
  466.    rb_context->draw_rule.shader[PIPE_SHADER_VERTEX] = U642VOID(rule->vertex);
  467.    rb_context->draw_rule.shader[PIPE_SHADER_FRAGMENT] = U642VOID(rule->fragment);
  468.    rb_context->draw_rule.texture = U642VOID(rule->texture);
  469.    rb_context->draw_rule.surf = U642VOID(rule->surface);
  470.    rb_context->draw_rule.blocker = rule->block;
  471.    rb_context->draw_blocker |= RBUG_BLOCK_RULE;
  472.    pipe_mutex_unlock(rb_context->draw_mutex);
  473.  
  474.    pipe_condvar_broadcast(rb_context->draw_cond);
  475.  
  476.    pipe_mutex_unlock(rb_screen->list_mutex);
  477.  
  478.    return 0;
  479. }
  480.  
  481. static int
  482. rbug_context_flush(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
  483. {
  484.    struct rbug_proto_context_flush *flush = (struct rbug_proto_context_flush *)header;
  485.  
  486.    struct rbug_screen *rb_screen = tr_rbug->rb_screen;
  487.    struct rbug_context *rb_context = NULL;
  488.  
  489.    pipe_mutex_lock(rb_screen->list_mutex);
  490.    rb_context = rbug_get_context_locked(rb_screen, flush->context);
  491.  
  492.    if (!rb_context) {
  493.       pipe_mutex_unlock(rb_screen->list_mutex);
  494.       return -ESRCH;
  495.    }
  496.  
  497.    /* protect the pipe context */
  498.    pipe_mutex_lock(rb_context->call_mutex);
  499.  
  500.    rb_context->pipe->flush(rb_context->pipe, NULL, 0);
  501.  
  502.    pipe_mutex_unlock(rb_context->call_mutex);
  503.    pipe_mutex_unlock(rb_screen->list_mutex);
  504.  
  505.    return 0;
  506. }
  507.  
  508. static int
  509. rbug_shader_list(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
  510. {
  511.    struct rbug_proto_shader_list *list = (struct rbug_proto_shader_list *)header;
  512.  
  513.    struct rbug_screen *rb_screen = tr_rbug->rb_screen;
  514.    struct rbug_context *rb_context = NULL;
  515.    struct rbug_shader *tr_shdr = NULL;
  516.    struct rbug_list *ptr;
  517.    rbug_shader_t *shdrs;
  518.    int i = 0;
  519.  
  520.    pipe_mutex_lock(rb_screen->list_mutex);
  521.    rb_context = rbug_get_context_locked(rb_screen, list->context);
  522.  
  523.    if (!rb_context) {
  524.       pipe_mutex_unlock(rb_screen->list_mutex);
  525.       return -ESRCH;
  526.    }
  527.  
  528.    pipe_mutex_lock(rb_context->list_mutex);
  529.    shdrs = MALLOC(rb_context->num_shaders * sizeof(rbug_shader_t));
  530.    foreach(ptr, &rb_context->shaders) {
  531.       tr_shdr = container_of(ptr, struct rbug_shader, list);
  532.       shdrs[i++] = VOID2U64(tr_shdr);
  533.    }
  534.  
  535.    pipe_mutex_unlock(rb_context->list_mutex);
  536.    pipe_mutex_unlock(rb_screen->list_mutex);
  537.  
  538.    rbug_send_shader_list_reply(tr_rbug->con, serial, shdrs, i, NULL);
  539.    FREE(shdrs);
  540.  
  541.    return 0;
  542. }
  543.  
  544. static int
  545. rbug_shader_info(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
  546. {
  547.    struct rbug_proto_shader_info *info = (struct rbug_proto_shader_info *)header;
  548.  
  549.    struct rbug_screen *rb_screen = tr_rbug->rb_screen;
  550.    struct rbug_context *rb_context = NULL;
  551.    struct rbug_shader *tr_shdr = NULL;
  552.    unsigned original_len;
  553.    unsigned replaced_len;
  554.  
  555.    pipe_mutex_lock(rb_screen->list_mutex);
  556.    rb_context = rbug_get_context_locked(rb_screen, info->context);
  557.  
  558.    if (!rb_context) {
  559.       pipe_mutex_unlock(rb_screen->list_mutex);
  560.       return -ESRCH;
  561.    }
  562.  
  563.    pipe_mutex_lock(rb_context->list_mutex);
  564.  
  565.    tr_shdr = rbug_get_shader_locked(rb_context, info->shader);
  566.  
  567.    if (!tr_shdr) {
  568.       pipe_mutex_unlock(rb_context->list_mutex);
  569.       pipe_mutex_unlock(rb_screen->list_mutex);
  570.       return -ESRCH;
  571.    }
  572.  
  573.    /* just in case */
  574.    assert(sizeof(struct tgsi_token) == 4);
  575.  
  576.    original_len = tgsi_num_tokens(tr_shdr->tokens);
  577.    if (tr_shdr->replaced_tokens)
  578.       replaced_len = tgsi_num_tokens(tr_shdr->replaced_tokens);
  579.    else
  580.       replaced_len = 0;
  581.  
  582.    rbug_send_shader_info_reply(tr_rbug->con, serial,
  583.                                (uint32_t*)tr_shdr->tokens, original_len,
  584.                                (uint32_t*)tr_shdr->replaced_tokens, replaced_len,
  585.                                tr_shdr->disabled,
  586.                                NULL);
  587.  
  588.    pipe_mutex_unlock(rb_context->list_mutex);
  589.    pipe_mutex_unlock(rb_screen->list_mutex);
  590.  
  591.    return 0;
  592. }
  593.  
  594. static int
  595. rbug_shader_disable(struct rbug_rbug *tr_rbug, struct rbug_header *header)
  596. {
  597.    struct rbug_proto_shader_disable *dis = (struct rbug_proto_shader_disable *)header;
  598.  
  599.    struct rbug_screen *rb_screen = tr_rbug->rb_screen;
  600.    struct rbug_context *rb_context = NULL;
  601.    struct rbug_shader *tr_shdr = NULL;
  602.  
  603.    pipe_mutex_lock(rb_screen->list_mutex);
  604.    rb_context = rbug_get_context_locked(rb_screen, dis->context);
  605.  
  606.    if (!rb_context) {
  607.       pipe_mutex_unlock(rb_screen->list_mutex);
  608.       return -ESRCH;
  609.    }
  610.  
  611.    pipe_mutex_lock(rb_context->list_mutex);
  612.  
  613.    tr_shdr = rbug_get_shader_locked(rb_context, dis->shader);
  614.  
  615.    if (!tr_shdr) {
  616.       pipe_mutex_unlock(rb_context->list_mutex);
  617.       pipe_mutex_unlock(rb_screen->list_mutex);
  618.       return -ESRCH;
  619.    }
  620.  
  621.    tr_shdr->disabled = dis->disable;
  622.  
  623.    pipe_mutex_unlock(rb_context->list_mutex);
  624.    pipe_mutex_unlock(rb_screen->list_mutex);
  625.  
  626.    return 0;
  627. }
  628.  
  629. static int
  630. rbug_shader_replace(struct rbug_rbug *tr_rbug, struct rbug_header *header)
  631. {
  632.    struct rbug_proto_shader_replace *rep = (struct rbug_proto_shader_replace *)header;
  633.  
  634.    struct rbug_screen *rb_screen = tr_rbug->rb_screen;
  635.    struct rbug_context *rb_context = NULL;
  636.    struct rbug_shader *tr_shdr = NULL;
  637.    struct pipe_context *pipe = NULL;
  638.    void *state;
  639.  
  640.    pipe_mutex_lock(rb_screen->list_mutex);
  641.    rb_context = rbug_get_context_locked(rb_screen, rep->context);
  642.  
  643.    if (!rb_context) {
  644.       pipe_mutex_unlock(rb_screen->list_mutex);
  645.       return -ESRCH;
  646.    }
  647.  
  648.    pipe_mutex_lock(rb_context->list_mutex);
  649.  
  650.    tr_shdr = rbug_get_shader_locked(rb_context, rep->shader);
  651.  
  652.    if (!tr_shdr) {
  653.       pipe_mutex_unlock(rb_context->list_mutex);
  654.       pipe_mutex_unlock(rb_screen->list_mutex);
  655.       return -ESRCH;
  656.    }
  657.  
  658.    /* protect the pipe context */
  659.    pipe_mutex_lock(rb_context->call_mutex);
  660.  
  661.    pipe = rb_context->pipe;
  662.  
  663.    /* remove old replaced shader */
  664.    if (tr_shdr->replaced_shader) {
  665.       /* if this shader is bound rebind the original shader */
  666.       if (rb_context->curr.shader[PIPE_SHADER_FRAGMENT] == tr_shdr || rb_context->curr.shader[PIPE_SHADER_VERTEX] == tr_shdr)
  667.          rbug_shader_bind_locked(pipe, tr_shdr, tr_shdr->shader);
  668.  
  669.       FREE(tr_shdr->replaced_tokens);
  670.       rbug_shader_delete_locked(pipe, tr_shdr, tr_shdr->replaced_shader);
  671.       tr_shdr->replaced_shader = NULL;
  672.       tr_shdr->replaced_tokens = NULL;
  673.    }
  674.  
  675.    /* empty inputs means restore old which we did above */
  676.    if (rep->tokens_len == 0)
  677.       goto out;
  678.  
  679.    tr_shdr->replaced_tokens = tgsi_dup_tokens((struct tgsi_token *)rep->tokens);
  680.    if (!tr_shdr->replaced_tokens)
  681.       goto err;
  682.  
  683.    state = rbug_shader_create_locked(pipe, tr_shdr, tr_shdr->replaced_tokens);
  684.    if (!state)
  685.       goto err;
  686.  
  687.    /* bind new shader if the shader is currently a bound */
  688.    if (rb_context->curr.shader[PIPE_SHADER_FRAGMENT] == tr_shdr || rb_context->curr.shader[PIPE_SHADER_VERTEX] == tr_shdr)
  689.       rbug_shader_bind_locked(pipe, tr_shdr, state);
  690.  
  691.    /* save state */
  692.    tr_shdr->replaced_shader = state;
  693.  
  694. out:
  695.    pipe_mutex_unlock(rb_context->call_mutex);
  696.    pipe_mutex_unlock(rb_context->list_mutex);
  697.    pipe_mutex_unlock(rb_screen->list_mutex);
  698.  
  699.    return 0;
  700.  
  701. err:
  702.    FREE(tr_shdr->replaced_tokens);
  703.    tr_shdr->replaced_shader = NULL;
  704.    tr_shdr->replaced_tokens = NULL;
  705.  
  706.    pipe_mutex_unlock(rb_context->call_mutex);
  707.    pipe_mutex_unlock(rb_context->list_mutex);
  708.    pipe_mutex_unlock(rb_screen->list_mutex);
  709.    return -EINVAL;
  710. }
  711.  
  712. static boolean
  713. rbug_header(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
  714. {
  715.    int ret = 0;
  716.  
  717.    switch(header->opcode) {
  718.       case RBUG_OP_PING:
  719.          rbug_send_ping_reply(tr_rbug->con, serial, NULL);
  720.          break;
  721.       case RBUG_OP_TEXTURE_LIST:
  722.          ret = rbug_texture_list(tr_rbug, header, serial);
  723.          break;
  724.       case RBUG_OP_TEXTURE_INFO:
  725.          ret = rbug_texture_info(tr_rbug, header, serial);
  726.          break;
  727.       case RBUG_OP_TEXTURE_READ:
  728.          ret = rbug_texture_read(tr_rbug, header, serial);
  729.          break;
  730.       case RBUG_OP_CONTEXT_LIST:
  731.          ret = rbug_context_list(tr_rbug, header, serial);
  732.          break;
  733.       case RBUG_OP_CONTEXT_INFO:
  734.          ret = rbug_context_info(tr_rbug, header, serial);
  735.          break;
  736.       case RBUG_OP_CONTEXT_DRAW_BLOCK:
  737.          ret = rbug_context_draw_block(tr_rbug, header, serial);
  738.          break;
  739.       case RBUG_OP_CONTEXT_DRAW_STEP:
  740.          ret = rbug_context_draw_step(tr_rbug, header, serial);
  741.          break;
  742.       case RBUG_OP_CONTEXT_DRAW_UNBLOCK:
  743.          ret = rbug_context_draw_unblock(tr_rbug, header, serial);
  744.          break;
  745.       case RBUG_OP_CONTEXT_DRAW_RULE:
  746.          ret = rbug_context_draw_rule(tr_rbug, header, serial);
  747.          break;
  748.       case RBUG_OP_CONTEXT_FLUSH:
  749.          ret = rbug_context_flush(tr_rbug, header, serial);
  750.          break;
  751.       case RBUG_OP_SHADER_LIST:
  752.          ret = rbug_shader_list(tr_rbug, header, serial);
  753.          break;
  754.       case RBUG_OP_SHADER_INFO:
  755.          ret = rbug_shader_info(tr_rbug, header, serial);
  756.          break;
  757.       case RBUG_OP_SHADER_DISABLE:
  758.          ret = rbug_shader_disable(tr_rbug, header);
  759.          break;
  760.       case RBUG_OP_SHADER_REPLACE:
  761.          ret = rbug_shader_replace(tr_rbug, header);
  762.          break;
  763.       default:
  764.          debug_printf("%s - unsupported opcode %u\n", __FUNCTION__, header->opcode);
  765.          ret = -ENOSYS;
  766.          break;
  767.    }
  768.    rbug_free_header(header);
  769.  
  770.    if (ret)
  771.       rbug_send_error_reply(tr_rbug->con, serial, ret, NULL);
  772.  
  773.    return TRUE;
  774. }
  775.  
  776. static void
  777. rbug_con(struct rbug_rbug *tr_rbug)
  778. {
  779.    struct rbug_header *header;
  780.    uint32_t serial;
  781.  
  782.    debug_printf("%s - connection received\n", __FUNCTION__);
  783.  
  784.    while(tr_rbug->running) {
  785.       header = rbug_get_message(tr_rbug->con, &serial);
  786.       if (!header)
  787.          break;
  788.  
  789.       if (!rbug_header(tr_rbug, header, serial))
  790.          break;
  791.    }
  792.  
  793.    debug_printf("%s - connection closed\n", __FUNCTION__);
  794.  
  795.    rbug_disconnect(tr_rbug->con);
  796.    tr_rbug->con = NULL;
  797. }
  798.  
  799. PIPE_THREAD_ROUTINE(rbug_thread, void_tr_rbug)
  800. {
  801.    struct rbug_rbug *tr_rbug = void_tr_rbug;
  802.    uint16_t port = 13370;
  803.    int s = -1;
  804.    int c;
  805.  
  806.    u_socket_init();
  807.  
  808.    for (;port <= 13379 && s < 0; port++)
  809.       s = u_socket_listen_on_port(port);
  810.  
  811.    if (s < 0) {
  812.       debug_printf("rbug_rbug - failed to listen\n");
  813.       return NULL;
  814.    }
  815.  
  816.    u_socket_block(s, false);
  817.  
  818.    debug_printf("rbug_rbug - remote debugging listening on port %u\n", --port);
  819.  
  820.    while(tr_rbug->running) {
  821.       os_time_sleep(1);
  822.  
  823.       c = u_socket_accept(s);
  824.       if (c < 0)
  825.          continue;
  826.  
  827.       u_socket_block(c, true);
  828.       tr_rbug->con = rbug_from_socket(c);
  829.  
  830.       rbug_con(tr_rbug);
  831.  
  832.       u_socket_close(c);
  833.    }
  834.  
  835.    u_socket_close(s);
  836.  
  837.    u_socket_stop();
  838.  
  839.    return NULL;
  840. }
  841.  
  842. /**********************************************************
  843.  *
  844.  */
  845.  
  846. struct rbug_rbug *
  847. rbug_start(struct rbug_screen *rb_screen)
  848. {
  849.    struct rbug_rbug *tr_rbug = CALLOC_STRUCT(rbug_rbug);
  850.    if (!tr_rbug)
  851.       return NULL;
  852.  
  853.    tr_rbug->rb_screen = rb_screen;
  854.    tr_rbug->running = TRUE;
  855.    tr_rbug->thread = pipe_thread_create(rbug_thread, tr_rbug);
  856.  
  857.    return tr_rbug;
  858. }
  859.  
  860. void
  861. rbug_stop(struct rbug_rbug *tr_rbug)
  862. {
  863.    if (!tr_rbug)
  864.       return;
  865.  
  866.    tr_rbug->running = false;
  867.    pipe_thread_wait(tr_rbug->thread);
  868.  
  869.    FREE(tr_rbug);
  870.  
  871.    return;
  872. }
  873.  
  874. void
  875. rbug_notify_draw_blocked(struct rbug_context *rb_context)
  876. {
  877.    struct rbug_screen *rb_screen = rbug_screen(rb_context->base.screen);
  878.    struct rbug_rbug *tr_rbug = rb_screen->rbug;
  879.  
  880.    if (tr_rbug && tr_rbug->con)
  881.       rbug_send_context_draw_blocked(tr_rbug->con,
  882.                                      VOID2U64(rb_context), rb_context->draw_blocked, NULL);
  883. }
  884.