Subversion Repositories Kolibri OS

Rev

Go to most recent revision | 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 "nouveau_driver.h"
  29. #include "nouveau_context.h"
  30. #include "nouveau_bufferobj.h"
  31. #include "nouveau_fbo.h"
  32. #include "nv_object.xml.h"
  33.  
  34. #include "main/api_exec.h"
  35. #include "main/dd.h"
  36. #include "main/framebuffer.h"
  37. #include "main/fbobject.h"
  38. #include "main/light.h"
  39. #include "main/state.h"
  40. #include "main/version.h"
  41. #include "main/vtxfmt.h"
  42. #include "drivers/common/meta.h"
  43. #include "drivers/common/driverfuncs.h"
  44. #include "swrast/swrast.h"
  45. #include "swrast/s_context.h"
  46. #include "vbo/vbo.h"
  47. #include "tnl/tnl.h"
  48. #include "tnl/t_context.h"
  49.  
  50. GLboolean
  51. nouveau_context_create(gl_api api,
  52.                        const struct gl_config *visual, __DRIcontext *dri_ctx,
  53.                        unsigned major_version,
  54.                        unsigned minor_version,
  55.                        uint32_t flags,
  56.                        unsigned *error,
  57.                        void *share_ctx)
  58. {
  59.         __DRIscreen *dri_screen = dri_ctx->driScreenPriv;
  60.         struct nouveau_screen *screen = dri_screen->driverPrivate;
  61.         struct nouveau_context *nctx;
  62.         struct gl_context *ctx;
  63.  
  64.         switch (api) {
  65.         case API_OPENGL_COMPAT:
  66.                 /* Do after-the-fact version checking (below).
  67.                  */
  68.                 break;
  69.         case API_OPENGLES:
  70.                 /* NV10 and NV20 can support OpenGL ES 1.0 only.  Older chips
  71.                  * cannot do even that.
  72.                  */
  73.                 if ((screen->device->chipset & 0xf0) == 0x00) {
  74.                         *error = __DRI_CTX_ERROR_BAD_API;
  75.                         return GL_FALSE;
  76.                 } else if (minor_version != 0) {
  77.                         *error = __DRI_CTX_ERROR_BAD_VERSION;
  78.                         return GL_FALSE;
  79.                 }
  80.                 break;
  81.         case API_OPENGLES2:
  82.         case API_OPENGL_CORE:
  83.                 *error = __DRI_CTX_ERROR_BAD_API;
  84.                 return GL_FALSE;
  85.         }
  86.  
  87.         /* API and flag filtering is handled in dri2CreateContextAttribs.
  88.          */
  89.         (void) flags;
  90.  
  91.         ctx = screen->driver->context_create(screen, visual, share_ctx);
  92.         if (!ctx) {
  93.                 *error = __DRI_CTX_ERROR_NO_MEMORY;
  94.                 return GL_FALSE;
  95.         }
  96.  
  97.         nctx = to_nouveau_context(ctx);
  98.         nctx->dri_context = dri_ctx;
  99.         dri_ctx->driverPrivate = ctx;
  100.  
  101.         _mesa_compute_version(ctx);
  102.         if (ctx->Version < major_version * 10 + minor_version) {
  103.            nouveau_context_destroy(dri_ctx);
  104.            *error = __DRI_CTX_ERROR_BAD_VERSION;
  105.            return GL_FALSE;
  106.         }
  107.  
  108.         /* Exec table initialization requires the version to be computed */
  109.         _mesa_initialize_dispatch_tables(ctx);
  110.         _mesa_initialize_vbo_vtxfmt(ctx);
  111.  
  112.         if (nouveau_bo_new(context_dev(ctx), NOUVEAU_BO_VRAM, 0, 4096,
  113.                            NULL, &nctx->fence)) {
  114.                 nouveau_context_destroy(dri_ctx);
  115.                 *error = __DRI_CTX_ERROR_NO_MEMORY;
  116.                 return GL_FALSE;
  117.         }
  118.  
  119.         *error = __DRI_CTX_ERROR_SUCCESS;
  120.         return GL_TRUE;
  121. }
  122.  
  123. GLboolean
  124. nouveau_context_init(struct gl_context *ctx, struct nouveau_screen *screen,
  125.                      const struct gl_config *visual, struct gl_context *share_ctx)
  126. {
  127.         struct nouveau_context *nctx = to_nouveau_context(ctx);
  128.         struct dd_function_table functions;
  129.         int ret;
  130.  
  131.         nctx->screen = screen;
  132.         nctx->fallback = HWTNL;
  133.  
  134.         /* Initialize the function pointers. */
  135.         _mesa_init_driver_functions(&functions);
  136.         nouveau_driver_functions_init(&functions);
  137.         nouveau_bufferobj_functions_init(&functions);
  138.         nouveau_texture_functions_init(&functions);
  139.         nouveau_fbo_functions_init(&functions);
  140.  
  141.         /* Initialize the mesa context. */
  142.         _mesa_initialize_context(ctx, API_OPENGL_COMPAT, visual,
  143.                                  share_ctx, &functions);
  144.  
  145.         nouveau_state_init(ctx);
  146.         nouveau_scratch_init(ctx);
  147.         _mesa_meta_init(ctx);
  148.         _swrast_CreateContext(ctx);
  149.         _vbo_CreateContext(ctx);
  150.         _tnl_CreateContext(ctx);
  151.         nouveau_span_functions_init(ctx);
  152.         _mesa_allow_light_in_model(ctx, GL_FALSE);
  153.  
  154.         /* Allocate a hardware channel. */
  155.         ret = nouveau_object_new(&context_dev(ctx)->object, 0xbeef0000,
  156.                                  NOUVEAU_FIFO_CHANNEL_CLASS,
  157.                                  &(struct nv04_fifo){
  158.                                         .vram = 0xbeef0201,
  159.                                         .gart = 0xbeef0202
  160.                                  }, sizeof(struct nv04_fifo), &nctx->hw.chan);
  161.         if (ret) {
  162.                 nouveau_error("Error initializing the FIFO.\n");
  163.                 return GL_FALSE;
  164.         }
  165.  
  166.         /* Allocate a client (thread data) */
  167.         ret = nouveau_client_new(context_dev(ctx), &nctx->hw.client);
  168.         if (ret) {
  169.                 nouveau_error("Error creating thread data\n");
  170.                 return GL_FALSE;
  171.         }
  172.  
  173.         /* Allocate a push buffer */
  174.         ret = nouveau_pushbuf_new(nctx->hw.client, nctx->hw.chan, 4,
  175.                                   512 * 1024, true, &nctx->hw.pushbuf);
  176.         if (ret) {
  177.                 nouveau_error("Error allocating DMA push buffer\n");
  178.                 return GL_FALSE;
  179.         }
  180.  
  181.         /* Allocate buffer context */
  182.         ret = nouveau_bufctx_new(nctx->hw.client, 16, &nctx->hw.bufctx);
  183.         if (ret) {
  184.                 nouveau_error("Error allocating buffer context\n");
  185.                 return GL_FALSE;
  186.         }
  187.  
  188.         nctx->hw.pushbuf->user_priv = nctx->hw.bufctx;
  189.  
  190.         /* Allocate NULL object */
  191.         ret = nouveau_object_new(nctx->hw.chan, 0x00000000, NV01_NULL_CLASS,
  192.                                  NULL, 0, &nctx->hw.null);
  193.         if (ret) {
  194.                 nouveau_error("Error allocating NULL object\n");
  195.                 return GL_FALSE;
  196.         }
  197.  
  198.         /* Enable any supported extensions. */
  199.         ctx->Extensions.EXT_blend_color = true;
  200.         ctx->Extensions.EXT_blend_minmax = true;
  201.         ctx->Extensions.EXT_framebuffer_blit = true;
  202.         ctx->Extensions.EXT_packed_depth_stencil = true;
  203.         ctx->Extensions.EXT_texture_filter_anisotropic = true;
  204.         ctx->Extensions.NV_texture_env_combine4 = true;
  205.  
  206.         return GL_TRUE;
  207. }
  208.  
  209. void
  210. nouveau_context_deinit(struct gl_context *ctx)
  211. {
  212.         struct nouveau_context *nctx = to_nouveau_context(ctx);
  213.  
  214.         if (TNL_CONTEXT(ctx))
  215.                 _tnl_DestroyContext(ctx);
  216.  
  217.         if (vbo_context(ctx))
  218.                 _vbo_DestroyContext(ctx);
  219.  
  220.         if (SWRAST_CONTEXT(ctx))
  221.                 _swrast_DestroyContext(ctx);
  222.  
  223.         if (ctx->Meta)
  224.                 _mesa_meta_free(ctx);
  225.  
  226.         nouveau_bufctx_del(&nctx->hw.bufctx);
  227.         nouveau_pushbuf_del(&nctx->hw.pushbuf);
  228.         nouveau_client_del(&nctx->hw.client);
  229.         nouveau_object_del(&nctx->hw.chan);
  230.  
  231.         nouveau_scratch_destroy(ctx);
  232.         _mesa_free_context_data(ctx);
  233. }
  234.  
  235. void
  236. nouveau_context_destroy(__DRIcontext *dri_ctx)
  237. {
  238.         struct nouveau_context *nctx = dri_ctx->driverPrivate;
  239.         struct gl_context *ctx = &nctx->base;
  240.  
  241.         nouveau_bo_ref(NULL, &nctx->fence);
  242.         context_drv(ctx)->context_destroy(ctx);
  243. }
  244.  
  245. void
  246. nouveau_update_renderbuffers(__DRIcontext *dri_ctx, __DRIdrawable *draw)
  247. {
  248.         struct gl_context *ctx = dri_ctx->driverPrivate;
  249.         struct nouveau_context *nctx = to_nouveau_context(ctx);
  250.         __DRIscreen *screen = dri_ctx->driScreenPriv;
  251.         struct gl_framebuffer *fb = draw->driverPrivate;
  252.         struct nouveau_framebuffer *nfb = to_nouveau_framebuffer(fb);
  253.         unsigned int attachments[10];
  254.         __DRIbuffer *buffers = NULL;
  255.         int i = 0, count, ret;
  256.  
  257.         if (draw->lastStamp == draw->dri2.stamp)
  258.                 return;
  259.         draw->lastStamp = draw->dri2.stamp;
  260.  
  261.         if (nfb->need_front)
  262.                 attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
  263.         if (fb->Visual.doubleBufferMode)
  264.                 attachments[i++] = __DRI_BUFFER_BACK_LEFT;
  265.         if (fb->Visual.haveDepthBuffer && fb->Visual.haveStencilBuffer)
  266.                 attachments[i++] = __DRI_BUFFER_DEPTH_STENCIL;
  267.         else if (fb->Visual.haveDepthBuffer)
  268.                 attachments[i++] = __DRI_BUFFER_DEPTH;
  269.         else if (fb->Visual.haveStencilBuffer)
  270.                 attachments[i++] = __DRI_BUFFER_STENCIL;
  271.  
  272.         buffers = (*screen->dri2.loader->getBuffers)(draw, &draw->w, &draw->h,
  273.                                                      attachments, i, &count,
  274.                                                      draw->loaderPrivate);
  275.         if (buffers == NULL)
  276.                 return;
  277.  
  278.         for (i = 0; i < count; i++) {
  279.                 struct gl_renderbuffer *rb;
  280.                 struct nouveau_surface *s;
  281.                 uint32_t old_name;
  282.                 int index;
  283.  
  284.                 switch (buffers[i].attachment) {
  285.                 case __DRI_BUFFER_FRONT_LEFT:
  286.                 case __DRI_BUFFER_FAKE_FRONT_LEFT:
  287.                         index = BUFFER_FRONT_LEFT;
  288.                         break;
  289.                 case __DRI_BUFFER_BACK_LEFT:
  290.                         index = BUFFER_BACK_LEFT;
  291.                         break;
  292.                 case __DRI_BUFFER_DEPTH:
  293.                 case __DRI_BUFFER_DEPTH_STENCIL:
  294.                         index = BUFFER_DEPTH;
  295.                         break;
  296.                 case __DRI_BUFFER_STENCIL:
  297.                         index = BUFFER_STENCIL;
  298.                         break;
  299.                 default:
  300.                         assert(0);
  301.                 }
  302.  
  303.                 rb = fb->Attachment[index].Renderbuffer;
  304.                 s = &to_nouveau_renderbuffer(rb)->surface;
  305.  
  306.                 s->width = draw->w;
  307.                 s->height = draw->h;
  308.                 s->pitch = buffers[i].pitch;
  309.                 s->cpp = buffers[i].cpp;
  310.  
  311.                 if (index == BUFFER_DEPTH && s->bo) {
  312.                         ret = nouveau_bo_name_get(s->bo, &old_name);
  313.                         /*
  314.                          * Disable fast Z clears in the next frame, the
  315.                          * depth buffer contents are undefined.
  316.                          */
  317.                         if (!ret && old_name != buffers[i].name)
  318.                                 nctx->hierz.clear_seq = 0;
  319.                 }
  320.  
  321.                 nouveau_bo_ref(NULL, &s->bo);
  322.                 ret = nouveau_bo_name_ref(context_dev(ctx),
  323.                                           buffers[i].name, &s->bo);
  324.                 assert(!ret);
  325.         }
  326.  
  327.         _mesa_resize_framebuffer(ctx, fb, draw->w, draw->h);
  328. }
  329.  
  330. static void
  331. update_framebuffer(__DRIcontext *dri_ctx, __DRIdrawable *draw,
  332.                    int *stamp)
  333. {
  334.         struct gl_context *ctx = dri_ctx->driverPrivate;
  335.         struct gl_framebuffer *fb = draw->driverPrivate;
  336.  
  337.         *stamp = draw->dri2.stamp;
  338.  
  339.         nouveau_update_renderbuffers(dri_ctx, draw);
  340.         _mesa_resize_framebuffer(ctx, fb, draw->w, draw->h);
  341.  
  342.         /* Clean up references to the old framebuffer objects. */
  343.         context_dirty(ctx, FRAMEBUFFER);
  344.         nouveau_bufctx_reset(to_nouveau_context(ctx)->hw.bufctx, BUFCTX_FB);
  345.         PUSH_KICK(context_push(ctx));
  346. }
  347.  
  348. GLboolean
  349. nouveau_context_make_current(__DRIcontext *dri_ctx, __DRIdrawable *dri_draw,
  350.                              __DRIdrawable *dri_read)
  351. {
  352.         if (dri_ctx) {
  353.                 struct nouveau_context *nctx = dri_ctx->driverPrivate;
  354.                 struct gl_context *ctx = &nctx->base;
  355.  
  356.                 /* Ask the X server for new renderbuffers. */
  357.                 if (dri_draw->driverPrivate != ctx->WinSysDrawBuffer)
  358.                         update_framebuffer(dri_ctx, dri_draw,
  359.                                            &dri_ctx->dri2.draw_stamp);
  360.  
  361.                 if (dri_draw != dri_read &&
  362.                     dri_read->driverPrivate != ctx->WinSysReadBuffer)
  363.                         update_framebuffer(dri_ctx, dri_read,
  364.                                            &dri_ctx->dri2.read_stamp);
  365.  
  366.                 /* Pass it down to mesa. */
  367.                 _mesa_make_current(ctx, dri_draw->driverPrivate,
  368.                                    dri_read->driverPrivate);
  369.                 _mesa_update_state(ctx);
  370.  
  371.         } else {
  372.                 _mesa_make_current(NULL, NULL, NULL);
  373.         }
  374.  
  375.         return GL_TRUE;
  376. }
  377.  
  378. GLboolean
  379. nouveau_context_unbind(__DRIcontext *dri_ctx)
  380. {
  381.         /* Unset current context and dispatch table */
  382.         _mesa_make_current(NULL, NULL, NULL);
  383.  
  384.         return GL_TRUE;
  385. }
  386.  
  387. void
  388. nouveau_fallback(struct gl_context *ctx, enum nouveau_fallback mode)
  389. {
  390.         struct nouveau_context *nctx = to_nouveau_context(ctx);
  391.  
  392.         nctx->fallback = MAX2(HWTNL, mode);
  393.  
  394.         if (mode < SWRAST) {
  395.                 nouveau_state_emit(ctx);
  396. #if 0
  397.                 nouveau_bo_state_emit(ctx);
  398. #endif
  399.         } else {
  400.                 PUSH_KICK(context_push(ctx));
  401.         }
  402. }
  403.  
  404. static void
  405. validate_framebuffer(__DRIcontext *dri_ctx, __DRIdrawable *draw,
  406.                      int *stamp)
  407. {
  408.         struct gl_framebuffer *fb = draw->driverPrivate;
  409.         struct nouveau_framebuffer *nfb = to_nouveau_framebuffer(fb);
  410.         GLboolean need_front =
  411.                 (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT ||
  412.                  fb->_ColorReadBufferIndex == BUFFER_FRONT_LEFT);
  413.  
  414.         if (nfb->need_front != need_front) {
  415.                 nfb->need_front = need_front;
  416.                 dri2InvalidateDrawable(draw);
  417.         }
  418.  
  419.         if (draw->dri2.stamp != *stamp)
  420.                 update_framebuffer(dri_ctx, draw, stamp);
  421. }
  422.  
  423. void
  424. nouveau_validate_framebuffer(struct gl_context *ctx)
  425. {
  426.         __DRIcontext *dri_ctx = to_nouveau_context(ctx)->dri_context;
  427.         __DRIdrawable *dri_draw = dri_ctx->driDrawablePriv;
  428.         __DRIdrawable *dri_read = dri_ctx->driReadablePriv;
  429.  
  430.         if (_mesa_is_winsys_fbo(ctx->DrawBuffer))
  431.                 validate_framebuffer(dri_ctx, dri_draw,
  432.                                      &dri_ctx->dri2.draw_stamp);
  433.  
  434.         if (_mesa_is_winsys_fbo(ctx->ReadBuffer))
  435.                 validate_framebuffer(dri_ctx, dri_read,
  436.                                      &dri_ctx->dri2.read_stamp);
  437.  
  438.         if (ctx->NewState & _NEW_BUFFERS)
  439.                 _mesa_update_state(ctx);
  440. }
  441.