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 NV50_WITH_DRAW_MODULE
  27. #include "draw/draw_context.h"
  28. #endif
  29.  
  30. #include "nv50_context.h"
  31. #include "nv50_screen.h"
  32. #include "nv50_resource.h"
  33.  
  34. static void
  35. nv50_flush(struct pipe_context *pipe,
  36.            struct pipe_fence_handle **fence,
  37.            unsigned flags)
  38. {
  39.    struct nouveau_screen *screen = nouveau_screen(pipe->screen);
  40.  
  41.    if (fence)
  42.       nouveau_fence_ref(screen->fence.current, (struct nouveau_fence **)fence);
  43.  
  44.    PUSH_KICK(screen->pushbuf);
  45.  
  46.    nouveau_context_update_frame_stats(nouveau_context(pipe));
  47. }
  48.  
  49. static void
  50. nv50_texture_barrier(struct pipe_context *pipe)
  51. {
  52.    struct nouveau_pushbuf *push = nv50_context(pipe)->base.pushbuf;
  53.  
  54.    BEGIN_NV04(push, SUBC_3D(NV50_GRAPH_SERIALIZE), 1);
  55.    PUSH_DATA (push, 0);
  56.    BEGIN_NV04(push, NV50_3D(TEX_CACHE_CTL), 1);
  57.    PUSH_DATA (push, 0x20);
  58. }
  59.  
  60. void
  61. nv50_default_kick_notify(struct nouveau_pushbuf *push)
  62. {
  63.    struct nv50_screen *screen = push->user_priv;
  64.  
  65.    if (screen) {
  66.       nouveau_fence_next(&screen->base);
  67.       nouveau_fence_update(&screen->base, TRUE);
  68.       if (screen->cur_ctx)
  69.          screen->cur_ctx->state.flushed = TRUE;
  70.    }
  71. }
  72.  
  73. static void
  74. nv50_context_unreference_resources(struct nv50_context *nv50)
  75. {
  76.    unsigned s, i;
  77.  
  78.    nouveau_bufctx_del(&nv50->bufctx_3d);
  79.    nouveau_bufctx_del(&nv50->bufctx);
  80.  
  81.    util_unreference_framebuffer_state(&nv50->framebuffer);
  82.  
  83.    for (i = 0; i < nv50->num_vtxbufs; ++i)
  84.       pipe_resource_reference(&nv50->vtxbuf[i].buffer, NULL);
  85.  
  86.    pipe_resource_reference(&nv50->idxbuf.buffer, NULL);
  87.  
  88.    for (s = 0; s < 3; ++s) {
  89.       for (i = 0; i < nv50->num_textures[s]; ++i)
  90.          pipe_sampler_view_reference(&nv50->textures[s][i], NULL);
  91.  
  92.       for (i = 0; i < NV50_MAX_PIPE_CONSTBUFS; ++i)
  93.          if (!nv50->constbuf[s][i].user)
  94.             pipe_resource_reference(&nv50->constbuf[s][i].u.buf, NULL);
  95.    }
  96. }
  97.  
  98. static void
  99. nv50_destroy(struct pipe_context *pipe)
  100. {
  101.    struct nv50_context *nv50 = nv50_context(pipe);
  102.  
  103.    if (nv50_context_screen(nv50)->cur_ctx == nv50) {
  104.       nv50->base.pushbuf->kick_notify = NULL;
  105.       nv50_context_screen(nv50)->cur_ctx = NULL;
  106.       nouveau_pushbuf_bufctx(nv50->base.pushbuf, NULL);
  107.    }
  108.    /* need to flush before destroying the bufctx */
  109.    nouveau_pushbuf_kick(nv50->base.pushbuf, nv50->base.pushbuf->channel);
  110.  
  111.    nv50_context_unreference_resources(nv50);
  112.  
  113. #ifdef NV50_WITH_DRAW_MODULE
  114.    draw_destroy(nv50->draw);
  115. #endif
  116.  
  117.    nouveau_context_destroy(&nv50->base);
  118. }
  119.  
  120. static int
  121. nv50_invalidate_resource_storage(struct nouveau_context *ctx,
  122.                                  struct pipe_resource *res,
  123.                                  int ref)
  124. {
  125.    struct nv50_context *nv50 = nv50_context(&ctx->pipe);
  126.    unsigned s, i;
  127.  
  128.    if (res->bind & PIPE_BIND_RENDER_TARGET) {
  129.       for (i = 0; i < nv50->framebuffer.nr_cbufs; ++i) {
  130.          if (nv50->framebuffer.cbufs[i] &&
  131.              nv50->framebuffer.cbufs[i]->texture == res) {
  132.             nv50->dirty |= NV50_NEW_FRAMEBUFFER;
  133.             nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_FB);
  134.             if (!--ref)
  135.                return ref;
  136.          }
  137.       }
  138.    }
  139.    if (res->bind & PIPE_BIND_DEPTH_STENCIL) {
  140.       if (nv50->framebuffer.zsbuf &&
  141.           nv50->framebuffer.zsbuf->texture == res) {
  142.          nv50->dirty |= NV50_NEW_FRAMEBUFFER;
  143.          nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_FB);
  144.          if (!--ref)
  145.             return ref;
  146.       }
  147.    }
  148.  
  149.    if (res->bind & PIPE_BIND_VERTEX_BUFFER) {
  150.       for (i = 0; i < nv50->num_vtxbufs; ++i) {
  151.          if (nv50->vtxbuf[i].buffer == res) {
  152.             nv50->dirty |= NV50_NEW_ARRAYS;
  153.             nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_VERTEX);
  154.             if (!--ref)
  155.                return ref;
  156.          }
  157.       }
  158.    }
  159.    if (res->bind & PIPE_BIND_INDEX_BUFFER) {
  160.       if (nv50->idxbuf.buffer == res)
  161.          if (!--ref)
  162.             return ref;
  163.    }
  164.  
  165.    if (res->bind & PIPE_BIND_SAMPLER_VIEW) {
  166.       for (s = 0; s < 5; ++s) {
  167.       for (i = 0; i < nv50->num_textures[s]; ++i) {
  168.          if (nv50->textures[s][i] &&
  169.              nv50->textures[s][i]->texture == res) {
  170.             nv50->dirty |= NV50_NEW_TEXTURES;
  171.             nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_TEXTURES);
  172.             if (!--ref)
  173.                return ref;
  174.          }
  175.       }
  176.       }
  177.    }
  178.  
  179.    if (res->bind & PIPE_BIND_CONSTANT_BUFFER) {
  180.       for (s = 0; s < 5; ++s) {
  181.       for (i = 0; i < nv50->num_vtxbufs; ++i) {
  182.          if (!nv50->constbuf[s][i].user &&
  183.              nv50->constbuf[s][i].u.buf == res) {
  184.             nv50->dirty |= NV50_NEW_CONSTBUF;
  185.             nv50->constbuf_dirty[s] |= 1 << i;
  186.             nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_CB(s, i));
  187.             if (!--ref)
  188.                return ref;
  189.          }
  190.       }
  191.       }
  192.    }
  193.  
  194.    return ref;
  195. }
  196.  
  197. struct pipe_context *
  198. nv50_create(struct pipe_screen *pscreen, void *priv)
  199. {
  200.    struct nv50_screen *screen = nv50_screen(pscreen);
  201.    struct nv50_context *nv50;
  202.    struct pipe_context *pipe;
  203.    int ret;
  204.    uint32_t flags;
  205.  
  206.    nv50 = CALLOC_STRUCT(nv50_context);
  207.    if (!nv50)
  208.       return NULL;
  209.    pipe = &nv50->base.pipe;
  210.  
  211.    if (!nv50_blitctx_create(nv50))
  212.       goto out_err;
  213.  
  214.    nv50->base.pushbuf = screen->base.pushbuf;
  215.    nv50->base.client = screen->base.client;
  216.  
  217.    ret = nouveau_bufctx_new(screen->base.client, NV50_BIND_COUNT,
  218.                             &nv50->bufctx_3d);
  219.    if (!ret)
  220.       ret = nouveau_bufctx_new(screen->base.client, 2, &nv50->bufctx);
  221.    if (ret)
  222.       goto out_err;
  223.  
  224.    nv50->base.screen    = &screen->base;
  225.    nv50->base.copy_data = nv50_m2mf_copy_linear;
  226.    nv50->base.push_data = nv50_sifc_linear_u8;
  227.    nv50->base.push_cb   = nv50_cb_push;
  228.  
  229.    nv50->screen = screen;
  230.    pipe->screen = pscreen;
  231.    pipe->priv = priv;
  232.  
  233.    pipe->destroy = nv50_destroy;
  234.  
  235.    pipe->draw_vbo = nv50_draw_vbo;
  236.    pipe->clear = nv50_clear;
  237.  
  238.    pipe->flush = nv50_flush;
  239.    pipe->texture_barrier = nv50_texture_barrier;
  240.  
  241.    if (!screen->cur_ctx) {
  242.       screen->cur_ctx = nv50;
  243.       nouveau_pushbuf_bufctx(screen->base.pushbuf, nv50->bufctx);
  244.    }
  245.    nv50->base.pushbuf->kick_notify = nv50_default_kick_notify;
  246.  
  247.    nv50_init_query_functions(nv50);
  248.    nv50_init_surface_functions(nv50);
  249.    nv50_init_state_functions(nv50);
  250.    nv50_init_resource_functions(pipe);
  251.  
  252.    nv50->base.invalidate_resource_storage = nv50_invalidate_resource_storage;
  253.  
  254. #ifdef NV50_WITH_DRAW_MODULE
  255.    /* no software fallbacks implemented */
  256.    nv50->draw = draw_create(pipe);
  257.    assert(nv50->draw);
  258.    draw_set_rasterize_stage(nv50->draw, nv50_draw_render_stage(nv50));
  259. #endif
  260.  
  261.    if (screen->base.device->chipset < 0x84) {
  262.       /* PMPEG */
  263.       nouveau_context_init_vdec(&nv50->base);
  264.    } else if (screen->base.device->chipset < 0x98 ||
  265.               screen->base.device->chipset == 0xa0) {
  266.       /* VP2 */
  267.       pipe->create_video_decoder = nv84_create_decoder;
  268.       pipe->create_video_buffer = nv84_video_buffer_create;
  269.    } else {
  270.       /* Unsupported, but need to init pointers. */
  271.       nouveau_context_init_vdec(&nv50->base);
  272.    }
  273.  
  274.    flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD;
  275.  
  276.    BCTX_REFN_bo(nv50->bufctx_3d, SCREEN, flags, screen->code);
  277.    BCTX_REFN_bo(nv50->bufctx_3d, SCREEN, flags, screen->uniforms);
  278.    BCTX_REFN_bo(nv50->bufctx_3d, SCREEN, flags, screen->txc);
  279.    BCTX_REFN_bo(nv50->bufctx_3d, SCREEN, flags, screen->stack_bo);
  280.  
  281.    flags = NOUVEAU_BO_GART | NOUVEAU_BO_WR;
  282.  
  283.    BCTX_REFN_bo(nv50->bufctx_3d, SCREEN, flags, screen->fence.bo);
  284.    BCTX_REFN_bo(nv50->bufctx, FENCE, flags, screen->fence.bo);
  285.  
  286.    nv50->base.scratch.bo_size = 2 << 20;
  287.  
  288.    return pipe;
  289.  
  290. out_err:
  291.    if (nv50) {
  292.       if (nv50->bufctx_3d)
  293.          nouveau_bufctx_del(&nv50->bufctx_3d);
  294.       if (nv50->bufctx)
  295.          nouveau_bufctx_del(&nv50->bufctx);
  296.       if (nv50->blit)
  297.          FREE(nv50->blit);
  298.       FREE(nv50);
  299.    }
  300.    return NULL;
  301. }
  302.  
  303. void
  304. nv50_bufctx_fence(struct nouveau_bufctx *bufctx, boolean on_flush)
  305. {
  306.    struct nouveau_list *list = on_flush ? &bufctx->current : &bufctx->pending;
  307.    struct nouveau_list *it;
  308.  
  309.    for (it = list->next; it != list; it = it->next) {
  310.       struct nouveau_bufref *ref = (struct nouveau_bufref *)it;
  311.       struct nv04_resource *res = ref->priv;
  312.       if (res)
  313.          nv50_resource_validate(res, (unsigned)ref->priv_data);
  314.    }
  315. }
  316.