Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2.  * Copyright 2012 Red Hat Inc.
  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.  * Authors: Ben Skeggs
  23.  *
  24.  */
  25.  
  26. #include "draw/draw_context.h"
  27.  
  28. #include "nouveau/nv_object.xml.h"
  29. #include "nv30-40_3d.xml.h"
  30.  
  31. #include "nouveau/nouveau_fence.h"
  32. #include "nv30_context.h"
  33. #include "nv30_transfer.h"
  34. #include "nv30_state.h"
  35.  
  36. static void
  37. nv30_context_kick_notify(struct nouveau_pushbuf *push)
  38. {
  39.    struct nouveau_screen *screen;
  40.    struct nv30_context *nv30;
  41.  
  42.    if (!push->user_priv)
  43.       return;
  44.    nv30 = container_of(push->user_priv, nv30, bufctx);
  45.    screen = &nv30->screen->base;
  46.  
  47.    nouveau_fence_next(screen);
  48.    nouveau_fence_update(screen, TRUE);
  49.  
  50.    if (push->bufctx) {
  51.       struct nouveau_bufref *bref;
  52.       LIST_FOR_EACH_ENTRY(bref, &push->bufctx->current, thead) {
  53.          struct nv04_resource *res = bref->priv;
  54.          if (res && res->mm) {
  55.             nouveau_fence_ref(screen->fence.current, &res->fence);
  56.  
  57.             if (bref->flags & NOUVEAU_BO_RD)
  58.                res->status |= NOUVEAU_BUFFER_STATUS_GPU_READING;
  59.  
  60.             if (bref->flags & NOUVEAU_BO_WR) {
  61.                nouveau_fence_ref(screen->fence.current, &res->fence_wr);
  62.                res->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING |
  63.                   NOUVEAU_BUFFER_STATUS_DIRTY;
  64.             }
  65.          }
  66.       }
  67.    }
  68. }
  69.  
  70. static void
  71. nv30_context_flush(struct pipe_context *pipe, struct pipe_fence_handle **fence,
  72.                    unsigned flags)
  73. {
  74.    struct nv30_context *nv30 = nv30_context(pipe);
  75.    struct nouveau_pushbuf *push = nv30->base.pushbuf;
  76.  
  77.    if (fence)
  78.       nouveau_fence_ref(nv30->screen->base.fence.current,
  79.                         (struct nouveau_fence **)fence);
  80.  
  81.    PUSH_KICK(push);
  82.  
  83.    nouveau_context_update_frame_stats(&nv30->base);
  84. }
  85.  
  86. static int
  87. nv30_invalidate_resource_storage(struct nouveau_context *nv,
  88.                                  struct pipe_resource *res,
  89.                                  int ref)
  90. {
  91.    struct nv30_context *nv30 = nv30_context(&nv->pipe);
  92.    unsigned i;
  93.  
  94.    if (res->bind & PIPE_BIND_RENDER_TARGET) {
  95.       for (i = 0; i < nv30->framebuffer.nr_cbufs; ++i) {
  96.          if (nv30->framebuffer.cbufs[i] &&
  97.              nv30->framebuffer.cbufs[i]->texture == res) {
  98.             nv30->dirty |= NV30_NEW_FRAMEBUFFER;
  99.             nouveau_bufctx_reset(nv30->bufctx, BUFCTX_FB);
  100.             if (!--ref)
  101.                return ref;
  102.          }
  103.       }
  104.    }
  105.    if (res->bind & PIPE_BIND_DEPTH_STENCIL) {
  106.       if (nv30->framebuffer.zsbuf &&
  107.           nv30->framebuffer.zsbuf->texture == res) {
  108.             nv30->dirty |= NV30_NEW_FRAMEBUFFER;
  109.             nouveau_bufctx_reset(nv30->bufctx, BUFCTX_FB);
  110.             if (!--ref)
  111.                return ref;
  112.       }
  113.    }
  114.  
  115.    if (res->bind & PIPE_BIND_VERTEX_BUFFER) {
  116.       for (i = 0; i < nv30->num_vtxbufs; ++i) {
  117.          if (nv30->vtxbuf[i].buffer == res) {
  118.             nv30->dirty |= NV30_NEW_ARRAYS;
  119.             nouveau_bufctx_reset(nv30->bufctx, BUFCTX_VTXBUF);
  120.             if (!--ref)
  121.                return ref;
  122.          }
  123.       }
  124.    }
  125.    if (res->bind & PIPE_BIND_INDEX_BUFFER) {
  126.       if (nv30->idxbuf.buffer == res) {
  127.          nouveau_bufctx_reset(nv30->bufctx, BUFCTX_IDXBUF);
  128.          if (!--ref)
  129.             return ref;
  130.       }
  131.    }
  132.  
  133.    if (res->bind & PIPE_BIND_SAMPLER_VIEW) {
  134.       for (i = 0; i < nv30->fragprog.num_textures; ++i) {
  135.          if (nv30->fragprog.textures[i] &&
  136.              nv30->fragprog.textures[i]->texture == res) {
  137.             nv30->dirty |= NV30_NEW_FRAGTEX;
  138.             nouveau_bufctx_reset(nv30->bufctx, BUFCTX_FRAGTEX(i));
  139.             if (!--ref)
  140.                return ref;
  141.          }
  142.       }
  143.       for (i = 0; i < nv30->vertprog.num_textures; ++i) {
  144.          if (nv30->vertprog.textures[i] &&
  145.              nv30->vertprog.textures[i]->texture == res) {
  146.             nv30->dirty |= NV30_NEW_VERTTEX;
  147.             nouveau_bufctx_reset(nv30->bufctx, BUFCTX_VERTTEX(i));
  148.             if (!--ref)
  149.                return ref;
  150.          }
  151.       }
  152.    }
  153.  
  154.    return ref;
  155. }
  156.  
  157. static void
  158. nv30_context_destroy(struct pipe_context *pipe)
  159. {
  160.    struct nv30_context *nv30 = nv30_context(pipe);
  161.  
  162.    if (nv30->blitter)
  163.       util_blitter_destroy(nv30->blitter);
  164.  
  165.    if (nv30->draw)
  166.       draw_destroy(nv30->draw);
  167.  
  168.    nouveau_bufctx_del(&nv30->bufctx);
  169.  
  170.    if (nv30->screen->cur_ctx == nv30)
  171.       nv30->screen->cur_ctx = NULL;
  172.  
  173.    nouveau_context_destroy(&nv30->base);
  174. }
  175.  
  176. #define FAIL_CONTEXT_INIT(str, err)                   \
  177.    do {                                               \
  178.       NOUVEAU_ERR(str, err);                          \
  179.       nv30_context_destroy(pipe);                     \
  180.       return NULL;                                    \
  181.    } while(0)
  182.  
  183. struct pipe_context *
  184. nv30_context_create(struct pipe_screen *pscreen, void *priv)
  185. {
  186.    struct nv30_screen *screen = nv30_screen(pscreen);
  187.    struct nv30_context *nv30 = CALLOC_STRUCT(nv30_context);
  188.    struct nouveau_pushbuf *push;
  189.    struct pipe_context *pipe;
  190.    int ret;
  191.  
  192.    if (!nv30)
  193.       return NULL;
  194.  
  195.    nv30->screen = screen;
  196.    nv30->base.screen = &screen->base;
  197.    nv30->base.copy_data = nv30_transfer_copy_data;
  198.  
  199.    pipe = &nv30->base.pipe;
  200.    pipe->screen = pscreen;
  201.    pipe->priv = priv;
  202.    pipe->destroy = nv30_context_destroy;
  203.    pipe->flush = nv30_context_flush;
  204.  
  205.    /*XXX: *cough* per-context client */
  206.    nv30->base.client = screen->base.client;
  207.  
  208.    /*XXX: *cough* per-context pushbufs */
  209.    push = screen->base.pushbuf;
  210.    nv30->base.pushbuf = push;
  211.    nv30->base.pushbuf->user_priv = &nv30->bufctx; /* hack at validate time */
  212.    nv30->base.pushbuf->rsvd_kick = 16; /* hack in screen before first space */
  213.    nv30->base.pushbuf->kick_notify = nv30_context_kick_notify;
  214.  
  215.    nv30->base.invalidate_resource_storage = nv30_invalidate_resource_storage;
  216.  
  217.    ret = nouveau_bufctx_new(nv30->base.client, 64, &nv30->bufctx);
  218.    if (ret) {
  219.       nv30_context_destroy(pipe);
  220.       return NULL;
  221.    }
  222.  
  223.    /*XXX: make configurable with performance vs quality, these defaults
  224.     *     match the binary driver's defaults
  225.     */
  226.    if (screen->eng3d->oclass < NV40_3D_CLASS)
  227.       nv30->config.filter = 0x00000004;
  228.    else
  229.       nv30->config.filter = 0x00002dc4;
  230.  
  231.    nv30->config.aniso = NV40_3D_TEX_WRAP_ANISO_MIP_FILTER_OPTIMIZATION_OFF;
  232.  
  233.    if (debug_get_bool_option("NV30_SWTNL", FALSE))
  234.       nv30->draw_flags |= NV30_NEW_SWTNL;
  235.  
  236.    /*XXX: nvfx... */
  237.    nv30->is_nv4x = (screen->eng3d->oclass >= NV40_3D_CLASS) ? ~0 : 0;
  238.    nv30->use_nv4x = (screen->eng3d->oclass >= NV40_3D_CLASS) ? ~0 : 0;
  239.    nv30->render_mode = HW;
  240.  
  241.    nv30->sample_mask = 0xffff;
  242.    nv30_vbo_init(pipe);
  243.    nv30_query_init(pipe);
  244.    nv30_state_init(pipe);
  245.    nv30_resource_init(pipe);
  246.    nv30_clear_init(pipe);
  247.    nv30_fragprog_init(pipe);
  248.    nv30_vertprog_init(pipe);
  249.    nv30_texture_init(pipe);
  250.    nv30_fragtex_init(pipe);
  251.    nv40_verttex_init(pipe);
  252.    nv30_draw_init(pipe);
  253.  
  254.    nv30->blitter = util_blitter_create(pipe);
  255.    if (!nv30->blitter) {
  256.       nv30_context_destroy(pipe);
  257.       return NULL;
  258.    }
  259.  
  260.    return pipe;
  261. }
  262.