Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright (C) 2009 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 <stdio.h>
  28. #include <xf86drm.h>
  29. #include <nouveau_drm.h>
  30. #include "nouveau_driver.h"
  31. #include "nouveau_context.h"
  32. #include "nouveau_fbo.h"
  33. #include "nouveau_texture.h"
  34. #include "nv04_driver.h"
  35. #include "nv10_driver.h"
  36. #include "nv20_driver.h"
  37.  
  38. #include "main/framebuffer.h"
  39. #include "main/fbobject.h"
  40. #include "main/renderbuffer.h"
  41. #include "swrast/s_renderbuffer.h"
  42.  
  43. static const __DRIextension *nouveau_screen_extensions[];
  44.  
  45. static void
  46. nouveau_destroy_screen(__DRIscreen *dri_screen);
  47.  
  48. static const __DRIconfig **
  49. nouveau_get_configs(void)
  50. {
  51.         __DRIconfig **configs = NULL;
  52.         int i;
  53.  
  54.         const uint8_t depth_bits[]   = { 0, 16, 24, 24 };
  55.         const uint8_t stencil_bits[] = { 0,  0,  0,  8 };
  56.         const uint8_t msaa_samples[] = { 0 };
  57.  
  58.         static const mesa_format formats[3] = {
  59.                 MESA_FORMAT_B5G6R5_UNORM,
  60.                 MESA_FORMAT_B8G8R8A8_UNORM,
  61.                 MESA_FORMAT_B8G8R8X8_UNORM,
  62.         };
  63.  
  64.         const GLenum back_buffer_modes[] = {
  65.                 GLX_NONE, GLX_SWAP_UNDEFINED_OML
  66.         };
  67.  
  68.         for (i = 0; i < ARRAY_SIZE(formats); i++) {
  69.                 __DRIconfig **config;
  70.  
  71.                 config = driCreateConfigs(formats[i],
  72.                                           depth_bits, stencil_bits,
  73.                                           ARRAY_SIZE(depth_bits),
  74.                                           back_buffer_modes,
  75.                                           ARRAY_SIZE(back_buffer_modes),
  76.                                           msaa_samples,
  77.                                           ARRAY_SIZE(msaa_samples),
  78.                                           GL_TRUE);
  79.                 assert(config);
  80.  
  81.                 configs = driConcatConfigs(configs, config);
  82.         }
  83.  
  84.         return (const __DRIconfig **)configs;
  85. }
  86.  
  87. static const __DRIconfig **
  88. nouveau_init_screen2(__DRIscreen *dri_screen)
  89. {
  90.         const __DRIconfig **configs;
  91.         struct nouveau_screen *screen;
  92.         int ret;
  93.  
  94.         /* Allocate the screen. */
  95.         screen = CALLOC_STRUCT(nouveau_screen);
  96.         if (!screen)
  97.                 return NULL;
  98.  
  99.         dri_screen->driverPrivate = screen;
  100.  
  101.         /* Open the DRM device. */
  102.         ret = nouveau_device_wrap(dri_screen->fd, 0, &screen->device);
  103.         if (ret) {
  104.                 nouveau_error("Error opening the DRM device.\n");
  105.                 goto fail;
  106.         }
  107.  
  108.         /* Choose the card specific function pointers. */
  109.         switch (screen->device->chipset & 0xf0) {
  110.         case 0x00:
  111.                 screen->driver = &nv04_driver;
  112.                 dri_screen->max_gl_compat_version = 12;
  113.                 break;
  114.         case 0x10:
  115.                 screen->driver = &nv10_driver;
  116.                 dri_screen->max_gl_compat_version = 12;
  117.                 dri_screen->max_gl_es1_version = 10;
  118.                 break;
  119.         case 0x20:
  120.                 screen->driver = &nv20_driver;
  121.                 dri_screen->max_gl_compat_version = 13;
  122.                 dri_screen->max_gl_es1_version = 10;
  123.                 break;
  124.         default:
  125.                 nouveau_error("Unknown chipset: %02X\n",
  126.                               screen->device->chipset);
  127.                 goto fail;
  128.         }
  129.  
  130.         dri_screen->extensions = nouveau_screen_extensions;
  131.         screen->dri_screen = dri_screen;
  132.  
  133.         configs = nouveau_get_configs();
  134.         if (!configs)
  135.                 goto fail;
  136.  
  137.         return configs;
  138. fail:
  139.         nouveau_destroy_screen(dri_screen);
  140.         return NULL;
  141.  
  142. }
  143.  
  144. static int
  145. nouveau_query_renderer_integer(__DRIscreen *psp, int param,
  146.                                unsigned int *value)
  147. {
  148.         const struct nouveau_screen *const screen =
  149.                 (struct nouveau_screen *) psp->driverPrivate;
  150.  
  151.         switch (param) {
  152.         case __DRI2_RENDERER_VENDOR_ID:
  153.                 value[0] = 0x10de;
  154.                 return 0;
  155.         case __DRI2_RENDERER_DEVICE_ID: {
  156.                 uint64_t device_id;
  157.  
  158.                 if (nouveau_getparam(screen->device,
  159.                                      NOUVEAU_GETPARAM_PCI_DEVICE,
  160.                                      &device_id)) {
  161.                         nouveau_error("Error retrieving the device PCIID.\n");
  162.                         device_id = -1;
  163.                 }
  164.                 value[0] = (unsigned int) device_id;
  165.                 return 0;
  166.         }
  167.         case __DRI2_RENDERER_ACCELERATED:
  168.                 value[0] = 1;
  169.                 return 0;
  170.         case __DRI2_RENDERER_VIDEO_MEMORY:
  171.                 /* XXX: return vram_size or vram_limit ? */
  172.                 value[0] = screen->device->vram_size >> 20;
  173.                 return 0;
  174.         case __DRI2_RENDERER_UNIFIED_MEMORY_ARCHITECTURE:
  175.                 value[0] = 0;
  176.                 return 0;
  177.         default:
  178.                 return driQueryRendererIntegerCommon(psp, param, value);
  179.         }
  180. }
  181.  
  182. static int
  183. nouveau_query_renderer_string(__DRIscreen *psp, int param, const char **value)
  184. {
  185.         const struct nouveau_screen *const screen =
  186.                 (struct nouveau_screen *) psp->driverPrivate;
  187.  
  188.         switch (param) {
  189.         case __DRI2_RENDERER_VENDOR_ID:
  190.                 value[0] = nouveau_vendor_string;
  191.                 return 0;
  192.         case __DRI2_RENDERER_DEVICE_ID:
  193.                 value[0] = nouveau_get_renderer_string(screen->device->chipset);
  194.                 return 0;
  195.         default:
  196.                 return -1;
  197.    }
  198. }
  199.  
  200. static const __DRI2rendererQueryExtension nouveau_renderer_query_extension = {
  201.         .base = { __DRI2_RENDERER_QUERY, 1 },
  202.  
  203.         .queryInteger        = nouveau_query_renderer_integer,
  204.         .queryString         = nouveau_query_renderer_string
  205. };
  206.  
  207. static void
  208. nouveau_destroy_screen(__DRIscreen *dri_screen)
  209. {
  210.         struct nouveau_screen *screen = dri_screen->driverPrivate;
  211.  
  212.         if (!screen)
  213.                 return;
  214.  
  215.         nouveau_device_del(&screen->device);
  216.  
  217.         free(screen);
  218.         dri_screen->driverPrivate = NULL;
  219. }
  220.  
  221. static GLboolean
  222. nouveau_create_buffer(__DRIscreen *dri_screen,
  223.                       __DRIdrawable *drawable,
  224.                       const struct gl_config *visual,
  225.                       GLboolean is_pixmap)
  226. {
  227.         struct gl_renderbuffer *rb;
  228.         struct gl_framebuffer *fb;
  229.         GLenum color_format;
  230.  
  231.         if (is_pixmap)
  232.                 return GL_FALSE; /* not implemented */
  233.  
  234.         if (visual->redBits == 5)
  235.                 color_format = GL_RGB5;
  236.         else if (visual->alphaBits == 0)
  237.                 color_format = GL_RGB8;
  238.         else
  239.                 color_format = GL_RGBA8;
  240.  
  241.         fb = nouveau_framebuffer_dri_new(visual);
  242.         if (!fb)
  243.                 return GL_FALSE;
  244.  
  245.         /* Front buffer. */
  246.         rb = nouveau_renderbuffer_dri_new(color_format, drawable);
  247.         _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, rb);
  248.  
  249.         /* Back buffer */
  250.         if (visual->doubleBufferMode) {
  251.                 rb = nouveau_renderbuffer_dri_new(color_format, drawable);
  252.                 _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, rb);
  253.         }
  254.  
  255.         /* Depth/stencil buffer. */
  256.         if (visual->depthBits == 24 && visual->stencilBits == 8) {
  257.                 rb = nouveau_renderbuffer_dri_new(GL_DEPTH24_STENCIL8_EXT, drawable);
  258.                 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb);
  259.                 _mesa_add_renderbuffer(fb, BUFFER_STENCIL, rb);
  260.  
  261.         } else if (visual->depthBits == 24) {
  262.                 rb = nouveau_renderbuffer_dri_new(GL_DEPTH_COMPONENT24, drawable);
  263.                 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb);
  264.  
  265.         } else if (visual->depthBits == 16) {
  266.                 rb = nouveau_renderbuffer_dri_new(GL_DEPTH_COMPONENT16, drawable);
  267.                 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb);
  268.         }
  269.  
  270.         /* Software renderbuffers. */
  271.         _swrast_add_soft_renderbuffers(fb, GL_FALSE, GL_FALSE, GL_FALSE,
  272.                                        visual->accumRedBits > 0,
  273.                                        GL_FALSE, GL_FALSE);
  274.  
  275.         drawable->driverPrivate = fb;
  276.  
  277.         return GL_TRUE;
  278. }
  279.  
  280. static void
  281. nouveau_destroy_buffer(__DRIdrawable *drawable)
  282. {
  283.         _mesa_reference_framebuffer(
  284.                 (struct gl_framebuffer **)&drawable->driverPrivate, NULL);
  285. }
  286.  
  287. static void
  288. nouveau_drawable_flush(__DRIdrawable *draw)
  289. {
  290. }
  291.  
  292. static const struct __DRI2flushExtensionRec nouveau_flush_extension = {
  293.    .base = { __DRI2_FLUSH, 3 },
  294.  
  295.    .flush               = nouveau_drawable_flush,
  296.    .invalidate          = dri2InvalidateDrawable,
  297. };
  298.  
  299. static const struct __DRItexBufferExtensionRec nouveau_texbuffer_extension = {
  300.    .base = { __DRI_TEX_BUFFER, 3 },
  301.  
  302.    .setTexBuffer        = NULL,
  303.    .setTexBuffer2       = nouveau_set_texbuffer,
  304.    .releaseTexBuffer    = NULL,
  305. };
  306.  
  307. static const __DRIextension *nouveau_screen_extensions[] = {
  308.     &nouveau_flush_extension.base,
  309.     &nouveau_texbuffer_extension.base,
  310.     &nouveau_renderer_query_extension.base,
  311.     &dri2ConfigQueryExtension.base,
  312.     NULL
  313. };
  314.  
  315. const struct __DriverAPIRec nouveau_driver_api = {
  316.         .InitScreen      = nouveau_init_screen2,
  317.         .DestroyScreen   = nouveau_destroy_screen,
  318.         .CreateBuffer    = nouveau_create_buffer,
  319.         .DestroyBuffer   = nouveau_destroy_buffer,
  320.         .CreateContext   = nouveau_context_create,
  321.         .DestroyContext  = nouveau_context_destroy,
  322.         .MakeCurrent     = nouveau_context_make_current,
  323.         .UnbindContext   = nouveau_context_unbind,
  324. };
  325.  
  326. static const struct __DRIDriverVtableExtensionRec nouveau_vtable = {
  327.    .base = { __DRI_DRIVER_VTABLE, 1 },
  328.    .vtable = &nouveau_driver_api,
  329. };
  330.  
  331. /* This is the table of extensions that the loader will dlsym() for. */
  332. static const __DRIextension *nouveau_driver_extensions[] = {
  333.         &driCoreExtension.base,
  334.         &driDRI2Extension.base,
  335.         &nouveau_vtable.base,
  336.         NULL
  337. };
  338.  
  339. PUBLIC const __DRIextension **__driDriverGetExtensions_nouveau_vieux(void)
  340. {
  341.    globalDriverAPI = &nouveau_driver_api;
  342.  
  343.    return nouveau_driver_extensions;
  344. }
  345.