Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright (C) 2009-2010 Francisco Jerez.
  3.  * All Rights Reserved.
  4.  *
  5.  * Permission is hereby granted, free of charge, to any person obtaining
  6.  * a copy of this software and associated documentation files (the
  7.  * "Software"), to deal in the Software without restriction, including
  8.  * without limitation the rights to use, copy, modify, merge, publish,
  9.  * distribute, sublicense, and/or sell copies of the Software, and to
  10.  * permit persons to whom the Software is furnished to do so, subject to
  11.  * the following conditions:
  12.  *
  13.  * The above copyright notice and this permission notice (including the
  14.  * next paragraph) shall be included in all copies or substantial
  15.  * portions of the Software.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18.  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  20.  * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
  21.  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  22.  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  23.  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  24.  *
  25.  */
  26.  
  27. #include <stdbool.h>
  28. #include <stdio.h>
  29. #include "nouveau_driver.h"
  30. #include "nouveau_context.h"
  31. #include "nouveau_bufferobj.h"
  32. #include "nouveau_fbo.h"
  33. #include "nv_object.xml.h"
  34.  
  35. #include "main/api_exec.h"
  36. #include "main/dd.h"
  37. #include "main/framebuffer.h"
  38. #include "main/fbobject.h"
  39. #include "main/light.h"
  40. #include "main/state.h"
  41. #include "main/version.h"
  42. #include "main/vtxfmt.h"
  43. #include "drivers/common/meta.h"
  44. #include "drivers/common/driverfuncs.h"
  45. #include "swrast/swrast.h"
  46. #include "swrast/s_context.h"
  47. #include "vbo/vbo.h"
  48. #include "tnl/tnl.h"
  49. #include "tnl/t_context.h"
  50.  
  51. GLboolean
  52. nouveau_context_create(gl_api api,
  53.                        const struct gl_config *visual, __DRIcontext *dri_ctx,
  54.                        unsigned major_version,
  55.                        unsigned minor_version,
  56.                        uint32_t flags,
  57.                        bool notify_reset,
  58.                        unsigned *error,
  59.                        void *share_ctx)
  60. {
  61.         __DRIscreen *dri_screen = dri_ctx->driScreenPriv;
  62.         struct nouveau_screen *screen = dri_screen->driverPrivate;
  63.         struct nouveau_context *nctx;
  64.         struct gl_context *ctx;
  65.  
  66.         if (flags & ~__DRI_CTX_FLAG_DEBUG) {
  67.                 *error = __DRI_CTX_ERROR_UNKNOWN_FLAG;
  68.                 return false;
  69.         }
  70.  
  71.         if (notify_reset) {
  72.                 *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE;
  73.                 return false;
  74.         }
  75.  
  76.         ctx = screen->driver->context_create(screen, api, visual, share_ctx);
  77.         if (!ctx) {
  78.                 *error = __DRI_CTX_ERROR_NO_MEMORY;
  79.                 return GL_FALSE;
  80.         }
  81.  
  82.         driContextSetFlags(ctx, flags);
  83.  
  84.         nctx = to_nouveau_context(ctx);
  85.         nctx->dri_context = dri_ctx;
  86.         dri_ctx->driverPrivate = ctx;
  87.  
  88.         _mesa_compute_version(ctx);
  89.         if (ctx->Version < major_version * 10 + minor_version) {
  90.            nouveau_context_destroy(dri_ctx);
  91.            *error = __DRI_CTX_ERROR_BAD_VERSION;
  92.            return GL_FALSE;
  93.         }
  94.  
  95.         /* Exec table initialization requires the version to be computed */
  96.         _mesa_initialize_dispatch_tables(ctx);
  97.         _mesa_initialize_vbo_vtxfmt(ctx);
  98.  
  99.         if (nouveau_bo_new(context_dev(ctx), NOUVEAU_BO_VRAM, 0, 4096,
  100.                            NULL, &nctx->fence)) {
  101.                 nouveau_context_destroy(dri_ctx);
  102.                 *error = __DRI_CTX_ERROR_NO_MEMORY;
  103.                 return GL_FALSE;
  104.         }
  105.  
  106.         *error = __DRI_CTX_ERROR_SUCCESS;
  107.         return GL_TRUE;
  108. }
  109.  
  110. GLboolean
  111. nouveau_context_init(struct gl_context *ctx, gl_api api,
  112.                      struct nouveau_screen *screen,
  113.                      const struct gl_config *visual, struct gl_context *share_ctx)
  114. {
  115.         struct nouveau_context *nctx = to_nouveau_context(ctx);
  116.         struct dd_function_table functions;
  117.         int ret;
  118.  
  119.         nctx->screen = screen;
  120.         nctx->fallback = HWTNL;
  121.  
  122.         /* Initialize the function pointers. */
  123.         _mesa_init_driver_functions(&functions);
  124.         nouveau_driver_functions_init(&functions);
  125.         nouveau_bufferobj_functions_init(&functions);
  126.         nouveau_texture_functions_init(&functions);
  127.         nouveau_fbo_functions_init(&functions);
  128.  
  129.         /* Initialize the mesa context. */
  130.         if (!_mesa_initialize_context(ctx, api, visual, share_ctx, &functions))
  131.                 return GL_FALSE;
  132.  
  133.         nouveau_state_init(ctx);
  134.         nouveau_scratch_init(ctx);
  135.         _mesa_meta_init(ctx);
  136.         _swrast_CreateContext(ctx);
  137.         _vbo_CreateContext(ctx);
  138.         _tnl_CreateContext(ctx);
  139.         nouveau_span_functions_init(ctx);
  140.         _mesa_allow_light_in_model(ctx, GL_FALSE);
  141.  
  142.         /* Allocate a hardware channel. */
  143.         ret = nouveau_object_new(&context_dev(ctx)->object, 0xbeef0000,
  144.                                  NOUVEAU_FIFO_CHANNEL_CLASS,
  145.                                  &(struct nv04_fifo){
  146.                                         .vram = 0xbeef0201,
  147.                                         .gart = 0xbeef0202
  148.                                  }, sizeof(struct nv04_fifo), &nctx->hw.chan);
  149.         if (ret) {
  150.                 nouveau_error("Error initializing the FIFO.\n");
  151.                 return GL_FALSE;
  152.         }
  153.  
  154.         /* Allocate a client (thread data) */
  155.         ret = nouveau_client_new(context_dev(ctx), &nctx->hw.client);
  156.         if (ret) {
  157.                 nouveau_error("Error creating thread data\n");
  158.                 return GL_FALSE;
  159.         }
  160.  
  161.         /* Allocate a push buffer */
  162.         ret = nouveau_pushbuf_new(nctx->hw.client, nctx->hw.chan, 4,
  163.                                   512 * 1024, true, &nctx->hw.pushbuf);
  164.         if (ret) {
  165.                 nouveau_error("Error allocating DMA push buffer\n");
  166.                 return GL_FALSE;
  167.         }
  168.  
  169.         /* Allocate buffer context */
  170.         ret = nouveau_bufctx_new(nctx->hw.client, 16, &nctx->hw.bufctx);
  171.         if (ret) {
  172.                 nouveau_error("Error allocating buffer context\n");
  173.                 return GL_FALSE;
  174.         }
  175.  
  176.         nctx->hw.pushbuf->user_priv = nctx->hw.bufctx;
  177.  
  178.         /* Allocate NULL object */
  179.         ret = nouveau_object_new(nctx->hw.chan, 0x00000000, NV01_NULL_CLASS,
  180.                                  NULL, 0, &nctx->hw.null);
  181.         if (ret) {
  182.                 nouveau_error("Error allocating NULL object\n");
  183.                 return GL_FALSE;
  184.         }
  185.  
  186.         /* Enable any supported extensions. */
  187.         ctx->Extensions.EXT_blend_color = true;
  188.         ctx->Extensions.EXT_blend_minmax = true;
  189.         ctx->Extensions.EXT_texture_filter_anisotropic = true;
  190.         ctx->Extensions.NV_texture_env_combine4 = true;
  191.         ctx->Const.MaxColorAttachments = 1;
  192.  
  193.         /* This effectively disables 3D textures */
  194.         ctx->Const.Max3DTextureLevels = 1;
  195.  
  196.         return GL_TRUE;
  197. }
  198.  
  199. void
  200. nouveau_context_deinit(struct gl_context *ctx)
  201. {
  202.         struct nouveau_context *nctx = to_nouveau_context(ctx);
  203.  
  204.         if (TNL_CONTEXT(ctx))
  205.                 _tnl_DestroyContext(ctx);
  206.  
  207.         if (vbo_context(ctx))
  208.                 _vbo_DestroyContext(ctx);
  209.  
  210.         if (SWRAST_CONTEXT(ctx))
  211.                 _swrast_DestroyContext(ctx);
  212.  
  213.         if (ctx->Meta)
  214.                 _mesa_meta_free(ctx);
  215.  
  216.         nouveau_bufctx_del(&nctx->hw.bufctx);
  217.         nouveau_pushbuf_del(&nctx->hw.pushbuf);
  218.         nouveau_client_del(&nctx->hw.client);
  219.         nouveau_object_del(&nctx->hw.chan);
  220.  
  221.         nouveau_scratch_destroy(ctx);
  222.         _mesa_free_context_data(ctx);
  223. }
  224.  
  225. void
  226. nouveau_context_destroy(__DRIcontext *dri_ctx)
  227. {
  228.         struct nouveau_context *nctx = dri_ctx->driverPrivate;
  229.         struct gl_context *ctx = &nctx->base;
  230.  
  231.         nouveau_bo_ref(NULL, &nctx->fence);
  232.         context_drv(ctx)->context_destroy(ctx);
  233. }
  234.  
  235. void
  236. nouveau_update_renderbuffers(__DRIcontext *dri_ctx, __DRIdrawable *draw)
  237. {
  238.         struct gl_context *ctx = dri_ctx->driverPrivate;
  239.         struct nouveau_context *nctx = to_nouveau_context(ctx);
  240.         __DRIscreen *screen = dri_ctx->driScreenPriv;
  241.         struct gl_framebuffer *fb = draw->driverPrivate;
  242.         struct nouveau_framebuffer *nfb = to_nouveau_framebuffer(fb);
  243.         unsigned int attachments[10];
  244.         __DRIbuffer *buffers = NULL;
  245.         int i = 0, count, ret;
  246.  
  247.         if (draw->lastStamp == draw->dri2.stamp)
  248.                 return;
  249.         draw->lastStamp = draw->dri2.stamp;
  250.  
  251.         if (nfb->need_front)
  252.                 attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
  253.         if (fb->Visual.doubleBufferMode)
  254.                 attachments[i++] = __DRI_BUFFER_BACK_LEFT;
  255.         if (fb->Visual.haveDepthBuffer && fb->Visual.haveStencilBuffer)
  256.                 attachments[i++] = __DRI_BUFFER_DEPTH_STENCIL;
  257.         else if (fb->Visual.haveDepthBuffer)
  258.                 attachments[i++] = __DRI_BUFFER_DEPTH;
  259.         else if (fb->Visual.haveStencilBuffer)
  260.                 attachments[i++] = __DRI_BUFFER_STENCIL;
  261.  
  262.         buffers = (*screen->dri2.loader->getBuffers)(draw, &draw->w, &draw->h,
  263.                                                      attachments, i, &count,
  264.                                                      draw->loaderPrivate);
  265.         if (buffers == NULL)
  266.                 return;
  267.  
  268.         for (i = 0; i < count; i++) {
  269.                 struct gl_renderbuffer *rb;
  270.                 struct nouveau_surface *s;
  271.                 uint32_t old_name;
  272.                 int index;
  273.  
  274.                 switch (buffers[i].attachment) {
  275.                 case __DRI_BUFFER_FRONT_LEFT:
  276.                 case __DRI_BUFFER_FAKE_FRONT_LEFT:
  277.                         index = BUFFER_FRONT_LEFT;
  278.                         break;
  279.                 case __DRI_BUFFER_BACK_LEFT:
  280.                         index = BUFFER_BACK_LEFT;
  281.                         break;
  282.                 case __DRI_BUFFER_DEPTH:
  283.                 case __DRI_BUFFER_DEPTH_STENCIL:
  284.                         index = BUFFER_DEPTH;
  285.                         break;
  286.                 case __DRI_BUFFER_STENCIL:
  287.                         index = BUFFER_STENCIL;
  288.                         break;
  289.                 default:
  290.                         assert(0);
  291.                 }
  292.  
  293.                 rb = fb->Attachment[index].Renderbuffer;
  294.                 s = &to_nouveau_renderbuffer(rb)->surface;
  295.  
  296.                 s->width = draw->w;
  297.                 s->height = draw->h;
  298.                 s->pitch = buffers[i].pitch;
  299.                 s->cpp = buffers[i].cpp;
  300.  
  301.                 if (index == BUFFER_DEPTH && s->bo) {
  302.                         ret = nouveau_bo_name_get(s->bo, &old_name);
  303.                         /*
  304.                          * Disable fast Z clears in the next frame, the
  305.                          * depth buffer contents are undefined.
  306.                          */
  307.                         if (!ret && old_name != buffers[i].name)
  308.                                 nctx->hierz.clear_seq = 0;
  309.                 }
  310.  
  311.                 nouveau_bo_ref(NULL, &s->bo);
  312.                 ret = nouveau_bo_name_ref(context_dev(ctx),
  313.                                           buffers[i].name, &s->bo);
  314.                 assert(!ret);
  315.         }
  316.  
  317.         _mesa_resize_framebuffer(ctx, fb, draw->w, draw->h);
  318. }
  319.  
  320. static void
  321. update_framebuffer(__DRIcontext *dri_ctx, __DRIdrawable *draw,
  322.                    int *stamp)
  323. {
  324.         struct gl_context *ctx = dri_ctx->driverPrivate;
  325.         struct gl_framebuffer *fb = draw->driverPrivate;
  326.  
  327.         *stamp = draw->dri2.stamp;
  328.  
  329.         nouveau_update_renderbuffers(dri_ctx, draw);
  330.         _mesa_resize_framebuffer(ctx, fb, draw->w, draw->h);
  331.  
  332.         /* Clean up references to the old framebuffer objects. */
  333.         context_dirty(ctx, FRAMEBUFFER);
  334.         nouveau_bufctx_reset(to_nouveau_context(ctx)->hw.bufctx, BUFCTX_FB);
  335.         PUSH_KICK(context_push(ctx));
  336. }
  337.  
  338. GLboolean
  339. nouveau_context_make_current(__DRIcontext *dri_ctx, __DRIdrawable *dri_draw,
  340.                              __DRIdrawable *dri_read)
  341. {
  342.         if (dri_ctx) {
  343.                 struct nouveau_context *nctx = dri_ctx->driverPrivate;
  344.                 struct gl_context *ctx = &nctx->base;
  345.  
  346.                 /* Ask the X server for new renderbuffers. */
  347.                 if (dri_draw->driverPrivate != ctx->WinSysDrawBuffer)
  348.                         update_framebuffer(dri_ctx, dri_draw,
  349.                                            &dri_ctx->dri2.draw_stamp);
  350.  
  351.                 if (dri_draw != dri_read &&
  352.                     dri_read->driverPrivate != ctx->WinSysReadBuffer)
  353.                         update_framebuffer(dri_ctx, dri_read,
  354.                                            &dri_ctx->dri2.read_stamp);
  355.  
  356.                 /* Pass it down to mesa. */
  357.                 _mesa_make_current(ctx, dri_draw->driverPrivate,
  358.                                    dri_read->driverPrivate);
  359.                 _mesa_update_state(ctx);
  360.  
  361.         } else {
  362.                 _mesa_make_current(NULL, NULL, NULL);
  363.         }
  364.  
  365.         return GL_TRUE;
  366. }
  367.  
  368. GLboolean
  369. nouveau_context_unbind(__DRIcontext *dri_ctx)
  370. {
  371.         /* Unset current context and dispatch table */
  372.         _mesa_make_current(NULL, NULL, NULL);
  373.  
  374.         return GL_TRUE;
  375. }
  376.  
  377. void
  378. nouveau_fallback(struct gl_context *ctx, enum nouveau_fallback mode)
  379. {
  380.         struct nouveau_context *nctx = to_nouveau_context(ctx);
  381.  
  382.         nctx->fallback = MAX2(HWTNL, mode);
  383.  
  384.         if (mode < SWRAST) {
  385.                 nouveau_state_emit(ctx);
  386. #if 0
  387.                 nouveau_bo_state_emit(ctx);
  388. #endif
  389.         } else {
  390.                 PUSH_KICK(context_push(ctx));
  391.         }
  392. }
  393.  
  394. static void
  395. validate_framebuffer(__DRIcontext *dri_ctx, __DRIdrawable *draw,
  396.                      int *stamp)
  397. {
  398.         struct gl_framebuffer *fb = draw->driverPrivate;
  399.         struct nouveau_framebuffer *nfb = to_nouveau_framebuffer(fb);
  400.         GLboolean need_front =
  401.                 (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT ||
  402.                  fb->_ColorReadBufferIndex == BUFFER_FRONT_LEFT);
  403.  
  404.         if (nfb->need_front != need_front) {
  405.                 nfb->need_front = need_front;
  406.                 dri2InvalidateDrawable(draw);
  407.         }
  408.  
  409.         if (draw->dri2.stamp != *stamp)
  410.                 update_framebuffer(dri_ctx, draw, stamp);
  411. }
  412.  
  413. void
  414. nouveau_validate_framebuffer(struct gl_context *ctx)
  415. {
  416.         __DRIcontext *dri_ctx = to_nouveau_context(ctx)->dri_context;
  417.         __DRIdrawable *dri_draw = dri_ctx->driDrawablePriv;
  418.         __DRIdrawable *dri_read = dri_ctx->driReadablePriv;
  419.  
  420.         if (_mesa_is_winsys_fbo(ctx->DrawBuffer))
  421.                 validate_framebuffer(dri_ctx, dri_draw,
  422.                                      &dri_ctx->dri2.draw_stamp);
  423.  
  424.         if (_mesa_is_winsys_fbo(ctx->ReadBuffer))
  425.                 validate_framebuffer(dri_ctx, dri_read,
  426.                                      &dri_ctx->dri2.read_stamp);
  427.  
  428.         if (ctx->NewState & _NEW_BUFFERS)
  429.                 _mesa_update_state(ctx);
  430. }
  431.