Home | History | Annotate | Download | only in rbug
      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/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    unsigned num_layers;
    208 
    209    pipe_mutex_lock(rb_screen->list_mutex);
    210    foreach(ptr, &rb_screen->resources) {
    211       tr_tex = container_of(ptr, struct rbug_resource, list);
    212       if (gpti->texture == VOID2U64(tr_tex))
    213          break;
    214       tr_tex = NULL;
    215    }
    216 
    217    if (!tr_tex) {
    218       pipe_mutex_unlock(rb_screen->list_mutex);
    219       return -ESRCH;
    220    }
    221 
    222    t = tr_tex->resource;
    223    num_layers = util_max_layer(t, 0) + 1;
    224 
    225    rbug_send_texture_info_reply(tr_rbug->con, serial,
    226                                t->target, t->format,
    227                                &t->width0, 1,
    228                                &t->height0, 1,
    229                                &num_layers, 1,
    230                                util_format_get_blockwidth(t->format),
    231                                util_format_get_blockheight(t->format),
    232                                util_format_get_blocksize(t->format),
    233                                t->last_level,
    234                                t->nr_samples,
    235                                t->bind,
    236                                NULL);
    237 
    238    pipe_mutex_unlock(rb_screen->list_mutex);
    239 
    240    return 0;
    241 }
    242 
    243 static int
    244 rbug_texture_read(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
    245 {
    246    struct rbug_proto_texture_read *gptr = (struct rbug_proto_texture_read *)header;
    247 
    248    struct rbug_screen *rb_screen = tr_rbug->rb_screen;
    249    struct rbug_resource *tr_tex = NULL;
    250    struct rbug_list *ptr;
    251 
    252    struct pipe_context *context = rb_screen->private_context;
    253    struct pipe_resource *tex;
    254    struct pipe_transfer *t;
    255 
    256    void *map;
    257 
    258    pipe_mutex_lock(rb_screen->list_mutex);
    259    foreach(ptr, &rb_screen->resources) {
    260       tr_tex = container_of(ptr, struct rbug_resource, list);
    261       if (gptr->texture == VOID2U64(tr_tex))
    262          break;
    263       tr_tex = NULL;
    264    }
    265 
    266    if (!tr_tex) {
    267       pipe_mutex_unlock(rb_screen->list_mutex);
    268       return -ESRCH;
    269    }
    270 
    271    tex = tr_tex->resource;
    272    map = pipe_transfer_map(context, tex,
    273                            gptr->level, gptr->face + gptr->zslice,
    274                            PIPE_TRANSFER_READ,
    275                            gptr->x, gptr->y, gptr->w, gptr->h, &t);
    276 
    277    rbug_send_texture_read_reply(tr_rbug->con, serial,
    278                                 t->resource->format,
    279                                 util_format_get_blockwidth(t->resource->format),
    280                                 util_format_get_blockheight(t->resource->format),
    281                                 util_format_get_blocksize(t->resource->format),
    282                                 (uint8_t*)map,
    283                                 t->stride * util_format_get_nblocksy(t->resource->format,
    284                                                                      t->box.height),
    285                                 t->stride,
    286                                 NULL);
    287 
    288    context->transfer_unmap(context, t);
    289 
    290    pipe_mutex_unlock(rb_screen->list_mutex);
    291 
    292    return 0;
    293 }
    294 
    295 static int
    296 rbug_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 
    318 static int
    319 rbug_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_SHADER_SAMPLER_VIEWS];
    327    unsigned 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 
    362 static int
    363 rbug_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 
    387 static int
    388 rbug_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 
    419 static int
    420 rbug_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 
    452 static int
    453 rbug_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 
    484 static int
    485 rbug_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, 0);
    504 
    505    pipe_mutex_unlock(rb_context->call_mutex);
    506    pipe_mutex_unlock(rb_screen->list_mutex);
    507 
    508    return 0;
    509 }
    510 
    511 static int
    512 rbug_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 
    547 static int
    548 rbug_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 
    597 static int
    598 rbug_shader_disable(struct rbug_rbug *tr_rbug, struct rbug_header *header)
    599 {
    600    struct rbug_proto_shader_disable *dis = (struct rbug_proto_shader_disable *)header;
    601 
    602    struct rbug_screen *rb_screen = tr_rbug->rb_screen;
    603    struct rbug_context *rb_context = NULL;
    604    struct rbug_shader *tr_shdr = NULL;
    605 
    606    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 
    632 static int
    633 rbug_shader_replace(struct rbug_rbug *tr_rbug, struct rbug_header *header)
    634 {
    635    struct rbug_proto_shader_replace *rep = (struct rbug_proto_shader_replace *)header;
    636 
    637    struct rbug_screen *rb_screen = tr_rbug->rb_screen;
    638    struct rbug_context *rb_context = NULL;
    639    struct rbug_shader *tr_shdr = NULL;
    640    struct pipe_context *pipe = NULL;
    641    void *state;
    642 
    643    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 
    697 out:
    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 
    704 err:
    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 
    715 static boolean
    716 rbug_header(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
    717 {
    718    int ret = 0;
    719 
    720    switch(header->opcode) {
    721       case RBUG_OP_PING:
    722          rbug_send_ping_reply(tr_rbug->con, serial, NULL);
    723          break;
    724       case RBUG_OP_TEXTURE_LIST:
    725          ret = rbug_texture_list(tr_rbug, header, serial);
    726          break;
    727       case RBUG_OP_TEXTURE_INFO:
    728          ret = rbug_texture_info(tr_rbug, header, serial);
    729          break;
    730       case RBUG_OP_TEXTURE_READ:
    731          ret = rbug_texture_read(tr_rbug, header, serial);
    732          break;
    733       case RBUG_OP_CONTEXT_LIST:
    734          ret = rbug_context_list(tr_rbug, header, serial);
    735          break;
    736       case RBUG_OP_CONTEXT_INFO:
    737          ret = rbug_context_info(tr_rbug, header, serial);
    738          break;
    739       case RBUG_OP_CONTEXT_DRAW_BLOCK:
    740          ret = rbug_context_draw_block(tr_rbug, header, serial);
    741          break;
    742       case RBUG_OP_CONTEXT_DRAW_STEP:
    743          ret = rbug_context_draw_step(tr_rbug, header, serial);
    744          break;
    745       case RBUG_OP_CONTEXT_DRAW_UNBLOCK:
    746          ret = rbug_context_draw_unblock(tr_rbug, header, serial);
    747          break;
    748       case RBUG_OP_CONTEXT_DRAW_RULE:
    749          ret = rbug_context_draw_rule(tr_rbug, header, serial);
    750          break;
    751       case RBUG_OP_CONTEXT_FLUSH:
    752          ret = rbug_context_flush(tr_rbug, header, serial);
    753          break;
    754       case RBUG_OP_SHADER_LIST:
    755          ret = rbug_shader_list(tr_rbug, header, serial);
    756          break;
    757       case RBUG_OP_SHADER_INFO:
    758          ret = rbug_shader_info(tr_rbug, header, serial);
    759          break;
    760       case RBUG_OP_SHADER_DISABLE:
    761          ret = rbug_shader_disable(tr_rbug, header);
    762          break;
    763       case RBUG_OP_SHADER_REPLACE:
    764          ret = rbug_shader_replace(tr_rbug, header);
    765          break;
    766       default:
    767          debug_printf("%s - unsupported opcode %u\n", __FUNCTION__, header->opcode);
    768          ret = -ENOSYS;
    769          break;
    770    }
    771    rbug_free_header(header);
    772 
    773    if (ret)
    774       rbug_send_error_reply(tr_rbug->con, serial, ret, NULL);
    775 
    776    return TRUE;
    777 }
    778 
    779 static void
    780 rbug_con(struct rbug_rbug *tr_rbug)
    781 {
    782    struct rbug_header *header;
    783    uint32_t serial;
    784 
    785    debug_printf("%s - connection received\n", __FUNCTION__);
    786 
    787    while(tr_rbug->running) {
    788       header = rbug_get_message(tr_rbug->con, &serial);
    789       if (!header)
    790          break;
    791 
    792       if (!rbug_header(tr_rbug, header, serial))
    793          break;
    794    }
    795 
    796    debug_printf("%s - connection closed\n", __FUNCTION__);
    797 
    798    rbug_disconnect(tr_rbug->con);
    799    tr_rbug->con = NULL;
    800 }
    801 
    802 PIPE_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 0;
    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 0;
    843 }
    844 
    845 /**********************************************************
    846  *
    847  */
    848 
    849 struct rbug_rbug *
    850 rbug_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 
    863 void
    864 rbug_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 
    877 void
    878 rbug_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