Home | History | Annotate | Download | only in nv50
      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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
     18  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
     19  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     20  * 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 {
     38    struct nouveau_screen *screen = nouveau_screen(pipe->screen);
     39 
     40    if (fence)
     41       nouveau_fence_ref(screen->fence.current, (struct nouveau_fence **)fence);
     42 
     43    PUSH_KICK(screen->pushbuf);
     44 }
     45 
     46 static void
     47 nv50_texture_barrier(struct pipe_context *pipe)
     48 {
     49    struct nouveau_pushbuf *push = nv50_context(pipe)->base.pushbuf;
     50 
     51    BEGIN_NV04(push, SUBC_3D(NV50_GRAPH_SERIALIZE), 1);
     52    PUSH_DATA (push, 0);
     53    BEGIN_NV04(push, NV50_3D(TEX_CACHE_CTL), 1);
     54    PUSH_DATA (push, 0x20);
     55 }
     56 
     57 void
     58 nv50_default_kick_notify(struct nouveau_pushbuf *push)
     59 {
     60    struct nv50_screen *screen = push->user_priv;
     61 
     62    if (screen) {
     63       nouveau_fence_next(&screen->base);
     64       nouveau_fence_update(&screen->base, TRUE);
     65       if (screen->cur_ctx)
     66          screen->cur_ctx->state.flushed = TRUE;
     67    }
     68 }
     69 
     70 static void
     71 nv50_context_unreference_resources(struct nv50_context *nv50)
     72 {
     73    unsigned s, i;
     74 
     75    nouveau_bufctx_del(&nv50->bufctx_3d);
     76    nouveau_bufctx_del(&nv50->bufctx);
     77 
     78    util_unreference_framebuffer_state(&nv50->framebuffer);
     79 
     80    for (i = 0; i < nv50->num_vtxbufs; ++i)
     81       pipe_resource_reference(&nv50->vtxbuf[i].buffer, NULL);
     82 
     83    pipe_resource_reference(&nv50->idxbuf.buffer, NULL);
     84 
     85    for (s = 0; s < 3; ++s) {
     86       for (i = 0; i < nv50->num_textures[s]; ++i)
     87          pipe_sampler_view_reference(&nv50->textures[s][i], NULL);
     88 
     89       for (i = 0; i < NV50_MAX_PIPE_CONSTBUFS; ++i)
     90          if (!nv50->constbuf[s][i].user)
     91             pipe_resource_reference(&nv50->constbuf[s][i].u.buf, NULL);
     92    }
     93 }
     94 
     95 static void
     96 nv50_destroy(struct pipe_context *pipe)
     97 {
     98    struct nv50_context *nv50 = nv50_context(pipe);
     99 
    100    if (nv50_context_screen(nv50)->cur_ctx == nv50) {
    101       nv50->base.pushbuf->kick_notify = NULL;
    102       nv50_context_screen(nv50)->cur_ctx = NULL;
    103       nouveau_pushbuf_bufctx(nv50->base.pushbuf, NULL);
    104    }
    105    /* need to flush before destroying the bufctx */
    106    nouveau_pushbuf_kick(nv50->base.pushbuf, nv50->base.pushbuf->channel);
    107 
    108    nv50_context_unreference_resources(nv50);
    109 
    110 #ifdef NV50_WITH_DRAW_MODULE
    111    draw_destroy(nv50->draw);
    112 #endif
    113 
    114    nouveau_context_destroy(&nv50->base);
    115 }
    116 
    117 struct pipe_context *
    118 nv50_create(struct pipe_screen *pscreen, void *priv)
    119 {
    120    struct nv50_screen *screen = nv50_screen(pscreen);
    121    struct nv50_context *nv50;
    122    struct pipe_context *pipe;
    123    int ret;
    124    uint32_t flags;
    125 
    126    nv50 = CALLOC_STRUCT(nv50_context);
    127    if (!nv50)
    128       return NULL;
    129    pipe = &nv50->base.pipe;
    130 
    131    nv50->base.pushbuf = screen->base.pushbuf;
    132 
    133    ret = nouveau_bufctx_new(screen->base.client, NV50_BIND_COUNT,
    134                             &nv50->bufctx_3d);
    135    if (!ret)
    136       ret = nouveau_bufctx_new(screen->base.client, 2, &nv50->bufctx);
    137    if (ret)
    138       goto out_err;
    139 
    140    nv50->base.screen    = &screen->base;
    141    nv50->base.copy_data = nv50_m2mf_copy_linear;
    142    nv50->base.push_data = nv50_sifc_linear_u8;
    143    nv50->base.push_cb   = nv50_cb_push;
    144 
    145    nv50->screen = screen;
    146    pipe->screen = pscreen;
    147    pipe->priv = priv;
    148 
    149    pipe->destroy = nv50_destroy;
    150 
    151    pipe->draw_vbo = nv50_draw_vbo;
    152    pipe->clear = nv50_clear;
    153 
    154    pipe->flush = nv50_flush;
    155    pipe->texture_barrier = nv50_texture_barrier;
    156 
    157    if (!screen->cur_ctx) {
    158       screen->cur_ctx = nv50;
    159       nouveau_pushbuf_bufctx(screen->base.pushbuf, nv50->bufctx);
    160    }
    161 
    162    nv50_init_query_functions(nv50);
    163    nv50_init_surface_functions(nv50);
    164    nv50_init_state_functions(nv50);
    165    nv50_init_resource_functions(pipe);
    166 
    167 #ifdef NV50_WITH_DRAW_MODULE
    168    /* no software fallbacks implemented */
    169    nv50->draw = draw_create(pipe);
    170    assert(nv50->draw);
    171    draw_set_rasterize_stage(nv50->draw, nv50_draw_render_stage(nv50));
    172 #endif
    173 
    174    nouveau_context_init_vdec(&nv50->base);
    175 
    176    flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD;
    177 
    178    BCTX_REFN_bo(nv50->bufctx_3d, SCREEN, flags, screen->code);
    179    BCTX_REFN_bo(nv50->bufctx_3d, SCREEN, flags, screen->uniforms);
    180    BCTX_REFN_bo(nv50->bufctx_3d, SCREEN, flags, screen->txc);
    181    BCTX_REFN_bo(nv50->bufctx_3d, SCREEN, flags, screen->stack_bo);
    182 
    183    flags = NOUVEAU_BO_GART | NOUVEAU_BO_WR;
    184 
    185    BCTX_REFN_bo(nv50->bufctx_3d, SCREEN, flags, screen->fence.bo);
    186    BCTX_REFN_bo(nv50->bufctx, FENCE, flags, screen->fence.bo);
    187 
    188    nv50->base.scratch.bo_size = 2 << 20;
    189 
    190    return pipe;
    191 
    192 out_err:
    193    if (nv50) {
    194       if (nv50->bufctx_3d)
    195          nouveau_bufctx_del(&nv50->bufctx_3d);
    196       if (nv50->bufctx)
    197          nouveau_bufctx_del(&nv50->bufctx);
    198       FREE(nv50);
    199    }
    200    return NULL;
    201 }
    202 
    203 void
    204 nv50_bufctx_fence(struct nouveau_bufctx *bufctx, boolean on_flush)
    205 {
    206    struct nouveau_list *list = on_flush ? &bufctx->current : &bufctx->pending;
    207    struct nouveau_list *it;
    208 
    209    for (it = list->next; it != list; it = it->next) {
    210       struct nouveau_bufref *ref = (struct nouveau_bufref *)it;
    211       struct nv04_resource *res = ref->priv;
    212       if (res)
    213          nv50_resource_validate(res, (unsigned)ref->priv_data);
    214    }
    215 }
    216