Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2.  * Copyright 2010 Christoph Bumiller
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a
  5.  * copy of this software and associated documentation files (the "Software"),
  6.  * to deal in the Software without restriction, including without limitation
  7.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8.  * and/or sell copies of the Software, and to permit persons to whom the
  9.  * Software is furnished to do so, subject to the following conditions:
  10.  *
  11.  * The above copyright notice and this permission notice shall be included in
  12.  * all copies or substantial portions of the Software.
  13.  *
  14.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20.  * OTHER DEALINGS IN THE SOFTWARE.
  21.  */
  22.  
  23. #include "pipe/p_defines.h"
  24. #include "util/u_framebuffer.h"
  25.  
  26. #ifdef NVC0_WITH_DRAW_MODULE
  27. #include "draw/draw_context.h"
  28. #endif
  29.  
  30. #include "nvc0_context.h"
  31. #include "nvc0_screen.h"
  32. #include "nvc0_resource.h"
  33.  
  34. static void
  35. nvc0_flush(struct pipe_context *pipe,
  36.            struct pipe_fence_handle **fence,
  37.            unsigned flags)
  38. {
  39.    struct nvc0_context *nvc0 = nvc0_context(pipe);
  40.    struct nouveau_screen *screen = &nvc0->screen->base;
  41.  
  42.    if (fence)
  43.       nouveau_fence_ref(screen->fence.current, (struct nouveau_fence **)fence);
  44.  
  45.    PUSH_KICK(nvc0->base.pushbuf); /* fencing handled in kick_notify */
  46.  
  47.    nouveau_context_update_frame_stats(&nvc0->base);
  48. }
  49.  
  50. static void
  51. nvc0_texture_barrier(struct pipe_context *pipe)
  52. {
  53.    struct nouveau_pushbuf *push = nvc0_context(pipe)->base.pushbuf;
  54.  
  55.    IMMED_NVC0(push, NVC0_3D(SERIALIZE), 0);
  56.    IMMED_NVC0(push, NVC0_3D(TEX_CACHE_CTL), 0);
  57. }
  58.  
  59. static void
  60. nvc0_context_unreference_resources(struct nvc0_context *nvc0)
  61. {
  62.    unsigned s, i;
  63.  
  64.    nouveau_bufctx_del(&nvc0->bufctx_3d);
  65.    nouveau_bufctx_del(&nvc0->bufctx);
  66.    nouveau_bufctx_del(&nvc0->bufctx_cp);
  67.  
  68.    util_unreference_framebuffer_state(&nvc0->framebuffer);
  69.  
  70.    for (i = 0; i < nvc0->num_vtxbufs; ++i)
  71.       pipe_resource_reference(&nvc0->vtxbuf[i].buffer, NULL);
  72.  
  73.    pipe_resource_reference(&nvc0->idxbuf.buffer, NULL);
  74.  
  75.    for (s = 0; s < 6; ++s) {
  76.       for (i = 0; i < nvc0->num_textures[s]; ++i)
  77.          pipe_sampler_view_reference(&nvc0->textures[s][i], NULL);
  78.  
  79.       for (i = 0; i < NVC0_MAX_PIPE_CONSTBUFS; ++i)
  80.          if (!nvc0->constbuf[s][i].user)
  81.             pipe_resource_reference(&nvc0->constbuf[s][i].u.buf, NULL);
  82.    }
  83.  
  84.    for (s = 0; s < 2; ++s) {
  85.       for (i = 0; i < NVC0_MAX_SURFACE_SLOTS; ++i)
  86.          pipe_surface_reference(&nvc0->surfaces[s][i], NULL);
  87.    }
  88.  
  89.    for (i = 0; i < nvc0->num_tfbbufs; ++i)
  90.       pipe_so_target_reference(&nvc0->tfbbuf[i], NULL);
  91.  
  92.    for (i = 0; i < nvc0->global_residents.size / sizeof(struct pipe_resource *);
  93.         ++i) {
  94.       struct pipe_resource **res = util_dynarray_element(
  95.          &nvc0->global_residents, struct pipe_resource *, i);
  96.       pipe_resource_reference(res, NULL);
  97.    }
  98.    util_dynarray_fini(&nvc0->global_residents);
  99. }
  100.  
  101. static void
  102. nvc0_destroy(struct pipe_context *pipe)
  103. {
  104.    struct nvc0_context *nvc0 = nvc0_context(pipe);
  105.  
  106.    if (nvc0->screen->cur_ctx == nvc0) {
  107.       nvc0->base.pushbuf->kick_notify = NULL;
  108.       nvc0->screen->cur_ctx = NULL;
  109.       nouveau_pushbuf_bufctx(nvc0->base.pushbuf, NULL);
  110.    }
  111.    nouveau_pushbuf_kick(nvc0->base.pushbuf, nvc0->base.pushbuf->channel);
  112.  
  113.    nvc0_context_unreference_resources(nvc0);
  114.    nvc0_blitctx_destroy(nvc0);
  115.  
  116. #ifdef NVC0_WITH_DRAW_MODULE
  117.    draw_destroy(nvc0->draw);
  118. #endif
  119.  
  120.    nouveau_context_destroy(&nvc0->base);
  121. }
  122.  
  123. void
  124. nvc0_default_kick_notify(struct nouveau_pushbuf *push)
  125. {
  126.    struct nvc0_screen *screen = push->user_priv;
  127.  
  128.    if (screen) {
  129.       nouveau_fence_next(&screen->base);
  130.       nouveau_fence_update(&screen->base, TRUE);
  131.       if (screen->cur_ctx)
  132.          screen->cur_ctx->state.flushed = TRUE;
  133.    }
  134.    NOUVEAU_DRV_STAT(&screen->base, pushbuf_count, 1);
  135. }
  136.  
  137. static int
  138. nvc0_invalidate_resource_storage(struct nouveau_context *ctx,
  139.                                  struct pipe_resource *res,
  140.                                  int ref)
  141. {
  142.    struct nvc0_context *nvc0 = nvc0_context(&ctx->pipe);
  143.    unsigned s, i;
  144.  
  145.    if (res->bind & PIPE_BIND_RENDER_TARGET) {
  146.       for (i = 0; i < nvc0->framebuffer.nr_cbufs; ++i) {
  147.          if (nvc0->framebuffer.cbufs[i] &&
  148.              nvc0->framebuffer.cbufs[i]->texture == res) {
  149.             nvc0->dirty |= NVC0_NEW_FRAMEBUFFER;
  150.             nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_FB);
  151.             if (!--ref)
  152.                return ref;
  153.          }
  154.       }
  155.    }
  156.    if (res->bind & PIPE_BIND_DEPTH_STENCIL) {
  157.       if (nvc0->framebuffer.zsbuf &&
  158.           nvc0->framebuffer.zsbuf->texture == res) {
  159.          nvc0->dirty |= NVC0_NEW_FRAMEBUFFER;
  160.          nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_FB);
  161.          if (!--ref)
  162.             return ref;
  163.       }
  164.    }
  165.  
  166.    if (res->bind & PIPE_BIND_VERTEX_BUFFER) {
  167.       for (i = 0; i < nvc0->num_vtxbufs; ++i) {
  168.          if (nvc0->vtxbuf[i].buffer == res) {
  169.             nvc0->dirty |= NVC0_NEW_ARRAYS;
  170.             nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_VTX);
  171.             if (!--ref)
  172.                return ref;
  173.          }
  174.       }
  175.    }
  176.    if (res->bind & PIPE_BIND_INDEX_BUFFER) {
  177.       if (nvc0->idxbuf.buffer == res) {
  178.          nvc0->dirty |= NVC0_NEW_IDXBUF;
  179.          nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_IDX);
  180.          if (!--ref)
  181.             return ref;
  182.       }
  183.    }
  184.  
  185.    if (res->bind & PIPE_BIND_SAMPLER_VIEW) {
  186.       for (s = 0; s < 5; ++s) {
  187.       for (i = 0; i < nvc0->num_textures[s]; ++i) {
  188.          if (nvc0->textures[s][i] &&
  189.              nvc0->textures[s][i]->texture == res) {
  190.             nvc0->textures_dirty[s] |= 1 << i;
  191.             nvc0->dirty |= NVC0_NEW_TEXTURES;
  192.             nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_TEX(s, i));
  193.             if (!--ref)
  194.                return ref;
  195.          }
  196.       }
  197.       }
  198.    }
  199.  
  200.    if (res->bind & PIPE_BIND_CONSTANT_BUFFER) {
  201.       for (s = 0; s < 5; ++s) {
  202.       for (i = 0; i < nvc0->num_vtxbufs; ++i) {
  203.          if (!nvc0->constbuf[s][i].user &&
  204.              nvc0->constbuf[s][i].u.buf == res) {
  205.             nvc0->dirty |= NVC0_NEW_CONSTBUF;
  206.             nvc0->constbuf_dirty[s] |= 1 << i;
  207.             nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_CB(s, i));
  208.             if (!--ref)
  209.                return ref;
  210.          }
  211.       }
  212.       }
  213.    }
  214.  
  215.    return ref;
  216. }
  217.  
  218. static void
  219. nvc0_context_get_sample_position(struct pipe_context *, unsigned, unsigned,
  220.                                  float *);
  221.  
  222. struct pipe_context *
  223. nvc0_create(struct pipe_screen *pscreen, void *priv)
  224. {
  225.    struct nvc0_screen *screen = nvc0_screen(pscreen);
  226.    struct nvc0_context *nvc0;
  227.    struct pipe_context *pipe;
  228.    int ret;
  229.    uint32_t flags;
  230.  
  231.    nvc0 = CALLOC_STRUCT(nvc0_context);
  232.    if (!nvc0)
  233.       return NULL;
  234.    pipe = &nvc0->base.pipe;
  235.  
  236.    if (!nvc0_blitctx_create(nvc0))
  237.       goto out_err;
  238.  
  239.    nvc0->base.pushbuf = screen->base.pushbuf;
  240.    nvc0->base.client = screen->base.client;
  241.  
  242.    ret = nouveau_bufctx_new(screen->base.client, 2, &nvc0->bufctx);
  243.    if (!ret)
  244.       ret = nouveau_bufctx_new(screen->base.client, NVC0_BIND_3D_COUNT,
  245.                                &nvc0->bufctx_3d);
  246.    if (!ret)
  247.       ret = nouveau_bufctx_new(screen->base.client, NVC0_BIND_CP_COUNT,
  248.                                &nvc0->bufctx_cp);
  249.    if (ret)
  250.       goto out_err;
  251.  
  252.    nvc0->screen = screen;
  253.    nvc0->base.screen = &screen->base;
  254.  
  255.    pipe->screen = pscreen;
  256.    pipe->priv = priv;
  257.  
  258.    pipe->destroy = nvc0_destroy;
  259.  
  260.    pipe->draw_vbo = nvc0_draw_vbo;
  261.    pipe->clear = nvc0_clear;
  262.    if (nvc0->screen->base.class_3d >= NVE4_3D_CLASS)
  263.       pipe->launch_grid = nve4_launch_grid;
  264.  
  265.    pipe->flush = nvc0_flush;
  266.    pipe->texture_barrier = nvc0_texture_barrier;
  267.    pipe->get_sample_position = nvc0_context_get_sample_position;
  268.  
  269.    if (!screen->cur_ctx) {
  270.       screen->cur_ctx = nvc0;
  271.       nouveau_pushbuf_bufctx(screen->base.pushbuf, nvc0->bufctx);
  272.    }
  273.    screen->base.pushbuf->kick_notify = nvc0_default_kick_notify;
  274.  
  275.    nvc0_init_query_functions(nvc0);
  276.    nvc0_init_surface_functions(nvc0);
  277.    nvc0_init_state_functions(nvc0);
  278.    nvc0_init_transfer_functions(nvc0);
  279.    nvc0_init_resource_functions(pipe);
  280.  
  281.    nvc0->base.invalidate_resource_storage = nvc0_invalidate_resource_storage;
  282.  
  283. #ifdef NVC0_WITH_DRAW_MODULE
  284.    /* no software fallbacks implemented */
  285.    nvc0->draw = draw_create(pipe);
  286.    assert(nvc0->draw);
  287.    draw_set_rasterize_stage(nvc0->draw, nvc0_draw_render_stage(nvc0));
  288. #endif
  289.  
  290.    pipe->create_video_decoder = nvc0_create_decoder;
  291.    pipe->create_video_buffer = nvc0_video_buffer_create;
  292.  
  293.    /* shader builtin library is per-screen, but we need a context for m2mf */
  294.    nvc0_program_library_upload(nvc0);
  295.  
  296.    /* add permanently resident buffers to bufctxts */
  297.  
  298.    flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD;
  299.  
  300.    BCTX_REFN_bo(nvc0->bufctx_3d, SCREEN, flags, screen->text);
  301.    BCTX_REFN_bo(nvc0->bufctx_3d, SCREEN, flags, screen->uniform_bo);
  302.    BCTX_REFN_bo(nvc0->bufctx_3d, SCREEN, flags, screen->txc);
  303.    if (screen->compute) {
  304.       BCTX_REFN_bo(nvc0->bufctx_cp, CP_SCREEN, flags, screen->text);
  305.       BCTX_REFN_bo(nvc0->bufctx_cp, CP_SCREEN, flags, screen->txc);
  306.       BCTX_REFN_bo(nvc0->bufctx_cp, CP_SCREEN, flags, screen->parm);
  307.    }
  308.  
  309.    flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR;
  310.  
  311.    BCTX_REFN_bo(nvc0->bufctx_3d, SCREEN, flags, screen->poly_cache);
  312.    if (screen->compute)
  313.       BCTX_REFN_bo(nvc0->bufctx_cp, CP_SCREEN, flags, screen->tls);
  314.  
  315.    flags = NOUVEAU_BO_GART | NOUVEAU_BO_WR;
  316.  
  317.    BCTX_REFN_bo(nvc0->bufctx_3d, SCREEN, flags, screen->fence.bo);
  318.    BCTX_REFN_bo(nvc0->bufctx, FENCE, flags, screen->fence.bo);
  319.    if (screen->compute)
  320.       BCTX_REFN_bo(nvc0->bufctx_cp, CP_SCREEN, flags, screen->fence.bo);
  321.  
  322.    nvc0->base.scratch.bo_size = 2 << 20;
  323.  
  324.    memset(nvc0->tex_handles, ~0, sizeof(nvc0->tex_handles));
  325.  
  326.    util_dynarray_init(&nvc0->global_residents);
  327.  
  328.    return pipe;
  329.  
  330. out_err:
  331.    if (nvc0) {
  332.       if (nvc0->bufctx_3d)
  333.          nouveau_bufctx_del(&nvc0->bufctx_3d);
  334.       if (nvc0->bufctx_cp)
  335.          nouveau_bufctx_del(&nvc0->bufctx_cp);
  336.       if (nvc0->bufctx)
  337.          nouveau_bufctx_del(&nvc0->bufctx);
  338.       if (nvc0->blit)
  339.          FREE(nvc0->blit);
  340.       FREE(nvc0);
  341.    }
  342.    return NULL;
  343. }
  344.  
  345. void
  346. nvc0_bufctx_fence(struct nvc0_context *nvc0, struct nouveau_bufctx *bufctx,
  347.                   boolean on_flush)
  348. {
  349.    struct nouveau_list *list = on_flush ? &bufctx->current : &bufctx->pending;
  350.    struct nouveau_list *it;
  351.    NOUVEAU_DRV_STAT_IFD(unsigned count = 0);
  352.  
  353.    for (it = list->next; it != list; it = it->next) {
  354.       struct nouveau_bufref *ref = (struct nouveau_bufref *)it;
  355.       struct nv04_resource *res = ref->priv;
  356.       if (res)
  357.          nvc0_resource_validate(res, (unsigned)ref->priv_data);
  358.       NOUVEAU_DRV_STAT_IFD(count++);
  359.    }
  360.    NOUVEAU_DRV_STAT(&nvc0->screen->base, resource_validate_count, count);
  361. }
  362.  
  363. static void
  364. nvc0_context_get_sample_position(struct pipe_context *pipe,
  365.                                  unsigned sample_count, unsigned sample_index,
  366.                                  float *xy)
  367. {
  368.    static const uint8_t ms1[1][2] = { { 0x8, 0x8 } };
  369.    static const uint8_t ms2[2][2] = {
  370.       { 0x4, 0x4 }, { 0xc, 0xc } }; /* surface coords (0,0), (1,0) */
  371.    static const uint8_t ms4[4][2] = {
  372.       { 0x6, 0x2 }, { 0xe, 0x6 },   /* (0,0), (1,0) */
  373.       { 0x2, 0xa }, { 0xa, 0xe } }; /* (0,1), (1,1) */
  374.    static const uint8_t ms8[8][2] = {
  375.       { 0x1, 0x7 }, { 0x5, 0x3 },   /* (0,0), (1,0) */
  376.       { 0x3, 0xd }, { 0x7, 0xb },   /* (0,1), (1,1) */
  377.       { 0x9, 0x5 }, { 0xf, 0x1 },   /* (2,0), (3,0) */
  378.       { 0xb, 0xf }, { 0xd, 0x9 } }; /* (2,1), (3,1) */
  379. #if 0
  380.    /* NOTE: there are alternative modes for MS2 and MS8, currently not used */
  381.    static const uint8_t ms8_alt[8][2] = {
  382.       { 0x9, 0x5 }, { 0x7, 0xb },   /* (2,0), (1,1) */
  383.       { 0xd, 0x9 }, { 0x5, 0x3 },   /* (3,1), (1,0) */
  384.       { 0x3, 0xd }, { 0x1, 0x7 },   /* (0,1), (0,0) */
  385.       { 0xb, 0xf }, { 0xf, 0x1 } }; /* (2,1), (3,0) */
  386. #endif
  387.  
  388.    const uint8_t (*ptr)[2];
  389.  
  390.    switch (sample_count) {
  391.    case 0:
  392.    case 1: ptr = ms1; break;
  393.    case 2: ptr = ms2; break;
  394.    case 4: ptr = ms4; break;
  395.    case 8: ptr = ms8; break;
  396.    default:
  397.       assert(0);
  398.       break;
  399.    }
  400.    xy[0] = ptr[sample_index][0] * 0.0625f;
  401.    xy[1] = ptr[sample_index][1] * 0.0625f;
  402. }
  403.